/*
 * $Header: /home/cvspublic/jakarta-slide/src/stores/slidestore/j2ee/J2EEDescriptorsStore2.java,v 1.0 2002/04/11 00:16:52 akumar Exp $
 * $Revision: 1.0 $
 * $Date: 2002/04/11 00:16:52 $
 *
 * ====================================================================
 *
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights 
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:  
 *       "This product includes software developed by the 
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written 
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * [Additional notices, if required by prior licensing conditions]
 *
 */

package slidestore.j2ee;

import java.lang.reflect.Constructor;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Vector;
import java.util.Date;
import java.util.Arrays;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.*;
import	java.sql.Timestamp;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import org.apache.slide.common.*;
import org.apache.slide.store.*;
import org.apache.slide.structure.*;
import org.apache.slide.security.*;
import org.apache.slide.lock.*;
import org.apache.slide.content.*;
import org.apache.slide.util.logger.Logger;
//For the Datasource implementation
import javax.sql.DataSource;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * J2EE Descriptors store implementation for the new Indexed DB Schema..
 *
 * Alpha version (for development only)
 *
 * @author <a href="mailto:msmith@apache.org">Michael Smith</a>
 * @author <a href="mailto:akumar@metatomix.com">Ashok Kumar</a>
 * @version $Revision: 1.0 $
 */

public class J2EEDescriptorsStore2 extends J2EEStore2 implements LockStore, NodeStore, RevisionDescriptorsStore, RevisionDescriptorStore, SecurityStore {

	private final 	String 	SELECT_OBJECT = "select CLASS_NAME from OBJECT where URI_ID= ?";
	private	final	String	SELECT_URI_STRING  = "select URI_STRING from URI where URI_ID IN (SELECT CHILD_URI_ID FROM CHILDREN WHERE URI_ID = ?)";
	private	final	String	SELECT_LINK = "select URI_STRING from URI where URI_ID IN (select URI_ID from LINKS where LINK_TO_ID= ?)";
	private	final	String	SELECT_LINK_URI_STRING ="select URI_STRING from URI where URI_ID IN (select LINK_TO_ID from LINKS where URI_ID= ?)";
	private	final	String	SELECT_OBJECT_FROM_URI_ID = "select 1 from OBJECT where URI_ID=?";
	private	final	String	INSERT_CHILDREN="insert into CHILDREN (URI_ID,CHILD_URI_ID) values(?,?)";
	private	final	String	INSERT_LINK="insert into LINKS (URI_ID,LINK_TO_ID) values(?,?)";
	private	final	String	INSERT_OBJECT="insert into OBJECT (URI_ID,CLASS_NAME) values (?,?)";
	private	final	String	DELETE_OBJECT="delete from OBJECT where URI_ID =?";
	private	final	String	DELETE_CHILDREN="delete from CHILDREN where URI_ID = ? OR CHILD_URI_ID = ?";
	private	final	String	DELETE_LINK = "delete from LINKS where URI_ID = ?";
	private	final	String	DELETE_VERSION_HISTORY = "delete from VERSION_HISTORY where URI_ID =?";
	private	final	String	DELETE_VERSION = "delete from VERSION where URI_ID = ?";
	private	final	String	DELETE_URI = "delete from URI where URI_ID = ?";
	private	final	String	PERMISSION_EXISTS = "select 1 from PERMISSIONS where OBJECT_ID = ? and SUBJECT_ID= ? and ACTION_ID = ?";
	private	final	String	CREATE_PERMISSION = "insert into PERMISSIONS (OBJECT_ID,SUBJECT_ID,ACTION_ID,VERSION_NO,IS_INHERITABLE,IS_NEGATIVE) values(?,?,?,?,?,?)";
	private	final	String	DELETE_PERMISSIONS = "delete from PERMISSIONS where OBJECT_ID= ? and SUBJECT_ID = ? and ACTION_ID = ? and VERSION_NO = ? ";
	private	final	String	DELETE_PERMISSION = "delete from PERMISSIONS where OBJECT_ID=?";
	private	final	String	SELECT_PERMISSIONS = "select * from PERMISSIONS where OBJECT_ID = ?";
	private	final	String	CREATE_LOCK = "insert into LOCKS (LOCK_ID,OBJECT_ID,SUBJECT_ID,TYPE_ID,EXPIRATION_DATE,IS_INHERITABLE,IS_EXCLUSIVE) values(?,?,?,?,?,?,?)";
	private	final	String	REMOVE_LOCK = "delete from LOCKS where LOCK_ID= ?";
	private	final	String	LIST_LOCKS="select * from LOCKS where OBJECT_ID=?";
	private	final	String	IS_VERSIONNED = "select IS_VERSIONED from VERSION where URI_ID= ?";
	private	final	String	GET_REVISION_NUMBER="select VERSION_ID,REVISION_NO, B.BRANCH_STRING  from VERSION_HISTORY A , BRANCH B where A.URI_ID= ? and A.BRANCH_ID = B.BRANCH_ID";
	private	final	String	GET_PREDECESSOR = "select PREDECESSOR_ID from VERSION_PREDS where VERSION_ID  = ?";
	private	final	String	VERSION_EXISTS = "SELECT 1 FROM VERSION WHERE URI_ID = ?";
	private	final	String	INSERT_VERSION = "insert into VERSION (URI_ID,IS_VERSIONED) values(?,?)";
	private	final	String	VERSION_HISTORY_EXISTS = "SELECT 1 FROM VERSION_HISTORY WHERE URI_ID =? and BRANCH_ID =? and REVISION_NO =?";
	private	final	String	INSERT_VERSION_HISTORY = "insert into VERSION_HISTORY (URI_ID,BRANCH_ID,REVISION_NO) values(?,?,?)";
	private	final	String	REMOVE_VERSION_DESC = "delete from VERSION_PREDS where VERSION_ID = (SELECT VERSION_ID FROM VERSION_HISTORY where URI_ID =?)";
	private	final	String	SELECT_VERSION_ID_AND_BRANCH = "select A.VERSION_ID, B.BRANCH_STRING from VERSION_HISTORY A, BRANCH B where A.URI_ID = ? and A.REVISION_NO = ? and B.BRANCH_ID = A.BRANCH_ID";
	private	final	String	SELECT_LABEL_VERSION_LABEL = "select LABEL_ID from VERSION_LABELS where VERSION_ID =?";
	private	final	String	SELECT_PROPERTIES = "select * from PROPERTIES where VERSION_ID = ?";
	private	final	String	INSERT_VERSION_LABEL = "insert into VERSION_LABELS (VERSION_ID,LABEL_ID) values(?,?)";
	private	final	String	INSERT_PROPERTY="insert into PROPERTIES (VERSION_ID,PROPERTY_NAMESPACE,PROPERTY_NAME,PROPERTY_VALUE,PROPERTY_TYPE,IS_PROTECTED) values(?,?,?,?,?,? )";
	private	final	String	DELETE_VERSION_LABEL="delete from VERSION_LABELS where VERSION_ID=?";
	private	final	String	DELETE_PROPERTIES="delete from PROPERTIES where VERSION_ID=?";
	private	final	String	SELECT_URI_ID = "select  URI_ID from URI where URI_STRING = ?";
	private	final	String	SELECT_URI_STRING2 = "select URI_STRING from URI where URI_ID = ?";
	private	final	String	INSERT_URI_STRING = "insert into URI (URI_STRING) values (?)";
	private	final	String	SELECT_BRANCH_ID = "select BRANCH_ID from BRANCH where BRANCH_STRING =?";
	private	final	String	CREATE_BRANCH = "insert into BRANCH (BRANCH_STRING) values (?)";
	private	final	String	GET_LABEL_ID = "select LABEL_ID from LABEL where LABEL_STRING = ?";
	private	final	String	GET_LABEL_NAME = "select LABEL_STRING from LABEL where LABEL_ID = ?";
	private	final	String	CREATE_LABEL = "insert into LABEL (LABEL_STRING) values (?)";
	private	final	String	GET_CHILDREN = "select URI_STRING FROM URI WHERE URI_ID IN (SELECT CHILD_URI_ID from CHILDREN where URI_ID =  ?)";
	private	final	String	LINK_EXISTS = "select 1 from LINKS where URI_ID = ? and LINK_TO_ID = ?";
	private	final	String	LOCK_EXISTS = "select 1 from LOCKS where LOCK_ID = ?";
	private	final	String	GET_VERSION_ID = "select A.VERSION_ID from VERSION_HISTORY A, BRANCH B where  A.URI_ID=  ? and A.BRANCH_ID = B.BRANCH_ID and B.BRANCH_STRING = ? and A.REVISION_NO= ?";
	private	final	String	GET_XNUMBER = "select A.REVISION_NO from VERSION_HISTORY A, BRANCH B where A.VERSION_ID = ? and A.URI_ID= ? and A.BRANCH_ID = B.BRANCH_ID and B.BRANCH_STRING = ? ";
	private	final	String	SELECT_VERSION_IDS = "SELECT VERSION_ID FROM VERSION_HISTORY WHERE URI_ID=?";
	protected NodeRevisionDescriptor myRevisionDescriptor = null;

	// ----------------------------------------------- DescriptorsStore Methods

	/**
	 * Retrive an object.
	 * 
	 * @param uri Uri of the object we want to retrieve
	 * @exception ServiceAccessException Error accessing the Service
	 * @exception ObjectNotFoundException The object to retrieve was not found
	 */
	
	public ObjectNode retrieveObject(Uri uri) throws ServiceAccessException, ObjectNotFoundException {

		ObjectNode 			result = null;
		PreparedStatement 	statement = null;
		Connection 			connection = getCurrentConnection();
		ResultSet 			res = null;

		try {

			long l_currentUriID = this.getURIID(uri.toString());

			if (l_currentUriID == 0) {
				throw new ObjectNotFoundException(uri);
			}
			statement = connection.prepareStatement(SELECT_OBJECT);
			statement.setLong(1,l_currentUriID);

			res = statement.executeQuery();

			// Parsing result set

			String className;

			if (res.next()) {
				// Retrieving and loading the object
				className = res.getString("CLASS_NAME");
			} else {
				// Object was not found ...
				throw new ObjectNotFoundException(uri);
			}
			res.close();
			statement.close();
			
			statement = connection.prepareStatement(SELECT_URI_STRING);
			statement.setLong(1,l_currentUriID);
			res = statement.executeQuery();

			Vector childrenVector = new Vector();

			// Parse result set
			while (res.next()) {
				// Load each permission
				String sts = res.getString("URI_STRING");
				childrenVector.addElement(sts);
			}
			res.close();
			statement.close();
			
			statement = connection.prepareStatement(SELECT_LINK);
			statement.setLong(1,l_currentUriID);
			res = statement.executeQuery();

			Vector linksVector = new Vector();

			// Parse result set
			while (res.next()) {
				// Load each permission
				linksVector.addElement(res.getString("URI_STRING"));
			}
			res.close();
			statement.close();

			if (className.equals("org.apache.slide.structure.LinkNode")) {

				String linkTo = new String();
				
				statement = connection.prepareStatement(SELECT_LINK_URI_STRING);
				statement.setLong(1,l_currentUriID);
				res = statement.executeQuery();

				if (res.next())
					linkTo = res.getString("URI_STRING");
				res.close();
				statement.close();
				result = new LinkNode(uri.toString(), childrenVector, linksVector, linkTo);
			} else {

				try {
					Class objclass = Class.forName(className);

					Class[] argClasses = { Class.forName("java.lang.String"), Class.forName("java.util.Vector"), Class.forName("java.util.Vector")};
					Object[] arguments = { uri.toString(), childrenVector, linksVector };

					Constructor constructor = objclass.getConstructor(argClasses);
					result = (ObjectNode) constructor.newInstance(arguments);
				} catch (Exception e) {
					// ClassNotFoundException, NoSuchMethodException, etc. 
					throw new ServiceAccessException(this, e);
				}

			}

		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				if(res!=null) {res.close();}
				if(statement!=null) {statement.close();}
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}
		return result;
	}

	/**
	 * Update an object.
	 * 
	 * @param object Object to update
	 * @exception ServiceAccessException Error accessing the Service
	 * @exception ObjectNotFoundException The object to update was not found
	 */
	public void storeObject(Uri uri, ObjectNode object) throws ServiceAccessException, ObjectNotFoundException {

		PreparedStatement 	statement = null;
		Connection 			connection = getCurrentConnection();
		ResultSet			res = null;

		try {

			long l_uriid = this.getURIID(uri.toString());

			statement = connection.prepareStatement(SELECT_OBJECT_FROM_URI_ID);
			statement.setLong(1,l_uriid);
			res = statement.executeQuery();
			// Parsing result set

			if (!res.next()) {
				throw new ObjectNotFoundException(uri);
			}
			res.close();
			statement.close();

			long l_parent = this.getURIID(object.getUri());
			Enumeration children = getNewChildren(l_parent, object.enumerateChildren());
			if (children != null) {
				statement = connection.prepareStatement(INSERT_CHILDREN);
				while (children.hasMoreElements()) {
					statement.setLong(1,l_parent);
					statement.setLong(2,this.getURIID((String) children.nextElement()));
					statement.execute();
				}
			}
			// Updating link

			if (object instanceof LinkNode) {
				long l_link_to = this.getURIID(((LinkNode) object).getLinkedUri());
				if (!this.isLinkExist(l_parent, l_link_to)) {
					
					statement = connection.prepareStatement(INSERT_LINK);					
					statement.setLong(1,l_parent);
					statement.setLong(2,l_link_to);
					statement.execute();
					statement.close();
				}
			}

		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				res.close();
				statement.close();
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}

	}

	/**
	 * Create a new object.
	 * 
	 * @param object ObjectNode
	 * @param uri Uri of the object we want to create
	 * @exception ServiceAccessException Error accessing the Service
	 * @exception ObjectAlreadyExistsException An object already exists 
	 * at this Uri
	 */
	public void createObject(Uri uri, ObjectNode object) throws ServiceAccessException, ObjectAlreadyExistsException {


		getLogger().log("about to create uri:" + uri.toString(), LOG_CHANNEL, Logger.ERROR);		
		PreparedStatement 	statement = null;
		ResultSet			res = null;
		Connection 			connection = getCurrentConnection();

		try {
			this.setURIID(uri.toString());
			long l_uriid = this.getURIID(uri.toString());

			String className = object.getClass().getName();

			statement = connection.prepareStatement(SELECT_OBJECT_FROM_URI_ID);
			statement.setLong(1,l_uriid);
			res = statement.executeQuery();
			// Parsing result set

			if (res.next()) {
				throw new ObjectAlreadyExistsException(uri.toString());
			}
			res.close();
			statement.close();

			statement = connection.prepareStatement(INSERT_OBJECT);
			statement.setLong(1,l_uriid);
			statement.setObject(2,className);
			statement.execute();
			statement.close();

			Enumeration children = getNewChildren(l_uriid, object.enumerateChildren());
			if (children != null) {
				statement = connection.prepareStatement(INSERT_CHILDREN);
				while (children.hasMoreElements()) {
					statement.setLong(1,l_uriid);
					statement.setLong(2,this.getURIID((String) children.nextElement()));
					statement.execute();
				}
				statement.close();
			}

			// If the object is a link, also store the link information
			if (object instanceof LinkNode) {
				long l_link_to = this.getURIID(((LinkNode) object).getLinkedUri());
				if (!this.isLinkExist(l_uriid, l_link_to)) {
					
					statement = connection.prepareStatement(INSERT_LINK);
					statement.setLong(1,l_uriid);
					statement.setLong(2,l_link_to);
					statement.execute();
					statement.close();
				}
			}

		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				res.close();
				statement.close();
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}

	}
	private	void	deleteProperties(long uriId) throws SQLException {
		PreparedStatement statement = null;		
		PreparedStatement statement2 = null;		
		Connection connection = getCurrentConnection();
		
		try {
			statement = connection.prepareStatement(SELECT_VERSION_IDS);
			statement2 = connection.prepareStatement(DELETE_PROPERTIES);
			statement.setLong(1,uriId);
			ResultSet	res = statement.executeQuery();
			while(res.next()) {
				long	versionId = res.getLong("VERSION_ID");
				statement2.setLong(1,versionId);
				statement2.execute();
			}
		} finally {
			if(statement!=null) 
				statement.close();
			if(statement2!=null) 
				statement2.close();
		}
	}
	/**
	 * Remove an object.
	 * 
	 * @param object Object to remove
	 * @exception ServiceAccessException Error accessing the Service
	 * @exception ObjectNotFoundException The object to remove was not found
	 */
	public void removeObject(Uri uri, ObjectNode object) throws ServiceAccessException, ObjectNotFoundException {
		PreparedStatement statement = null;		
		Connection connection = getCurrentConnection();
		try {
			long l_uriid = this.getURIID(object.getUri());

			// Removing object
			statement = connection.prepareStatement(DELETE_OBJECT);
			statement.setLong(1,l_uriid);
			statement.execute();
			statement.close();

			// Removing children
			statement = connection.prepareStatement(DELETE_CHILDREN);
			statement.setLong(1,l_uriid);
			statement.setLong(2,l_uriid);
			statement.execute();
			statement.close();

			// Removing REST

			statement = connection.prepareStatement(DELETE_LINK);
			statement.setLong(1,l_uriid);
			statement.execute();
			statement.close();

			deleteProperties(l_uriid);

			statement = connection.prepareStatement(DELETE_VERSION_HISTORY);
			statement.setLong(1,l_uriid);
			statement.execute();
			statement.close();

			statement = connection.prepareStatement(DELETE_VERSION);
			statement.setLong(1,l_uriid);
			statement.execute();
			statement.close();

			statement = connection.prepareStatement(DELETE_URI);
			statement.setLong(1,l_uriid);
			statement.execute();
			statement.close();

			hsh_uriid_lookup.remove(object.getUri());
			hsh_uri_lookup.remove(new Long(l_uriid));

		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try { statement.close();} catch(Exception e) {;}
		}
	}

	/**
	 * Grant a new permission.
	 * 
	 * @param permission Permission we want to create
	 * @exception ServiceAccessException Error accessing the Service
	 */
	public void grantPermission(Uri uri, NodePermission permission) throws ServiceAccessException {

		PreparedStatement 	statement = null;
		Connection 		connection = getCurrentConnection();
		ResultSet 		res = null;

		try {
			int inheritable = 0;
			if (permission.isInheritable()) {
				inheritable = 1;
			}

			int negative = 0;
			if (permission.isNegative()) {
				negative = 1;
			}
			
			NodeRevisionNumber revisionNumber = permission.getRevisionNumber();
			String revisionNumberStr = (revisionNumber == null) ? null : revisionNumber.toString();
			this.setURIID(permission.getObjectUri());
			this.setURIID(permission.getSubjectUri());
			this.setURIID(permission.getActionUri());
			long l_objid = this.getURIID(permission.getObjectUri());
			long l_subid = this.getURIID(permission.getSubjectUri());
			long l_actid = this.getURIID(permission.getActionUri());

			statement = connection.prepareStatement(PERMISSION_EXISTS);
			statement.setLong(1,l_objid);
			statement.setLong(2,l_subid);
			statement.setLong(3,l_actid);
		
			res = statement.executeQuery();

			if (!res.next()) {
				res.close();
				statement.close();
				statement = connection.prepareStatement(CREATE_PERMISSION);
				if (revisionNumberStr == null) {
					statement.setLong(1,l_objid);
					statement.setLong(2,l_subid);
					statement.setLong(3,l_actid);
					statement.setNull(4,java.sql.Types.VARCHAR);
					statement.setInt(5,inheritable);
					statement.setInt(6,negative);
				} else {
					statement.setLong(1,l_objid);
					statement.setLong(2,l_subid);
					statement.setLong(3,l_actid);
					statement.setString(4,revisionNumberStr);
					statement.setInt(5,inheritable);
					statement.setInt(6,negative);
				}
				statement.execute();
			} else {
				res.close();
			}
			statement.close();
		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				res.close();
				statement.close();
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}

	}

	/**
	 * Revoke a permission.
	 * 
	 * @param permission Permission we want to create
	 * @exception ServiceAccessException Error accessing the Service
	 */
	public void revokePermission(Uri uri, NodePermission permission) throws ServiceAccessException {

		PreparedStatement statement = null;
		Connection connection = getCurrentConnection();

		try {
			
			NodeRevisionNumber revisionNumber = permission.getRevisionNumber();
			statement = connection.prepareStatement(DELETE_PERMISSIONS);
			statement.setLong(1,this.getURIID(permission.getObjectUri()));
			statement.setLong(2,this.getURIID(permission.getSubjectUri()));
			statement.setLong(3,this.getURIID(permission.getActionUri()));
			if (revisionNumber == null) {
				statement.setNull(4,java.sql.Types.VARCHAR);
			} else {
				statement.setString(4,revisionNumber.toString());
			}
			statement.execute();
		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				statement.close();
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}

	}

	/**
	 * Revoke all the permissions on an object.
	 * 
	 * @param permission Permission we want to create
	 * @exception ServiceAccessException Error accessing the Service
	 */
	public void revokePermissions(Uri uri) throws ServiceAccessException {

		PreparedStatement statement = null;
		Connection connection = getCurrentConnection();

		try {

			statement = connection.prepareStatement(DELETE_PERMISSION);
			statement.setLong(1,this.getURIID(uri.toString()));
			statement.execute();
		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				statement.close();
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}

	}

	/**
	 * Enumerate permissions on an object.
	 * 
	 * @param permission Permission we want to create
	 * @exception ServiceAccessException Error accessing the Service
	 */
	public Enumeration enumeratePermissions(Uri uri) throws ServiceAccessException {

		Vector 			permissionVector = new Vector();
		PreparedStatement 	statement = null;
		Connection 		connection = getCurrentConnection();
		ResultSet		res = null;

		try {
			statement = connection.prepareStatement(SELECT_PERMISSIONS);
			statement.setLong(1,this.getURIID(uri.toString()));
			res = statement.executeQuery();
		
			String object = null;
			while (res.next()) {
				if (object == null) {
					object = this.getURIString(res.getLong("OBJECT_ID"));
				}
				String revision = res.getString("VERSION_NO");
				String subject = this.getURIString(res.getLong("SUBJECT_ID"));
				String action = this.getURIString(res.getLong("ACTION_ID"));

				boolean inheritable = false;
				if (res.getInt("IS_INHERITABLE") == 1) {
					inheritable = true;
				}
				boolean negative = false;
				if (res.getInt("IS_NEGATIVE") == 1) {
					negative = true;
				}
				NodePermission permission = new NodePermission(object, revision, subject, action, inheritable, negative);
				permissionVector.addElement(permission);
			}

		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				res.close();
				statement.close();
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}

		return permissionVector.elements();
	}

	/**
	 * Create a new lock.
	 * 
	 * @param lock Lock token
	 * @exception ServiceAccessException Service access error
	 */
	public void putLock(Uri uri, NodeLock lock) throws ServiceAccessException {

		PreparedStatement 	statement = null;
		Connection 		connection = getCurrentConnection();

		try {
			int inheritable = 0;
			if (lock.isInheritable()) {
				inheritable = 1;
			}

			int exclusive = 0;
			if (lock.isExclusive()) {
				exclusive = 1;
			}
			statement = connection.prepareStatement(CREATE_LOCK);
			statement.setLong(1,this.getURIID(lock.getLockId()));
			statement.setLong(2,this.getURIID(lock.getObjectUri()));
			statement.setLong(3,this.getURIID(lock.getSubjectUri()));
			statement.setLong(4,this.getURIID(lock.getTypeUri()));
			statement.setTimestamp(5,new Timestamp(lock.getExpirationDate().getTime()));
			statement.setInt(6,inheritable);
			statement.setInt(7,exclusive);
			statement.execute();
		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				statement.close();
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}

	}

	/**
	 * Renew a lock.
	 * 
	 * @param lock Token to renew
	 * @exception ServiceAccessException Service access error
	 * @exception LockTokenNotFoundException Lock token was not found
	 */
	public void renewLock(Uri uri, NodeLock lock) throws ServiceAccessException, LockTokenNotFoundException {

		try {
			if (!isLockExist(this.getURIID(lock.getLockId()))) {
				this.putLock(uri, lock);
			}
		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		}
	}

	/**
	 * Unlock.
	 * 
	 * @param lock Token to remove
	 * @exception ServiceAccessException Service access error
	 * @exception LockTokenNotFoundException Lock token was not found
	 */
	public void removeLock(Uri uri, NodeLock lock) throws ServiceAccessException, LockTokenNotFoundException {

		PreparedStatement statement = null;
		Connection connection = getCurrentConnection();

		try {

			

			int inheritable = 0;
			if (lock.isInheritable()) {
				inheritable = 1;
			}
			statement = connection.prepareStatement(REMOVE_LOCK);
			statement.setLong(1,this.getURIID(lock.getLockId()));
			statement.execute();

		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				statement.close();
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}

	}

	/**
	 * Kill a lock.
	 * 
	 * @param lock Token to remove
	 * @exception ServiceAccessException Service access error
	 * @exception LockTokenNotFoundException Lock token was not found
	 */
	public void killLock(Uri uri, NodeLock lock) throws ServiceAccessException, LockTokenNotFoundException {

		removeLock(uri, lock);

	}

	/**
	 * Enumerate locks on an object.
	 * 
	 * @param subject Subject
	 * @return Enumeration List of locks which have been put on the subject
	 * @exception ServiceAccessException Service access error
	 */
	public Enumeration enumerateLocks(Uri uri) throws ServiceAccessException {

		Vector 			lockVector = new Vector();
		PreparedStatement 	statement = null;
		Connection 		connection = getCurrentConnection();
		ResultSet		res = null;

		try {

			statement = connection.prepareStatement(LIST_LOCKS);
			statement.setLong(1,this.getURIID(uri.toString()));
			res = statement.executeQuery();

			while (res.next()) {
				NodeLock lock = new NodeLock(this.getURIString(res.getLong("LOCK_ID")), this.getURIString(res.getLong("OBJECT_ID")), this.getURIString(res.getLong("SUBJECT_ID")), this.getURIString(res.getLong("TYPE_ID")), res.getDate("EXPIRATION_DATE"), (res.getInt("IS_INHERITABLE") == 1), (res.getInt("IS_EXCLUSIVE") == 1));
				lockVector.addElement(lock);
			}

		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				res.close();
				statement.close();
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}
		return lockVector.elements();
	}

	/**
	 * Retrieve the revisions informations of an object.
	 * 
	 * @param uri Uri
	 * @exception ServiceAccessException Service access error
	 * @exception RevisionDescriptorNotFoundException Revision descriptor 
	 * was not found
	 */
	public NodeRevisionDescriptors retrieveRevisionDescriptors(Uri uri) throws ServiceAccessException, RevisionDescriptorNotFoundException {

		NodeRevisionDescriptors revisionDescriptors = null;
		PreparedStatement statement = null;
		PreparedStatement statement2 = null;
		Connection connection = getCurrentConnection();
		ResultSet res = null;
		ResultSet res2 = null;

		try {
			

			NodeRevisionNumber initialRevision = new NodeRevisionNumber();
			Hashtable workingRevisions = new Hashtable();
			Hashtable latestRevisionNumbers = new Hashtable();
			Hashtable branches = new Hashtable();
			boolean isVersioned = false;
			long l_uriid = this.getURIID(uri.toString());
			statement = connection.prepareStatement(IS_VERSIONNED);
			statement.setLong(1,l_uriid);
			res = statement.executeQuery();
			//statement2 = connection.createStatement();
			if (res.next()) {
				int isVersionedInt = res.getInt("IS_VERSIONED");
				if (isVersionedInt == 1) {
					isVersioned = true;
				}
			} else {
				throw new RevisionDescriptorNotFoundException(uri.toString());
			}
			res.close();
			statement.close();
			statement = connection.prepareStatement(GET_REVISION_NUMBER);
			statement.setLong(1,l_uriid);
			res = statement.executeQuery();
			statement2 = connection.prepareStatement(GET_PREDECESSOR);
			while (res.next()) {
				String l_branchid = res.getString("BRANCH_STRING");

				long l_versionid = res.getLong("VERSION_ID");
				String currentRevisionNumber = res.getString("REVISION_NO");
				latestRevisionNumbers.put(l_branchid, new NodeRevisionNumber(currentRevisionNumber));

				// We parse the revision list of the object
				statement2.setLong(1,l_versionid);
				res2 = statement2.executeQuery();
				Vector childList = new Vector();

				while (res2.next()) {
					childList.addElement(new NodeRevisionNumber(this.getXNumber(res2.getLong("PREDECESSOR_ID"), l_uriid, l_branchid)));
				}

				branches.put(new NodeRevisionNumber(currentRevisionNumber), childList);

				res2.close();
			}

			revisionDescriptors = new NodeRevisionDescriptors(uri.toString(), initialRevision, workingRevisions, latestRevisionNumbers, branches, isVersioned);

		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				if(statement!=null)
					statement.close();
				if(statement2!=null)
					statement2.close();
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}
		return revisionDescriptors;
	}

	/**
	 * Create a new revision information object.
	 * 
	 * @param uri Uri
	 * @param revisionDescriptors Node revision descriptors
	 * @exception ServiceAccessException Service access error
	 */
	public void createRevisionDescriptors(Uri uri, NodeRevisionDescriptors revisionDescriptors) throws ServiceAccessException {

		// TODO : Here, we have the option of "cleaning up" before 
		// creating the new records in the database.

		PreparedStatement 	statement = null;
		Connection 		connection = getCurrentConnection();
		ResultSet		res = null;

		try {
			res = null;

			// Creating record in revisions tables

			int isVersioned = 0;
			if (revisionDescriptors.isVersioned()) {
				isVersioned = 1;
			}
			long l_urid = this.getURIID(uri.toString());
			statement = connection.prepareStatement(VERSION_EXISTS);
			statement.setLong(1,l_urid);
			res = statement.executeQuery();
			if (!res.next()) {
				statement.close();
				statement = connection.prepareStatement(INSERT_VERSION);
				statement.setLong(1,l_urid);
				statement.setInt(2,isVersioned);
				statement.execute();
				statement.close();
			} else {
				statement.close();
			}

			// For now, only the latest revision from the main branch is stored
			long l_brid = this.getBranchID(NodeRevisionDescriptors.MAIN_BRANCH.toString());
			
			statement = connection.prepareStatement(VERSION_HISTORY_EXISTS);
			statement.setLong(1,l_urid);
			statement.setLong(2,l_brid);
			if (revisionDescriptors.getLatestRevision() == null) {
				statement.setNull(3,java.sql.Types.VARCHAR);
			} else {
				statement.setString(3,revisionDescriptors.getLatestRevision().toString());
			}
			res = statement.executeQuery();
			if (!res.next()) {
				if (revisionDescriptors.getLatestRevision() != null) {
					statement.close();
					
					statement = connection.prepareStatement(INSERT_VERSION_HISTORY);
					statement.setLong(1,l_urid);
					statement.setLong(2,l_brid);
					statement.setString(3,revisionDescriptors.getLatestRevision().toString());
					res = statement.executeQuery();
				}
			}
			statement.close();
			// Creating records in the branches table
			// TODO Retained from the old Slide Schema

		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				statement.close();
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}

	}

	/**
	 * Update revision information.
	 * 
	 * @param uri Uri
	 * @param revisionDescriptors Node revision descriptors
	 * @exception ServiceAccessException Service access error
	 * @exception RevisionDescriptorNotFoundException Revision descriptor 
	 * was not found
	 */
	public void storeRevisionDescriptors(Uri uri, NodeRevisionDescriptors revisionDescriptors) throws ServiceAccessException, RevisionDescriptorNotFoundException {

		removeRevisionDescriptors(uri);
		createRevisionDescriptors(uri, revisionDescriptors);

	}

	/**
	 * Remove revision information.
	 * 
	 * @param uri Uri
	 * @exception ServiceAccessException Service access error
	 */
	public void removeRevisionDescriptors(Uri uri) throws ServiceAccessException {

		PreparedStatement statement = null;
		Connection connection = getCurrentConnection();

		try {
			long l_uriid = this.getURIID(uri.toString());

			statement = connection.prepareStatement(REMOVE_VERSION_DESC);
			statement.setLong(1,l_uriid);
			statement.execute();

		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				statement.close();
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}

	}

	/**
	 * Retrieve an individual object's revision descriptor.
	 * 
	 * @param Uri uri
	 * @param revisionNumber Node revision number
	 */
	public NodeRevisionDescriptor retrieveRevisionDescriptor(Uri uri, NodeRevisionNumber revisionNumber) throws ServiceAccessException, RevisionDescriptorNotFoundException {

		NodeRevisionDescriptor 	revisionDescriptor = null;
		PreparedStatement 		statement = null;
		Connection 				connection = getCurrentConnection();
		ResultSet 				res = null;
		if (revisionNumber == null)
			throw new RevisionDescriptorNotFoundException(uri.toString());
		try {

			
			long l_uri = this.getURIID(uri.toString());
			String branchName = null;
			Vector labels = new Vector();
			Hashtable properties = new Hashtable();

			// Retrieving branch name (and also check that revision 
			// does indeed exist)

			statement = connection.prepareStatement(SELECT_VERSION_ID_AND_BRANCH);
			statement.setLong(1,l_uri);
			statement.setString(2,revisionNumber.toString());
			res = statement.executeQuery();
			long l_Version_ID = 0;
			if (res.next()) {
				branchName = res.getString("BRANCH_STRING");
				l_Version_ID = res.getLong("VERSION_ID");
			} else {
				throw new RevisionDescriptorNotFoundException(uri.toString());
			}

			// Retrieve labels
			statement.close();
			statement = connection.prepareStatement(SELECT_LABEL_VERSION_LABEL);
			statement.setLong(1,l_Version_ID);
			res = statement.executeQuery();

			while (res.next()) {
				labels.addElement(this.getLabelName(res.getLong("LABEL_ID")));
			}
			statement.close();
			// Retrieve properties

			statement = connection.prepareStatement(SELECT_PROPERTIES);
			statement.setLong(1,l_Version_ID);
			res = statement.executeQuery();

			while (res.next()) {
				String propertyName = res.getString("PROPERTY_NAME");
				String propertyNamespace = res.getString("PROPERTY_NAMESPACE");
				NodeProperty property = new NodeProperty(propertyName, res.getString("PROPERTY_VALUE"), propertyNamespace, res.getString("PROPERTY_TYPE"), (res.getInt("IS_PROTECTED") == 1));
				properties.put(propertyNamespace + propertyName, property);
			}
			statement.close();
			revisionDescriptor = new NodeRevisionDescriptor(revisionNumber, branchName, labels, properties);

		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				statement.close();
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}

		return revisionDescriptor;
	}

	/**
	 * Create a new revision descriptor.
	 * 
	 * @param uri Uri
	 * @param revisionDescriptor Node revision descriptor
	 * @exception ServiceAccessException Service access error
	 */
	public void createRevisionDescriptor(Uri uri, NodeRevisionDescriptor revisionDescriptor) throws ServiceAccessException {

		PreparedStatement statement = null;
		Connection connection = getCurrentConnection();

		try {
			ResultSet res = null;

			long l_uri = this.getURIID(uri.toString());
			long l_brid = this.getBranchID(revisionDescriptor.getBranchName());
			if (l_brid == 0) {
				this.setBranchID(revisionDescriptor.getBranchName());
				l_brid = this.getBranchID(revisionDescriptor.getBranchName());
			}
			
			statement = connection.prepareStatement(VERSION_HISTORY_EXISTS);
			statement.setLong(1,l_uri);
			statement.setLong(2,l_brid);
			statement.setString(3,revisionDescriptor.getRevisionNumber().toString());
			res = statement.executeQuery();

			if (!res.next()) {
				statement.close();
				statement = connection.prepareStatement(INSERT_VERSION_HISTORY);
				statement.setLong(1,l_uri);
				statement.setLong(2,l_brid);
				statement.setString(3,revisionDescriptor.getRevisionNumber().toString());
				statement.executeQuery();
			}
			statement.close();
			long Version_ID = this.getVersionID(l_uri, revisionDescriptor.getBranchName(), revisionDescriptor.getRevisionNumber().toString());

			// Creating revision labels
			Enumeration labels = revisionDescriptor.enumerateLabels();
			while (labels.hasMoreElements()) {
				String sLabel = (String) labels.nextElement();
				long l_label = this.getLabelID(sLabel);
				if (l_label == 0) {
					this.setLabelID(sLabel);
					l_label = this.getLabelID(sLabel);
				}
				statement = connection.prepareStatement(INSERT_VERSION_LABEL);
				statement.setLong(1,Version_ID);
				statement.setLong(2,l_label);
				statement.executeQuery();
				statement.close();
			}

			// Creating associated properties
			Enumeration properties = revisionDescriptor.enumerateProperties();
			PreparedStatement pstmt = connection.prepareStatement(INSERT_PROPERTY);
			while (properties.hasMoreElements()) {
				NodeProperty property = (NodeProperty) properties.nextElement();
				int protectedProperty = 0;
				if (property.isProtected()) {
					protectedProperty = 1;
				}
				pstmt.setLong(1, Version_ID);
				pstmt.setString(2, property.getNamespace());
				pstmt.setString(3, property.getName());
				pstmt.setString(4, property.getValue().toString());
				pstmt.setString(5, property.getType());
				pstmt.setByte(6, (byte)protectedProperty);
				pstmt.execute();
				//pstmt.addBatch();
			}
			//pstmt.executeBatch();
			pstmt.close();

		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				statement.close();
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}

	}

	/**
	 * Update a revision descriptor.
	 * 
	 * @param uri Uri
	 * @param revisionDescriptors Node revision descriptor
	 * @exception ServiceAccessException Service access error
	 * @exception RevisionDescriptorNotFoundException Revision descriptor 
	 * was not found
	 */
	public void storeRevisionDescriptor(Uri uri, NodeRevisionDescriptor revisionDescriptor) throws ServiceAccessException, RevisionDescriptorNotFoundException {
		myRevisionDescriptor = revisionDescriptor;
		removeRevisionDescriptor(uri, revisionDescriptor.getRevisionNumber());
		createRevisionDescriptor(uri, revisionDescriptor);
	}

	/**
	 * Remove a revision descriptor.
	 * 
	 * @param uri Uri
	 * @param revisionNumber Revision number
	 * @exception ServiceAccessException Service access error
	 */
	public void removeRevisionDescriptor(Uri uri, NodeRevisionNumber revisionNumber) throws ServiceAccessException {

		PreparedStatement statement = null;
		Connection connection = getCurrentConnection();

		try {
			long l_uri = this.getURIID(uri.toString());
			long Version_ID = this.getVersionID(l_uri, myRevisionDescriptor.getBranchName(), revisionNumber.toString());
			statement = connection.prepareStatement(DELETE_VERSION_LABEL);
			statement.setLong(1,Version_ID);
			statement.execute();
			statement.close();

			// Removing associated properties
			statement = connection.prepareStatement(DELETE_PROPERTIES);
			statement.setLong(1,Version_ID);
			statement.execute();
			statement.close();
		} catch (SQLException e) {
			getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
			throw new ServiceAccessException(this, e);
		} finally {
			try {
				statement.close();
			} catch (SQLException e) {
				getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
				throw new ServiceAccessException(this, e);
			}
		}

	}

	// ------------------------------------------------------ Protected Methods
	/**
	 * Retrieve the URI ID For the URI.
	 */

	protected long getURIID(String revisionUri) throws SQLException {
		PreparedStatement getStatement = null;
		try {
			Long l_urivalue = (Long) hsh_uriid_lookup.get(revisionUri);
			if (l_urivalue == null) {
				Connection connection = getCurrentConnection();
	
				getStatement = connection.prepareStatement(SELECT_URI_ID);
				getStatement.setString(1,revisionUri);
				ResultSet rslt = getStatement.executeQuery();
				if (rslt.next()) {
					long l_uriid = rslt.getLong("URI_ID");
					if (hsh_uriid_lookup.size() == 2000) {
						hsh_uriid_lookup.clear();
					}
					hsh_uriid_lookup.put(revisionUri, new Long(l_uriid));
					return l_uriid;
				} else {
					return 0;
				}
			} else {
				return l_urivalue.longValue();
			}
		} finally {
			if(getStatement!=null) {
				getStatement.close();
			}
		}
	}

	/**
	 * Retrieve the URI Name.
	 */

	protected String getURIString(long revisionUriID) throws SQLException {
		PreparedStatement getStatement = null;
		try {
			Long uri_key = new Long(revisionUriID);
			String URI_String = (String) hsh_uri_lookup.get(uri_key);
	
			if (URI_String == null) {
				Connection connection = getCurrentConnection();
	
				getStatement = connection.prepareStatement(SELECT_URI_STRING2);
				getStatement.setLong(1,revisionUriID);
				ResultSet rslt = getStatement.executeQuery();
				if (rslt.next()) {
					URI_String = rslt.getString("URI_STRING");
					if (hsh_uri_lookup.size() == 2000) {
						hsh_uri_lookup.clear();
					}
					hsh_uri_lookup.put(uri_key, URI_String);
				} else {
					return null;
				}
			}
			return URI_String;
		} finally {
			if(getStatement!=null)
				getStatement.close();
		}
	}

	/**
	 * Add the URI.
	 */

	protected void setURIID(String revisionUri) throws SQLException {
		PreparedStatement addStatement = null;
		if (this.getURIID(revisionUri) == 0) {
			try {
				Connection connection = getCurrentConnection();
				addStatement = connection.prepareStatement(INSERT_URI_STRING);
				addStatement.setString(1,revisionUri);
				addStatement.execute();
			} finally {
				if(addStatement!=null)
					addStatement.close();
			}
		}
	}

	/**
	 * Retrieve the Branch ID For the given Branch.
	 */

	protected long getBranchID(String branchName) throws SQLException {
		PreparedStatement getStatement = null;
		try {
			Connection connection = getCurrentConnection();
	
			getStatement = connection.prepareStatement(SELECT_BRANCH_ID);
			getStatement.setString(1,branchName);
			ResultSet rslt = getStatement.executeQuery();
			if (rslt.next()) {
				return rslt.getLong("BRANCH_ID");
			} else {
				return 0;
			}
		} finally {
			if(getStatement!=null) 
				getStatement.close();
		}
	}

	/**
	 * Add the branchname and id
	 */

	protected void setBranchID(String branchName) throws SQLException {
		PreparedStatement addStatement = null;
		try {
			if (this.getBranchID(branchName) == 0) {
				Connection connection = getCurrentConnection();
				addStatement = connection.prepareStatement(CREATE_BRANCH);
				addStatement.setString(1,branchName);
				addStatement.execute();
			}
		} finally {
			if(addStatement!=null) 
				addStatement.close();
		}
	}

	/**
	 * Retrieve the label ID For the labelName.
	 */

	protected long getLabelID(String labelName) throws SQLException {
		PreparedStatement getStatement = null;
		try {
			Connection connection = getCurrentConnection();
	
			getStatement = connection.prepareStatement(GET_LABEL_ID);
			getStatement.setString(1,labelName);
			ResultSet rslt = getStatement.executeQuery();
			if (rslt.next()) {
				return rslt.getLong("LABEL_ID");
			} else {
				return 0;
			}
		} finally {
			if(getStatement!=null) {
				getStatement.close();
			}
		}
	}

	/**
	 * Retrieve the label NAME For the labelid.
	 */

	protected String getLabelName(long labelID) throws SQLException {

		PreparedStatement getStatement = null;
		try {
			Connection connection = getCurrentConnection();
	
			getStatement = connection.prepareStatement(GET_LABEL_ID);
			getStatement.setLong(1,labelID);
			ResultSet rslt = getStatement.executeQuery();
			if (rslt.next()) {
				return rslt.getString("LABEL_STRING");
			} else {
				return null;
			}
		} finally {
			if(getStatement!=null) {
				getStatement.close();
			}
		}
	}

	/**
	 * Add the labelName and id
	 */

	protected void setLabelID(String labelName) throws SQLException {
		PreparedStatement addStatement = null;
		try {
			if (this.getBranchID(labelName) == 0) {
				Connection connection = getCurrentConnection();
				addStatement = connection.prepareStatement(CREATE_LABEL);
				addStatement.setString(1,labelName);
				addStatement.execute();
				addStatement.close();
			}
		} finally {
			if(addStatement!=null) 
				addStatement.close();
		}
	}

	/**
	* Filter for all the new children
	*/

	protected Enumeration getNewChildren(long parent, Enumeration childlist) throws SQLException {
		PreparedStatement getStatement = null;
		try {
			Hashtable hshtempHash = new Hashtable();
			Hashtable hshnewChild = new Hashtable();
			Connection connection = getCurrentConnection();
			getStatement = connection.prepareStatement(GET_CHILDREN);
			getStatement.setLong(1,parent);
			ResultSet rslt = getStatement.executeQuery();
			String s_child = null;
			while (rslt.next()) {
				s_child = rslt.getString("URI_STRING");
				hshtempHash.put(s_child, s_child);
			}
			while (childlist.hasMoreElements()) {
				String temp_child = (String) childlist.nextElement();
				if (hshtempHash.containsKey(temp_child)) {} else {
					hshnewChild.put(temp_child, temp_child);
				}
			}
			hshtempHash.clear();
			return hshnewChild.elements();
		} finally {
			if(getStatement!=null) {
				getStatement.close();
			}
		}
	}

	/**
	* Check if the Link exist.
	*/

	protected boolean isLinkExist(long parent, long child) throws SQLException {
		PreparedStatement getStatement = null;
		try {
			Connection connection = getCurrentConnection();
			getStatement = connection.prepareStatement(LINK_EXISTS);
			getStatement.setLong(1,parent);
			getStatement.setLong(2,child);
			ResultSet rslt = getStatement.executeQuery();
			return rslt.next();
		} finally {
			if(getStatement!=null)
				getStatement.close();
		}
	}

	/**
	* Check if the Lock exist.
	*/

	protected boolean isLockExist(long parent) throws SQLException {
		PreparedStatement getStatement = null;
		try {
			Connection connection = getCurrentConnection();
			getStatement = connection.prepareStatement(LOCK_EXISTS);
			getStatement.setLong(1,parent);
			ResultSet rslt = getStatement.executeQuery();
			return rslt.next();
		} finally {
			if(getStatement!=null)
				getStatement.close();
		}
	}

	/**
	* Get the VersionID for the current URI
	*/
	protected long getVersionID(long uri_id, String branch_name, String sXNumber) throws SQLException {
		PreparedStatement getStatement = null;
		try {
			Connection connection = getCurrentConnection();
			getStatement = connection.prepareStatement(GET_VERSION_ID);
			getStatement.setLong(1,uri_id);
			getStatement.setString(2,branch_name);
			getStatement.setString(3,sXNumber);
			ResultSet rslt = getStatement.executeQuery();
			if (rslt.next()) {
				return rslt.getLong("VERSION_ID");
			} else {
				return 0;
			}
		} finally {
			if(getStatement!=null)
				getStatement.close();
		}
	}

	/**
	* Get the XNUMBER for the current URI
	*/

	protected String getXNumber(long version_id, long uri_id, String branch_name) throws SQLException {
		PreparedStatement getStatement = null;
		try {
			Connection connection = getCurrentConnection();
			getStatement = connection.prepareStatement(GET_XNUMBER);
			getStatement.setLong(1,version_id);
			getStatement.setLong(2,uri_id);
			getStatement.setString(3,branch_name);
			ResultSet rslt = getStatement.executeQuery();
			if (rslt.next()) {
				return rslt.getString("REVISION_NO");
			} else {
				return null;
			}
		} finally {
			if(getStatement!=null)
				getStatement.close();
		}
	}

}