Merge pull request #213 from bartvde/wmtsclean

Implement WMTS GetCapabilities parser.
This commit is contained in:
Bart van den Eijnden
2013-02-19 07:45:08 -08:00
16 changed files with 1334 additions and 2 deletions

View File

@@ -88,3 +88,19 @@ ol.Coordinate.toStringXY = function(coordinate, opt_precision) {
return '';
}
};
/**
* Create an ol.Coordinate from an Array and take into account axis order.
* @param {Array} array The array with coordinates.
* @param {string} axis the axis info.
* @return {ol.Coordinate} The coordinate created.
*/
ol.Coordinate.fromProjectedArray = function(array, axis) {
var firstAxis = axis.charAt(0);
if (firstAxis === 'n' || firstAxis === 's') {
return new ol.Coordinate(array[1], array[0]);
} else {
return new ol.Coordinate(array[0], array[1]);
}
};

View File

@@ -0,0 +1,214 @@
goog.provide('ol.parser.ogc.OWSCommon_v1');
goog.require('ol.Extent');
goog.require('ol.parser.XML');
/**
* @constructor
* @extends {ol.parser.XML}
*/
ol.parser.ogc.OWSCommon_v1 = function() {
this.readers = {
'http://www.opengis.net/ows': {
'ServiceIdentification': function(node, obj) {
obj['serviceIdentification'] = {};
this.readChildNodes(node, obj['serviceIdentification']);
},
'Title': function(node, obj) {
obj['title'] = this.getChildValue(node);
},
'Abstract': function(node, serviceIdentification) {
serviceIdentification['abstract'] = this.getChildValue(node);
},
'Keywords': function(node, serviceIdentification) {
serviceIdentification['keywords'] = {};
this.readChildNodes(node, serviceIdentification['keywords']);
},
'Keyword': function(node, keywords) {
keywords[this.getChildValue(node)] = true;
},
'ServiceType': function(node, serviceIdentification) {
serviceIdentification['serviceType'] = {
'codeSpace': node.getAttribute('codeSpace'),
'value': this.getChildValue(node)};
},
'ServiceTypeVersion': function(node, serviceIdentification) {
serviceIdentification['serviceTypeVersion'] = this.getChildValue(node);
},
'Fees': function(node, serviceIdentification) {
serviceIdentification['fees'] = this.getChildValue(node);
},
'AccessConstraints': function(node, serviceIdentification) {
serviceIdentification['accessConstraints'] =
this.getChildValue(node);
},
'ServiceProvider': function(node, obj) {
obj['serviceProvider'] = {};
this.readChildNodes(node, obj['serviceProvider']);
},
'ProviderName': function(node, serviceProvider) {
serviceProvider['providerName'] = this.getChildValue(node);
},
'ProviderSite': function(node, serviceProvider) {
serviceProvider['providerSite'] = this.getAttributeNS(node,
'http://www.w3.org/1999/xlink', 'href');
},
'ServiceContact': function(node, serviceProvider) {
serviceProvider['serviceContact'] = {};
this.readChildNodes(node, serviceProvider['serviceContact']);
},
'IndividualName': function(node, serviceContact) {
serviceContact['individualName'] = this.getChildValue(node);
},
'PositionName': function(node, serviceContact) {
serviceContact['positionName'] = this.getChildValue(node);
},
'ContactInfo': function(node, serviceContact) {
serviceContact['contactInfo'] = {};
this.readChildNodes(node, serviceContact['contactInfo']);
},
'Phone': function(node, contactInfo) {
contactInfo['phone'] = {};
this.readChildNodes(node, contactInfo['phone']);
},
'Voice': function(node, phone) {
phone['voice'] = this.getChildValue(node);
},
'Address': function(node, contactInfo) {
contactInfo['address'] = {};
this.readChildNodes(node, contactInfo['address']);
},
'DeliveryPoint': function(node, address) {
address['deliveryPoint'] = this.getChildValue(node);
},
'City': function(node, address) {
address['city'] = this.getChildValue(node);
},
'AdministrativeArea': function(node, address) {
address['administrativeArea'] = this.getChildValue(node);
},
'PostalCode': function(node, address) {
address['postalCode'] = this.getChildValue(node);
},
'Country': function(node, address) {
address['country'] = this.getChildValue(node);
},
'ElectronicMailAddress': function(node, address) {
address['electronicMailAddress'] = this.getChildValue(node);
},
'Role': function(node, serviceContact) {
serviceContact['role'] = this.getChildValue(node);
},
'OperationsMetadata': function(node, obj) {
obj['operationsMetadata'] = {};
this.readChildNodes(node, obj['operationsMetadata']);
},
'Operation': function(node, operationsMetadata) {
var name = node.getAttribute('name');
operationsMetadata[name] = {};
this.readChildNodes(node, operationsMetadata[name]);
},
'DCP': function(node, operation) {
operation['dcp'] = {};
this.readChildNodes(node, operation['dcp']);
},
'HTTP': function(node, dcp) {
dcp['http'] = {};
this.readChildNodes(node, dcp['http']);
},
'Get': function(node, http) {
if (!http['get']) {
http['get'] = [];
}
var obj = {
'url': this.getAttributeNS(node, 'http://www.w3.org/1999/xlink',
'href')
};
this.readChildNodes(node, obj);
http['get'].push(obj);
},
'Post': function(node, http) {
if (!http['post']) {
http['post'] = [];
}
var obj = {
'url': this.getAttributeNS(node, 'http://www.w3.org/1999/xlink',
'href')
};
this.readChildNodes(node, obj);
http['post'].push(obj);
},
'Parameter': function(node, operation) {
if (!operation['parameters']) {
operation['parameters'] = {};
}
var name = node.getAttribute('name');
operation['parameters'][name] = {};
this.readChildNodes(node, operation['parameters'][name]);
},
'Constraint': function(node, obj) {
if (!obj['constraints']) {
obj['constraints'] = {};
}
var name = node.getAttribute('name');
obj['constraints'][name] = {};
this.readChildNodes(node, obj['constraints'][name]);
},
'Value': function(node, allowedValues) {
allowedValues[this.getChildValue(node)] = true;
},
'OutputFormat': function(node, obj) {
obj['formats'].push({'value': this.getChildValue(node)});
this.readChildNodes(node, obj);
},
'WGS84BoundingBox': function(node, obj) {
var boundingBox = {};
boundingBox['crs'] = node.getAttribute('crs');
if (obj['BoundingBox']) {
obj['BoundingBox'].push(boundingBox);
} else {
obj['projection'] = boundingBox['crs'];
boundingBox = obj;
}
this.readChildNodes(node, boundingBox);
},
'BoundingBox': function(node, obj) {
// FIXME: We consider that BoundingBox is the same as WGS84BoundingBox
// LowerCorner = "min_x min_y"
// UpperCorner = "max_x max_y"
// It should normally depend on the projection
var readers = this.readers['http://www.opengis.net/ows'];
readers['WGS84BoundingBox'].apply(this, [node, obj]);
},
'LowerCorner': function(node, obj) {
var str = this.getChildValue(node).replace(
this.regExes.trimSpace, '');
str = str.replace(this.regExes.trimComma, ',');
var pointList = str.split(this.regExes.splitSpace);
obj['left'] = pointList[0];
obj['bottom'] = pointList[1];
},
'UpperCorner': function(node, obj) {
var str = this.getChildValue(node).replace(
this.regExes.trimSpace, '');
str = str.replace(this.regExes.trimComma, ',');
var pointList = str.split(this.regExes.splitSpace);
obj['right'] = pointList[0];
obj['top'] = pointList[1];
obj['bounds'] = new ol.Extent(parseFloat(obj['left']),
parseFloat(obj['bottom']), parseFloat(obj['right']),
parseFloat(obj['top']));
delete obj['left'];
delete obj['bottom'];
delete obj['right'];
delete obj['top'];
},
'Language': function(node, obj) {
obj['language'] = this.getChildValue(node);
}
}
};
goog.base(this);
};
goog.inherits(ol.parser.ogc.OWSCommon_v1, ol.parser.XML);

View File

@@ -0,0 +1,45 @@
goog.provide('ol.parser.ogc.OWSCommon_v1_1_0');
goog.require('goog.object');
goog.require('ol.parser.ogc.OWSCommon_v1');
/**
* @constructor
* @extends {ol.parser.ogc.OWSCommon_v1}
*/
ol.parser.ogc.OWSCommon_v1_1_0 = function() {
goog.base(this);
this.readers['http://www.opengis.net/ows/1.1'] =
this.readers['http://www.opengis.net/ows'];
goog.object.extend(this.readers['http://www.opengis.net/ows/1.1'], {
'AllowedValues': function(node, parameter) {
parameter['allowedValues'] = {};
this.readChildNodes(node, parameter['allowedValues']);
},
'AnyValue': function(node, parameter) {
parameter['anyValue'] = true;
},
'DataType': function(node, parameter) {
parameter['dataType'] = this.getChildValue(node);
},
'Range': function(node, allowedValues) {
allowedValues['range'] = {};
this.readChildNodes(node, allowedValues['range']);
},
'MinimumValue': function(node, range) {
range['minValue'] = this.getChildValue(node);
},
'MaximumValue': function(node, range) {
range['maxValue'] = this.getChildValue(node);
},
'Identifier': function(node, obj) {
obj['identifier'] = this.getChildValue(node);
},
'SupportedCRS': function(node, obj) {
obj['supportedCRS'] = this.getChildValue(node);
}
});
};
goog.inherits(ol.parser.ogc.OWSCommon_v1_1_0,
ol.parser.ogc.OWSCommon_v1);

View File

@@ -0,0 +1,2 @@
@exportSymbol ol.parser.ogc.WMTSCapabilities
@exportProperty ol.parser.ogc.WMTSCapabilities.prototype.read

View File

@@ -0,0 +1,19 @@
goog.provide('ol.parser.ogc.WMTSCapabilities');
goog.require('ol.parser.ogc.Versioned');
goog.require('ol.parser.ogc.WMTSCapabilities_v1_0_0');
/**
* @constructor
* @param {Object=} opt_options Options which will be set on this object.
* @extends {ol.parser.ogc.Versioned}
*/
ol.parser.ogc.WMTSCapabilities = function(opt_options) {
opt_options = opt_options || {};
opt_options['defaultVersion'] = '1.0.0';
this.parsers = {};
this.parsers['v1_0_0'] = ol.parser.ogc.WMTSCapabilities_v1_0_0;
goog.base(this, opt_options);
};
goog.inherits(ol.parser.ogc.WMTSCapabilities, ol.parser.ogc.Versioned);

View File

@@ -0,0 +1,161 @@
goog.provide('ol.parser.ogc.WMTSCapabilities_v1_0_0');
goog.require('goog.dom.xml');
goog.require('ol.Coordinate');
goog.require('ol.Projection');
goog.require('ol.parser.XML');
goog.require('ol.parser.ogc.OWSCommon_v1_1_0');
/**
* @constructor
* @extends {ol.parser.XML}
*/
ol.parser.ogc.WMTSCapabilities_v1_0_0 = function() {
this.readers = {
'http://www.opengis.net/wmts/1.0': {
'Capabilities': function(node, obj) {
this.readChildNodes(node, obj);
},
'Contents': function(node, obj) {
obj['contents'] = {};
obj['contents']['layers'] = [];
obj['contents']['tileMatrixSets'] = {};
this.readChildNodes(node, obj['contents']);
},
'Layer': function(node, obj) {
var layer = {
'styles': [],
'formats': [],
'dimensions': [],
'tileMatrixSetLinks': []
};
layer['layers'] = [];
this.readChildNodes(node, layer);
obj['layers'].push(layer);
},
'Style': function(node, obj) {
var style = {};
style['isDefault'] = (node.getAttribute('isDefault') === 'true');
this.readChildNodes(node, style);
obj['styles'].push(style);
},
'Format': function(node, obj) {
obj['formats'].push(this.getChildValue(node));
},
'TileMatrixSetLink': function(node, obj) {
var tileMatrixSetLink = {};
this.readChildNodes(node, tileMatrixSetLink);
obj['tileMatrixSetLinks'].push(tileMatrixSetLink);
},
'TileMatrixSet': function(node, obj) {
// node could be child of wmts:Contents or wmts:TileMatrixSetLink
// duck type wmts:Contents by looking for layers
if (obj['layers']) {
// TileMatrixSet as object type in schema
var tileMatrixSet = {
'matrixIds': []
};
this.readChildNodes(node, tileMatrixSet);
obj['tileMatrixSets'][tileMatrixSet['identifier']] = tileMatrixSet;
} else {
// TileMatrixSet as string type in schema
obj['tileMatrixSet'] = this.getChildValue(node);
}
},
'TileMatrix': function(node, obj) {
var tileMatrix = {
'supportedCRS': obj.supportedCRS
};
this.readChildNodes(node, tileMatrix);
obj['matrixIds'].push(tileMatrix);
},
'ScaleDenominator': function(node, obj) {
obj['scaleDenominator'] = parseFloat(this.getChildValue(node));
},
'TopLeftCorner': function(node, obj) {
var topLeftCorner = this.getChildValue(node);
var coords = topLeftCorner.split(' ');
var axis = ol.Projection.getFromCode(obj['supportedCRS']).getAxis();
obj['topLeftCorner'] = ol.Coordinate.fromProjectedArray(
[parseFloat(coords[0]), parseFloat(coords[1])], axis);
},
'TileWidth': function(node, obj) {
obj['tileWidth'] = parseInt(this.getChildValue(node), 10);
},
'TileHeight': function(node, obj) {
obj['tileHeight'] = parseInt(this.getChildValue(node), 10);
},
'MatrixWidth': function(node, obj) {
obj['matrixWidth'] = parseInt(this.getChildValue(node), 10);
},
'MatrixHeight': function(node, obj) {
obj['matrixHeight'] = parseInt(this.getChildValue(node), 10);
},
'ResourceURL': function(node, obj) {
obj['resourceUrl'] = obj['resourceUrl'] || {};
var resourceType = node.getAttribute('resourceType');
if (!obj['resourceUrls']) {
obj['resourceUrls'] = [];
}
var resourceUrl = obj['resourceUrl'][resourceType] = {
'format': node.getAttribute('format'),
'template': node.getAttribute('template'),
'resourceType': resourceType
};
obj['resourceUrls'].push(resourceUrl);
},
'WSDL': function(node, obj) {
obj['wsdl'] = {};
obj['wsdl']['href'] = this.getAttributeNS(node,
'http://www.w3.org/1999/xlink', 'href');
// TODO: other attributes of <WSDL> element
},
'ServiceMetadataURL': function(node, obj) {
obj['serviceMetadataUrl'] = {};
obj['serviceMetadataUrl']['href'] =
this.getAttributeNS(node, 'http://www.w3.org/1999/xlink', 'href');
// TODO: other attributes of <ServiceMetadataURL> element
},
'LegendURL': function(node, obj) {
obj['legend'] = {};
obj['legend']['href'] = this.getAttributeNS(node,
'http://www.w3.org/1999/xlink', 'href');
obj['legend']['format'] = node.getAttribute('format');
},
'Dimension': function(node, obj) {
var dimension = {'values': []};
this.readChildNodes(node, dimension);
obj['dimensions'].push(dimension);
},
'Default': function(node, obj) {
obj['default'] = this.getChildValue(node);
},
'Value': function(node, obj) {
obj['values'].push(this.getChildValue(node));
}
}
};
var ows = new ol.parser.ogc.OWSCommon_v1_1_0();
this.readers['http://www.opengis.net/ows/1.1'] =
ows.readers['http://www.opengis.net/ows/1.1'];
goog.base(this);
};
goog.inherits(ol.parser.ogc.WMTSCapabilities_v1_0_0, ol.parser.XML);
/**
* @param {string|Document|Element} data Data to read.
* @return {Object} An object representing the document.
*/
ol.parser.ogc.WMTSCapabilities_v1_0_0.prototype.read = function(data) {
if (typeof data == 'string') {
data = goog.dom.xml.loadXml(data);
}
if (data && data.nodeType == 9) {
data = data.documentElement;
}
var obj = {};
this.readNode(data, obj);
return obj;
};

View File

@@ -6,6 +6,12 @@ goog.provide('ol.parser.XML');
* @constructor
*/
ol.parser.XML = function() {
this.regExes = {
trimSpace: (/^\s*|\s*$/g),
removeSpace: (/\s*/g),
splitSpace: (/\s+/),
trimComma: (/\s*,\s*/g)
};
};

View File

@@ -36,8 +36,9 @@ ol.ProjectionUnits = {
* @param {string} code Code.
* @param {ol.ProjectionUnits} units Units.
* @param {ol.Extent} extent Extent.
* @param {string=} opt_axis Axis order.
*/
ol.Projection = function(code, units, extent) {
ol.Projection = function(code, units, extent, opt_axis) {
/**
* @private
@@ -57,6 +58,12 @@ ol.Projection = function(code, units, extent) {
*/
this.extent_ = extent;
/**
* @private
* @type {string}
*/
this.axis_ = opt_axis || 'enu';
};
@@ -84,6 +91,14 @@ ol.Projection.prototype.getUnits = function() {
};
/**
* @return {string} Axis.
*/
ol.Projection.prototype.getAxis = function() {
return this.axis_;
};
/**
* @constructor
@@ -526,6 +541,7 @@ ol.Projection.EPSG_4326_EXTENT_ = new ol.Extent(-180, -90, 180, 90);
*/
ol.Projection.EPSG_4326_LIKE_CODES_ = [
'CRS:84',
'urn:ogc:def:crs:OGC:1.3:CRS84',
'EPSG:4326',
'urn:ogc:def:crs:EPSG:6.6:4326'
];
@@ -543,7 +559,9 @@ ol.Projection.EPSG_4326_LIKE_PROJECTIONS = goog.array.map(
return new ol.Projection(
code,
ol.ProjectionUnits.DEGREES,
ol.Projection.EPSG_4326_EXTENT_);
ol.Projection.EPSG_4326_EXTENT_,
code === 'CRS:84' || code === 'urn:ogc:def:crs:OGC:1.3:CRS84' ?
'enu' : 'neu');
});