[OpenLayers-Dev] [OpenLayers-Users] Help to create FeatureId filter & OpenLayers.Filter.Logical.NOT

Andreas Hocevar ahocevar at opengeo.org
Thu Dec 2 06:20:42 EST 2010


It violates the spec, but as you have found out, GeoServer at this point seems to support it. For the record, here is a patch to make it work through OpenLayers:

Index: tests/Format/Filter/v1.html
===================================================================
--- tests/Format/Filter/v1.html	(revision 10937)
+++ tests/Format/Filter/v1.html	(working copy)
@@ -166,7 +166,41 @@
 
     }
 
+    function test_Not_FeatureId(t) {
+        
+        t.plan(3);
+        
+        var str =
+            '<Filter xmlns="http://www.opengis.net/ogc">' +
+                '<Not>' +
+                    '<Filter>' +
+                        '<FeatureId fid="states.34"/>' +
+                        '<FeatureId fid="states.35"/>' +
+                    '</Filter>' +
+                '</Not>' +
+            '</Filter>';
 
+        var format = new OpenLayers.Format.Filter.v1_0_0();
+        var filter = new OpenLayers.Filter.Logical({
+            type: OpenLayers.Filter.Logical.NOT,
+            filters: [new OpenLayers.Filter.FeatureId({
+                fids: ["states.34", "states.35"]
+            })]
+        });
+        
+        // test writing
+        var node = format.write(filter);
+        t.xml_eq(node, str, "filter correctly written");
+        
+        // test reading
+        var doc = (new OpenLayers.Format.XML).read(str);
+        var got = format.read(doc.firstChild);
+        console.log(got);
+        t.eq(got.type, filter.type, "read correct type");
+        t.eq(got.filters[0].fids, filter.filters[0].fids, "read correct fids");
+
+    }
+
     </script> 
 </head> 
 <body>
Index: lib/OpenLayers/Format/Filter/v1.js
===================================================================
--- lib/OpenLayers/Format/Filter/v1.js	(revision 10937)
+++ lib/OpenLayers/Format/Filter/v1.js	(working copy)
@@ -87,9 +87,14 @@
                 };
                 this.readChildNodes(node, obj);
                 if(obj.fids.length > 0) {
-                    parent.filter = new OpenLayers.Filter.FeatureId({
+                    var filter = new OpenLayers.Filter.FeatureId({
                         fids: obj.fids
                     });
+                    if (parent.filters) {
+                        parent.filters.push(filter)
+                    } else {
+                        parent.filter = filter;
+                    }
                 } else if(obj.filters.length > 0) {
                     parent.filter = obj.filters[0];
                 }
@@ -390,7 +395,8 @@
      * Method: getFilterType
      */
     getFilterType: function(filter) {
-        var filterType = this.filterMap[filter.type];
+        var filterType = filter instanceof OpenLayers.Filter.FeatureId ?
+            "Filter" : this.filterMap[filter.type];
         if(!filterType) {
             throw "Filter writing not supported for rule type: " + filter.type;
         }

Regards,
Andreas.

On Dec 13, 2009, at 20:18 , Ivan Grcic wrote:

> From the Filter Impl. Specs:
> 
> The XML encoding for the logical operators AND, OR and NOT is defined
> by the following XML Schema fragment:
> 
>    <element name="And" type="ogc:BinaryLogicOpType"
> substitutionGroup="ogc:logicOps"/>
>    <element name="Or" type="ogc:BinaryLogicOpType"
> substitutionGroup="ogc:logicOps"/>
>    <element name="Not" type="ogc:UnaryLogicOpType"
> substitutionGroup="ogc:logicOps"/>
>    <element name="logicOps" type="ogc:LogicOpsType" abstract="true"/>
>    <complexType name="LogicOpsType" abstract="true"/>
>    <complexType name="BinaryLogicOpType">
>        <complexContent>
>            <extension base="ogc:LogicOpsType">
>                <choice minOccurs="2" maxOccurs="unbounded">
>                    <element ref="ogc:comparisonOps"/>
>                    <element ref="ogc:spatialOps"/>
>                    <element ref="ogc:logicOps"/>
>                </choice>
>            </extension>
>        </complexContent>
>    </complexType>
>    <complexType name="UnaryLogicOpType">
>        <complexContent>
>            <extension base="ogc:LogicOpsType">
>                <sequence>
>                    <choice>
>                        <element ref="ogc:comparisonOps"/>
>                        <element ref="ogc:spatialOps"/>
>                        <element ref="ogc:logicOps"/>
>                    </choice>
>                </sequence>
>            </extension>
>        </complexContent>
>    </complexType>
> 
> 
> It doesnt have FeatureIdType choice. And putting filter manually into
> geoserver expectedly throws:
> 
> Your .SLD file does not conform to the SLD Schema
> cvc-complex-type.2.4.a: Invalid content starting with element
> 'ogc:FeatureId'. One of '{"http://www.opengis.net/ogc":comparisonOps,
> "http://www.opengis.net/ogc":spatialOps,
> "http://www.opengis.net/ogc":logicOps}' is expected
> 
> But creating filter in OL and making request DOES return all the
> features but listed ones. So geoserver does support it.
> 
> Does anyone know what would be the correct (compliant) way then to
> make filter that will fetch all the features except the ones in
> FeatureIds ?
> 
> Cheers
> 
> On Sun, Dec 13, 2009 at 2:38 PM, Eric Lemoine
> <eric.lemoine at camptocamp.com> wrote:
>> On Thursday, December 10, 2009, Ivan Grcic <ivan.grcic at geofoto.hr> wrote:
>>> Hi devs,
>>> 
>>> before opening ticket i want to confirm that im right about this issue
>>> 
>>> Currently its not possible to make filter like this:
>>> <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
>>> <And>
>>> <Not><ogc:FeatureId fid="Feature.1"/></Not>
>>> <Not><ogc:FeatureId fid="Feature.2"/></Not>
>>> </And>
>>> </Filter>
>>> 
>>> I trace the source of it, in Format/Filter/v1.js writers&readers for
>>> AND,OR, NOT do not handle FeatureIds seperatly as root "Filter" does.
>>> 
>>> line: 296
>>> 
>>>             "Not": function(filter) {
>>>                 var node = this.createElementNSPlus("ogc:Not");
>>>                 var childFilter = filter.filters[0];
>>>                 this.writeNode(
>>>                     this.getFilterType(childFilter), childFilter, node
>>>                 );
>>>                 return node;
>>>             },
>>> 
>>> That happens because FeatureId doesnt have type and getFilterType
>>> method throws "Filter writing not supported for rule type: undefined"
>>> if we try to encapsulate FeatureId with Logical.Not
>>> 
>>> Its neccesary to check if filter is of FeatureId type and treat it
>>> differently, like the root Filter element does
>>> 
>>>             "Not": function(filter) {
>>>                 var node = this.createElementNSPlus("ogc:Not");
>>>                 var childFilter = filter.filters[0];
>>> 
>>>                 var sub = childFilter.CLASS_NAME.split(".").pop();
>>>                 if(sub === "FeatureId") {
>>>                     for(var i=0; i<childFilter.fids.length; ++i) {
>>>                         this.writeNode("FeatureId", childFilter.fids[i], node);
>>>                     }
>>>                 } else {
>>>                     this.writeNode(
>>>                         this.getFilterType(childFilter), childFilter, node
>>>                     );
>>>                 }
>>>                 return node;
>>>             }
>>> 
>>> Please can anyone confirm this?
>> 
>> Hi. I don't know the specs but they allow FeatureID filters within NOT
>> filters then I agree there's a bug in the library. And I think the
>> problem exists for AND and OR as well, no?
>> 
>> Cheers,
>> 
>> --
>> Eric Lemoine
>> 
>> Camptocamp France SAS
>> Savoie Technolac, BP 352
>> 73377 Le Bourget du Lac, Cedex
>> 
>> Tel : 00 33 4 79 44 44 96
>> Mail : eric.lemoine at camptocamp.com
>> http://www.camptocamp.com
>> 
> 
> 
> 
> -- 
> Ivan Grcic
> _______________________________________________
> Dev mailing list
> Dev at openlayers.org
> http://openlayers.org/mailman/listinfo/dev

-- 
Andreas Hocevar
OpenGeo - http://opengeo.org/
Expert service straight from the developers.



More information about the Dev mailing list