[OpenLayers-Commits] r4746 - in sandbox/ahocevar/sldRenderer/lib: . OpenLayers OpenLayers/Format OpenLayers/Rule

commits at openlayers.org commits at openlayers.org
Mon Oct 1 23:06:18 EDT 2007


Author: ahocevar
Date: 2007-10-01 23:06:16 -0400 (Mon, 01 Oct 2007)
New Revision: 4746

Added:
   sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule.js
   sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule/
   sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule/Comparison.js
   sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule/FeatureId.js
   sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule/Logical.js
Modified:
   sandbox/ahocevar/sldRenderer/lib/OpenLayers.js
   sandbox/ahocevar/sldRenderer/lib/OpenLayers/Format/SLD.js
   sandbox/ahocevar/sldRenderer/lib/OpenLayers/Style.js
Log:
got rid of using eval for evaluating the rules! Now there is a new class OpenLayers.Rule, with subclasses for three basic types of rules (similar to the ogc rules xsd schema). Also: code style fixes (< 80 chars/line) and improved NaturalDocs comments.

Modified: sandbox/ahocevar/sldRenderer/lib/OpenLayers/Format/SLD.js
===================================================================
--- sandbox/ahocevar/sldRenderer/lib/OpenLayers/Format/SLD.js	2007-10-02 02:55:22 UTC (rev 4745)
+++ sandbox/ahocevar/sldRenderer/lib/OpenLayers/Format/SLD.js	2007-10-02 03:06:16 UTC (rev 4746)
@@ -3,9 +3,12 @@
  * for the full text of the license. */
 
 /**
- * @requires OpenLayers/UserStyle.js
- * @requires OpenLayers/Format.js
  * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Style.js
+ * @requires OpenLayers/Rule.js
+ * @requires OpenLayers/Rule/FeatureId.js
+ * @requires OpenLayers/Rule/Logical.js
+ * @requires OpenLayers/Rule/Comparison.js
  *
  * Class: OpenLayers.Format.SLD
  * Read/Wite SLD. Create a new instance with the <OpenLayers.Format.SLD>
@@ -62,14 +65,16 @@
             data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
         }
         
-        var userStyles = this.getElementsByTagNameNS(data, this.sldns, "UserStyle");
+        var userStyles = this.getElementsByTagNameNS(data, this.sldns,
+                "UserStyle");
         if (userStyles.length == 0) {
             return {};
         }
         var styles = {};
         for (var i=0; i<userStyles.length; i++) {
-            var name = OpenLayers.Util.getXmlNodeValue(
-                    this.getElementsByTagNameNS(userStyles[i], this.sldns, "Name")[0]);
+            var nameNode = this.getElementsByTagNameNS(userStyles[i],
+                    this.sldns, "Name")
+            var name = OpenLayers.Util.getXmlNodeValue(nameNode[0]);
             styles[name] = this.parseUserStyle(userStyles[i]);
         }
         
@@ -89,13 +94,15 @@
     parseUserStyle: function(xmlNode) {
         var userStyle = new OpenLayers.Style();
          
-        var ruleNodes = this.getElementsByTagNameNS(xmlNode, this.sldns, "Rule");
+        var ruleNodes = this.getElementsByTagNameNS(xmlNode, this.sldns,
+                "Rule");
         if (ruleNodes.length == 0) { return []; }
 
         var rules = userStyle.rules;
         for (var i=0; i<ruleNodes.length; i++) {
-            var name = OpenLayers.Util.getXmlNodeValue(
-                    this.getElementsByTagNameNS(ruleNodes[i], this.sldns, "Name")[0]);
+            var nameNode = this.getElementsByTagNameNS(ruleNodes[i], this.sldns,
+                    "Name");
+            var name = OpenLayers.Util.getXmlNodeValue(nameNode[0]);
             rules.push(this.parseRule(ruleNodes[i], name));
         }
 
@@ -114,20 +121,17 @@
      * {Object} Hash of rule properties
      */
     parseRule: function(xmlNode, name) {
-        var rule = {};
-        OpenLayers.Util.extend(rule, OpenLayers.Style.RULE);
-        rule.name = name;
-        rule.symbolizer = {};
-        
+
         // FILTERS
         
         var filter = this.getElementsByTagNameNS(xmlNode, this.ogcns, "Filter");
         if (filter && filter.length > 0) {
-           rule.appliesIf += this.parseFilter(filter[0]);
+           var rule = this.parseFilter(filter[0], null);
         } else {
-            // style applies to all features
-            rule.appliesIf = "true";
+            // rule applies to all features
+            var rule = new OpenLayers.Rule()
         }
+        rule.name = name;
         
         // SCALE DENOMINATORS
         
@@ -162,68 +166,43 @@
                 var style = {};
             
                 // externalGraphic
-                var externalGraphic = this.getElementsByTagNameNS(symbolizer[0],
-                        this.sldns, "ExternalGraphic");
-                if (externalGraphic && externalGraphic.length > 0) {
-                    style.externalGraphic = this.getElementsByTagNameNS(
-                            externalGraphic[0], this.sldns, "OnlineResource").getAttribute("xlink:href");
+                var graphic = this.getElementsByTagNameNS(symbolizer[0],
+                        this.sldns, "Graphic");
+                if (graphic && graphic.length > 0) {
+                    style.externalGraphic = this.parseProperty(graphic[0],
+                            "ExternalGraphic", this.sldns, "OnlineResource",
+                            "xlink:href");
+                    style.pointRadius = this.parseProperty(graphic[0], "Size",
+                            this.sldns);
+                    style.graphicOpacity = this.parseProperty(graphic[0],
+                            "Opacity", this.sldns);
                 }
-                var size = this.getElementsByTagNameNS(symbolizer[0], this.sldns, "Size");
-                if (size && size.length > 0) {
-                    style.pointRadius = parseFloat(OpenLayers.Util.getXmlNodeValue(size[0]));
-                }
-                var opacity = this.getElementsByTagNameNS(symbolizer[0], this.sldns, "Opacity");
-                if (opacity && opacity.length > 0) {
-                    style.graphicOpacity = parseFloat(OpenLayers.Util.getXmlNodeValue(opacity[0]));
-                }
                 
                 // fill
-                var fill = this.getElementsByTagNameNS(symbolizer[0], this.sldns, "Fill");
+                var fill = this.getElementsByTagNameNS(symbolizer[0],
+                        this.sldns, "Fill");
                 if (fill && fill.length > 0) {
-                    var cssParameter = this.getElementsByTagNameNS(fill[0], this.sldns, "CssParameter");
-                    var literal, attribute;
-                    for (var i=0; i<cssParameter.length; i++) {
-                        literal = this.getElementsByTagNameNS(cssParameter[i], this.ogcns, "Literal");
-                        attribute = cssParameter[i].getAttribute("name");
-                        // fillColor
-                        if (attribute == "fill") {
-                            style.fillColor = OpenLayers.String.trim(
-                                    OpenLayers.Util.getXmlNodeValue(cssParameter[i]));
-                        } else
-                        // fillOpacity
-                        if (attribute == "fill-opacity") {
-                            style.fillOpacity = parseFloat(OpenLayers.Util.getXmlNodeValue(cssParameter[i]));
-                        }
-                    }
+                    style.fillColor = this.parseProperty(fill[0], this.sldns,
+                            "CssParameter", "name", "fill");
+                    style.fillOpacity = this.parseProperty(fill[0],
+                            this.sldns, "CssParameter", "name", "fill-opacity");
                 }
             
                 // stroke
-                var stroke = this.getElementsByTagNameNS(symbolizer[0], this.sldns, "Stroke");
+                var stroke = this.getElementsByTagNameNS(symbolizer[0],
+                        this.sldns, "Stroke");
                 if (stroke && stroke.length > 0) {
-                    var cssParameter = this.getElementsByTagNameNS(stroke[0], this.sldns, "CssParameter");
-                    var literal, attribute;
-                    for (var i=0; i<cssParameter.length; i++) {
-                        literal = this.getElementsByTagNameNS(cssParameter[i], this.ogcns, "Literal");
-                        attribute = cssParameter[i].getAttribute("name");
-                        // strokeColor
-                        if (attribute == "stroke") {
-                            style.strokeColor = OpenLayers.String.trim(
-                                    OpenLayers.Util.getXmlNodeValue(cssParameter[i]));
-                        } else
-                        // strokeOpacity
-                        if (attribute == "stroke-opacity") {
-                            style.strokeOpacity = parseFloat(OpenLayers.Util.getXmlNodeValue(cssParameter[i]));
-                        } else
-                        // strokeWidth
-                        if (attribute == "stroke-width") {
-                            style.strokeWidth = parseFloat(OpenLayers.Util.getXmlNodeValue(cssParameter[i]));
-                        } else
-                        // strokeLinecap
-                        if (attribute == "stroke-linecap") {
-                            style.strokeLinecap = OpenLayers.String.trim(
-                                    OpenLayers.Util.getXmlNodeValue(cssParameter[i]));
-                        }
-                    }
+                    style.strokeColor = this.parseProperty(stroke[0],
+                            this.sldns, "CssParameter", "name", "stroke");
+                    style.strokeOpacity = this.parseProperty(stroke[0],
+                            this.sldns, "CssParameter", "name",
+                            "stroke-opacity");
+                    style.strokeWidth = this.parseProperty(stroke[0],
+                            this.sldns, "CssParameter", "name",
+                            "stroke-width");
+                    style.strokeLinecap = this.parseProperty(stroke[0],
+                            this.sldns, "CssParameter", "name",
+                            "stroke-linecap");
                 }
                 
                 // set the [point|line|polygon]Symbolizer property of the rule
@@ -249,21 +228,16 @@
                xmlNode.nodeName.split(":")[1] :
                xmlNode.nodeName;
 
-        var appliesIf = "(";
-        
         // ogc:FeatureId filter
         var fidFilter = (nodeName == "FeatureId") ?
                 xmlNode :
                 this.getElementsByTagNameNS(xmlNode, this.ogcns, "FeatureId");
         if (fidFilter && fidFilter.length > 0) {
+            var rule = new OpenLayers.Rule.FeatureId();
             for (var i=0; i<fidFilter.length; i++) {
-                var fid = fidFilter[i].getAttribute("fid");
-                if (appliesIf != "(") {
-                    appliesIf += " || ";
-                }
-                appliesIf += "feature.fid == '" + fid + "'";
+                rule.fids.push(fidFilter[i].getAttribute("fid"));
             }
-            return appliesIf+")";
+            return rule;
         }
         
         // ogc:And filter
@@ -274,16 +248,15 @@
             andFilter = andFilter[0];
         }
         if (andFilter.childNodes && andFilter.parentNode == xmlNode) {
+            var rule = new OpenLayers.Rule.Logical(
+                    {type: OpenLayers.Rule.Logical.Type.AND});
             var filters = andFilter.childNodes; 
             for (var i=0; i<filters.length; i++) {
                 if (filters[i].nodeType == 1) {
-                    if (appliesIf != "(") {
-                        appliesIf += " && ";
-                    }
-                    appliesIf += this.parseFilter(filters[i]);
+                    rule.children.push(this.parseFilter(filters[i], rule));
                 }
             }
-            return appliesIf+")";
+            return rule;
         }
 
         // ogc:Or filter
@@ -294,16 +267,15 @@
             orFilter = orFilter[0];
         }
         if (orFilter.childNodes && orFilter.parentNode == xmlNode) {
+            var rule = new OpenLayers.Rule.Logical(
+                    {type: OpenLayers.Rule.Logical.Type.OR})
             var filters = orFilter.childNodes; 
             for (var i=0; i<filters.length; i++) {
                 if (filters[i].nodeType == 1) {
-                    if (appliesIf != "(") {
-                        appliesIf += " || ";
-                    }
-                    appliesIf += this.parseFilter(filters[i]);
+                    rule.children.push(this.parseFilter(filters[i], rule));
                 }
             }
-            return appliesIf+")";
+            return rule;
         }
 
         // ogc:Not filter
@@ -314,91 +286,147 @@
             notFilter = notFilter[0];
         }
         if (notFilter.childNodes && notFilter.parentNode == xmlNode) {
-            appliesIf += "!" + this.parseFilter(notFilter);
-            return appliesIf+")";
+            var rule = new OpenLayers.Rule.Logical(
+                    {type: OpenLayers.Rule.Logical.Type.NOT});
+            rule.children.push(this.parseFilter(notFilter, rule));
+            return rule;
         }
         
-        // ogc BinaryComparison filters
-        var binaryComparisonOps = {
-                'PropertyIsEqualTo': "==",
-                'PropertyIsNotEqualTo': "!=",
-                'PropertyIsLessThan': "<",
-                'PropertyIsGreaterThan': ">",
-                'PropertyIsLessThanOrEqualTo': "<=",
-                'PropertyIsGreaterThanOrEqualTo': ">="
-        };
-        for (var i in binaryComparisonOps) {
-            var binaryComparisonFilter = (nodeName == i) ?
+        // Comparison filters
+        for (var i in OpenLayers.Rule.Comparison.Type) {
+            // calculate the rule node name
+            var type = OpenLayers.String.camelize("-property-is-"+
+                    i.replace("_", "-").toLowerCase());
+            var comparisonFilter = (nodeName == type) ?
                     xmlNode :
-                    this.getElementsByTagNameNS(xmlNode, this.ogcns, i);
-            if (binaryComparisonFilter.length > 0) {
-                binaryComparisonFilter = binaryComparisonFilter[0];
+                    this.getElementsByTagNameNS(xmlNode, this.ogcns, type);
+            if (comparisonFilter.length > 0) {
+                comparisonFilter = comparisonFilter[0];
             }
-            if (binaryComparisonFilter.childNodes) {
-                appliesIf += this.parseComparison(binaryComparisonFilter, binaryComparisonOps[i]);
-                return appliesIf+")";
+            if (comparisonFilter.childNodes) {
+                var property = this.parseProperty(
+                        xmlNode, this.ogcns, "PropertyName");
+                var lowerBoundary = this.parseProperty(
+                        xmlNode, this.ogcns, "LowerBoundary");
+                if (lowerBoundary) {
+                    var upperBoundary = this.parseProperty(
+                            xmlNode, this.ogcns, "UpperBoundary");
+                    var rule = new OpenLayers.Rule.Comparison({
+                            type: OpenLayers.Rule.Comparison.Type.BETWEEN,
+                            lowerBoundary: lowerBoundary,
+                            upperBoundary: upperBoundary});
+                } else {
+                    var value = this.parseProperty(
+                            xmlNode, this.ogcns, "Literal");
+                    var rule = new OpenLayers.Rule.Comparison({
+                            type: OpenLayers.Rule.Comparison.Type[i],
+                            value: value});
+                }
+                rule.property = property;
+                return rule;
             }
         }
-        
-        // ogc:PropertyIsBetween
-        var propertyIsBetweenFilter = (nodeName == "PropertyIsBetween") ?
-                xmlNode :
-                this.getElementsByTagNameNS(xmlNode, this.ogcns, "PropertyIsBetween");
-        if (propertyIsBetweenFilter.length > 0) {
-            propertyIsBetweenFilter = propertyIsBetweenFilter[0];
-        }
-        if (propertyIsBetweenFilter.childNodes) {
-            var propertyName = OpenLayers.String.trim(OpenLayers.Util.getXmlNodeValue(
-                    this.getElementsByTagNameNS(propertyNameIsBetweenFilter, this.ogcns, "PropertyName")[0]));
-            var lowerBoundaryNode = this.getElementsByTagNameNS(
-                    propertyIsBetweenFilter, this.ogcns, "LowerBoundary");
-            var lowerBoundary = OpenLayers.String.trim(OpenLayers.Util.getXmlNodeValue(
-                    this.getElementsByTagNameNS(lowerBoundaryNode, this.ogcns, "Literal")[0]));
-            if (isNaN(lowerBoundary)) {
-                lowerBoundary = "'"+lowerBoundary+"'";
-            }
-            var upperBoundaryNode = this.getElementsByTagNameNS(
-                    propertyIsBetweenFilter, this.ogcns, "UpperBoundary");
-            var upperBoundary = OpenLayers.String.trim(OpenLayers.Util.getXmlNodeValue(
-                    this.getElementsByTagNameNS(upperBoundaryNode[0], this.ogcns, "Literal")[0]));
-            if (isNaN(upperBoundary)) {
-                upperBoundary = "'"+upperBoundary+"'";
-            }
-            appliesIf += "feature.attributes['"+propertyName+"']"+
-                    ">"+lowerBoundary+" && "+
-                    "feature.attributes['"+propertyName+"']"+
-                    "<"+upperBoundary;
-            
-            return appliesIf+")";
-        }
-        
-        return "";
     },
     
     /**
-     * Method: parseComparison
-     * Parses ogc comparisons and builds a JS boolean expression.
+     * Method: parseProperty
+     * Convenience method to parse the different kinds of properties
+     * found in the sld and ogc namespace.
+     * Parses an ogc node that can either contain a value directly,
+     * or inside a <Literal> property. The parsing can also be limited
+     * to nodes with certain attribute names and/or values
      *
      * Parameters:
-     * xmlNode - {<DOMElement>}
-     * insertBetween - {<String>} string to insert between property and literal
+     * xmlNode        - {<DOMElement>}
+     * namespace      - {String} namespace of the node to find
+     * propertyName   - {String} name of the property to parse
+     * attributeName  - {String} optional name of the property to match
+     * attributeValue - {String} optional value of the specified attribute
      * 
      * Returns:
-     * {String} JavaScript eval'able boolean snippet
+     * {String} The value for the requested property
      */    
-    parseComparison: function(xmlNode, insertBetween) {
-        var property = OpenLayers.String.trim(OpenLayers.Util.getXmlNodeValue(
-                this.getElementsByTagNameNS(xmlNode, this.ogcns, "PropertyName")[0]));
-        var literal = OpenLayers.String.trim(OpenLayers.Util.getXmlNodeValue(
-                this.getElementsByTagNameNS(xmlNode, this.ogcns, "Literal")[0]));
-        if (isNaN(literal)) {
-            literal = "'"+literal+"'";
+    parseProperty: function(xmlNode, namespace, propertyName, attributeName,
+                                                              attributeValue) {
+        var result = null;
+        var propertyNodeList = this.getElementsByTagNameNS(
+                xmlNode, namespace, propertyName);
+                
+        if (propertyNodeList && propertyNodeList.length > 0) {
+            var propertyNode = attributeName ?
+                    this.getNodeWithAttribute(propertyNodeList, 
+                            attributeName) :
+                    propertyNodeList[0];
+
+            // get the property value from the node matching attributeName
+            // and attributeValue
+            if (attributeName && attributeValue) {
+                propertyNode = this.getNodeWithAttribute(propertyNodeList,
+                        attributeName, attributeValue);
+                result = OpenLayers.Util.getXmlNodeValue(propertyNode);
+            }
+
+            // get the attribute value and use it as result
+            if (attributeName && !attributeValue) {
+                var propertyNode = this.getNodeWithAttribute(propertyNodeList,
+                        attributeName);
+                result = propertyNode.getAttribute(attributeName);                
+            }
+            
+            // get the property value from the textContent of the first node
+            if (!result) {
+                propertyNode = propertyNodeList[0];
+                result = OpenLayers.Util.getXmlNodeValue(propertyNode);
+            }
+            
+            // get the property value from an ogc:Literal at the level of
+            // the property node.
+            if (!result) {
+                var result = this.parseProperty(
+                        propertyNode, this.ogcns, "Literal");
+            }
+            
+            // finally, get the property value from an ogc:Literal at the same
+            // level as the xmlNode
+            if (!result) {
+                var result = this.parseProperty(xmlNode, this.ogcns, "Literal");
+            }
         }
         
-        return "feature.attributes['"+property+"']"+
-                insertBetween+
-                literal;
+        // adjust the result to be a trimmed string or a number
+        if (result) {
+            result = OpenLayers.String.trim(result);
+            if (!isNaN(result)) {
+                result = parseFloat(result);
+            }
+        }
+        
+        return result;
     },
     
+    /**
+     * Method: getNodeWithAttribute
+     * Walks through a list of xml nodes and returns the fist node that has an
+     * attribute with the name and optional value specified.
+     * 
+     * Parameters:
+     * xmlNodeList    - {Array(<DOMElement>)} list to search
+     * attributeName  - {String} name of the attribute to match
+     * attributeValue - {String} optional value of the attribute
+     */
+    getNodeWithAttribute: function(xmlNodeList, attributeName, attributeValue) {
+        for (var i=0; i<xmlNodeList.length; i++) {
+            var currentAttributeValue =
+                    xmlNodeList[i].getAttribute(attributeName);
+            if (currentAttributeValue) {
+                if (!attributeValue) {
+                    return xmlNodeList[i];
+                } else if (currentAttributeValue == attributeValue) {
+                    return xmlNodeList[i];
+                }
+            }
+        }
+    },
+    
     CLASS_NAME: "OpenLayers.Format.SLD" 
 });
\ No newline at end of file

Added: sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule/Comparison.js
===================================================================
--- sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule/Comparison.js	                        (rev 0)
+++ sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule/Comparison.js	2007-10-02 03:06:16 UTC (rev 4746)
@@ -0,0 +1,145 @@
+/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license.
+ * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 
+ * for the full text of the license. */
+
+
+/**
+ * @requires: OpenLayers/Rule.js
+ *
+ * Class: OpenLayers.Rule.Comparison
+ * 
+ * This class represents the comparison rules, as being used for rule-based 
+ * SLD styling
+ * 
+ * Inherits from
+ * - <OpenLayers.Rule>
+ */
+OpenLayers.Rule.Comparison = OpenLayers.Class({
+
+    /**
+     * APIProperty: type
+     * {<OpenLayers.Rule.Logical.Type>} type: type of the comparison.
+     */
+    type: null,
+    
+    /**
+     * APIProperty: property
+     * {String}
+     * name of the feature attribute to compare
+     */
+    property: null,
+    
+    /**
+     * APIProperty: value
+     * {Number} or {String}
+     * comparison value for binary comparisons
+     */
+    value: null,
+    
+    /**
+     * APIProperty: lowerBoundary
+     * {Number} or {String}
+     * lower boundary for between comparisons
+     */
+    lowerBoundary: null,
+    
+    /**
+     * APIProperty: upperBoundary
+     * {Number} or {String}
+     * upper boundary for between comparisons
+     */
+    upperBoundary: null,
+
+    /** 
+     * Constructor: OpenLayers.Rule.Logical
+     * Creates a logical rule (And, Or, Not).
+     *
+     * Parameters:
+     * params  - {Object} Hash of parameters for this rule:
+     *              - 
+     *              - value: 
+     * options - {Object} An optional object with properties to set on the
+     *           rule
+     * 
+     * Returns:
+     * {<OpenLayers.Rule>}
+     */
+    initialize: function(options) {
+        OpenLayers.Rule.prototype.initialize.apply(
+                this, [options]);
+    },
+
+    /**
+     * APIMethod: evaluate
+     * evaluates this rule for a specific feature
+     * 
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} feature to apply the rule to.
+     * 
+     * Returns:
+     * {boolean} true if the rule applies, false if it does not
+     */
+    evaluate: function(feature) {
+        switch(this.type) {
+            case OpenLayers.Rule.Comparison.Type.EQUAL_TO:
+            case OpenLayers.Rule.Comparison.Type.LESS_THAN:
+            case OpenLayers.Rule.Comparison.Type.GREATER_THAN:
+            case OpenLayers.Rule.Comparison.Type.LESS_THAN_OR_EQUAL_TO:
+            case OpenLayers.Rule.Comparison.Type.GREATER_THAN_OR_EQUAL_TO:
+                return this.binaryCompare(feature, this.property, this.value);
+            
+            case OpenLayers.Rule.Comparison.Type.BETWEEN:
+                var result = false;
+                result = result &&
+                        feature.attributes[this.property] > this.lowerBoundary;
+                result = result &&
+                        feature.attributes[this.property] < this.upperBoundary;
+                return result;                
+        }
+    },
+    
+    /**
+     * Function: binaryCompare
+     * Compares a feature property to a rule value
+     * 
+     * Parameters:
+     * feature  - {<OpenLayers.Feature.Vector>}
+     * property - {String} or {Number}
+     * value    - {String} or {Number}, same as property
+     * 
+     * Returns:
+     * {boolean}
+     */
+    binaryCompare: function(feature, property, value) {
+        switch (this.type) {
+            case OpenLayers.Rule.Comparison.Type.EQUAL_TO:
+                return feature.attributes[property] == value;
+            case OpenLayers.Rule.Comparison.Type.NOT_EQUAL_TO:
+                return feature.attributes[property] != value;
+            case OpenLayers.Rule.Comparison.Type.LESS_THAN:
+                return feature.attributes[property] < value;
+            case OpenLayers.Rule.Comparison.Type.GREATER_THAN:
+                return feature.attributes[property] > value;
+            case OpenLayers.Rule.Comparison.Type.LESS_THAN_OR_EQUAL_TO:
+                return feature.attributes[property] <= value;
+            case OpenLayers.Rule.Comparison.Type.GREATER_THAN_OR_EQUAL_TO:
+                return feature.attributes[property] >= value;
+        }      
+    },
+    
+    CLASS_NAME: "OpenLayers.Rule.Comparison"
+});
+
+
+/**
+ * Constant:
+ * {Object} OpenLayers.Rule.Comparison.Type
+ */
+OpenLayers.Rule.Comparison.Type = {
+        'EQUAL_TO': 0,
+        'NOT_EQUAL_TO': 1,
+        'LESS_THAN': 2,
+        'GREATER_THAN': 3,
+        'LESS_THAN_OR_EQUAL_TO': 4,
+        'GREATER_THAN_OR_EQUAL_TO': 5,
+        'BETWEEN': 6};
\ No newline at end of file

Added: sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule/FeatureId.js
===================================================================
--- sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule/FeatureId.js	                        (rev 0)
+++ sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule/FeatureId.js	2007-10-02 03:06:16 UTC (rev 4746)
@@ -0,0 +1,63 @@
+/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license.
+ * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 
+ * for the full text of the license. */
+
+
+/**
+ * @requires: OpenLayers/Rule.js
+ *
+ * Class: OpenLayers.Rule
+ * 
+ * This class represents a ogc:FeatureId Rule, as being used for rule-based SLD
+ * styling
+ * 
+ * Inherits from
+ * - <OpenLayers.Rule>
+ */
+OpenLayers.Rule.FeatureId = OpenLayers.Class({
+
+    /** 
+     * APIProperty: fid 
+     * {Array(<String>)} Feature Ids to evaluate this rule against. To be passed
+     * To be passed inside the params object.
+     */
+    fids: null,
+    
+    /** 
+     * Constructor: OpenLayers.Rule.FeatureId
+     * Creates an ogc:FeatureId rule.
+     *
+     * Parameters:
+     * options - {Object} An optional object with properties to set on the
+     *           rule
+     * 
+     * Returns:
+     * {<OpenLayers.Rule>}
+     * 
+     * Inherits from:
+     *  - <OpenLayers.Rule>
+     */
+    initialize: function(options) {
+        this.fids = [];
+        OpenLayers.Rule.prototype.initialize.apply(
+                this, [options]);
+    },
+
+    /**
+     * APIMethod: evaluate
+     * evaluates this rule for a specific feature
+     * 
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} feature to apply the rule to.
+     */
+    evaluate: function(feature) {
+        for (var i=0; i<this.fids.length; i++) {
+            if (feature.fid == this.fids[i]) {
+                return true;
+            }
+        }
+        return false;
+    },
+    
+    CLASS_NAME: "OpenLayers.Rule.FeatureId"
+});
\ No newline at end of file

Added: sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule/Logical.js
===================================================================
--- sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule/Logical.js	                        (rev 0)
+++ sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule/Logical.js	2007-10-02 03:06:16 UTC (rev 4746)
@@ -0,0 +1,91 @@
+/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license.
+ * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 
+ * for the full text of the license. */
+
+
+/**
+ * @requires: OpenLayers/Rule.js
+ *
+ * Class: OpenLayers.Rule.Logical
+ * 
+ * This class represents ogc:And, ogc:Or and ogc:Not rules.
+ * 
+ * Inherits from
+ * - <OpenLayers.Rule>
+ */
+OpenLayers.Rule.Logical = OpenLayers.Class({
+
+    /**
+     * APIProperty: children
+     * {Array(<OpenLayers.Rule.Logical>)} child rules for this rule
+     */
+    children: null, 
+     
+    /**
+     * APIProperty: type
+     * {<OpenLayers.Rule.Logical.Type>} type of logical operator.
+     */
+    type: null,
+
+    /** 
+     * Constructor: OpenLayers.Rule.Logical
+     * Creates a logical rule (And, Or, Not).
+     *
+     * Parameters:
+     * options - {Object} An optional object with properties to set on the
+     *           rule
+     * 
+     * Returns:
+     * {<OpenLayers.Rule>}
+     */
+    initialize: function(options) {
+        this.children = [];
+        OpenLayers.Rule.prototype.initialize.apply(
+                this, [options]);
+    },
+
+    /**
+     * APIMethod: evaluate
+     * evaluates this rule for a specific feature
+     * 
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} feature to apply the rule to.
+     * 
+     * Returns:
+     * {boolean} true if the rule applies, false if it does not
+     */
+    evaluate: function(feature) {
+        switch(this.type) {
+            case OpenLayers.Rule.Logical.Type.AND:
+                for (var i=0; i<this.children.length; i++) {
+                    if (this.children[i].evaluate(feature) == false) {
+                        return false;
+                    }
+                }
+                return true;
+                
+            case OpenLayers.Rule.Logical.Type.OR:
+                for (var i=0; i<this.children.length; i++) {
+                    if (this.children[i].evaluate(feature) == true) {
+                        return true;
+                    }
+                }
+                return false;
+            
+            case OpenLayers.Rule.Logical.Type.NOT:
+                return (!this.children[0].evaluate(feature));
+        }
+    },
+    
+    CLASS_NAME: "OpenLayers.Rule.Logical"
+});
+
+
+/**
+ * Constant:
+ * {Object} OpenLayers.Rule.Logical.Type
+ */
+OpenLayers.Rule.Logical.Type = {
+        'AND': 0,
+        'OR': 1,
+        'NOT': 2};
\ No newline at end of file

Added: sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule.js
===================================================================
--- sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule.js	                        (rev 0)
+++ sandbox/ahocevar/sldRenderer/lib/OpenLayers/Rule.js	2007-10-02 03:06:16 UTC (rev 4746)
@@ -0,0 +1,83 @@
+/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license.
+ * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 
+ * for the full text of the license. */
+
+
+/**
+ * Class: OpenLayers.Rule
+ * 
+ * This class represents a OGC Rule, as being used for rule-based SLD styling
+ */
+OpenLayers.Rule = OpenLayers.Class({
+    
+    /**
+     * APIProperty: name
+     * {String} name of this rule
+     */
+    name: 'default',
+
+    /**
+     * Property: symbolizer
+     * {Object} Hash of styles for this rule. Contains hashes of feature
+     * styles. Keys are one or more of ["Point", "Line", "Polygon"]
+     */
+    symbolizer: null,
+    
+    /**
+     * APIProperty: minScaleDenominator
+     * {Number} minimum scale at which to draw the feature.
+     */
+    minScaleDenominator: null,
+
+    /**
+     * APIProperty: maxScaleDenominator
+     * {Number} maximum scale at which to draw the feature.
+     */
+    maxScaleDenominator: null,
+
+    /** 
+     * Constructor: OpenLayers.Rule
+     * Creates a Rule.
+     *
+     * Parameters:
+     * options - {Object} An optional object with properties to set on the
+     *           rule
+     * 
+     * Returns:
+     * {<OpenLayers.Rule>}
+     */
+    initialize: function(options) {
+        OpenLayers.Util.extend(this, options);
+        
+        this.symbolizer = {};
+    },
+
+    /** 
+     * APIMethod: destroy
+     * nullify references to prevent circular references and memory leaks
+     */
+    destroy: function() {
+        for (var i=0; i<children.length; i++) {
+            this.children[i].destroy();
+        }
+        this.children = null;
+    },
+    
+    /**
+     * APIMethod: evaluate
+     * evaluates this rule for a specific feature
+     * 
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} feature to apply the rule to.
+     * 
+     * Returns:
+     * {boolean} true if the rule applies, false if it does not.
+     * This rule is the default rule and always returns true.
+     */
+    evaluate: function(feature) {
+        // Default rule always applies. Subclasses will want to override this.
+        return true;
+    },
+    
+    CLASS_NAME: "OpenLayers.Rule"
+});
\ No newline at end of file

Modified: sandbox/ahocevar/sldRenderer/lib/OpenLayers/Style.js
===================================================================
--- sandbox/ahocevar/sldRenderer/lib/OpenLayers/Style.js	2007-10-02 02:55:22 UTC (rev 4745)
+++ sandbox/ahocevar/sldRenderer/lib/OpenLayers/Style.js	2007-10-02 03:06:16 UTC (rev 4746)
@@ -15,7 +15,7 @@
 
     /** 
      * APIProperty: rules 
-     * {Array(<OpenLayers.Format.SLD.Rule>} 
+     * {Array(<OpenLayers.Rule>} 
      */
     rules: null,
     
@@ -64,7 +64,7 @@
     },
 
     /** 
-     * Method: destroy
+     * APIMethod: destroy
      * nullify references to prevent circular references and memory leaks
      */
     destroy: function() {
@@ -75,6 +75,18 @@
         this.rules = null;
     },
     
+    /**
+     * APIMethod: createStyle
+     * creates a style by applying all feature-dependent rules to the base
+     * style.
+     * 
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>} feature to evaluate rules for
+     * baseStyle - {Object} hash of styles feature styles to extend
+     * 
+     * Returns:
+     * {<OpenLayers.Feature.Vector.Style>} hash of feature styles
+     */
     createStyle: function(feature, baseStyle) {
         if (!baseStyle) {
             baseStyle = this.defaultStyle;
@@ -84,7 +96,7 @@
         
         for (var i=0; i<this.rules.length; i++) {
             // does the rule apply?        
-            var applies = eval(this.rules[i].appliesIf);
+            var applies = this.rules[i].evaluate(feature);
             if (applies) {
                 // check if within minScale/maxScale bounds
                 var scale = feature.layer.map.getScale();

Modified: sandbox/ahocevar/sldRenderer/lib/OpenLayers.js
===================================================================
--- sandbox/ahocevar/sldRenderer/lib/OpenLayers.js	2007-10-02 02:55:22 UTC (rev 4745)
+++ sandbox/ahocevar/sldRenderer/lib/OpenLayers.js	2007-10-02 03:06:16 UTC (rev 4746)
@@ -167,6 +167,10 @@
             "OpenLayers/Layer/Vector.js",
             "OpenLayers/Layer/GML.js",
             "OpenLayers/Style.js",
+            "OpenLayers/Rule.js",
+            "OpenLayers/Rule/FeatureId.js",
+            "OpenLayers/Rule/Logical.js",
+            "OpenLayers/Rule/Comparison.js",
             "OpenLayers/Format.js",
             "OpenLayers/Format/XML.js",
             "OpenLayers/Format/GML.js",



More information about the Commits mailing list