Add support for relations to match multiple tags. Turned out to be a bit more involve...
authorSteve Bennett <stevagewp@gmail.com>
Fri, 18 Feb 2011 11:32:12 +0000 (11:32 +0000)
committerSteve Bennett <stevagewp@gmail.com>
Fri, 18 Feb 2011 11:32:12 +0000 (11:32 +0000)
The syntax is slightly inconsistent:
    <tag k="route" v="hiking" vmatch="hiking|foot"/>
on the relation, but
      <match k="route" v="hiking|foot"/>
on the path. I don't think it's a major drama, and easily changed. Also, match/@v is not a regexp, it's just pipe-separated values.
Inspired by NopMap <ekkehart@gmx.de> on potlatch-dev, 14 Feb 2011.

net/systemeD/halcyon/connection/Connection.as
net/systemeD/potlatch2/RelationSelectPanel.mxml
net/systemeD/potlatch2/mapfeatures/editors/RelationMemberEditor.as
net/systemeD/potlatch2/mapfeatures/editors/RelationMemberEditorFactory.as
net/systemeD/potlatch2/mapfeatures/editors/RouteEditor.mxml
resources/map_features.xml
resources/map_features/paths.xml

index 847b6dd..1a6ddaf 100644 (file)
@@ -1,12 +1,12 @@
 package net.systemeD.halcyon.connection {
 
-    import flash.net.*;
-
-    import flash.events.EventDispatcher;
     import flash.events.Event;
-       import net.systemeD.halcyon.connection.actions.*;
-       import net.systemeD.halcyon.AttentionEvent;
-       import net.systemeD.halcyon.MapEvent;
+    import flash.events.EventDispatcher;
+    import flash.net.*;
+    
+    import net.systemeD.halcyon.AttentionEvent;
+    import net.systemeD.halcyon.MapEvent;
+    import net.systemeD.halcyon.connection.actions.*;
 
        public class Connection extends EventDispatcher {
 
@@ -308,14 +308,18 @@ package net.systemeD.halcyon.connection {
             return list;
         }
 
+        /** Returns all available relations that match all of {k1: [v1,v2,...], k2: [v1...] ...} 
+        * where p1 is an array [v1, v2, v3...] */
         public function getMatchingRelationIDs(match:Object):Array {
             var list:Array = [];
-                       var ok:Boolean;
             for each (var relation:Relation in relations) {
-                               ok=true;
-                               if (relation.deleted) { ok=false; }
+                var ok: Boolean = true;
+                               if (relation.deleted) { continue; }
                                for (var k:String in match) {
-                                       if (!relation.getTagsHash()[k] || relation.getTagsHash()[k]!=match[k]) { ok=false; }
+                                       var v:String = relation.getTagsHash()[k];
+                                       if (!v || match[k].indexOf(v) < 0) { 
+                                          ok = false; break;  
+                                       }
                                }
                                if (ok) { list.push(relation.id); }
                        }
index 4a1a2b9..37a184f 100644 (file)
         private var conn:Connection;
         private var relationList:Array;
         private var entity:Entity;
-               private var tags:Object;
+               private var defaulttags:Object;
 
+        /** Initialise panel used to add and remove relations from an entity.
+        *   @param e Entity that is being edited.
+        *   @param t Object containing tag match patterns as properties, for the kind of relation sought.
+        */
         public function init(e:Entity, t:Object):void {
           entity = e;
-          tags = {}; for (var k:String in t) { tags[k]=t[k]; } // deep copy tags
+          defaulttags = {};
+          for (var k:String in t) {  
+            //tagmatches[k]=t[k];// deep copy match pattern tags
+            defaulttags[k]=t[k][0];  // route=[hiking,foot] -> route=hiking
+          }    
           PopUpManager.addPopUp(this, Application(Application.application), true);
           PopUpManager.centerPopUp(this);
     
           var titles:Array = [];
           conn = Connection.getConnectionInstance();
-          relationList = conn.getMatchingRelationIDs(tags);
+          relationList = conn.getMatchingRelationIDs(t);
           if (relationList.length == 0) {
             warning.text = "No relations available";
           } else {
@@ -64,7 +72,7 @@
                                        members.push(new RelationMember(e, ''));
                                }
                        } else members.push(new RelationMember(entity, ''));
-                       var relation:Relation = conn.createRelation(tags, members, MainUndoStack.getGlobalStack().addAction);
+                       var relation:Relation = conn.createRelation(defaulttags, members, MainUndoStack.getGlobalStack().addAction);
 
                        PopUpManager.removePopUp(this);
                        var panel:RelationEditorPanel = RelationEditorPanel(
index 86947ba..212f17a 100644 (file)
@@ -25,16 +25,19 @@ package net.systemeD.potlatch2.mapfeatures.editors {
           if (_entity == null)
               return [];
           
-          var relationTags:Object = _factory.relationTags;
+          var relationTagPatterns:Object = _factory.relationTagPatterns;
           var matched:Array = [];
+          
           for each(var relation:Relation in _entity.parentRelations) {
               var addable:Boolean = true;
-              for ( var k:String in relationTags ) {
+              for ( var k:String in relationTagPatterns ) {
                   var relVal:String = relation.getTag(k);
-                  if ( relVal != relationTags[k] )
+                  if ( relationTagPatterns[k].indexOf(relVal) < 0 ) {
                       addable = false;
+                      break;
+                  }
               }
-              if (_factory.role && !relation.hasMemberInRole(_entity,_factory.role) ) { addable=false; }
+              if (_factory.role && !relation.hasMemberInRole(_entity,_factory.role) ) { continue; }
 
               if (addable) {
                   for each( var memberIndex:int in relation.findEntityMemberIndexes(_entity)) {
index 180810e..8aa73f4 100644 (file)
@@ -1,26 +1,30 @@
 package net.systemeD.potlatch2.mapfeatures.editors {
 
+    import flash.display.*;
+    
     import net.systemeD.halcyon.connection.*;
     import net.systemeD.potlatch2.mapfeatures.*;
-    import flash.display.*;
 
        public class RelationMemberEditorFactory extends EditorFactory {
-           private var _relationTags:Object;
+           /** Contains "route"=["hiking","foot"] key/values. The <match> map_features tag is parsed here from
+           * "hiking|foot" pipe-separated values. */
+           private var _relationTagPatterns:Object;
                private var _role:String;
         
+        /** Constructs the editing panel for a relation(###), given its <relation> in map_features.xml */
         public function RelationMemberEditorFactory(inputXML:XML) {
             super(inputXML);
-            _relationTags = {};
+            _relationTagPatterns = {};
             for each(var match:XML in inputXML.match) {
-                _relationTags[match.@k] = match.@v;
+                _relationTagPatterns[match.@k] = match.@v.split('|');
             }
                        for each(var role:XML in inputXML.role) {
                                _role=role.@role;
                        }
         }
         
-        public function get relationTags():Object {
-            return _relationTags;
+        public function get relationTagPatterns():Object {
+            return _relationTagPatterns;
         }
         
         public function get role():String {
@@ -35,9 +39,9 @@ package net.systemeD.potlatch2.mapfeatures.editors {
             // get relations for the entity
             for each(var relation:Relation in parentRelations) {
                                var match:Boolean=true;
-                for ( var k:String in _relationTags ) {
+                for ( var k:String in _relationTagPatterns ) {
                     var relVal:String = relation.getTag(k);
-                    if ( relVal != _relationTags[k] ) { match=false; break; }
+                    if (k.indexOf(relVal) < 0) { match=false; break; }
                                        if ( _role && !relation.hasMemberInRole(entity,_role) ) { match=false; break; }
                 }
                                if (match) { return true; }
index d773ba6..53e9ad6 100644 (file)
@@ -39,7 +39,7 @@
     }
 
        public function addToRelation():void {
-               new RelationSelectPanel().init(_entity, _factory.relationTags);        
+               new RelationSelectPanel().init(_entity, _factory.relationTagPatterns);        
        }
     
   ]]></mx:Script>
index d79146c..afb3c4b 100644 (file)
@@ -473,7 +473,7 @@ Quick documentation:
   <inputSet id="ldp">
     <input type="route" name="National Walking Route" description="National walking route" category="Walking" priority="normal">
       <match k="type" v="route"/>
-      <match k="route" v="hiking"/>
+      <match k="route" v="hiking|foot"/>
       <match k="network" v="nwn"/>
       <icon image="features/route__nwn.png" background="red" foreground="white">
         <font size="14pt"><b>${ref}</b></font><br/>
@@ -482,7 +482,7 @@ Quick documentation:
     </input>
     <input type="route" name="Regional Walking Route" description="Regional walking route" category="Walking" priority="low">
       <match k="type" v="route"/>
-      <match k="route" v="hiking"/>
+      <match k="route" v="hiking|foot"/>
       <match k="network" v="rwn"/>
       <icon image="features/route__rwn.png" background="cyan" foreground="white">
         <font size="14pt"><b>${ref}</b></font><br/>
@@ -491,7 +491,7 @@ Quick documentation:
     </input>
     <input type="route" name="Local Walking Route" description="Local walking route" category="Walking" priority="lowest">
       <match k="type" v="route"/>
-      <match k="route" v="hiking"/>
+      <match k="route" v="hiking|foot"/>
       <match k="network" v="lwn"/>
       <icon image="features/route__lwn.png" background="blue" foreground="white">
         <font size="14pt"><b>${ref}</b></font><br/>
index f574de0..4b7b2a3 100644 (file)
 \r
     <relation/>\r
     <tag k="type" v="route"/>\r
-    <tag k="route" v="hiking"/>\r
+    <tag k="route" v="hiking" vmatch="hiking|foot"/>\r
 \r
     <inputSet ref="route"/>\r
     <inputSet ref="common"/>\r