More trip planner testing with colors
[busui.git] / labs / openlayers / lib / OpenLayers / Format / SLD / v1.js
blob:a/labs/openlayers/lib/OpenLayers/Format/SLD/v1.js -> blob:b/labs/openlayers/lib/OpenLayers/Format/SLD/v1.js
  /* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for
  * full list of contributors). Published under the Clear BSD license.
  * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
  * full text of the license. */
   
  /**
  * @requires OpenLayers/Rule.js
  * @requires OpenLayers/Format/SLD.js
  * @requires OpenLayers/Format/Filter/v1_0_0.js
  */
   
  /**
  * Class: OpenLayers.Format.SLD.v1
  * Superclass for SLD version 1 parsers.
  *
  * Inherits from:
  * - <OpenLayers.Format.Filter.v1_0_0>
  */
  OpenLayers.Format.SLD.v1 = OpenLayers.Class(OpenLayers.Format.Filter.v1_0_0, {
   
  /**
  * Property: namespaces
  * {Object} Mapping of namespace aliases to namespace URIs.
  */
  namespaces: {
  sld: "http://www.opengis.net/sld",
  ogc: "http://www.opengis.net/ogc",
  gml: "http://www.opengis.net/gml",
  xlink: "http://www.w3.org/1999/xlink",
  xsi: "http://www.w3.org/2001/XMLSchema-instance"
  },
   
  /**
  * Property: defaultPrefix
  */
  defaultPrefix: "sld",
   
  /**
  * Property: schemaLocation
  * {String} Schema location for a particular minor version.
  */
  schemaLocation: null,
   
  /**
  * APIProperty: multipleSymbolizers
  * {Boolean} Support multiple symbolizers per rule. Default is false. if
  * true, an OpenLayers.Style2 instance will be created to represent
  * user styles instead of an OpenLayers.Style instace. The
  * OpenLayers.Style2 class allows collections of rules with multiple
  * symbolizers, but is not currently useful for client side rendering.
  * If multiple symbolizers is true, multiple FeatureTypeStyle elements
  * are preserved in reading/writing by setting symbolizer zIndex values.
  * In addition, the <defaultSymbolizer> property is ignored if
  * multiple symbolizers are supported (defaults should be applied
  * when rendering).
  */
  multipleSymbolizers: false,
   
  /**
  * Property: featureTypeCounter
  * {Number} Private counter for multiple feature type styles.
  */
  featureTypeCounter: null,
   
  /**
  * APIProperty: defaultSymbolizer.
  * {Object} A symbolizer with the SLD defaults.
  */
  defaultSymbolizer: {
  fillColor: "#808080",
  fillOpacity: 1,
  strokeColor: "#000000",
  strokeOpacity: 1,
  strokeWidth: 1,
  strokeDashstyle: "solid",
  pointRadius: 3,
  graphicName: "square"
  },
   
  /**
  * Constructor: OpenLayers.Format.SLD.v1
  * Instances of this class are not created directly. Use the
  * <OpenLayers.Format.SLD> constructor instead.
  *
  * Parameters:
  * options - {Object} An optional object whose properties will be set on
  * this instance.
  */
  initialize: function(options) {
  OpenLayers.Format.Filter.v1_0_0.prototype.initialize.apply(this, [options]);
  },
   
  /**
  * Method: read
  *
  * Parameters:
  * data - {DOMElement} An SLD document element.
  * options - {Object} Options for the reader.
  *
  * Valid options:
  * namedLayersAsArray - {Boolean} Generate a namedLayers array. If false,
  * the namedLayers property value will be an object keyed by layer name.
  * Default is false.
  *
  * Returns:
  * {Object} An object representing the SLD.
  */
  read: function(data, options) {
  options = OpenLayers.Util.applyDefaults(options, this.options);
  var sld = {
  namedLayers: options.namedLayersAsArray === true ? [] : {}
  };
  this.readChildNodes(data, sld);
  return sld;
  },
   
  /**
  * Property: readers
  * Contains public functions, grouped by namespace prefix, that will
  * be applied when a namespaced node is found matching the function
  * name. The function will be applied in the scope of this parser
  * with two arguments: the node being read and a context object passed
  * from the parent.
  */
  readers: OpenLayers.Util.applyDefaults({
  "sld": {
  "StyledLayerDescriptor": function(node, sld) {
  sld.version = node.getAttribute("version");
  this.readChildNodes(node, sld);
  },
  "Name": function(node, obj) {
  obj.name = this.getChildValue(node);
  },
  "Title": function(node, obj) {
  obj.title = this.getChildValue(node);
  },
  "Abstract": function(node, obj) {
  obj.description = this.getChildValue(node);
  },
  "NamedLayer": function(node, sld) {
  var layer = {
  userStyles: [],
  namedStyles: []
  };
  this.readChildNodes(node, layer);
  // give each of the user styles this layer name
  for(var i=0, len=layer.userStyles.length; i<len; ++i) {
  layer.userStyles[i].layerName = layer.name;
  }
  if(sld.namedLayers instanceof Array) {
  sld.namedLayers.push(layer);
  } else {
  sld.namedLayers[layer.name] = layer;
  }
  },
  "NamedStyle": function(node, layer) {
  layer.namedStyles.push(
  this.getChildName(node.firstChild)
  );
  },
  "UserStyle": function(node, layer) {
  var obj = {defaultsPerSymbolizer: true, rules: []};
  this.featureTypeCounter = -1;
  this.readChildNodes(node, obj);
  var style;
  if (this.multipleSymbolizers) {
  delete obj.defaultsPerSymbolizer;
  style = new OpenLayers.Style2(obj);
  } else {
  style = new OpenLayers.Style(this.defaultSymbolizer, obj);
  }
  layer.userStyles.push(style);
  },
  "IsDefault": function(node, style) {
  if(this.getChildValue(node) == "1") {
  style.isDefault = true;
  }
  },
  "FeatureTypeStyle": function(node, style) {
  ++this.featureTypeCounter;
  var obj = {
  rules: this.multipleSymbolizers ? style.rules : []
  };
  this.readChildNodes(node, obj);
  if (!this.multipleSymbolizers) {
  style.rules = obj.rules;
  }
  },
  "Rule": function(node, obj) {
  var config;
  if (this.multipleSymbolizers) {
  config = {symbolizers: []};
  }
  var rule = new OpenLayers.Rule(config);
  this.readChildNodes(node, rule);
  obj.rules.push(rule);
  },
  "ElseFilter": function(node, rule) {
  rule.elseFilter = true;
  },
  "MinScaleDenominator": function(node, rule) {
  rule.minScaleDenominator = parseFloat(this.getChildValue(node));
  },
  "MaxScaleDenominator": function(node, rule) {
  rule.maxScaleDenominator = parseFloat(this.getChildValue(node));
  },
  "TextSymbolizer": function(node, rule) {
  var config = {};
  this.readChildNodes(node, config);
  if (this.multipleSymbolizers) {
  config.zIndex = this.featureTypeCounter;
  rule.symbolizers.push(
  new OpenLayers.Symbolizer.Text(config)
  );
  } else {
  rule.symbolizer["Text"] = OpenLayers.Util.applyDefaults(
  config, rule.symbolizer["Text"]
  );
  }
  },
  "Label": function(node, symbolizer) {
  // only supporting literal or property name
  var obj = {};
  this.readChildNodes(node, obj);
  if(obj.property) {
  symbolizer.label = "${" + obj.property + "}";
  } else {
  var value = this.readOgcExpression(node);
  if(value) {
  symbolizer.label = value;
  }
  }
  },
  "Font": function(node, symbolizer) {
  this.readChildNodes(node, symbolizer);
  },
  "Halo": function(node, symbolizer) {
  // halo has a fill, so send fresh object
  var obj = {};
  this.readChildNodes(node, obj);
  symbolizer.haloRadius = obj.haloRadius;
  symbolizer.haloColor = obj.fillColor;
  symbolizer.haloOpacity = obj.fillOpacity;
  },
  "Radius": function(node, symbolizer) {
  var radius = this.readOgcExpression(node);
  if(radius != null) {
  // radius is only used for halo
  symbolizer.haloRadius = radius;
  }
  },
  "RasterSymbolizer": function(node, rule) {
  var config = {};
  this.readChildNodes(node, config);
  if (this.multipleSymbolizers) {
  config.zIndex = this.featureTypeCounter;
  rule.symbolizers.push(
  new OpenLayers.Symbolizer.Raster(config)
  );
  } else {
  rule.symbolizer["Raster"] = OpenLayers.Util.applyDefaults(
  config, rule.symbolizer["Raster"]
  );
  }
  },
  "Geometry": function(node, obj) {
  obj.geometry = {};
  this.readChildNodes(node, obj.geometry);
  },
  "ColorMap": function(node, symbolizer) {
  symbolizer.colorMap = [];
  this.readChildNodes(node, symbolizer.colorMap);
  },
  "ColorMapEntry": function(node, colorMap) {
  var q = node.getAttribute("quantity");
  var o = node.getAttribute("opacity");
  colorMap.push({
  color: node.getAttribute("color"),
  quantity: q !== null ? parseFloat(q) : undefined,
  label: node.getAttribute("label") || undefined,
  opacity: o !== null ? parseFloat(o) : undefined
  });
  },
  "LineSymbolizer": function(node, rule) {
  var config = {};
  this.readChildNodes(node, config);
  if (this.multipleSymbolizers) {
  config.zIndex = this.featureTypeCounter;
  rule.symbolizers.push(
  new OpenLayers.Symbolizer.Line(config)
  );
  } else {
  rule.symbolizer["Line"] = OpenLayers.Util.applyDefaults(
  config, rule.symbolizer["Line"]
  );
  }
  },
  "PolygonSymbolizer": function(node, rule) {
  var config = {
  fill: false,
  stroke: false
  };
  if (!this.multipleSymbolizers) {
  config = rule.symbolizer["Polygon"] || config;
  }
  this.readChildNodes(node, config);
  if (this.multipleSymbolizers) {
  config.zIndex = this.featureTypeCounter;
  rule.symbolizers.push(
  new OpenLayers.Symbolizer.Polygon(config)
  );
  } else {
  rule.symbolizer["Polygon"] = config;
  }
  },
  "PointSymbolizer": function(node, rule) {
  var config = {
  fill: false,
  stroke: false,
  graphic: false
  };
  if (!this.multipleSymbolizers) {
  config = rule.symbolizer["Point"] || config;
  }
  this.readChildNodes(node, config);
  if (this.multipleSymbolizers) {
  config.zIndex = this.featureTypeCounter;
  rule.symbolizers.push(
  new OpenLayers.Symbolizer.Point(config)
  );
  } else {
  rule.symbolizer["Point"] = config;
  }
  },
  "Stroke": function(node, symbolizer) {
  symbolizer.stroke = true;
  this.readChildNodes(node, symbolizer);
  },
  "Fill": function(node, symbolizer) {
  symbolizer.fill = true;
  this.readChildNodes(node, symbolizer);
  },
  "CssParameter": function(node, symbolizer) {
  var cssProperty = node.getAttribute("name");
  var symProperty = this.cssMap[cssProperty];
  if(symProperty) {
  // Limited support for parsing of OGC expressions
  var value = this.readOgcExpression(node);
  // always string, could be an empty string
  if(value) {
  symbolizer[symProperty] = value;
  }
  }
  },
  "Graphic": function(node, symbolizer) {
  symbolizer.graphic = true;
  var graphic = {};
  // painter's order not respected here, clobber previous with next
  this.readChildNodes(node, graphic);