//#######################################################################################################
//###   CREATED WITHIN THE DIPLOMA THESIS <Default Inheritance for OWL-S, 2007> by Simon Ferndriger   ###
//#######################################################################################################


/* *****************************************************************/
/* LIBRARY (Support functions) *************************************/


/*
	1. OWL
		1.1 Applications
			1.1.0 Get DOMs by Point
			1.1.1 Get DOM-Object by Node-URI
				1.1.1.1 Get DOM-Objects by Point if URI
				1.1.1.2 Get DOM-Objects by Point if BlankNode-URI
					1.1.2.1 Get OWL Objects by Property Via DOM (Helper)
			1.1.2 Get OWL Objects by Property				
			1.1.3 Get OWL Subjects by Property
			1.1.4 Get OWL DataType Object by Property
			1.1.5 Get Elements by NodeType
			
		1.2 Elements
			1.2.1 Normalize URI
			1.2.2 Get Resource-URI by DOM-Object
				1.2.2.1 Get Resource-url by DOM-Object
			1.2.3 Get BlankNode-URI by DOM-Object
			1.2.4 Get Node Identity
				1.2.4.1 Get BlankNode Identity
				1.2.4.2 Get Identity URI by Point
				1.2.4.3 Check if Point has specific URI Identity
			1.2.5 Check element for TagNS and TagName
				1.2.5.1 Check Element Type for a Point
				1.2.5.2 Get One-Of Element Type for a Point
			1.2.6 Get Element Type
			1.2.7 Get ALL Elements By Type
				1.2.7.1 Get All Indirect Elements By Type
		1.3 Document
			1.3.1 Get RDF prefix
		1.4 Create
			1.4.1 Create New OWL Element
			1.4.2 Create New OWL Property
			1.4.3 Create New OWL DataType Property
			
	2. DOM
		2.1 Generation
			2.1.1 Cached XML File Downloading; Returns DOM
				2.1.1.1 Convert XML File into DOM
					2.1.1.1.1 Find and add Imports (if they have the same NS)
				2.1.1.2 Save DOM
			2.1.2 Check whether File exists
		2.2 Elements
			2.2.1 Normalize DOM-Object
		2.3 Storage
			2.3.1 Save New Service
			2.3.2 Save Groundings
		2.4 Information
			2.4.1 Get Default Namespace
			2.4.2 Check if ID already exists
			2.4.3 Check if DOMs are equal
		2.5 Serialization
			2.5.1 Get Serialized DOM by URI
			2.5.2 Get Serialized DOM by DOM
	3. Logfile
		3.1 Write Logfile
			3.1.1 Write Logfile for a DOM Point
		3.2 Write ERROR Logfile
	4. String functions
		4.1 Get URL by valid URI
			4.1.1 Get NS by valid URI
		4.2 Get ID by valid URI
		4.3 Check URI validity
		4.4 Merge two arrays
		4.5 Check Point validiy
		4.6 Get File Name
		4.7 Get New Grounding URI
		4.8 Get URI By Point
		4.9 Generate SESSION ID
		
		
*/

//////////////////////////////////////////////////////////////////////////////////////////
// 1. OWL
//////////////////////////////////////////////////////////////////////////////////////////
/* 1.1 OWL: Applications ****************************************************************/

/* ######################################################################### */
// [OWL App] 1.1.0 Get DOMs by Point
/* ######################################################################### */
function OWL_getDOMsByPoint(Point) {
	
	var DOMs;
	
	switch(Point['type']) {
		
		case 'URI':
			DOMs = OWL_getDOMsByPointIfURI(Point);
			break;
		
		case 'blankNode_URI':
			DOMs = OWL_getDOMSByPointIfBlankNode(Point);
			break;
		
		case 'DOM':
			DOMs = new Array(Point['DOM']);
			break;
			
		default:
			/* Error handling~~~~~~~~~~*/
			error_log('No type given for OWL_getDOMsByPoint()');
			return;
			/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
	}
	
	return DOMs;
}


/* ######################################################################### */
// [OWL App] 1.1.1 Get DOM-Object by Node-URI
/* ######################################################################### */
function OWL_getDOMsByURI(nodeType_NS, nodeType_ID, URI, _optional_isBlankNode) {
	
	var log_level = 2;
	var return_elements = new Array();
	
	// Get DOM
	var url = getURLfromURI(URI);
	if(url)
		DOM = getDOM(url);
	
	/* Error handling~~~~~~~~~~*/
	if(!DOM) {
		error_log('No DOM found for OWL_getDOMsByURI()');
		return;
	}
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
	
	
	var elements = OWL_getAllElementsByType(DOM, nodeType_NS, nodeType_ID);

	// Look for elements with the requested URI identity
	for(var i=0; i<elements.length; i++) {
	
		if(_optional_isBlankNode)
			var cur_URI = OWL_getBlankNodeIdentity(elements[i]);
		else
			var cur_URI = OWL_getNodeIdentityURI(elements[i]);

		if(cur_URI == URI)
			return_elements.push(elements[i]);
	}
	
	// Return Array
	return return_elements;
}


/* ######################################################################### */
// [OWL App] 1.1.1.1 Get DOM-Objects by Point if URI
/* ######################################################################### */
function OWL_getDOMsByPointIfURI(DOMPoint) {

	var log_level = 2;
	var return_DOMs = new Array();
	var URI = DOMPoint['URI'];
	var url = getURLfromURI(URI);

	if(url)
		var DOM = getDOM(url);
	/* Error handling~~~~~~~~~~*/
	else {
		error_log('No DOM found in OWL_getDOMsByPointIfURI()');
		return;
	}
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
		
	
	// Get direct elements which could match
	var direct_elements = new Array();
	
	/* Error handling~~~~~~~~~~*/
	if(!DOMPoint['matchTypes'][0]) {
		error_log('MatchTypes of Point missing.');
		return;
	}
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
	
	for(var i=0; DOMPoint['matchTypes'][i]; i++) {
		
		var parts = DOMPoint['matchTypes'][i].split('#');
	
		/* Error handling~~~~~~~~~~*/
		if(parts.length != 2) {
			error_log('Point match type invalid (URI expected): ' + DOMPoint['matchTypes'][i]);
			return;
		}
		/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
		
		var cur_elements = DOM.getElementsByTagNameNS(parts[0] + '#', parts[1]);
		direct_elements = merge_arrays(direct_elements, cur_elements);
	}

	// Get indirect elements which could match
	var indirect_elements = DOM.getElementsByTagNameNS(_rdf, 'Description');
	var lazy_elements = DOM.getElementsByTagNameNS(_owl, 'Thing');

	// Elements found.....................................
	var elements = merge_arrays(direct_elements, indirect_elements, lazy_elements);

	for(var i=0; i < elements.length; i++) {
		var nodeIdentity = OWL_getNodeIdentityURI(elements[i]);
		if(nodeIdentity == URI)
			return_DOMs.push(elements[i]);
	}
	
	
	// Return elements found..............................
	log(return_DOMs.length + ' DOM object(s) found for: ' + URI, log_level);
	
	if(return_DOMs.length == 0)
		return false;
	
	return return_DOMs;
}

/* ######################################################################### */
// [OWL App] 1.1.1.2 Get DOM-Objects by Point if BlankNode-URI
/* ######################################################################### */
function OWL_getDOMSByPointIfBlankNode(DOMPoint) {
	
	var log_level = 2;
	var return_DOMs = new Array();
	var blankNodeURI = DOMPoint['blankNodeURI'];
	var blankNodeID = getIDfromURI(blankNodeURI);
	var url = getURLfromURI(blankNodeURI);
	var DOM = getDOM(url);
	
	// Looking up different node types which could match with the needed object
	var elements = new Array();
	for(var i=0; i<DOMPoint['matchTypes']; i++) {
		var parts = DOMPoint['matchTypes'][i].split('#');
		var cur_elements = DOM.getElementsByTagNameNS(parts[0] + '#', parts[1]);
		elements = merge_arrays(elements, cur_elements);
	}
	
	// Get indirect elements which could match with the needed object
	var indirect_elements = OWL_getAllIndirectElementsByType(DOM);
	
	
	elements = merge_arrays(elements, indirect_elements);
	if(elements)
		for(var i=0; i < elements.length; i++)
			if(OWL_getNodeID(elements[i]) == blankNodeID)
				return_DOMs.push(elements[i]);
		
	
	// X elements found..............................
	log(return_DOMs.length + 'DOM object(s) found.', log_level);
	
	if(return_DOMs.length == 0)
		return false;
	
	return return_DOMs;
}


/* ######################################################################### */
// [OWL App] 1.1.2 Get OWL Objects by Property
/* ######################################################################### */
function OWL_getObjectsByProperty(subjectPoint, propery_NS, property_ID, _isURL, _isTextDOM) {
	var log_level = 2;
	var return_objects = new Array();
	
	if(!validPoint(subjectPoint))
		return;
	
	// Case 1: Subject is a DOM element with no ID
	if(subjectPoint['type'] == 'DOM') {

		return_objects = OWL_getObjectsByPropertyViaDOM(subjectPoint['DOM'], propery_NS, property_ID, _isURL, _isTextDOM);
	}
	// Case 2: Subject is represented via a URI
	else if(subjectPoint['type'] == 'URI') {
		
		var subjects = OWL_getDOMsByPointIfURI(subjectPoint);

		/* Error handling~~~~~~~~~~*/
		if(!subjects) {
			error_log('No subjects found by URI:' + subjectPoint['URI']);	
			return;
		}
		/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
	
		for(var i=0; subjects[i]; i++) {
			
			var current_objects = OWL_getObjectsByPropertyViaDOM(subjects[i], propery_NS, property_ID, _isURL, _isTextDOM);
			return_objects = merge_arrays(return_objects, current_objects);
		}
		
	}
	// Case 3: Subject is represented via a blank node URI
	else if(subjectPoint['type'] == 'blankNode_URI') {
		
		var subjects = OWL_getDOMSByPointIfBlankNode(subjectPoint);
		
		/* Error handling~~~~~~~~~~*/
		if(!subjects) {
			error_log('No subjects found by blankNode.');
			return;
		}
		/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
		
		for(var i=0; i<subjects.length; i++) {
			
			var current_objects = OWL_getObjectsByPropertyViaDOM(subjects[i], propery_NS, property_ID, _isURL, _isTextDOM);
			return_objects = merge_arrays(return_objects, current_objects);
		}
	}
	/* Error handling~~~~~~~~~~*/
	else {
		error_log('No subject type (DOM or URI) defined in OWL_getObjectsByProperty().');
		return;
	}
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/

	log(return_objects.length + ' object(s) found, using the property: ' + property_ID, log_level);
	if(return_objects.length == 0)
		return false;
		
	return return_objects;
}

/* ######################################################################### */
// [OWL App] 1.1.2.1 Get OWL Objects by Property Via DOM (Helper)
/* ######################################################################### */
function OWL_getObjectsByPropertyViaDOM(subjectDOM, propery_NS, property_ID, _isURL, _isTextDOM) {
	
	var log_level = 2;
	var return_objects = new Array();
	
	// Set DOM Mode..........................................................
	var DOM_Mode = new Object();
	
	if(_isTextDOM) {
		DOM_Mode['nodeType'] = 3;
		DOM_Mode['PointType'] = 'TextDOM';
	}
	else {
		DOM_Mode['nodeType'] = 1;
		DOM_Mode['PointType'] = 'DOM';
	}

	// Subject must have childnodes which represent properties...............
	if(subjectDOM.hasChildNodes()) {

		// Finds all properties, also from deeper levels (which we don't want)
		var possible_properties = subjectDOM.getElementsByTagNameNS(propery_NS, property_ID);

		for(var i=0; i<possible_properties.length; i++) {
			
			// The property is a direct child of the subject: OK good
			if(possible_properties[i].parentNode == subjectDOM) {

				cur_property = possible_properties[i];
				
				// Get different possible matches...................................
				var resource_url = null, resource_URI = null, blankNode_URI = null;
				if(_isURL)
					resource_url = OWL_getResourceURL(cur_property);	
				else {
					resource_URI = OWL_getResourceURI(cur_property);
					blankNode_URI = OWL_getBlankNodeURI(cur_property);
				}
	
				// Object is referred with "rdf:resource=" and is an url.............
				if(_isURL && resource_url) {
					var object = new Object();
					object['type'] = 'url';
					object['url'] = resource_url;
					return_objects.push(object);
					log('Object resource *url* found: ' + resource_url, log_level);
				}
				
				// Object is referred in the property with "rdf:resource="
				else if(resource_URI) {
					var object = new Object();
					object['type'] = 'URI';
					object['URI'] = resource_URI;
					return_objects.push(object);
					log('Object resource URI found: ' + resource_URI, log_level);
				}
				// Object can be found in the <tag> hierarchy
				else if(cur_property.hasChildNodes()) {
					
					var subelement = cur_property.firstChild;
					
					while(subelement) {
					
						var URI = OWL_getNodeIdentityURI(subelement);
						var bn_URI = OWL_getBlankNodeURI(subelement);
						
						// object has an ID
						if(URI) {
							var object = new Object();
							object['type'] = 'URI';
							object['URI'] = URI;
							return_objects.push(object);
							log('Object resource URI found: ' + URI, log_level);
						}
						// object has a blank node ID
						else if(bn_URI) {
							var object = new Object();
							object['type'] = 'blankNode_URI';
							object['URI'] = bn_URI;
							return_objects.push(object);
							log('Object blankNode URI found: ' + bn_URI, log_level);
						}
						// object has NO ID at all and is an element node
						else if(subelement.nodeType == DOM_Mode['nodeType']) {
							var object = new Object();
							object['type'] = DOM_Mode['PointType'];
							object[DOM_Mode['PointType']] = subelement;
							return_objects.push(object);
							log(DOM_Mode['PointType'] + ' object found: ' + subelement, log_level);
						}
						
						subelement = subelement.nextSibling;
					}
				}
				// Object is referred via blank node
				else if(blankNode_URI) {
					var object = new Object();
					object['type'] = 'blankNode_URI';
					object['URI'] = blankNode_URI;
					return_objects.push(object);
					log('Object blankNode URI found: ' + blankNode_URI, log_level);
				}
				else {
					log('No object found', log_level);
				}
			}
			else {
				log('No property found for subject', log_level);	
			}
		}
	}
	else {
		log('Object has no child nodes', log_level);
	}
	
	// Return objects found for one subject element
	return return_objects;
}

/* ######################################################################### */
// [OWL App] 1.1.3 Get OWL Subjects by Property
/* ######################################################################### */
function OWL_getSubjectArrayByProperty(propery_NS, property_ID, objectPoint) {
	

	var log_level = 2;
	
	/* Error handling~~~~~~~~~~*/
	if(objectPoint['type'] != 'URI') {
		error_log('Not supported');
		return;
	}
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
	
	var return_subjects = new Array();
	var URI = objectPoint['URI'];
	var url = getURLfromURI(URI);
	var DOM = getDOM(url);
	
	// Crawling through all properties
	var properties = new Array();
	var properties = DOM.getElementsByTagNameNS(propery_NS, property_ID);
	
	for(var i=0; i<properties.length; i++) {
		
		cur_property = properties[i];
		if(OWL_getResourceURI(cur_property) == URI) {
			
			var parent = cur_property.parentNode;
			
			var IDURI = OWL_getNodeIdentityURI(parent);
			var bn_URI = OWL_getBlankNodeURI(parent);
			
			// object has an ID
			if(IDURI) {
				var subject = new Object();
				subject['type'] = 'URI';
				subject['URI'] = IDURI;
				return_subjects.push(subject);
				log('Subject resource URI found: ' + URI, log_level);
			}
			// object has a blank node ID
			else if(bn_URI) {
				var subject = new Object();
				subject['type'] = 'blankNode_URI';
				subject['URI'] = bn_URI;
				return_subjects.push(subject);
				log('Subject blankNode URI found: ' + bn_URI, log_level);
			}
			// object has NO ID at all
			else {
				var subject = new Object();
				subject['type'] = 'DOM';
				subject['DOM'] = parent;
				return_subjects.push(subject);
				log('DOM subject found: ' + parent, log_level);
			}
		
		}
	}

	log(return_subjects.length + ' subject(s) found, using the property: ' + property_ID, log_level);
	if(return_subjects.length == 0)
		return false;
	return return_subjects;
}

/* ######################################################################### */
// [OWL App] 1.1.4 Get OWL DataType Object by Property
/* ######################################################################### */
function OWL_getDataTypeObjectByProperty(SubjectPoint, propery_NS, property_ID) {
	
	var objects = OWL_getObjectsByProperty(SubjectPoint, propery_NS, property_ID, null, true); // true = 'TextDOM'
	var return_objects = new Array();

	for(var i=0; i<objects.length; i++) {

		switch(objects[i]['type']) {
			case 'TextDOM':
				var parts = objects[i]['TextDOM'].nodeValue.split('^^');
				var object = new Object();
				object['data'] = parts[0];
				object['datatype'] = parts[1];
				
				// < ...rdf:datatype="">123</...>
				if(parts.length == 1)
					object['datatype'] = OWL_getAttribute(objects[i]['TextDOM'].parentNode, _rdf, 'datatype');
					
				return_objects.push(object);
				break;
				
			default:
				/* Error handling~~~~~~~~~~*/
				error_log('Unknown datatype syntax found: ' + objects[i]['type']);
				return;
				/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
		}
	}
	
	// No data found
	if(return_objects.length == 0)
		return false;
	
	return return_objects;
}


/* ######################################################################### */
// [OWL App] 1.1.5 Get Elements by NodeType
/* ######################################################################### */
function OWL_getElementsByNodeType(DOM, NS, ID) {

	var log_level = 2;

	// Simple Syntax................................
	var result_elements = DOM.getElementsByTagNameNS(NS, ID);

	// Complex Syntax................................
	var indirect_elements = OWL_getAllIndirectElementsByType(DOM);
	for(var i=0; i < indirect_elements.length; i++) {
		
		var nodeType = OWL_getElementTypeByDOM(indirect_elements[i]);
		
		if(nodeType == NS + ID)
			result_elements.push(indirect_elements[i]);
	}

	return result_elements;
}


//////////////////////////////////////////////////////////////////////////////////////////
/* 1.2 OWL: Elements ********************************************************************/

function OWL_getID(DOM_obj) {
	return OWL_getAttribute(DOM_obj, _rdf, 'ID');
}
function OWL_getURI(DOM_obj) {
	var ID = OWL_getID(DOM_obj) || OWL_getNodeID(DOM_obj);
	if(ID) return _cur_NS + ID;
	return false;
}
function OWL_getNodeID(DOM_obj) {
	return OWL_getAttribute(DOM_obj, _rdf, 'nodeID');
}
function OWL_getAboutURI(DOM_obj) {
	return  OWL_$(OWL_getAttribute(DOM_obj, _rdf, 'about'), DOM_obj);
}
function OWL_getAttribute(DOM_obj, NS, ID) {
	try { return DOM_obj.getAttributeNodeNS(NS, ID).nodeValue; }catch(e) { return false; }
}
function OWL_getNodeType_byDOM(DOM_obj) {
	return DOM_obj.namespaceURI + DOM_obj.localName;
}


/* ######################################################################### */
// [OWL Element] 1.2.1 Normalize URI
/* ######################################################################### */
function OWL_$(URI, _optional_DOM) {
	
	/* No URI at all */
	if(!URI)
		return false;
	
	/* Wrong syntax */
	if(!validURI(URI))
		return false;

	// Find out current namespace
	/* Used when the URI is relative, i.e. when the URI is an rdf:ID attribute */
	if(_optional_DOM) {
		var xmlNS = getDefaultNamespaceByDOM(_optional_DOM);
	}
	
	/* Local URI */
	if(!getURLfromURI(URI)) {
		
		/* Depreciation handling~~~~*/
		if(!xmlNS) {
			log('------------------------------------------------ Careful: OLD CALL');
			xmlNS = _cur_NS;// For the sake of safety
		}
		/* ~~~~~~~~~~~~~~~~~~~~~~~~*/

		return xmlNS + getIDfromURI(URI);
	}
	
	/* Full URI */
	return URI;
}

/* ######################################################################### */
// [OWL Element] 1.2.2 Get Resource-URI by DOM-Object
/* ######################################################################### */
function OWL_getResourceURI(DOM_obj) {
	var resource_URI = OWL_getAttribute(DOM_obj, _rdf, 'resource');
	return  OWL_$(resource_URI, DOM_obj);
}

/* ######################################################################### */
// [OWL Element] 1.2.2.1 Get Resource-url by DOM-Object
/* ######################################################################### */
function OWL_getResourceURL(DOM_obj) {
	var resource_url = OWL_getAttribute(DOM_obj, _rdf, 'resource');
	return  resource_url;
}


/* ######################################################################### */
// [OWL Element] 1.2.3 Get BlankNode-URI by DOM-Object
/* ######################################################################### */
function OWL_getBlankNodeURI(DOM_obj) {
	
	// Get URI
	var blankNode_ID = OWL_getAttribute(DOM_obj, _rdf, 'nodeID');
	if(blankNode_ID)
		return OWL_$('#' + blankNode_ID, DOM_obj);

	return false;
}

/* ######################################################################### */
// [OWL Element] 1.2.4 Get Node Identity
/* ######################################################################### */
function OWL_getNodeIdentityURI(DOM_obj) {
	
	// Syntax: <... rdf:ID=""...>
	var ID = OWL_getAttribute(DOM_obj, _rdf, 'ID');
	if(ID)
		return OWL_$('#' + ID, DOM_obj);
	
	// Syntax: < rdf:about="">
	var about = OWL_getAboutURI(DOM_obj);

	if(about)
		return about;
	
	// No ID found
	return false;
}

/* ######################################################################### */
// [OWL Element] 1.2.4.1 Get BlankNode Identity
/* ######################################################################### */
function OWL_getBlankNodeIdentity(DOM_obj) {
	
	// Syntax: <... rdf:nodeID=""...>
	var nodeID = OWL_getAttribute(DOM_obj, _rdf, 'nodeID');

	if(nodeID)
		return OWL_$('#' + nodeID, DOM_obj);

	// No nodeID found
	return false;
}

/* ######################################################################### */
// [OWL Element] 1.2.4.2 Get Identity URI by Point
/* ######################################################################### */
function OWL_getIdentityByPoint(Point) {
	
	if(!validPoint(Point))
		return;
	
	/* Error handling~~~~~~~~~~*/
	if(Point['type'] != 'URI') {
		error_log('Element does not have an URI identity.');
		return;
	}
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
	
	return Point['URI'];
}

/* ######################################################################### */
// [OWL Element] 1.2.4.3 Check if Point has specific URI Identity
/* ######################################################################### */
function OWL_checkIdentityForPoint(Point, IdentityURI) {
	
	// No valid Point
	if(!validPoint(Point))
		return;
	
	// Point is not an URI and therefore cannot have an identity
	if(Point['type'] != 'URI')
		return false;
	
	// Return 'true' if the point has the IdentityURI
	return OWL_getIdentityByPoint(Point) == IdentityURI;
}

/* ######################################################################### */
// [OWL Element] 1.2.5 Check element for type
/* ######################################################################### */
function OWL_checkNodeTypeByDOM(DOM, TagNS, TagID) {

	var log_level = 1;
	
	var parent = DOM.parentNode;
	var possible_goals = parent.getElementsByTagNameNS(TagNS, TagID);
	
	for(var i=0; i<possible_goals.length; i++) {
		if(possible_goals[i].isEqualNode(DOM)) {
			
			// Element does have the desired TagNs and TagName
			log('TagCheck successful', log_level);
			return true;
		}
	}
	
	// Element does NOT have the desired TagNs and TagName
	log('TagCheck failed', log_level);
	return false;
}

/* ######################################################################### */
// [OWL Element] 1.2.5.1 Check Element Type for a Point
/* ######################################################################### */
function OWL_checkElementTypeForPoint(Point, elementType_NS, elementType_ID) {

	var log_level = 2;
	
	if(!validPoint(Point))
		return;
	
	// Get possible DOM elements for that point
	Point['matchTypes'] = new Array(elementType_NS + elementType_ID);
	var DOMs = OWL_getDOMsByPoint(Point);
	if(!DOMs)
		return;

	// Checking DOMs for element type.......................................
	for(var i=0; i<DOMs.length; i++) {
		
		var cur_type = OWL_getElementTypeByDOM(DOMs[i]);	
		if(cur_type == elementType_NS + elementType_ID) {
			log('PointCheck succeeded', log_level);
			return true;
		}
	}

	// NOT successfull
	log('PointCheck failed', log_level);
	return false;
}

/* ######################################################################### */
// [OWL Element] 1.2.5.2 Get One-Of Element Type for a Point
/* ######################################################################### */
function OWL_getOneOfPointType(Point, typeURIs) {
	
	for(var i=0; typeURIs[i]; i++)	
		if(OWL_checkElementTypeForPoint(Point, getNSfromURI(typeURIs[i]), getIDfromURI(typeURIs[i])))
			return typeURIs[i];
			
	/* Error handling~~~~~~~~~~*/
	error_log('Type could not be identified.');
	return;
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
}

/* ######################################################################### */
// [OWL Element] 1.2.6 Get Element Type By DOM
/* ######################################################################### */
function OWL_getElementTypeByDOM(DOM) {
	
	var log_level = 2;
	
	/* Error handling~~~~~~~~~~*/
	if(!DOM) {
		error_log('No DOM provided.');
		return;
	}

	// DOM object is not an element
	if(DOM.nodeType != 1) {
		return;
	}
	var nodeType_NS = DOM.namespaceURI;
	var nodeType_ID = DOM.localName;

	/* Error handling~~~~~~~~~~*/
	if(!nodeType_NS || !nodeType_ID) {
		error_log('No valid DOM provided.');
		return;
	}
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
	
	// Complex Syntax <rdf:Description ...> or <owl:Thing>
	if(nodeType_NS + nodeType_ID == _rdf + 'Description' || nodeType_NS + nodeType_ID == _owl + 'Thing') {
		
		var cur_child = DOM.firstChild;
		while(cur_child) {
		
			if(cur_child.namespaceURI == _rdf && cur_child.localName == 'type') {
				
				// Case: Resource
				var resourceURI = OWL_getResourceURI(cur_child);
				if(resourceURI)
					return resourceURI;
				
				// Case: Child
				if(cur_child.hasChildNodes()) {

					tmp_cur_child = cur_child.firstChild;
					while(tmp_cur_child) {
						
						var tmp_NS = tmp_cur_child.namespaceURI;
						var tmp_ID = tmp_cur_child.localName;
						
						if(tmp_NS == _owl && tmp_ID == 'Class') {
							var aboutURI = OWL_getAboutURI(tmp_cur_child);
							if(aboutURI)
								return aboutURI;
						}
						
						tmp_cur_child = tmp_cur_child.nextSibling;
					}
				}
			}
			cur_child = cur_child.nextSibling;
		}
		
		/* Error handling~~~~~~~~~~*/
		log('No node type found', log_level);
		return;
		/* ~~~~~~~~~~~~~~~~~~~~~~~~*/		
	}
	
	// Simple Syntax <Service:Service ...>
	return nodeType_NS + nodeType_ID;
}

/* ######################################################################### */
// [OWL Element] 1.2.7 Get All Elements By Type
/* ######################################################################### */
function OWL_getAllElementsByType(DOM, nodeType_NS, nodeType_ID) {
	
	var direct_elements = DOM.getElementsByTagNameNS(nodeType_NS, nodeType_ID);
	var indirect_elements = DOM.getElementsByTagNameNS(_rdf, 'Description');
	var lazy_elements = DOM.getElementsByTagNameNS(_owl, 'Thing');
	
	return merge_arrays(direct_elements, indirect_elements, lazy_elements);
}

/* ######################################################################### */
// [OWL Element] 1.2.7.1 Get All Indirect Elements By Type
/* ######################################################################### */
function OWL_getAllIndirectElementsByType(DOM) {
	
	var indirect_elements = DOM.getElementsByTagNameNS(_rdf, 'Description');
	var lazy_elements = DOM.getElementsByTagNameNS(_owl, 'Thing');
	
	return merge_arrays(indirect_elements, lazy_elements);
}


/* ######################################################################### */
// [OWL Document] 1.3.1 Get RDF prefix
/* ######################################################################### */
function getRDF_prefix(DOM) {
	
	/* Error handling~~~~~~~~~~*/
	if(!DOM) {
		error_log('No DOM in getRDF_prefix()');
		return;
	}
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
	
	var rdf_prefix = DOM.ownerDocument.documentElement.prefix;
	
	/* Error handling~~~~~~~~~~*/
	if(!rdf_prefix) {
		error_log('No RDF prefix found');
		return;
	}
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
	
	return rdf_prefix;
}

//////////////////////////////////////////////////////////////////////////////////////////
/* 1.4 OWL: Create **********************************************************************/


/* ######################################################################### */
// [OWL Create] 1.4.1 Create New OWL Element
/* ######################################################################### */
function OWL_CreateElement(parentDOM, NS, ID, IdentityURI) {
	
	// Create the element
	var doc = parentDOM.ownerDocument;
	var new_elementNode = doc.createElementNS(NS, ID);
	
	// Append the node
	var appendedElementNode = parentDOM.appendChild(new_elementNode);
	
	// Set the identity
	if(IdentityURI)
		appendedElementNode.setAttributeNS(_rdf, 'about', IdentityURI);
	
	// Return the new element
	return appendedElementNode;
}

/* ######################################################################### */
// [OWL Create] 1.4.2 Create New OWL Property
/* ######################################################################### */
function OWL_CreateProperty(parentDOM, NS, ID, ResourceURI) {
	
	// Create the property
	var doc = parentDOM.ownerDocument;
	var new_propertyNode = doc.createElementNS(NS, ID);
	var appendedPropertyNode = parentDOM.appendChild(new_propertyNode);
	
	// Set the resource and append it to the parent
	if(ResourceURI)
		appendedPropertyNode.setAttributeNS(_rdf, 'resource', ResourceURI);

	return appendedPropertyNode;
}

/* ######################################################################### */
// [OWL Create] 1.4.3 Create New OWL DataType Property
/* ######################################################################### */
function OWL_CreateDataTypeProperty(parentDOM, NS, ID, data, datatype) {
	
	// Create the property
	var doc = parentDOM.ownerDocument;
	var new_propertyNode = doc.createElementNS(NS, ID);
	
	// Set the resource and append it to the parent
	var appendedPropertyNode = parentDOM.appendChild(new_propertyNode);
	appendedPropertyNode.setAttributeNS(_rdf, 'datatype', datatype);

	// Add text value
	var doc = parentDOM.ownerDocument;
	var textNode = doc.createTextNode(data);
	appendedPropertyNode.appendChild(textNode);
}


//////////////////////////////////////////////////////////////////////////////////////////
// 2. DOM
//////////////////////////////////////////////////////////////////////////////////////////
/* 2.1 DOM: Generation ******************************************************************/

/* ######################################################################### */
// [DOM Generation] 2.1.1 Cached XML File Downloading; Returns DOM
/* ######################################################################### */
function getDOM(url, isImportedOntology, _importURLs) {
	var log_level = 1;
	
	// Return current DOM
	if(!url)
		return _cur_DOM;
	
	// Regular proceeding
	log('Download needed: ' + url, log_level);
	var xmlDoc = _loaded_URLs[url];

	
	/***********************************************************
		The template is used for new service construction.
		It gets temporary changed and should therefore never
		be taken from  cache.
	************************************************************/
	var isTemplate = (url == _FIX_storage_path + 'template');
	
	/* A: Content already downloaded into cache */
	if(xmlDoc && !isTemplate) {
		log('Already loaded. Taking file from cache.', log_level);
	}
	/* B: Download the contents of the URL */
	else {
		var a = new AJAX('loadurl.php', null, null, true);
		a.setParameter('url', url);

		a.ontransferstart = function() {
			log('Downloading URL...', log_level);
		}

		// Contents saved in variable 'xml'
		var xml = a.send();

		// Error handling
		if(xml.length == 0) {
			error_log('While loading ' + url);
			return;
		}
		
		// Save downloaded XML document
		log('URL downloaded.', log_level);
		xmlDoc = loadXML(xml);
		
		_loaded_URLs[url] = xmlDoc;
	}

	if(!isImportedOntology) {

		// Set global DOM
		_cur_DOM = xmlDoc;
		
		// Configure new global namespace
		var xmlns = _cur_DOM.getAttribute('xmlns');
		var base = _cur_DOM.getAttribute('xml:base');
		var new_NS;
		
		if(xmlns)
			new_NS = xmlns;
		else if(base)
			new_NS = base + '#';
		
		/* Error handling~~~~~~~~~~*/
		else {
			error_log('No namespace found in: ' + url);
			return;
		}
		/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
		
		// Information
		if(new_NS != _cur_NS)
				log('New default Namespace: ' + new_NS, log_level);
		
		// Set new global namespace
		_cur_NS =  new_NS;

		// Set current url for import management
		_cur_url = url;
	}
	
	// Return DOM....................................
	if(_enable_active_import) {
		return addImports(xmlDoc, _importURLs); // slow
	}
	else
		return xmlDoc; // fast
}

/* ######################################################################### */
// [DOM Generation] 2.1.1.1 Convert XML File into DOM (Helper)
/* ######################################################################### */
function loadXML(xml) {
	var doc = null;

	/* Supported browsers ~~~~~~~~~~
	
		- Mozilla Firefox 2.0
	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	var parser = new DOMParser();
	doc = parser.parseFromString(xml, "text/xml");
	
	/* Returning root Node */
	return doc.documentElement;
}

/* ######################################################################### */
// [DOM Generation] 2.1.1.2 Find and add Imports (if they have the same NS) (Helper)
/* ######################################################################### */
function addImports(DOM, _importURLs) {
	var log_level = 1;
	var return_DOM = DOM;
	var thisURL = DOM.ownerDocument.URL;
	
	// Take from cache...............................................
	if(_imported_URLs[thisURL])
		return _imported_URLs[thisURL];
		
	// Do NOT take from cache........................................
	
	if(!_importURLs)
		_importURLs = new Array(DOM.ownerDocument.URL);

	// Goind through all import statements
	var import_elements = DOM.getElementsByTagNameNS(_owl, 'imports');
	for(var i=0; i<import_elements.length; i++) {
		
		var parentType = OWL_getElementTypeByDOM(import_elements[i].parentNode);
		if(parentType == _owl + 'Ontology') {
			
			var cur_url = OWL_getAttribute(import_elements[i], _rdf, 'resource');

			if(_importURLs.indexOf(cur_url) != -1)
				log('Import url already done.', log_level);
			else if(cur_url) {
				log('Importing: ' + cur_url);
				_importURLs.push(cur_url);
				
				// Loading the imported ontology without doubles
				var cur_import = getDOM(cur_url, true, _importURLs);
				var children = cur_import.childNodes;

				// Importing nodes across two documents
				for(var k=0; children[k]; k++) {
					var newNode = return_DOM.ownerDocument.importNode(children[k], true);
					return_DOM.appendChild(newNode);
				}
			}
		}
	}

	_imported_URLs[thisURL] = return_DOM;
	return return_DOM;
}


/* ######################################################################### */
// [DOM Generation] 2.1.2 Check whether File exists
/* ######################################################################### */
function URL_exists(url) {
	var log_level = 1;
	
	/* Error handling~~~~~~~~~~*/
	if(!url) {
		error_log('No URL provided.' + url, log_level);
		return true;
	}
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/

	var a = new AJAX('loadurl.php', null, null, true);
	a.setParameter('url', url);

	a.ontransferstart = function() {
		log('Try to download URL...', log_level);
	}

	// Contents saved in variable 'xml'
	var file = a.send();

	// URL does NOT exist
	if(file.length == 0)
		return false;
	// URL does exist
	else
		return true;
}

//////////////////////////////////////////////////////////////////////////////////////////
/* 2.2 DOM: Elements ********************************************************************/

function $e(element_name) {// Returns a created HTML element
	return document.createElement(element_name);
}
function $a(attribute_name) {// Returns a created HTML attribute
	return document.createAttribute(attribute_name);
}
function $t(text) {// Returns a created HTML text node
	return document.createTextNode(text);
}

/* ######################################################################### */
// [DOM Element] 2.2.1 Normalize DOM-Object
/* ######################################################################### */
function $(n) {
	if(typeof(n) == 'object')
		return n;

	/* Error handling~~~~~~~~~~*/
	if(typeof(n) != 'string'){
		error_log('No valid DOM-Object. Input must be an object or a string, representing a DOM-Object.');
		return null;
	}
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/

	return document.getElementById(n);
}


//////////////////////////////////////////////////////////////////////////////////////////
/* 2.3 DOM: Storage *********************************************************************/


/* ######################################################################### */
// [DOM Storage] 2.3.1 Save New Service
/* ######################################################################### */
function saveNewService(superserviceDOM, renamings, oldBASE, newBASE) {
	
	var Serializer = new XMLSerializer();
	var serviceDOM = getDOM(newBASE);
	
	/************************************************************************
		Check whether the to-be-saved ontology has its origin on the
		webserver.
		This is necessary, since file-writing-access is needed.
	************************************************************************/
	var parts = newBASE.split('.owl');
	var path =  parts[0].substring(0, parts[0].lastIndexOf('/') + 1);
	if(path != _FIX_storage_path) {
		alert('Cannot save ontology because it is not located on this server (' + _FIX_storage_path + ')');
		return;
	}
	
	// Convert namespace in superservice..........................................................
	var doc = superserviceDOM.ownerDocument;
	var serializedXML = Serializer.serializeToString(doc);
	serializedXML = serializedXML.replace(oldBASE, newBASE, 'g');

	// Perform renamings of rdf:IDs...............................................................
	var rdf_prefix = getRDF_prefix(serviceDOM);
	for(var i=0; i<renamings.length; i++) {
		
		/* rdf:ID */
		var cur_old = ' ' + rdf_prefix + ':ID="' + renamings[i]['oldID'] + '"';
		var cur_new = ' ' + rdf_prefix + ':ID="' + renamings[i]['newID'] + '"';
		serializedXML = serializedXML.replace(cur_old, cur_new, 'g');
		
		/* rdf:about, rdf:resource: NS#ID */
		var cur_old = oldBASE + renamings[i]['oldID'] + '"';
		var cur_new = newBASE + renamings[i]['newID'] + '"';
		serializedXML = serializedXML.replace(cur_old, cur_new, 'g');
		
		/* rdf:about, rdf:resource: #ID */
		var cur_old = '"#' + renamings[i]['oldID'] + '"';
		var cur_new = '"#' + renamings[i]['newID'] + '"';
		serializedXML = serializedXML.replace(cur_old, cur_new, 'g');
	}
	
	// Get superserviceDOM with new namespace and new names.......................................
	var curSESSION_ID = generateSessionID();
	/* Save temp ontology */
	saveXML(serializedXML, '.tmp' + curSESSION_ID);
	/* Read temp ontology */
	var convertedSSDOM = getDOM(_FIX_storage_path + '.tmp' + curSESSION_ID);
	/* Delete temp ontology */
	deleteFile('.tmp' + curSESSION_ID);
	
	// Importing nodes across two documents.......................................................
	var new_children = convertedSSDOM.childNodes;
	var old_children = serviceDOM.childNodes;

	for(var i=0; i<new_children.length; i++) {//*********************************@@@@@ !!!!!
		
		var newNode = serviceDOM.ownerDocument.importNode(new_children[i], true); // true: including subchildren
		
		/********************************************
			Only copy the new nodes. If the profile
			gets interpreted several times, this
			would cause multiple entries otherwise.
		*********************************************/
		var isAlreadyMember = false;
		for(var j=0; old_children[j]; j++)
			if(check_isEqualNode(newNode, old_children[j]))
				isAlreadyMember = true;

		if(!isAlreadyMember)
			serviceDOM.appendChild(newNode);		
	}
	
	
	var doc = serviceDOM.ownerDocument;
	var serializedXML = Serializer.serializeToString(doc);

	// Save File to Server........................................................
	filename = getFileNameByURL(newBASE);
	saveXML(serializedXML, filename);
	
	// Clear cache silently (DOM models need to be updated).......................
	clear_cache(true);
}

/* ######################################################################### */
// [DOM Storage] 2.3.2 Save Groundings
/* ######################################################################### */
function saveNewGroundings(groundings, serviceURI, superserviceURI) {

	var log_level = 1;
	log('Save new Groundings.', log_level);
	
	// No groundings provided
	if(!groundings)
		return;
		
	// Get neccessary variables
	var newServiceBASE = getURLfromURI(serviceURI); /* BASE from the current service */
	var newBASE = _FIX_storage_path + 'Groundings/' + getFileNameByURL(newServiceBASE); /* BASE from the according grounding */
	var oldSuperserviceBASE = getURLfromURI(superserviceURI); /* BASE from the superservice */
	
	// Save all groundings
	for(var i=0; groundings[i]; i++) {
		
		var curXML;
		var oldBASE;
	
		switch(groundings[i]['type']) {
			
			case 'DOM':
				curXML = getSerializedDOM(groundings[i]['DOM']);
				oldBASE = getURLfromURI(getDefaultNamespaceByDOM(groundings[i]['DOM']) + 'dummyID');
				
				break;
				
			case 'URI':
				curXML = getSerializedDOMByURI(groundings[i]['URI' ]);
				oldBASE = getURLfromURI(groundings[i]['URI' ]);
				
				break;
			
			default:
				return;
		}
		
		// Replace BASE of current grounding
		curXML = curXML.replace(oldBASE, newBASE, 'g');
		
		// Replace SuperService BASE of current grounding (old refernces to the service model)
		curXML = curXML.replace(oldSuperserviceBASE, newServiceBASE, 'g');
		
		// Save XML
		log('Grounding saved.', log_level);
		var filename = getFileNameByURL(newServiceBASE);
		saveXML(curXML, filename, true);
	}
}


/* ######################################################################### */
// [DOM Information] 2.4.1 Get Default Namespace
/* ######################################################################### */
function getDefaultNamespaceByDOM(DOM) {
	
	var mainElement = DOM.ownerDocument.documentElement;
	var xmlns = mainElement.getAttribute('xmlns');
	var base = mainElement.getAttribute('xml:base');
	
	if(xmlns)
		return xmlns;
	
	if(base)
		return base + '#';

	/* Error handling~~~~~~~~~~*/
	error_log('No default namespace found');
	return;
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
}

/* ######################################################################### */
// [DOM Information] 2.4.2 Check if ID already exists
/* ######################################################################### */
function checkIfIDExists(URI, id) {
	
	var xmlText = getSerializedDOMByURI(URI);
	var occurencies = new Array('"' + id + '"', '"#' + id + '"', '"' + getNSfromURI(URI) + id + '"');
	
	for(var i=0; occurencies[i]; i++)
		if(xmlText.indexOf(occurencies[i]) != -1)
			// ID does exist in the ontology
			return true;
	
	// ID does NOT exist in the ontology
	return false;
}

/* ######################################################################### */
// [DOM Information] 2.4.3 Check if DOMs are equal
/* ######################################################################### */
function check_isEqualNode(X, Y) {

	var log_level = 1;
	
	log('Testing nodes...................' + X.nodeType + '=?=' + Y.nodeType, log_level);

	// Test NodeType
	if(X.nodeType != Y.nodeType) {
		log('NodeTypes are NOT equal: ' + X.nodeType + '!=' + Y.nodeType, log_level);
		return false;
	}
	
	// Test String Values
	if(X.localName != Y.localName || X.namespaceURI != Y.namespaceURI || X.nodeValue != Y.nodeValue) {
		log('String Values are NOT equal: ' + X.nodeName + ',' + X.localName + ',' + X.namespaceURI + ',' + X.prefix + ',' + X.nodeValue + '!=' + Y.nodeName + ',' + Y.localName + ',' + Y.namespaceURI + ',' + Y.prefix + ',' + Y.nodeValue, log_level);
		return false;
	}
		
	// Test If Attributes
	if(X.hasAttributes() != Y.hasAttributes()) {
		log('hasAttributes() NOT equal: ' + X.hasAttributes() + '!=' + Y.hasAttributes(), log_level);
		return false;
	}
	
	
	// Test Attributes
	if(X.hasAttributes()) {
		if(X.attributes.length != Y.attributes.length) {
			log('attributes.length NOT equal: ' + X.attributes.length + '!=' + Y.attributes.length, log_level);
			return false;
		}
	
		var Xlist = X.attributes;
		var Ylist = Y.attributes;
		
		for(var i=0; i<Xlist.length; i++)
			if(Xlist[i].name != Ylist[i].name || Xlist[i].value != Ylist[i].value) {
				log('Attribute NOT equal: ' + Xlist[i].name + ',' + Xlist[i].value + '!=' + Ylist[i].name + ',' + Ylist[i].value, log_level);
				return false;
			}

	}
		
	
	// Test If Childnodes
	if(X.hasChildNodes() != Y.hasChildNodes()) {
		log('hasChildNodes() NOT equal: ' + X.hasChildNodes() + '!=' + Y.hasChildNodes(), log_level);
		return false;
	}
		
	// Test Childnoes
	if(X.hasChildNodes()) {
		if(X.childNodes.length != Y.childNodes.length) {
			log('childNodes.length NOT equal: ' + X.childNodes.length + '!=' + Y.childNodes.length, log_level);
			return false;
		}
	
		// Test Childnoes
		var Xchildren = X.childNodes;
		var Ychildren = Y.childNodes;
		
		for(var i=0; i<Xchildren.length; i++)
			if(!check_isEqualNode(Xchildren[i], Ychildren[i])) {
				log('subchild is not equal: nr.' + i, log_level);
				return false;
			}
	}

	// Nodes are equal
	log('Nodes are equal', log_level);
	return true;
}

//////////////////////////////////////////////////////////////////////////////////////////
/* 2.5 DOM: Serialization ***************************************************************/

/* ######################################################################### */
// [DOM Serialization] 2.5.1 Get Serialized DOM by URI
/* ######################################################################### */
function getSerializedDOMByURI(URI) {

	var DOM = getDOM(getURLfromURI(URI));
	return getSerializedDOM(DOM);
}

/* ######################################################################### */
// [DOM Serialization] 2.5.2 Get Serialized DOM by DOM
/* ######################################################################### */
function getSerializedDOM(DOM) {

	var Serializer = new XMLSerializer();
	var doc = DOM.ownerDocument;
	
	// Return serialized XML
	return Serializer.serializeToString(doc);
}

//////////////////////////////////////////////////////////////////////////////////////////
// 3. Logfile
//////////////////////////////////////////////////////////////////////////////////////////

function set_global_Logfile_level(level) {
	_current_Logfile_level = level;
}

/* ######################################################################### */
// [Logfile] 3.1 Write Logfile
/* ######################################################################### */
function log(s, importance_level) {
	var output = $('log');

	/* Only requested statements are shown */
	if(!importance_level || importance_level > _current_Logfile_level) {
		output.value += s + '\n';
		
		// Fillup loading info box
		$('current_loading').innerHTML = s.substring(0, 42); + '...';
	}

	/* Scroll to bottom */
	output.scrollTop = output.scrollHeight - output.clientHeight;

	return;
}

/* ######################################################################### */
// [Logfile] 3.1.1 Write Logfile for a DOM Point
/* ######################################################################### */
function logP(Point) {
	
	switch(Point['type']) {
		
		case 'URI':
			return Point['URI'];
		
		case 'blankNode_URI':
			return Point['type'];
			
		case 'DOM':
			return Point['type'];
			
		default:
			/* Error handling~~~~~~~~~~*/
			if(!Point['type'])
				error_log('No (valid) Point!');
			/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
			return '';
	}
}

/* ######################################################################### */
// [Logfile] 3.2 Write ERROR Logfile
/* ######################################################################### */
function error_log(s) {
	log('ERROR: ' + s);
	
	// VISUAL ----------------------------------------------------------------/
	SET_ERROR_Logfile();
}


//////////////////////////////////////////////////////////////////////////////////////////
// 4. String Mutations
//////////////////////////////////////////////////////////////////////////////////////////

/* ######################################################################### */
// [String Mutation] 4.1 Get URL by valid URI
/* ######################################################################### */
function getURLfromURI(URI) {

	if(!validURI(URI))
		return false;

	var parts = URI.split('#');
	return parts[0];
}

/* ######################################################################### */
// [String Mutation] 4.1.1 Get NS by valid URI
/* ######################################################################### */
function getNSfromURI(URI) {

	return getURLfromURI(URI) + '#';
}

/* ######################################################################### */
// [String Mutation] 4.2 Get ID by valid URI
/* ######################################################################### */
function getIDfromURI(URI) {
	
	if(!validURI(URI))
		return;
	
	var parts = URI.split('#');
	return parts[1];
}

/* ######################################################################### */
// [String Mutation] 4.3 Check URI validity
/* ######################################################################### */
function validURI(URI) {
	/* No URI */
	if(!URI)
		return false;

	/* Correct URI */
	try {
		var parts = URI.split('#');
		if(parts.length == 2)
			return true;
	}
	catch(e){}
		
	/* Error handling~~~~~~~~~~*/
	error_log('No valid URI: ' + URI);
	return false;
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
}

/* ######################################################################### */
// [String Mutation] 4.4 Merge two arrays
/* ######################################################################### */
function merge_arrays(array_1, array_2, array_3) {
	
	/*********************************/
	//	Special Case
	if(array_3)
		return merge_arrays(array_1, merge_arrays(array_2, array_3));
	/*********************************/
	
	var result = new Array();
	
	if(array_1) {
		if(array_1.length > 0)
			for(var i=0; i < array_1.length; i++)
				result.push(array_1[i]);
	}
	
	if(array_2) {
		if(array_2.length > 0)
			for(var i=0; i < array_2.length; i++)
				result.push(array_2[i]);
	}
				
	return result;
}


/* ######################################################################### */
// [String Mutation] 4.4 Check Point validity
/* ######################################################################### */
function validPoint(Point) {

	/* Error handling~~~~~~~~~~*/
	if(!Point) {
		error_log('Point missing.');
		return;
	}
	if(!Point['type']) {
		error_log('Point has no type: ' + Point);
		return false;
	}
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
	
	return true;
}


/* ######################################################################### */
// [String Mutation] 4.6 Get File Name -> e.g. 'test.owl'
/* ######################################################################### */
function getFileNameByURL(url) {
	
	var path = url.split('/');
	if(path.length > 0)
		var filename = path[path.length - 1];
		
	/* Error handling~~~~~~~~~~*/
	if(!filename) {
		error_log('No filename found in: ' + url);
		return;
	}
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
	
	return filename;
}

/* ######################################################################### */
// [String Mutation] 4.7 Get New Grounding URI
/* ######################################################################### */
function getNewGroundingsURI(oldGroundingURI, newServiceURI) {

	var oldID = getIDfromURI(oldGroundingURI);
	var newServiceFilename = getFileNameByURL(getURLfromURI(newServiceURI));
	var newPath = _FIX_storage_path + 'Groundings/';
	
	// e.g. http://www.fo-ss.ch/simon/DiplomaThesis/Ontologies/Groundings/CharlyService.owl#BravoAirGrounding
	return newPath + newServiceFilename + '#' + oldID;
}

/* ######################################################################### */
// [String Mutation] 4.8 Get URI By Point
/* ######################################################################### */
function getURIbyPoint(Point) {
	
	if(!validPoint(Point))
		return;
		
	/* Error handling~~~~~~~~~~*/
	if(!Point['URI']) {
		error_log('Point has no URI ' + Point);
		return;
	}
	/* ~~~~~~~~~~~~~~~~~~~~~~~~*/
	
	return Point['URI'];
}

/* ######################################################################### */
// [String Mutation] 4.9 Generate SESSION ID
/* ######################################################################### */
function generateSessionID() {
	
	// Get date
	var date = new Date();
	
	// Return SESSION ID
	return Math.random() + date.getTime();
}