Add support for ArcIMS/ArcXML to OpenLayers.

Thanks for the killer effort from David Zwarg from Avencia in building this, 
and for Tim Schaub from OpenGeo for his excellent review. r=me,tschaub
(Closes #213)


git-svn-id: http://svn.openlayers.org/trunk/openlayers@9249 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
crschmidt
2009-04-09 00:15:48 +00:00
parent 08077f0f42
commit 2b7e8f5198
12 changed files with 2120 additions and 7 deletions

View File

@@ -0,0 +1,77 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>ArcIMS Thematic Example</title>
<link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
<link rel="stylesheet" href="style.css" type="text/css" />
<script src="../lib/OpenLayers.js"></script>
<script type="text/javascript">
var lon = 0;
var lat = 0;
var zoom = 1;
var map, layer;
var query, renderer;
function init() {
OpenLayers.ProxyHost = "proxy.cgi?url=";
map = new OpenLayers.Map('map');
query = {where: "FIPS_ID>100 AND FIPS_ID<200"};
renderer = {
type: 'valuemap',
lookupfield: 'FIPS_ID',
ranges: [
{ lower: 100, upper: 120, symbol: { type: 'simplepolygon', fillcolor: '255,0,0' } },
{ lower: 120, upper: 140, symbol: { type: 'simplepolygon', fillcolor: '255,255,0' } },
{ lower: 140, upper: 160, symbol: { type: 'simplepolygon', fillcolor: '0,255,0' } },
{ lower: 160, upper: 180, symbol: { type: 'simplepolygon', fillcolor: '0,255,255' } },
{ lower: 180, upper: 200, symbol: { type: 'simplepolygon', fillcolor: '0,0,255' } }
]
};
var options = {
layers: [{
id: "1",
visible: true,
query: query,
renderer: renderer
}],
serviceName: "OpenLayers_Sample",
singleTile: true,
async: true
};
layer = new OpenLayers.Layer.ArcIMS(
"Global Sample Map",
"http://sample.avencia.com/servlet/com.esri.esrimap.Esrimap",
options
);
map.addLayer(layer);
map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
map.addControl(new OpenLayers.Control.LayerSwitcher());
}
</script>
</head>
<body onload="init()">
<h1 id="title">ArcIMS Thematic Example</h1>
<div id="tags">
</div>
<p id="shortdesc">
Shows the advanced use of OpenLayers using a thematic ArcIMS layer
</p>
<div id="map" class="smallmap"></div>
<div id="docs">
<p>This is an example of how to add an ArcIMS layer to an OpenLayers map.</p>
<p>Following the ArcXML convention to create a thematic (or chloropleth) map,
a layer definition is created with a query and a renderer to select portions
of the map data, and change their representation in the generated map tiles.</p>
</div>
</body>
</html>

52
examples/arcims.html Normal file
View File

@@ -0,0 +1,52 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>ArcIMS Example</title>
<link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
<link rel="stylesheet" href="style.css" type="text/css" />
<script src="../lib/OpenLayers.js"></script>
<script type="text/javascript">
var lon = 0;
var lat = 0;
var zoom = 1;
var map, layer;
function init(){
OpenLayers.ProxyHost = "proxy.cgi?url=";
map = new OpenLayers.Map( 'map' );
var options = {
serviceName: "OpenLayers_Sample",
async: true
};
layer = new OpenLayers.Layer.ArcIMS( "Global Sample Map",
"http://sample.avencia.com/servlet/com.esri.esrimap.Esrimap", options );
map.addLayer(layer);
map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
map.addControl( new OpenLayers.Control.LayerSwitcher() );
}
</script>
</head>
<body onload="init()">
<h1 id="title">ArcIMS Example</h1>
<div id="tags">
</div>
<p id="shortdesc">
Shows the basic use of OpenLayers using an ArcIMS layer
</p>
<div id="map" class="smallmap"></div>
<div id="docs">
This is an example of how to add an ArcIMS layer to the OpenLayers window.
</div>
</body>
</html>

View File

@@ -19,7 +19,7 @@ allowedHosts = ['www.openlayers.org', 'openlayers.org',
'labs.metacarta.com', 'world.freemap.in',
'prototype.openmnnd.org', 'geo.openplans.org',
'sigma.openplans.org', 'demo.opengeo.org',
'www.openstreetmap.org']
'www.openstreetmap.org', 'sample.avencia.com']
method = os.environ["REQUEST_METHOD"]

View File

@@ -113,6 +113,7 @@
"OpenLayers/Layer/ArcGIS93Rest.js",
"OpenLayers/Layer/WMS.js",
"OpenLayers/Layer/WMS/Untiled.js",
"OpenLayers/Layer/ArcIMS.js",
"OpenLayers/Layer/GeoRSS.js",
"OpenLayers/Layer/Boxes.js",
"OpenLayers/Layer/XYZ.js",
@@ -211,6 +212,8 @@
"OpenLayers/Filter/Spatial.js",
"OpenLayers/Format.js",
"OpenLayers/Format/XML.js",
"OpenLayers/Format/ArcXML.js",
"OpenLayers/Format/ArcXML/Features.js",
"OpenLayers/Format/GML.js",
"OpenLayers/Format/GML/Base.js",
"OpenLayers/Format/GML/v2.js",

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,48 @@
/* Copyright (c) 2009 MetaCarta, Inc., 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/ArcXML.js
*/
/**
* Class: OpenLayers.Format.ArcXML.Features
* Read/Wite ArcXML features. Create a new instance with the
* <OpenLayers.Format.ArcXML.Features> constructor.
*
* Inherits from:
* - <OpenLayers.Format.XML>
*/
OpenLayers.Format.ArcXML.Features = OpenLayers.Class(OpenLayers.Format.XML, {
/**
* Constructor: OpenLayers.Format.ArcXML.Features
* Create a new parser/writer for ArcXML Features. Create an instance of this class
* to get a set of features from an ArcXML response.
*
* Parameters:
* options - {Object} An optional object whose properties will be set on
* this instance.
*/
initialize: function(options) {
OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
},
/**
* APIMethod: read
* Read data from a string of ArcXML, and return a set of OpenLayers features.
*
* Parameters:
* data - {String} or {DOMElement} data to read/parse.
*
* Returns:
* {Array(<OpenLayers.Feature.Vector>)} A collection of features.
*/
read: function(data) {
var axl = new OpenLayers.Format.ArcXML();
var parsed = axl.read(data);
return parsed.features.feature;
}
});

View File

@@ -0,0 +1,442 @@
/* Copyright (c) 2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Layer/Grid.js
* @requires OpenLayers/Tile/Image.js
* @requires OpenLayers/Format/ArcXML.js
* @requires OpenLayers/Request.js
*/
/**
* Class: OpenLayers.Layer.ArcIMS
* Instances of OpenLayers.Layer.ArcIMS are used to display data from ESRI ArcIMS
* Mapping Services. Create a new ArcIMS layer with the <OpenLayers.Layer.ArcIMS>
* constructor.
*
* Inherits from:
* - <OpenLayers.Layer.Grid>
*/
OpenLayers.Layer.ArcIMS = OpenLayers.Class(OpenLayers.Layer.Grid, {
/**
* Constant: DEFAULT_PARAMS
* {Object} Default query string parameters.
*/
DEFAULT_PARAMS: {
ClientVersion: "9.2",
ServiceName: ''
},
/**
* APIProperty: tileSize
* {<OpenLayers.Size>} Size for tiles. Default is 512x512.
*/
tileSize: null,
/**
* APIProperty: featureCoordSys
* {String} Code for feature coordinate system. Default is "4326".
*/
featureCoordSys: "4326",
/**
* APIProperty: filterCoordSys
* {String} Code for filter coordinate system. Default is "4326".
*/
filterCoordSys: "4326",
/**
* APIProperty: layers
* {Array} An array of objects with layer properties.
*/
layers: null,
/**
* APIProperty: async
* {Boolean} Request images asynchronously. Default is true.
*/
async: true,
/**
* APIProperty: name
* {String} Layer name. Default is "ArcIMS".
*/
name: "ArcIMS",
/**
* APIProperty: isBaseLayer
* {Boolean} The layer is a base layer. Default is true.
*/
isBaseLayer: true,
/**
* Constant: DEFAULT_OPTIONS
* {Object} Default layers properties.
*/
DEFAULT_OPTIONS: {
tileSize: new OpenLayers.Size(512, 512),
featureCoordSys: "4326",
filterCoordSys: "4326",
layers: null,
isBaseLayer: true,
async: true,
name: "ArcIMS"
},
/**
* Constructor: OpenLayers.Layer.ArcIMS
* Create a new ArcIMS layer object.
*
* Example:
* (code)
* var arcims = new OpenLayers.Layer.ArcIMS(
* "Global Sample",
* "http://sample.avencia.com/servlet/com.esri.esrimap.Esrimap",
* {
* service: "OpenLayers_Sample",
* layers: [
* // layers to manipulate
* {id: "1", visible: true}
* ]
* }
* );
* (end)
*
* Parameters:
* name - {String} A name for the layer
* url - {String} Base url for the ArcIMS server
* options - {Object} Optional object with properties to be set on the
* layer.
*/
initialize: function(name, url, options) {
this.tileSize = new OpenLayers.Size(512, 512);
// parameters
this.params = OpenLayers.Util.applyDefaults(
{ServiceName: options.serviceName},
this.DEFAULT_PARAMS
);
this.options = OpenLayers.Util.applyDefaults(
options, this.DEFAULT_OPTIONS
);
OpenLayers.Layer.Grid.prototype.initialize.apply(
this, [name, url, this.params, options]
);
//layer is transparent
if (this.transparent) {
// unless explicitly set in options, make layer an overlay
if (!this.isBaseLayer) {
this.isBaseLayer = false;
}
// jpegs can never be transparent, so intelligently switch the
// format, depending on the browser's capabilities
if (this.format == "image/jpeg") {
this.format = OpenLayers.Util.alphaHack() ? "image/gif" : "image/png";
}
}
// create an empty layer list if no layers specified in the options
if (this.options.layers === null) {
this.options.layers = [];
}
},
/**
* Method: destroy
* Destroy this layer
*/
destroy: function() {
// for now, nothing special to do here.
OpenLayers.Layer.Grid.prototype.destroy.apply(this, arguments);
},
/**
* Method: getURL
* Return an image url this layer.
*
* Parameters:
* bounds - {<OpenLayers.Bounds>} A bounds representing the bbox for the
* request.
*
* Returns:
* {String} A string with the map image's url.
*/
getURL: function(bounds) {
var url = "";
bounds = this.adjustBounds(bounds);
// create an arcxml request to generate the image
var axlReq = new OpenLayers.Format.ArcXML(
OpenLayers.Util.extend(this.options, {
requesttype: "image",
envelope: bounds.toArray(),
tileSize: this.tileSize
})
);
// create a synchronous ajax request to get an arcims image
var req = new OpenLayers.Request.POST({
url: this.getFullRequestString(),
data: axlReq.write(),
async: false
});
// if the response exists
if (req != null) {
var doc = req.responseXML;
if (!doc || !doc.documentElement) {
doc = req.responseText;
}
// create a new arcxml format to read the response
var axlResp = new OpenLayers.Format.ArcXML();
var arcxml = axlResp.read(doc);
url = this.getUrlOrImage(arcxml.image.output);
}
return url;
},
/**
* Method: getURLasync
* Get an image url this layer asynchronously, and execute a callback
* when the image url is generated.
*
* Parameters:
* bounds - {<OpenLayers.Bounds>} A bounds representing the bbox for the
* request.
* scope - {Object} The scope of the callback method.
* prop - {String} The name of the property in the scoped object to
* recieve the image url.
* callback - {Function} Function to call when image url is retrieved.
*/
getURLasync: function(bounds, scope, prop, callback) {
bounds = this.adjustBounds(bounds);
// create an arcxml request to generate the image
var axlReq = new OpenLayers.Format.ArcXML(
OpenLayers.Util.extend(this.options, {
requesttype: "image",
envelope: bounds.toArray(),
tileSize: this.tileSize
})
);
// create an asynchronous ajax request to get an arcims image
OpenLayers.Request.POST({
url: this.getFullRequestString(),
async: true,
data: axlReq.write(),
callback: function(req) {
// process the response from ArcIMS, and call the callback function
// to set the image URL
var doc = req.responseXML;
if (!doc || !doc.documentElement) {
doc = req.responseText;
}
// create a new arcxml format to read the response
var axlResp = new OpenLayers.Format.ArcXML();
var arcxml = axlResp.read(doc);
scope[prop] = this.getUrlOrImage(arcxml.image.output);
// call the callback function to recieve the updated property on the
// scoped object
callback.apply(scope);
},
scope: this
});
},
/**
* Method: getUrlOrImage
* Extract a url or image from the ArcXML image output.
*
* Parameters:
* output - {Object} The image.output property of the object returned from
* the ArcXML format read method.
*
* Returns:
* {String} A URL for an image (potentially with the data protocol).
*/
getUrlOrImage: function(output) {
var ret = "";
if(output.url) {
// If the image response output url is a string, then the image
// data is not inline.
ret = output.url;
} else if(output.data) {
// The image data is inline and base64 encoded, create a data
// url for the image. This will only work for small images,
// due to browser url length limits.
ret = "data:image/" + output.type +
";base64," + output.data;
}
return ret;
},
/**
* Method: setLayerQuery
* Set the query definition on this layer. Query definitions are used to
* render parts of the spatial data in an image, and can be used to
* filter features or layers in the ArcIMS service.
*
* Parameters:
* id - {String} The ArcIMS layer ID.
* queryDef - {Object} The query definition to apply to this layer.
*/
setLayerQuery: function(id, querydef) {
// find the matching layer, if it exists
for (var lyr = 0; lyr < this.options.layers.length; lyr++) {
if (id == this.options.layers[lyr].id) {
// replace this layer definition
this.options.layers[lyr].query = querydef;
return;
}
}
// no layer found, create a new definition
this.options.layers.push({id: id, visible: true, query: querydef});
},
/**
* Method: getFeatureInfo
* Get feature information from ArcIMS. Using the applied geometry, apply
* the options to the query (buffer, area/envelope intersection), and
* query the ArcIMS service.
*
* A note about accuracy:
* ArcIMS interprets the accuracy attribute in feature requests to be
* something like the 'modulus' operator on feature coordinates,
* applied to the database geometry of the feature. It doesn't round,
* so your feature coordinates may be up to (1 x accuracy) offset from
* the actual feature coordinates. If the accuracy of the layer is not
* specified, the accuracy will be computed to be approximately 1
* feature coordinate per screen pixel.
*
* Parameters:
* geometry - {<OpenLayers.LonLat>} or {<OpenLayers.Geometry.Polygon>} The
* geometry to use when making the query. This should be a closed
* polygon for behavior approximating a free selection.
* layer - {Object} The ArcIMS layer definition. This is an anonymous object
* that looks like:
* (code)
* {
* id: "ArcXML layer ID", // the ArcXML layer ID
* query: {
* where: "STATE = 'PA'", // the where clause of the query
* accuracy: 100 // the accuracy of the returned feature
* }
* }
* (end)
* options - {Object} Object with non-default properties to set on the layer.
* Supported properties are buffer, callback, scope, and any other
* properties applicable to the ArcXML format. Set the 'callback' and
* 'scope' for an object and function to recieve the parsed features
* from ArcIMS.
*/
getFeatureInfo: function(geometry, layer, options) {
// set the buffer to 1 unit (dd/m/ft?) by default
var buffer = options.buffer || 1;
// empty callback by default
var callback = options.callback || function() {};
// default scope is window (global)
var scope = options.scope || window;
// apply these option to the request options
var requestOptions = {};
OpenLayers.Util.extend(requestOptions, this.options);
// this is a feature request
requestOptions.requesttype = "feature";
if (geometry instanceof OpenLayers.LonLat) {
// create an envelope if the geometry is really a lon/lat
requestOptions.polygon = null;
requestOptions.envelope = [
geometry.lon - buffer,
geometry.lat - buffer,
geometry.lon + buffer,
geometry.lat + buffer
];
} else if (geometry instanceof OpenLayers.Geometry.Polygon) {
// use the polygon assigned, and empty the envelope
requestOptions.envelope = null;
requestOptions.polygon = geometry;
}
// create an arcxml request to get feature requests
var arcxml = new OpenLayers.Format.ArcXML(requestOptions);
// apply any get feature options to the arcxml request
OpenLayers.Util.extend(arcxml.request.get_feature, options);
arcxml.request.get_feature.layer = layer.id;
if (typeof layer.query.accuracy == "number") {
// set the accuracy if it was specified
arcxml.request.get_feature.query.accuracy = layer.query.accuracy;
} else {
// guess that the accuracy is 1 per screen pixel
var mapCenter = this.map.getCenter();
var viewPx = this.map.getViewPortPxFromLonLat(mapCenter);
viewPx.x++;
var mapOffCenter = this.map.getLonLatFromPixel(viewPx);
arcxml.request.get_feature.query.accuracy = mapOffCenter.lon - mapCenter.lon;
}
// set the get_feature query to be the same as the layer passed in
arcxml.request.get_feature.query.where = layer.query.where;
// use area_intersection
arcxml.request.get_feature.query.spatialfilter.relation = "area_intersection";
// create a new asynchronous request to get the feature info
OpenLayers.Request.POST({
url: this.getFullRequestString({'CustomService': 'Query'}),
data: arcxml.write(),
callback: function(request) {
// parse the arcxml response
var response = arcxml.parseResponse(request.responseText);
if (!arcxml.iserror()) {
// if the arcxml is not an error, call the callback with the features parsed
callback.call(scope, arcxml.features);
} else {
// if the arcxml is an error, return null features selected
callback.call(scope, null);
}
}
});
},
/**
* Method: addTile
* addTile creates a tile, initializes it, and adds it to the layer div.
*
* Parameters:
* bounds - {<OpenLayers.Bounds>}
* position - {<OpenLayers.Pixel>}
*
* Returns:
* {<OpenLayers.Tile.Image>} The added image tile.
*/
addTile:function(bounds,position) {
return new OpenLayers.Tile.Image(
this, position, bounds, null, this.tileSize
);
},
CLASS_NAME: "OpenLayers.Layer.ArcIMS"
});

View File

@@ -284,15 +284,44 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, {
this.imgDiv.viewRequestID = this.layer.map.viewRequestID;
// needed for changing to a different serve for onload error
if (this.layer.url instanceof Array) {
this.imgDiv.urls = this.layer.url.slice();
}
if (this.layer.async) {
// Asyncronous image requests call the asynchronous getURL method
// on the layer to fetch an image that covers 'this.bounds', in the scope of
// 'this', setting the 'url' property of the layer itself, and running
// the callback 'positionFrame' when the image request returns.
this.layer.getURLasync(this.bounds, this, "url", this.positionImage);
} else {
// syncronous image requests get the url and position the frame immediately,
// and don't wait for an image request to come back.
// needed for changing to a different server for onload error
if (this.layer.url instanceof Array) {
this.imgDiv.urls = this.layer.url.slice();
}
this.url = this.layer.getURL(this.bounds);
// position the frame immediately
this.positionImage();
}
return true;
},
/**
* Method: positionImage
* Using the properties currenty set on the layer, position the tile correctly.
* This method is used both by the async and non-async versions of the Tile.Image
* code.
*/
positionImage: function() {
// if the this layer doesn't exist at the point the image is
// returned, do not attempt to use it for size computation
if ( this.layer == null )
return;
this.url = this.layer.getURL(this.bounds);
// position the frame
OpenLayers.Util.modifyDOMElement(this.frame,
null, this.position, this.size);
null, this.position, this.size);
if (this.layerAlphaHack) {
OpenLayers.Util.modifyAlphaImageDiv(this.imgDiv,
@@ -302,7 +331,6 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, {
null, null, this.size) ;
this.imgDiv.src = this.url;
}
return true;
},
/**

277
tests/Format/ArcXML.html Normal file
View File

@@ -0,0 +1,277 @@
<html>
<head>
<script src="../../lib/OpenLayers.js"></script>
<script type="text/javascript">
var axl_image_response = '<?xml version="1.0" encoding="UTF-8"?><ARCXML version="1.1"><RESPONSE><IMAGE><ENVELOPE minx="-2471.42857142857" miny="0" maxx="105671.428571429" maxy="75700" /><OUTPUT url="http://localhost/output/364826560.png" /></IMAGE></RESPONSE></ARCXML>';
var axl_feature_response = '<?xml version="1.0" encoding="Cp1252"?><ARCXML version="1.1"><RESPONSE><FEATURES><FEATURE><FIELDS><FIELD name="UNIQUE_ID" value="514504b5-0458-461d-b540-8e18a454f619" /><FIELD name="LABEL" value="LIBRARY" /><FIELD name="Y_COORD" value="39.57" /><FIELD name="X_COORD" value="-104.24" /><FIELD name="#SHAPE#" value="[Geometry]" /><FIELD name="OBJECTID" value="1" /><FIELD name="shape.area" value="0" /><FIELD name="shape.len" value="0" /></FIELDS></FEATURE><FEATURE><FIELDS><FIELD name="UNIQUE_ID" value="514504b5-0458-461d-b540-8e81a454f619" /><FIELD name="LABEL" value="LIBRARY2" /><FIELD name="Y_COORD" value="39.75" /><FIELD name="X_COORD" value="-104.42" /><FIELD name="#SHAPE#" value="[Geometry]" /><FIELD name="OBJECTID" value="2" /><FIELD name="shape.area" value="0" /><FIELD name="shape.len" value="0" /></FIELDS></FEATURE><FEATURECOUNT count="2" hasmore="false" /><ENVELOPE minx="-678853.220047791" miny="1810.22081371862" maxx="-678853.220047791" maxy="1810.22081371862"/></FEATURES></RESPONSE></ARCXML>';
//
// creating a new arcxml format creates an object that has a read and write function
//
function test_Format_ArcXML_constructor1(t) {
t.plan(4);
var format = new OpenLayers.Format.ArcXML();
t.ok(format instanceof OpenLayers.Format.ArcXML,
"new OpenLayers.Format.ArcXML returns object" );
t.ok(format.request, null, "no options creates a null request");
t.eq(typeof format.read, "function", "format has a read function");
t.eq(typeof format.write, "function", "format has a write function");
}
//
// creating a new arcxml format with a set of options for an image request
// creates a request child object, and a get_image grandchild.
//
function test_Format_ArcXML_constructor2(t) {
t.plan(6);
var options = {
requesttype:'image',
envelope: new OpenLayers.Bounds( -180, -90, 180, 90 ).toArray(),
layers: [],
tileSize: new OpenLayers.Size( 256,256 ),
featureCoordSys: '4326',
filterCoordSys: '4326'
};
var format = new OpenLayers.Format.ArcXML( options );
t.ok(format instanceof OpenLayers.Format.ArcXML,
"new OpenLayers.Format.ArcXML returns object" );
t.ok(format.request instanceof OpenLayers.Format.ArcXML.Request,
"constructor with 'image' requesttype generates a request");
t.ok( format.request.get_image !== null, "get_image property exists" );
t.ok( format.request.get_feature === null, "get_feature property does not exists" );
t.eq(typeof format.read, "function", "format has a read function");
t.eq(typeof format.write, "function", "format has a write function");
}
//
// creating a new arcxml format with a set of options for a feature request
// creates a request child object, and a get_feature grandchild
//
function test_Format_ArcXML_constructor3(t) {
t.plan(6);
var options = {
requesttype:'feature'
};
var format = new OpenLayers.Format.ArcXML( options );
t.ok(format instanceof OpenLayers.Format.ArcXML,
"new OpenLayers.Format.ArcXML returns object" );
t.ok(format.request instanceof OpenLayers.Format.ArcXML.Request,
"constructor with 'feature' requesttype generates a request");
t.ok( format.request.get_feature !== null, "get_feature property exists" );
t.ok( format.request.get_image === null, "get_image property does not exists" );
t.eq(typeof format.read, "function", "format has a read function");
t.eq(typeof format.write, "function", "format has a write function");
}
//
// read in a known good axl image response
//
function test_Format_ArcXML_read1(t) {
t.plan(4);
var f = new OpenLayers.Format.ArcXML();
var response = f.read(axl_image_response);
t.ok(response !== null, "get_image response object is not null" );
t.ok(response.image !== null, "get_image image tag is not null");
t.ok(response.image.envelope !== null, "get_image image envelope tag is not null");
t.ok(response.image.output !== null, "get_image image output tag is not null");
}
//
// read in a known good axl feature response
//
function test_Format_ArcXML_read2(t) {
t.plan(10);
var f = new OpenLayers.Format.ArcXML();
var response = f.read(axl_feature_response);
t.ok(response !== null, "get_feature response object is not null" );
t.ok(response.features !== null, "get_feature features tag is not null");
t.ok(response.features.envelope !== null, "get_feature envelope tag is not null");
t.eq(response.features.featurecount, "2", "feature count is 2" );
// test the second feature parsed
// <FIELD name="UNIQUE_ID" value="514504b5-0458-461d-b540-8e81a454f619" />
// <FIELD name="LABEL" value="LIBRARY2" />
// <FIELD name="Y_COORD" value="39.75" />
// <FIELD name="X_COORD" value="-104.42" />
// <FIELD name="#SHAPE#" value="[Geometry]" />
// <FIELD name="OBJECTID" value="2" />
// <FIELD name="shape.area" value="0" />
// <FIELD name="shape.len" value="0" />
t.eq( response.features.feature[1].attributes['UNIQUE_ID'], "514504b5-0458-461d-b540-8e81a454f619", "field 1 for feature 2 is correct" );
t.eq( response.features.feature[1].attributes['LABEL'], "LIBRARY2", "field 2 for feature 2 is correct" );
t.eq( response.features.feature[1].attributes['Y_COORD'], "39.75", "field 3 for feature 2 is correct" );
t.eq( response.features.feature[1].attributes['X_COORD'], "-104.42", "field 4 for feature 2 is correct" );
t.eq( response.features.feature[1].attributes['#SHAPE#'], "[Geometry]", "field 5 for feature 2 is correct" );
t.eq( response.features.feature[1].attributes['OBJECTID'], "2", "field 6 for feature 2 is correct" );
}
//
// cause an error by parsing bad axl
//
function test_Format_ArcXML_parseerror(t) {
t.plan(1);
var f = new OpenLayers.Format.ArcXML();
try {
f.read( '<?xml version="1.0" encoding="Cp1252"?><ARCXML version="1.1"><NO END TAG>' );
t.fail("parsing failed to fail")
} catch (ex) {
t.ok( true, "Exception message indicates parsing error." );
}
}
//
// create an arcxml image request, and verify that it matches a known image request
//
function test_format_ArcXML_write1(t) {
var options = {
requesttype:'image',
envelope: new OpenLayers.Bounds( -180, -90, 180, 90 ).toArray(),
layers: [],
tileSize: new OpenLayers.Size( 256,256 ),
featureCoordSys: '4326',
filterCoordSys: '4326'
};
var truth = '<ARCXML version="1.1"><REQUEST><GET_IMAGE><PROPERTIES><FEATURECOORDSYS id="4326"/><FILTERCOORDSYS id="4326"/><ENVELOPE minx="-180" miny="-90" maxx="180" maxy="90"/><IMAGESIZE height="256" width="256"/></PROPERTIES></GET_IMAGE></REQUEST></ARCXML>';
axl_write(t,options,truth);
}
//
// create an arcxml image request that specifies layer visibilities, and
// verify that it matches a known image request
//
function test_format_ArcXML_write2(t) {
var options = {
requesttype:'image',
envelope: new OpenLayers.Bounds( -180, -90, 180, 90 ).toArray(),
layers: [{
id: "0",
visible: "true"
}],
tileSize: new OpenLayers.Size( 256,256 ),
featureCoordSys: '4326',
filterCoordSys: '4326'
};
var truth = '<ARCXML version="1.1"><REQUEST><GET_IMAGE><PROPERTIES><FEATURECOORDSYS id="4326"/><FILTERCOORDSYS id="4326"/><ENVELOPE minx="-180" miny="-90" maxx="180" maxy="90"/><IMAGESIZE height="256" width="256"/><LAYERLIST><LAYERDEF id="0" visible="true"/></LAYERLIST></PROPERTIES></GET_IMAGE></REQUEST></ARCXML>';
axl_write(t, options, truth );
}
//
// create an arcxml image request that performs a query for thematic mapping,
// and verify that it matches a known image request
//
function test_format_ArcXML_write3(t) {
var options = {
requesttype:'image',
envelope: new OpenLayers.Bounds( -180, -90, 180, 90 ).toArray(),
layers: [{
id: "0",
visible: "true",
query: {
where: "COMPANY='AVENCIA'"
}
}],
tileSize: new OpenLayers.Size( 256,256 ),
featureCoordSys: '4326',
filterCoordSys: '4326'
};
var truth = '<ARCXML version="1.1"><REQUEST><GET_IMAGE><PROPERTIES><FEATURECOORDSYS id="4326"/><FILTERCOORDSYS id="4326"/><ENVELOPE minx="-180" miny="-90" maxx="180" maxy="90"/><IMAGESIZE height="256" width="256"/><LAYERLIST><LAYERDEF id="0" visible="true"><QUERY where="COMPANY=\'AVENCIA\'"/></LAYERDEF></LAYERLIST></PROPERTIES></GET_IMAGE></REQUEST></ARCXML>';
axl_write(t, options, truth );
}
//
// create an arcxml image request that performs a spatial query for thematic mapping,
// and verify that it matches a known image request
//
function test_format_ArcXML_write4(t) {
var options = {
requesttype:'image',
envelope: new OpenLayers.Bounds( -180, -90, 180, 90 ).toArray(),
layers: [{
id: "0",
visible: "true",
query: {
spatialfilter: true,
where: "COMPANY='AVENCIA'"
}
}],
tileSize: new OpenLayers.Size( 256,256 ),
featureCoordSys: '4326',
filterCoordSys: '4326'
};
var truth = '<ARCXML version="1.1"><REQUEST><GET_IMAGE><PROPERTIES><FEATURECOORDSYS id="4326"/><FILTERCOORDSYS id="4326"/><ENVELOPE minx="-180" miny="-90" maxx="180" maxy="90"/><IMAGESIZE height="256" width="256"/><LAYERLIST><LAYERDEF id="0" visible="true"><SPATIALQUERY where="COMPANY=\'AVENCIA\'"/></LAYERDEF></LAYERLIST></PROPERTIES></GET_IMAGE></REQUEST></ARCXML>';
axl_write(t, options, truth );
}
//
// create an arcxml image request that performs a thematic map request, and
// verify that it matches a known image request.
//
function test_format_ArcXML_write5(t) {
var options = {
requesttype:'image',
envelope: new OpenLayers.Bounds( -180, -90, 180, 90 ).toArray(),
layers: [{
id: "0",
visible: "true",
query: {
spatialfilter: true,
where: "COMPANY='AVENCIA'"
},
renderer: {
type: 'valuemap',
lookupfield: 'lookup',
ranges: [{
lower: 0,
upper: 10,
symbol: {
type: 'simplepolygon',
fillcolor: '0,0,0'
}
},{
lower: 10,
upper: 20,
symbol: {
type: 'simplepolygon',
fillcolor: '255,255,255'
}
}]
}
}],
tileSize: new OpenLayers.Size( 256,256 ),
featureCoordSys: '4326',
filterCoordSys: '4326'
};
var truth = '<ARCXML version="1.1"><REQUEST><GET_IMAGE><PROPERTIES><FEATURECOORDSYS id="4326"/><FILTERCOORDSYS id="4326"/><ENVELOPE minx="-180" miny="-90" maxx="180" maxy="90"/><IMAGESIZE height="256" width="256"/><LAYERLIST><LAYERDEF id="0" visible="true"><SPATIALQUERY where="COMPANY=\'AVENCIA\'"/><VALUEMAPRENDERER lookupfield="lookup"><RANGE lower="0" upper="10"><SIMPLEPOLYGONSYMBOL fillcolor="0,0,0"/></RANGE><RANGE lower="10" upper="20"><SIMPLEPOLYGONSYMBOL fillcolor="255,255,255"/></RANGE></VALUEMAPRENDERER></LAYERDEF></LAYERLIST></PROPERTIES></GET_IMAGE></REQUEST></ARCXML>';
axl_write(t, options, truth );
}
//
// helper function to write some axl, and compare it against a truth axl string
//
function axl_write(t, options, truth) {
t.plan(1);
var f = new OpenLayers.Format.ArcXML( options );
var arcxml = f.write();
t.eq( arcxml, truth, "ArcXML request is correct.");
}
</script>
</head>
<body>
</body>
</html>

View File

@@ -0,0 +1,69 @@
<html>
<head>
<script src="../../../lib/OpenLayers.js"></script>
<script type="text/javascript">
var axl_feature_response = '<?xml version="1.0" encoding="Cp1252"?><ARCXML version="1.1"><RESPONSE><FEATURES><FEATURE><FIELDS><FIELD name="UNIQUE_ID" value="514504b5-0458-461d-b540-8e18a454f619" /><FIELD name="LABEL" value="LIBRARY" /><FIELD name="Y_COORD" value="39.57" /><FIELD name="X_COORD" value="-104.24" /><FIELD name="#SHAPE#" value="[Geometry]" /><FIELD name="OBJECTID" value="1" /><FIELD name="shape.area" value="0" /><FIELD name="shape.len" value="0" /></FIELDS></FEATURE><FEATURE><FIELDS><FIELD name="UNIQUE_ID" value="514504b5-0458-461d-b540-8e81a454f619" /><FIELD name="LABEL" value="LIBRARY2" /><FIELD name="Y_COORD" value="39.75" /><FIELD name="X_COORD" value="-104.42" /><FIELD name="#SHAPE#" value="[Geometry]" /><FIELD name="OBJECTID" value="2" /><FIELD name="shape.area" value="0" /><FIELD name="shape.len" value="0" /></FIELDS></FEATURE><FEATURECOUNT count="2" hasmore="false" /><ENVELOPE minx="-678853.220047791" miny="1810.22081371862" maxx="-678853.220047791" maxy="1810.22081371862"/></FEATURES></RESPONSE></ARCXML>';
//
// creating a new arcxml features format creates an object that has a read and write function
//
function test_initialize(t) {
t.plan(3);
var format = new OpenLayers.Format.ArcXML.Features();
t.ok(format instanceof OpenLayers.Format.ArcXML.Features,
"new OpenLayers.Format.ArcXML.Features returns object" );
t.eq(typeof format.read, "function", "format has a read function");
t.eq(typeof format.write, "function", "format has a write function");
}
//
// read in a known good axl feature response
//
function test_read1(t) {
t.plan(8);
var f = new OpenLayers.Format.ArcXML.Features();
var features = f.read(axl_feature_response);
t.ok(features !== null, "features are not null" );
t.eq(features.length, 2, "feature count is 2" );
// test the second feature parsed
// <FIELD name="UNIQUE_ID" value="514504b5-0458-461d-b540-8e81a454f619" />
// <FIELD name="LABEL" value="LIBRARY2" />
// <FIELD name="Y_COORD" value="39.75" />
// <FIELD name="X_COORD" value="-104.42" />
// <FIELD name="#SHAPE#" value="[Geometry]" />
// <FIELD name="OBJECTID" value="2" />
// <FIELD name="shape.area" value="0" />
// <FIELD name="shape.len" value="0" />
t.eq( features[1].attributes['UNIQUE_ID'], "514504b5-0458-461d-b540-8e81a454f619", "field 1 for feature 2 is correct" );
t.eq( features[1].attributes['LABEL'], "LIBRARY2", "field 2 for feature 2 is correct" );
t.eq( features[1].attributes['Y_COORD'], "39.75", "field 3 for feature 2 is correct" );
t.eq( features[1].attributes['X_COORD'], "-104.42", "field 4 for feature 2 is correct" );
t.eq( features[1].attributes['#SHAPE#'], "[Geometry]", "field 5 for feature 2 is correct" );
t.eq( features[1].attributes['OBJECTID'], "2", "field 6 for feature 2 is correct" );
}
//
// cause an error by parsing bad axl
//
function test_parseerror(t) {
t.plan(1);
var f = new OpenLayers.Format.ArcXML.Features();
try {
f.read( '<?xml version="1.0" encoding="Cp1252"?><ARCXML version="1.1"><NO END TAG>' );
t.fail("reading didn't fail");
} catch (ex) {
t.eq( ex.message, "Error parsing the ArcXML request", "Exception message indicates parsing error." );
}
}
</script>
</head>
<body>
</body>
</html>

89
tests/Layer/ArcIMS.html Normal file
View File

@@ -0,0 +1,89 @@
<html>
<head>
<script type="text/javascript" src="../../lib/OpenLayers.js"></script>
<script type="text/javascript">
// use an arcims map service against Avencia Inc.'s global sample map services
var serviceName = "OpenLayers_Sample";
var layerName = "Global Sample Map";
var imsUrl = "http://sample.avencia.com/servlet/com.esri.esrimap.Esrimap";
//
// create an arcims layer
//
function test_Layer_ArcIMS_constructor( t ) {
t.plan(11);
var options = {
serviceName: serviceName,
async: false,
displayOutsideMaxExtent: true
};
var layer = new OpenLayers.Layer.ArcIMS( layerName, imsUrl, options );
// check layer & properties
t.ok( layer instanceof OpenLayers.Layer.ArcIMS, "new OpenLayers.Layer.ArcIMS returns object" );
t.eq( layer.url, imsUrl, "layer.url is correct (HTTPRequest inited)" );
t.eq( layer.name, layerName, "layer.name is correct" );
t.eq( layer.displayOutsideMaxExtent, options.displayOutsideMaxExtent,
"displayOutsideMaxExtent property set correctly from options" );
// check request parameters
t.eq( layer.params.ServiceName, serviceName, "ServiceName set properly" );
t.eq( layer.params.ClientVersion, "9.2", "ClientVersion set properly" );
// check request options
t.eq( layer.options.async, options.async, "async property set correctly from options" );
t.eq( layer.options.serviceName, serviceName, "serviceName property set correctly from options" );
t.eq( layer.options.layers.length, 0, "layers option is the correct length" );
t.eq( layer.options.tileSize.w, 512, "default tile width set correctly" );
t.eq( layer.options.tileSize.h, 512, "default tile height set correctly" );
}
/*
* how to test getURL, getURLasync, and getFeatureInfo without a proxy?
*
*/
//
// Create an arcims layer, and verify that the query changes properly
//
function test_Layer_ArcIMS_setLayerQuery(t) {
t.plan(9);
var options = { serviceName: serviceName };
var layer = new OpenLayers.Layer.ArcIMS( layerName, imsUrl, options );
var querydef = {
where: "FIPS_CNTRY = 'US'"
};
t.eq( layer.options.layers.length, 0, "layer definitions are empty" );
layer.setLayerQuery( "layerID", querydef );
t.eq( layer.options.layers.length, 1, "layers definitions contain one layerdef" );
t.ok( layer.options.layers[0].query !== null, "layer query exists" );
t.eq( typeof layer.options.layers[0].query.where, "string", "where query is a string" );
t.eq( layer.options.layers[0].query.where, querydef.where, "where query matches" );
// change the definition
querydef = {
where: "FIPS_CNTRY = 'UV'",
spatialfilter:true
}
layer.setLayerQuery( "layerID", querydef );
t.eq( layer.options.layers.length, 1, "layers definitions contain one layerdef" );
t.ok( layer.options.layers[0].query !== null, "layer query exists" );
t.eq( typeof layer.options.layers[0].query.where, "string", "where query is a string" );
t.eq( layer.options.layers[0].query.where, querydef.where, "where query matches" );
}
</script>
</head>
</html>

View File

@@ -45,6 +45,8 @@
<li>Filter/Logical.html</li>
<li>Filter/Spatial.html</li>
<li>Format.html</li>
<li>Format/ArcXML.html</li>
<li>Format/ArcXML/Features.html</li>
<li>Format/GeoJSON.html</li>
<li>Format/GeoRSS.html</li>
<li>Format/GML.html</li>
@@ -103,6 +105,7 @@
<li>Icon.html</li>
<li>Lang.html</li>
<li>Layer.html</li>
<li>Layer/ArcIMS.html</li>
<li>Layer/ArcGIS93Rest.html</li>
<li>Layer/EventPane.html</li>
<li>Layer/FixedZoomLevels.html</li>