<commit_before>/*
 * Copyright 1999-2010 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Represents the main entry-point to work with OrientDB databases.
 * 
 * @author <NAME>
 */

function ODatabase(databasePath) {
	this.databaseUrl = "";
	this.databaseName = "";
	this.encodedDatabaseName = "";
	this.databaseInfo = null;
	this.commandResult = null;
	this.commandResponse = null;
	this.errorMessage = null;
	this.evalResponse = true;
	this.parseResponseLink = true;
	this.removeObjectCircleReferences = true;
	this.urlPrefix = "";
	this.urlSuffix = "";

	if (databasePath) {
		var pos = databasePath.indexOf('orientdb_proxy', 8); // JUMP HTTP
		if (pos > -1) {
			pos = databasePath.indexOf('/', pos); // END OF PROXY
		} else {
			pos = databasePath.indexOf('/', 8);
		}

		this.databaseUrl = databasePath.substring(0, pos + 1);
		this.databaseName = databasePath.substring(pos + 1);
		if (this.databaseName.indexOf('/') > -1) {
			this.encodedDatabaseName = "";
			var parts = this.databaseName.split('/');
			for (p in parts) {
				if (this.encodedDatabaseName.length > 0)
					this.encodedDatabaseName += '$';
				this.encodedDatabaseName += parts[p];
			}
		} else
		this.encodedDatabaseName = this.databaseName;
	}

	ODatabase.prototype.getDatabaseInfo = function() {
		return this.databaseInfo;
	}
	ODatabase.prototype.setDatabaseInfo = function(iDatabaseInfo) {
		this.databaseInfo = iDatabaseInfo;
	}

    ODatabase.prototype.getUrlSuffix = function() {
        return this.urlSuffix;
    }
    ODatabase.prototype.setUrlSuffix = function(iUrlSuffix) {
        this.urlSuffix = iUrlSuffix;
    }

	ODatabase.prototype.getCommandResult = function() {
		return this.commandResult;
	}
	ODatabase.prototype.setCommandResult = function(iCommandResult) {
		this.commandResult = iCommandResult;
	}

	ODatabase.prototype.getCommandResponse = function() {
		return this.commandResponse;
	}
	ODatabase.prototype.setCommandResponse = function(iCommandResponse) {
		this.commandResponse = iCommandResponse;
	}

	ODatabase.prototype.getErrorMessage = function() {
		return this.errorMessage;
	}
	ODatabase.prototype.setErrorMessage = function(iErrorMessage) {
		this.errorMessage = iErrorMessage;
	}

	ODatabase.prototype.getDatabaseUrl = function() {
		return this.databaseUrl;
	}
	ODatabase.prototype.setDatabaseUrl = function(iDatabaseUrl) {
		this.databaseUrl = iDatabaseUrl;
	}

	ODatabase.prototype.getDatabaseName = function() {
		return this.encodedDatabaseName;
	}
	ODatabase.prototype.setDatabaseName = function(iDatabaseName) {
		this.encodedDatabaseName = iDatabaseName;
	}

	ODatabase.prototype.getEvalResponse = function() {
		return this.evalResponse;
	}
	ODatabase.prototype.setEvalResponse = function(iEvalResponse) {
		this.evalResponse = iEvalResponse;
	}

	ODatabase.prototype.getParseResponseLinks = function() {
		return this.parseResponseLink;
	}
	ODatabase.prototype.setParseResponseLinks = function(iParseResponseLinks) {
		this.parseResponseLink = iParseResponseLinks;
	}
	
	ODatabase.prototype.getUserName = function() {
		if( !this.databaseInfo )
			return null;
		
		return this.databaseInfo.currentUser;
	}
	
	ODatabase.prototype.getUser = function() {
		var queryString = "select from OUser where name = '" + this.getUserName() + "'";
		query = this.query(queryString, null, '*:-1');
		if( query == null )
			return null;

		return query.result[0];
	}
	
	ODatabase.prototype.getRemoveObjectCircleReferences = function() {
		return this.removeObjectCircleReferences;
	}
	ODatabase.prototype.setRemoveObjectCircleReferences = function(
			iRemoveObjectCircleReferences) {
		this.removeObjectCircleReferences = iRemoveObjectCircleReferences;
	}

	ODatabase.prototype.open = function(userName, userPass, authProxy, type) {
		if (userName == null) {
			userName = '';
		}
		if (userPass == null) {
			userPass = '';
		}
		if (authProxy != null && authProxy != '') {
			urlPrefix = this.databaseUrl + authProxy + "/";
		} else
			urlPrefix = this.databaseUrl;

		if (type == null || type == '') {
			type = 'GET';
		}
		$.ajax({
			type : type,
			url : urlPrefix + 'connect/' + this.encodedDatabaseName + this.urlSuffix,
			context : this,
			async : false,
			username : userName,
			password : <PASSWORD>,
			success : function(msg) {
				this.setErrorMessage(null);
				this.setDatabaseInfo(this.transformResponse(msg));
			},
			error : function(msg, textStatus, errorThrown) {
				this.setErrorMessage('Connect error: ' + msg.responseText);
				this.setDatabaseInfo(null);
			}
		});
		return this.getDatabaseInfo();
	}
	


	ODatabase.prototype.create = function(userName, userPass, type) {
		if (userName == null) {
			userName = '';
		}
		if (userPass == null) {
			userPass = '';
		}
		urlPrefix = this.databaseUrl;

		if (type == null || type == '') {
			type = 'local';
		}
		$.ajax({
			type : "POST",
			url : urlPrefix + 'database/' + this.encodedDatabaseName
			+ '/' + type + this.urlSuffix,
			context : this,
			async : false,
			username : userName,
			password : <PASSWORD>,
			success : function(msg) {
				this.setErrorMessage(null);
				this.setDatabaseInfo(this.transformResponse(msg));
			},
			error : function(msg) {
				this.setErrorMessage('Connect error: ' + msg.responseText);
				this.setDatabaseInfo(null);
			}
		});
		return this.getDatabaseInfo();
	}

	ODatabase.prototype.query = function(iQuery, iLimit, iFetchPlan, successCallback) {
		if (this.databaseInfo == null) {
			this.open();
		}
		if (iLimit == null || iLimit == '') {
			iLimit = '';
		} else {
			iLimit = '/' + iLimit;
		}
		if (iFetchPlan == null || iFetchPlan == '') {
			iFetchPlan = '';
		} else {
			if (iLimit == '') {
				iLimit = '/20';
			}
			iFetchPlan = '/' + iFetchPlan;
		}
		iQuery = this.URLEncode(iQuery);
		iFetchPlan = this.URLEncode(iFetchPlan);
		$.ajax({
			type : "GET",
			url : urlPrefix + 'query/' + this.encodedDatabaseName + '/sql/'
					+ iQuery + iLimit + iFetchPlan + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
				if (successCallback)
					successCallback();
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Query error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.load = function(iRID, iFetchPlan) {
		if (this.databaseInfo == null) {
			this.open();
		}

		if (iFetchPlan != null && iFetchPlan != '') {
			iFetchPlan = '/' + iFetchPlan;
		} else {
			iFetchPlan = '';
		}

		if (iRID && iRID.charAt(0) == '#')
			iRID = iRID.substring(1);

		iRID = this.URLEncode(iRID);
		$.ajax({
			type : "GET",
			url : urlPrefix + 'document/' + this.encodedDatabaseName + '/'
					+ iRID + iFetchPlan + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Query error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.save = function(obj, errorCallback, successCallback) {
		if (this.databaseInfo == null) {
			this.open();
		}
	
		var rid = obj['@rid'];
		var methodType = rid == null || rid == '-1:-1' ? 'POST' : 'PUT';
		if (this.removeObjectCircleReferences && typeof obj == 'object') {
			this.removeCircleReferences(obj, {});
		}
		var url = urlPrefix + 'document/' + this.encodedDatabaseName;
		if (rid)
			url += '/' + this.URLEncode(rid);
		
		$.ajax({
			type : methodType,
			url : url + this.urlSuffix,
			data : $.toJSON(obj),
			processData : false,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.setCommandResponse(msg);
				this.setCommandResult(msg);
				if(successCallback)
					successCallback();
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Save error: ' + msg.responseText);
				if(errorCallback)
					errorCallback(msg.responseText);
			}
		});
		
		 
		if (methodType == 'PUT') {
			return rid;
		} else {
			return this.getCommandResult();
		}
	}

	ODatabase.prototype.remove = function(obj, onsuccess, onerror) {
		if (this.databaseInfo == null)
			this.open();

		var rid;
		if (typeof obj == "string")
			rid = obj;
		else
			rid = obj['@rid'];

		rid = this.URLEncode(rid);
		$.ajax({
			type : "DELETE",
			url : urlPrefix + 'document/' + this.encodedDatabaseName + '/'
					+ rid + this.urlSuffix,
			processData : false,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
				if (onsuccess) {
					onsuccess();
				}
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Remove error: ' + msg.responseText);
				if (onerror) {
					onerror();
				}
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.indexPut = function(iIndexName, iKey, iValue) {
		if (this.databaseInfo == null)
			this.open();

		var req = urlPrefix + 'index/' + this.encodedDatabaseName + '/'
				+ iIndexName + "/" + iKey;

		var content;
		if (typeof iValue == "object")
			content = $.toJSON(iValue);
		else {
			req += "/" + iValue;
			content = null;
		}

		$.ajax({
			type : "PUT",
			url : req + this.urlSuffix,
			context : this,
			async : false,
			data : content,
			success : function(msg) {
				this.setErrorMessage(null);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Index put error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.indexGet = function(iIndexName, iKey) {
		if (this.databaseInfo == null)
			this.open();

		$.ajax({
			type : "GET",
			url : urlPrefix + 'index/' + this.encodedDatabaseName + '/'
					+ iIndexName + "/" + iKey + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Index get error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.indexRemove = function(iIndexName, iKey) {
		if (this.databaseInfo == null)
			this.open();

		$
				.ajax({
					type : "DELETE",
					url : urlPrefix + 'index/' + this.encodedDatabaseName + '/'
							+ iIndexName + "/" + iKey + this.urlSuffix,
					context : this,
					async : false,
					success : function(msg) {
						this.setErrorMessage(null);
						this.handleResponse(msg);
					},
					error : function(msg) {
						this.handleResponse(null);
						this.setErrorMessage('Index remove error: '
								+ msg.responseText);
					}
				});
		return this.getCommandResult();
	}

	ODatabase.prototype.classInfo = function(iClassName) {
		if (this.databaseInfo == null) {
			this.open();
		}
		$.ajax({
			type : "GET",
			url : urlPrefix + 'class/' + this.encodedDatabaseName + '/'
					+ iClassName + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.createClass = function(iClassName) {
		if (this.databaseInfo == null) {
			this.open();
		}
		$.ajax({
			type : "POST",
			url : urlPrefix + 'class/' + this.encodedDatabaseName + '/'
					+ iClassName + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}
	
	ODatabase.prototype.createProperty = function(iClassName, iPropertyName, iPropertyType, iLinkedType) {
		if (this.databaseInfo == null) {
			this.open();
		}
		if (iPropertyType == null || iPropertyType == '') {
			iPropertyType = '';
		} else {
			iPropertyType = '/' + iPropertyType;
		}
		if (iLinkedType == null || iLinkedType == '') {
			iLinkedType = '';
		} else {
			iLinkedType = '/' + iLinkedType;
		}
		$.ajax({
			type : "POST",
			url : urlPrefix + 'property/' + this.encodedDatabaseName + '/'
					+ iClassName + '/' + iPropertyName + iPropertyType + iLinkedType + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}
	
	ODatabase.prototype.createProperties = function(iClassName,iPropertiesJson) {
		if (this.databaseInfo == null) {
			this.open();
		}
		var jsonData;
		if (typeof iPropertiesJson == 'object' ){
			jsonData = $toJSON(iPropertiesJson)
		} else {
			jsonData = iPropertiesJson;
		}
		$.ajax({
			type : "POST",
			url : urlPrefix + 'property/' + this.encodedDatabaseName + '/'
					+ iClassName + this.urlSuffix,
			context : this,
			data : jsonData,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.browseCluster = function(iClassName) {
		if (this.databaseInfo == null) {
			this.open();
		}
		$.ajax({
			type : "GET",
			url : urlPrefix + 'cluster/' + this.encodedDatabaseName + '/'
					+ iClassName + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.executeCommand = function(iCommand, iLanguage, iLimit) {
		if (this.databaseInfo == null)
			this.open();

		if (!iLanguage)
			iLanguage = "sql";

		if (!iLimit)
			iLimit = -1;

		var dataType = this.evalResponse ? null : 'text';

		iCommand = this.URLEncode(iCommand);
		$.ajax({
			type : "POST",
			url : urlPrefix + 'command/' + this.encodedDatabaseName + '/'
					+ iLanguage + '/' + iCommand + "/" + iLimit + this.urlSuffix,
			context : this,
			async : false,
			'dataType' : dataType,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResponse();
	}

	ODatabase.prototype.serverInfo = function() {
		if (this.databaseInfo == null) {
			this.open();
		}
		$.ajax({
			type : "GET",
			url : urlPrefix + 'server' + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.listDatabases = function() {
		$.ajax({
			type : "GET",
			url : this.databaseUrl + '/' + 'listDatabases' + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.schema = function() {
		if (this.databaseInfo == null) {
			this.setErrorMessage('Database is closed');
			return null;
		}
		return this.transformResponse(this.getDatabaseInfo())['classes'];
	}

	ODatabase.prototype.securityRoles = function() {
		if (this.databaseInfo == null) {
			this.setErrorMessage('Database is closed');
			return null;
		}
		return this.transformResponse(this.getDatabaseInfo())['roles'];
	}

	ODatabase.prototype.securityUsers = function() {
		if (this.databaseInfo == null) {
			this.setErrorMessage('Database is closed');
			return null;
		}
		return this.transformResponse(this.getDatabaseInfo())['users'];
	}

	ODatabase.prototype.close = function() {
		if (this.databaseInfo != null) {
			$.ajax({
				type : 'GET',
				url : urlPrefix + 'disconnect' + this.urlSuffix,
				dataType : "json",
				async : false,
				context : this,
				success : function(msg) {
					this.handleResponse(msg);
					this.setErrorMessage(null);
				},
				error : function(msg) {
					this.handleResponse(null);
					this.setErrorMessage('Command response: '
							+ msg.responseText);
				}
			});
		}
		this.databaseInfo = null;
		return this.getCommandResult();
	}

	ODatabase.prototype.handleResponse = function(iResponse) {
		if (typeof iResponse != 'object'){
			iResponse = this.UTF8Encode(iResponse);
		}
		this.setCommandResponse(iResponse);
		if (iResponse != null)
			this.setCommandResult(this.transformResponse(iResponse));
		else
			this.setCommandResult(null);
	}

	ODatabase.prototype.transformResponse = function(msg) {
		if (this.getEvalResponse()) {
			var returnValue;
			if (msg.length > 0 && typeof msg != 'object') {
				returnValue = jQuery.parseJSON(msg)
			} else {
				returnValue = msg;
			}
			if (this.getParseResponseLinks()) {
				return this.parseConnections(returnValue);
			} else {
				return returnValue;
			}
		} else {
			return msg;
		}
	}

	ODatabase.prototype.parseConnections = function(obj) {
		if (typeof obj == 'object') {
			var linkMap = {
				"foo" : 0
			};
			linkMap = this.createObjectsLinksMap(obj, linkMap);
			if (linkMap["foo"] == 1) {
				linkMap = this.putObjectInLinksMap(obj, linkMap);
				if (linkMap["foo"] == 2) {
					obj = this.getObjectFromLinksMap(obj, linkMap);
				}
			}
		}
		return obj;
	}

	ODatabase.prototype.createObjectsLinksMap = function(obj, linkMap) {
		for (field in obj) {
			var value = obj[field];
			if (typeof value == 'object') {
				this.createObjectsLinksMap(value, linkMap);
			} else {
				if (typeof value == 'string') {
					if (value.length > 0 && value.charAt(0) == '#') {
						if (!linkMap.hasOwnProperty(value)) {
							linkMap["foo"] = 1;
							linkMap[value] = null;
						}
					}
				}
			}
		}
		return linkMap;
	}

	ODatabase.prototype.putObjectInLinksMap = function(obj, linkMap) {
		for (field in obj) {
			var value = obj[field];
			if (typeof value == 'object') {
				this.putObjectInLinksMap(value, linkMap);
			} else {
				if (field == '@rid' && value.length > 0
						&& linkMap.hasOwnProperty(value)
						&& linkMap[value] === null) {
					linkMap["foo"] = 2;
					linkMap[value] = obj;
				}
			}
		}
		return linkMap;
	}

	ODatabase.prototype.getObjectFromLinksMap = function(obj, linkMap) {
		for (field in obj) {
			var value = obj[field];
			if (typeof value == 'object') {
				this.getObjectFromLinksMap(value, linkMap);
			} else {
				if (field != '@rid' && value.length > 0 && value.charAt(0) == '#'
						&& linkMap[value] != null) {
					obj[field] = linkMap[value];
				}
			}
		}
		return obj;
	}

	ODatabase.prototype.removeCircleReferences = function(obj, linkMap) {
		linkMap = this.removeCircleReferencesPopulateMap(obj, linkMap);
		this.removeCircleReferencesChangeObject(obj, linkMap);
	}

	ODatabase.prototype.removeCircleReferencesPopulateMap = function(obj,
			linkMap) {
		for (field in obj) {
			var value = obj[field];
			if (value!=null && typeof value == 'object' && !$.isArray(value)) {
				if (value['@rid'] != null && value['@rid']) {
					var rid = this.getRidWithPound(value['@rid']);
					if (linkMap[rid] == null || !linkMap[rid]) {
						linkMap[rid] = value;<commit_msg>Fixed bug on circle references removing.<commit_after>/*
 * Copyright 1999-2010 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Represents the main entry-point to work with OrientDB databases.
 * 
 * @author <NAME>
 */

function ODatabase(databasePath) {
	this.databaseUrl = "";
	this.databaseName = "";
	this.encodedDatabaseName = "";
	this.databaseInfo = null;
	this.commandResult = null;
	this.commandResponse = null;
	this.errorMessage = null;
	this.evalResponse = true;
	this.parseResponseLink = true;
	this.removeObjectCircleReferences = true;
	this.urlPrefix = "";
	this.urlSuffix = "";

	if (databasePath) {
		var pos = databasePath.indexOf('orientdb_proxy', 8); // JUMP HTTP
		if (pos > -1) {
			pos = databasePath.indexOf('/', pos); // END OF PROXY
		} else {
			pos = databasePath.indexOf('/', 8);
		}

		this.databaseUrl = databasePath.substring(0, pos + 1);
		this.databaseName = databasePath.substring(pos + 1);
		if (this.databaseName.indexOf('/') > -1) {
			this.encodedDatabaseName = "";
			var parts = this.databaseName.split('/');
			for (p in parts) {
				if (this.encodedDatabaseName.length > 0)
					this.encodedDatabaseName += '$';
				this.encodedDatabaseName += parts[p];
			}
		} else
		this.encodedDatabaseName = this.databaseName;
	}

	ODatabase.prototype.getDatabaseInfo = function() {
		return this.databaseInfo;
	}
	ODatabase.prototype.setDatabaseInfo = function(iDatabaseInfo) {
		this.databaseInfo = iDatabaseInfo;
	}

    ODatabase.prototype.getUrlSuffix = function() {
        return this.urlSuffix;
    }
    ODatabase.prototype.setUrlSuffix = function(iUrlSuffix) {
        this.urlSuffix = iUrlSuffix;
    }

	ODatabase.prototype.getCommandResult = function() {
		return this.commandResult;
	}
	ODatabase.prototype.setCommandResult = function(iCommandResult) {
		this.commandResult = iCommandResult;
	}

	ODatabase.prototype.getCommandResponse = function() {
		return this.commandResponse;
	}
	ODatabase.prototype.setCommandResponse = function(iCommandResponse) {
		this.commandResponse = iCommandResponse;
	}

	ODatabase.prototype.getErrorMessage = function() {
		return this.errorMessage;
	}
	ODatabase.prototype.setErrorMessage = function(iErrorMessage) {
		this.errorMessage = iErrorMessage;
	}

	ODatabase.prototype.getDatabaseUrl = function() {
		return this.databaseUrl;
	}
	ODatabase.prototype.setDatabaseUrl = function(iDatabaseUrl) {
		this.databaseUrl = iDatabaseUrl;
	}

	ODatabase.prototype.getDatabaseName = function() {
		return this.encodedDatabaseName;
	}
	ODatabase.prototype.setDatabaseName = function(iDatabaseName) {
		this.encodedDatabaseName = iDatabaseName;
	}

	ODatabase.prototype.getEvalResponse = function() {
		return this.evalResponse;
	}
	ODatabase.prototype.setEvalResponse = function(iEvalResponse) {
		this.evalResponse = iEvalResponse;
	}

	ODatabase.prototype.getParseResponseLinks = function() {
		return this.parseResponseLink;
	}
	ODatabase.prototype.setParseResponseLinks = function(iParseResponseLinks) {
		this.parseResponseLink = iParseResponseLinks;
	}
	
	ODatabase.prototype.getUserName = function() {
		if( !this.databaseInfo )
			return null;
		
		return this.databaseInfo.currentUser;
	}
	
	ODatabase.prototype.getUser = function() {
		var queryString = "select from OUser where name = '" + this.getUserName() + "'";
		query = this.query(queryString, null, '*:-1');
		if( query == null )
			return null;

		return query.result[0];
	}
	
	ODatabase.prototype.getRemoveObjectCircleReferences = function() {
		return this.removeObjectCircleReferences;
	}
	ODatabase.prototype.setRemoveObjectCircleReferences = function(
			iRemoveObjectCircleReferences) {
		this.removeObjectCircleReferences = iRemoveObjectCircleReferences;
	}

	ODatabase.prototype.open = function(userName, userPass, authProxy, type) {
		if (userName == null) {
			userName = '';
		}
		if (userPass == null) {
			userPass = '';
		}
		if (authProxy != null && authProxy != '') {
			urlPrefix = this.databaseUrl + authProxy + "/";
		} else
			urlPrefix = this.databaseUrl;

		if (type == null || type == '') {
			type = 'GET';
		}
		$.ajax({
			type : type,
			url : urlPrefix + 'connect/' + this.encodedDatabaseName + this.urlSuffix,
			context : this,
			async : false,
			username : userName,
			password : <PASSWORD>,
			success : function(msg) {
				this.setErrorMessage(null);
				this.setDatabaseInfo(this.transformResponse(msg));
			},
			error : function(msg, textStatus, errorThrown) {
				this.setErrorMessage('Connect error: ' + msg.responseText);
				this.setDatabaseInfo(null);
			}
		});
		return this.getDatabaseInfo();
	}
	


	ODatabase.prototype.create = function(userName, userPass, type) {
		if (userName == null) {
			userName = '';
		}
		if (userPass == null) {
			userPass = '';
		}
		urlPrefix = this.databaseUrl;

		if (type == null || type == '') {
			type = 'local';
		}
		$.ajax({
			type : "POST",
			url : urlPrefix + 'database/' + this.encodedDatabaseName
			+ '/' + type + this.urlSuffix,
			context : this,
			async : false,
			username : userName,
			password : <PASSWORD>,
			success : function(msg) {
				this.setErrorMessage(null);
				this.setDatabaseInfo(this.transformResponse(msg));
			},
			error : function(msg) {
				this.setErrorMessage('Connect error: ' + msg.responseText);
				this.setDatabaseInfo(null);
			}
		});
		return this.getDatabaseInfo();
	}

	ODatabase.prototype.query = function(iQuery, iLimit, iFetchPlan, successCallback) {
		if (this.databaseInfo == null) {
			this.open();
		}
		if (iLimit == null || iLimit == '') {
			iLimit = '';
		} else {
			iLimit = '/' + iLimit;
		}
		if (iFetchPlan == null || iFetchPlan == '') {
			iFetchPlan = '';
		} else {
			if (iLimit == '') {
				iLimit = '/20';
			}
			iFetchPlan = '/' + iFetchPlan;
		}
		iQuery = this.URLEncode(iQuery);
		iFetchPlan = this.URLEncode(iFetchPlan);
		$.ajax({
			type : "GET",
			url : urlPrefix + 'query/' + this.encodedDatabaseName + '/sql/'
					+ iQuery + iLimit + iFetchPlan + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
				if (successCallback)
					successCallback();
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Query error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.load = function(iRID, iFetchPlan) {
		if (this.databaseInfo == null) {
			this.open();
		}

		if (iFetchPlan != null && iFetchPlan != '') {
			iFetchPlan = '/' + iFetchPlan;
		} else {
			iFetchPlan = '';
		}

		if (iRID && iRID.charAt(0) == '#')
			iRID = iRID.substring(1);

		iRID = this.URLEncode(iRID);
		$.ajax({
			type : "GET",
			url : urlPrefix + 'document/' + this.encodedDatabaseName + '/'
					+ iRID + iFetchPlan + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Query error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.save = function(obj, errorCallback, successCallback) {
		if (this.databaseInfo == null) {
			this.open();
		}
	
		var rid = obj['@rid'];
		var methodType = rid == null || rid == '-1:-1' ? 'POST' : 'PUT';
		if (this.removeObjectCircleReferences && typeof obj == 'object') {
			this.removeCircleReferences(obj, {});
		}
		var url = urlPrefix + 'document/' + this.encodedDatabaseName;
		if (rid)
			url += '/' + this.URLEncode(rid);
		
		$.ajax({
			type : methodType,
			url : url + this.urlSuffix,
			data : $.toJSON(obj),
			processData : false,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.setCommandResponse(msg);
				this.setCommandResult(msg);
				if(successCallback)
					successCallback();
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Save error: ' + msg.responseText);
				if(errorCallback)
					errorCallback(msg.responseText);
			}
		});
		
		 
		if (methodType == 'PUT') {
			return rid;
		} else {
			return this.getCommandResult();
		}
	}

	ODatabase.prototype.remove = function(obj, onsuccess, onerror) {
		if (this.databaseInfo == null)
			this.open();

		var rid;
		if (typeof obj == "string")
			rid = obj;
		else
			rid = obj['@rid'];

		rid = this.URLEncode(rid);
		$.ajax({
			type : "DELETE",
			url : urlPrefix + 'document/' + this.encodedDatabaseName + '/'
					+ rid + this.urlSuffix,
			processData : false,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
				if (onsuccess) {
					onsuccess();
				}
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Remove error: ' + msg.responseText);
				if (onerror) {
					onerror();
				}
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.indexPut = function(iIndexName, iKey, iValue) {
		if (this.databaseInfo == null)
			this.open();

		var req = urlPrefix + 'index/' + this.encodedDatabaseName + '/'
				+ iIndexName + "/" + iKey;

		var content;
		if (typeof iValue == "object")
			content = $.toJSON(iValue);
		else {
			req += "/" + iValue;
			content = null;
		}

		$.ajax({
			type : "PUT",
			url : req + this.urlSuffix,
			context : this,
			async : false,
			data : content,
			success : function(msg) {
				this.setErrorMessage(null);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Index put error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.indexGet = function(iIndexName, iKey) {
		if (this.databaseInfo == null)
			this.open();

		$.ajax({
			type : "GET",
			url : urlPrefix + 'index/' + this.encodedDatabaseName + '/'
					+ iIndexName + "/" + iKey + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Index get error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.indexRemove = function(iIndexName, iKey) {
		if (this.databaseInfo == null)
			this.open();

		$
				.ajax({
					type : "DELETE",
					url : urlPrefix + 'index/' + this.encodedDatabaseName + '/'
							+ iIndexName + "/" + iKey + this.urlSuffix,
					context : this,
					async : false,
					success : function(msg) {
						this.setErrorMessage(null);
						this.handleResponse(msg);
					},
					error : function(msg) {
						this.handleResponse(null);
						this.setErrorMessage('Index remove error: '
								+ msg.responseText);
					}
				});
		return this.getCommandResult();
	}

	ODatabase.prototype.classInfo = function(iClassName) {
		if (this.databaseInfo == null) {
			this.open();
		}
		$.ajax({
			type : "GET",
			url : urlPrefix + 'class/' + this.encodedDatabaseName + '/'
					+ iClassName + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.createClass = function(iClassName) {
		if (this.databaseInfo == null) {
			this.open();
		}
		$.ajax({
			type : "POST",
			url : urlPrefix + 'class/' + this.encodedDatabaseName + '/'
					+ iClassName + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}
	
	ODatabase.prototype.createProperty = function(iClassName, iPropertyName, iPropertyType, iLinkedType) {
		if (this.databaseInfo == null) {
			this.open();
		}
		if (iPropertyType == null || iPropertyType == '') {
			iPropertyType = '';
		} else {
			iPropertyType = '/' + iPropertyType;
		}
		if (iLinkedType == null || iLinkedType == '') {
			iLinkedType = '';
		} else {
			iLinkedType = '/' + iLinkedType;
		}
		$.ajax({
			type : "POST",
			url : urlPrefix + 'property/' + this.encodedDatabaseName + '/'
					+ iClassName + '/' + iPropertyName + iPropertyType + iLinkedType + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}
	
	ODatabase.prototype.createProperties = function(iClassName,iPropertiesJson) {
		if (this.databaseInfo == null) {
			this.open();
		}
		var jsonData;
		if (typeof iPropertiesJson == 'object' ){
			jsonData = $toJSON(iPropertiesJson)
		} else {
			jsonData = iPropertiesJson;
		}
		$.ajax({
			type : "POST",
			url : urlPrefix + 'property/' + this.encodedDatabaseName + '/'
					+ iClassName + this.urlSuffix,
			context : this,
			data : jsonData,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.browseCluster = function(iClassName) {
		if (this.databaseInfo == null) {
			this.open();
		}
		$.ajax({
			type : "GET",
			url : urlPrefix + 'cluster/' + this.encodedDatabaseName + '/'
					+ iClassName + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.executeCommand = function(iCommand, iLanguage, iLimit) {
		if (this.databaseInfo == null)
			this.open();

		if (!iLanguage)
			iLanguage = "sql";

		if (!iLimit)
			iLimit = -1;

		var dataType = this.evalResponse ? null : 'text';

		iCommand = this.URLEncode(iCommand);
		$.ajax({
			type : "POST",
			url : urlPrefix + 'command/' + this.encodedDatabaseName + '/'
					+ iLanguage + '/' + iCommand + "/" + iLimit + this.urlSuffix,
			context : this,
			async : false,
			'dataType' : dataType,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResponse();
	}

	ODatabase.prototype.serverInfo = function() {
		if (this.databaseInfo == null) {
			this.open();
		}
		$.ajax({
			type : "GET",
			url : urlPrefix + 'server' + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.listDatabases = function() {
		$.ajax({
			type : "GET",
			url : this.databaseUrl + '/' + 'listDatabases' + this.urlSuffix,
			context : this,
			async : false,
			success : function(msg) {
				this.setErrorMessage(null);
				this.handleResponse(msg);
			},
			error : function(msg) {
				this.handleResponse(null);
				this.setErrorMessage('Command error: ' + msg.responseText);
			}
		});
		return this.getCommandResult();
	}

	ODatabase.prototype.schema = function() {
		if (this.databaseInfo == null) {
			this.setErrorMessage('Database is closed');
			return null;
		}
		return this.transformResponse(this.getDatabaseInfo())['classes'];
	}

	ODatabase.prototype.securityRoles = function() {
		if (this.databaseInfo == null) {
			this.setErrorMessage('Database is closed');
			return null;
		}
		return this.transformResponse(this.getDatabaseInfo())['roles'];
	}

	ODatabase.prototype.securityUsers = function() {
		if (this.databaseInfo == null) {
			this.setErrorMessage('Database is closed');
			return null;
		}
		return this.transformResponse(this.getDatabaseInfo())['users'];
	}

	ODatabase.prototype.close = function() {
		if (this.databaseInfo != null) {
			$.ajax({
				type : 'GET',
				url : urlPrefix + 'disconnect' + this.urlSuffix,
				dataType : "json",
				async : false,
				context : this,
				success : function(msg) {
					this.handleResponse(msg);
					this.setErrorMessage(null);
				},
				error : function(msg) {
					this.handleResponse(null);
					this.setErrorMessage('Command response: '
							+ msg.responseText);
				}
			});
		}
		this.databaseInfo = null;
		return this.getCommandResult();
	}

	ODatabase.prototype.handleResponse = function(iResponse) {
		if (typeof iResponse != 'object'){
			iResponse = this.UTF8Encode(iResponse);
		}
		this.setCommandResponse(iResponse);
		if (iResponse != null)
			this.setCommandResult(this.transformResponse(iResponse));
		else
			this.setCommandResult(null);
	}

	ODatabase.prototype.transformResponse = function(msg) {
		if (this.getEvalResponse()) {
			var returnValue;
			if (msg.length > 0 && typeof msg != 'object') {
				returnValue = jQuery.parseJSON(msg)
			} else {
				returnValue = msg;
			}
			if (this.getParseResponseLinks()) {
				return this.parseConnections(returnValue);
			} else {
				return returnValue;
			}
		} else {
			return msg;
		}
	}

	ODatabase.prototype.parseConnections = function(obj) {
		if (typeof obj == 'object') {
			var linkMap = {
				"foo" : 0
			};
			linkMap = this.createObjectsLinksMap(obj, linkMap);
			if (linkMap["foo"] == 1) {
				linkMap = this.putObjectInLinksMap(obj, linkMap);
				if (linkMap["foo"] == 2) {
					obj = this.getObjectFromLinksMap(obj, linkMap);
				}
			}
		}
		return obj;
	}

	ODatabase.prototype.createObjectsLinksMap = function(obj, linkMap) {
		for (field in obj) {
			var value = obj[field];
			if (typeof value == 'object') {
				this.createObjectsLinksMap(value, linkMap);
			} else {
				if (typeof value == 'string') {
					if (value.length > 0 && value.charAt(0) == '#') {
						if (!linkMap.hasOwnProperty(value)) {
							linkMap["foo"] = 1;
							linkMap[value] = null;
						}
					}
				}
			}
		}
		return linkMap;
	}

	ODatabase.prototype.putObjectInLinksMap = function(obj, linkMap) {
		for (field in obj) {
			var value = obj[field];
			if (typeof value == 'object') {
				this.putObjectInLinksMap(value, linkMap);
			} else {
				if (field == '@rid' && value.length > 0
						&& linkMap.hasOwnProperty(value)
						&& linkMap[value] === null) {
					linkMap["foo"] = 2;
					linkMap[value] = obj;
				}
			}
		}
		return linkMap;
	}

	ODatabase.prototype.getObjectFromLinksMap = function(obj, linkMap) {
		for (field in obj) {
			var value = obj[field];
			if (typeof value == 'object') {
				this.getObjectFromLinksMap(value, linkMap);
			} else {
				if (field != '@rid' && value.length > 0 && value.charAt(0) == '#'
						&& linkMap[value] != null) {
					obj[field] = linkMap[value];
				}
			}
		}
		return obj;
	}

	ODatabase.prototype.removeCircleReferences = function(obj, linkMap) {
        linkMap = this.removeCircleReferencesPopulateMap(obj, linkMap);
        if (obj != null && typeof obj == 'object' && !$.isArray(obj)) {
            if (obj['@rid'] != null && obj['@rid']) {
                var rid = this.getRidWithPound(obj['@rid']);
                linkMap[rid] = rid;
            }
        }
        this.removeCircleReferencesChangeObject(obj, linkMap);
    }

	ODatabase.prototype.removeCircleReferencesPopulateMap = function(obj,
			linkMap) {
		for (field in obj) {
			var value = obj[field];
			if (value!=null && typeof value == 'object' && !$.isArray(value)) {
				if (value['@rid'] != null && value['@rid']) {
					var rid = this.getRidWithPound(value['@rid']);
					if (linkMap[rid] == null || !linkMap[rid]) {
						linkMap[rid] = value;
{'fraction_non_alphanumeric': 0.14694966646452395, 'fraction_numerical': 0.0019890842935112187, 'mean_word_length': 3.274782248029863, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7130717', 'n_tokens_mistral': 16107, 'n_tokens_neox': 13462, 'n_words': 2620}