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

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>