1
|
/*
|
2
|
License: LGPL as per: http://www.gnu.org/copyleft/lesser.html
|
3
|
$Id$
|
4
|
*/
|
5
|
|
6
|
/**
|
7
|
* Stores a Web Map Context (WMC) document as defined by the Open GIS Consortium
|
8
|
* http://opengis.org and extensions the the WMC.
|
9
|
*
|
10
|
* Listeners supported by this model:
|
11
|
* "refresh" called when window parameters (width/height, bbox) are changed
|
12
|
* "hidden" called when visibilty of a layer is changed
|
13
|
*
|
14
|
* @constructor
|
15
|
* @base ModelBase
|
16
|
* @author Cameron Shorter
|
17
|
* @param modelNode Pointer to the xml node for this model from the config file.
|
18
|
* @param parent The parent model for the object.
|
19
|
*
|
20
|
*/
|
21
|
function Context(modelNode, parent) {
|
22
|
// Inherit the ModelBase functions and parameters
|
23
|
ModelBase.apply(this, new Array(modelNode, parent));
|
24
|
|
25
|
this.namespace = "xmlns:mb='http://mapbuilder.sourceforge.net/mapbuilder' xmlns:wmc='http://www.opengis.net/context' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'";
|
26
|
|
27
|
/**
|
28
|
* Change a Layer's visibility.
|
29
|
* @param layerName The name of the layer that is to be changed
|
30
|
* @param hidden String with the value to be set; 1=hidden, 0=visible.
|
31
|
*/
|
32
|
this.setHidden=function(layerName, hidden){
|
33
|
// Set the hidden attribute in the Context
|
34
|
var hiddenValue = "0";
|
35
|
if (hidden) hiddenValue = "1";
|
36
|
|
37
|
var layer=this.doc.selectSingleNode("/wmc:ViewContext/wmc:LayerList/wmc:Layer[wmc:Name='"+layerName+"']");
|
38
|
if (layer) layer.setAttribute("hidden", hiddenValue);
|
39
|
// Call the listeners
|
40
|
this.callListeners("hidden", layerName);
|
41
|
}
|
42
|
|
43
|
/**
|
44
|
* Get the layer's visiblity attribute value.
|
45
|
* @param layerName The name of the layer that is to be changed
|
46
|
* @return hidden String with the value; 1=hidden, 0=visible.
|
47
|
*/
|
48
|
this.getHidden=function(layerName){
|
49
|
var hidden=1;
|
50
|
var layer=this.doc.selectSingleNode("/wmc:ViewContext/wmc:LayerList/wmc:Layer[wmc:Name='"+layerName+"']");
|
51
|
if (layer) hidden = layer.getAttribute("hidden");
|
52
|
return hidden;
|
53
|
}
|
54
|
|
55
|
/**
|
56
|
* Get the BoundingBox value from the Context document.
|
57
|
* @return BoundingBox array with the sequence (xmin,ymin,xmax,ymax).
|
58
|
*/
|
59
|
this.getBoundingBox=function() {
|
60
|
var boundingBox=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:BoundingBox");
|
61
|
bbox = new Array();
|
62
|
bbox[0]=parseFloat(boundingBox.getAttribute("minx"));
|
63
|
bbox[1]=parseFloat(boundingBox.getAttribute("miny"));
|
64
|
bbox[2]=parseFloat(boundingBox.getAttribute("maxx"));
|
65
|
bbox[3]=parseFloat(boundingBox.getAttribute("maxy"));
|
66
|
return bbox;
|
67
|
}
|
68
|
|
69
|
/**
|
70
|
* Set the BoundingBox element and call the refresh listeners
|
71
|
* @param boundingBox array in the sequence (xmin, ymin, xmax, ymax).
|
72
|
*/
|
73
|
this.setBoundingBox=function(boundingBox) {
|
74
|
// Set BoundingBox in context
|
75
|
//bbox=this.doc.documentElement.getElementsByTagName("BoundingBox").item(0);
|
76
|
var bbox=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:BoundingBox");
|
77
|
bbox.setAttribute("minx", boundingBox[0]);
|
78
|
bbox.setAttribute("miny", boundingBox[1]);
|
79
|
bbox.setAttribute("maxx", boundingBox[2]);
|
80
|
bbox.setAttribute("maxy", boundingBox[3]);
|
81
|
// Call the listeners
|
82
|
this.callListeners("bbox", boundingBox);
|
83
|
}
|
84
|
|
85
|
/**
|
86
|
* Set the BoundingBox element and call the refresh listeners
|
87
|
* @param boundingBox array in the sequence (xmin, ymin, xmax, ymax).
|
88
|
*/
|
89
|
this.initBbox=function(objRef) {
|
90
|
// Set BoundingBox in context from URL CGI params
|
91
|
if (window.cgiArgs["bbox"]) { //set as minx,miny,maxx,maxy
|
92
|
var bbox = window.cgiArgs["bbox"].split(',');
|
93
|
var ul = new Array(parseFloat(bbox[0]),parseFloat(bbox[3]));
|
94
|
var lr = new Array(parseFloat(bbox[2]),parseFloat(bbox[1]));
|
95
|
objRef.extent.zoomToBox(ul, lr);
|
96
|
}
|
97
|
}
|
98
|
//PGC this.addListener( "loadModel", this.initBbox, this );
|
99
|
this.addListener( "contextLoaded", this.initBbox, this );
|
100
|
|
101
|
/**
|
102
|
* Set the aoi param and call the refresh listeners
|
103
|
* @param boundingBox array in the sequence (xmin, ymin, xmax, ymax).
|
104
|
*/
|
105
|
this.initAoi=function(objRef) {
|
106
|
// Set AOI of context from URL CGI params
|
107
|
if (window.cgiArgs["aoi"]) { //set as ul,lr point arrays
|
108
|
var aoi = window.cgiArgs["aoi"].split(',');
|
109
|
objRef.setParam("aoi",new Array(new Array(aoi[0],aoi[3]),new Array(aoi[2],aoi[1])));
|
110
|
}
|
111
|
}
|
112
|
this.addListener( "loadModel", this.initAoi, this );
|
113
|
//MA this.addListener( "contextLoaded", this.initAoi, this );
|
114
|
|
115
|
/**
|
116
|
* Set the Spacial Reference System for the context document.
|
117
|
* @param srs The Spatial Reference System.
|
118
|
*/
|
119
|
this.setSRS=function(srs) {
|
120
|
var bbox=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:BoundingBox");
|
121
|
bbox.setAttribute("SRS",srs);
|
122
|
this.callListeners("srs");
|
123
|
}
|
124
|
|
125
|
/**
|
126
|
* Get the Spacial Reference System from the context document.
|
127
|
* @return srs The Spatial Reference System.
|
128
|
*/
|
129
|
this.getSRS=function() {
|
130
|
var bbox=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:BoundingBox");
|
131
|
srs=bbox.getAttribute("SRS");
|
132
|
return srs;
|
133
|
}
|
134
|
|
135
|
/**
|
136
|
* Get the Window width.
|
137
|
* @return width The width of map window from the context document
|
138
|
*/
|
139
|
this.getWindowWidth=function() {
|
140
|
var win=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:Window");
|
141
|
return win.getAttribute("width");
|
142
|
}
|
143
|
|
144
|
/**
|
145
|
* Set the Window width.
|
146
|
* @param width The width of map window (therefore of map layer images).
|
147
|
*/
|
148
|
this.setWindowWidth=function(width) {
|
149
|
var win=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:Window");
|
150
|
win.setAttribute("width", width);
|
151
|
this.callListeners("resize");
|
152
|
}
|
153
|
|
154
|
/**
|
155
|
* Get the Window height.
|
156
|
* @return height The height of map window from the context document.
|
157
|
*/
|
158
|
this.getWindowHeight=function() {
|
159
|
var win=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:Window");
|
160
|
return win.getAttribute("height");
|
161
|
}
|
162
|
|
163
|
/**
|
164
|
* Set the Window height.
|
165
|
* @param height The height of map window to set in the context document
|
166
|
*/
|
167
|
this.setWindowHeight=function(height) {
|
168
|
var win=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:Window");
|
169
|
win.setAttribute("height", height);
|
170
|
this.callListeners("resize");
|
171
|
}
|
172
|
|
173
|
/**
|
174
|
* Returns the serverUrl for the layer passed in as the feature argument.
|
175
|
* @param requestName ignored for context docs (only GetMap supported)
|
176
|
* @param method ignored for context docs (only GET supported)
|
177
|
* @param feature the Layer node from the context doc
|
178
|
* @return URL for the GetMap request
|
179
|
*/
|
180
|
this.getServerUrl = function(requestName, method, feature) {
|
181
|
return feature.selectSingleNode("wmc:Server/wmc:OnlineResource").getAttribute("xlink:href");
|
182
|
}
|
183
|
|
184
|
/**
|
185
|
* Returns the WMS version for the layer passed in as the feature argument
|
186
|
* @param feature the Layer node from the context doc
|
187
|
* @return the WMS GetMap version for the Layer.
|
188
|
*/
|
189
|
this.getVersion = function(feature) {
|
190
|
return feature.selectSingleNode("wmc:Server").getAttribute("version");
|
191
|
}
|
192
|
|
193
|
/**
|
194
|
* Get HTTP method for the specified feature
|
195
|
* @param feature the Layer node from the context doc
|
196
|
* @return the HTTP method to get the feature with
|
197
|
*/
|
198
|
this.getMethod = function(feature) {
|
199
|
return feature.selectSingleNode("wmc:Server/wmc:OnlineResource").getAttribute("wmc:method");
|
200
|
}
|
201
|
|
202
|
/**
|
203
|
* Method to get a list of queryable layers
|
204
|
* @return the list with queryable layers
|
205
|
*/
|
206
|
this.getQueryableLayers = function() {
|
207
|
var listNodeArray = this.doc.selectNodes("/wmc:ViewContext/wmc:LayerList/wmc:Layer[attribute::queryable='1']/wmc:Name");
|
208
|
return listNodeArray;
|
209
|
}
|
210
|
|
211
|
/**
|
212
|
* Method to get a list of all layers in the context doc
|
213
|
* TBD: merge this with above, passing queryable as an optional boolean param?
|
214
|
* @return the list with all layers
|
215
|
*/
|
216
|
this.getAllLayers = function() {
|
217
|
var listNodeArray = this.doc.selectNodes("/wmc:ViewContext/wmc:LayerList/wmc:Layer");
|
218
|
return listNodeArray;
|
219
|
}
|
220
|
|
221
|
/**
|
222
|
* Method to get a layer with the specified name in the context doc
|
223
|
* @param layerName the layer to be returned
|
224
|
* @return the list with all layers
|
225
|
*/
|
226
|
this.getLayer = function(layerName) {
|
227
|
var layer = this.doc.selectSingleNode("/wmc:ViewContext/wmc:LayerList/wmc:Layer[wmc:Name='"+layerName+"']");
|
228
|
//TBD: add in time stamp
|
229
|
return layer;
|
230
|
}
|
231
|
|
232
|
/**
|
233
|
* Method to add a Layer to the LayerList
|
234
|
* @param layerNode the Layer node from another context doc or capabiltiies doc
|
235
|
*/
|
236
|
this.addLayer = function(objRef, layerNode) {
|
237
|
var parentNode = objRef.doc.selectSingleNode("/wmc:ViewContext/wmc:LayerList");
|
238
|
parentNode.appendChild(layerNode.cloneNode(true));
|
239
|
objRef.modified = true;
|
240
|
//objRef.callListeners("refresh");
|
241
|
}
|
242
|
this.addFirstListener( "addLayer", this.addLayer, this );
|
243
|
|
244
|
/**
|
245
|
* Method to remove a Layer from the LayerList
|
246
|
* @param layerName the Layer to be deleted
|
247
|
*/
|
248
|
this.deleteLayer = function(objRef, layerName) {
|
249
|
var deletedNode = objRef.getLayer(layerName);
|
250
|
if (!deletedNode) {
|
251
|
alert("node note found; unable to delete node:"+layerName);
|
252
|
return;
|
253
|
}
|
254
|
deletedNode.parentNode.removeChild(deletedNode);
|
255
|
objRef.modified = true;
|
256
|
}
|
257
|
this.addFirstListener( "deleteLayer", this.deleteLayer, this );
|
258
|
|
259
|
/**
|
260
|
* Method to move a Layer in the LayerList up
|
261
|
* @param layerName the layer to be moved
|
262
|
*/
|
263
|
this.moveLayerUp = function(objRef, layerName) {
|
264
|
var movedNode = objRef.getLayer(layerName);
|
265
|
var sibNode = movedNode.selectSingleNode("following-sibling::*");
|
266
|
if (!sibNode) {
|
267
|
alert("can't move node past beginning of list:"+layerName);
|
268
|
return;
|
269
|
}
|
270
|
movedNode.parentNode.insertBefore(sibNode,movedNode);
|
271
|
objRef.modified = true;
|
272
|
}
|
273
|
this.addFirstListener( "moveLayerUp", this.moveLayerUp, this );
|
274
|
|
275
|
/**
|
276
|
* Method to move a Layer in the LayerList down
|
277
|
* @param layerName the layer to be moved
|
278
|
*/
|
279
|
this.moveLayerDown = function(objRef, layerName) {
|
280
|
var movedNode = objRef.getLayer(layerName);
|
281
|
var listNodeArray = movedNode.selectNodes("preceding-sibling::*"); //preceding-sibling axis contains all previous siblings
|
282
|
var sibNode = listNodeArray[listNodeArray.length-1];
|
283
|
if (!sibNode) {
|
284
|
alert("can't move node past beginning of list:"+layerName);
|
285
|
return;
|
286
|
}
|
287
|
movedNode.parentNode.insertBefore(movedNode,sibNode);
|
288
|
objRef.modified = true;
|
289
|
}
|
290
|
this.addFirstListener( "moveLayerDown", this.moveLayerDown, this );
|
291
|
|
292
|
/**
|
293
|
* Adds a node to the Context document extension element. The extension element
|
294
|
* will be created if it doesn't already exist.
|
295
|
* @param extensionNode the node to be appended in the extension element.
|
296
|
* @return the ndoe added to the extension element
|
297
|
*/
|
298
|
this.setExtension = function(extensionNode) {
|
299
|
var extension = this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:Extension");
|
300
|
if (!extension) {
|
301
|
var general = this.doc.selectSingleNode("/wmc:ViewContext/wmc:General");
|
302
|
var newChild = createElementWithNS(this.doc,"Extension",'http://www.opengis.net/context');
|
303
|
extension = general.appendChild(newChild);
|
304
|
}
|
305
|
return extension.appendChild(extensionNode);
|
306
|
}
|
307
|
|
308
|
/**
|
309
|
* Returns the contents of the extension element
|
310
|
* @return the contents of the extension element
|
311
|
*/
|
312
|
this.getExtension = function() {
|
313
|
return this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:Extension");
|
314
|
}
|
315
|
|
316
|
/**
|
317
|
* Parses a Dimension element from the Context document as a loadModel listener.
|
318
|
* This results in an XML structure with one element for each GetMap time value
|
319
|
* parameter and added to the Context extrension element.
|
320
|
* @param objRef a pointer to this object
|
321
|
*/
|
322
|
this.initTimeExtent = function( objRef ) {
|
323
|
//only the first one selected is used as the timestamp source
|
324
|
//var extentNode = objRef.doc.selectSingleNode("//wmc:Layer/wmc:Dimension[@name='time']");
|
325
|
//TBD: how to deal with multiple time dimensions in one context doc, or caps doc?
|
326
|
var timeNodes = objRef.doc.selectNodes("//wmc:Dimension[@name='time']");
|
327
|
for (var i=0; i<timeNodes.length; ++i) {
|
328
|
var extentNode = timeNodes[i];
|
329
|
objRef.timestampList = createElementWithNS(objRef.doc,"TimestampList",mbNsUrl);
|
330
|
var layerName = extentNode.parentNode.parentNode.selectSingleNode("wmc:Name").firstChild.nodeValue;
|
331
|
objRef.timestampList.setAttribute("layerName", layerName);
|
332
|
//alert("found time dimension, extent:"+extentNode.firstChild.nodeValue);
|
333
|
var times = extentNode.firstChild.nodeValue.split(","); //comma separated list of arguments
|
334
|
for (var j=0; j<times.length; ++j) {
|
335
|
var params = times[j].split("/"); // parses start/end/period
|
336
|
if (params.length==3) {
|
337
|
var start = setISODate(params[0]);
|
338
|
var stop = setISODate(params[1]);
|
339
|
var period = params[2];
|
340
|
var parts = period.match(/^P((\d*)Y)?((\d*)M)?((\d*)D)?T?((\d*)H)?((\d*)M)?((.*)S)?/);
|
341
|
for (var i=1; i<parts.length; ++i) {
|
342
|
if (!parts[i]) parts[i]=0;
|
343
|
}
|
344
|
//alert("start time:"+start.toString());
|
345
|
do {
|
346
|
var timestamp = createElementWithNS(objRef.doc,"Timestamp",mbNsUrl);
|
347
|
timestamp.appendChild(objRef.doc.createTextNode(getISODate(start)));
|
348
|
objRef.timestampList.appendChild(timestamp);
|
349
|
|
350
|
start.setFullYear(start.getFullYear()+parseInt(parts[2],10));
|
351
|
start.setMonth(start.getMonth()+parseInt(parts[4],10));
|
352
|
start.setDate(start.getDate()+parseInt(parts[6],10));
|
353
|
start.setHours(start.getHours()+parseInt(parts[8],10));
|
354
|
start.setMinutes(start.getMinutes()+parseInt(parts[10],10));
|
355
|
start.setSeconds(start.getSeconds()+parseFloat(parts[12]));
|
356
|
//alert("time:"+start.toString());
|
357
|
} while(start.getTime() <= stop.getTime());
|
358
|
|
359
|
} else {
|
360
|
//output single date value
|
361
|
var timestamp = createElementWithNS(objRef.doc,"Timestamp",mbNsUrl);
|
362
|
timestamp.appendChild(objRef.doc.createTextNode(times[j]));
|
363
|
objRef.timestampList.appendChild(timestamp);
|
364
|
}
|
365
|
}
|
366
|
objRef.setExtension(objRef.timestampList);
|
367
|
}
|
368
|
}
|
369
|
this.addFirstListener( "loadModel", this.initTimeExtent, this );
|
370
|
|
371
|
/**
|
372
|
* Returns the current timestamp value.
|
373
|
* @param layerName the name of the Layer from which the timestamp list was generated
|
374
|
* @return the current timestamp value.
|
375
|
*/
|
376
|
this.getCurrentTimestamp = function( layerName ) {
|
377
|
var index = this.getParam("timestamp");
|
378
|
return this.timestampList.childNodes[index].firstChild.nodeValue;
|
379
|
}
|
380
|
}
|
381
|
|