/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*
* $Id: XindiceCollection.java 511426 2007-02-25 03:25:02Z vgritsenko $
*/
package org.apache.xindice.client.xmldb;
import org.apache.xindice.client.xmldb.resources.XMLResourceImpl;
import org.apache.xindice.client.xmldb.resources.BinaryResourceImpl;
import org.apache.xindice.client.xmldb.services.CollectionManagementServiceImpl;
import org.apache.xindice.client.xmldb.services.MetaService;
import org.apache.xindice.client.xmldb.services.XPathQueryServiceImpl;
import org.apache.xindice.client.xmldb.services.XUpdateQueryServiceImpl;
import org.apache.xindice.core.FaultCodes;
import org.apache.xindice.core.meta.MetaData;
import org.apache.xindice.xml.NodeSource;
import org.w3c.dom.Document;
import org.xmldb.api.base.Collection;
import org.xmldb.api.base.ErrorCodes;
import org.xmldb.api.base.Resource;
import org.xmldb.api.base.ResourceSet;
import org.xmldb.api.base.Service;
import org.xmldb.api.base.XMLDBException;
import java.util.Enumeration;
import java.util.Hashtable;
/**
* This is a base XML:DB Collection that is extended by all Xindice
* XML:DB API drivers. It includes the functionality that is common to
* all drivers and abstract methods for all other driver specific methods.
* This enables the implementation of drivers in just two classes and the
* use of common services implementations.
*
* @author <a href="mailto:kstaken@xmldatabases.org">Kimbro Staken</a>
* @author <a href="mailto:james.bates@amplexor.com">James Bates</a>
* @version $Revision: 511426 $, $Date: 2007-02-24 22:25:02 -0500 (Sat, 24 Feb 2007) $
*/
public abstract class XindiceCollection extends CommonConfigurable implements Collection {
/**
* Xindice query result meta-info namespace
*/
public static final String QUERY_NS = NodeSource.SOURCE_NS;
/**
* Instantiated named services map
*/
protected final Hashtable services = new Hashtable();
/**
* Path to the collection on target server
*/
protected final String collPath;
/**
* Creates new <code>CollectionImpl</code> instance representing connection
* to server collection.
*
* @exception XMLDBException thrown if a connection could not be established,
* because of URL syntax errors, or connection failure, or if no
* collection with path <code>collPath</code> could be located.
*/
public XindiceCollection(String collPath) throws XMLDBException {
this.collPath = collPath.endsWith("/") ? collPath.substring(0, collPath.length() - 1) : collPath;
// Register all services supported by this collection implementation.
final XPathQueryServiceImpl xpath = new XPathQueryServiceImpl();
xpath.setCollection(this);
// xpath.setSymbolDeserializer(syms);
registerService(xpath);
final XUpdateQueryServiceImpl xupdate = new XUpdateQueryServiceImpl();
xupdate.setCollection(this);
registerService(xupdate);
// TODO if (this.col.isMetaEnabled()) {
final MetaService meta = new MetaService();
meta.setCollection(this);
registerService(meta);
try {
final CollectionManagementServiceImpl manager = new CollectionManagementServiceImpl();
manager.setCollection(this);
registerService(manager);
// CollectionManagementServiceImpl provides both standard access as a
// CollectionManagementService and Xindice specific access as a
// CollectionManager and DatabaseInstanceManager.
// We need to register it explicitly to make it available
services.put("CollectionManager" + manager.getVersion(), manager);
services.put("DatabaseInstanceManager" + manager.getVersion(), manager);
} catch (Exception e) {
throw FaultCodes.createXMLDBException(e);
}
}
/**
* Provides a list of all services known to the collection. If no services
* are known an empty list is returned.
*
* @return An array of registered <code>Service</code> implementations.
* @exception XMLDBException with expected error codes.<br />
* <code>ErrorCodes.VENDOR_ERROR</code> for any vendor
* specific errors that occur.<br />
* <code>ErrorCodes.COLLECTION_CLOSED</code> if the <code>close</code>
* method has been called on the <code>Collection</code><br />
*/
public Service[] getServices() throws XMLDBException {
checkOpen();
Enumeration e = services.elements();
Service[] result = new Service[services.size()];
int i = 0;
while (e.hasMoreElements()) {
result[i] = (Service) e.nextElement();
i++;
}
return result;
}
/**
* Returns a <code>Service</code> instance for the requested service name and version. If
* no <code>Service</code> exists for those parameters a null value is returned.
*
* @param name Description of Parameter
* @param version Description of Parameter
* @return the Service instance or null if no Service could be found.
* @exception XMLDBException with expected error codes.<br />
* <code>ErrorCodes.VENDOR_ERROR</code> for any vendor
* specific errors that occur.<br />
* <code>ErrorCodes.COLLECTION_CLOSED</code> if the <code>close</code>
* method has been called on the <code>Collection</code><br />
*/
public org.xmldb.api.base.Service getService(String name, String version) throws XMLDBException {
checkOpen();
Service result = (Service) services.get(name + version);
return result;
}
/**
* Registers a new Service with this Collection.
*
* @param service Description of Parameter
* @exception XMLDBException
*/
public void registerService(org.xmldb.api.base.Service service) throws XMLDBException {
service.setCollection(this);
services.put(service.getName() + service.getVersion(), service);
}
/**
* Checks if the collection is still open. Only open collections are safe
* to work with.
*
* @return whether the collection is still open
*/
public abstract boolean isOpen();
/**
* Throws an exception if collection is no longer open
*
* @exception XMLDBException thrown if collection is closed
*/
protected void checkOpen() throws XMLDBException {
if (!isOpen()) {
throw new XMLDBException(ErrorCodes.COLLECTION_CLOSED);
}
}
/**
* Returns the name associated with the <code>Collection</code> instance.
*
* @return the name of the object.
*/
public String getName() {
return collPath.substring(collPath.lastIndexOf('/') + 1);
}
/**
* Returns complete path to collection
*
* @return the collection path
*/
public String getCanonicalName() {
return collPath;
}
/**
* Returns XML:DB URI that would retrieve this collection
*
* @return a complete XML:DB URI
*/
public abstract String getURI();
/**
* Constructs a new resource that will belong in this collection.
*
* Only XML resources are supported. To save the resource to the database, you
* must first set the resource's XML data, and then call
* <code>storeResource()</code>.
*
* @param name Name for the new resource. If it is empty or <code>null</code>, a name
* will be assigned when storing the resource in the database.
* @param type Type must be either <code>XMLResource</code> or <code>BinaryResource</code>.
* @exception XMLDBException thrown in case of an invalid resource type or name
*/
public Resource createResource(String name, String type) throws XMLDBException {
if (!"XMLResource".equals(type) && !"BinaryResource".equals(type)) {
throw new XMLDBException(ErrorCodes.UNKNOWN_RESOURCE_TYPE,
"Only XMLResource and BinaryResource supported");
}
if (name == null || name.length() == 0) {
// fulfill contract stating
// "If id is null or its value is empty then an id is generated by calling createId()."
name = createId();
} else if (name.indexOf('/') != -1) {
throw new XMLDBException(ErrorCodes.INVALID_RESOURCE,
"Name cannot contain '/'");
}
if ("XMLResource".equals(type)) {
return new XMLResourceImpl(name, this);
} else {
return new BinaryResourceImpl(name, this, null);
}
}
/**
* Queries the entire collection and resturns the result
*
* @param queryLang <code>XUpdate</code> or <code>XPath</code>
* @param query the text of the query statement
* @param nsMap namespace bindings to use when evaluating query
* @return set containing result of query
* @throws XMLDBException thrown in case of invalid query or other error
*/
public ResourceSet query(String queryLang, String query, Hashtable nsMap) throws XMLDBException {
return query(null, queryLang, query, nsMap);
}
/**
* Queries a specific document or the entire collection and returns result
*
* @param name name of document to query, or <code>null</code> to query
* entire collection.
* @param queryLang <code>XUpdate</code> or <code>XPath</code>.
* @param query the text of the query statement
* @param nsMap namespace bindings to use when evaluating query
* @return set containing result of query
* @throws XMLDBException thrown in case of invalid query or other error
*/
public abstract ResourceSet query(String name, String queryLang, String query, Hashtable nsMap) throws XMLDBException;
/**
* Creates a new child collection in this collection
*
* @param name The name for new child collection
* @return object representing newly created collection
* @exception XMLDBException thrown if collection creation fails for some
* reason
*/
public abstract Collection createCollection(String name) throws XMLDBException;
/**
* Creates a new child collection.
* If path is a simple name (no '/' character), collection will be created
* in this collection. If path contains more then one element, collection will be
* created in the corresponding sub-collection of this collection (which must
* already exist).
*
* @param path The path for new child collection
* @return object representing newly created collection
* @exception XMLDBException thrown if collection creation fails for some
* reason
*/
public abstract Collection createCollection(String path, Document configuration) throws XMLDBException;
/**
* Removes child collection from this collection
*
* @param name name of child collection
* @exception XMLDBException thrown if collection creation fails for some
* reason
*/
public abstract void removeCollection(String name) throws XMLDBException;
/**
* Returns a list of all indexers for this collection.
*
* @return the list of indexers
* @exception XMLDBException
*/
public abstract String[] listIndexers() throws XMLDBException;
/**
* Creates a new Indexer for this collection.
*
* @param configuration The configuration to use for this indexer.
* @exception XMLDBException
*/
public abstract void createIndexer(Document configuration) throws XMLDBException;
/**
* Drops the indexer from the collection
*
* @param name The name of the indexer to drop.
* @exception XMLDBException
*/
public abstract void dropIndexer(String name) throws XMLDBException;
/**
* Shutsdown the Database instance
*
* @exception XMLDBException
*/
public abstract void shutdown() throws XMLDBException;
/**
* Returns {@link MetaData} object for the specified document or the current
* collection
* @param name name of document to get meta, or <code>null</code> to get meta
* of the collection.
* @return Requested meta data object
* @exception XMLDBException thrown if unable to obtain meta information
*/
public abstract MetaData getMetaData(String name) throws XMLDBException;
/**
* Updates {@link MetaData} object for the specified document or the current
* collection
* @param name name of document to update meta, or <code>null</code> to update meta
* of the collection.
* @param meta meta data object
* @exception XMLDBException thrown if unable to obtain meta information
*/
public abstract void setMetaData(String name, MetaData meta) throws XMLDBException;
}