Index: applications/editors/josm/plugins/pointInfo/README.md
===================================================================
--- applications/editors/josm/plugins/pointInfo/README.md	(revision 34109)
+++ applications/editors/josm/plugins/pointInfo/README.md	(revision 34168)
@@ -6,13 +6,17 @@
 
 This plugin shows all available information for clicked point from external database.
-There is only a Czech RUIAN module available at this moment.
+Only Czech RUIAN and Spanish Cadastre Web Services modules are available at this moment.
 
 Plugin could be easy extend to show another data source.
 
-##Author
+## Author
 
  * Marián Kyral <mkyral@email.cz>
 
-##Websites
+## Contributors
+
+  * Javier Sánchez Portero <javiersanp@gmail.com> (Spanish Cadastre Web Services module)
+
+## Websites
 
  * OSM wiki - not available yet
@@ -20,10 +24,10 @@
  * [Github](https://github.com/mkyral/josm-pointInfo)
 
-##Licence:
+## Licence:
 
  * GPL v2 or later
 
 ---
-###The RUIAN module
+### The RUIAN module
 
  * Shows data about building, addresses, streets,  parcels and cadastral area from Czech RUIAN registry (https://wiki.openstreetmap.org/wiki/RUIAN)
@@ -37,6 +41,10 @@
     * [![](https://raw.githubusercontent.com/mkyral/josm-pointInfo/master/images/dialogs/create-bug-report.png)] Report an issue with building
 
+### The Spanish Cadastre Web Services module
+
+  * Easy access the Spanish Cadastre Web Services (only Cadastre photographs at the moment).
+
 ---
-###The interface:
+### The interface:
 
 - Input is position, output html string that is shown on message.
Index: applications/editors/josm/plugins/pointInfo/build.xml
===================================================================
--- applications/editors/josm/plugins/pointInfo/build.xml	(revision 34109)
+++ applications/editors/josm/plugins/pointInfo/build.xml	(revision 34168)
@@ -3,5 +3,5 @@
 
     <!-- enter the SVN commit message -->
-    <property name="commit.message" value="PointInfo: Replace depricated AddCommand function."/>
+    <property name="commit.message" value="PointInfo: Add Spanish Cadastre Web Services module. Patch by Javier Sánchez Portero."/>
     <!-- enter the *lowest* JOSM version this plugin is currently compatible with -->
     <property name="plugin.main.version" value="12666"/>
@@ -15,5 +15,5 @@
     <property name="plugin.author" value="Marián Kyral"/>
     <property name="plugin.class" value="org.openstreetmap.josm.plugins.pointinfo.PointInfoPlugin"/>
-    <property name="plugin.description" value="Shows an additional information about point on map. There is only a Czech RUIAN module available at this moment."/>
+    <property name="plugin.description" value="Shows an additional information about point on map. Only Czech RUIAN and Spanish Cadastre Web Services modules are available at this moment."/>
     <property name="plugin.icon" value="images/mapmode/info-sml.png"/>
     <property name="plugin.link" value="https://github.com/mkyral/josm-pointInfo"/>
Index: applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/AbstractPointInfoModule.java
===================================================================
--- applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/AbstractPointInfoModule.java	(revision 34168)
+++ applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/AbstractPointInfoModule.java	(revision 34168)
@@ -0,0 +1,38 @@
+// License: GPL. See LICENSE file for details.
+package org.openstreetmap.josm.plugins.pointinfo;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+
+public abstract class AbstractPointInfoModule {
+
+    /**
+     * Return Html text representation
+     * @return String htmlText
+     */
+    public abstract String getHtml();
+
+    /**
+     * Perform given action
+     *  e.g.: copy tags to clipboard
+     * @param act Action to be performed
+     */
+    public abstract void performAction(String act);
+
+    /**
+     * Get a information about given position.
+     * @param pos Position on the map
+     */
+    public abstract void prepareData(LatLon pos);
+
+    /**
+     * Returns the public name of this module
+     * @return String name
+     */
+    public abstract String getName();
+
+    /**
+     * Returns the name of the area (country, state) where this module is valid
+     * @return String areaName
+     */
+    public abstract String getArea();
+}
Index: applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/PointInfoAction.java
===================================================================
--- applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/PointInfoAction.java	(revision 34109)
+++ applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/PointInfoAction.java	(revision 34168)
@@ -25,5 +25,5 @@
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.gui.util.GuiHelper;
-import org.openstreetmap.josm.plugins.pointinfo.ruian.RuianModule;
+import org.openstreetmap.josm.plugins.pointinfo.AbstractPointInfoModule;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
@@ -37,5 +37,5 @@
 
     protected boolean cancel;
-    protected RuianModule mRuian = new RuianModule();
+    protected AbstractPointInfoModule module;
 
     private String htmlText = "";
@@ -76,4 +76,5 @@
 
         try {
+            module = PointInfoPlugin.getModule(pos);
             PleaseWaitRunnable infoTask = new PleaseWaitRunnable(tr("Connecting server")) {
                 @Override
@@ -95,10 +96,10 @@
                         msgLabel.addHyperlinkListener(hle -> {
                             if (HyperlinkEvent.EventType.ACTIVATED.equals(hle.getEventType())) {
+                                Logging.info(hle.getURL().toString());
                                 if (hle.getURL() == null || hle.getURL().toString().isEmpty()) {
                                     return;
                                 }
-                                System.out.println("URL: "+ hle.getURL());
                                 if (!hle.getURL().toString().startsWith("http")) {
-                                    mRuian.performAction(hle.getURL().toString());
+                                    module.performAction(hle.getURL().toString());
                                 } else {
                                     String ret = OpenBrowser.displayUrl(hle.getURL().toString());
@@ -132,6 +133,6 @@
         progressMonitor.beginTask(null, 3);
         try {
-            mRuian.prepareData(pos);
-            htmlText = mRuian.getHtml();
+            module.prepareData(pos);
+            htmlText = module.getHtml();
             coordinatesText = PointInfoUtils.formatCoordinates(pos.lat(), pos.lon());
 
Index: applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/PointInfoPlugin.java
===================================================================
--- applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/PointInfoPlugin.java	(revision 34109)
+++ applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/PointInfoPlugin.java	(revision 34168)
@@ -2,8 +2,19 @@
 package org.openstreetmap.josm.plugins.pointinfo;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.MainMenu;
 import org.openstreetmap.josm.plugins.Plugin;
 import org.openstreetmap.josm.plugins.PluginInformation;
+import org.openstreetmap.josm.plugins.pointinfo.ruian.RuianModule;
+import org.openstreetmap.josm.plugins.pointinfo.catastro.CatastroModule;
 
 /**
@@ -12,4 +23,10 @@
  */
 public class PointInfoPlugin extends Plugin {
+
+    private static final HashMap<String, AbstractPointInfoModule> modules = new HashMap<>();
+    static {
+        registerModule(new RuianModule());
+        registerModule(new CatastroModule());
+    }
 
     /**
@@ -21,3 +38,53 @@
         MainMenu.add(MainApplication.getMenu().moreToolsMenu, new PointInfoAction());
     }
+
+    @Override
+    public PreferenceSetting getPreferenceSetting() {
+        return new PointInfoPreference();
+    }
+
+    /**
+     * Register a module as available to select in the preferences.
+     * @param module PointInfo module
+     */
+    public static void registerModule(AbstractPointInfoModule module) {
+        modules.put(module.getName(), module);
+    }
+
+    /**
+     * Returns a list of available modules names
+     * @return modsList
+     */
+    public static List<String> getModules() {
+        return new ArrayList<>(modules.keySet());
+    }
+
+    /**
+     * Returns a valid module for this point. If auto mode is selected, returns
+     * the first valid module for the area in the given position
+     the currently selected module
+     * @param pos position LatLon
+     * @return module
+     * @throws IOException if any IO error occurs.
+    */
+    public static AbstractPointInfoModule getModule(LatLon pos) throws IOException {
+        AbstractPointInfoModule module;
+        module = null;
+        if (Main.pref.getBoolean("plugin.pointinfo.automode", true)) {
+            ReverseRecord r = ReverseFinder.queryNominatim(pos);
+            Iterator i = modules.values().iterator();
+            while (module == null && i.hasNext()) {
+                AbstractPointInfoModule m = (AbstractPointInfoModule) i.next();
+                if (r.matchAnyArea(m.getArea())) {
+                    module = m;
+                }
+            }
+        } else {
+            module = modules.get(Main.pref.get("plugin.pointinfo.module", "RUIAN"));
+        }
+        if (module == null) {
+            module = modules.get("RUIAN");
+        }
+        return module;
+    }
 }
Index: applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/PointInfoPreference.java
===================================================================
--- applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/PointInfoPreference.java	(revision 34168)
+++ applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/PointInfoPreference.java	(revision 34168)
@@ -0,0 +1,66 @@
+// License: GPL. See LICENSE file for details.
+package org.openstreetmap.josm.plugins.pointinfo;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.Box;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.preferences.DefaultTabPreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
+import org.openstreetmap.josm.tools.GBC;
+
+/**
+ * Plugin preferences.
+ */
+public class PointInfoPreference extends DefaultTabPreferenceSetting {
+
+    private final JComboBox<String> module = new JComboBox<>();
+    private final JCheckBox autoMode = new JCheckBox(tr("Automatically detect the module"));
+
+    /**
+     * Constructs a new {@code PointInfoPreference}.
+     */
+    public PointInfoPreference() {
+        super("pointinfo", tr("Point information settings"), tr("Settings for the point information plugin."), true);
+    }
+
+    @Override
+    public String getIconName() {
+        return "info-sml.png";
+    }
+
+    @Override
+    public void addGui(PreferenceTabbedPane gui) {
+        JPanel panel = new JPanel(new GridBagLayout());
+        // autoMode
+        autoMode.setSelected(Main.pref.getBoolean("plugin.pointinfo.automode", false));
+        autoMode.setToolTipText(tr("Try to guess the appropriate module from the location."
+                + " If it fails, use the module selected below."));
+        panel.add(autoMode, GBC.eol().insets(0, 0, 0, 0));
+        // module
+        for (String modName : PointInfoPlugin.getModules()) {
+            module.addItem(modName);
+        }
+        module.setSelectedItem(Main.pref.get("plugin.pointinfo.module", "RUIAN"));
+        module.setToolTipText(tr("The module called to get the point information."));
+        panel.add(new JLabel(tr("Module")), GBC.std());
+        panel.add(module, GBC.eol().fill(GridBagConstraints.HORIZONTAL).insets(5, 0, 0, 5));
+        panel.add(Box.createVerticalGlue(), GBC.eol().fill(GridBagConstraints.VERTICAL));
+        createPreferenceTabWithScrollPane(gui, panel);
+    }
+
+    @Override
+    public boolean ok() {
+        Main.pref.putBoolean("plugin.pointinfo.automode", autoMode.isSelected());
+        Main.pref.put("plugin.pointinfo.module", (String) module.getSelectedItem());
+        return false;
+    }
+}
Index: applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/PointInfoUtils.java
===================================================================
--- applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/PointInfoUtils.java	(revision 34109)
+++ applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/PointInfoUtils.java	(revision 34168)
@@ -38,6 +38,6 @@
     /**
      * Return text representation of coordinates.
-     # @param  lat Lat coordinate
-     # @param  lon Lon coordinate
+     * @param lat the lat part of coordinates
+     * @param lon the lon part of coordinates
      * @return String coordinatesText
      */
Index: applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/ReverseFinder.java
===================================================================
--- applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/ReverseFinder.java	(revision 34168)
+++ applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/ReverseFinder.java	(revision 34168)
@@ -0,0 +1,43 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.pointinfo;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.net.URL;
+import java.util.Locale;
+
+import javax.json.Json;
+import javax.json.JsonObject;
+import javax.json.JsonReader;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.tools.HttpClient;
+
+/**
+ * Class to access Nominatim Reverse Geocoding
+ * @author Javier Sánchez Portero
+ */
+public class ReverseFinder {
+
+    public static final String NOMINATIM_URL = "https://nominatim.openstreetmap.org/reverse?format=json&lat=%f&lon=%f";
+
+    private ReverseFinder() {
+    }
+
+    /**
+     * Performs a Nominatim search.
+     * @param pos Coordinates to search
+     * @return search results
+     * @throws IOException if any IO error occurs.
+     */
+    public static ReverseRecord queryNominatim(LatLon pos) throws IOException {
+        String request = String.format(Locale.ENGLISH, NOMINATIM_URL, pos.lat(), pos.lon());
+        String result = HttpClient.create(new URL(request)).connect().fetchContent();
+        JsonReader jsonReader = Json.createReader(new ByteArrayInputStream(result.getBytes(StandardCharsets.UTF_8)));
+        JsonObject obj = jsonReader.readObject();
+        jsonReader.close();
+        ReverseRecord record = new ReverseRecord(obj);
+        return record;
+    }
+}
Index: applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/ReverseRecord.java
===================================================================
--- applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/ReverseRecord.java	(revision 34168)
+++ applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/ReverseRecord.java	(revision 34168)
@@ -0,0 +1,88 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.pointinfo;
+
+import javax.json.JsonObject;
+
+/**
+ * Class to contain Nominatim Reverse Geocoding data
+ * @author Javier Sánchez Portero
+ */
+class ReverseRecord {
+
+    private String countryCode;
+    private String country;
+    private String state;
+    private String stateDistrict;
+    private String county;
+    private String city;
+    private String town;
+    private String village;
+    private String cityDistrict;
+    private String suburb;
+
+    /**
+     * Default constructor
+     *
+     */
+    ReverseRecord() {
+        init();
+    }
+
+    /**
+     * Constructor from JSON
+     * @param obj the Json object
+     *
+     */
+    ReverseRecord(JsonObject obj) {
+        init();
+        JsonObject address = obj.getJsonObject("address");
+        if (address != null) {
+            countryCode = address.getString("country_code", null);
+            country = address.getString("country", null);
+            state = address.getString("state", null);
+            stateDistrict = address.getString("state_district", null);
+            county = address.getString("county", null);
+            city = address.getString("city", null);
+            town = address.getString("town", null);
+            village = address.getString("village", null);
+            cityDistrict = address.getString("city_district", null);
+            suburb = address.getString("suburb", null);
+        }
+    }
+
+    /**
+     * Initialization
+     *
+     */
+    private void init() {
+        countryCode = null;
+        country = null;
+        state = null;
+        stateDistrict = null;
+        county = null;
+        city = null;
+        town = null;
+        village = null;
+        cityDistrict = null;
+        suburb = null;
+    }
+
+    /**
+     * Returns true if area is equals to any address value
+     * @param area area to be checked
+     * @return match area matched
+     */
+    public Boolean matchAnyArea(String area) {
+        if (area.equals(countryCode)) return true;
+        if (area.equals(country)) return true;
+        if (area.equals(state)) return true;
+        if (area.equals(stateDistrict)) return true;
+        if (area.equals(county)) return true;
+        if (area.equals(city)) return true;
+        if (area.equals(town)) return true;
+        if (area.equals(village)) return true;
+        if (area.equals(cityDistrict)) return true;
+        if (area.equals(suburb)) return true;
+        return false;
+    }
+}
Index: applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/catastro/AddrPlaces.java
===================================================================
--- applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/catastro/AddrPlaces.java	(revision 34168)
+++ applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/catastro/AddrPlaces.java	(revision 34168)
@@ -0,0 +1,222 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.pointinfo.catastro;
+
+import java.text.DecimalFormat;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+
+/**
+ * Private class to store address places
+ * @author Marián Kyral
+ */
+class AddrPlaces {
+    // CHECKSTYLE.OFF: SingleSpaceSeparator
+    private long    m_ruian_id;
+    private LatLon  m_position;
+    private long    m_budova_id;
+    private String  m_cislo_typ;
+    private String  m_cislo_domovni;
+    private String  m_cislo_orientacni;
+    private long    m_ulice_kod;
+    private String  m_ulice;
+    private long    m_cast_obce_kod;
+    private String  m_cast_obce;
+    private long    m_mestska_cast_kod;
+    private String  m_mestska_cast;
+    private long    m_obec_kod;
+    private String  m_obec;
+    private long    m_okres_kod;
+    private String  m_okres;
+    private long    m_kraj_kod;
+    private String  m_kraj;
+    private String  m_psc;
+    private float   m_vzdalenost;
+    // CHECKSTYLE.ON: SingleSpaceSeparator
+
+    AddrPlaces() {
+        init();
+    }
+
+    private void init() {
+        m_ruian_id = 0;
+        m_position = new LatLon(0., 0.);
+        m_budova_id = 0;
+        m_cislo_typ = "";
+        m_cislo_domovni = "";
+        m_cislo_orientacni = "";
+        m_ulice_kod = 0;
+        m_ulice = "";
+        m_cast_obce_kod = 0;
+        m_cast_obce = "";
+        m_mestska_cast_kod = 0;
+        m_mestska_cast = "";
+        m_obec_kod = 0;
+        m_obec = "";
+        m_okres_kod = 0;
+        m_okres = "";
+        m_kraj_kod = 0;
+        m_kraj = "";
+        m_psc = "";
+        m_vzdalenost = 0;
+    }
+
+    public void setRuianID(long v) {
+        m_ruian_id = v;
+    }
+
+    public void setPosition(LatLon v) {
+        m_position = v;
+    }
+
+    public void setBudovaID(long v) {
+        m_budova_id = v;
+    }
+
+    public void setCisloTyp(String v) {
+        m_cislo_typ = v;
+    }
+
+    public void setCisloDomovni(String v) {
+        m_cislo_domovni = v;
+    }
+
+    public void setCisloOrientacni(String v) {
+        m_cislo_orientacni = v;
+    }
+
+    public void setUliceID(long v) {
+        m_ulice_kod = v;
+    }
+
+    public void setUlice(String v) {
+        m_ulice = v;
+    }
+
+    public void setCastObceID(long v) {
+        m_cast_obce_kod = v;
+    }
+
+    public void setCastObce(String v) {
+        m_cast_obce = v;
+    }
+
+    public void setMestskaCastID(long v) {
+        m_mestska_cast_kod = v;
+    }
+
+    public void setMestskaCast(String v) {
+        m_mestska_cast = v;
+    }
+
+    public void setObecID(long v) {
+        m_obec_kod = v;
+    }
+
+    public void setObec(String v) {
+        m_obec = v;
+    }
+
+    public void setOkresID(long v) {
+        m_okres_kod = v;
+    }
+
+    public void setOkres(String v) {
+        m_okres = v;
+    }
+
+    public void setKrajID(long v) {
+        m_kraj_kod = v;
+    }
+
+    public void setKraj(String v) {
+        m_kraj = v;
+    }
+
+    public void setPsc(String v) {
+        m_psc = v;
+    }
+
+    public void setVzdalenost(float v) {
+        m_vzdalenost = v;
+    }
+
+    public long getRuianID() {
+        return m_ruian_id;
+    }
+
+    public long getBudovaID() {
+        return m_budova_id;
+    }
+
+    public LatLon getPosition() {
+        return m_position;
+    }
+
+    public String getCisloTyp() {
+        return m_cislo_typ;
+    }
+
+    public String getCisloDomovni() {
+        return m_cislo_domovni;
+    }
+
+    public String getCisloOrientacni() {
+        return m_cislo_orientacni;
+    }
+
+    public long getUliceID() {
+        return m_ulice_kod;
+    }
+
+    public String getUlice() {
+        return m_ulice;
+    }
+
+    public long getCastObceID() {
+        return m_cast_obce_kod;
+    }
+
+    public String getCastObce() {
+        return m_cast_obce;
+    }
+
+    public long getMestskaCastID() {
+        return m_mestska_cast_kod;
+    }
+
+    public String getMestskaCast() {
+        return m_mestska_cast;
+    }
+
+    public long getObecID() {
+        return m_obec_kod;
+    }
+
+    public String getObec() {
+        return m_obec;
+    }
+
+    public long getOkresID() {
+        return m_okres_kod;
+    }
+
+    public String getOkres() {
+        return m_okres;
+    }
+
+    public long getKrajID() {
+        return m_kraj_kod;
+    }
+
+    public String getKraj() {
+        return m_kraj;
+    }
+
+    public String getPsc() {
+        return m_psc;
+    }
+
+    public String getVzdalenost() {
+        return new DecimalFormat("0.00").format(m_vzdalenost) + "m";
+    }
+}
Index: applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/catastro/CatastroModule.java
===================================================================
--- applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/catastro/CatastroModule.java	(revision 34168)
+++ applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/catastro/CatastroModule.java	(revision 34168)
@@ -0,0 +1,63 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.pointinfo.catastro;
+
+import java.net.URL;
+import java.util.Locale;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.tools.HttpClient;
+import org.openstreetmap.josm.tools.Logging;
+
+import org.openstreetmap.josm.plugins.pointinfo.AbstractPointInfoModule;
+
+/**
+ * A module for the Spanish Cadastre Web Services
+ * @author Javier Sánchez Portero
+ */
+public class CatastroModule extends AbstractPointInfoModule {
+
+    private static final String moduleName = "Catastro";
+    private static final String areaName = "es";
+    private static final String catURL = "http://ovc.catastro.meh.es/ovcservweb/OVCSWLocalizacionRC/OVCCoordenadas.asmx/Consulta_RCCOOR?SRS=EPSG:4326&Coordenada_X=%f&Coordenada_Y=%f";
+
+    private CatastroRecord m_record = new CatastroRecord();
+
+    public CatastroModule() {
+
+    }
+
+    @Override
+    public String getHtml() {
+        return m_record.getHtml();
+    }
+
+    @Override
+    public void performAction(String act) {
+        m_record.performAction(act);
+    }
+
+    /**
+     * Get a information about given position from Consulta_RCCOOR Web Service.
+     * @param pos Position on the map
+     */
+    @Override
+    public void prepareData(LatLon pos) {
+        try {
+            String request = String.format(Locale.ENGLISH, catURL, pos.lon(), pos.lat());
+            String result = HttpClient.create(new URL(request)).connect().fetchContent();
+            m_record.parseXML(result);
+        } catch (Exception e) {
+            Logging.warn(e);
+        }
+    }
+
+    @Override
+    public String getName() {
+        return moduleName;   
+    }
+
+    @Override
+    public String getArea() {
+        return areaName;
+    }
+}
Index: applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/catastro/CatastroRecord.java
===================================================================
--- applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/catastro/CatastroRecord.java	(revision 34168)
+++ applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/catastro/CatastroRecord.java	(revision 34168)
@@ -0,0 +1,157 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.pointinfo.catastro;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+
+import javax.json.Json;
+import javax.json.JsonObject;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.DocumentBuilder;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Node;
+import org.w3c.dom.Element;
+
+import org.openstreetmap.josm.tools.Logging;
+import java.util.logging.Level;
+
+/**
+ * Class to contain Catastro data
+ * @author Javier Sánchez Portero
+ */
+class CatastroRecord {
+
+    public static final String fURL = "http://ovc.catastro.meh.es/OVCServWeb/"+
+        "OVCWcfLibres/OVCFotoFachada.svc/RecuperarFotoFachadaGet?ReferenciaCatastral=";
+    public static final String cURL = "http://www.catastro.meh.es/";
+    public static final String cSource = "Dirección General del Catastro";
+
+    private ArrayList<JsonObject> errors;
+    private ArrayList<JsonObject> coords;
+
+    /**
+     * Constructor
+     *
+     */
+    CatastroRecord() {
+        init();
+    }
+
+    /**
+     * Initialization
+     *
+     */
+    private void init() {
+        errors = new ArrayList<JsonObject>();
+        coords = new ArrayList<JsonObject>();
+    }
+
+    /**
+     * Parse given XML string and fill variables with Catastro data
+     * @param xmlStr XML string with Catastro Consulta_RCCOOR response
+     */
+    public void parseXML(String xmlStr) {
+        init();
+        try {
+            InputStream input = new ByteArrayInputStream(xmlStr.getBytes(StandardCharsets.UTF_8));
+            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
+            Document doc = dBuilder.parse(input);
+            doc.getDocumentElement().normalize();
+            parseErrors(doc);
+            parseCoordenadas(doc);
+        } catch (Exception e) {
+            Logging.log(Level.WARNING, e);
+        }
+    }
+
+    private void parseErrors(Document doc) {
+        try {
+            NodeList nList = doc.getElementsByTagName("err");
+            for (int temp = 0; temp < nList.getLength(); temp++) {
+                Node nNode = nList.item(temp);            
+                if (nNode.getNodeType() == Node.ELEMENT_NODE) {
+                    Element eElement = (Element) nNode;
+                    String code = eElement.getElementsByTagName("cod").item(0).getTextContent();
+                    String desc = eElement.getElementsByTagName("des").item(0).getTextContent();
+                    JsonObject error = Json.createObjectBuilder()
+                        .add("code", code)
+                        .add("desc", desc)
+                        .build();
+                    errors.add(error);
+                    Logging.info("Error: (" + code + ") " + desc);
+                }
+            }
+        } catch (Exception e) {
+            Logging.log(Level.WARNING, "errors:", e);
+        }
+    }
+    
+    private void parseCoordenadas(Document doc) {
+        try {
+            NodeList nList = doc.getElementsByTagName("coord");
+            for (int temp = 0; temp < nList.getLength(); temp++) {
+                Node nNode = nList.item(temp);            
+                if (nNode.getNodeType() == Node.ELEMENT_NODE) {
+                    Element eElement = (Element) nNode;
+                    String ref = eElement.getElementsByTagName("pc1").item(0).getTextContent()
+                        + eElement.getElementsByTagName("pc2").item(0).getTextContent();
+                    String address = eElement.getElementsByTagName("ldt")
+                        .item(0).getTextContent();
+                    JsonObject coord = Json.createObjectBuilder()
+                        .add("ref", ref)
+                        .add("address", address)
+                        .build();
+                    coords.add(coord);
+                    Logging.info("Referencia Catastral: " + ref);
+                    Logging.info("Dirección: " + address);
+                }
+            }
+        } catch (Exception e) {
+            Logging.log(Level.WARNING, "coordenadas:", e);
+        }
+    }
+    
+    /**
+     * Return Html text representation
+     * @return String htmlText
+     */
+    public String getHtml() {
+        StringBuilder r = new StringBuilder();
+        r.append("<html><body bgcolor=\"white\" color=\"black\" ><table><tr><td>");
+        r.append("<br/>");
+        for (JsonObject coord: coords) {
+            r.append("<i><u>Información de la parcela</u></i><br/>");
+            r.append("<b>Referencia Catastral: </b>" + coord.getString("ref") + "<br/>");
+            r.append("<b>Dirección: </b>" + coord.getString("address") + "<br/>");
+            r.append("<b>Fotografía de fachada:</b> <a href=\"" 
+                + fURL + coord.getString("ref") + "\">"
+                + "Enlace a web de Catastro</a><br/><br/>");
+        }
+        if (errors.size() > 0) {
+            r.append("<i><u>Errores</u></i><br/>");
+        }
+        for (JsonObject error: errors) {
+            r.append("(" + error.getString("code") + ") ");
+            r.append(error.getString("desc") + "<br/>");
+        }
+        r.append("<hr/>");
+        r.append("<center><i>Fuente: <a href=\"" + cURL +"\">" + cSource + "</a></i></center>");
+        r.append("</td></tr></table></body></html>");
+        return r.toString();
+    }
+
+    /**
+     * Perform given action
+     *  e.g.: copy tags to clipboard
+     * @param act Action to be performed
+     */
+    public void performAction(String act) {
+    }
+}
Index: applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/catastro/ObjectWithoutGeometry.java
===================================================================
--- applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/catastro/ObjectWithoutGeometry.java	(revision 34168)
+++ applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/catastro/ObjectWithoutGeometry.java	(revision 34168)
@@ -0,0 +1,116 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.pointinfo.catastro;
+
+import java.text.DecimalFormat;
+
+class ObjectWithoutGeometry {
+    // CHECKSTYLE.OFF: SingleSpaceSeparator
+    private long    m_ruian_id;
+    private int     m_podlazi;
+    private int     m_byty;
+    private String  m_zpusob_vyuziti;
+    private String  m_zpusob_vyuziti_kod;
+    private String  m_zpusob_vyuziti_key;
+    private String  m_zpusob_vyuziti_val;
+    private String  m_dokonceni;
+    private String  m_plati_od;
+    private float   m_vzdalenost;
+    // CHECKSTYLE.ON: SingleSpaceSeparator
+
+    ObjectWithoutGeometry() {
+        init();
+    }
+
+    private void init() {
+        m_ruian_id = 0;
+        m_podlazi = 0;
+        m_byty = 0;
+        m_zpusob_vyuziti = "";
+        m_zpusob_vyuziti_kod = "";
+        m_zpusob_vyuziti_key = "";
+        m_zpusob_vyuziti_val = "";
+        m_dokonceni = "";
+        m_plati_od = "";
+        m_vzdalenost = 0;
+    }
+
+    public void setRuianID(long v) {
+        m_ruian_id = v;
+    }
+
+    public void setPodlazi(int v) {
+        m_podlazi = v;
+    }
+
+    public void setByty(int v) {
+        m_byty = v;
+    }
+
+    public void setZpusobVyuziti(String v) {
+        m_zpusob_vyuziti = v;
+    }
+
+    public void setZpusobVyuzitiKod(String v) {
+        m_zpusob_vyuziti_kod = v;
+    }
+
+    public void setZpusobVyuzitiKey(String v) {
+        m_zpusob_vyuziti_key = v;
+    }
+
+    public void setZpusobVyuzitiVal(String v) {
+        m_zpusob_vyuziti_val = v;
+    }
+
+    public void setDokonceni(String v) {
+        m_dokonceni = v;
+    }
+
+    public void setPlatiOd(String v) {
+        m_plati_od = v;
+    }
+
+    public void setVzdalenost(float v) {
+        m_vzdalenost = v;
+    }
+
+    public long getRuianID() {
+        return m_ruian_id;
+    }
+
+    public int getPodlazi() {
+        return m_podlazi;
+    }
+
+    public int getByty() {
+        return m_byty;
+    }
+
+    public String getZpusobVyuziti() {
+        return m_zpusob_vyuziti;
+    }
+
+    public String getZpusobVyuzitiKod() {
+        return m_zpusob_vyuziti_kod;
+    }
+
+    public String getZpusobVyuzitiKey() {
+        return m_zpusob_vyuziti_key;
+    }
+
+    public String getZpusobVyuzitiVal() {
+        return m_zpusob_vyuziti_val;
+    }
+
+    public String getDokonceni() {
+        return m_dokonceni;
+    }
+
+    public String getPlatiOd() {
+        return m_plati_od;
+    }
+
+    public String getVzdalenost() {
+        return new DecimalFormat("0.00").format(m_vzdalenost) + "m";
+    }
+}
Index: applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/ruian/RuianModule.java
===================================================================
--- applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/ruian/RuianModule.java	(revision 34109)
+++ applications/editors/josm/plugins/pointInfo/src/org/openstreetmap/josm/plugins/pointinfo/ruian/RuianModule.java	(revision 34168)
@@ -8,11 +8,15 @@
 import org.openstreetmap.josm.tools.Logging;
 
+import org.openstreetmap.josm.plugins.pointinfo.AbstractPointInfoModule;
+
 /**
  * A module for the Czech RUIAN database
  * @author Marián Kyral
  */
-public class RuianModule {
+public class RuianModule extends AbstractPointInfoModule {
 
-    private String URL = "http://josm.poloha.net/pointInfo/v4/index.php";
+    private static final String moduleName = "RUIAN";
+    private static final String areaName = "cz";
+    private static final String URL = "http://josm.poloha.net/pointInfo/v4/index.php";
 
     private RuianRecord m_record = new RuianRecord();
@@ -22,17 +26,10 @@
     }
 
-    /**
-     * Return Html text representation
-     * @return String htmlText
-     */
+    @Override
     public String getHtml() {
         return m_record.getHtml();
     }
 
-    /**
-     * Perform given action
-     *  e.g.: copy tags to clipboard
-     * @param act Action to be performed
-     */
+    @Override
     public void performAction(String act) {
         m_record.performAction(act);
@@ -43,4 +40,5 @@
      * @param pos Position on the map
      */
+    @Override
     public void prepareData(LatLon pos) {
         try {
@@ -51,3 +49,13 @@
         }
     }
+
+    @Override
+    public String getName() {
+        return moduleName;   
+    }
+
+    @Override
+    public String getArea() {
+        return areaName;
+    }
 }
