Snippets

Created by Marcel Kocisek last modified
/*
	ol control Edit Tool
	*/
	.ol-editTool{
		top: 95px;
		left: 8px;
	}
	.ol-editTool button:first-child{
		-webkit-border-radius: 2px 2px 0px 0px;
		-moz-border-radius: 2px 2px 0px 0px;
		-ms-border-radius: 2px 2px 0px 0px;
		-o-border-radius: 2px 2px 0px 0px;
		border-radius: 2px 2px 0px 0px;
	}
	.ol-editTool button{
		-moz-border-radius: 0px 0px 0px 0px;
		-webkit-border-radius: 0px 0px 0px 0px;
		-o-border-radius: 0px 0px 0px 0px;
		-ms-border-radius: 0px 0px 0px 0px;
		border-radius: 0px 0px 0px 0px;
	}
	.ol-editTool button:last-child{
		-webkit-border-radius: 0px 0px 2px 2px;
		-moz-border-radius: 0px 0px 2px 2px;
		-ms-border-radius: 0px 0px 2px 2px;
		-o-border-radius: 0px 0px 2px 2px;
		border-radius: 0px 0px 2px 2px;
	}
	.ol-point{
		background-color: #212121;
		width: 6px;
		height: 6px;
		-webkit-border-radius: 3px;
		-moz-border-radius: 3px;
		-ms-border-radius: 3px;
		-o-border-radius: 3px;
		border-radius: 3px;
	}
	.ol-point:first-child{
		margin-left:21%;
	}
	.ol-point:last-child{
		margin-left:55%;
	}
	.ol-line{
		background-color: #212121;
		width: 53%;
		height: 2px;
		transform: rotate(65deg);
		margin: -5px auto;
	}
	.ol-line:after{
		content: "";
		display: inline-block;
		background-color: inherit;
		width: 96%;
		height: inherit;
		transform: rotate(85deg);
		margin: 7px;
	}
	.ol-polygon{
		width: 35%;
		height: 70%;
		background-color: #212121;
		margin: 0px 20%;
	}
	.ol-polygon:after{
		content: "";
		background-color: inherit;
		display: block;
		height: 33%;
		width: 170%;
	}
goog.provide('ol.control.EditTool');
goog.require('ol.interaction.Draw');
goog.require('ol.control.Control');
goog.require('ol.source.Vector');
goog.require('ol.geom.GeometryType');
goog.require('ol.source.Vector');
goog.require('goog.object');
goog.require('goog.events');
goog.require('goog.array');
goog.require('goog.dom');
	/**
	Create edit tools with buttons for writing point, line and polygon. Buttons for removing and adding (empty) vector layers.
	@param {Object} options:
		selectInteraction {ol.interaction.Select|undefined}
		controlClass {string=} defeault options: ol-editTool ol-unselectable ol-control 
		pointTitle {string=} default is Point
		lineTitle {string=} defalt is Line
		polygonTitle {string=} default is Polygon
		target {Element|string|undefined} Specify a target if you want the control to be rendered outside of the map's viewport.
	@extends {ol.control.Control}
	@constructor
	*/
	ol.control.EditTool = function(options){
		var options = options || {};
		// for editing title in layer switcher "U+270E"
		// --create buttons for editing enabling
		var pointBtn = goog.dom.createDom('button', {'title': options.pointTitle || 'Point', 'name': 'Point'}, goog.dom.createDom('div', {'class': 'ol-point'}), goog.dom.createDom('div', {'class': 'ol-point'}));
		var lineBtn = goog.dom.createDom('button', {'title': options.lineTitle || 'Line', 'name': 'LineString'}, goog.dom.createDom('div', {'class': 'ol-line'}));
		var polygonBtn = goog.dom.createDom('button', {'title': options.polygonTitle || 'Polygon', 'name': 'Polygon'}, goog.dom.createDom('div', {'class': 'ol-polygon'}));
		var container = goog.dom.createDom('div', {'class': options.controlClass || "ol-editTool ol-unselectable ol-control"}, pointBtn, lineBtn, polygonBtn); // --append container for buttons and checkboxes
		goog.base(this, {
			element: container,
			target: options.target
		});
		var btnArr = [pointBtn, lineBtn, polygonBtn];
		var geometriesArr = [ol.geom.GeometryType.POINT,ol.geom.GeometryType.LINE_STRING, ol.geom.GeometryType.POLYGON];
		// --def new vector layer as container
		/**
		type {ol.source.Vector}
		*/
		var sourcesArr = [new ol.source.Vector(), new ol.source.Vector(), new ol.source.Vector()];
		/**
		Select interaction to toggle acitve
		*/
		this.selectInteraction = options.selectInteraction || null;	
		/**
		@type
		Main object for delete layers and start and stop interactions:
			ol.geom.GeometryType : {Array.<ol.interaction.Draw, ol.layer.Vector>}
		*/
		this.configObject = {};
		for(var i = 0; i < 3; i++){ // --for 
			var geometryType = geometriesArr[i];
			var button = btnArr[i];
			var draw = new ol.interaction.Draw({
				source: sourcesArr[i],
				type: /** @type {ol.geom.GeometryType} */ geometryType
			});
			draw.setActive(false);
			// draw.once('change:active', this.toggleSelect, this); // --event toggle select interction in map defined as options.selectInteraction
			var layer = new ol.layer.Vector({
				source: sourcesArr[i],
				title: "Draw " + geometryType
			});
			goog.object.set(this.configObject, geometryType, [draw, layer]);
			//draw.setActive(false);
			// this.layersArr.push(layer);
			// this.interactionArr.push(draw);
			goog.events.listen(button, goog.events.EventType.CLICK, this.startDrawing, false, this);
			goog.events.listen(button, [goog.events.EventType.FOCUSOUT, goog.events.EventType.MOUSEOUT], function() {
				this.blur();
			}, false);
		}
	}
	goog.inherits(ol.control.EditTool, ol.control.Control);
	/**
	Toggle select interaction.
	@param active {boolean} set this as active
	@this {ol.control.EditTool}
	*/
	ol.control.EditTool.prototype.toggleSelect = function(active){	
		var select = this.selectInteraction;
		if(select){
			select.setActive(active);
		}
	}
	/**
	If interactions to drawing are not in map, add it. Initial state.
	*/
	ol.control.EditTool.prototype.initial = function(){
		var map = this.getMap();
		goog.object.forEach(this.configObject, function(e){
			map.addInteraction(e[0]);
		});
	}
	ol.control.EditTool.prototype.clearInteractions = function(){
		var map = this.getMap();
		goog.object.forEach(this.configObject, function(e){
			map.removeInteraction(e[0]);
		});
	}
	/**
	Disable interactions and remove empty layers added to map with edit buttons. If interaction is added to map, active event dont fire, so
	must disable select interaction.
	@param {ol.interaction.Draw}
	*/
	ol.control.EditTool.prototype.dissableEmpty = function(draw){
		var map = this.getMap();
		var active = draw.getActive(); // --inow is active
		if(!draw.getMap()){ // --if interaction not in map --true --add --all draw interactions
			this.initial();
		}
		goog.object.forEach(this.configObject, function(e){
			var layer = e[1];
			var drawToUnactive = e[0];
			if(goog.getUid(draw) !== goog.getUid(drawToUnactive)){ // --if --not draw to add, set active to false
				drawToUnactive.setActive(false);
				if(goog.array.isEmpty(layer.getSource().getFeatures())){ // --if empty layer without features
					map.removeLayer(layer);
				}
			}else{ // draw to add or remove
				if(drawToUnactive.getActive()){ // is active, i now that deactivate
					if(goog.array.isEmpty(layer.getSource().getFeatures())){ // --if empty layer without features
						map.removeLayer(layer);
					}
				}else{//not active
					var inMap = goog.array.findRight(map.getLayers().getArray(), function(l){ // --if layer not in map --true add it
						return goog.getUid(l) === goog.getUid(layer);
					});
					if(!inMap){
						map.addLayer(layer);
					}
				}
			}
		});
		draw.setActive(!active);
		map.set("editing", !active); // dissable editing attribute in ol.Map
		this.toggleSelect(active); 
	}
	ol.control.EditTool.prototype.startDrawing = function(e){
		var buttonName = e.currentTarget.name;
		var type = this.configObject[buttonName];
		var draw = type[0];
		var layerToAdd = type[1];
		this.dissableEmpty(draw);
	}
/*
Style for layer switcher.
*/
.ol-border-grey{
		border: solid 1px #AEA6A6
}
.ol-layerSwitcher{
		color:#212121;
		right:.5em;
		top:.5em;
		width:45%;
		overflow:hidden;
		max-width:36px;
	  -webkit-transition: max-width 300ms linear;
	  -moz-transition: max-width 300ms linear;
	  -o-transition: max-width 300ms linear;
	  -ms-transition: max-width 300ms linear;
	  transition: max-width 300ms linear;
	}
	.ol-layerSwitcher:not(.ol-collapsed){
		background:rgba(234, 233, 233, 0.8);
		height:auto;
		max-width:1000px;
	}
	.ol-layerSwitcher button{
		float:right;
		background-image: url("icons/maps-and-geolocation-layers-icon.png");
		background-repeat: no-repeat;
		background-position:center;
		width:34px;
		height:34px;
	}
	/* .ol-layerSwitcher > ul{
		margin-left:20px;
	} */
	.ol-layerSwitcher li:not(#header-layer-li){
		white-space: nowrap;
		cursor:pointer;
		margin:.1em 0px;
		padding:1%;
		clear: both;
		overflow: hidden;
		background-color: rgba(255, 255, 255, 0.3); 
		-webkit-transition: background-color 400ms linear;
	  -moz-transition: background-color 400ms linear;
	  -o-transition: background-color 400ms linear;
	  -ms-transition: background-color 400ms linear;
	  transition: background-color 400ms linear;
	}
	.ol-layerSwitcher li:not(#header-layer-li):hover{
		/* color: #AEA6A6; */
		background-color:#DBDBDB
	}
	.ol-layerSwitcher li:hover #ol-layerSwitcher-buttons > #ol-selecter{
		background-color:#3BD748;
	}
	.ol-layerSwitcher li:hover #ol-layerSwitcher-buttons > .ol-layerSwitcher-remove{
		background-color:#FF8282;
	}
	.ol-layerSwitcher li#header-layer-li{
		line-height: 30px;
		height: 34px;
		font-size:1.2em;
		color:#605E5E;
		white-space:nowrap;
	}
	.ol-layerSwitcher span#header-layer{
		display: inline-block;
		vertical-align: middle;
	}
	.ol-layerSwitcher span#layer-title{
		font-size:.9em;
		margin-left:4%;
	}
	.ol-layerSwitcher.ol-collapsed > ul{
		display:none;
	}
	.ol-layerSwitcher-button{
		background-color:#AEA6A6;
		margin-left: 2%;
		float:left;
		font-size: 0.9em;
		border:none
	}
	.ol-layerSwitcher-remove:hover{
		background-color: #FFCACA !important;
	}
	#ol-selecter:hover{
		background-color:#8CEF94 !important;
	}
	#ol-scroll-layers{
		overflow-x:hidden; overflow-y: auto; width: 100%; max-height: 222px;
	}
goog.provide('ol.control.LayerSwitcher');
goog.require('ol.control.Control');
goog.require('ol.source.Vector');
goog.require('ol.layer.Group');
goog.require('goog.events');
goog.require('goog.dom');
goog.require('goog.dom.classlist');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.array');
goog.require('goog.object');
	/**
	@consructor
	@extends {ol.control.Control}
	@param {Object} opt_options:
	target (Element|undefined), 
	selectInteraction (ol.interaction.Select), 
	tipLabel (string=) or text Layers, 
	selectValue (string=) or text Select
	buttonCreator (function=) empty function with ol.control.LayerSwitcher in this,
		parameters: actual layer, element with buttons to layer, layers of layer group (if undefined null), actual layer group.
	buttonCreator_this
	*/
	ol.control.LayerSwitcher = function(opt_options){
		var options = opt_options || {};
		var tipLabel = options.tipLabel || 'Layers';
		var button = goog.dom.createDom('button', { // --var button for layers
			'type': 'button',
			'title': tipLabel
		});
		var headerLi = goog.dom.createDom('li', {'id':'header-layer-li', 'class': 'grey-font'}, goog.dom.createDom('span', {id:'header-layer'}, goog.dom.createTextNode(tipLabel)));
		this.layersUl = goog.dom.createDom('ul', {'id': 'ol-scroll-layers'});
		var mainUl = goog.dom.createDom('ul', null, headerLi, this.layersUl); // -def ul with layers
		goog.events.listen(button, goog.events.EventType.CLICK, this.makeClick_, false, this);
		goog.events.listen(button, [goog.events.EventType.FOCUSOUT, goog.events.EventType.MOUSEOUT], function() {
		/**
		For uncolored button after mouseout
		*/
			this.blur();
		}, false);
		var container = goog.dom.createDom('div', {'class': "ol-layerSwitcher ol-unselectable ol-control ol-collapsed"}, button, mainUl); // --append container for li layers and button
		goog.events.listen(button, goog.events.EventType.CLICK, this.makeClick_, false, this);
		goog.base(this, {
			element: container,
			render: ol.control.LayerSwitcher.render,
			target: options.target
		});
		this.buttonCreator = options.buttonCreator || function(){};
		this.buttonCreator_this = options.buttonCreator_this || this;
		this.selectValue = options.selectValue || 'Select';
		this.removeValue = options.selectValue || 'Remove';
		this.selectInteraction = options.selectInteraction;
	    this.result = [];
	    this.UIDs = [];
		this.layersUIDs = {};
		this.cursorLayerGroup = null;
	}
	goog.inherits(ol.control.LayerSwitcher, ol.control.Control);
	/**
	* @param {ol.MapEvent} mapEvent Map event.
	* @this {ol.control.LayerSwitcher}
	* @api
	*/
	ol.control.LayerSwitcher.render = function(MapEvent){
		this.updateLayers(MapEvent.map);
		this.result.length = 0;
	    this.UIDs.length = 0;
		this.cursorLayerGroup = null;
	}
	/**
	Function to display layers (if ol-collapsed).
	*/
	ol.control.LayerSwitcher.prototype.makeClick_ = function(e){
		goog.dom.classlist.toggle(this.element,'ol-collapsed');
		goog.dom.classlist.toggle(this.element,'ol-border-grey');
	}
	/**
	Select features to ol.interaction.Select defined in options. 
	@param layer {array.ol.layer.Layer}
	*/
	ol.control.LayerSwitcher.prototype.selectFeaturesFromLayer = function(layer){
		var selectedFeatures = this.selectInteraction.getFeatures(); // --var select interaction ol.Collection 
		for(var i = 0, ii=layer.length; i < ii; i++){
			var featuresInLayer = layer[i].getSource().getFeatures(); // --var features in layer source
			var arrFeatures = selectedFeatures.getArray();
			featuresInLayer.forEach(function(e, i){
				var element = e;
				if(goog.array.every(arrFeatures, function(e,i){ // --if --not find feature with UID in selected features --then push feature from layer to selected
					return goog.getUid(element) !== goog.getUid(e);
				})){
					selectedFeatures.push(element); 
				};
			});
		}
	}
	/**
	Create select button and bind in to layer or layergroup. Validating for exitistence of ol.source.Vector in layer array.
	@param layer {Array.ol.layer.Layer}
	@param {element} to append the button
	@param {Array.<ol.layer.Layer>}layersOfGroup to check, if its some vectors to select button
	@param {ol.layer.Group||null} on button remove
	*/
	ol.control.LayerSwitcher.prototype.createButtons = function(layer, parentElement, layersOfGroup, layerGroup){
		var closeButton = goog.dom.createDom('input', {'type': 'button', 'class': 'ol-layerSwitcher-button ol-layerSwitcher-remove', 'value': this.removeValue});
		goog.events.listen(closeButton, goog.events.EventType.CLICK, function(e){
			/**
			If layerGroup, remove from layer group, else from map.
			*/
			if(layerGroup){
				layerGroup.getLayers().remove(layer); // remove layer from layer group --if its child of layergroup
			}else{
				this.getMap().removeLayer(layer);
			}
		}, false, this);
		var validVectorLayers = goog.array.filter(layersOfGroup || [layer], function(e,i,o){
			if(e instanceof ol.layer.Group){
				return true;
			}else{
				return e.getSource() instanceof ol.source.Vector;
			}
		});
		if(validVectorLayers.length > 0){ // - if vector, push buttons
			var sButton = goog.dom.createDom('input', {'id':'ol-selecter', 'class': 'ol-layerSwitcher-button', 'type':'button', 'value': this.selectValue});
			goog.events.listen(sButton, goog.events.EventType.CLICK, function(e){
				e.preventDefault();
				this.selectFeaturesFromLayer(validVectorLayers);
			}, false, this);
			goog.dom.appendChild(parentElement, sButton);
		}
		goog.dom.appendChild(parentElement, closeButton); // append closing button to li
	}
	/**
	Add li element with layer tools to the ul. Extend object with active layers -> test if active layers contains oldLayer UID -> 
	if not, remove li element with layer.
	@param map {ol.Map}
	*/
	ol.control.LayerSwitcher.prototype.updateLayers = function(map){
		var layers = map.getLayers();
	    this.findNewLayers(layers);
	    var actualLayers = this.layersUIDs;
	        goog.array.forEach(goog.object.getKeys(actualLayers), function(e,i,o){ // --if layer in layerSwither --not --in actual layers UIDs --remove
				var key = e;
				if(!goog.array.some(this.UIDs, function(element,i,o){
					return element === key;
				})){
					goog.dom.removeNode(actualLayers[e]);
					goog.object.remove(actualLayers, e);
	            }
		}, this);
		this.addLayers();
	}
        /**
	 find new layers in map and return position of this layer in standard object. All founded UIDs of layers push to this.UIDs array.
	 After its possible to compare with this.layerUIDs object if layer exists or no.
	 -- filter for new layers
	 */
        ol.control.LayerSwitcher.prototype.findNewLayers = function(layers, opt_array){
	    var news = opt_array || this.result;
	    var layerss = layers.getArray();
	    var len = layers.getLength(); 
	    for(var i = len - 1; i >= 0; --i){
			var layer = layerss[i];
			var layerUID = goog.getUid(layer).toString(); // --var get uid of layer/layer collection to test, if we dont have this layer in map
			var obj = {"l": layer, "child":[], "newvalue": true, "layerGroup": false};
			this.UIDs.push(layerUID);
			if(layer instanceof ol.layer.Group){
				goog.object.set(obj, "layerGroup", true);
				if(goog.object.containsKey(this.layersUIDs, layerUID)){
					goog.object.set(obj, "newvalue", false);
				}
				news.push(obj); // set if layer group, but attribute newvalue if false, so not to render
				this.findNewLayers(layer.getLayers(), obj["child"]);
			}else{
				if(!goog.object.containsKey(this.layersUIDs, layerUID)){
					news.push(obj);
				}
			}
	    }
	}
	/**
	Replace ol.dom.Input
	@param input {DOM} checkbox
	@param layer {ol.layer.Layer}
	*/
	ol.control.LayerSwitcher.prototype.checking = function(input, layer){
		goog.dom.setProperties(input, {"checked": layer.getVisible()});
		goog.events.listen(input, goog.events.EventType.CHANGE, function(e){
			var checked = e.target.checked;
			if (checked !== layer.getVisible()) {
				layer.setVisible(checked);
			}
		});
		layer.on('change:visible', function(){
			var visible = this.getVisible();
			if (visible !== input.checked) {
				input.checked = visible;
			}
		});
	}
	/**
	Add li element and tools for layers (buttons ...), recursively self call if found something @param newLayersArray {Array}
	@param newLayersArray {Array}
	*/
	ol.control.LayerSwitcher.prototype.addLayers = function(opt_newLayersArray, opt_ul){
		goog.array.forEach(opt_newLayersArray || this.result, function(e, i, a){
		/**
		@this {ol.control.LayerSwitcher}
		*/
		var layer = e["l"];
		if(e["newvalue"]){
			var inputVisible = goog.dom.createDom('input', {'type': 'checkbox'});
			var layerName = goog.dom.createDom('span', {'id':'layer-title'}); // layer title text
			var buttoncontainer = goog.dom.createDom('div', {'id': 'ol-layerSwitcher-buttons'});
		    var li = goog.dom.createDom('li', null, inputVisible, layerName, buttoncontainer); // --var main li element to which append
			this.checking(inputVisible, layer);
		    goog.object.set(this.layersUIDs, goog.getUid(layer), li); // set uid to uids object defined in constructor
		    goog.dom.insertChildAt(opt_ul || this.layersUl, li, i); // --append to opt_ul element on the strict place depended on i --not this ul element of ol.control.LayerSwitcher
		    if(e["layerGroup"]){ // --if layer group --true self call --not add layer to ul
				if(!opt_newLayersArray){ // -- if recusrsion
					this.cursorLayerGroup = null;
				}
				var childUl = goog.dom.createDom('ul');
				this.createButtons(layer, buttoncontainer, layer.getLayers().getArray(), this.cursorLayerGroup); // --function create button for selecting features from group
				this.buttonCreator.call(this.buttonCreator_this, layer, buttoncontainer, layer.getLayers().getArray(), this.cursorLayerGroup);
				goog.dom.setTextContent(layerName, layer.get("title") || "Layer Group " + (i + 1));
				goog.dom.appendChild(li, childUl);
				this.cursorLayerGroup = layer;
				this.addLayers(e["child"], childUl) // --call recursivly function for Layer group with ul, also with layer group (layer)
		    }else{ // --not layergroup
				goog.dom.setTextContent(layerName, layer.get("title") || "Layer " + (i + 1));
				this.createButtons(layer, buttoncontainer, null, this.cursorLayerGroup);
				this.buttonCreator.call(this.buttonCreator_this, layer, buttoncontainer, null, this.cursorLayerGroup);
		    }
		}else{ // --not new
		    var li = goog.object.get(this.layersUIDs, goog.getUid(e["l"]));
		    if(layer instanceof ol.layer.Group){ // --if layer group --true self call --not add layer to ul
				this.addLayers(e["child"], li.querySelector("ul")) // --call recursivly function for Layer group with ul
		    }
		}
	}, this);
}
goog.provide('ol.format.Ows');
goog.require('ol.format.XML');
goog.require('ol.format.XSD');
goog.require('ol.xml');
goog.require('ol.extent');
goog.require('goog.dom.xml');
	/**
	For ows format with projection definition.
	@constructor 
	@param proj {ol.proj.ProjectionLike}
	@extends {ol.format.XML}
	*/
	ol.format.Ows = function(proj){
		this.projection = goog.isDef(proj) ? proj : "EPSG:4326";
		this.dimensions = "2";
		/**
		@type
		@api
		*/
		this.attr = {
			"crs": this.projection,
			"dimensions": this.dimensions
		}
		goog.base(this);
	}
	goog.inherits(ol.format.Ows, ol.format.XML);
	ol.format.Ows.EX_BBOXPUSHER = function(node, value, objectStack){
	    var corner = value.join(" ");
		ol.format.XSD.writeStringTextNode(node, corner); // into lower and upper we push ol.Coordinates joined with space.
	}
	ol.format.Ows.BBOX_SERIALIZER = ol.xml.makeStructureNS(
        [null, 'http://www.opengis.net/ows/1.1'], {
      'LowerCorner': ol.xml.makeChildAppender(ol.format.Ows.EX_BBOXPUSHER),
	  'UpperCorner': ol.xml.makeChildAppender(ol.format.Ows.EX_BBOXPUSHER)
    });
	/**
	Write lower corner and upper corner nodes.
	@param extent {<ol.Extent>}
	@param opt_bboxnode {Node|undefined} if undefined, create ows:BoundingBox element, else append lower corner and upper corner to this node.
	@param opt_objectStack {Array=} if is used in other serializers or empty array.
	@return {node|null|undefined} if opt_bboxnode returns null, extent not array returns undefined, else return ows:BoundingBox node
	@api
	*/
	ol.format.Ows.prototype.writeBoundingBox = function(extent, opt_bboxnode, opt_objectStack){
		if(goog.isArray(extent)){
			var bottomLeft = ol.extent.getBottomLeft(extent);
			var topRight = ol.extent.getTopRight(extent);
		}else{
			return;
		}
		if(goog.isDef(opt_bboxnode)){
			ol.xml.pushSerializeAndPop({node: opt_bboxnode}, ol.format.Ows.BBOX_SERIALIZER,
			ol.xml.NodeCreator, [bottomLeft, topRight], opt_objectStack || [],[["LowerCorner", "http://www.opengis.net/ows/1.1"], ["UpperCorner", "http://www.opengis.net/ows/1.1"]]);
			return null;
		}else{
			var bboxNode = ol.xml.createElementNS('http://www.opengis.net/ows/1.1', 'ows:BoundingBox');
			ol.xml.pushSerializeAndPop({node: bboxNode}, ol.format.Ows.BBOX_SERIALIZER,
			ol.xml.NodeCreator, [bottomLeft, topRight], opt_objectStack || [],[["LowerCorner", "http://www.opengis.net/ows/1.1"], ["UpperCorner", "http://www.opengis.net/ows/1.1"]]);
			goog.dom.xml.setAttributes(bboxNode, this.attr); // attributes to new node
			return bboxNode;
		}
	}
	ol.format.Ows.BBOX_PARSECORNERS = function(node, objectStack){ // read coordinates string and return array of coordinates
		var corner = ol.format.XSD.readString(node);
		var coordinates = corner.split(" ");
		return coordinates;
	}
	ol.format.Ows.BBOX_PARSER = ol.xml.makeParsersNS( // bbox format
		[null, 'http://www.opengis.net/ows/1.1'], {
		'LowerCorner': ol.xml.makeArrayPusher(ol.format.Ows.BBOX_PARSECORNERS),
		'UpperCorner': ol.xml.makeArrayPusher(ol.format.Ows.BBOX_PARSECORNERS)
	});
	ol.format.Ows.BBOX_reader = function(node, objectStack){
		return ol.xml.pushParseAndPop([],
			ol.format.Ows.BBOX_PARSER, node, objectStack);
	}
	
	ol.format.Ows.BBOX_MAINPARSER = ol.xml.makeParsersNS( // bbox format
		[null,'http://www.opengis.net/ows/1.1'], {
		'BoundingBox': ol.xml.makeObjectPropertySetter(ol.format.Ows.BBOX_reader)
	});
	/**
	@param node {Node} BoundingBox node with LowerCorner and Upper corner or node with Bounding Box element as child element.
	@return {object} 
	@api
	*/
	ol.format.Ows.prototype.readBoundingBox = function(node){	
		if(node.localName !== 'BoundingBox'){
			return ol.xml.pushParseAndPop({},ol.format.Ows.BBOX_MAINPARSER, node, []);
		}else{
			var bboxarr = ol.xml.pushParseAndPop([],ol.format.Ows.BBOX_PARSER, node, []);
			return {'BoundingBox':bboxarr};
		}
	};
	goog.exportProperty(ol.format.Ows.prototype,'writeBoundingBox', ol.format.Ows.prototype.writeBoundingBox);
	goog.exportProperty(ol.format.Ows.prototype,'readBoundingBox', ol.format.Ows.prototype.readBoundingBox);
	goog.exportSymbol('ol.format.Ows.attr', ol.format.Ows.attr);
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
goog.provide('ol.format.WPS');
goog.require('ol.format.XML');
goog.require('ol.xml');
goog.require('ol.format.XSD');
goog.require('ol.format.GML');
goog.require('ol.format.WFS');
goog.require('ol.format.GeoJSON');
goog.require('ol.format.WKT');
goog.require('ol.format.Ows');
goog.require('goog.asserts');
goog.require('goog.object');
goog.require('goog.array');
goog.require('goog.dom');
goog.require('goog.dom.xml');
	/**
	@consructor
	@extends {ol.format.XML}
	*/
	ol.format.WPS = function(){ 
		// --for jquery parsers not now this.url = options.url ? options.url : null;
		goog.base(this);
		this.process = null;
		this.desc_process = null;
	} 
	goog.inherits(ol.format.WPS, ol.format.XML);
		  // namespaces -----------------------------------------------------------------------
		  ol.format.WPS.GMLNS = [null, 'http://www.opengis.net/gml'];
		   ol.format.WPS.NAMESPACE_URIS_ = [null,'http://www.opengis.net/wps/1.0.0', 'http://www.opengeospatial.net/wps'];
		  ol.format.WPS.NAMESPACE_URIS_OWS_ = [null, 'http://www.opengis.net/ows/1.1', 'http://www.opengeospatial.net/ows'];
		  ol.format.WPS.NAMESPACE_URIS_ALL_ = [null, 'http://www.opengis.net/ows/1.1','http://www.opengis.net/wps/1.0.0'];
		  ol.format.WPS.NAMESPACE_NOTHING_ = [null];
		  
		  // get capabilities parser
		  ol.format.WPS.describeObj = { // object for parsing identifier... of som process, inputs...
		   'Identifier': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
			'Title': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
			'Abstract': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString)
			}
		  // proces capabilities format ol --------------------------------------------------------------------
		    ol.format.WPS.PROCESS_DESC_formatS_ = ol.xml.makeParsersNS( // proces offerings format
			ol.format.WPS.NAMESPACE_URIS_OWS_, ol.format.WPS.describeObj);    
		ol.format.WPS.parseProcess = function(node, objectStack){
		    return ol.xml.pushParseAndPop({},
			     ol.format.WPS.PROCESS_DESC_formatS_, node, objectStack);
		   }  
		  ol.format.WPS.PROCESS_formatS_ = ol.xml.makeParsersNS( // proces offerings format
			ol.format.WPS.NAMESPACE_URIS_, {
			'Process': ol.xml.makeArrayPusher(ol.format.WPS.parseProcess)
			});
		ol.format.WPS.readProces = function(node, objectStack){
		   return ol.xml.pushParseAndPop([],
			    ol.format.WPS.PROCESS_formatS_ , node, objectStack);
		}
		   ol.format.WPS.PROCESSOFF_formatS_ = ol.xml.makeParsersNS( // proces offerings parser
			   ol.format.WPS.NAMESPACE_URIS_, {
			   'ProcessOfferings': ol.xml.makeObjectPropertySetter(ol.format.WPS.readProces)
			}); 
			// --section --name describe process parser ol -----------------------------------------------------------------------------
                   // allowed values      
	   ol.format.WPS.ALLOWED = ol.xml.makeParsersNS( // proces input format - allowed
			ol.format.WPS.NAMESPACE_URIS_OWS_, {
			'Value': ol.xml.makeArrayPusher(ol.format.XSD.readValue) 			
			});
		
		ol.format.WPS.readAllowed = function(node, objectStack){
		    return ol.xml.pushParseAndPop([], ol.format.WPS.ALLOWED, node, objectStack)
		}
		            // data type
		ol.format.WPS.readDataType = function(node, objectStack){
		    var topush = node.getAttribute('ows:reference') && {'reference':node.getAttribute('ows:reference'), 'format': ol.format.XSD.readString(node)} || ol.format.XSD.readString(node);
			return topush;
			}
		ol.format.WPS.LiteralDataDESC  = ol.xml.makeParsersNS( // proces input parser - Literal data
			ol.format.WPS.NAMESPACE_URIS_OWS_, { // TREBA DOROBIT UOMS!!!!!!!!!!!!!!!
			'DataType': ol.xml.makeObjectPropertySetter(ol.format.WPS.readDataType),
			'AnyValue': ol.xml.makeObjectPropertySetter(ol.format.XSD.trueReturner),
			'AllowedValues': ol.xml.makeObjectPropertySetter(ol.format.WPS.readAllowed),
            'DefaultValue': ol.xml.makeObjectPropertySetter(ol.format.XSD.readValue) 			
			});
           // complex Data	
        ol.format.WPS.COMPLEXDATA_FORMAT_READER = ol.xml.makeParsersNS( // proces input format - Complex Data - Format - MimeType
			ol.format.WPS.NAMESPACE_NOTHING_, {
			'MimeType': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
            'Encoding': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
            'Schema': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString)			
			});
	   ol.format.WPS.readFormatCapabilities = function(node, objectStack){
	         return ol.xml.pushParseAndPop({}, ol.format.WPS.COMPLEXDATA_FORMAT_READER, node, objectStack);   
	   }	
	        // Bbox complex data
	   ol.format.WPS.readCRSs = function(node, objectStack){
	       var crs = ol.xml.makeParsersNS( // proces input parser - Complex Data - Format
			ol.format.WPS.NAMESPACE_NOTHING_, {
            'CRS': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString)		
			});
          return ol.xml.pushParseAndPop({}, crs, node, objectStack);   			
	   }
       ol.format.WPS.COMPLEXDATA_FORMAT = ol.xml.makeParsersNS( // proces input parser - Complex Data - Format
			ol.format.WPS.NAMESPACE_NOTHING_, {
			'Format': ol.xml.makeArrayPusher(ol.format.WPS.readFormatCapabilities),
            'CRS': ol.xml.makeArrayPusher(ol.format.XSD.readString),
            'CRSsType': ol.xml.makeArrayPusher(ol.format.WPS.readCRSs)			
			});
       ol.format.WPS.formatReader = function(node, objectStack){
	      return ol.xml.pushParseAndPop([], ol.format.WPS.COMPLEXDATA_FORMAT, node, objectStack); 
	   }			
	   ol.format.WPS.COMPLEXDATA = ol.xml.makeParsersNS( // proces input parser - Complex Data
			 ol.format.WPS.NAMESPACE_URIS_OWS_, {
			'Default': ol.xml.makeObjectPropertySetter(ol.format.WPS.formatReader),
            'Supported': ol.xml.makeObjectPropertySetter(ol.format.WPS.formatReader) 			
			});  
            // input description			
	   ol.format.WPS.readComplexBBOXData = function(node, objectStack){
		   return ol.xml.pushParseAndPop({}, ol.format.WPS.COMPLEXDATA, node, objectStack);   
		}			
		ol.format.WPS.readLiteralData = function(node, objectStack){
		     return ol.xml.pushParseAndPop({}, ol.format.WPS.LiteralDataDESC, node, objectStack);
		}
		ol.format.WPS.INPUT_OUTPUT_DESC_formatS_ = ol.xml.makeParsersNS( // proces input format
			ol.format.WPS.NAMESPACE_URIS_OWS_,{
			  'Identifier': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
			'Title': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
			'Abstract': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
			'LiteralData': ol.xml.makeObjectPropertySetter(ol.format.WPS.readLiteralData),
			'ComplexData': ol.xml.makeObjectPropertySetter(ol.format.WPS.readComplexBBOXData),
			'BoundingBoxData': ol.xml.makeObjectPropertySetter(ol.format.WPS.readComplexBBOXData),
			'ComplexOutput': ol.xml.makeObjectPropertySetter(ol.format.WPS.readComplexBBOXData),
			'BoundingBoxOutput': ol.xml.makeObjectPropertySetter(ol.format.WPS.readComplexBBOXData),
            'LiteralOutput': ol.xml.makeObjectPropertySetter(ol.format.WPS.readLiteralData)			
			});    
		ol.format.WPS.readInputDescription = function(node, objectStack){
		    return ol.xml.pushParseAndPop({'max':node.getAttribute('maxOccurs'), 
			                           'min':node.getAttribute('minOccurs')}, ol.format.WPS.INPUT_OUTPUT_DESC_formatS_, node, objectStack);	
		}   
		ol.format.WPS.readOutputDescription = function(node, objectStack){ // output description
		     return ol.xml.pushParseAndPop({}, ol.format.WPS.INPUT_OUTPUT_DESC_formatS_, node, objectStack);
		}
		ol.format.WPS.INPUTS_OUTPUTS_format_ = ol.xml.makeParsersNS( //  make object in array of inputs
			ol.format.WPS.NAMESPACE_NOTHING_, {
			'Input': ol.xml.makeArrayPusher(ol.format.WPS.readInputDescription),
			'Output': ol.xml.makeArrayPusher(ol.format.WPS.readOutputDescription) 
			});    		
        ol.format.WPS.readInputsOutputs = function(node, objectStack){
		    return ol.xml.pushParseAndPop([], ol.format.WPS.INPUTS_OUTPUTS_format_, node, objectStack);
		}
		ol.format.WPS.DESCPROCES_DESC_formatS_ = ol.xml.makeParsersNS( // proces dexription format
			ol.format.WPS.NAMESPACE_URIS_OWS_, {
			'Identifier': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
			'Title': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
			'Abstract': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
			'DataInputs': ol.xml.makeObjectPropertySetter(ol.format.WPS.readInputsOutputs),
			'ProcessOutputs': ol.xml.makeObjectPropertySetter(ol.format.WPS.readInputsOutputs)
			});    
		ol.format.WPS.parseDescription = function(node, objectStack){
		    return ol.xml.pushParseAndPop({},
			     ol.format.WPS.DESCPROCES_DESC_formatS_, node, objectStack);
		   }  
		   ol.format.WPS.PROCESDESC_formatS_ = ol.xml.makeParsersNS( // make item in array on each proces description
			   ol.format.WPS.NAMESPACE_URIS_, {
			   'ProcessDescription': ol.xml.makeObjectPropertyPusher(ol.format.WPS.parseDescription, 'ProcessDescriptions')
			});
			//-----------------end of formats -----------------------------------
		 	ol.format.WPS.readFromNode = {
			"getCapabilities":function(node, objectStack){
			       return ol.xml.pushParseAndPop({},
			         ol.format.WPS.PROCESSOFF_formatS_, node, objectStack);						 
			},
			"describeProcess":function(node, objectStack){
			      if(node.firstChild.localName === "ProcessDescription"){ 
				   return ol.xml.pushParseAndPop({'ProcessDescriptions':[]},
			         ol.format.WPS.PROCESDESC_formatS_, node, objectStack);		
				  }else{
			      	return ol.format.WPS.parseDescription(node, objectStack);	
                    }					 
			}
		}
		/**
		DEPRACTED BY PRODUCTION.
		*/
		
		/** Parse getCapabilities to JSON.
		* @param {Object} options:
		* doc (Document): xml doc
		* node (Node): node with capabilities
		* @notypecheck
		*/
        ol.format.WPS.prototype.readGetCapabilities = function(options){
			goog.asserts.assertObject(options);
			if(goog.isDef(options.doc)){
			    this.process = ol.format.WPS.readFromNode["getCapabilities"](options.doc.firstChild, []); 
			}
			if(goog.isDef(options.node)){
			    this.process = ol.format.WPS.readFromNode["getCapabilities"](options.node, []); 
			}
			return this.process;
		}; 		
	    /**
		Read describe process wps response and convert it to object.
		@param {Object} options: 
		doc(Document|undefined)
		node(Node|undefined)
		oneprocessoutput {boolean=} if I have one process output, I wanna return only first object with output, not all object)
		@return Describe proces object
		*/
		ol.format.WPS.prototype.readDescribeProcess = function(options){
			goog.asserts.assertObject(options);
			var oneprocessoutput = options["oneprocessoutput"] == null ? true : false;
			if(goog.isDef(options.doc)){
			    this.desc_process = ol.format.WPS.readFromNode["describeProcess"](options.doc.firstChild, []); 
			}
			else if(goog.isDef(options.node)){
				this.desc_process = ol.format.WPS.readFromNode["describeProcess"](options.node, []);
			}else{
			    return false;
			}
			if(this.desc_process["ProcessDescriptions"] && this.desc_process["ProcessDescriptions"].length < 2 && oneprocessoutput){
				return this.desc_process["ProcessDescriptions"][0];
			}else{
				return this.desc_process;
			}
		}
		
			
	      /* writing features to execute proces
		    inputs: featureCollection or feature
              		  
		  */
		
					 // end of parser
		// opt object to execute process
		/**
		Options object for writing execute xml.
		*/
		  ol.format.WPS.OPT_OBJECT_write = {
		     "BBOXCOMPLEX_value": "value",
			 "LiteralData": "LiteralData",
			 "BBOX_Data": "BoundingBoxData",
			 "ComplexData": "ComplexData",
			 "ComplexOutput": "ComplexOutput",
			 "BBOX_Output": "BoundingBoxOutput",
			 "LiteralData_Output": "LiteralOutput",
			 "OutputsTypes": function(){return [this["BBOX_Output"], this["ComplexOutput"], this["LiteralData_Output"]]}, // array of names of outputs types
			 "InputsTypes": function(){return [this["LiteralData"],this["ComplexData"],this["BBOX_Data"]]},
			 "object_keys_support": !!Object.keys,
			 "default":"none" // --def value for which nothing write to Input
		  } 
	ol.format.WPS.EX_objectKeysReturner = function(obj){
		var exobject_keys = ol.format.WPS.OPT_OBJECT_write["object_keys_support"] ? Object.keys(obj) : goog.object.getKeys(obj); // loop cez "ComplexData atd."
		return exobject_keys;
	}
		// ------------------------ WRITING EXECUTE XML------------------------------------ //
	    // functions for create Elements
	  ol.format.WPS.writeExecuteNode = function(simple_execute){// method for creating header Execute element - simple to wps:Body and header not simple
		       var Execute = ol.xml.createElementNS('http://www.opengis.net/wps/1.0.0', 'wps:Execute'); // prvy tag wps:Execute hlavickovy
			   ol.xml.setAttributeNS(Execute, "http://www.w3.org/2001/XMLSchema-instance", "xsi:schemaLocation", "http://www.opengis.net/wps/1.0.0 " + "http://schemas.opengis.net/wps/" + "1.0.0/wpsAll.xsd");
			   Execute.setAttribute("version", "1.0.0");
			   Execute.setAttribute("service", "WPS");
			   if(!simple_execute){
               // Execute.setAttribute("xmlns:wfs", "http://www.opengis.net/wfs/1.1.0");
			   ol.xml.setAttributeNS(Execute, "http://www.w3.org/2000/xmlns/", "xmlns:wfs", "http://www.opengis.net/wfs/1.1.0");
			   // Execute.setAttribute("xmlns:ows", "http://www.opengis.net/ows/1.1");
			   ol.xml.setAttributeNS(Execute, "http://www.w3.org/2000/xmlns/", "xmlns:ows", "http://www.opengis.net/ows/1.1");
			   // Execute.setAttribute("xmlns:gml", "http://www.opengis.net/gml");
			   ol.xml.setAttributeNS(Execute, "http://www.w3.org/2000/xmlns/", "xmlns:gml", "http://www.opengis.net/gml");
			   // Execute.setAttribute("xmlns:ogc", "http://www.opengis.net/ogc");
			   ol.xml.setAttributeNS(Execute, "http://www.w3.org/2000/xmlns/", "xmlns:ogc", "http://www.opengis.net/ogc");
			   // Execute.setAttribute("xmlns:wcs", "http://www.opengis.net/wcs/1.1.1");
			   ol.xml.setAttributeNS(Execute, "http://www.w3.org/2000/xmlns/", "xmlns:wcs", "http://www.opengis.net/wcs/1.1.1");
			   // Execute.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
			   ol.xml.setAttributeNS(Execute, "http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink");
		    }
			return Execute;
		} // we must see, how namespaces are implement in WPS execute.
	
	ol.format.WPS.EX_writeElementIFEXISTS = function(elementName){
	/**
    Check if value in data is null, false, NaN, undefined, null, OPT_OBJECT_write.default - if true return undefined, else return element with elementName  
    @param elementName {string} 
	*/
		return (function(value, objectStack){
		var dataValue = objectStack[objectStack.length - 1]['dataObject'][value][ol.format.WPS.OPT_OBJECT_write["BBOXCOMPLEX_value"]];
		// if input is null, undefined, NaN or OPT_OBJECT_write.default, but is not number 0 (0 is valid value)
		//var features = (objectStack[0].features != null && goog.isArray(objectStack[0].features)) && objectStack[0].features[0];
		if(dataValue && dataValue !== ol.format.WPS.OPT_OBJECT_write["default"] || dataValue === 0){ // --if dataValue --and --not default value defined in OPT --or dataValue --is 0 
			return ol.xml.createElementNS('http://www.opengis.net/wps/1.0.0',elementName);			
		}else{ // --else --return undefined
			return;
		};
	  });
	} 
	ol.format.WPS.EX_GMLGeometryPusher = function(xml, appendNode){
	/**
	@param xml {Node} where find geometry
	@param appendNode {Node} where append geometry element
	*/
		var childrens = goog.dom.getChildren(xml); // childrens of feature members and features
		for(var i = 0, ii = childrens.length; i < ii; i++){
			var geom = goog.dom.findNode(childrens[i], function(n){
				return n.localName === "geometry";
			});
			appendNode.appendChild(geom.firstChild);
		}
	}
	ol.format.WPS.mainConstrunctors = {
		"gmlFormat": new ol.format.GML({featureNS:"http://localhost/OL3", featureType:"wpsapp"}),
		"wfsFormat": new ol.format.WFS(),
		"wktFormat": new ol.format.WKT(),
		"GeoJSONFormat": new ol.format.GeoJSON()
	}
	ol.format.WPS.EX_mimetype_functions = {
	/**
	   What to do with features in specifed format as key. 
	*/
		// "gmlFormat": new ol.format.GML({featureNS:"http://localhost/OL3", featureType:"wpsapp", multiSurface:true, multiCurve:true}), 
	    "gml": function(features, node){
			var gml_xml = ol.format.WPS.mainConstrunctors["gmlFormat"].writeFeaturesNode(features);
			ol.format.WPS.EX_GMLGeometryPusher(gml_xml,node); // push geomery to node
		},
		"wfs-collection": function(features, node){
		    var Collection = ol.xml.createElementNS('http://www.opengis.net/wfs', 'wfs:FeatureCollection');
			// push bounded by to FeatureCollection
			/*pushSerializeAndPop({node: Collection}, ol.format.WPS.GML_boundedBy,
				ol.format.WPS.WPS_EX_IDNODE_FACTORY_, [null], [], [["gml:boundedBy", "http://www.opengis.net/ows/1.1"]]);
			*/
			ol.xml.setAttributeNS(Collection, "http://www.w3.org/2001/XMLSchema-instance", "xsi:schemaLocation", "http://www.opengis.net/wfs " + "http://schemas.opengis.net/wfs/" + "1.1.0/wfs.xsd");
			var gml_xml = ol.format.WPS.mainConstrunctors["gmlFormat"].writeFeaturesNode(features);
			Collection.appendChild(gml_xml);
			node.appendChild(Collection);
		}
	}
	ol.format.WPS.complex_data_attr = {
	    "mimeType": "text/xml; subtype=gml/3.1.1"
	}
	ol.format.WPS.dataType_EX_Convertor = { 
	 /**  
	    functions fo converting datatypes of input OBJ
	 */
		"int": function(node, number){ol.format.XSD.writeIntegerTextNode(node, number);},
		"integer": function(node, number){ol.format.XSD.writeIntegerTextNode(node, number);},
		"double": function(node, number){ol.format.XSD.writeDecimalTextNode(node, number);},
		"decimal": function(node, number){ol.format.XSD.writeDecimalTextNode(node, number);},
		"float":  function(node, number){ol.format.XSD.writeDecimalTextNode(node, number);}
	}
	ol.format.WPS.EX_dataPUSHER = function(node, value, objectStack){
	    var obj = objectStack[objectStack.length - 1];
	    var typeOfData = obj['key']; // complex data ...
		var values = obj['inputObject'][ol.format.WPS.OPT_OBJECT_write["BBOXCOMPLEX_value"]]; // returns value of input, for example: {value:ol.extent} returns ol.extent
		goog.object.remove(obj['inputObject'], ol.format.WPS.OPT_OBJECT_write["BBOXCOMPLEX_value"]);
		var patt = /int$|integer$|double$|float$|decimal$/; // if xs:float or float is true
		var reg = obj['inputObject']['DataType'] && patt.exec(obj['inputObject']['DataType']);
		var Literal_DataType = reg ? reg : null;  
		ol.xml.pushSerializeAndPop({node: node}, ol.format.WPS.EX_INPUTSERIALIZER_DATATYPE_PUSH,
				ol.xml.makeSimpleNodeFactory("wps:" + typeOfData), [[values, Literal_DataType, obj['inputObject']]], objectStack);
	}
	/**
		Returns object with replaced keys to lower based on first place in key´s string. Replace all argument is object which contains keys to replace whole key´s string to lower.
		@param obj {Object}
		@param replaceall_obj{Object|undefined} object contains keys, which replace all key´s string to lower.
	*/
	ol.format.WPS.A_REPLACE_KEYS = function(obj, replaceall_obj){
		goog.asserts.assertObject(obj);
		replaceall_obj = replaceall_obj || {};
		var nob = {};
		var oob = ol.format.WPS.EX_objectKeysReturner(obj), key;
		for(var i = 0, ii = oob.length; i<ii; i++){
			key = oob[i];
			var key_lower = key.toLowerCase();
			var first = key.charAt(0);
			if(first !== first.toLowerCase()){
				if(goog.object.containsKey(replaceall_obj, key_lower)){
					goog.object.set(nob, key_lower, obj[key]);
					continue;
				}else{
					var others = key.slice(1);
					goog.object.set(nob, first.toLowerCase()+others, obj[key]);
				}
			}else{ // if on first place is Lower, simply copy key:value
				goog.object.set(nob, key, obj[key]);
			}
		};
		return nob;
	}
	/**
	@const 
	object to replace all characters to lower
	*/
	ol.format.WPS.EX_COMPLEXDATA_ATTR = {
		'encoding': 1,
		'schema': 1
	};
	ol.format.WPS.EX_COMPLEXDATA_PUSHER = function(node, value, objectStack){
	/**
	Append ComplexData element with geometryin GML or other supported format (wfs-collection) to node.
	*/
		goog.asserts.assertObject(value[0]); // if features Object
		var cloner = goog.object.clone(ol.format.WPS.complex_data_attr);
		var lower = ol.format.WPS.A_REPLACE_KEYS(value[2], ol.format.WPS.EX_COMPLEXDATA_ATTR); // converts input object to lower on the first place MimeType -> mimeType.
		goog.object.extend(cloner,lower);
		var regexped = /gml|wfs-collection/.exec(cloner["mimeType"]);// we must test for feature mimetype
	    goog.dom.xml.setAttributes(node, cloner);
		ol.format.WPS.EX_mimetype_functions[regexped[0]](value[0], node); //value[0] are features in this case
	}
	ol.format.WPS.EX_BBOXCONST = new ol.format.Ows(); //  --new constructor for write and read bbox data
	ol.format.WPS.EX_BBOXDATA_PUSHER = function(node, value, objectStack){
	    /**
		Converts ol.extent in "value" input to LowerCase and UpperCase nodes.
		*/
		goog.asserts.assert(value[0].length === 4);
		var cloner = goog.object.clone(ol.format.WPS.EX_BBOXCONST["attr"]);
		var lower = ol.format.WPS.A_REPLACE_KEYS(value[2], cloner); // converts input object to lower on the first place CRS -> crs.
		goog.object.extend(cloner,lower);
		 // value[0] is ol.extent<Array> in this case
		// set attributes to BBOX element, which are needed
		goog.dom.xml.setAttributes(node, cloner);
		return ol.format.WPS.EX_BBOXCONST.writeBoundingBox(value[0], node, objectStack);
	}
	ol.format.WPS.EX_XSDFORMAT_PUSHER = function(node, value, objectStack){
	    if(ol.format.WPS.dataType_EX_Convertor[value[1]] == null){
			ol.format.XSD.writeStringTextNode(node, value[0]);
		}else{
			ol.format.WPS.dataType_EX_Convertor[value[1]](node, value[0]);
		}
	}
	// methods for input and output
	ol.format.WPS.EX_writeInputOutput = function(node, value, objectStack){
	    /**
		   if input is true, return Input element, else RawDataOutput. Loop trought object keys inputs or outputs.  
		*/
		var ex_object = objectStack[objectStack.length - 1]["executeObject"];
		var object_keys = ol.format.WPS.EX_objectKeysReturner(ex_object),object_val,key;
		for(var i = 0; i < object_keys.length; i++){
		    key = object_keys[i];
			object_val = ex_object[key];
			if(!goog.object.isEmpty(object_val) && goog.array.contains(this["types"], key)){
			    // keys of input = data input Identifier  
				var value_o_keys = ol.format.WPS.EX_objectKeysReturner(object_val);
				// into object stack we send dataInputnode, key (if LiteralData and so on), and identifier of input, which is possible
				var object_to_send = {node: node, 'dataObject': ex_object[key], 'dataObjectKey': key};
				if(this["input"]){// if type is input type 
				  ol.xml.pushSerializeAndPop(object_to_send, ol.format.WPS.EX_INPUTS_OUTPUTSERIALIZER,
					ol.format.WPS.EX_writeElementIFEXISTS("wps:Input")/*if exists or is 0 value, so create Input, elese nothing*/, value_o_keys, objectStack);   // iterate over dataInputs (Identifier), in child appender function for Input - its now value arg
				}else{ // if type is output type - literal data, complex data...
					ol.xml.pushSerializeAndPop(object_to_send, ol.format.WPS.EX_INPUTS_OUTPUTSERIALIZER,
					ol.xml.makeSimpleNodeFactory("wps:RawDataOutput"), value_o_keys, objectStack);   // iterate over dataOutputs (Identifier), in child appender function for Input - its now value arg
				}
			}
		}
	}
	// data output and input
	/* --depracted --merged ol.format.WPS.EX_writeInputOutput
	ol.format.WPS.EX_InputOutput = {
	    "Input": function(node, value, objectStack){
			        var ex_object = objectStack[objectStack.length - 1]["executeObject"];
					// --this var inputTypes = ol.format.WPS.OPT_OBJECT_write.InputsTypes();
					ol.format.WPS.EX_writeInputOutput(node, value, objectStack, [ex_object, inputTypes],  true);
				},
		"Output": function(node, value, objectStack){
		            var ex_object = objectStack[objectStack.length - 1]["executeObject"];
					// --this var outputTypes = ol.format.WPS.OPT_OBJECT_write.OutputsTypes();
					/*var new_arr = [];
					for(var i = 0; i < ex_objectkeys[1].length; i++){
					   if(goog.array.contains(ol.format.WPS.OPT_OBJECT_write.OutputsTypes(), ex_objectkeys[1][i])){
						    new_arr.push(ex_objectkeys[1][i]);
						};
					};
					goog.array.insertAt(ex_objectkeys, new_arr, 1);
					ol.format.WPS.EX_writeInputOutput(node, value, objectStack, [ex_object, outputTypes], false);
				}
			}
	*/
	ol.format.WPS.EX_RAWDATAPUSHER = function(node, value, objectStack){
	/**
	Get object with data for output and push attributes to raw data output node. Write identifier of output to Identifier node.
	*/
	     //goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
		 var outputObject = objectStack[objectStack.length - 1]['dataObject'][value];
		 var cloner = goog.object.clone(ol.format.WPS.EX_BBOXCONST.attr);
		 var lower = ol.format.WPS.A_REPLACE_KEYS(outputObject, cloner); // converts output object to lower on the first place CRS -> crs. 
		 // prida atributy do raw data output node.
		 goog.dom.xml.setAttributes(node, lower);
		 ol.xml.pushSerializeAndPop({node: node}, ol.format.WPS.EX_INPUTSERIALIZER_PUSH,
		 ol.xml.NodeCreator, [value], objectStack,[["ows:Identifier", "http://www.opengis.net/ows/1.1"]]);   // iterate over dataOutputs (Identifier), in child appender function for Input - its now value arg	 
	}	
	ol.format.WPS.EX_INPUTPUSHER = function(node, value, objectStack){
	    var inputDataObject = objectStack[objectStack.length - 1]["dataObject"][value]; // value and format of input 
	    var keyOfDataType = objectStack[objectStack.length - 1]['dataObjectKey']; // Complex data ....
		//var inputobject_keys = ol.format.WPS.OPT_OBJECT_write.object_keys_support ? Object.keys(inputDataObject) : goog.object.getKeys(inputDataObject),key; // loop cez input identifiers"
		var inputValue = inputDataObject[ol.format.WPS.OPT_OBJECT_write["BBOXCOMPLEX_value"]]; // value 
		// ak je value object, tak musi dat Reference, inak Data
		/*if(goog.isObject(inputDataObject[ol.format.WPS.OPT_OBJECT_write["BBOXCOMPLEX_value"]]) && !goog.object.isEmpty(inputDataObject[ol.format.WPS.OPT_OBJECT_write["BBOXCOMPLEX_value"]])){
		    var wps = new ol.format.WPS(); // tu pojde rekuzia na wps:body   ----- DOROBIT!!!
			ol.xml.pushSerializeAndPop({node: node, 'inputObject': inputDataObject, key:keyOfDataType}, ol.format.WPS.EX_INPUTSERIALIZER_PUSH,
				ol.format.WPS.WPS_EX_IDNODE_FACTORY_, [value,value], objectStack, [["ows:Identifier", "http://www.opengis.net/ows/1.1"],["wps:Reference", 'http://www.opengis.net/wps/1.0.0']]); 
		}else{*/
		   ol.xml.pushSerializeAndPop({node: node, 'inputObject': inputDataObject, key:keyOfDataType}, ol.format.WPS.EX_INPUTSERIALIZER_PUSH,
				ol.xml.NodeCreator, [value,value], objectStack, [["ows:Identifier", "http://www.opengis.net/ows/1.1"],["wps:Data", 'http://www.opengis.net/wps/1.0.0']]);
		/*}
		ol.xml.pushSerializeAndPop({node: node, 'dataObject': executeInputObj[key], 'dataObjectKey': key}, ol.format.WPS.EX_INPUTSERIALIZER,
				ol.format.WPS.WPS_EX_IDNODE_FACTORY_, [value], objectStack, [["ows:Identifier", "http://www.opengis.net/ows/1.1"]]);
	*/
	}
	// //gml bounded by creating
		  // /**
	       // <gml:boundedBy><gml:Box>unknown</gml:null></gml:boundedBy>
		   // */
		  // ol.format.WPS.GML_boundedBy = ol.xml.makeStructureNS(
        // ol.format.WPS.GMLNS, {
          // 'boundedBy': ol.xml.makeChildAppender(ol.format.WPS.EX_BBOXPUSHER),
	      // 'Box': ol.xml.makeChildAppender(ol.format.WPS.EX_BBOXPUSHER)
		  // 'coordinates'
        // });
	// execute
	
    ol.format.WPS.EX_INPUTSERIALIZER_DATATYPE_PUSH = ol.xml.makeStructureNS(
        ol.format.WPS.NAMESPACE_URIS_, {
      'LiteralData': ol.xml.makeChildAppender(ol.format.WPS.EX_XSDFORMAT_PUSHER), // rozhodne ktory datovy typ piise 
	  'BoundingBoxData': ol.xml.makeChildAppender(ol.format.WPS.EX_BBOXDATA_PUSHER),
	  'ComplexData': ol.xml.makeChildAppender(ol.format.WPS.EX_COMPLEXDATA_PUSHER)
    });
	ol.format.WPS.EX_INPUTSERIALIZER_PUSH = ol.xml.makeStructureNS(
       ol.format.WPS.NAMESPACE_URIS_ALL_, {
      'Identifier': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
	  'Data': ol.xml.makeChildAppender(ol.format.WPS.EX_dataPUSHER),
	  'Reference': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode)
    });
    ol.format.WPS.EX_INPUTS_OUTPUTSERIALIZER = ol.xml.makeStructureNS(
       ol.format.WPS.NAMESPACE_URIS_, {
      'Input': ol.xml.makeChildAppender(ol.format.WPS.EX_INPUTPUSHER),
	  'RawDataOutput': ol.xml.makeChildAppender(ol.format.WPS.EX_RAWDATAPUSHER)
    });
	ol.format.WPS.WPS_IDSERIALIZER_ = ol.xml.makeStructureNS(
       ol.format.WPS.NAMESPACE_URIS_ALL_, {
      'Identifier': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
	  'DataInputs': ol.xml.makeChildAppender(ol.format.WPS.EX_writeInputOutput, {"input":true, "types": ol.format.WPS.OPT_OBJECT_write["InputsTypes"]()}), // --def -- /n
	  'ResponseForm': ol.xml.makeChildAppender(ol.format.WPS.EX_writeInputOutput, {"input": false, "types": ol.format.WPS.OPT_OBJECT_write["OutputsTypes"]()}) // --def --{} for returning input or output and OutputTypes (BBOX, LITERAL...)
    });
		 /**
		Function for writing XML execute request.
		@param options {Object}:
			objectExecute (Object) configuration object for writing execute XML
				{Identifier, LiteralData {value}, ComplexData {value}, BoundingBoxData {value}}
		*/
          ol.format.WPS.prototype.writeExecute = function(options){
			   goog.asserts.assertObject(options);
			   goog.asserts.assertObject(options["objectExecute"]);
			   this.ExecuteNode = ol.format.WPS.writeExecuteNode();
			   var elements_arr = [["ows:Identifier", "http://www.opengis.net/ows/1.1"], ["wps:DataInputs", 'http://www.opengis.net/wps/1.0.0'], ["wps:ResponseForm", 'http://www.opengis.net/wps/1.0.0']];
			   ol.xml.pushSerializeAndPop( 
                {node: this.ExecuteNode, "executeObject": options["objectExecute"]}, ol.format.WPS.WPS_IDSERIALIZER_,
                           ol.xml.NodeCreator, [options["objectExecute"]["Identifier"], null, null], [], elements_arr);
				//console.log(customer.xmlToString(this.ExecuteNode));
				return this.ExecuteNode;
			}
			
	    // --section --name Output parsers 
		ol.format.WPS.Supported = {
			"gml": function(gmlGeometry){
				var format = ol.format.WPS.mainConstrunctors["gmlFormat"]; // gml
				if(gmlGeometry.localName === "featureMembers"){
					return format.readFeatures(gmlGeometry);
				}
				/**
				Create geometry node and push geometries nodes to this node. Read geometry from created geometry node.
				@param gmlGeometry {node} geometry to parse
				@return ol.Feature
				*/
				var geometryElement = ol.xml.createElementNS("http://www.opengis.net/gml", "geometry");	
				geometryElement.appendChild(gmlGeometry); // append gml result to geometry container
				var olGeometry = format.readGeometryFromNode(geometryElement); // read geometry from geometryElement and reaturns ol.geom	
				var olfeature = new ol.Feature({geometry:olGeometry}); // create ol.Feature
				return olfeature;
			},
			"ows": function(bboxNode){
			/**
			Create extent Array from response of bounding box
			@param bboxNode {node}
			@return {<ol.Extent>|null}
			*/
				if(bboxNode.localName === "BoundingBox"){
					var response = ol.format.WPS.EX_BBOXCONST.readBoundingBox(bboxNode);
				    var bboxarr = response["BoundingBox"];
					var extent = goog.array.join(bboxarr[0], bboxarr[1]);
					return extent;
				}else{
					return null;
				}
			},
			"wfs": function(collectionNode){
			/**
			@param collectionNode {node} WFS collection node
			@return {array.<ol.Feature>}
			*/
				var features = ol.format.WPS.mainConstrunctors["wfsFormat"].readFeatures(collectionNode);
				return features;
			},
			"wkt":function(wktstring){
				var features = ol.format.WPS.mainConstrunctors["wktFormat"].readFeatures(wktstring);
				return features;
			},
			"geojson": function(geojsonObject){
				if(!goog.object.containsKey(geojsonObject, "type")){
					return null;
				}
				var features = ol.format.WPS.mainConstrunctors["GeoJSONFormat"].readFeatures(geojsonObject);
				return features;
			},
			pattNode: /gml|ows|wfs/
		}
		
		/**
		Read response from WPS process (source) and returns ol.Features (Complex Output), ol.Extent (Bounding box output) or string (Literal data output).
		This method supports GML, WKT, GeoJSON and ows:BoundingBox as inputs. More formats you can defined in opt_options (pattNode also for xml formats).
		@param source {Node|string|object.<GeoJSON>} data returned from WPS process
		@param opt_options {Object=} or ol.formatWPS.Supported. If xml formats keys depend on prefix of first node (wfs:FeatureCollection) or namespaceURI. 
		@return {<ol.Feature>|array.<ol.Feature>|<ol.Extent>|string|null}
		@api
		*/
        ol.format.WPS.prototype.readExecuteResponse = function(source, opt_options){
			goog.asserts.assert(source != null);
			var opt = goog.object.clone(ol.format.WPS.Supported);
			if(goog.isDef(opt_options)){
				goog.object.extend(opt, opt_options);
			}// extend a opt object with user define
			// alert(JSON.stringify("JSONNN" + source)); // what
			if(goog.dom.isNodeLike(source)){ // gml, ows, wfs
				var prefixns = opt.pattNode.exec(source.prefix) == null ? opt.pattNode.exec(source.namespaceURI) : opt.pattNode.exec(source.prefix);
				if(prefixns != null){
					//alert(prefixns);
					return opt[prefixns[0]](source); // -- completed Regexped gml, ows or wfs bounding box data. Returns features or extent
				}else{
					return prefixns; // null
				}
			}
			if(goog.isString(source)){
				var featuresorplain;
			    try{
					featuresorplain = opt["wkt"](source);// --completed wkt, or simple string
				}catch(e){
					featuresorplain = source;
				} 
				return featuresorplain;
			}
			if(goog.isObject(source)){
				return opt["geojson"](source)// --completed geojson
			}
			return null; // else return null
		}			
goog.exportProperty(ol.format.WPS.prototype,'readGetCapabilities', ol.format.WPS.prototype.readGetCapabilities);
goog.exportProperty(ol.format.WPS.prototype,'readDescribeProcess', ol.format.WPS.prototype.readDescribeProcess);
goog.exportProperty(ol.format.WPS.prototype,'writeExecute', ol.format.WPS.prototype.writeExecute);
goog.exportProperty(ol.format.WPS.prototype,'readExecuteResponse', ol.format.WPS.prototype.readExecuteResponse);
goog.exportSymbol('ol.format.WPS.EX_objectKeysReturner', ol.format.WPS.EX_objectKeysReturner);

Comments (2)