Project

General

Profile

1
/*
2
License: LGPL as per: http://www.gnu.org/copyleft/lesser.html
3
$Id: Context.js 3887 2008-02-27 18:18:53Z ahocevar $
4
*/
5

    
6
// Ensure this object's dependancies are loaded.
7
mapbuilder.loadScript(baseDir+"/model/ModelBase.js");
8

    
9
/**
10
 * Stores a Web Map Context (WMC) document as defined by the Open Geospatial Consortium
11
 * (http://www.opengeospatial.org/) and extensions the the WMC.
12
 *
13
 * Listeners supported by this model:
14
 * "refresh" called when window parameters (width/height, bbox) are changed
15
 * "hidden" called when visibilty of a layer is changed
16
 *
17
 * @constructor
18
 * @base ModelBase
19
 * @author Cameron Shorter
20
 * @param modelNode Pointer to the xml node for this model from the config file.
21
 * @param parent    The parent model for the object.
22
  *
23
 */
24
function Context(modelNode, parent) {
25
  // Inherit the ModelBase functions and parameters
26
  ModelBase.apply(this, new Array(modelNode, parent));
27

    
28
  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'";
29

    
30
  /**
31
   * Change a Layer's visibility.
32
   * @param layerId  The name of the layer that is to be changed
33
   * @param hidden     String with the value to be set; 1=hidden, 0=visible.
34
   */
35
  this.setHidden=function(layerId, hidden){
36
    // Set the hidden attribute in the Context
37
    var hiddenValue = "0";
38
    if (hidden) hiddenValue = "1";
39

    
40
    var layer = this.getLayer(layerId);
41
    if (layer) layer.setAttribute("hidden", hiddenValue);
42
    // Call the listeners
43
    this.callListeners("hidden", layerId);
44
  }
45

    
46
  /**
47
   * Get the layer's visiblity attribute value.
48
   * @param layerId  The name of the layer that is to be changed
49
   * @return hidden  String with the value; 1=hidden, 0=visible.
50
   */
51
  this.getHidden=function(layerId){
52
    var hidden=1;
53
    var layer = this.getLayer(layerId);
54
    if (layer) hidden = layer.getAttribute("hidden");
55
    return hidden;
56
  }
57

    
58
  /**
59
   * Get the BoundingBox value from the Context document.
60
   * @return BoundingBox array with the sequence (xmin,ymin,xmax,ymax).
61
   */
62
  this.getBoundingBox=function() {
63
    var bbox = new Array();
64
    // Extract BoundingBox from the context
65
    var boundingBox=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:BoundingBox");
66
    bbox[0]=parseFloat(boundingBox.getAttribute("minx"));
67
    bbox[1]=parseFloat(boundingBox.getAttribute("miny"));
68
    bbox[2]=parseFloat(boundingBox.getAttribute("maxx"));
69
    bbox[3]=parseFloat(boundingBox.getAttribute("maxy"));
70
    return bbox;
71
  }
72

    
73
  /**
74
   * Set the BoundingBox element and call the refresh listeners
75
   * @param boundingBox array in the sequence (xmin, ymin, xmax, ymax).
76
   */
77
  this.setBoundingBox=function(boundingBox) {
78
    // Set BoundingBox in context
79
    var bbox=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:BoundingBox");
80
    bbox.setAttribute("minx", boundingBox[0]);
81
    bbox.setAttribute("miny", boundingBox[1]);
82
    bbox.setAttribute("maxx", boundingBox[2]);
83
    bbox.setAttribute("maxy", boundingBox[3]);
84
    // Call the listeners
85
    this.callListeners("bbox", boundingBox);
86
  }
87

    
88
  /**
89
   * Set the BoundingBox element and call the refresh listeners
90
   * @param boundingBox array in the sequence (xmin, ymin, xmax, ymax).
91
   */
92
  this.initBbox=function(objRef) {
93
    // Set BoundingBox in context from URL CGI params
94
    if (window.cgiArgs["bbox"]) {   //set as minx,miny,maxx,maxy
95
      var bbox = window.cgiArgs["bbox"].split(',');
96
      objRef.setBoundingBox(bbox);
97
    }
98
  }
99
  this.addListener( "loadModel", this.initBbox, this );
100
  //this.addListener( "contextLoaded", this.initBbox, this );
101

    
102
  /**
103
   * Set the aoi param and call the refresh listeners
104
   * @param boundingBox array in the sequence (xmin, ymin, xmax, ymax).
105
   */
106
  this.initAoi=function(objRef) {
107
    // Set AOI of context from URL CGI params
108
    if (window.cgiArgs["aoi"]) {      //set as ul,lr point arrays
109
      var aoi = window.cgiArgs["aoi"].split(',');
110
      objRef.setParam("aoi",new Array(new Array(aoi[0],aoi[3]),new Array(aoi[2],aoi[1])));
111
    }
112
  }
113
  this.addListener( "loadModel", this.initAoi, this );
114
  //MA this.addListener( "contextLoaded", this.initAoi, this );
115

    
116
  /**
117
   * Set the Spatial Reference System for the context document.
118
   * @param srs The Spatial Reference System.
119
   */
120
  this.setSRS=function(srs) {
121
    var bbox=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:BoundingBox");
122
    bbox.setAttribute("SRS",srs);
123
    this.callListeners("srs");
124
  }
125

    
126
  /**
127
   * Get the Spatial Reference System from the context document.
128
   * @return srs The Spatial Reference System.
129
   */
130
  this.getSRS=function() {
131
    var bbox=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:BoundingBox");
132
    srs=bbox.getAttribute("SRS");
133
    srs = srs ? srs : 'EPSG:4326';
134
    return srs;
135
  }
136

    
137
  /**
138
   * Get the Projection object from the context document.
139
   * @return Proj Object of  The Spatial Reference System.
140
   */
141
  this.initProj=function(objRef) {
142
    objRef.proj=new OpenLayers.Projection(objRef.getSRS());
143
  }
144
  this.addFirstListener( "loadModel", this.initProj, this );
145

    
146
  /**
147
   * Get the Window width.
148
   * @return width The width of map window from the context document
149
   */
150
  this.getWindowWidth=function() {
151
    var win=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:Window");
152
    return win.getAttribute("width");
153
  }
154

    
155
  /**
156
   * Set the Window width.
157
   * @param width The width of map window to set in the context document
158
   */
159
  this.setWindowWidth=function(width) {
160
    var win=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:Window");
161
    win.setAttribute("width", width);
162
    this.callListeners("resize");
163
  }
164

    
165
  /**
166
   * Get the Window height.
167
   * @return height The height of map window from the context document.
168
   */
169
  this.getWindowHeight=function() {
170
    var win=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:Window");
171
    return win.getAttribute("height");
172
  }
173

    
174
  /**
175
   * Set the Window height.
176
   * @param height The height of map window to set in the context document
177
   */
178
  this.setWindowHeight=function(height) {
179
    var win=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:Window");
180
    win.setAttribute("height", height);
181
    this.callListeners("resize");
182
  }
183

    
184
  /**
185
   * Returns the width/height of the map window as an array
186
   */
187
  this.getWindowSize=function() {
188
    var win=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:Window");
189
    return new Array(win.getAttribute("width"), win.getAttribute("height"));
190
  }
191

    
192
  /**
193
   * Set the Window width and height in one function call to avoid a resize event in between
194
   * setting width and height, because that causes checkBbox to be triggered, which adjusts the
195
   * bbox then when it should not yet be adjusted.
196
   * Added by VTS for dynamic map window resizing (AutoResize tool)
197
   * @param size Size of the map window as (width, height) array
198
   */
199
  this.setWindowSize=function(size) {
200
    var width = size[0];
201
    var height = size[1];
202
    var win=this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:Window");
203
    win.setAttribute("width", width);
204
    win.setAttribute("height", height);
205
    this.callListeners("resize");
206
  }
207

    
208
  /**
209
   * Returns the Layer node with the specified name from the list of nodes
210
   * selected by the nodeSelectXpath from the capabilities doc.
211
   * @param featureName name of the featureType to look up
212
   * @return the Layer node with the specified name.
213
   */
214
  this.getFeatureNode = function(featureName) {
215
    return this.doc.selectSingleNode(this.nodeSelectXpath+"[wmc:Name='"+featureName+"']");
216
  }
217

    
218
  /**
219
   * Returns the serverUrl for the layer passed in as the feature argument.
220
   * @param requestName ignored for context docs (only GetMap supported)
221
   * @param method ignored for context docs (only GET supported)
222
   * @param feature the Layer node from the context doc
223
   * @return URL for the GetMap request
224
   */
225
  this.getServerUrl = function(requestName, method, feature) {
226
    return feature.selectSingleNode("wmc:Server/wmc:OnlineResource").getAttribute("xlink:href");
227
  }
228

    
229
  /**
230
   * Returns the WMS version for the layer passed in as the feature argument
231
   * @param feature the Layer node from the context doc
232
   * @return the WMS GetMap version for the Layer.
233
   */
234
  this.getVersion = function(feature) {
235
    return feature.selectSingleNode("wmc:Server").getAttribute("version");
236
  }
237

    
238
  /**
239
   * Get HTTP method for the specified feature
240
   * @param feature the Layer node from the context doc
241
   * @return the HTTP method to get the feature with
242
   */
243
  this.getMethod = function(feature) {
244
    return feature.selectSingleNode("wmc:Server/wmc:OnlineResource").getAttribute("wmc:method");
245
  }
246

    
247
  /**
248
   * Method to get a list of queryable layers
249
   * @return the list with queryable layers
250
   */
251
  this.getQueryableLayers = function() {
252
    var listNodeArray = this.doc.selectNodes("/wmc:ViewContext/wmc:LayerList/wmc:Layer[attribute::queryable='1']");
253
    return listNodeArray;
254
  }
255

    
256
  /**
257
   * Method to get a list of all layers in the context doc
258
   * TBD: merge this with above, passing queryable as an optional boolean param?
259
   * @return the list with all layers
260
   */
261
  this.getAllLayers = function() {
262
    var listNodeArray = this.doc.selectNodes("/wmc:ViewContext/wmc:LayerList/wmc:Layer");
263
    return listNodeArray;
264
  }
265

    
266
  /**
267
   * Method to get a layer with the specified name in the context doc
268
   * @param layerId the id of the layer to be returned
269
   * @return the list with all layers
270
   */
271
  this.getLayer = function(layerId) {
272
    var layer = this.doc.selectSingleNode("/wmc:ViewContext/wmc:LayerList/wmc:Layer[@id='"+layerId+"']");
273
    if (layer == null) {
274
      layer = this.doc.selectSingleNode("/wmc:ViewContext/wmc:LayerList/wmc:Layer[wmc:Name='"+layerId+"']");
275
    }
276
    //TBD: add in time stamp
277
    return layer;
278
  }
279

    
280
  /**
281
   * Method to get a layer id with the specified id/name in the context doc
282
   * @param layerName the name of the layer of which the id is to be returned
283
   * @return the id of the layer || false
284
   */
285
  this.getLayerIdByName = function(layerName) {
286
    var layer = this.getLayer(layerName);
287
    var id;
288
    if (layer) {
289
      id = layer.getAttribute("id");
290
    }
291

    
292
    return id || false;
293
  }
294

    
295
  /**
296
   * Method to add a Layer to the LayerList
297
   * @param layerNode the Layer node from another context doc or capabiltiies doc
298
   */
299
  this.addLayer = function(objRef, layerNode) {
300

    
301
    var parentNode = objRef.doc.selectSingleNode("/wmc:ViewContext/wmc:LayerList");
302
    parentNode.appendChild(layerNode);
303

    
304
    // Generate layer id if layer doesn't have an id
305
    if (!layerNode.getAttribute("id")) {
306
      var randomNumber = Math.round(10000 * Math.random());
307
      id = Mapbuilder.getProperty(layerNode, "wmc:Name") + "_" + randomNumber; 
308
      layerNode.setAttribute("id", id);
309
    }
310

    
311
    objRef.modified = true;
312
    //objRef.callListeners("refresh");
313
  }
314
  this.addFirstListener( "addLayer", this.addLayer, this );
315

    
316
 /**
317
   * Method to add a Sld tag to the StyleList
318
   * @param layerName the Layer name from another context doc or capabiltiies doc
319
   */
320
  this.addSLD = function(objRef,sldNode) {
321
    // alert("context addSLD : "+objRef.id);
322
    var layerName=Mapbuilder.getProperty(sldNode, "//Name");
323
    var parentNode = objRef.doc.selectSingleNode("//wmc:Layer[wmc:Name='"+layerName+"']");
324
    parentNode.appendChild(sldNode.cloneNode(true));
325
    objRef.modified = true;
326
    var attribs=[];
327
    attribs["sld_body"]=(new XMLSerializer()).serializeToString(objRef.doc.selectSingleNode("//wmc:Layer[wmc:Name='"+layerName+"']/wmc:StyleList/wmc:Style/wmc:SLD/wmc:StyledLayerDescriptor"));
328
	objRef.map.mbMapPane.refreshLayer(objRef.map.mbMapPane,layerName,attribs);
329
	
330
  }
331
  this.addFirstListener( "addSLD", this.addSLD, this );
332

    
333
  /**
334
   * Method to remove a Layer from the LayerList
335
   * @param layerId the Layer to be deleted
336
   */
337
  this.deleteLayer = function(objRef, layerId) {
338
    var deletedNode = objRef.getLayer(layerId);
339
    if (!deletedNode) {
340
      alert(mbGetMessage("nodeNotFound", layerId));
341
      return;
342
    }
343
    deletedNode.parentNode.removeChild(deletedNode);
344
    objRef.modified = true;
345
  }
346
  this.addFirstListener( "deleteLayer", this.deleteLayer, this );
347

    
348
  /**
349
   * Method to move a Layer in the LayerList up
350
   * @param layerId the layer to be moved
351
   */
352
  this.moveLayerUp = function(objRef, layerId) {
353
    var movedNode = objRef.getLayer(layerId);
354
    var sibNode = movedNode.selectSingleNode("following-sibling::*");
355
    if (!sibNode) {
356
      alert(mbGetMessage("cantMoveUp", layerId));
357
      return;
358
    }
359
    movedNode.parentNode.insertBefore(sibNode,movedNode);
360
    objRef.modified = true;
361
  }
362
  this.addFirstListener( "moveLayerUp", this.moveLayerUp, this );
363

    
364
  /**
365
   * Method to move a Layer in the LayerList down
366
   * @param layerId the layer to be moved
367
   */
368
  this.moveLayerDown = function(objRef, layerId) {
369
    var movedNode = objRef.getLayer(layerId);
370
    var listNodeArray = movedNode.selectNodes("preceding-sibling::*");  //preceding-sibling axis contains all previous siblings
371
    var sibNode = listNodeArray[listNodeArray.length-1];
372
    if (!sibNode) {
373
      alert(mbGetMessage("cantMoveDown", layerId));
374
      return;
375
    }
376
    movedNode.parentNode.insertBefore(movedNode,sibNode);
377
    objRef.modified = true;
378
  }
379
  this.addFirstListener( "moveLayerDown", this.moveLayerDown, this );
380

    
381
  /**
382
   * Adds a node to the Context document extension element.  The extension element
383
   * will be created if it doesn't already exist.
384
   * @param extensionNode the node to be appended in the extension element.
385
   * @return the ndoe added to the extension element
386
   */
387
  this.setExtension = function(extensionNode) {
388
    var extension = this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:Extension");
389
    if (!extension) {
390
      var general = this.doc.selectSingleNode("/wmc:ViewContext/wmc:General");
391
      var newChild = createElementWithNS(this.doc,"Extension",'http://www.opengis.net/context');
392
      extension = general.appendChild(newChild);
393
    }
394
    return extension.appendChild(extensionNode);
395
  }
396

    
397
  /**
398
   * Returns the contents of the extension element
399
   * @return the contents of the extension element
400
   */
401
  this.getExtension = function() {
402
    return this.doc.selectSingleNode("/wmc:ViewContext/wmc:General/wmc:Extension");
403
  }
404

    
405
  /**
406
   * Parses a Dimension element from the Context document as a loadModel listener.
407
   * This results in an XML structure with one element for each GetMap time value
408
   * parameter and added to the Context extrension element.
409
   * @param objRef a pointer to this object
410
   */
411
  this.initTimeExtent = function( objRef ) {
412
    //only the first one selected is used as the timestamp source
413
    //var extentNode = objRef.doc.selectSingleNode("//wmc:Layer/wmc:Dimension[@name='time']");
414
    //TBD: how to deal with multiple time dimensions in one context doc, or caps doc?
415
    var timeNodes = objRef.doc.selectNodes("//wmc:Dimension[@name='time']");
416
    for (var i=0; i<timeNodes.length; ++i) {
417
      var extentNode = timeNodes[i];
418
      objRef.timestampList = createElementWithNS(objRef.doc,"TimestampList",mbNsUrl);
419
      var layerId;
420
      var layerNode = extentNode.parentNode.parentNode;
421
      if (layerNode.selectSingleNode("@id")) {
422
        layerId = Mapbuilder.getProperty(layerNode, "@id");
423
      } else {
424
        layerId = Mapbuilder.getProperty(layerNode, "wmc:Name");
425
      }
426
      objRef.timestampList.setAttribute("layerId", layerId);
427
      //alert("found time dimension, extent:"+getNodeValue(extentNode));
428
      var times = getNodeValue(extentNode).split(",");   //comma separated list of arguments
429
      for (var j=0; j<times.length; ++j) {
430
        var params = times[j].split("/");     // parses start/end/period
431
        if (params.length==3) {
432
          var start = setISODate(params[0]);
433
          var stop = setISODate(params[1]);
434
          var period = params[2];
435
          var parts = period.match(/^P((\d*)Y)?((\d*)M)?((\d*)D)?T?((\d*)H)?((\d*)M)?((.*)S)?/);
436
          for (var i=1; i<parts.length; ++i) {
437
            if (!parts[i]) parts[i]=0;
438
          }
439
          //alert("start time:"+start.toString());
440
          do {
441
            var timestamp = createElementWithNS(objRef.doc,"Timestamp",mbNsUrl);
442
            timestamp.appendChild(objRef.doc.createTextNode(getISODate(start)));
443
            objRef.timestampList.appendChild(timestamp);
444

    
445
            start.setFullYear(start.getFullYear()+parseInt(parts[2],10));
446
            start.setMonth(start.getMonth()+parseInt(parts[4],10));
447
            start.setDate(start.getDate()+parseInt(parts[6],10));
448
            start.setHours(start.getHours()+parseInt(parts[8],10));
449
            start.setMinutes(start.getMinutes()+parseInt(parts[10],10));
450
            start.setSeconds(start.getSeconds()+parseFloat(parts[12]));
451
            //alert("time:"+start.toString());
452
          } while(start.getTime() <= stop.getTime());
453

    
454
        } else {
455
          //output single date value
456
          var timestamp = createElementWithNS(objRef.doc,"Timestamp",mbNsUrl);
457
          timestamp.appendChild(objRef.doc.createTextNode(times[j]));
458
          objRef.timestampList.appendChild(timestamp);
459
        }
460
      }
461
     objRef.setExtension(objRef.timestampList);
462
    }
463
  }
464
  this.addFirstListener( "loadModel", this.initTimeExtent, this );
465
  
466
  /**
467
   * clear the time extent created by initTimeExtent
468
   * @param objRef reference to this model
469
   */
470
  this.clearTimeExtent = function( objRef ) {
471
    var tsList = objRef.timestampList;
472
    if (tsList) {
473
      tsList.parentNode.removeChild(tsList);
474
    }
475
  }
476
  this.addListener("newModel", this.clearTimeExtent, this);
477

    
478
  /**
479
   * Returns the current timestamp value.
480
   * @param layerId the name of the Layer from which the timestamp list was generated
481
   * @return the current timestamp value.
482
   */
483
  this.getCurrentTimestamp = function( layerId ) {
484
    var index = this.getParam("timestamp");
485
    return getNodeValue(this.timestampList.childNodes[index]);
486
  }
487

    
488
  // PL -BRGM
489
  /**
490
   * Change a Layer's opacity
491
   * @param layerId  The name of the layer that is to be changed
492
   * @param Opacity     Value of the opacity
493
   */
494
  this.setOpacity=function(layerId, Opacity){
495
    // Set the hidden attribute in the Context
496
    var layer = this.getLayer(layerId);
497
    if (layer) layer.setAttribute("opacity", Opacity);
498
    // Call the listeners
499
    this.callListeners("opacity", layerId);
500
  }
501

    
502
  /**
503
   * Get the layer's opacity attribute value.
504
   * @param layerId  The name of the layer that is to be changed
505
   * @return hidden  String with the value; 1=hidden, 0=visible.
506
   */
507
  this.getOpacity=function(layerId){
508
    var opacity=1;
509
    var layer = this.getLayer(layerId);
510
    if (layer) opacity = layer.getAttribute("opacity");
511
    return opacity;
512
  }
513
  // PL -END
514
}
(2-2/19)