Package org.apache.xindice.client.xmldb.embed

Source Code of org.apache.xindice.client.xmldb.embed.CollectionImpl

/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* 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.
*
* CVS $Id: CollectionImpl.java,v 1.34 2004/03/30 14:01:07 vgritsenko Exp $
*/

package org.apache.xindice.client.xmldb.embed;

import org.apache.xindice.client.xmldb.ResourceSetImpl;
import org.apache.xindice.client.xmldb.XindiceCollection;
import org.apache.xindice.client.xmldb.resources.BinaryResourceImpl;
import org.apache.xindice.client.xmldb.resources.XMLResourceImpl;
import org.apache.xindice.core.Collection;
import org.apache.xindice.core.Database;
import org.apache.xindice.core.FaultCodes;
import org.apache.xindice.core.data.NodeSet;
import org.apache.xindice.core.meta.MetaData;
import org.apache.xindice.core.query.QueryUtil;
import org.apache.xindice.util.Configuration;
import org.apache.xindice.xml.dom.DocumentImpl;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xmldb.api.base.ErrorCodes;
import org.xmldb.api.base.Resource;
import org.xmldb.api.base.ResourceSet;
import org.xmldb.api.base.XMLDBException;
import org.xmldb.api.modules.BinaryResource;
import org.xmldb.api.modules.XMLResource;

import java.util.Hashtable;
import java.util.StringTokenizer;

/**
* Implementation of XML:DB's <code>Collection</code> interface using
* direct access to interact with database server
*
* @author <a href="mailto:james.bates@amplexor.com">James Bates</a>
* @author <a href="mailto:kstaken@xmldatabases.org">Kimbro Staken</a>
* @version CVS $Revision: 1.34 $, $Date: 2004/03/30 14:01:07 $
*/
public class CollectionImpl extends XindiceCollection {

    private Database db = null;
    private Collection col = null;

    /**
     * Creates new <code>CollectionImpl</code> instance representing connection
     * to server collection.
     *
     * @param db Database this collection resides in
     * @param collPath Canonical path of this collection (including database name)
     * @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 CollectionImpl(Database db, String collPath) throws XMLDBException {
        super(collPath);
        this.db = db;

        // Extract path of the collection within database
        String collName = "/";
        int colIndex = collPath.indexOf('/', 1);
        if (colIndex != -1) {
            collName = collPath.substring(colIndex);
            if (collName.equals("")) {
                collName = "/";
            }
        }

        try {
            this.col = db.getCollection(collName);
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(ErrorCodes.INVALID_COLLECTION,
                                                  "Collection not available: " + collPath, e);
        }

        if (this.col == null) {
            throw new XMLDBException(ErrorCodes.NO_SUCH_COLLECTION,
                                     "Collection not found: " + collPath);
        }
    }

    /**
     * Retrieves a <code>Resource</code> from the database. If the
     * <code>Resource</code> could not be
     * located a null value will be returned.
     *
     * @param id the unique id for the requested resource.
     * @return The retrieved <code>Resource</code> instance.
     * @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 Resource getResource(String id) throws XMLDBException {

        checkOpen();
        try {
            Object entry = col.getEntry(id);
            if (entry == null) {
                return null;
            } else if (entry instanceof Document) {
                DocumentImpl doc = (DocumentImpl) entry;

                // This should probably just pass the document.
                return new XMLResourceImpl(id, id, this,
                                           doc.getSymbols(),
                                           doc.getDataBytes());

            } else if (entry instanceof byte[]) {
                return new BinaryResourceImpl(id, this, (byte[])entry);
            } else {
                throw new XMLDBException(ErrorCodes.UNKNOWN_RESOURCE_TYPE,
                                         "Internal error: Unexpected resource type " + entry.getClass().getName());
            }
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException("Resource not available: " + id, e);
        }
    }

    /**
     * Returns the number of resources currently stored in this collection or 0
     * if the collection is empty.
     *
     * @return the number of resource in the collection.
     * @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 int getResourceCount() throws XMLDBException {

        checkOpen();
        try {
            return (int) col.getDocumentCount();
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(e);
        }
    }

    /**
     * Stores the provided resource into the database. If the resource does not
     * already exist it will be created. If it does already exist it will be
     * updated.
     *
     * @param res the resource to store in the database.
     * @exception XMLDBException with expected error codes.<br />
     <code>ErrorCodes.VENDOR_ERROR</code> for any vendor
     *  specific errors that occur.<br />
     <code>ErrorCodes.INVALID_RESOURCE</code> if the <code>Resource</code> is
     *   not valid.
     *  <code>ErrorCodes.COLLECTION_CLOSED</code> if the <code>close</code>
     *  method has been called on the <code>Collection</code><br />
     */
    public void storeResource(Resource res) throws XMLDBException {
        if (res.getContent() == null) {
            throw new XMLDBException(ErrorCodes.INVALID_RESOURCE,
                                     "No resource data");
        }

        checkOpen();

        if (res instanceof BinaryResource) {
            Object content = res.getContent();
            byte[] bytes;
            if (content instanceof byte[]) {
                bytes = (byte[]) content;
            } else {
                throw new XMLDBException(ErrorCodes.INVALID_RESOURCE,
                                         "The contents of a binary resource must have type byte[].");
            }

            try {
                if (res.getId() != null) {
                    col.insertBinary(res.getId(), bytes);
                } else {
                    String name = col.insertBinary(bytes).toString();
                    ((BinaryResourceImpl) res).setId(name);
                }
            } catch (Exception e) {
                throw FaultCodes.createXMLDBException(ErrorCodes.INVALID_RESOURCE,
                                                      "Invalid resource:" + res.getId(), e);
            }

        } else if (res instanceof XMLResource) {
            try {
                String name = "";
                Node content = ((XMLResourceImpl) res).getContentAsDOM();
                if (content != null && content instanceof Document) {
                    if (res.getId() != null) {
                        col.insertDocument(res.getId(), (Document) content);
                    } else {
                        name = col.insertDocument((Document) content).toString();
                        ((XMLResourceImpl) res).setId(name);
                    }
                } else {
                    throw new XMLDBException(ErrorCodes.INVALID_RESOURCE,
                                             "A resource must be a document in order to be stored.");
                }
            } catch (Exception e) {
                throw FaultCodes.createXMLDBException(ErrorCodes.INVALID_RESOURCE,
                                                      "Invalid resource: " + res.getId(), e);
            }

        } else {
            throw new XMLDBException(ErrorCodes.INVALID_RESOURCE,
                                     "Only XMLResource and BinaryResource supported");
        }
    }

    /* see superclass for documentation */
    public boolean isOpen() {
        return (col != null);
    }

    /* see superclass for documentation */
    public String getURI() {
        return "xmldb:" + DatabaseImpl.DRIVER_NAME + "://" + getCanonicalName();
    }

    /**
     * Returns a <code>Collection</code> instance for the requested child collection
     * if it exists.
     *
     * @param name the name of the child collection to retrieve.
     * @return the requested child collection or null if it couldn't 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.Collection getChildCollection(String name) throws XMLDBException {

        if (name.indexOf('/') != -1) {
            throw new XMLDBException(ErrorCodes.INVALID_COLLECTION,
                                     "Invalid collection: " + name);
        }

        try {
            return new CollectionImpl(db, getCanonicalName() + "/" + name);
        } catch (XMLDBException e) {
            if (e.errorCode == ErrorCodes.NO_SUCH_COLLECTION) {
                // per getChildCollection contract, return null if not found
                return null;
            }
            throw e;
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(ErrorCodes.INVALID_COLLECTION,
                                                  "Invalid collection: " + name, e);
        }
    }

    /**
     * Creates a new unique ID within the context of the <code>Collection</code>
     *
     * @return the created id as a string.
     * @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 String createId() throws XMLDBException {

        checkOpen();
        try {
            return col.createNewOID().toString();
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(e);
        }
    }

    /**
     * Releases all resources consumed by the <code>Collection</code>.
     * The <code>close</code> method must
     * always be called when use of a <code>Collection</code> is complete. It is
     * not safe to use a  <code>Collection</code> after the <code>close</code>
     * method has been called.
     *
     * @exception XMLDBException with expected error codes.<br />
     <code>ErrorCodes.VENDOR_ERROR</code> for any vendor
     *  specific errors that occur.<br />
     */
    public void close() throws XMLDBException {
        col = null;
        // FIXME Should not be necessary here:
        db.flushConfig();
    }

    /**
     * Returns the parent collection for this collection or null if no parent
     * collection exists.
     *
     * @return the parent <code>Collection</code> instance.
     * @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.Collection getParentCollection() throws XMLDBException {

        // If there's only one slash then it's the root.
        if (collPath.lastIndexOf("/") == 0) {
            return null;
        }

        try {
            return new CollectionImpl(db, collPath.substring(0, collPath.lastIndexOf('/')));
        } catch (XMLDBException e) {
            if (e.errorCode == ErrorCodes.NO_SUCH_COLLECTION) {
                // per getParentCollection contract, return null if no parent
                return null;
            }
            throw e;
        }
    }

    /**
     * Removes the <code>Resource</code> from the database.
     *
     * @param res the resource to remove.
     * @exception XMLDBException with expected error codes.<br />
     <code>ErrorCodes.VENDOR_ERROR</code> for any vendor
     *  specific errors that occur.<br />
     <code>ErrorCodes.INVALID_RESOURCE</code> if the <code>Resource</code> is
     *   not valid.<br />
     <code>ErrorCodes.NO_SUCH_RESOURCE</code> if the <code>Resource</code> is
     *   not known to this <code>Collection</code>.
     *  <code>ErrorCodes.COLLECTION_CLOSED</code> if the <code>close</code>
     *  method has been called on the <code>Collection</code><br />
     */
    public void removeResource(Resource res) throws XMLDBException {

        if (res == null || res.getId() == null || res.getId().length() == 0) {
            // Query result resource will have null ID
            throw new XMLDBException(ErrorCodes.INVALID_RESOURCE,
                                     "Resource passed is null or its ID is empty.");
        }

        checkOpen();
        try {
            col.remove(res.getId());
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(e);
        }
    }

    /**
     * Returns a list of collection names naming all child collections
     * of the current collection. If no child collections exist an empty list is
     * returned.
     *
     * @return an array containing collection names for all child
     *      collections.
     * @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 String[] listChildCollections() throws XMLDBException {

        checkOpen();
        try {
            return col.listCollections();
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(e);
        }
    }

    /**
     * Returns the number of child collections under this
     * <code>Collection</code> or 0 if no child collections exist.
     *
     * @return the number of child collections.
     * @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 int getChildCollectionCount() throws XMLDBException {

        checkOpen();
        try {
            return (int) col.countCollections();
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(e);
        }
    }

    /**
     * Returns a list of the ids for all resources stored in the collection.
     *
     * @return a string array containing the names for all
     *  <code>Resource</code>s in the collection.
     * @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 String[] listResources() throws XMLDBException {

        checkOpen();
        try {
            return col.listDocuments();
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(e);
        }
    }

    /* see superclass for documentation */
    public ResourceSet query(String name, String queryLang, String query, Hashtable nsMap) throws XMLDBException {

        checkOpen();
        try {
            NodeSet nodeSet;
            if (name != null) {
                nodeSet = col.queryDocument(queryLang, query, QueryUtil.mapNamespaces(nsMap), name);
            } else {
                nodeSet = col.queryCollection(queryLang, query, QueryUtil.mapNamespaces(nsMap));
            }

            return new ResourceSetImpl(this, QueryUtil.queryResultsToDOM(nodeSet));
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(FaultCodes.QRY_PROCESSING_ERROR,
                                                  "Query error: " + e.getMessage(), e);
        }
    }

    /* see superclass for documentation */
    public org.xmldb.api.base.Collection createCollection(String name) throws XMLDBException {

        checkOpen();
        try {
            Document doc = new DocumentImpl();

            Element colEle = doc.createElement("collection");
            colEle.setAttribute("compressed", "true");
            colEle.setAttribute("name", name);
            doc.appendChild(colEle);

            Element filEle = doc.createElement("filer");
            filEle.setAttribute("class", "org.apache.xindice.core.filer.BTreeFiler");
            colEle.appendChild(filEle);

            return createCollection(name, doc);
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(ErrorCodes.INVALID_COLLECTION,
                                                  FaultCodes.GEN_UNKNOWN,
                                                  "Cannot create child collection", e);
        }
    }

    // See superclass for documentation. Note that first argument is the path, not the name.
    public org.xmldb.api.base.Collection createCollection(String path, Document configuration) throws XMLDBException {
        checkOpen();
        try {
            Configuration config = new Configuration(configuration.getDocumentElement(), false);
            col.createCollection(path, config);

            // Traverse path to get newly created collection
            org.xmldb.api.base.Collection col = this;
            if (path.indexOf("/") != -1) {
                StringTokenizer st = new StringTokenizer(path, "/");
                while (col != null && st.hasMoreTokens()) {
                    path = st.nextToken().trim();
                    if (path.length() == 0) {
                        continue;
                    }

                    if (st.hasMoreTokens()) {
                        col = col.getChildCollection(path);
                    } else {
                        break;
                    }
                }
            }

            return col.getChildCollection(path);
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(ErrorCodes.INVALID_COLLECTION,
                                                  FaultCodes.GEN_UNKNOWN,
                                                  "Cannot create child collection", e);
        }
    }

    /* see superclass for documentation */
    public void removeCollection(String childName) throws XMLDBException {

        if (null == childName || childName.length() == 0) {
            throw new XMLDBException(ErrorCodes.NO_SUCH_COLLECTION,
                                     FaultCodes.COL_COLLECTION_NOT_FOUND,
                                     "Cannot remove child collection '" + childName + "': Name is empty");
        }

        checkOpen();
        try {
            col.dropCollection(col.getCollection(childName));
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(ErrorCodes.INVALID_COLLECTION,
                                                  FaultCodes.GEN_UNKNOWN,
                                                  "Cannot remove child collection '" + childName + "'", e);
        }
    }

    /* see superclass for documentation */
    public String[] listIndexers() throws XMLDBException {
        checkOpen();
        try {
            return col.listIndexers();
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(e);
        }
    }

    /* see superclass for documentation */
    public void createIndexer(Document configuration) throws XMLDBException {
        checkOpen();
        try {
            col.createIndexer(new Configuration(configuration, false));
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(e);
        }
    }

    /* see superclass for documentation */
    public void dropIndexer(String name) throws XMLDBException {
        checkOpen();
        try {
            col.dropIndexer(col.getIndexer(name));
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(e);
        }
    }

    /* see superclass for documentation */
    public void shutdown() throws XMLDBException {
        try {
            db.close();
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(e);
        }
    }

    public MetaData getMetaData(String id) throws XMLDBException {
        try {
            if (id == null) {
                return col.getCollectionMeta();
            } else {
                return col.getDocumentMeta(id);
            }
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(e);
        }
    }

    public void setMetaData(String id, MetaData meta) throws XMLDBException {
        try {
            if (id == null) {
                col.setCollectionMeta(meta);
            } else {
                col.setDocumentMeta(id, meta);
            }
        } catch (Exception e) {
            throw FaultCodes.createXMLDBException(e);
        }
    }
}
TOP

Related Classes of org.apache.xindice.client.xmldb.embed.CollectionImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.