Index: /applications/editors/josm/plugins/tag2link/README
===================================================================
--- /applications/editors/josm/plugins/tag2link/README	(revision 26916)
+++ /applications/editors/josm/plugins/tag2link/README	(revision 26917)
@@ -10,5 +10,3 @@
 
 See http://wiki.openstreetmap.org/wiki/JOSM/Plugins/Tag2Link
-
-The icon has been created by TODO
  
Index: /applications/editors/josm/plugins/tag2link/build.xml
===================================================================
--- /applications/editors/josm/plugins/tag2link/build.xml	(revision 26916)
+++ /applications/editors/josm/plugins/tag2link/build.xml	(revision 26917)
@@ -28,5 +28,5 @@
 **
 -->
-<project name="imagery-xml-bounds" default="dist" basedir=".">
+<project name="tag2link" default="dist" basedir=".">
     <!-- enter the SVN commit message -->
     <property name="commit.message" value="Commit message"/>
@@ -102,5 +102,5 @@
                 <attribute name="fr_Plugin-Description" value="TODO"/>
                 <attribute name="Plugin-Early" value="false"/>
-                <attribute name="Plugin-Icon" value="images/tag2link_24.png"/>
+                <attribute name="Plugin-Icon" value="images/tag2linkv2_24x24.png"/>
                 <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/wiki/JOSM/Plugins/Tag2Link"/>
                 <attribute name="Plugin-Mainversion" value="${plugin.main.version}"/>
Index: plications/editors/josm/plugins/tag2link/data/tag2link_sources.xml
===================================================================
--- /applications/editors/josm/plugins/tag2link/data/tag2link_sources.xml	(revision 26916)
+++ 	(revision )
@@ -1,88 +1,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-//    JOSM tag2link plugin.
-//    Copyright (C) 2011 Don-vip & FrViPofm
-//
-//    This program is free software: you can redistribute it and/or modify
-//    it under the terms of the GNU General Public License as published by
-//    the Free Software Foundation, either version 3 of the License, or
-//    (at your option) any later version.
-//
-//    This program is distributed in the hope that it will be useful,
-//    but WITHOUT ANY WARRANTY; without even the implied warranty of
-//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//    GNU General Public License for more details.
-//
-//    You should have received a copy of the GNU General Public License
-//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
- -->
-<tag2link>
-
-    <!-- Global -->
-
-    <source name="Common">
-       <rule>
-           <condition k="website" />
-           <link name="View website" href="{v}" />
-       </rule>
-       <rule>
-           <condition k="url" />
-           <link name="View URL" href="{v}" />
-       </rule>
-    </source>
-	
-	<source name="Wikipedia">
-	   <rule>
-	       <condition k="wikipedia(?::([\p{Lower}]{2,}))?" />
-           <link name="View {name} article" href="http://{k.1:en}.wikipedia.org/wiki/{v}" />
-	   </rule>
-	</source>
-	
-	<!-- Only for France -->
-    
-    <source name="SANDRE" country-code="FR">
-       <rule>
-           <condition k="ref:sandre" v="[A-Z0-9-]{8}" />
-           <link name="View {name} sheet of river" href="http://services.sandre.eaufrance.fr/Courdo/Fiche/client/fiche_courdo.php?CdSandre={v}" />
-       </rule>
-    </source>
-    
-    <source name="INSEE" country-code="FR">
-       <rule>
-           <condition k="admin_level" v="8"/>
-           <condition k="ref:INSEE" v="(\p{Digit}{2})(\p{Digit}{3})"/>
-           <link name="View {name} municipality sheet" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/fichecommunale.asp?codedep={v.1}&amp;codecom={v.2}" />
-       </rule>
-       <rule>
-           <condition k="political_division" v="FR:canton"/>
-           <condition k="ref:INSEE" v="(\p{Digit}{2})(\p{Digit}{2})"/>
-           <link name="View {name} map of municipalities" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/carte_comcan.asp?codecan={v}" />
-           <link name="View {name} list of municipalities" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/comcan.asp?codedep={v.1}&amp;codecan={v.2}" />
-       </rule>
-       <rule>
-           <condition k="admin_level" v="7"/>
-           <condition k="ref:INSEE" v="(\p{Digit}{2})(\p{Digit}{1})"/>
-           <link name="View {name} map of cantons" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/carte_canarr.asp?codearr={v}" />
-           <link name="View {name} list of cantons" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/canarr.asp?codedep={v.1}&amp;codearr={v.2}" />
-       </rule>
-       <rule>
-           <condition k="admin_level" v="6"/>
-           <condition k="ref:INSEE" v="\p{Digit}{2}"/>
-           <link name="View {name} map of arrondissements" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/carte_arrdep.asp?codedep={v}" />
-           <link name="View {name} list of arrondissements" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/arrdep.asp?codedep={v}" />
-       </rule>
-       <rule>
-           <condition k="admin_level" v="4"/>
-           <condition k="ref:INSEE" v="\p{Digit}{2}"/>
-           <link name="View {name} map of departments" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/carte_depreg.asp?codereg={v}" />
-           <link name="View {name} list of departments" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/depreg.asp?codereg={v}" />
-       </rule>
-       <rule>
-           <condition k="admin_level" v="2"/>
-           <condition k="name" v="France*"/>
-           <link name="View {name} map of regions" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/carte_regions.asp" />
-           <link name="View {name} list of regions" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/region.asp" />
-       </rule>
-    </source>
-    
-</tag2link>
Index: /applications/editors/josm/plugins/tag2link/resources/tag2link_sources.xml
===================================================================
--- /applications/editors/josm/plugins/tag2link/resources/tag2link_sources.xml	(revision 26917)
+++ /applications/editors/josm/plugins/tag2link/resources/tag2link_sources.xml	(revision 26917)
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+//    JOSM tag2link plugin.
+//    Copyright (C) 2011 Don-vip & FrViPofm
+//
+//    This program is free software: you can redistribute it and/or modify
+//    it under the terms of the GNU General Public License as published by
+//    the Free Software Foundation, either version 3 of the License, or
+//    (at your option) any later version.
+//
+//    This program is distributed in the hope that it will be useful,
+//    but WITHOUT ANY WARRANTY; without even the implied warranty of
+//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//    GNU General Public License for more details.
+//
+//    You should have received a copy of the GNU General Public License
+//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ -->
+<tag2link>
+
+    <!-- Global -->
+
+    <source name="Common">
+       <rule>
+           <condition k="website" />
+           <link name="View website" href="{v}" />
+       </rule>
+       <rule>
+           <condition k="url" />
+           <link name="View URL" href="{v}" />
+       </rule>
+    </source>
+	
+	<source name="Wikipedia">
+	   <rule>
+	       <condition k="wikipedia(?::([\p{Lower}]{2,}))?" />
+           <link name="View {name} article" href="http://{k.1:en}.wikipedia.org/wiki/{v}" />
+	   </rule>
+	</source>
+	
+	<!-- Only for France -->
+    
+    <source name="SANDRE" country-code="FR">
+       <rule>
+           <condition k="ref:sandre" v="[A-Z0-9-]{8}" />
+           <link name="View {name} sheet of river" href="http://services.sandre.eaufrance.fr/Courdo/Fiche/client/fiche_courdo.php?CdSandre={v}" />
+       </rule>
+    </source>
+    
+    <source name="INSEE" country-code="FR">
+       <rule>
+           <condition k="admin_level" v="8"/>
+           <condition k="ref:INSEE" v="(\p{Digit}{2})(\p{Digit}{3})" id="ref"/>
+           <link name="View {name} municipality sheet" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/fichecommunale.asp?codedep={ref.v.1}&amp;codecom={ref.v.2}" />
+       </rule>
+       <rule>
+           <condition k="political_division" v="FR:canton"/>
+           <condition k="ref:INSEE" v="(\p{Digit}{2})(\p{Digit}{2})" id="ref"/>
+           <link name="View {name} map of municipalities" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/carte_comcan.asp?codecan={ref.v}" />
+           <link name="View {name} list of municipalities" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/comcan.asp?codedep={ref.v.1}&amp;codecan={ref.v.2}" />
+       </rule>
+       <rule>
+           <condition k="admin_level" v="7"/>
+           <condition k="ref:INSEE" v="(\p{Digit}{2})(\p{Digit}{1})" id="ref"/>
+           <link name="View {name} map of cantons" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/carte_canarr.asp?codearr={ref.v}" />
+           <link name="View {name} list of cantons" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/canarr.asp?codedep={ref.v.1}&amp;codearr={ref.v.2}" />
+       </rule>
+       <rule>
+           <condition k="admin_level" v="6"/>
+           <condition k="ref:INSEE" v="\p{Digit}{2}" id="ref"/>
+           <link name="View {name} map of arrondissements" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/carte_arrdep.asp?codedep={ref.v}" />
+           <link name="View {name} list of arrondissements" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/arrdep.asp?codedep={ref.v}" />
+       </rule>
+       <rule>
+           <condition k="admin_level" v="4"/>
+           <condition k="ref:INSEE" v="\p{Digit}{2}" id="ref"/>
+           <link name="View {name} map of departments" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/carte_depreg.asp?codereg={ref.v}" />
+           <link name="View {name} list of departments" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/depreg.asp?codereg={ref.v}" />
+       </rule>
+       <rule>
+           <condition k="admin_level" v="2"/>
+           <condition k="name" v="France*"/>
+           <link name="View {name} map of regions" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/carte_regions.asp" />
+           <link name="View {name} list of regions" href="http://www.insee.fr/fr/methodes/nomenclatures/cog/region.asp" />
+       </rule>
+    </source>
+    
+</tag2link>
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/Tag2LinkConstants.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/Tag2LinkConstants.java	(revision 26916)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/Tag2LinkConstants.java	(revision 26917)
@@ -16,10 +16,6 @@
 package org.openstreetmap.josm.plugins.tag2link;
 
-import javax.swing.ImageIcon;
-
-import org.openstreetmap.josm.tools.ImageProvider;
-
 /**
- * Main constants of JOSM Imagery XML Bounds plugin.
+ * Main constants of JOSM tag2link plugin.
  * @author Don-vip
  *
@@ -30,11 +26,6 @@
 	 * XML Schema
 	 */
-	public static final String XML_LOCATION = "resource://data/tag2link_sources.xml";
+	public static final String XML_LOCATION = "/resources/tag2link_sources.xml";
 	
-    /**
-     * XML tags
-     */
-    // TODO
-
 	/**
 	 * File encoding.
@@ -45,6 +36,6 @@
 	 * Plugin icons.
 	 */
-	public static ImageIcon ICON_16 = ImageProvider.get("tag2link_16.png");
-	public static ImageIcon ICON_24 = ImageProvider.get("tag2link_24.png");
-    public static ImageIcon ICON_48 = ImageProvider.get("tag2link_48.png");
+	public static String ICON_16 = "tag2linkv2_16x16.png";
+	public static String ICON_24 = "tag2linkv2_24x24.png";
+    public static String ICON_48 = "tag2linkv2_48x48.png";
 }
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/Tag2LinkPlugin.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/Tag2LinkPlugin.java	(revision 26916)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/Tag2LinkPlugin.java	(revision 26917)
@@ -16,6 +16,12 @@
 package org.openstreetmap.josm.plugins.tag2link;
 
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
 import org.openstreetmap.josm.plugins.Plugin;
 import org.openstreetmap.josm.plugins.PluginInformation;
+import org.openstreetmap.josm.plugins.tag2link.listeners.MembershipPopupListener;
+import org.openstreetmap.josm.plugins.tag2link.listeners.PropertyPopupListener;
+import org.openstreetmap.josm.plugins.tag2link.listeners.RelationPopupListener;
+import org.openstreetmap.josm.plugins.tag2link.listeners.SelectionPopupListener;
 
 /**
@@ -28,4 +34,6 @@
 public class Tag2LinkPlugin extends Plugin {
 
+    private Tag2LinkPreferenceSetting preferenceSetting;
+    
 	/**
 	 * Initializes the plugin.
@@ -34,4 +42,28 @@
 	public Tag2LinkPlugin(PluginInformation info) {
 		super(info);
+		this.preferenceSetting = new Tag2LinkPreferenceSetting();
+		Tag2LinkRuleChecker.init();
 	}
+
+    /* (non-Javadoc)
+     * @see org.openstreetmap.josm.plugins.Plugin#getPreferenceSetting()
+     */
+    @Override
+    public PreferenceSetting getPreferenceSetting() {
+        return this.preferenceSetting;
+    }
+    
+    /* (non-Javadoc)
+     * @see org.openstreetmap.josm.plugins.Plugin#mapFrameInitialized(org.openstreetmap.josm.gui.MapFrame, org.openstreetmap.josm.gui.MapFrame)
+     */
+    @Override
+    public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
+        if (newFrame != null) {
+            // Initialize dialogs listeners only after the main frame is created 
+            newFrame.selectionListDialog.addPopupMenuListener(new SelectionPopupListener(newFrame));
+            newFrame.propertiesDialog.addMembershipPopupMenuListener(new MembershipPopupListener(newFrame));
+            newFrame.propertiesDialog.addPropertyPopupMenuListener(new PropertyPopupListener(newFrame));
+            newFrame.relationListDialog.addPopupMenuListener(new RelationPopupListener(newFrame));
+        }
+    }
 }
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/Tag2LinkPreferenceSetting.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/Tag2LinkPreferenceSetting.java	(revision 26917)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/Tag2LinkPreferenceSetting.java	(revision 26917)
@@ -0,0 +1,38 @@
+//    JOSM tag2link plugin.
+//    Copyright (C) 2011 Don-vip & FrViPofm
+//
+//    This program is free software: you can redistribute it and/or modify
+//    it under the terms of the GNU General Public License as published by
+//    the Free Software Foundation, either version 3 of the License, or
+//    (at your option) any later version.
+//
+//    This program is distributed in the hope that it will be useful,
+//    but WITHOUT ANY WARRANTY; without even the implied warranty of
+//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//    GNU General Public License for more details.
+//
+//    You should have received a copy of the GNU General Public License
+//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+package org.openstreetmap.josm.plugins.tag2link;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import javax.swing.JPanel;
+
+import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
+
+public class Tag2LinkPreferenceSetting implements PreferenceSetting, Tag2LinkConstants {
+
+    @Override
+    public void addGui(PreferenceTabbedPane gui) {
+        JPanel p = gui.createPreferenceTab(ICON_48, tr("Tag2Link Preferences"),
+                tr("Tag2Link Preferences"), false);
+        // TODO
+    }
+
+    @Override
+    public boolean ok() {
+        return false;
+    }
+}
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/Tag2LinkRuleChecker.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/Tag2LinkRuleChecker.java	(revision 26917)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/Tag2LinkRuleChecker.java	(revision 26917)
@@ -0,0 +1,59 @@
+//    JOSM tag2link plugin.
+//    Copyright (C) 2011 Don-vip & FrViPofm
+//
+//    This program is free software: you can redistribute it and/or modify
+//    it under the terms of the GNU General Public License as published by
+//    the Free Software Foundation, either version 3 of the License, or
+//    (at your option) any later version.
+//
+//    This program is distributed in the hope that it will be useful,
+//    but WITHOUT ANY WARRANTY; without even the implied warranty of
+//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//    GNU General Public License for more details.
+//
+//    You should have received a copy of the GNU General Public License
+//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+package org.openstreetmap.josm.plugins.tag2link;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.plugins.tag2link.data.Link;
+import org.openstreetmap.josm.plugins.tag2link.data.Rule;
+import org.openstreetmap.josm.plugins.tag2link.data.Rule.EvalResult;
+import org.openstreetmap.josm.plugins.tag2link.data.Rule.MatchingTag;
+import org.openstreetmap.josm.plugins.tag2link.data.Source;
+import org.openstreetmap.josm.plugins.tag2link.io.SourcesReader;
+
+public class Tag2LinkRuleChecker implements Tag2LinkConstants {
+
+    private static Collection<Source> sources = new ArrayList<Source>();
+    
+    private static boolean initialized = false;
+        
+    public static void init() {
+        if (!initialized) {
+            sources = SourcesReader.readSources();
+            initialized = true;
+        }
+    }
+    
+    public static Collection<Link> getLinks(OsmPrimitive p) {
+        Collection<Link> result = new ArrayList<Link>();
+        for (Source source : sources) {
+            for (Rule rule : source.rules) {
+                EvalResult eval = rule.evaluates(p);
+                if (eval.matches()) {
+                    Set<String> links = new HashSet<String>();
+                    for (MatchingTag tag : eval.matchingTags) {
+                        
+                    }
+                }
+            }
+        }
+        return result;
+    }
+}
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/action/OpenLinkAction.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/action/OpenLinkAction.java	(revision 26917)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/action/OpenLinkAction.java	(revision 26917)
@@ -0,0 +1,25 @@
+package org.openstreetmap.josm.plugins.tag2link.action;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.plugins.tag2link.Tag2LinkConstants;
+import org.openstreetmap.josm.plugins.tag2link.data.Link;
+import org.openstreetmap.josm.tools.OpenBrowser;
+
+public class OpenLinkAction extends JosmAction implements Tag2LinkConstants {
+
+    private String url;
+    
+    public OpenLinkAction(Link link) {
+        super(tr(link.name), ICON_16, tr("Launch browser with information about the selected object"), null, true);
+        this.url = link.url;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        OpenBrowser.displayUrl(url);
+    }
+}
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Condition.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Condition.java	(revision 26917)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Condition.java	(revision 26917)
@@ -0,0 +1,9 @@
+package org.openstreetmap.josm.plugins.tag2link.data;
+
+import java.util.regex.Pattern;
+
+public class Condition {
+    public Pattern keyPattern;
+    public Pattern valPattern;
+    public String id;
+}
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Link.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Link.java	(revision 26917)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Link.java	(revision 26917)
@@ -0,0 +1,18 @@
+package org.openstreetmap.josm.plugins.tag2link.data;
+
+public class Link {
+    public String name;
+    public String url;
+    private boolean containsParams(String s) {
+        return s.matches("[^{}]*{[^{}]*}[^{}]*");
+    }
+    public boolean nameContainsParams() {
+        return containsParams(name);
+    }
+    public boolean urlContainsParams() {
+        return containsParams(url);
+    }
+    public boolean containsParams() {
+        return nameContainsParams() || urlContainsParams();
+    }
+}
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Rule.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Rule.java	(revision 26917)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Rule.java	(revision 26917)
@@ -0,0 +1,41 @@
+package org.openstreetmap.josm.plugins.tag2link.data;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+
+public class Rule {
+    public final Collection<Condition> conditions = new ArrayList<Condition>();
+    public final Collection<Link> links = new ArrayList<Link>();
+    
+    public static class MatchingTag {
+        public String key;
+        public String value;
+        public final Map<String, String> params = new HashMap<String, String>();
+    }
+    
+    public static class EvalResult {
+        public final Collection<MatchingTag> matchingTags = new ArrayList<MatchingTag>();
+        public boolean matches() {
+            return !matchingTags.isEmpty();
+        }
+    }
+    
+    public EvalResult evaluates(OsmPrimitive p) {
+        EvalResult result = new EvalResult();
+        Map<String, String> tags = p.getKeys();
+        for (Condition c : conditions) {
+            for (String key : tags.keySet()) {
+                Matcher m = c.keyPattern.matcher(key);
+                if (m.matches()) {
+                    
+                }
+            }
+        }
+        return result;
+    }
+}
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Source.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Source.java	(revision 26917)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/data/Source.java	(revision 26917)
@@ -0,0 +1,9 @@
+package org.openstreetmap.josm.plugins.tag2link.data;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class Source {
+    public String name;
+    public final Collection<Rule> rules = new ArrayList<Rule>();
+}
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/io/SourcesReader.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/io/SourcesReader.java	(revision 26917)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/io/SourcesReader.java	(revision 26917)
@@ -0,0 +1,182 @@
+package org.openstreetmap.josm.plugins.tag2link.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.openstreetmap.josm.io.UTFInputStreamReader;
+import org.openstreetmap.josm.plugins.tag2link.Tag2LinkConstants;
+import org.openstreetmap.josm.plugins.tag2link.data.Condition;
+import org.openstreetmap.josm.plugins.tag2link.data.Link;
+import org.openstreetmap.josm.plugins.tag2link.data.Rule;
+import org.openstreetmap.josm.plugins.tag2link.data.Source;
+
+public class SourcesReader implements Tag2LinkConstants {
+    
+    XMLStreamReader parser;
+    
+    public SourcesReader(XMLStreamReader parser) {
+        this.parser = parser;
+    }
+
+    public static Collection<Source> readSources() {
+        List<Source> result = new ArrayList<Source>();
+
+        try {
+            InputStream is = SourcesReader.class.getResourceAsStream(XML_LOCATION);
+            InputStreamReader ir = UTFInputStreamReader.create(is, ENCODING);
+            XMLStreamReader parser = XMLInputFactory.newInstance().createXMLStreamReader(ir);
+            result.addAll(new SourcesReader(parser).parseDoc());
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (XMLStreamException e) {
+            e.printStackTrace();
+        } catch (FactoryConfigurationError e) {
+            e.printStackTrace();
+        }
+        
+        return result;
+    }
+    
+    /**
+     * When cursor is at the start of an element, moves it to the end tag of that element.
+     * Nested content is skipped.
+     *
+     * This is basically the same code as parseUnkown(), except for the warnings, which
+     * are displayed for inner elements and not at top level.
+     */
+    private void jumpToEnd(boolean printWarning) throws XMLStreamException {
+        while (true) {
+            int event = parser.next();
+            if (event == XMLStreamConstants.START_ELEMENT) {
+                parseUnknown(printWarning);
+            } else if (event == XMLStreamConstants.END_ELEMENT) {
+                return;
+            }
+        }
+    }
+
+    private void jumpToEnd() throws XMLStreamException {
+        jumpToEnd(true);
+    }
+    
+    protected void parseUnknown() throws XMLStreamException {
+        parseUnknown(true);
+    }
+    
+    protected void parseUnknown(boolean printWarning) throws XMLStreamException {
+        if (printWarning) {
+            System.out.println(tr("Undefined element ''{0}'' found in input stream. Skipping.", parser.getLocalName()));
+        }
+        while (parser.hasNext()) {
+            int event = parser.next();
+            if (event == XMLStreamConstants.START_ELEMENT) {
+                parseUnknown(false); /* no more warning for inner elements */
+            } else if (event == XMLStreamConstants.END_ELEMENT) {
+                return;
+            }
+        }
+    }
+    
+    private Collection<Source> parseDoc() throws XMLStreamException {
+        List<Source> result = new ArrayList<Source>();
+        while (parser.hasNext()) {
+            int event = parser.next();
+            if (event == XMLStreamConstants.START_ELEMENT) {
+                if (parser.getLocalName().equals("tag2link")) {
+                    result.addAll(parseRoot());
+                } else {
+                    parseUnknown();
+                }
+            } else if (event == XMLStreamConstants.END_ELEMENT) {
+                break;
+            }
+        }
+        return result;
+    }
+    
+    private Collection<Source> parseRoot() throws XMLStreamException {
+        List<Source> result = new ArrayList<Source>();
+        while (parser.hasNext()) {
+            int event = parser.next();
+            if (event == XMLStreamConstants.START_ELEMENT) {
+                if (parser.getLocalName().equals("source")) {
+                    result.add(parseSource());
+                } else {
+                    parseUnknown();
+                }
+            } else if (event == XMLStreamConstants.END_ELEMENT) {
+                break;
+            }
+        }
+        return result;
+    }
+
+    private Source parseSource() throws XMLStreamException {
+        Source source = new Source();
+        while (parser.hasNext()) {
+            int event = parser.next();
+            if (event == XMLStreamConstants.START_ELEMENT) {
+                if (parser.getLocalName().equals("rule")) {
+                    source.rules.add(parseRule());
+                } else {
+                    parseUnknown();
+                }
+            } else if (event == XMLStreamConstants.END_ELEMENT) {
+                break;
+            }
+        }
+        return source;
+    }
+
+    private Rule parseRule() throws XMLStreamException {
+        Rule rule = new Rule();
+        while (parser.hasNext()) {
+            int event = parser.next();
+            if (event == XMLStreamConstants.START_ELEMENT) {
+                if (parser.getLocalName().equals("condition")) {
+                    rule.conditions.add(parseCondition());
+                } else if (parser.getLocalName().equals("link")) {
+                        rule.links.add(parseLink());
+                } else {
+                    parseUnknown();
+                }
+            } else if (event == XMLStreamConstants.END_ELEMENT) {
+                break;
+            }
+        }
+        return rule;
+    }
+
+    private Condition parseCondition() throws XMLStreamException {
+        Condition c = new Condition();
+        c.keyPattern = Pattern.compile(parser.getAttributeValue(null, "k"));
+        String v = parser.getAttributeValue(null, "v");
+        if (v != null) {
+        	c.valPattern = Pattern.compile(v);
+        }
+        c.id = parser.getAttributeValue(null, "id");
+        jumpToEnd();
+        return c;
+    }
+
+    private Link parseLink() throws XMLStreamException {
+        Link link = new Link();
+        link.name = parser.getAttributeValue(null, "name");
+        link.url  = parser.getAttributeValue(null, "href");
+        jumpToEnd();
+        return link;
+    }
+}
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/AbstractOsmPrimitivePopupListener.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/AbstractOsmPrimitivePopupListener.java	(revision 26917)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/AbstractOsmPrimitivePopupListener.java	(revision 26917)
@@ -0,0 +1,44 @@
+//    JOSM tag2link plugin.
+//    Copyright (C) 2011 Don-vip & FrViPofm
+//
+//    This program is free software: you can redistribute it and/or modify
+//    it under the terms of the GNU General Public License as published by
+//    the Free Software Foundation, either version 3 of the License, or
+//    (at your option) any later version.
+//
+//    This program is distributed in the hope that it will be useful,
+//    but WITHOUT ANY WARRANTY; without even the implied warranty of
+//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//    GNU General Public License for more details.
+//
+//    You should have received a copy of the GNU General Public License
+//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+package org.openstreetmap.josm.plugins.tag2link.listeners;
+
+import javax.swing.JPopupMenu;
+import javax.swing.event.PopupMenuEvent;
+
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.plugins.tag2link.Tag2LinkRuleChecker;
+import org.openstreetmap.josm.plugins.tag2link.data.Link;
+
+public abstract class AbstractOsmPrimitivePopupListener extends AbstractPopupListener {
+
+    protected AbstractOsmPrimitivePopupListener(MapFrame frame) {
+        super(frame);
+    }
+
+    protected abstract OsmPrimitive getFirstSelectedPrimitive();
+    
+    @Override
+    public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
+        OsmPrimitive p = getFirstSelectedPrimitive();
+        if (p != null) {
+            JPopupMenu popup = (JPopupMenu) e.getSource();
+            for (Link link : Tag2LinkRuleChecker.getLinks(p)) {
+                addLink(popup, link);
+            }
+        }
+    }
+}
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/AbstractPopupListener.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/AbstractPopupListener.java	(revision 26917)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/AbstractPopupListener.java	(revision 26917)
@@ -0,0 +1,56 @@
+//    JOSM tag2link plugin.
+//    Copyright (C) 2011 Don-vip & FrViPofm
+//
+//    This program is free software: you can redistribute it and/or modify
+//    it under the terms of the GNU General Public License as published by
+//    the Free Software Foundation, either version 3 of the License, or
+//    (at your option) any later version.
+//
+//    This program is distributed in the hope that it will be useful,
+//    but WITHOUT ANY WARRANTY; without even the implied warranty of
+//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//    GNU General Public License for more details.
+//
+//    You should have received a copy of the GNU General Public License
+//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+package org.openstreetmap.josm.plugins.tag2link.listeners;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.event.PopupMenuEvent;
+import javax.swing.event.PopupMenuListener;
+
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.plugins.tag2link.action.OpenLinkAction;
+import org.openstreetmap.josm.plugins.tag2link.data.Link;
+
+public abstract class AbstractPopupListener implements PopupMenuListener {
+    
+    protected final MapFrame frame;
+    protected final List<JMenuItem> itemList;
+    
+    protected AbstractPopupListener(MapFrame frame) {
+        this.frame = frame;
+        this.itemList = new ArrayList<JMenuItem>();
+    }
+    
+    @Override
+    public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
+        JPopupMenu popup =  (JPopupMenu) e.getSource();
+        for (JMenuItem item : itemList) {
+            popup.remove(item);
+        }
+        itemList.clear();
+    }
+
+    @Override
+    public void popupMenuCanceled(PopupMenuEvent e) {
+    }
+    
+    protected void addLink(JPopupMenu popup, Link link) {
+        itemList.add(popup.add(new OpenLinkAction(link)));
+    }
+}
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/MembershipPopupListener.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/MembershipPopupListener.java	(revision 26917)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/MembershipPopupListener.java	(revision 26917)
@@ -0,0 +1,32 @@
+//    JOSM tag2link plugin.
+//    Copyright (C) 2011 Don-vip & FrViPofm
+//
+//    This program is free software: you can redistribute it and/or modify
+//    it under the terms of the GNU General Public License as published by
+//    the Free Software Foundation, either version 3 of the License, or
+//    (at your option) any later version.
+//
+//    This program is distributed in the hope that it will be useful,
+//    but WITHOUT ANY WARRANTY; without even the implied warranty of
+//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//    GNU General Public License for more details.
+//
+//    You should have received a copy of the GNU General Public License
+//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+package org.openstreetmap.josm.plugins.tag2link.listeners;
+
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.gui.MapFrame;
+
+public class MembershipPopupListener extends AbstractOsmPrimitivePopupListener {
+
+    public MembershipPopupListener(MapFrame frame) {
+        super(frame);
+    }
+
+    @Override
+    protected OsmPrimitive getFirstSelectedPrimitive() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+}
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/PropertyPopupListener.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/PropertyPopupListener.java	(revision 26917)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/PropertyPopupListener.java	(revision 26917)
@@ -0,0 +1,35 @@
+//    JOSM tag2link plugin.
+//    Copyright (C) 2011 Don-vip & FrViPofm
+//
+//    This program is free software: you can redistribute it and/or modify
+//    it under the terms of the GNU General Public License as published by
+//    the Free Software Foundation, either version 3 of the License, or
+//    (at your option) any later version.
+//
+//    This program is distributed in the hope that it will be useful,
+//    but WITHOUT ANY WARRANTY; without even the implied warranty of
+//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//    GNU General Public License for more details.
+//
+//    You should have received a copy of the GNU General Public License
+//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+package org.openstreetmap.josm.plugins.tag2link.listeners;
+
+import javax.swing.event.PopupMenuEvent;
+
+import org.openstreetmap.josm.gui.MapFrame;
+
+public class PropertyPopupListener extends AbstractPopupListener {
+
+    public PropertyPopupListener(MapFrame frame) {
+        super(frame);
+        // TODO Auto-generated constructor stub
+    }
+
+    @Override
+    public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
+        // TODO Auto-generated method stub
+
+    }
+
+}
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/RelationPopupListener.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/RelationPopupListener.java	(revision 26917)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/RelationPopupListener.java	(revision 26917)
@@ -0,0 +1,31 @@
+//    JOSM tag2link plugin.
+//    Copyright (C) 2011 Don-vip & FrViPofm
+//
+//    This program is free software: you can redistribute it and/or modify
+//    it under the terms of the GNU General Public License as published by
+//    the Free Software Foundation, either version 3 of the License, or
+//    (at your option) any later version.
+//
+//    This program is distributed in the hope that it will be useful,
+//    but WITHOUT ANY WARRANTY; without even the implied warranty of
+//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//    GNU General Public License for more details.
+//
+//    You should have received a copy of the GNU General Public License
+//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+package org.openstreetmap.josm.plugins.tag2link.listeners;
+
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.gui.MapFrame;
+
+public class RelationPopupListener extends AbstractOsmPrimitivePopupListener {
+
+    public RelationPopupListener(MapFrame frame) {
+        super(frame);
+    }
+
+    @Override
+    protected OsmPrimitive getFirstSelectedPrimitive() {
+        return frame.relationListDialog.getSelectedRelations().iterator().next();
+    }
+}
Index: /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/SelectionPopupListener.java
===================================================================
--- /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/SelectionPopupListener.java	(revision 26917)
+++ /applications/editors/josm/plugins/tag2link/src/org/openstreetmap/josm/plugins/tag2link/listeners/SelectionPopupListener.java	(revision 26917)
@@ -0,0 +1,31 @@
+//    JOSM tag2link plugin.
+//    Copyright (C) 2011 Don-vip & FrViPofm
+//
+//    This program is free software: you can redistribute it and/or modify
+//    it under the terms of the GNU General Public License as published by
+//    the Free Software Foundation, either version 3 of the License, or
+//    (at your option) any later version.
+//
+//    This program is distributed in the hope that it will be useful,
+//    but WITHOUT ANY WARRANTY; without even the implied warranty of
+//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//    GNU General Public License for more details.
+//
+//    You should have received a copy of the GNU General Public License
+//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+package org.openstreetmap.josm.plugins.tag2link.listeners;
+
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.gui.MapFrame;
+
+public class SelectionPopupListener extends AbstractOsmPrimitivePopupListener {
+
+    public SelectionPopupListener(MapFrame frame) {
+        super(frame);
+    }
+
+    @Override
+    protected OsmPrimitive getFirstSelectedPrimitive() {
+        return frame.selectionListDialog.getSelectedPrimitives().iterator().next();
+    }
+}
