/*
* eXist Open Source Native XML Database
* Copyright (C) 2001-2007 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $Id$
*/
package org.exist.xmldb;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.Properties;
import java.util.Vector;
import org.exist.EXistException;
import org.exist.Namespaces;
import org.exist.dom.NodeProxy;
import org.exist.dom.SortedNodeSet;
import org.exist.security.User;
import org.exist.storage.BrokerPool;
import org.exist.storage.DBBroker;
import org.exist.storage.serializers.Serializer;
import org.exist.util.serializer.SAXSerializer;
import org.exist.util.serializer.SerializerPool;
import org.exist.xquery.XPathException;
import org.exist.xquery.value.AtomicValue;
import org.exist.xquery.value.Item;
import org.exist.xquery.value.NodeValue;
import org.exist.xquery.value.Sequence;
import org.exist.xquery.value.SequenceIterator;
import org.exist.xquery.value.Type;
import org.exist.xquery.value.ValueSequence;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.xmldb.api.base.ErrorCodes;
import org.xmldb.api.base.Resource;
import org.xmldb.api.base.ResourceIterator;
import org.xmldb.api.base.ResourceSet;
import org.xmldb.api.base.XMLDBException;
public class LocalResourceSet implements ResourceSet {
protected BrokerPool brokerPool;
protected LocalCollection collection;
protected Vector resources = new Vector();
protected Properties outputProperties;
private User user;
private LocalResourceSet() {}
public LocalResourceSet(
User user,
BrokerPool pool,
LocalCollection col,
Properties properties,
Sequence val,
String sortExpr)
throws XMLDBException {
if(col == null)
throw new NullPointerException("Collection cannot be null");
this.user = user;
this.brokerPool = pool;
this.outputProperties = properties;
this.collection = col;
if(val.isEmpty())
return;
if(Type.subTypeOf(val.getItemType(), Type.NODE) && sortExpr != null) {
SortedNodeSet sorted = new SortedNodeSet(brokerPool, user, sortExpr, collection.getAccessContext());
try {
sorted.addAll(val);
} catch (XPathException e) {
throw new XMLDBException(ErrorCodes.INVALID_RESOURCE,
e.getMessage(), e);
}
val = sorted;
}
Item item;
try {
for(SequenceIterator i = val.iterate(); i.hasNext(); ) {
item = i.nextItem();
resources.add(item);
}
} catch (XPathException e) {
throw new XMLDBException(ErrorCodes.INVALID_RESOURCE,
e.getMessage(), e);
}
}
public void addResource(Resource resource) throws XMLDBException {
resources.add(resource);
}
public void clear() throws XMLDBException {
resources.clear();
}
public ResourceIterator getIterator() throws XMLDBException {
return new NewResourceIterator();
}
public ResourceIterator getIterator(long start) throws XMLDBException {
return new NewResourceIterator(start);
}
public Resource getMembersAsResource() throws XMLDBException {
SAXSerializer handler = (SAXSerializer) SerializerPool.getInstance().borrowObject(SAXSerializer.class);
StringWriter writer = new StringWriter();
handler.setOutput(writer, outputProperties);
DBBroker broker = null;
try {
broker = brokerPool.get(user);
// configure the serializer
Serializer serializer = broker.getSerializer();
serializer.reset();
collection.properties.setProperty(Serializer.GENERATE_DOC_EVENTS, "false");
serializer.setProperties(outputProperties);
serializer.setUser(user);
serializer.setSAXHandlers(handler, handler);
// serialize results
handler.startDocument();
handler.startPrefixMapping("exist", Namespaces.EXIST_NS);
AttributesImpl attribs = new AttributesImpl();
attribs.addAttribute(
"",
"hitCount",
"hitCount",
"CDATA",
Integer.toString(resources.size()));
handler.startElement(
Namespaces.EXIST_NS,
"result",
"exist:result",
attribs);
Item current;
char[] value;
for(Iterator i = resources.iterator(); i.hasNext(); ) {
current = (Item)i.next();
if(Type.subTypeOf(current.getType(), Type.NODE)) {
((NodeValue)current).toSAX(broker, handler, outputProperties);
} else {
value = current.toString().toCharArray();
handler.characters(value, 0, value.length);
}
}
handler.endElement(Namespaces.EXIST_NS, "result", "exist:result");
handler.endPrefixMapping("exist");
handler.endDocument();
} catch (EXistException e) {
throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, "serialization error", e);
} catch (SAXException e) {
throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, "serialization error", e);
} finally {
brokerPool.release(broker);
}
Resource res = new LocalXMLResource(user, brokerPool, collection, XmldbURI.EMPTY_URI);
res.setContent(writer.toString());
SerializerPool.getInstance().returnObject(handler);
return res;
}
public Resource getResource(long pos) throws XMLDBException {
if (pos < 0 || pos >= resources.size())
return null;
Object r = resources.get((int) pos);
LocalXMLResource res = null;
if (r instanceof NodeProxy) {
NodeProxy p = (NodeProxy) r;
// the resource might belong to a different collection
// than the one by which this resource set has been
// generated: adjust if necessary.
LocalCollection coll = collection;
if (p.getDocument().getCollection() == null
|| coll.getCollection().getId() != p.getDocument().getCollection().getId()) {
coll = new LocalCollection(user, brokerPool, null, p.getDocument().getCollection().getURI(), coll.getAccessContext());
coll.properties = outputProperties;
}
res = new LocalXMLResource(user, brokerPool, coll, p);
} else if (r instanceof Node) {
res = new LocalXMLResource(user, brokerPool, collection, XmldbURI.EMPTY_URI);
res.setContentAsDOM((Node)r);
} else if (r instanceof AtomicValue) {
res = new LocalXMLResource(user, brokerPool, collection, XmldbURI.EMPTY_URI);
res.setContent(r);
} else if (r instanceof Resource)
return (Resource) r;
res.setProperties(outputProperties);
return res;
}
public Sequence toSequence() {
if (resources.size() == 0)
return Sequence.EMPTY_SEQUENCE;
if (resources.size() == 1)
return ((Item) resources.get(0)).toSequence();
ValueSequence s = new ValueSequence();
for (int i = 0; i < resources.size(); i++) {
Item item = (Item) resources.get(i);
s.add(item);
}
return s;
}
/**
* Gets the size attribute of the LocalResourceSet object
*
*@return The size value
*@exception XMLDBException Description of the Exception
*/
public long getSize() throws XMLDBException {
return resources.size();
}
/**
* Description of the Method
*
*@param pos Description of the Parameter
*@exception XMLDBException Description of the Exception
*/
public void removeResource(long pos) throws XMLDBException {
resources.removeElementAt((int) pos);
}
/**
* Description of the Class
*
*@author wolf
*@created 3. Juni 2002
*/
class NewResourceIterator implements ResourceIterator {
long pos = 0;
/** Constructor for the NewResourceIterator object */
public NewResourceIterator() {
}
/**
* Constructor for the NewResourceIterator object
*
*@param start Description of the Parameter
*/
public NewResourceIterator(long start) {
pos = start;
}
/**
* Description of the Method
*
*@return Description of the Return Value
*@exception XMLDBException Description of the Exception
*/
public boolean hasMoreResources() throws XMLDBException {
return pos < getSize();
}
/**
* Description of the Method
*
*@return Description of the Return Value
*@exception XMLDBException Description of the Exception
*/
public Resource nextResource() throws XMLDBException {
return getResource(pos++);
}
}
}