More trip planner testing with colors
[busui.git] / labs / openlayers / lib / OpenLayers / Format / ArcXML.js
blob:a/labs/openlayers/lib/OpenLayers/Format/ArcXML.js -> blob:b/labs/openlayers/lib/OpenLayers/Format/ArcXML.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/Format/XML.js
  * @requires OpenLayers/Geometry/Polygon.js
  * @requires OpenLayers/Geometry/Point.js
  * @requires OpenLayers/Geometry/MultiPolygon.js
  * @requires OpenLayers/Geometry/LinearRing.js
  */
   
  /**
  * Class: OpenLayers.Format.ArcXML
  * Read/Wite ArcXML. Create a new instance with the <OpenLayers.Format.ArcXML>
  * constructor.
  *
  * Inherits from:
  * - <OpenLayers.Format>
  */
  OpenLayers.Format.ArcXML = OpenLayers.Class(OpenLayers.Format.XML, {
   
  /**
  * Property: fontStyleKeys
  * {Array} List of keys used in font styling.
  */
  fontStyleKeys: [
  'antialiasing', 'blockout', 'font', 'fontcolor','fontsize', 'fontstyle',
  'glowing', 'interval', 'outline', 'printmode', 'shadow', 'transparency'
  ],
   
  /**
  * Property: request
  * A get_image request destined for an ArcIMS server.
  */
  request: null,
   
  /**
  * Property: response
  * A parsed response from an ArcIMS server.
  */
  response: null,
   
  /**
  * Constructor: OpenLayers.Format.ArcXML
  * Create a new parser/writer for ArcXML. Create an instance of this class
  * to begin authoring a request to an ArcIMS service. This is used
  * primarily by the ArcIMS layer, but could be used to do other wild
  * stuff, like geocoding.
  *
  * Parameters:
  * options - {Object} An optional object whose properties will be set on
  * this instance.
  */
  initialize: function(options) {
  this.request = new OpenLayers.Format.ArcXML.Request();
  this.response = new OpenLayers.Format.ArcXML.Response();
   
  if (options) {
  if (options.requesttype == "feature") {
  this.request.get_image = null;
   
  var qry = this.request.get_feature.query;
  this.addCoordSys(qry.featurecoordsys, options.featureCoordSys);
  this.addCoordSys(qry.filtercoordsys, options.filterCoordSys);
   
  if (options.polygon) {
  qry.isspatial = true;
  qry.spatialfilter.polygon = options.polygon;
  } else if (options.envelope) {
  qry.isspatial = true;
  qry.spatialfilter.envelope = {minx:0, miny:0, maxx:0, maxy:0};
  this.parseEnvelope(qry.spatialfilter.envelope, options.envelope);
  }
  } else if (options.requesttype == "image") {
  this.request.get_feature = null;
   
  var props = this.request.get_image.properties;
  this.parseEnvelope(props.envelope, options.envelope);
   
  this.addLayers(props.layerlist, options.layers);
  this.addImageSize(props.imagesize, options.tileSize);
  this.addCoordSys(props.featurecoordsys, options.featureCoordSys);
  this.addCoordSys(props.filtercoordsys, options.filterCoordSys);
  } else {
  // if an arcxml object is being created with no request type, it is
  // probably going to consume a response, so do not throw an error if
  // the requesttype is not defined
  this.request = null;
  }
  }
   
  OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
  },
   
  /**
  * Method: parseEnvelope
  * Parse an array of coordinates into an ArcXML envelope structure.
  *
  * Parameters:
  * env - {Object} An envelope object that will contain the parsed coordinates.
  * arr - {Array(double)} An array of coordinates in the order: [ minx, miny, maxx, maxy ]
  */
  parseEnvelope: function(env, arr) {
  if (arr && arr.length == 4) {
  env.minx = arr[0];
  env.miny = arr[1];
  env.maxx = arr[2];
  env.maxy = arr[3];
  }
  },
   
  /**
  * Method: addLayers
  * Add a collection of layers to another collection of layers. Each layer in the list is tuple of
  * { id, visible }. These layer collections represent the
  * /ARCXML/REQUEST/get_image/PROPERTIES/LAYERLIST/LAYERDEF items in ArcXML
  *
  * TODO: Add support for dynamic layer rendering.
  *
  * Parameters:
  * ll - {Array({id,visible})} A list of layer definitions.
  * lyrs - {Array({id,visible})} A list of layer definitions.
  */
  addLayers: function(ll, lyrs) {
  for(var lind = 0, len=lyrs.length; lind < len; lind++) {
  ll.push(lyrs[lind]);
  }
  },
   
  /**
  * Method: addImageSize
  * Set the size of the requested image.
  *
  * Parameters:
  * imsize - {Object} An ArcXML imagesize object.
  * olsize - {OpenLayers.Size} The image size to set.
  */
  addImageSize: function(imsize, olsize) {
  if (olsize !== null) {
  imsize.width = olsize.w;
  imsize.height = olsize.h;
  imsize.printwidth = olsize.w;
  imsize.printheight = olsize.h;
  }
  },
   
  /**
  * Method: addCoordSys
  * Add the coordinate system information to an object. The object may be
  *
  * Parameters:
  * featOrFilt - {Object} A featurecoordsys or filtercoordsys ArcXML structure.
  * fsys - {String} or {OpenLayers.Projection} or {filtercoordsys} or
  * {featurecoordsys} A projection representation. If it's a {String},
  * the value is assumed to be the SRID. If it's a {OpenLayers.Projection}
  * AND Proj4js is available, the projection number and name are extracted
  * from there. If it's a filter or feature ArcXML structure, it is copied.
  */
  addCoordSys: function(featOrFilt, fsys) {
  if (typeof fsys == "string") {
  featOrFilt.id = parseInt(fsys);
  featOrFilt.string = fsys;
  }
  // is this a proj4js instance?
  else if (typeof fsys == "object" && fsys.proj !== null){
  featOrFilt.id = fsys.proj.srsProjNumber;
  featOrFilt.string = fsys.proj.srsCode;
  } else {
  featOrFilt = fsys;
  }
  },
   
  /**
  * APIMethod: iserror
  * Check to see if the response from the server was an error.
  *
  * Parameters:
  * data - {String} or {DOMElement} data to read/parse. If nothing is supplied,
  * the current response is examined.
  *
  * Returns:
  * {Boolean} true if the response was an error.
  */
  iserror: function(data) {
  var ret = null;
   
  if (!data) {
  ret = (this.response.error !== '');
  } else {
  data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
  var errorNodes = data.documentElement.getElementsByTagName("ERROR");
  ret = (errorNodes !== null && errorNodes.length > 0);
  }
   
  return ret;
  },
   
  /**
  * APIMethod: read
  * Read data from a string, and return an response.
  *
  * Parameters:
  * data - {String} or {DOMElement} data to read/parse.
  *
  * Returns:
  * {OpenLayers.Format.ArcXML.Response} An ArcXML response. Note that this response
  * data may change in the future.
  */
  read: function(data) {
  if(typeof data == "string") {
  data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
  }
   
  var arcNode = null;
  if (data && data.documentElement) {
  if(data.documentElement.nodeName == "ARCXML") {
  arcNode = data.documentElement;
  } else {
  arcNode = data.documentElement.getElementsByTagName("ARCXML")[0];
  }
  }
   
  // in Safari, arcNode will be there but will have a child named
  // parsererror
  if (!arcNode || arcNode.firstChild.nodeName === 'parsererror') {
  var error, source;
  try {
  error = data.firstChild.nodeValue;
  source = data.firstChild.childNodes[1].firstChild.nodeValue;
  } catch (err) {
  // pass
  }
  throw {
  message: "Error parsing the ArcXML request",
  error: error,
  source: source
  };
  }
   
  var response = this.parseResponse(arcNode);
  return response;
  },
   
  /**
  * APIMethod: write
  * Generate an ArcXml document string for sending to an ArcIMS server.
  *
  * Returns:
  * {String} A string representing the ArcXML document request.
  */
  write: function(request) {
  if (!request) {
  request = this.request;
  }
  var root = this.createElementNS("", "ARCXML");
  root.setAttribute("version","1.1");
   
  var reqElem = this.createElementNS("", "REQUEST");
   
  if (request.get_image != null) {
  var getElem = this.createElementNS("", "GET_IMAGE");
  reqElem.appendChild(getElem);
   
  var propElem = this.createElementNS("", "PROPERTIES");
  getElem.appendChild(propElem);
   
  var props = request.get_image.properties;
  if (props.featurecoordsys != null) {
  var feat = this.createElementNS("", "FEATURECOORDSYS");
  propElem.appendChild(feat);
   
  if (props.featurecoordsys.id === 0) {
  feat.setAttribute("string", props.featurecoordsys['string']);
  }
  else {
  feat.setAttribute("id", props.featurecoordsys.id);
  }
  }
   
  if (props.filtercoordsys != null) {
  var filt = this.createElementNS("", "FILTERCOORDSYS");
  propElem.appendChild(filt);
   
  if (props.filtercoordsys.id === 0) {
  filt.setAttribute("string", props.filtercoordsys.string);
  }
  else {
  filt.setAttribute("id", props.filtercoordsys.id);
  }
  }
   
  if (props.envelope != null) {
  var env = this.createElementNS("", "ENVELOPE");
  propElem.appendChild(env);
   
  env.setAttribute("minx", props.envelope.minx);
  env.setAttribute("miny", props.envelope.miny);
  env.setAttribute("maxx", props.envelope.maxx);
  env.setAttribute("maxy", props.envelope.maxy);
  }
   
  var imagesz = this.createElementNS("", "IMAGESIZE");
  propElem.appendChild(imagesz);
   
  imagesz.setAttribute("height", props.imagesize.height);
  imagesz.setAttribute("width", props.imagesize.width);
   
  if (props.imagesize.height != props.imagesize.printheight ||
  props.imagesize.width != props.imagesize.printwidth) {
  imagesz.setAttribute("printheight", props.imagesize.printheight);
  imagesz.setArrtibute("printwidth", props.imagesize.printwidth);
  }
   
  if (props.background != null) {
  var backgrnd = this.createElementNS("", "BACKGROUND");
  propElem.appendChild(backgrnd);
   
  backgrnd.setAttribute("color",
  props.background.color.r + "," +
  props.background.color.g + "," +
  props.background.color.b);
   
  if (props.background.transcolor !== null) {
  backgrnd.setAttribute("transcolor",
  props.background.transcolor.r + "," +
  props.background.transcolor.g + "," +
  props.background.transcolor.b);
  }
  }
   
  if (props.layerlist != null && props.layerlist.length > 0) {
  var layerlst = this.createElementNS("", "LAYERLIST");
  propElem.appendChild(layerlst);
   
  for (var ld = 0; ld < props.layerlist.length; ld++) {
  var ldef = this.createElementNS("", "LAYERDEF");
  layerlst.appendChild(ldef);
   
  ldef.setAttribute("id", props.layerlist[ld].id);
  ldef.setAttribute("visible", props.layerlist[ld].visible);
   
  if (typeof props.layerlist[ld].query == "object") {
  var query = props.layerlist[ld].query;
   
  if (query.where.length < 0) {
  continue;
  }
   
  var queryElem = null;
  if (typeof query.spatialfilter == "boolean" && query.spatialfilter) {
  // handle spatial filter madness
  queryElem = this.createElementNS("", "SPATIALQUERY");
  }
  else {
  queryElem = this.createElementNS("", "QUERY");
  }
   
  queryElem.setAttribute("where", query.where);
   
  if (typeof query.accuracy == "number" && query.accuracy > 0) {