You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xindice-dev@xml.apache.org by ke...@apache.org on 2003/07/15 17:44:37 UTC
cvs commit: xml-xindice/java/src/org/apache/xindice/tools/command XPathQuery.java
kevinross 2003/07/15 08:44:36
Modified: java/src/org/apache/xindice/xml/dom ContainerNodeImpl.java
DocumentImpl.java CharacterDataImpl.java
ProcessingInstructionImpl.java ElementImpl.java
EntityReferenceImpl.java
java/src/org/apache/xindice/core DBObserver.java
CollectionManager.java SystemCollection.java
Collection.java
java/src/org/apache/xindice/core/filer FSFiler.java
BTree.java HashFiler.java BTreeFiler.java
java/src/org/apache/xindice/core/xupdate
XUpdateQueryResolver.java
java/src/org/apache/xindice/xml/jaxp
DocumentBuilderImpl.java
java/src/org/apache/xindice/core/indexer IndexManager.java
NameIndexer.java ValueIndexer.java
java/src/org/apache/xindice/util Configuration.java
java/src/org/apache/xindice/core/request URIMapper.java
java/src/org/apache/xindice/core/query QueryEngine.java
XPathQueryResolver.java
java/src/org/apache/xindice/xml TextWriter.java
java/src/org/apache/xindice/tools/command XPathQuery.java
Log:
Losing Exceptions fix:
1. change any catch(and no throw) with log.debug("No message", e) to log.warn(e);
2. format (of course)
3. org imports
Revision Changes Path
1.6 +416 -417 xml-xindice/java/src/org/apache/xindice/xml/dom/ContainerNodeImpl.java
Index: ContainerNodeImpl.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/dom/ContainerNodeImpl.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ContainerNodeImpl.java 4 Nov 2002 06:39:55 -0000 1.5
+++ ContainerNodeImpl.java 15 Jul 2003 15:44:34 -0000 1.6
@@ -59,20 +59,25 @@
* $Id$
*/
-import org.apache.xindice.util.ByteArrayInput;
-import org.apache.xindice.xml.SymbolTable;
-import org.apache.xindice.xml.XMLCompressedInput;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.w3c.dom.*;
-import org.w3c.dom.traversal.*;
-
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.xindice.util.ByteArrayInput;
+import org.apache.xindice.xml.SymbolTable;
+import org.apache.xindice.xml.XMLCompressedInput;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.w3c.dom.traversal.DocumentTraversal;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.NodeIterator;
+
/**
* ContainerNodeImpl performs most of the child-rearing behavior of the
* Element and Document implementations.
@@ -80,310 +85,306 @@
public abstract class ContainerNodeImpl extends NodeImpl {
- private static Log log = LogFactory.getLog("org.apache.xindice.xml");
+ private static Log log = LogFactory.getLog("org.apache.xindice.xml");
- protected NodeListImpl childNodes = new NodeListImpl(this);
+ protected NodeListImpl childNodes = new NodeListImpl(this);
- public ContainerNodeImpl() {
- }
-
- public ContainerNodeImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
- super(parentNode, data, pos, len);
- }
-
- public ContainerNodeImpl(NodeImpl parentNode, boolean dirty) {
- super(parentNode, dirty);
- }
-
- protected boolean isNodeTypeValid(short type) {
- return true;
- }
-
- protected final Node getPreviousSibling(Node node) {
- checkLoaded();
- int pos = childNodes.indexOf(node)-1;
- return pos >= 0 ? childNodes.item(pos)
- : null;
- }
-
- protected final Node getNextSibling(Node node) {
- checkLoaded();
- int pos = childNodes.indexOf(node)+1;
- return pos < childNodes.getLength() ? childNodes.item(pos)
- : null;
- }
-
- protected void checkLoaded() {
- if ( loaded )
- return;
- else
- loaded = true;
-
- try {
- if ( data != null ) {
- DocumentImpl doc = (DocumentImpl)getOwnerDocument();
- loadChildren(doc.getSymbols());
- }
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- protected final void loadChildren(SymbolTable st) throws IOException {
- ByteArrayInput bis = new ByteArrayInput(data, pos, len);
- XMLCompressedInput in = new XMLCompressedInput(bis, st);
-
- if ( getNodeType() == Node.ELEMENT_NODE ) {
- // Have to skip the attributes
- in.readSignature();
- in.readContentSize();
- in.readShort(); // Element Symbol
- int attrCount = in.readAttributeCount();
- for ( int i = 0 ; i < attrCount; i++ ) {
- in.readShort(); // Attribute Symbol
- in.skip(in.readShort()); // Attribute Length
- }
- }
- else {
- in.readInt();
- }
-
- while ( bis.available() > 0 ) {
- int pos = bis.getPos();
- /* TODO why is it used for? byte signature = */ in.readSignature();
- int len = in.readContentSize();
- if ( len == 0 )
- len = 1;
-
- switch ( in.getNodeType() ) {
-
- case Node.ELEMENT_NODE:
- childNodes.add(new ElementImpl(this, data, pos, len));
- break;
-
- case Node.TEXT_NODE:
- childNodes.add(new TextImpl(this, data, pos, len));
- break;
-
- case Node.CDATA_SECTION_NODE:
- childNodes.add(new CDATASectionImpl(this, data, pos, len));
- break;
-
- case Node.ENTITY_REFERENCE_NODE:
- childNodes.add(new EntityReferenceImpl(this, data, pos, len));
- break;
-
- case Node.ENTITY_NODE:
- childNodes.add(new EntityImpl(this, data, pos, len));
- break;
-
- case Node.PROCESSING_INSTRUCTION_NODE:
- childNodes.add(new ProcessingInstructionImpl(this, data, pos, len));
- break;
-
- case Node.COMMENT_NODE:
- childNodes.add(new CommentImpl(this, data, pos, len));
- break;
-
- case Node.NOTATION_NODE:
- childNodes.add(new NotationImpl(this, data, pos, len));
- break;
- }
-
- bis.setPos(pos);
- bis.skip(len);
- }
- }
-
- /**
- * This is a convenience method to allow easy determination of whether a
- * node has any children.
- * @return <code>true</code> if the node has any children,
- * <code>false</code> if the node has no children.
- */
- public final boolean hasChildNodes() {
- checkLoaded();
- return childNodes.getLength() > 0;
- }
-
- public final NodeList getChildNodes() {
- checkLoaded();
- return childNodes;
- }
-
- /**
- * The first child of this node. If there is no such node, this returns
- * <code>null</code>.
- */
- public final Node getFirstChild() {
- checkLoaded();
- if ( childNodes.size() > 0 )
- return childNodes.item(0);
- else
- return null;
- }
-
- /**
- * The last child of this node. If there is no such node, this returns
- * <code>null</code>.
- */
- public final Node getLastChild() {
- checkLoaded();
- if ( childNodes.size() > 0 )
- return childNodes.item(childNodes.getLength()-1);
- else
- return null;
- }
-
- /**
- * Replaces the child node <code>oldChild</code> with <code>newChild</code>
- * in the list of children, and returns the <code>oldChild</code> node. If
- * the <code>newChild</code> is already in the tree, it is first removed.
- * @param newChild The new node to put in the child list.
- * @param oldChild The node being replaced in the list.
- * @return The node replaced.
- * @exception DOMException
- * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
- * allow children of the type of the <code>newChild</code> node, or it
- * the node to put in is one of this node's ancestors.
- * <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created
- * from a different document than the one that created this node.
- * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
- * <br>NOT_FOUND_ERR: Raised if <code>oldChild</code> is not a child of
- * this node.
- */
- public final synchronized Node replaceChild(Node newChild, Node oldChild) throws DOMException {
- checkLoaded();
- checkReadOnly();
- if ( !isNodeTypeValid(newChild.getNodeType()) )
- throw EX_HIERARCHY_REQUEST;
- int idx = childNodes.indexOf(oldChild);
- if ( idx >= 0 ) {
- if ( newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE ) {
- childNodes.remove(idx);
- NodeList nl = ((DocumentFragment)newChild).getChildNodes();
- for ( int i = 0; i < nl.getLength(); i++ ) {
- NodeImpl impl = (NodeImpl)nl.item(i);
- impl.setParentNode(this);
- childNodes.add(idx+i, impl);
- }
- }
- else {
- NodeImpl impl = (NodeImpl)newChild;
- impl.setParentNode(this);
- childNodes.set(idx, impl);
- }
- }
- setDirty();
- return oldChild;
- }
-
- /**
- * Inserts the node <code>newChild</code> before the existing child node
- * <code>refChild</code>. If <code>refChild</code> is <code>null</code>,
- * insert <code>newChild</code> at the end of the list of children.
- * <br>If <code>newChild</code> is a <code>DocumentFragment</code> object,
- * all of its children are inserted, in the same order, before
- * <code>refChild</code>. If the <code>newChild</code> is already in the
- * tree, it is first removed.
- * @param newChild The node to insert.
- * @param refChild The reference node, i.e., the node before which the new
- * node must be inserted.
- * @return The node being inserted.
- * @exception DOMException
- * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
- * allow children of the type of the <code>newChild</code> node, or if
- * the node to insert is one of this node's ancestors.
- * <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created
- * from a different document than the one that created this node.
- * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
- * <br>NOT_FOUND_ERR: Raised if <code>refChild</code> is not a child of
- * this node.
- */
- public final synchronized Node insertBefore(Node newChild, Node refChild) throws DOMException {
- checkLoaded();
- checkReadOnly();
- int idx = childNodes.indexOf(refChild);
- if ( idx >= 0 ) {
- if ( !isNodeTypeValid(newChild.getNodeType()) )
- throw EX_HIERARCHY_REQUEST;
- if ( newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE ) {
- NodeList nl = ((DocumentFragment)newChild).getChildNodes();
- for ( int i = 0; i < nl.getLength(); i++ ) {
- NodeImpl impl = (NodeImpl)nl.item(i);
- impl.setParentNode(this);
- childNodes.add(idx+i, impl);
- }
- }
- else {
- NodeImpl impl = (NodeImpl)newChild;
- impl.setParentNode(this);
- childNodes.add(idx, impl);
- }
- }
- setDirty();
- return newChild;
- }
-
- /**
- * Removes the child node indicated by <code>oldChild</code> from the list
- * of children, and returns it.
- * @param oldChild The node being removed.
- * @return The node removed.
- * @exception DOMException
- * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
- * <br>NOT_FOUND_ERR: Raised if <code>oldChild</code> is not a child of
- * this node.
- */
- public final synchronized Node removeChild(Node oldChild) throws DOMException {
- checkLoaded();
- checkReadOnly();
- if ( !childNodes.remove(oldChild) )
- throw EX_NOT_FOUND;
- setDirty();
- return oldChild;
- }
-
- /**
- * Adds the node <code>newChild</code> to the end of the list of children of
- * this node. If the <code>newChild</code> is already in the tree, it is
- * first removed.
- * @param newChild The node to add.If it is a <code>DocumentFragment</code>
- * object, the entire contents of the document fragment are moved into
- * the child list of this node
- * @return The node added.
- * @exception DOMException
- * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
- * allow children of the type of the <code>newChild</code> node, or if
- * the node to append is one of this node's ancestors.
- * <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created
- * from a different document than the one that created this node.
- * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
- */
- public final synchronized Node appendChild(Node newChild) throws DOMException {
- checkLoaded();
- checkReadOnly();
- if ( !isNodeTypeValid(newChild.getNodeType()) )
- throw EX_HIERARCHY_REQUEST;
- if ( newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE ) {
- NodeList nl = ((DocumentFragment)newChild).getChildNodes();
- for ( int i = 0; i < nl.getLength(); i++ ) {
- NodeImpl impl = (NodeImpl)nl.item(i);
+ public ContainerNodeImpl() {}
+
+ public ContainerNodeImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
+ super(parentNode, data, pos, len);
+ }
+
+ public ContainerNodeImpl(NodeImpl parentNode, boolean dirty) {
+ super(parentNode, dirty);
+ }
+
+ protected boolean isNodeTypeValid(short type) {
+ return true;
+ }
+
+ protected final Node getPreviousSibling(Node node) {
+ checkLoaded();
+ int pos = childNodes.indexOf(node) - 1;
+ return pos >= 0 ? childNodes.item(pos) : null;
+ }
+
+ protected final Node getNextSibling(Node node) {
+ checkLoaded();
+ int pos = childNodes.indexOf(node) + 1;
+ return pos < childNodes.getLength() ? childNodes.item(pos) : null;
+ }
+
+ protected void checkLoaded() {
+ if (loaded)
+ return;
+ else
+ loaded = true;
+
+ try {
+ if (data != null) {
+ DocumentImpl doc = (DocumentImpl) getOwnerDocument();
+ loadChildren(doc.getSymbols());
+ }
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ protected final void loadChildren(SymbolTable st) throws IOException {
+ ByteArrayInput bis = new ByteArrayInput(data, pos, len);
+ XMLCompressedInput in = new XMLCompressedInput(bis, st);
+
+ if (getNodeType() == Node.ELEMENT_NODE) {
+ // Have to skip the attributes
+ in.readSignature();
+ in.readContentSize();
+ in.readShort(); // Element Symbol
+ int attrCount = in.readAttributeCount();
+ for (int i = 0; i < attrCount; i++) {
+ in.readShort(); // Attribute Symbol
+ in.skip(in.readShort()); // Attribute Length
+ }
+ }
+ else {
+ in.readInt();
+ }
+
+ while (bis.available() > 0) {
+ int pos = bis.getPos();
+ /* TODO why is it used for? byte signature = */
+ in.readSignature();
+ int len = in.readContentSize();
+ if (len == 0)
+ len = 1;
+
+ switch (in.getNodeType()) {
+
+ case Node.ELEMENT_NODE :
+ childNodes.add(new ElementImpl(this, data, pos, len));
+ break;
+
+ case Node.TEXT_NODE :
+ childNodes.add(new TextImpl(this, data, pos, len));
+ break;
+
+ case Node.CDATA_SECTION_NODE :
+ childNodes.add(new CDATASectionImpl(this, data, pos, len));
+ break;
+
+ case Node.ENTITY_REFERENCE_NODE :
+ childNodes.add(new EntityReferenceImpl(this, data, pos, len));
+ break;
+
+ case Node.ENTITY_NODE :
+ childNodes.add(new EntityImpl(this, data, pos, len));
+ break;
+
+ case Node.PROCESSING_INSTRUCTION_NODE :
+ childNodes.add(new ProcessingInstructionImpl(this, data, pos, len));
+ break;
+
+ case Node.COMMENT_NODE :
+ childNodes.add(new CommentImpl(this, data, pos, len));
+ break;
+
+ case Node.NOTATION_NODE :
+ childNodes.add(new NotationImpl(this, data, pos, len));
+ break;
+ }
+
+ bis.setPos(pos);
+ bis.skip(len);
+ }
+ }
+
+ /**
+ * This is a convenience method to allow easy determination of whether a
+ * node has any children.
+ * @return <code>true</code> if the node has any children,
+ * <code>false</code> if the node has no children.
+ */
+ public final boolean hasChildNodes() {
+ checkLoaded();
+ return childNodes.getLength() > 0;
+ }
+
+ public final NodeList getChildNodes() {
+ checkLoaded();
+ return childNodes;
+ }
+
+ /**
+ * The first child of this node. If there is no such node, this returns
+ * <code>null</code>.
+ */
+ public final Node getFirstChild() {
+ checkLoaded();
+ if (childNodes.size() > 0)
+ return childNodes.item(0);
+ else
+ return null;
+ }
+
+ /**
+ * The last child of this node. If there is no such node, this returns
+ * <code>null</code>.
+ */
+ public final Node getLastChild() {
+ checkLoaded();
+ if (childNodes.size() > 0)
+ return childNodes.item(childNodes.getLength() - 1);
+ else
+ return null;
+ }
+
+ /**
+ * Replaces the child node <code>oldChild</code> with <code>newChild</code>
+ * in the list of children, and returns the <code>oldChild</code> node. If
+ * the <code>newChild</code> is already in the tree, it is first removed.
+ * @param newChild The new node to put in the child list.
+ * @param oldChild The node being replaced in the list.
+ * @return The node replaced.
+ * @exception DOMException
+ * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
+ * allow children of the type of the <code>newChild</code> node, or it
+ * the node to put in is one of this node's ancestors.
+ * <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created
+ * from a different document than the one that created this node.
+ * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ * <br>NOT_FOUND_ERR: Raised if <code>oldChild</code> is not a child of
+ * this node.
+ */
+ public final synchronized Node replaceChild(Node newChild, Node oldChild) throws DOMException {
+ checkLoaded();
+ checkReadOnly();
+ if (!isNodeTypeValid(newChild.getNodeType()))
+ throw EX_HIERARCHY_REQUEST;
+ int idx = childNodes.indexOf(oldChild);
+ if (idx >= 0) {
+ if (newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE) {
+ childNodes.remove(idx);
+ NodeList nl = ((DocumentFragment) newChild).getChildNodes();
+ for (int i = 0; i < nl.getLength(); i++) {
+ NodeImpl impl = (NodeImpl) nl.item(i);
+ impl.setParentNode(this);
+ childNodes.add(idx + i, impl);
+ }
+ }
+ else {
+ NodeImpl impl = (NodeImpl) newChild;
+ impl.setParentNode(this);
+ childNodes.set(idx, impl);
+ }
+ }
+ setDirty();
+ return oldChild;
+ }
+
+ /**
+ * Inserts the node <code>newChild</code> before the existing child node
+ * <code>refChild</code>. If <code>refChild</code> is <code>null</code>,
+ * insert <code>newChild</code> at the end of the list of children.
+ * <br>If <code>newChild</code> is a <code>DocumentFragment</code> object,
+ * all of its children are inserted, in the same order, before
+ * <code>refChild</code>. If the <code>newChild</code> is already in the
+ * tree, it is first removed.
+ * @param newChild The node to insert.
+ * @param refChild The reference node, i.e., the node before which the new
+ * node must be inserted.
+ * @return The node being inserted.
+ * @exception DOMException
+ * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
+ * allow children of the type of the <code>newChild</code> node, or if
+ * the node to insert is one of this node's ancestors.
+ * <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created
+ * from a different document than the one that created this node.
+ * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ * <br>NOT_FOUND_ERR: Raised if <code>refChild</code> is not a child of
+ * this node.
+ */
+ public final synchronized Node insertBefore(Node newChild, Node refChild) throws DOMException {
+ checkLoaded();
+ checkReadOnly();
+ int idx = childNodes.indexOf(refChild);
+ if (idx >= 0) {
+ if (!isNodeTypeValid(newChild.getNodeType()))
+ throw EX_HIERARCHY_REQUEST;
+ if (newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE) {
+ NodeList nl = ((DocumentFragment) newChild).getChildNodes();
+ for (int i = 0; i < nl.getLength(); i++) {
+ NodeImpl impl = (NodeImpl) nl.item(i);
+ impl.setParentNode(this);
+ childNodes.add(idx + i, impl);
+ }
+ }
+ else {
+ NodeImpl impl = (NodeImpl) newChild;
+ impl.setParentNode(this);
+ childNodes.add(idx, impl);
+ }
+ }
+ setDirty();
+ return newChild;
+ }
+
+ /**
+ * Removes the child node indicated by <code>oldChild</code> from the list
+ * of children, and returns it.
+ * @param oldChild The node being removed.
+ * @return The node removed.
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ * <br>NOT_FOUND_ERR: Raised if <code>oldChild</code> is not a child of
+ * this node.
+ */
+ public final synchronized Node removeChild(Node oldChild) throws DOMException {
+ checkLoaded();
+ checkReadOnly();
+ if (!childNodes.remove(oldChild))
+ throw EX_NOT_FOUND;
+ setDirty();
+ return oldChild;
+ }
+
+ /**
+ * Adds the node <code>newChild</code> to the end of the list of children of
+ * this node. If the <code>newChild</code> is already in the tree, it is
+ * first removed.
+ * @param newChild The node to add.If it is a <code>DocumentFragment</code>
+ * object, the entire contents of the document fragment are moved into
+ * the child list of this node
+ * @return The node added.
+ * @exception DOMException
+ * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
+ * allow children of the type of the <code>newChild</code> node, or if
+ * the node to append is one of this node's ancestors.
+ * <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created
+ * from a different document than the one that created this node.
+ * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ */
+ public final synchronized Node appendChild(Node newChild) throws DOMException {
+ checkLoaded();
+ checkReadOnly();
+ if (!isNodeTypeValid(newChild.getNodeType()))
+ throw EX_HIERARCHY_REQUEST;
+ if (newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE) {
+ NodeList nl = ((DocumentFragment) newChild).getChildNodes();
+ for (int i = 0; i < nl.getLength(); i++) {
+ NodeImpl impl = (NodeImpl) nl.item(i);
+ impl.setParentNode(this);
+ childNodes.add(impl);
+ }
+ }
+ else {
+ NodeImpl impl = (NodeImpl) newChild;
impl.setParentNode(this);
childNodes.add(impl);
- }
- }
- else {
- NodeImpl impl = (NodeImpl)newChild;
- impl.setParentNode(this);
- childNodes.add(impl);
- }
- setDirty();
- return newChild;
- }
+ }
+ setDirty();
+ return newChild;
+ }
/**
* Puts all <code>Text</code> nodes in the full depth of the sub-tree
@@ -401,110 +402,108 @@
* <code>Text</code> nodes and <code>CDATASection</code> nodes.
* @since DOM Level 2
*/
- public final synchronized void normalize() {
- checkLoaded();
- checkReadOnly();
- List set = new ArrayList();
-
- NodeListImpl newList = new NodeListImpl(this);
- boolean modified = false;
-
- int size = childNodes.size();
- for ( int i = 0; i < size; i++ ) {
- Node add = null;
- Node n = (Node)childNodes.get(i);
- short type = n.getNodeType();
-
- switch ( type ) {
- case Node.TEXT_NODE:
- set.add(n);
- break;
- case Node.ELEMENT_NODE:
- n.normalize();
- default:
- add = n;
- }
-
- if ( !set.isEmpty() && ( type != Node.TEXT_NODE || i == size-1 ) ) {
- Text s = (Text)set.get(0);
- int len = set.size();
- for ( int j = 1 ; j < len; j++ ) {
- modified = true;
- Text a = (Text)set.get(j);
- s.appendData(a.getData());
- }
- newList.add(s);
- set.clear();
- }
- if ( add != null )
- newList.add(add);
- }
-
- if ( modified ) {
- childNodes = newList;
- setDirty();
- }
- }
-
- /**
- * Returns a <code>NodeList</code> of all descendant elements with a given
- * tag name, in the order in which they would be encountered in a preorder
- * traversal of the <code>Element</code> tree.
- * @param name The name of the tag to match on. The special value "*"
- * matches all tags.
- * @return A list of matching <code>Element</code> nodes.
- */
- public final NodeList getElementsByTagName(final String name) {
- checkLoaded();
- NodeListImpl list = new NodeListImpl(this);
-
- NodeFilter filter = new NodeFilter() {
- public short acceptNode(Node node) {
- if ( node.getNodeName().equals(name) )
- return (short)NodeFilter.FILTER_ACCEPT;
- else
- return (short)NodeFilter.FILTER_SKIP;
- }
- };
-
- NodeIterator enum = ((DocumentTraversal)getOwnerDocument()).createNodeIterator(this, NodeFilter.SHOW_ELEMENT, filter, false);
- Node node = null;
- do {
- node = enum.nextNode();
- if ( node != null )
- list.add(node);
- }
- while ( node != null );
- return list;
- }
-
- public final NodeList getElementsByTagNameNS(final String namespaceURI, final String localName) {
- checkLoaded();
- NodeListImpl list = new NodeListImpl(this);
-
- NodeFilter filter = new NodeFilter() {
- public short acceptNode(Node node) {
- if ( node.getLocalName().equals(localName)
- && node.getNamespaceURI().equals(namespaceURI) )
- return (short)NodeFilter.FILTER_ACCEPT;
- else
- return (short)NodeFilter.FILTER_SKIP;
- }
- };
-
- NodeIterator enum = ((DocumentTraversal)getOwnerDocument()).createNodeIterator(this, NodeFilter.SHOW_ELEMENT, filter, false);
- Node node = null;
- do {
- node = enum.nextNode();
- if ( node != null )
- list.add(node);
- }
- while ( node != null );
- return list;
- }
-
- public final Element getElementById(String elementId) {
- return null;
- }
-}
+ public final synchronized void normalize() {
+ checkLoaded();
+ checkReadOnly();
+ List set = new ArrayList();
+
+ NodeListImpl newList = new NodeListImpl(this);
+ boolean modified = false;
+
+ int size = childNodes.size();
+ for (int i = 0; i < size; i++) {
+ Node add = null;
+ Node n = (Node) childNodes.get(i);
+ short type = n.getNodeType();
+
+ switch (type) {
+ case Node.TEXT_NODE :
+ set.add(n);
+ break;
+ case Node.ELEMENT_NODE :
+ n.normalize();
+ default :
+ add = n;
+ }
+
+ if (!set.isEmpty() && (type != Node.TEXT_NODE || i == size - 1)) {
+ Text s = (Text) set.get(0);
+ int len = set.size();
+ for (int j = 1; j < len; j++) {
+ modified = true;
+ Text a = (Text) set.get(j);
+ s.appendData(a.getData());
+ }
+ newList.add(s);
+ set.clear();
+ }
+ if (add != null)
+ newList.add(add);
+ }
+
+ if (modified) {
+ childNodes = newList;
+ setDirty();
+ }
+ }
+ /**
+ * Returns a <code>NodeList</code> of all descendant elements with a given
+ * tag name, in the order in which they would be encountered in a preorder
+ * traversal of the <code>Element</code> tree.
+ * @param name The name of the tag to match on. The special value "*"
+ * matches all tags.
+ * @return A list of matching <code>Element</code> nodes.
+ */
+ public final NodeList getElementsByTagName(final String name) {
+ checkLoaded();
+ NodeListImpl list = new NodeListImpl(this);
+
+ NodeFilter filter = new NodeFilter() {
+ public short acceptNode(Node node) {
+ if (node.getNodeName().equals(name))
+ return (short) NodeFilter.FILTER_ACCEPT;
+ else
+ return (short) NodeFilter.FILTER_SKIP;
+ }
+ };
+
+ NodeIterator enum = ((DocumentTraversal) getOwnerDocument()).createNodeIterator(this, NodeFilter.SHOW_ELEMENT, filter, false);
+ Node node = null;
+ do {
+ node = enum.nextNode();
+ if (node != null)
+ list.add(node);
+ }
+ while (node != null);
+ return list;
+ }
+
+ public final NodeList getElementsByTagNameNS(final String namespaceURI, final String localName) {
+ checkLoaded();
+ NodeListImpl list = new NodeListImpl(this);
+
+ NodeFilter filter = new NodeFilter() {
+ public short acceptNode(Node node) {
+ if (node.getLocalName().equals(localName) && node.getNamespaceURI().equals(namespaceURI))
+ return (short) NodeFilter.FILTER_ACCEPT;
+ else
+ return (short) NodeFilter.FILTER_SKIP;
+ }
+ };
+
+ NodeIterator enum = ((DocumentTraversal) getOwnerDocument()).createNodeIterator(this, NodeFilter.SHOW_ELEMENT, filter, false);
+ Node node = null;
+ do {
+ node = enum.nextNode();
+ if (node != null)
+ list.add(node);
+ }
+ while (node != null);
+ return list;
+ }
+
+ public final Element getElementById(String elementId) {
+ return null;
+ }
+}
1.6 +478 -473 xml-xindice/java/src/org/apache/xindice/xml/dom/DocumentImpl.java
Index: DocumentImpl.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/dom/DocumentImpl.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- DocumentImpl.java 31 Oct 2002 07:16:52 -0000 1.5
+++ DocumentImpl.java 15 Jul 2003 15:44:34 -0000 1.6
@@ -59,20 +59,35 @@
* $Id$
*/
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.xindice.util.XindiceException;
import org.apache.xindice.xml.NodeSource;
import org.apache.xindice.xml.SymbolTable;
import org.apache.xindice.xml.dom.traversal.TreeWalkerImpl;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.w3c.dom.*;
-import org.w3c.dom.traversal.*;
-
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+import org.w3c.dom.traversal.DocumentTraversal;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.NodeIterator;
+import org.w3c.dom.traversal.TreeWalker;
/**
* DocumentImpl
@@ -80,474 +95,464 @@
public final class DocumentImpl extends ContainerNodeImpl implements CompressedDocument, DBDocument, DocumentTraversal {
- private static Log log = LogFactory.getLog("org.apache.xindice.xml");
+ private static Log log = LogFactory.getLog("org.apache.xindice.xml");
+
+ private DocumentType docType = null;
+ private String version = null;
+ private String actualEncoding = null;
+ private String encoding = null;
+ private boolean standalone = false;
+ private boolean strictErrorChecking = false;
+ private SymbolTable symbols = null;
+ private boolean readOnly = false;
+
+ public DocumentImpl() {
+ super(null, true);
+ }
+
+ public DocumentImpl(byte[] data, int pos, int len) {
+ super(null, data, pos, len);
+ }
+
+ public DocumentImpl(byte[] data) {
+ this(data, 0, data.length);
+ }
+
+ public DocumentImpl(byte[] data, SymbolTable symbols, NodeSource source) {
+ this(data);
+ this.symbols = symbols;
+ this.source = source;
+ }
+
+ public DocumentImpl(Document doc) throws XindiceException {
+ super(null, true);
+
+ boolean compress = true;
+
+ if (doc instanceof CompressedDocument) {
+ CompressedDocument c = (CompressedDocument) doc;
+ symbols = c.getSymbols();
+ if (!c.isDirty()) {
+ data = c.getDataBytes();
+ pos = c.getDataPos();
+ len = c.getDataLen();
+ compress = false;
+ }
+ }
+
+ if (compress) {
+ if (symbols == null)
+ symbols = new SymbolTable();
+ data = DOMCompressor.Compress(doc, symbols);
+ pos = 0;
+ len = data.length;
+ }
+
+ if (doc instanceof DBDocument) {
+ DBDocument d = (DBDocument) doc;
+ source = d.getSource();
+ }
+ }
+
+ public boolean isReadOnly() {
+ return readOnly;
+ }
- private DocumentType docType = null;
- private String version = null;
- private String actualEncoding = null;
- private String encoding = null;
- private boolean standalone = false;
- private boolean strictErrorChecking = false;
- private SymbolTable symbols = null;
- private boolean readOnly = false;
-
- public DocumentImpl() {
- super(null, true);
- }
-
- public DocumentImpl(byte[] data, int pos, int len) {
- super(null, data, pos, len);
- }
-
- public DocumentImpl(byte[] data) {
- this(data, 0, data.length);
- }
-
- public DocumentImpl(byte[] data, SymbolTable symbols, NodeSource source) {
- this(data);
- this.symbols = symbols;
- this.source = source;
- }
-
- public DocumentImpl(Document doc) throws XindiceException {
- super(null, true);
-
- boolean compress = true;
-
- if ( doc instanceof CompressedDocument ) {
- CompressedDocument c = (CompressedDocument)doc;
- symbols = c.getSymbols();
- if ( !c.isDirty() ) {
- data = c.getDataBytes();
- pos = c.getDataPos();
- len = c.getDataLen();
- compress = false;
- }
- }
-
- if ( compress ) {
- if ( symbols == null )
- symbols = new SymbolTable();
- data = DOMCompressor.Compress(doc, symbols);
- pos = 0;
- len = data.length;
- }
-
- if ( doc instanceof DBDocument ) {
- DBDocument d = (DBDocument)doc;
- source = d.getSource();
- }
- }
-
- public boolean isReadOnly() {
- return readOnly;
- }
-
- protected void checkLoaded() {
- if ( loaded )
- return;
- else
- loaded = true;
-
- try {
- if ( data != null )
- loadChildren(symbols);
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- public boolean isCaching() {
- String cache = DBDocument.CACHE;
-
- int size = childNodes.getLength();
- for ( int i = 0; i < size; i++ ) {
- Node n = childNodes.item(i);
- if ( n.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE
- && n.getNodeName().equals(CACHE_CONTROL) ) {
- cache = n.getNodeValue().trim();
- break;
- }
- }
-
- return (cache != null && cache.equals(CACHE));
- }
-
- public void setCaching(boolean caching) {
- // TODO delete String cache = DBDocument.CACHE;
-
- int size = childNodes.getLength();
- for ( int i = 0; i < size; i++ ) {
- Node n = childNodes.item(i);
- if ( n.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE
- && n.getNodeName().equals(CACHE_CONTROL) ) {
- n.setNodeValue(caching ? CACHE : NOCACHE);
+ protected void checkLoaded() {
+ if (loaded)
return;
- }
- }
+ else
+ loaded = true;
- ProcessingInstruction pi = createProcessingInstruction(CACHE_CONTROL, caching ? CACHE : NOCACHE);
- insertBefore(pi, getDocumentElement());
- }
-
- public SymbolTable getSymbols() {
- return symbols;
- }
-
- public void setSymbols(SymbolTable symbols) {
- this.symbols = symbols;
- }
-
- public void expandSource() {
- ElementImpl e = (ElementImpl)getDocumentElement();
- if ( e != null )
- e.expandSource();
- }
-
- public Node getNodeAtPos(int pos) {
- return null; // TODO: This
- }
-
- public short getNodeType() {
- return Node.DOCUMENT_NODE;
- }
-
- public String getNodeName() {
- return "#document";
- }
-
- /**
- * The Document Type Declaration (see <code>DocumentType</code>) associated
- * with this document. For HTML documents as well as XML documents without
- * a document type declaration this returns <code>null</code>. The DOM Level
- * 1 does not support editing the Document Type Declaration, therefore
- * <code>docType</code> cannot be altered in any way.
- */
- public DocumentType getDoctype() {
- return docType;
- }
-
- public void setDoctype(DocumentType docType) {
- this.docType = docType;
- }
-
- /**
- * The <code>DOMImplementation</code> object that handles this document. A
- * DOM application may use objects from multiple implementations.
- */
- public DOMImplementation getImplementation() {
- return DOMImplementationImpl.getInstance();
- }
-
- /**
- * Creates a <code>Text</code> node given the specified string.
- * @param data The data for the node.
- * @return The new <code>Text</code> object.
- */
- public Text createTextNode(String data) {
- return new TextImpl(this, data);
- }
-
- /**
- * This is a convenience attribute that allows direct access to the child
- * node that is the root element of the document. For HTML documents, this
- * is the element with the tagName "HTML".
- */
- public Element getDocumentElement() {
- checkLoaded();
- Iterator enum = childNodes.iterator();
- while ( enum.hasNext() ) {
- Node node = (Node)enum.next();
- if ( node.getNodeType() == Node.ELEMENT_NODE )
- return (Element)node;
- }
- return null;
- }
-
- /**
- * Creates a <code>CDATASection</code> node whose value is the specified
- * string.
- * @param data The data for the <code>CDATASection</code> contents.
- * @return The new <code>CDATASection</code> object.
- * @exception DOMException
- * NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
- */
- public CDATASection createCDATASection(String data) throws DOMException {
- return new CDATASectionImpl(this, data);
- }
-
- /**
- * Creates an element of the type specified. Note that the instance returned
- * implements the Element interface, so attributes can be specified
- * directly on the returned object.
- * @param tagName The name of the element type to instantiate. For XML, this
- * is case-sensitive. For HTML, the <code>tagName</code> parameter may
- * be provided in any case, but it must be mapped to the canonical
- * uppercase form by the DOM implementation.
- * @return A new <code>Element</code> object.
- * @exception DOMException
- * INVALID_CHARACTER_ERR: Raised if the specified name contains an
- * invalid character.
- */
- public Element createElement(String tagName) throws DOMException {
- return new ElementImpl(this, tagName);
- }
-
- /**
- * Creates an empty <code>DocumentFragment</code> object.
- * @return A new <code>DocumentFragment</code>.
- */
- public DocumentFragment createDocumentFragment() {
- return new DocumentFragmentImpl(this);
- }
-
- /**
- * Creates an <code>Attr</code> of the given name. Note that the
- * <code>Attr</code> instance can then be set on an <code>Element</code>
- * using the <code>setAttribute</code> method.
- * @param name The name of the attribute.
- * @return A new <code>Attr</code> object.
- * @exception DOMException
- * INVALID_CHARACTER_ERR: Raised if the specified name contains an
- * invalid character.
- */
- public Attr createAttribute(String name) throws DOMException {
- return new AttrImpl(this, name);
- }
-
- /**
- * Creates a <code>Comment</code> node given the specified string.
- * @param data The data for the node.
- * @return The new <code>Comment</code> object.
- */
- public Comment createComment(String data) {
- return new CommentImpl(this, data);
- }
-
- /**
- * Creates a <code>ProcessingInstruction</code> node given the specified
- * name and data strings.
- * @param target The target part of the processing instruction.
- * @param data The data for the node.
- * @return The new <code>ProcessingInstruction</code> object.
- * @exception DOMException
- * INVALID_CHARACTER_ERR: Raised if an invalid character is specified.
- * <br>NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
- */
- public ProcessingInstruction createProcessingInstruction(String target, String data) throws DOMException {
- return new ProcessingInstructionImpl(this, target, data);
- }
-
- /**
- * Creates an EntityReference object.
- * @param name The name of the entity to reference.
- * @return The new <code>EntityReference</code> object.
- * @exception DOMException
- * INVALID_CHARACTER_ERR: Raised if the specified name contains an
- * invalid character.
- * <br>NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
- */
- public EntityReference createEntityReference(String name) throws DOMException {
- return new EntityReferenceImpl(this, name);
- }
-
- private void importNamespaces(Node source, Node target) {
- if ( target.getNodeType() == Node.ELEMENT_NODE ) {
- // Retrieve Namespace definitions in scope
- Set set = new HashSet();
- Node n = source;
- Element elem = (Element)target;
- while ( n != null ) {
- NamedNodeMap nm = n.getAttributes();
- for ( int i = 0; i < nm.getLength(); i++ ) {
- Attr a = (Attr)nm.item(i);
- String name = a.getNodeName();
- if ( ( name.startsWith("xmlns:")
- || name.equals("xmlns") )
- && !set.contains(name) ) {
- set.add(name);
- elem.setAttribute(name, a.getValue());
- }
+ try {
+ if (data != null)
+ loadChildren(symbols);
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ public boolean isCaching() {
+ String cache = DBDocument.CACHE;
+
+ int size = childNodes.getLength();
+ for (int i = 0; i < size; i++) {
+ Node n = childNodes.item(i);
+ if (n.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && n.getNodeName().equals(CACHE_CONTROL)) {
+ cache = n.getNodeValue().trim();
+ break;
}
- n = n.getParentNode();
- if ( n.getNodeType() == DOCUMENT_NODE
- || n.getNodeType() == DOCUMENT_FRAGMENT_NODE )
- n = null;
- }
- }
- }
-
- public Node importNode(Node importedNode, boolean deep) {
- try {
- // If we're a Xindice DOM Node and share the same symbol table,
- // then we're golden
- if ( importedNode instanceof NodeImpl ) {
- NodeImpl impl = (NodeImpl)importedNode;
- DocumentImpl docImpl = (DocumentImpl)impl.getOwnerDocument();
- if ( docImpl.getSymbols() != null && ( docImpl.getSymbols() == symbols ) ) {
- NodeImpl clone = (NodeImpl)impl.cloneNode(deep);
- clone.setParentNode(this);
- importNamespaces(importedNode, clone);
- return clone;
+ }
+
+ return (cache != null && cache.equals(CACHE));
+ }
+
+ public void setCaching(boolean caching) {
+ // TODO delete String cache = DBDocument.CACHE;
+
+ int size = childNodes.getLength();
+ for (int i = 0; i < size; i++) {
+ Node n = childNodes.item(i);
+ if (n.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && n.getNodeName().equals(CACHE_CONTROL)) {
+ n.setNodeValue(caching ? CACHE : NOCACHE);
+ return;
}
- }
+ }
- // Crap, we have to do a full graph copy
- Node result = null;
- switch ( importedNode.getNodeType() ) {
- case Node.ATTRIBUTE_NODE:
- Attr sattr = (Attr)importedNode;
- Attr attr = createAttribute(sattr.getName());
- attr.setValue(sattr.getValue());
- result = attr;
- break;
-
- case Node.CDATA_SECTION_NODE:
- result = createCDATASection(importedNode.getNodeValue());
- break;
-
- case Node.COMMENT_NODE:
- result = createComment(importedNode.getNodeValue());
- break;
-
- case Node.ELEMENT_NODE:
- Element selem = (Element)importedNode;
- Element elem = createElement(selem.getTagName());
- NamedNodeMap attrs = selem.getAttributes();
- int size = attrs.getLength();
- for ( int i = 0; i < size; i++ ) {
- Attr a = (Attr)attrs.item(i);
- Attr ai = createAttribute(a.getName());
- ai.setValue(a.getValue());
- elem.setAttributeNode(ai);
- }
- result = elem;
- importNamespaces(importedNode, result);
- break;
-
- case Node.ENTITY_REFERENCE_NODE:
- result = createEntityReference(importedNode.getNodeValue());
- break;
-
- case Node.PROCESSING_INSTRUCTION_NODE:
- result = createProcessingInstruction(importedNode.getNodeName(), importedNode.getNodeValue());
- break;
-
- case Node.TEXT_NODE:
- result = createTextNode(importedNode.getNodeValue());
- break;
-
- default:
- }
-
- if ( deep && result != null ) {
- NodeList list = importedNode.getChildNodes();
- int size = list.getLength();
- for ( int i = 0; i < size; i++ ) {
- Node n = list.item(i);
- result.appendChild(importNode(n, deep));
+ ProcessingInstruction pi = createProcessingInstruction(CACHE_CONTROL, caching ? CACHE : NOCACHE);
+ insertBefore(pi, getDocumentElement());
+ }
+
+ public SymbolTable getSymbols() {
+ return symbols;
+ }
+
+ public void setSymbols(SymbolTable symbols) {
+ this.symbols = symbols;
+ }
+
+ public void expandSource() {
+ ElementImpl e = (ElementImpl) getDocumentElement();
+ if (e != null)
+ e.expandSource();
+ }
+
+ public Node getNodeAtPos(int pos) {
+ return null; // TODO: This
+ }
+
+ public short getNodeType() {
+ return Node.DOCUMENT_NODE;
+ }
+
+ public String getNodeName() {
+ return "#document";
+ }
+
+ /**
+ * The Document Type Declaration (see <code>DocumentType</code>) associated
+ * with this document. For HTML documents as well as XML documents without
+ * a document type declaration this returns <code>null</code>. The DOM Level
+ * 1 does not support editing the Document Type Declaration, therefore
+ * <code>docType</code> cannot be altered in any way.
+ */
+ public DocumentType getDoctype() {
+ return docType;
+ }
+
+ public void setDoctype(DocumentType docType) {
+ this.docType = docType;
+ }
+
+ /**
+ * The <code>DOMImplementation</code> object that handles this document. A
+ * DOM application may use objects from multiple implementations.
+ */
+ public DOMImplementation getImplementation() {
+ return DOMImplementationImpl.getInstance();
+ }
+
+ /**
+ * Creates a <code>Text</code> node given the specified string.
+ * @param data The data for the node.
+ * @return The new <code>Text</code> object.
+ */
+ public Text createTextNode(String data) {
+ return new TextImpl(this, data);
+ }
+
+ /**
+ * This is a convenience attribute that allows direct access to the child
+ * node that is the root element of the document. For HTML documents, this
+ * is the element with the tagName "HTML".
+ */
+ public Element getDocumentElement() {
+ checkLoaded();
+ Iterator enum = childNodes.iterator();
+ while (enum.hasNext()) {
+ Node node = (Node) enum.next();
+ if (node.getNodeType() == Node.ELEMENT_NODE)
+ return (Element) node;
+ }
+ return null;
+ }
+
+ /**
+ * Creates a <code>CDATASection</code> node whose value is the specified
+ * string.
+ * @param data The data for the <code>CDATASection</code> contents.
+ * @return The new <code>CDATASection</code> object.
+ * @exception DOMException
+ * NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
+ */
+ public CDATASection createCDATASection(String data) throws DOMException {
+ return new CDATASectionImpl(this, data);
+ }
+
+ /**
+ * Creates an element of the type specified. Note that the instance returned
+ * implements the Element interface, so attributes can be specified
+ * directly on the returned object.
+ * @param tagName The name of the element type to instantiate. For XML, this
+ * is case-sensitive. For HTML, the <code>tagName</code> parameter may
+ * be provided in any case, but it must be mapped to the canonical
+ * uppercase form by the DOM implementation.
+ * @return A new <code>Element</code> object.
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified name contains an
+ * invalid character.
+ */
+ public Element createElement(String tagName) throws DOMException {
+ return new ElementImpl(this, tagName);
+ }
+
+ /**
+ * Creates an empty <code>DocumentFragment</code> object.
+ * @return A new <code>DocumentFragment</code>.
+ */
+ public DocumentFragment createDocumentFragment() {
+ return new DocumentFragmentImpl(this);
+ }
+
+ /**
+ * Creates an <code>Attr</code> of the given name. Note that the
+ * <code>Attr</code> instance can then be set on an <code>Element</code>
+ * using the <code>setAttribute</code> method.
+ * @param name The name of the attribute.
+ * @return A new <code>Attr</code> object.
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified name contains an
+ * invalid character.
+ */
+ public Attr createAttribute(String name) throws DOMException {
+ return new AttrImpl(this, name);
+ }
+
+ /**
+ * Creates a <code>Comment</code> node given the specified string.
+ * @param data The data for the node.
+ * @return The new <code>Comment</code> object.
+ */
+ public Comment createComment(String data) {
+ return new CommentImpl(this, data);
+ }
+
+ /**
+ * Creates a <code>ProcessingInstruction</code> node given the specified
+ * name and data strings.
+ * @param target The target part of the processing instruction.
+ * @param data The data for the node.
+ * @return The new <code>ProcessingInstruction</code> object.
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if an invalid character is specified.
+ * <br>NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
+ */
+ public ProcessingInstruction createProcessingInstruction(String target, String data) throws DOMException {
+ return new ProcessingInstructionImpl(this, target, data);
+ }
+
+ /**
+ * Creates an EntityReference object.
+ * @param name The name of the entity to reference.
+ * @return The new <code>EntityReference</code> object.
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified name contains an
+ * invalid character.
+ * <br>NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
+ */
+ public EntityReference createEntityReference(String name) throws DOMException {
+ return new EntityReferenceImpl(this, name);
+ }
+
+ private void importNamespaces(Node source, Node target) {
+ if (target.getNodeType() == Node.ELEMENT_NODE) {
+ // Retrieve Namespace definitions in scope
+ Set set = new HashSet();
+ Node n = source;
+ Element elem = (Element) target;
+ while (n != null) {
+ NamedNodeMap nm = n.getAttributes();
+ for (int i = 0; i < nm.getLength(); i++) {
+ Attr a = (Attr) nm.item(i);
+ String name = a.getNodeName();
+ if ((name.startsWith("xmlns:") || name.equals("xmlns")) && !set.contains(name)) {
+ set.add(name);
+ elem.setAttribute(name, a.getValue());
+ }
+ }
+ n = n.getParentNode();
+ if (n.getNodeType() == DOCUMENT_NODE || n.getNodeType() == DOCUMENT_FRAGMENT_NODE)
+ n = null;
}
- }
+ }
+ }
- return result;
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- return null;
- }
- }
-
- public Element createElementNS(String namespaceURI, String qualifiedName) {
- return new ElementImpl(this, qualifiedName);
- }
-
- public Attr createAttributeNS(String namespaceURI, String qualifiedName) {
- return new AttrImpl(this, qualifiedName);
- }
-
- public NodeIterator createNodeIterator(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) throws DOMException {
- return new TreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
- }
-
- public TreeWalker createTreeWalker(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) throws DOMException {
- return new TreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
- }
-
- // DOM Level 3 Stuff
-
- public Node adoptNode(Node src) {
- // If we're a Xindice DOM Node and share the same symbol table
- // or the adopted node has no symbol table, then we're golden
- if ( src instanceof NodeImpl ) {
- NodeImpl impl = (NodeImpl)src;
- DocumentImpl docImpl = (DocumentImpl)impl.getOwnerDocument();
- if ( docImpl.getSymbols() == null || docImpl.getSymbols() == symbols ) {
- impl.getParentNode().removeChild(impl);
- impl.setParentNode(this);
- return impl;
- }
- }
- return importNode(src, true);
- }
-
- public String getActualEncoding() {
- checkLoaded();
- return actualEncoding;
- }
-
- public void setActualEncoding(String actualEncoding) {
- checkReadOnly();
- checkLoaded();
- this.actualEncoding = actualEncoding;
- }
-
- public String getEncoding() {
- checkLoaded();
- return encoding;
- }
-
- public void setEncoding(String encoding) {
- checkReadOnly();
- checkLoaded();
- this.encoding = encoding;
- }
-
- public String getVersion() {
- checkLoaded();
- return version;
- }
-
- public void setVersion(String version) {
- checkReadOnly();
- checkLoaded();
- this.version = version;
- }
-
- public boolean getStandalone() {
- checkLoaded();
- return standalone;
- }
-
- public void setStandalone(boolean standalone) {
- checkReadOnly();
- checkLoaded();
- this.standalone = standalone;
- }
-
- public boolean getStrictErrorChecking() {
- checkLoaded();
- return strictErrorChecking;
- }
-
- public void setStrictErrorChecking(boolean strictErrorChecking) {
- checkReadOnly();
- checkLoaded();
- this.strictErrorChecking = strictErrorChecking;
- }
-}
+ public Node importNode(Node importedNode, boolean deep) {
+ try {
+ // If we're a Xindice DOM Node and share the same symbol table,
+ // then we're golden
+ if (importedNode instanceof NodeImpl) {
+ NodeImpl impl = (NodeImpl) importedNode;
+ DocumentImpl docImpl = (DocumentImpl) impl.getOwnerDocument();
+ if (docImpl.getSymbols() != null && (docImpl.getSymbols() == symbols)) {
+ NodeImpl clone = (NodeImpl) impl.cloneNode(deep);
+ clone.setParentNode(this);
+ importNamespaces(importedNode, clone);
+ return clone;
+ }
+ }
+
+ // Crap, we have to do a full graph copy
+ Node result = null;
+ switch (importedNode.getNodeType()) {
+ case Node.ATTRIBUTE_NODE :
+ Attr sattr = (Attr) importedNode;
+ Attr attr = createAttribute(sattr.getName());
+ attr.setValue(sattr.getValue());
+ result = attr;
+ break;
+
+ case Node.CDATA_SECTION_NODE :
+ result = createCDATASection(importedNode.getNodeValue());
+ break;
+
+ case Node.COMMENT_NODE :
+ result = createComment(importedNode.getNodeValue());
+ break;
+
+ case Node.ELEMENT_NODE :
+ Element selem = (Element) importedNode;
+ Element elem = createElement(selem.getTagName());
+ NamedNodeMap attrs = selem.getAttributes();
+ int size = attrs.getLength();
+ for (int i = 0; i < size; i++) {
+ Attr a = (Attr) attrs.item(i);
+ Attr ai = createAttribute(a.getName());
+ ai.setValue(a.getValue());
+ elem.setAttributeNode(ai);
+ }
+ result = elem;
+ importNamespaces(importedNode, result);
+ break;
+
+ case Node.ENTITY_REFERENCE_NODE :
+ result = createEntityReference(importedNode.getNodeValue());
+ break;
+
+ case Node.PROCESSING_INSTRUCTION_NODE :
+ result = createProcessingInstruction(importedNode.getNodeName(), importedNode.getNodeValue());
+ break;
+
+ case Node.TEXT_NODE :
+ result = createTextNode(importedNode.getNodeValue());
+ break;
+
+ default :
+ }
+
+ if (deep && result != null) {
+ NodeList list = importedNode.getChildNodes();
+ int size = list.getLength();
+ for (int i = 0; i < size; i++) {
+ Node n = list.item(i);
+ result.appendChild(importNode(n, deep));
+ }
+ }
+ return result;
+ }
+ catch (Exception e) {
+ log.warn(e);
+ return null;
+ }
+ }
+
+ public Element createElementNS(String namespaceURI, String qualifiedName) {
+ return new ElementImpl(this, qualifiedName);
+ }
+
+ public Attr createAttributeNS(String namespaceURI, String qualifiedName) {
+ return new AttrImpl(this, qualifiedName);
+ }
+
+ public NodeIterator createNodeIterator(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) throws DOMException {
+ return new TreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
+ }
+
+ public TreeWalker createTreeWalker(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) throws DOMException {
+ return new TreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
+ }
+
+ // DOM Level 3 Stuff
+
+ public Node adoptNode(Node src) {
+ // If we're a Xindice DOM Node and share the same symbol table
+ // or the adopted node has no symbol table, then we're golden
+ if (src instanceof NodeImpl) {
+ NodeImpl impl = (NodeImpl) src;
+ DocumentImpl docImpl = (DocumentImpl) impl.getOwnerDocument();
+ if (docImpl.getSymbols() == null || docImpl.getSymbols() == symbols) {
+ impl.getParentNode().removeChild(impl);
+ impl.setParentNode(this);
+ return impl;
+ }
+ }
+ return importNode(src, true);
+ }
+
+ public String getActualEncoding() {
+ checkLoaded();
+ return actualEncoding;
+ }
+
+ public void setActualEncoding(String actualEncoding) {
+ checkReadOnly();
+ checkLoaded();
+ this.actualEncoding = actualEncoding;
+ }
+
+ public String getEncoding() {
+ checkLoaded();
+ return encoding;
+ }
+
+ public void setEncoding(String encoding) {
+ checkReadOnly();
+ checkLoaded();
+ this.encoding = encoding;
+ }
+
+ public String getVersion() {
+ checkLoaded();
+ return version;
+ }
+
+ public void setVersion(String version) {
+ checkReadOnly();
+ checkLoaded();
+ this.version = version;
+ }
+
+ public boolean getStandalone() {
+ checkLoaded();
+ return standalone;
+ }
+
+ public void setStandalone(boolean standalone) {
+ checkReadOnly();
+ checkLoaded();
+ this.standalone = standalone;
+ }
+
+ public boolean getStrictErrorChecking() {
+ checkLoaded();
+ return strictErrorChecking;
+ }
+
+ public void setStrictErrorChecking(boolean strictErrorChecking) {
+ checkReadOnly();
+ checkLoaded();
+ this.strictErrorChecking = strictErrorChecking;
+ }
+}
1.5 +203 -208 xml-xindice/java/src/org/apache/xindice/xml/dom/CharacterDataImpl.java
Index: CharacterDataImpl.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/dom/CharacterDataImpl.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- CharacterDataImpl.java 31 Oct 2002 07:02:23 -0000 1.4
+++ CharacterDataImpl.java 15 Jul 2003 15:44:34 -0000 1.5
@@ -59,14 +59,13 @@
* $Id$
*/
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.xindice.util.ByteArrayInput;
import org.apache.xindice.xml.SymbolTable;
import org.apache.xindice.xml.XMLCompressedInput;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.w3c.dom.*;
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.DOMException;
/**
* CharacterDataImpl
@@ -74,207 +73,203 @@
public abstract class CharacterDataImpl extends NodeImpl implements CharacterData {
- private static Log log = LogFactory.getLog("org.apache.xindice.xml");
+ private static Log log = LogFactory.getLog("org.apache.xindice.xml");
- public CharacterDataImpl() {
- }
-
- public CharacterDataImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
- super(parentNode, data, pos, len);
- }
-
- public CharacterDataImpl(NodeImpl parentNode, boolean dirty) {
- super(parentNode, dirty);
- }
-
- public CharacterDataImpl(NodeImpl parentNode, String nodeValue) {
- super(parentNode, true);
- if ( nodeValue == null )
- nodeValue = "";
- this.nodeValue = nodeValue;
- }
-
- protected final void checkLoaded() {
- if ( loaded )
- return;
- else
- loaded = true;
-
- try {
- if ( data != null ) {
- DocumentImpl doc = (DocumentImpl)getOwnerDocument();
- SymbolTable st = doc.getSymbols();
-
- ByteArrayInput bis = new ByteArrayInput(data, pos, len);
- XMLCompressedInput xci = new XMLCompressedInput(bis, st);
-
- xci.readSignature(); // Skip The Signature
- if ( getNodeType() == TEXT_NODE)
- xci.readContentSize();
- else
- xci.readInt();
-
- byte[] buf = new byte[bis.available()];
- xci.read(buf);
- nodeValue = new String(buf, "UTF-8");
- }
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- public final void setNodeValue(String nodeValue) throws DOMException {
- checkLoaded();
- checkReadOnly();
- if ( nodeValue == null )
- nodeValue = "";
- this.nodeValue = nodeValue;
- setDirty();
- }
-
- /**
- * Extracts a range of data from the node.
- * @param offset Start offset of substring to extract.
- * @param count The number of characters to extract.
- * @return The specified substring. If the sum of <code>offset</code> and
- * <code>count</code> exceeds the <code>length</code>, then all
- * characters to the end of the data are returned.
- * @exception DOMException
- * INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
- * than the number of characters in <code>data</code>, or if the
- * specified <code>count</code> is negative.
- * <br>DOMSTRING_SIZE_ERR: Raised if the specified range of text does not
- * fit into a <code>DOMString</code>.
- */
- public final String substringData(int offset, int count) throws DOMException {
- try {
- return nodeValue.substring(offset, offset+count);
- }
- catch ( Exception e ) {
- throw EX_INDEX_SIZE;
- }
- }
-
- /**
- * The character data of the node that implements this interface. The DOM
- * implementation may not put arbitrary limits on the amount of data that
- * may be stored in a <code>CharacterData</code> node. However,
- * implementation limits may mean that the entirety of a node's data may
- * not fit into a single <code>DOMString</code>. In such cases, the user
- * may call <code>substringData</code> to retrieve the data in
- * appropriately sized pieces.
- * @exception DOMException
- * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
- * @exception DOMException
- * DOMSTRING_SIZE_ERR: Raised when it would return more characters than
- * fit in a <code>DOMString</code> variable on the implementation
- * platform.
- */
- public final String getData() throws DOMException {
- return getNodeValue();
- }
-
- public final void setData(String data) throws DOMException {
- setNodeValue(data);
- }
-
- /**
- * Insert a string at the specified character offset.
- * @param offset The character offset at which to insert.
- * @param arg The <code>DOMString</code> to insert.
- * @exception DOMException
- * INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
- * than the number of characters in <code>data</code>.
- * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
- */
- public final void insertData(int offset, String arg) throws DOMException {
- String value = getNodeValue();
- checkReadOnly();
- try {
- setNodeValue(value.substring(0, offset) + arg + value.substring(offset+1));
- }
- catch ( Exception e ) {
- throw EX_INDEX_SIZE;
- }
- }
-
- /**
- * The number of characters that are available through <code>data</code> and
- * the <code>substringData</code> method below. This may have the value
- * zero, i.e., <code>CharacterData</code> nodes may be empty.
- */
- public final int getLength() {
- return getNodeValue().length();
- }
-
- /**
- * Replace the characters starting at the specified character offset with
- * the specified string.
- * @param offset The offset from which to start replacing.
- * @param count The number of characters to replace. If the sum of
- * <code>offset</code> and <code>count</code> exceeds <code>length</code>
- * , then all characters to the end of the data are replaced (i.e., the
- * effect is the same as a <code>remove</code> method call with the same
- * range, followed by an <code>append</code> method invocation).
- * @param arg The <code>DOMString</code> with which the range must be
- * replaced.
- * @exception DOMException
- * INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
- * than the number of characters in <code>data</code>, or if the
- * specified <code>count</code> is negative.
- * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
- */
- public final void replaceData(int offset, int count, String arg) throws DOMException {
- String value = getNodeValue();
- checkReadOnly();
- try {
- setNodeValue(value.substring(0, offset) + arg + value.substring(offset+count));
- }
- catch ( Exception e ) {
- throw EX_INDEX_SIZE;
- }
- }
-
- /**
- * Append the string to the end of the character data of the node. Upon
- * success, <code>data</code> provides access to the concatenation of
- * <code>data</code> and the <code>DOMString</code> specified.
- * @param arg The <code>DOMString</code> to append.
- * @exception DOMException
- * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
- */
- public final void appendData(String arg) throws DOMException {
- String value = getNodeValue();
- checkReadOnly();
- setNodeValue(value + arg);
- }
-
- /**
- * Remove a range of characters from the node. Upon success,
- * <code>data</code> and <code>length</code> reflect the change.
- * @param offset The offset from which to remove characters.
- * @param count The number of characters to delete. If the sum of
- * <code>offset</code> and <code>count</code> exceeds <code>length</code>
- * then all characters from <code>offset</code> to the end of the data
- * are deleted.
- * @exception DOMException
- * INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
- * than the number of characters in <code>data</code>, or if the
- * specified <code>count</code> is negative.
- * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
- */
- public final void deleteData(int offset, int count) throws DOMException {
- String value = getNodeValue();
- checkReadOnly();
- try {
- setNodeValue(value.substring(0, offset) + value.substring(offset+count));
- }
- catch ( Exception e ) {
- throw EX_INDEX_SIZE;
- }
- }
-}
+ public CharacterDataImpl() {}
+ public CharacterDataImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
+ super(parentNode, data, pos, len);
+ }
+
+ public CharacterDataImpl(NodeImpl parentNode, boolean dirty) {
+ super(parentNode, dirty);
+ }
+
+ public CharacterDataImpl(NodeImpl parentNode, String nodeValue) {
+ super(parentNode, true);
+ if (nodeValue == null)
+ nodeValue = "";
+ this.nodeValue = nodeValue;
+ }
+
+ protected final void checkLoaded() {
+ if (loaded)
+ return;
+ else
+ loaded = true;
+
+ try {
+ if (data != null) {
+ DocumentImpl doc = (DocumentImpl) getOwnerDocument();
+ SymbolTable st = doc.getSymbols();
+
+ ByteArrayInput bis = new ByteArrayInput(data, pos, len);
+ XMLCompressedInput xci = new XMLCompressedInput(bis, st);
+
+ xci.readSignature(); // Skip The Signature
+ if (getNodeType() == TEXT_NODE)
+ xci.readContentSize();
+ else
+ xci.readInt();
+
+ byte[] buf = new byte[bis.available()];
+ xci.read(buf);
+ nodeValue = new String(buf, "UTF-8");
+ }
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ public final void setNodeValue(String nodeValue) throws DOMException {
+ checkLoaded();
+ checkReadOnly();
+ if (nodeValue == null)
+ nodeValue = "";
+ this.nodeValue = nodeValue;
+ setDirty();
+ }
+
+ /**
+ * Extracts a range of data from the node.
+ * @param offset Start offset of substring to extract.
+ * @param count The number of characters to extract.
+ * @return The specified substring. If the sum of <code>offset</code> and
+ * <code>count</code> exceeds the <code>length</code>, then all
+ * characters to the end of the data are returned.
+ * @exception DOMException
+ * INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
+ * than the number of characters in <code>data</code>, or if the
+ * specified <code>count</code> is negative.
+ * <br>DOMSTRING_SIZE_ERR: Raised if the specified range of text does not
+ * fit into a <code>DOMString</code>.
+ */
+ public final String substringData(int offset, int count) throws DOMException {
+ try {
+ return nodeValue.substring(offset, offset + count);
+ }
+ catch (Exception e) {
+ throw EX_INDEX_SIZE;
+ }
+ }
+
+ /**
+ * The character data of the node that implements this interface. The DOM
+ * implementation may not put arbitrary limits on the amount of data that
+ * may be stored in a <code>CharacterData</code> node. However,
+ * implementation limits may mean that the entirety of a node's data may
+ * not fit into a single <code>DOMString</code>. In such cases, the user
+ * may call <code>substringData</code> to retrieve the data in
+ * appropriately sized pieces.
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
+ * @exception DOMException
+ * DOMSTRING_SIZE_ERR: Raised when it would return more characters than
+ * fit in a <code>DOMString</code> variable on the implementation
+ * platform.
+ */
+ public final String getData() throws DOMException {
+ return getNodeValue();
+ }
+
+ public final void setData(String data) throws DOMException {
+ setNodeValue(data);
+ }
+
+ /**
+ * Insert a string at the specified character offset.
+ * @param offset The character offset at which to insert.
+ * @param arg The <code>DOMString</code> to insert.
+ * @exception DOMException
+ * INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
+ * than the number of characters in <code>data</code>.
+ * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ */
+ public final void insertData(int offset, String arg) throws DOMException {
+ String value = getNodeValue();
+ checkReadOnly();
+ try {
+ setNodeValue(value.substring(0, offset) + arg + value.substring(offset + 1));
+ }
+ catch (Exception e) {
+ throw EX_INDEX_SIZE;
+ }
+ }
+
+ /**
+ * The number of characters that are available through <code>data</code> and
+ * the <code>substringData</code> method below. This may have the value
+ * zero, i.e., <code>CharacterData</code> nodes may be empty.
+ */
+ public final int getLength() {
+ return getNodeValue().length();
+ }
+
+ /**
+ * Replace the characters starting at the specified character offset with
+ * the specified string.
+ * @param offset The offset from which to start replacing.
+ * @param count The number of characters to replace. If the sum of
+ * <code>offset</code> and <code>count</code> exceeds <code>length</code>
+ * , then all characters to the end of the data are replaced (i.e., the
+ * effect is the same as a <code>remove</code> method call with the same
+ * range, followed by an <code>append</code> method invocation).
+ * @param arg The <code>DOMString</code> with which the range must be
+ * replaced.
+ * @exception DOMException
+ * INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
+ * than the number of characters in <code>data</code>, or if the
+ * specified <code>count</code> is negative.
+ * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ */
+ public final void replaceData(int offset, int count, String arg) throws DOMException {
+ String value = getNodeValue();
+ checkReadOnly();
+ try {
+ setNodeValue(value.substring(0, offset) + arg + value.substring(offset + count));
+ }
+ catch (Exception e) {
+ throw EX_INDEX_SIZE;
+ }
+ }
+
+ /**
+ * Append the string to the end of the character data of the node. Upon
+ * success, <code>data</code> provides access to the concatenation of
+ * <code>data</code> and the <code>DOMString</code> specified.
+ * @param arg The <code>DOMString</code> to append.
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ */
+ public final void appendData(String arg) throws DOMException {
+ String value = getNodeValue();
+ checkReadOnly();
+ setNodeValue(value + arg);
+ }
+
+ /**
+ * Remove a range of characters from the node. Upon success,
+ * <code>data</code> and <code>length</code> reflect the change.
+ * @param offset The offset from which to remove characters.
+ * @param count The number of characters to delete. If the sum of
+ * <code>offset</code> and <code>count</code> exceeds <code>length</code>
+ * then all characters from <code>offset</code> to the end of the data
+ * are deleted.
+ * @exception DOMException
+ * INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
+ * than the number of characters in <code>data</code>, or if the
+ * specified <code>count</code> is negative.
+ * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ */
+ public final void deleteData(int offset, int count) throws DOMException {
+ String value = getNodeValue();
+ checkReadOnly();
+ try {
+ setNodeValue(value.substring(0, offset) + value.substring(offset + count));
+ }
+ catch (Exception e) {
+ throw EX_INDEX_SIZE;
+ }
+ }
+}
1.6 +88 -92 xml-xindice/java/src/org/apache/xindice/xml/dom/ProcessingInstructionImpl.java
Index: ProcessingInstructionImpl.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/dom/ProcessingInstructionImpl.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ProcessingInstructionImpl.java 4 Nov 2002 06:39:55 -0000 1.5
+++ ProcessingInstructionImpl.java 15 Jul 2003 15:44:34 -0000 1.6
@@ -59,14 +59,14 @@
* $Id$
*/
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.xindice.util.ByteArrayInput;
import org.apache.xindice.xml.SymbolTable;
import org.apache.xindice.xml.XMLCompressedInput;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.w3c.dom.*;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
/**
* ProcessingInstructionImpl
@@ -74,91 +74,87 @@
public final class ProcessingInstructionImpl extends NodeImpl implements ProcessingInstruction {
- private static Log log = LogFactory.getLog("org.apache.xindice.xml");
-
- public ProcessingInstructionImpl() {
- }
-
- public ProcessingInstructionImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
- super(parentNode, data, pos, len);
- }
-
- public ProcessingInstructionImpl(NodeImpl parentNode, boolean dirty) {
- super(parentNode, dirty);
- }
-
- public ProcessingInstructionImpl(NodeImpl parentNode, String nodeName, String nodeValue) {
- super(parentNode, true);
- this.nodeName = nodeName;
- this.nodeValue = nodeValue;
- }
-
- protected void checkLoaded() {
- if ( loaded )
- return;
- else
- loaded = true;
-
- try {
- if ( data != null ) {
- DocumentImpl doc = (DocumentImpl)getOwnerDocument();
- SymbolTable st = doc.getSymbols();
-
- ByteArrayInput bis = new ByteArrayInput(data, pos, len);
- XMLCompressedInput xci = new XMLCompressedInput(bis, st);
-
- xci.readSignature(); // Skip The Signature
- /* TODO why is it used for? int size = */ xci.readInt();
-
- byte[] buf = new byte[bis.available()];
- xci.read(buf);
-
- String value = new String(buf, "UTF-8");
- int i = value.indexOf(' ');
- nodeName = value.substring(0, i);
- nodeValue = value.substring(i+1);
- }
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- public short getNodeType() {
- return Node.PROCESSING_INSTRUCTION_NODE;
- }
-
- public void setNodeValue(String nodeValue) throws DOMException {
- checkLoaded();
- checkReadOnly();
- this.nodeValue = nodeValue;
- setDirty();
- }
-
- /**
- * The target of this processing instruction. XML defines this as being the
- * first token following the markup that begins the processing instruction.
- */
- public String getTarget() {
- return getNodeName();
- }
-
- /**
- * The content of this processing instruction. This is from the first non
- * white space character after the target to the character immediately
- * preceding the <code>?></code>.
- * @exception DOMException
- * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
- */
- public String getData() {
- return getNodeValue();
- }
-
- public void setData(String data) throws DOMException {
- setNodeValue(data);
- }
-}
+ private static Log log = LogFactory.getLog("org.apache.xindice.xml");
+ public ProcessingInstructionImpl() {}
+ public ProcessingInstructionImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
+ super(parentNode, data, pos, len);
+ }
+
+ public ProcessingInstructionImpl(NodeImpl parentNode, boolean dirty) {
+ super(parentNode, dirty);
+ }
+
+ public ProcessingInstructionImpl(NodeImpl parentNode, String nodeName, String nodeValue) {
+ super(parentNode, true);
+ this.nodeName = nodeName;
+ this.nodeValue = nodeValue;
+ }
+
+ protected void checkLoaded() {
+ if (loaded)
+ return;
+ else
+ loaded = true;
+
+ try {
+ if (data != null) {
+ DocumentImpl doc = (DocumentImpl) getOwnerDocument();
+ SymbolTable st = doc.getSymbols();
+
+ ByteArrayInput bis = new ByteArrayInput(data, pos, len);
+ XMLCompressedInput xci = new XMLCompressedInput(bis, st);
+
+ xci.readSignature(); // Skip The Signature
+ /* TODO why is it used for? int size = */
+ xci.readInt();
+
+ byte[] buf = new byte[bis.available()];
+ xci.read(buf);
+
+ String value = new String(buf, "UTF-8");
+ int i = value.indexOf(' ');
+ nodeName = value.substring(0, i);
+ nodeValue = value.substring(i + 1);
+ }
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ public short getNodeType() {
+ return Node.PROCESSING_INSTRUCTION_NODE;
+ }
+
+ public void setNodeValue(String nodeValue) throws DOMException {
+ checkLoaded();
+ checkReadOnly();
+ this.nodeValue = nodeValue;
+ setDirty();
+ }
+
+ /**
+ * The target of this processing instruction. XML defines this as being the
+ * first token following the markup that begins the processing instruction.
+ */
+ public String getTarget() {
+ return getNodeName();
+ }
+
+ /**
+ * The content of this processing instruction. This is from the first non
+ * white space character after the target to the character immediately
+ * preceding the <code>?></code>.
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
+ */
+ public String getData() {
+ return getNodeValue();
+ }
+
+ public void setData(String data) throws DOMException {
+ setNodeValue(data);
+ }
+}
1.9 +288 -296 xml-xindice/java/src/org/apache/xindice/xml/dom/ElementImpl.java
Index: ElementImpl.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/dom/ElementImpl.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- ElementImpl.java 4 Nov 2002 06:39:55 -0000 1.8
+++ ElementImpl.java 15 Jul 2003 15:44:34 -0000 1.9
@@ -59,18 +59,20 @@
* $Id$
*/
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.xindice.core.data.Key;
import org.apache.xindice.util.ByteArrayInput;
import org.apache.xindice.xml.NodeSource;
import org.apache.xindice.xml.SymbolTable;
import org.apache.xindice.xml.XMLCompressedInput;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.w3c.dom.*;
-
-import java.io.IOException;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
/**
* ElementImpl
@@ -78,267 +80,258 @@
public final class ElementImpl extends ContainerNodeImpl implements Element {
- private static Log log = LogFactory.getLog("org.apache.xindice.xml");
+ private static Log log = LogFactory.getLog("org.apache.xindice.xml");
+
+ private static final String SRC_NS = XMLNS_PREFIX + ":src";
+ private static final String SRC_COL = "src:" + NodeSource.SOURCE_COL;
+ private static final String SRC_KEY = "src:" + NodeSource.SOURCE_KEY;
+
+ private NamedNodeMapImpl attributes = new NamedNodeMapImpl(this);
+ private short symbolID = -1;
+
+ public ElementImpl() {}
+
+ public ElementImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
+ super(parentNode, data, pos, len);
+ DocumentImpl doc = (DocumentImpl) getOwnerDocument();
+ try {
+ loadAttributes(doc.getSymbols());
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ public ElementImpl(NodeImpl parentNode, boolean dirty) {
+ super(parentNode, dirty);
+ }
+
+ public ElementImpl(NodeImpl parentNode, String nodeName) {
+ super(parentNode, true);
+ this.nodeName = nodeName;
+ }
+
+ protected boolean isNodeTypeValid(short type) {
+ return type == Node.ELEMENT_NODE || type == Node.COMMENT_NODE || type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE || type == Node.ENTITY_REFERENCE_NODE;
+ }
+
+ protected void checkLoaded() {
+ if (loaded)
+ return;
+ else
+ loaded = true;
+
+ try {
+ if (data != null) {
+ DocumentImpl doc = (DocumentImpl) getOwnerDocument();
+ SymbolTable st = doc.getSymbols();
+
+ ByteArrayInput bis = new ByteArrayInput(data, pos, len);
+ XMLCompressedInput in = new XMLCompressedInput(bis, st);
+
+ in.readSignature(); // Skip The Signature
+ in.readContentSize(); // Skip The Content Size
+
+ symbolID = in.readShort();
+ SymbolTable.SymbolInfo si = st.getSymbolInfo(symbolID);
+ nodeName = si.getQName();
+ nsURI = si.getNamespaceURI();
+
+ loadChildren(st);
+ }
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ public short getSymbolID() {
+ return symbolID;
+ }
+
+ public void expandSource() {
+ NodeSource src = getSource();
+ if (src != null) {
+ setAttribute(SRC_NS, NodeSource.SOURCE_NS);
+ setAttribute(SRC_COL, src.getCollection().getCanonicalName());
+ Key k = src.getKey();
+ if (k != null)
+ setAttribute(SRC_KEY, k.toString());
+ }
+ }
+
+ protected void loadAttributes(SymbolTable st) throws IOException {
+ ByteArrayInput bis = new ByteArrayInput(data, pos, len);
+ XMLCompressedInput in = new XMLCompressedInput(bis, st);
+
+ in.readSignature();
+ in.readContentSize();
+ /* TODO why is it used for? short elemSymbol = */
+ in.readShort();
+ int attrCount = in.readAttributeCount();
+
+ for (int i = 0; i < attrCount; i++) {
+ short symbol = in.readShort();
+ short strLen = in.readShort();
+ byte[] b = new byte[strLen];
+ in.read(b);
+ SymbolTable.SymbolInfo si = st.getSymbolInfo(symbol);
+ String name = si.getQName();
+ String nsURI = si.getNamespaceURI();
+ AttrImpl attr = new AttrImpl(this, name, nsURI, symbol, new String(b, "UTF-8"));
+ attributes.setNamedItem(attr);
+ }
+ }
+
+ public short getNodeType() {
+ return Node.ELEMENT_NODE;
+ }
+
+ /**
+ * A <code>NamedNodeMap</code> containing the attributes of this node (if it
+ * is an <code>Element</code>) or <code>null</code> otherwise.
+ */
+ public NamedNodeMap getAttributes() {
+ return attributes;
+ }
+
+ public boolean hasAttributes() {
+ return attributes.size() > 0;
+ }
+
+ public boolean hasAttribute(String name) {
+ return attributes.getNamedItem(name) != null;
+ }
+
+ /**
+ * Removes an attribute by name. If the removed attribute has a
+ * default value it is immediately replaced. If the named
+ * attribute does not exist, this method has no effect.
+ *
+ * @param name The name of the attribute to remove.
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ **/
+ public void removeAttribute(String name) throws DOMException {
+ checkReadOnly();
+ AttrImpl attr = (AttrImpl) attributes.removeNamedItem(name);
+ if (attr != null) {
+ attr.setParentNode((NodeImpl) this.getOwnerDocument());
+ }
+ setDirty();
+ }
+
+ /**
+ * The name of the element. For example, in: <elementExample
+ * id="demo"> ... </elementExample> , <code>tagName</code> has
+ * the value <code>"elementExample"</code>. Note that this is
+ * case-preserving in XML, as are all of the operations of the DOM. The
+ * HTML DOM returns the <code>tagName</code> of an HTML element in the
+ * canonical uppercase form, regardless of the case in the source HTML
+ * document.
+ */
+ public String getTagName() {
+ return getNodeName();
+ }
- private static final String SRC_NS = XMLNS_PREFIX+":src";
- private static final String SRC_COL = "src:"+NodeSource.SOURCE_COL;
- private static final String SRC_KEY = "src:"+NodeSource.SOURCE_KEY;
-
- private NamedNodeMapImpl attributes = new NamedNodeMapImpl(this);
- private short symbolID = -1;
-
- public ElementImpl() {
- }
-
- public ElementImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
- super(parentNode, data, pos, len);
- DocumentImpl doc = (DocumentImpl)getOwnerDocument();
- try {
- loadAttributes(doc.getSymbols());
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- public ElementImpl(NodeImpl parentNode, boolean dirty) {
- super(parentNode, dirty);
- }
-
- public ElementImpl(NodeImpl parentNode, String nodeName) {
- super(parentNode, true);
- this.nodeName = nodeName;
- }
-
- protected boolean isNodeTypeValid(short type) {
- return type == Node.ELEMENT_NODE
- || type == Node.COMMENT_NODE
- || type == Node.TEXT_NODE
- || type == Node.CDATA_SECTION_NODE
- || type == Node.ENTITY_REFERENCE_NODE;
- }
-
- protected void checkLoaded() {
- if ( loaded )
- return;
- else
- loaded = true;
-
- try {
- if ( data != null ) {
- DocumentImpl doc = (DocumentImpl)getOwnerDocument();
- SymbolTable st = doc.getSymbols();
-
- ByteArrayInput bis = new ByteArrayInput(data, pos, len);
- XMLCompressedInput in = new XMLCompressedInput(bis, st);
-
- in.readSignature(); // Skip The Signature
- in.readContentSize(); // Skip The Content Size
-
- symbolID = in.readShort();
- SymbolTable.SymbolInfo si = st.getSymbolInfo(symbolID);
- nodeName = si.getQName();
- nsURI = si.getNamespaceURI();
-
- loadChildren(st);
- }
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- public short getSymbolID() {
- return symbolID;
- }
-
- public void expandSource() {
- NodeSource src = getSource();
- if ( src != null ) {
- setAttribute(SRC_NS, NodeSource.SOURCE_NS);
- setAttribute(SRC_COL, src.getCollection().getCanonicalName());
- Key k = src.getKey();
- if ( k != null )
- setAttribute(SRC_KEY, k.toString());
- }
- }
-
- protected void loadAttributes(SymbolTable st) throws IOException {
- ByteArrayInput bis = new ByteArrayInput(data, pos, len);
- XMLCompressedInput in = new XMLCompressedInput(bis, st);
-
- in.readSignature();
- in.readContentSize();
- /* TODO why is it used for? short elemSymbol = */ in.readShort();
- int attrCount = in.readAttributeCount();
-
- for ( int i = 0 ; i < attrCount; i++ ) {
- short symbol = in.readShort();
- short strLen = in.readShort();
- byte[] b = new byte[strLen];
- in.read(b);
- SymbolTable.SymbolInfo si = st.getSymbolInfo(symbol);
- String name = si.getQName();
- String nsURI = si.getNamespaceURI();
- AttrImpl attr = new AttrImpl(this, name, nsURI, symbol, new String(b, "UTF-8"));
- attributes.setNamedItem(attr);
- }
- }
-
- public short getNodeType() {
- return Node.ELEMENT_NODE;
- }
-
- /**
- * A <code>NamedNodeMap</code> containing the attributes of this node (if it
- * is an <code>Element</code>) or <code>null</code> otherwise.
- */
- public NamedNodeMap getAttributes() {
- return attributes;
- }
-
- public boolean hasAttributes() {
- return attributes.size() > 0;
- }
-
- public boolean hasAttribute(String name) {
- return attributes.getNamedItem(name) != null;
- }
-
- /**
- * Removes an attribute by name. If the removed attribute has a
- * default value it is immediately replaced. If the named
- * attribute does not exist, this method has no effect.
- *
- * @param name The name of the attribute to remove.
- * @exception DOMException
- * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
- **/
- public void removeAttribute( String name ) throws DOMException {
- checkReadOnly();
- AttrImpl attr = (AttrImpl) attributes.removeNamedItem(name);
- if ( attr != null ) {
- attr.setParentNode( (NodeImpl)this.getOwnerDocument() );
- }
- setDirty();
- }
-
- /**
- * The name of the element. For example, in: <elementExample
- * id="demo"> ... </elementExample> , <code>tagName</code> has
- * the value <code>"elementExample"</code>. Note that this is
- * case-preserving in XML, as are all of the operations of the DOM. The
- * HTML DOM returns the <code>tagName</code> of an HTML element in the
- * canonical uppercase form, regardless of the case in the source HTML
- * document.
- */
- public String getTagName() {
- return getNodeName();
- }
-
- /**
- * Retrieves an attribute value by name.
- * @param name The name of the attribute to retrieve.
- * @return The <code>Attr</code> value as a string, or the empty string if
- * that attribute does not have a specified or default value.
- */
- public String getAttribute(String name) {
- Attr attr = (Attr)attributes.getNamedItem(name);
- return attr != null ? attr.getValue()
- : "";
- }
-
- /**
- * Adds a new attribute. If an attribute with that name is already present
- * in the element, it is replaced by the new one.
- * @param newAttr The <code>Attr</code> node to add to the attribute list.
- * @return If the <code>newAttr</code> attribute replaces an existing
- * attribute with the same name, the previously existing
- * <code>Attr</code> node is returned, otherwise <code>null</code> is
- * returned.
- * @exception DOMException
- * WRONG_DOCUMENT_ERR: Raised if <code>newAttr</code> was created from a
- * different document than the one that created the element.
- * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
- * <br>INUSE_ATTRIBUTE_ERR: Raised if <code>newAttr</code> is already an
- * attribute of another <code>Element</code> object. The DOM user must
- * explicitly clone <code>Attr</code> nodes to re-use them in other
- * elements.
- */
- public Attr setAttributeNode(Attr newAttr) throws DOMException {
- checkReadOnly();
- Attr oldAttr = (Attr)attributes.getNamedItem(newAttr.getName());
- DocumentImpl doc = (DocumentImpl)getOwnerDocument();
- if ( newAttr.getParentNode().getNodeType() == Node.ELEMENT_NODE )
- throw EX_INUSE_ATTRIBUTE;
- if ( doc != newAttr.getOwnerDocument() )
- throw EX_WRONG_DOCUMENT;
- ((AttrImpl)newAttr).setParentNode(this);
- attributes.setNamedItem(newAttr);
- setDirty();
- return oldAttr;
- }
-
- /**
- * Adds a new attribute. If an attribute with that name is already present
- * in the element, its value is changed to be that of the value parameter.
- * This value is a simple string, it is not parsed as it is being set. So
- * any markup (such as syntax to be recognized as an entity reference) is
- * treated as literal text, and needs to be appropriately escaped by the
- * implementation when it is written out. In order to assign an attribute
- * value that contains entity references, the user must create an
- * <code>Attr</code> node plus any <code>Text</code> and
- * <code>EntityReference</code> nodes, build the appropriate subtree, and
- * use <code>setAttributeNode</code> to assign it as the value of an
- * attribute.
- * @param name The name of the attribute to create or alter.
- * @param value Value to set in string form.
- * @exception DOMException
- * INVALID_CHARACTER_ERR: Raised if the specified name contains an
- * invalid character.
- * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
- */
- public void setAttribute(String name, String value) throws DOMException {
- Attr attr = getOwnerDocument().createAttribute(name);
- attr.setValue(value);
- setAttributeNode(attr);
- }
-
- /**
- * Retrieves an <code>Attr</code> node by name.
- * @param name The name of the attribute to retrieve.
- * @return The <code>Attr</code> node with the specified attribute name or
- * <code>null</code> if there is no such attribute.
- */
- public Attr getAttributeNode(String name) {
- return (Attr)attributes.getNamedItem(name);
- }
-
- /**
- * Removes the specified attribute.
- * @param oldAttr The <code>Attr</code> node to remove from the attribute
- * list. If the removed <code>Attr</code> has a default value it is
- * immediately replaced.
- * @return The <code>Attr</code> node that was removed.
- * @exception DOMException
- * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
- * <br>NOT_FOUND_ERR: Raised if <code>oldAttr</code> is not an attribute
- * of the element.
- **/
- public Attr removeAttributeNode( Attr oldAttr ) throws DOMException {
- checkReadOnly();
- if ( oldAttr.getParentNode() != this ) {
- throw EX_NOT_FOUND;
- }
- attributes.remove( oldAttr.getName() );
- ((AttrImpl)oldAttr).setParentNode( (NodeImpl)this.getOwnerDocument() );
- setDirty();
- return oldAttr;
- }
+ /**
+ * Retrieves an attribute value by name.
+ * @param name The name of the attribute to retrieve.
+ * @return The <code>Attr</code> value as a string, or the empty string if
+ * that attribute does not have a specified or default value.
+ */
+ public String getAttribute(String name) {
+ Attr attr = (Attr) attributes.getNamedItem(name);
+ return attr != null ? attr.getValue() : "";
+ }
+
+ /**
+ * Adds a new attribute. If an attribute with that name is already present
+ * in the element, it is replaced by the new one.
+ * @param newAttr The <code>Attr</code> node to add to the attribute list.
+ * @return If the <code>newAttr</code> attribute replaces an existing
+ * attribute with the same name, the previously existing
+ * <code>Attr</code> node is returned, otherwise <code>null</code> is
+ * returned.
+ * @exception DOMException
+ * WRONG_DOCUMENT_ERR: Raised if <code>newAttr</code> was created from a
+ * different document than the one that created the element.
+ * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ * <br>INUSE_ATTRIBUTE_ERR: Raised if <code>newAttr</code> is already an
+ * attribute of another <code>Element</code> object. The DOM user must
+ * explicitly clone <code>Attr</code> nodes to re-use them in other
+ * elements.
+ */
+ public Attr setAttributeNode(Attr newAttr) throws DOMException {
+ checkReadOnly();
+ Attr oldAttr = (Attr) attributes.getNamedItem(newAttr.getName());
+ DocumentImpl doc = (DocumentImpl) getOwnerDocument();
+ if (newAttr.getParentNode().getNodeType() == Node.ELEMENT_NODE)
+ throw EX_INUSE_ATTRIBUTE;
+ if (doc != newAttr.getOwnerDocument())
+ throw EX_WRONG_DOCUMENT;
+ ((AttrImpl) newAttr).setParentNode(this);
+ attributes.setNamedItem(newAttr);
+ setDirty();
+ return oldAttr;
+ }
+
+ /**
+ * Adds a new attribute. If an attribute with that name is already present
+ * in the element, its value is changed to be that of the value parameter.
+ * This value is a simple string, it is not parsed as it is being set. So
+ * any markup (such as syntax to be recognized as an entity reference) is
+ * treated as literal text, and needs to be appropriately escaped by the
+ * implementation when it is written out. In order to assign an attribute
+ * value that contains entity references, the user must create an
+ * <code>Attr</code> node plus any <code>Text</code> and
+ * <code>EntityReference</code> nodes, build the appropriate subtree, and
+ * use <code>setAttributeNode</code> to assign it as the value of an
+ * attribute.
+ * @param name The name of the attribute to create or alter.
+ * @param value Value to set in string form.
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified name contains an
+ * invalid character.
+ * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ */
+ public void setAttribute(String name, String value) throws DOMException {
+ Attr attr = getOwnerDocument().createAttribute(name);
+ attr.setValue(value);
+ setAttributeNode(attr);
+ }
+
+ /**
+ * Retrieves an <code>Attr</code> node by name.
+ * @param name The name of the attribute to retrieve.
+ * @return The <code>Attr</code> node with the specified attribute name or
+ * <code>null</code> if there is no such attribute.
+ */
+ public Attr getAttributeNode(String name) {
+ return (Attr) attributes.getNamedItem(name);
+ }
+
+ /**
+ * Removes the specified attribute.
+ * @param oldAttr The <code>Attr</code> node to remove from the attribute
+ * list. If the removed <code>Attr</code> has a default value it is
+ * immediately replaced.
+ * @return The <code>Attr</code> node that was removed.
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ * <br>NOT_FOUND_ERR: Raised if <code>oldAttr</code> is not an attribute
+ * of the element.
+ **/
+ public Attr removeAttributeNode(Attr oldAttr) throws DOMException {
+ checkReadOnly();
+ if (oldAttr.getParentNode() != this) {
+ throw EX_NOT_FOUND;
+ }
+ attributes.remove(oldAttr.getName());
+ ((AttrImpl) oldAttr).setParentNode((NodeImpl) this.getOwnerDocument());
+ setDirty();
+ return oldAttr;
+ }
/**
* Retrieves an attribute value by local name and namespace URI.
@@ -350,11 +343,10 @@
* value.
* @since DOM Level 2
*/
- public String getAttributeNS(String namespaceURI, String localName) {
- Attr attr = (Attr)attributes.getNamedItemNS(namespaceURI, localName);
- return attr != null ? attr.getValue()
- : "";
- }
+ public String getAttributeNS(String namespaceURI, String localName) {
+ Attr attr = (Attr) attributes.getNamedItemNS(namespaceURI, localName);
+ return attr != null ? attr.getValue() : "";
+ }
/**
* Adds a new attribute. If an attribute with the same local name and
@@ -393,11 +385,11 @@
* "http://www.w3.org/2000/xmlns/".
* @since DOM Level 2
*/
- public void setAttributeNS(String namespaceURI, String qualifiedName, String value) {
- Attr attr = getOwnerDocument().createAttributeNS(namespaceURI, qualifiedName);
- attr.setValue(value);
- setAttributeNodeNS(attr);
- }
+ public void setAttributeNS(String namespaceURI, String qualifiedName, String value) {
+ Attr attr = getOwnerDocument().createAttributeNS(namespaceURI, qualifiedName);
+ attr.setValue(value);
+ setAttributeNodeNS(attr);
+ }
/**
* Removes an attribute by local name and namespace URI. If the
@@ -414,14 +406,14 @@
* NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
* @since DOM Level 2
**/
- public void removeAttributeNS( String namespaceURI, String localName ) {
- checkReadOnly();
- AttrImpl attr = (AttrImpl) attributes.removeNamedItemNS( namespaceURI, localName );
- if ( attr != null ) {
- attr.setParentNode( (NodeImpl)this.getOwnerDocument() );
- }
- setDirty();
- }
+ public void removeAttributeNS(String namespaceURI, String localName) {
+ checkReadOnly();
+ AttrImpl attr = (AttrImpl) attributes.removeNamedItemNS(namespaceURI, localName);
+ if (attr != null) {
+ attr.setParentNode((NodeImpl) this.getOwnerDocument());
+ }
+ setDirty();
+ }
/**
* Retrieves an <code>Attr</code> node by local name and namespace URI.
@@ -433,9 +425,9 @@
* attribute.
* @since DOM Level 2
*/
- public Attr getAttributeNodeNS(String namespaceURI, String localName) {
- return (Attr)attributes.getNamedItemNS(namespaceURI, localName);
- }
+ public Attr getAttributeNodeNS(String namespaceURI, String localName) {
+ return (Attr) attributes.getNamedItemNS(namespaceURI, localName);
+ }
/**
* Adds a new attribute. If an attribute with that local name and that
@@ -457,11 +449,11 @@
* other elements.
* @since DOM Level 2
*/
- public Attr setAttributeNodeNS(Attr newAttr) {
- return setAttributeNode(newAttr);
- }
-
- public boolean hasAttributeNS(String namespaceURI, String localName) {
- return attributes.getNamedItemNS(namespaceURI, localName) != null;
- }
+ public Attr setAttributeNodeNS(Attr newAttr) {
+ return setAttributeNode(newAttr);
+ }
+
+ public boolean hasAttributeNS(String namespaceURI, String localName) {
+ return attributes.getNamedItemNS(namespaceURI, localName) != null;
+ }
}
1.4 +83 -89 xml-xindice/java/src/org/apache/xindice/xml/dom/EntityReferenceImpl.java
Index: EntityReferenceImpl.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/dom/EntityReferenceImpl.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- EntityReferenceImpl.java 31 Oct 2002 07:02:23 -0000 1.3
+++ EntityReferenceImpl.java 15 Jul 2003 15:44:34 -0000 1.4
@@ -59,15 +59,14 @@
* $Id$
*/
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.xindice.util.ByteArrayInput;
import org.apache.xindice.xml.Signatures;
import org.apache.xindice.xml.SymbolTable;
import org.apache.xindice.xml.XMLCompressedInput;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.w3c.dom.*;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Node;
/**
* EntityReferenceImpl
@@ -75,91 +74,86 @@
public final class EntityReferenceImpl extends NodeImpl implements EntityReference {
- private static Log log = LogFactory.getLog("org.apache.xindice.xml");
+ private static Log log = LogFactory.getLog("org.apache.xindice.xml");
+
+ private short symbolID = -1;
- private short symbolID = -1;
+ public EntityReferenceImpl() {}
- public EntityReferenceImpl() {
- }
-
- public EntityReferenceImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
- super(parentNode, data, pos, len);
- }
-
- public EntityReferenceImpl(NodeImpl parentNode, boolean dirty) {
- super(parentNode, dirty);
- }
-
- public EntityReferenceImpl(NodeImpl parentNode, String nodeName) {
- super(parentNode, true);
- this.nodeName = nodeName;
- }
-
- protected void checkLoaded() {
- if ( loaded )
- return;
- else
- loaded = true;
-
- try {
- if ( data != null ) {
- DocumentImpl doc = (DocumentImpl)getOwnerDocument();
- SymbolTable st = doc.getSymbols();
-
- ByteArrayInput bis = new ByteArrayInput(data, pos, len);
- XMLCompressedInput xci = new XMLCompressedInput(bis, st);
-
- byte signature = xci.readByte();
- byte entityType = (byte)(signature & 0x1F);
- switch ( entityType ) {
-
- case Signatures.EntUnknown:
- nodeName = null;
- break;
-
- case Signatures.EntDefined:
- symbolID = xci.readShort();
- nodeName = st.getName(symbolID);
- break;
-
- case Signatures.EntAmp:
- nodeName = "&";
- break;
-
- case Signatures.EntLt:
- nodeName = "<";
- break;
-
- case Signatures.EntGt:
- nodeName = ">";
- break;
-
- case Signatures.EntQuot:
- nodeName = """;
- break;
-
- case Signatures.EntApos:
- nodeName = "'";
- break;
-
- case Signatures.EntUnicode:
- nodeName = "";
- // TODO: This
- break;
+ public EntityReferenceImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
+ super(parentNode, data, pos, len);
+ }
+
+ public EntityReferenceImpl(NodeImpl parentNode, boolean dirty) {
+ super(parentNode, dirty);
+ }
+
+ public EntityReferenceImpl(NodeImpl parentNode, String nodeName) {
+ super(parentNode, true);
+ this.nodeName = nodeName;
+ }
+
+ protected void checkLoaded() {
+ if (loaded)
+ return;
+ else
+ loaded = true;
+
+ try {
+ if (data != null) {
+ DocumentImpl doc = (DocumentImpl) getOwnerDocument();
+ SymbolTable st = doc.getSymbols();
+
+ ByteArrayInput bis = new ByteArrayInput(data, pos, len);
+ XMLCompressedInput xci = new XMLCompressedInput(bis, st);
+
+ byte signature = xci.readByte();
+ byte entityType = (byte) (signature & 0x1F);
+ switch (entityType) {
+
+ case Signatures.EntUnknown :
+ nodeName = null;
+ break;
+
+ case Signatures.EntDefined :
+ symbolID = xci.readShort();
+ nodeName = st.getName(symbolID);
+ break;
+
+ case Signatures.EntAmp :
+ nodeName = "&";
+ break;
+
+ case Signatures.EntLt :
+ nodeName = "<";
+ break;
+
+ case Signatures.EntGt :
+ nodeName = ">";
+ break;
+
+ case Signatures.EntQuot :
+ nodeName = """;
+ break;
+
+ case Signatures.EntApos :
+ nodeName = "'";
+ break;
+
+ case Signatures.EntUnicode :
+ nodeName = "";
+ // TODO: This
+ break;
+ }
}
- }
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- public short getNodeType() {
- return Node.ENTITY_REFERENCE_NODE;
- }
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ public short getNodeType() {
+ return Node.ENTITY_REFERENCE_NODE;
+ }
}
-
-
1.5 +1 -1 xml-xindice/java/src/org/apache/xindice/core/DBObserver.java
Index: DBObserver.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/DBObserver.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- DBObserver.java 14 Jul 2003 19:07:14 -0000 1.4
+++ DBObserver.java 15 Jul 2003 15:44:35 -0000 1.5
@@ -11,7 +11,7 @@
* Observer for Xindice DB activities
*/
public abstract class DBObserver {
-
+
private static final DBObserver NOOP = new DBObserver() {
public void setDatabaseConfig(Database db, Map collections, Configuration cfg) {}
1.12 +195 -200 xml-xindice/java/src/org/apache/xindice/core/CollectionManager.java
Index: CollectionManager.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/CollectionManager.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- CollectionManager.java 14 Jul 2003 19:07:15 -0000 1.11
+++ CollectionManager.java 15 Jul 2003 15:44:35 -0000 1.12
@@ -59,229 +59,224 @@
* $Id$
*/
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.xindice.util.Configurable;
import org.apache.xindice.util.Configuration;
import org.apache.xindice.util.ConfigurationCallback;
import org.apache.xindice.util.Disposable;
import org.apache.xindice.util.XindiceException;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.StringTokenizer;
-
/**
* CollectionManager is the base class for both Database and Collection.
*/
public class CollectionManager implements Configurable, Disposable {
- private static final String COLLECTION = "collection";
- private static final String COLLECTIONS = "collections";
- private static final String[] EmptyStrings = new String[0];
- private static Log log = LogFactory.getLog("org.apache.xindice.core");
- private static final String NAME = "name";
- private Map collections = new HashMap(); // Collection
- private Configuration config = null;
-
- protected CollectionManager() {}
-
- /**
- *
- * @param collection
- */
- protected void addCollection(Collection collection){
-
- this.collections.put(collection.getName(), collection);
- }
-
- /**
- * Returns number of child collections
- *
- * @return number of collections
- */
- public final long countCollections() throws DBException {
- return (long) collections.size();
- }
-
- /**
- * createCollection creates a new Collection object and any associated
- * system resources that the Collection will need.
- *
- * @param path The relative path of the Collection
- * @param cfg The Collection's configuration
- * @return The newly created Collection
- */
- public Collection createCollection(String path, Configuration cfg) throws DBException {
- if (path.indexOf("/") != -1) {
- CollectionManager cm = this;
- StringTokenizer st = new StringTokenizer(path, "/");
- while (cm != null && st.hasMoreTokens()) {
- path = st.nextToken().trim();
- if (path.length() == 0)
- continue;
- if (st.hasMoreTokens())
- cm = (CollectionManager) cm.collections.get(path);
- else
- return cm.createCollection(path, cfg);
- }
- throw new DBException(FaultCodes.COL_COLLECTION_NOT_FOUND, "Parent Collection '" + path + "' doesn't exist");
- }
-
- Collection collection = null;
-
- if (CollectionManager.this instanceof Database)
- collection = new Collection((Database) CollectionManager.this);
- else
- collection = new Collection((Collection) CollectionManager.this);
-
- try {
- // Do a name check to see if all is well
- String n = cfg.getAttribute(NAME);
- if (n == null || n.trim().equals(""))
- throw new DBException(FaultCodes.COL_CANNOT_CREATE, "No name specified");
-
- if (getCollection(n) != null)
- throw new DBException(FaultCodes.COL_DUPLICATE_COLLECTION, "Duplicate Collection '" + n + "'");
-
- Configuration colConfig = this.config.getChild(COLLECTIONS, true);
- colConfig.add(cfg);
-
- collection.setConfig(cfg);
- collection.create();
- collections.put(n, collection);
- if (log.isInfoEnabled()) {
- log.info("Created a new collection named '" + n + "'");
- }
- }
- catch (DBException e) {
- throw e;
- }
- catch (Exception e) {
- throw new DBException(FaultCodes.COL_CANNOT_CREATE, "Error Creating Collection '" + path + "'", e);
- }
- return collection;
- }
+ private static final String COLLECTION = "collection";
+ private static final String COLLECTIONS = "collections";
+ private static final String[] EmptyStrings = new String[0];
+ private static Log log = LogFactory.getLog("org.apache.xindice.core");
+ private static final String NAME = "name";
+ private Map collections = new HashMap(); // Collection
+ private Configuration config = null;
+
+ protected CollectionManager() {}
+
+ /**
+ *
+ * @param collection
+ */
+ protected void addCollection(Collection collection) {
+
+ this.collections.put(collection.getName(), collection);
+ }
+
+ /**
+ * Returns number of child collections
+ *
+ * @return number of collections
+ */
+ public final long countCollections() throws DBException {
+ return (long) collections.size();
+ }
+
+ /**
+ * createCollection creates a new Collection object and any associated
+ * system resources that the Collection will need.
+ *
+ * @param path The relative path of the Collection
+ * @param cfg The Collection's configuration
+ * @return The newly created Collection
+ */
+ public Collection createCollection(String path, Configuration cfg) throws DBException {
+ if (path.indexOf("/") != -1) {
+ CollectionManager cm = this;
+ StringTokenizer st = new StringTokenizer(path, "/");
+ while (cm != null && st.hasMoreTokens()) {
+ path = st.nextToken().trim();
+ if (path.length() == 0)
+ continue;
+ if (st.hasMoreTokens())
+ cm = (CollectionManager) cm.collections.get(path);
+ else
+ return cm.createCollection(path, cfg);
+ }
+ throw new DBException(FaultCodes.COL_COLLECTION_NOT_FOUND, "Parent Collection '" + path + "' doesn't exist");
+ }
+
+ Collection collection = null;
+
+ if (CollectionManager.this instanceof Database)
+ collection = new Collection((Database) CollectionManager.this);
+ else
+ collection = new Collection((Collection) CollectionManager.this);
+
+ try {
+ // Do a name check to see if all is well
+ String n = cfg.getAttribute(NAME);
+ if (n == null || n.trim().equals(""))
+ throw new DBException(FaultCodes.COL_CANNOT_CREATE, "No name specified");
+
+ if (getCollection(n) != null)
+ throw new DBException(FaultCodes.COL_DUPLICATE_COLLECTION, "Duplicate Collection '" + n + "'");
+
+ Configuration colConfig = this.config.getChild(COLLECTIONS, true);
+ colConfig.add(cfg);
+
+ collection.setConfig(cfg);
+ collection.create();
+ collections.put(n, collection);
+ log.info("Created a new collection named '" + n + "'");
+ }
+ catch (DBException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ throw new DBException(FaultCodes.COL_CANNOT_CREATE, "Error Creating Collection '" + path + "'", e);
+ }
+ return collection;
+ }
- /**
+ /**
* @see org.apache.xindice.util.Disposable#dispose()
*/
public void dispose() {}
- /**
- * dropCollection physically removes the specified Collection and any
- * associated system resources that the Collection uses.
- *
- * @param collection The Collection to drop
- * @return Whether or not the Collection was dropped
- */
- public boolean dropCollection(Collection collection) throws DBException {
- if (collection == null)
- throw new DBException(FaultCodes.COL_COLLECTION_NOT_FOUND, "Collection Value Null");
-
- Collection cm = collection.getParentCollection();
-
- if (cm == null)
- throw new DBException(FaultCodes.DBE_CANNOT_DROP, "You Cannot Drop The Database");
-
- if (cm != this)
- return cm.dropCollection(collection);
- else {
- final String name = collection.getName();
- boolean dropped = collection.drop();
- if (dropped) {
- collections.remove(name);
- Configuration colConfig = config.getChild(COLLECTIONS);
- colConfig.processChildren(COLLECTION, new ConfigurationCallback() {
- public void process(Configuration cfg) {
- try {
- if (cfg.getAttribute(NAME).equals(name))
- cfg.delete();
- }
- catch (Exception e) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
- });
- }
- return dropped;
- }
- }
-
- /**
- * getCollection retrieves a Collection by name.
- *
- * @param path The Collection path
- * @return The Collection (or null)
- */
- public Collection getCollection(String path) throws DBException {
- if (path.indexOf("/") != -1) {
- CollectionManager cm = this;
- StringTokenizer st = new StringTokenizer(path, "/");
- while (cm != null && st.hasMoreTokens()) {
- path = st.nextToken();
- cm = (CollectionManager) cm.collections.get(path);
- }
- return (Collection) cm;
- }
- else
- return (Collection) collections.get(path);
- }
-
- /**
- * @return
- */
- protected Map getCollections() {
- return this.collections;
- }
+ /**
+ * dropCollection physically removes the specified Collection and any
+ * associated system resources that the Collection uses.
+ *
+ * @param collection The Collection to drop
+ * @return Whether or not the Collection was dropped
+ */
+ public boolean dropCollection(Collection collection) throws DBException {
+ if (collection == null)
+ throw new DBException(FaultCodes.COL_COLLECTION_NOT_FOUND, "Collection Value Null");
+
+ Collection cm = collection.getParentCollection();
+
+ if (cm == null)
+ throw new DBException(FaultCodes.DBE_CANNOT_DROP, "You Cannot Drop The Database");
+
+ if (cm != this)
+ return cm.dropCollection(collection);
+ else {
+ final String name = collection.getName();
+ boolean dropped = collection.drop();
+ if (dropped) {
+ collections.remove(name);
+ Configuration colConfig = config.getChild(COLLECTIONS);
+ colConfig.processChildren(COLLECTION, new ConfigurationCallback() {
+ public void process(Configuration cfg) {
+ try {
+ if (cfg.getAttribute(NAME).equals(name))
+ cfg.delete();
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+ });
+ }
+ return dropped;
+ }
+ }
+
+ /**
+ * getCollection retrieves a Collection by name.
+ *
+ * @param path The Collection path
+ * @return The Collection (or null)
+ */
+ public Collection getCollection(String path) throws DBException {
+ if (path.indexOf("/") != -1) {
+ CollectionManager cm = this;
+ StringTokenizer st = new StringTokenizer(path, "/");
+ while (cm != null && st.hasMoreTokens()) {
+ path = st.nextToken();
+ cm = (CollectionManager) cm.collections.get(path);
+ }
+ return (Collection) cm;
+ }
+ else
+ return (Collection) collections.get(path);
+ }
- /**
+ /**
+ * @return
+ */
+ protected Map getCollections() {
+ return this.collections;
+ }
+
+ /**
* @see org.apache.xindice.util.Configurable#getConfig()
*/
public Configuration getConfig() {
- return config;
- }
+ return config;
+ }
- /**
- * listCollections retrieves a list of Collections as an array of
- * Strings.
- *
- * @return The Collection list
- */
- public final String[] listCollections() throws DBException {
- return (String[]) collections.keySet().toArray(EmptyStrings);
- }
+ /**
+ * listCollections retrieves a list of Collections as an array of
+ * Strings.
+ *
+ * @return The Collection list
+ */
+ public final String[] listCollections() throws DBException {
+ return (String[]) collections.keySet().toArray(EmptyStrings);
+ }
- /**
+ /**
* @see org.apache.xindice.util.Configurable#setConfig(org.apache.xindice.util.Configuration)
*/
public void setConfig(Configuration config) throws XindiceException {
- this.config = config;
+ this.config = config;
- Configuration colConfig = config.getChild(COLLECTIONS);
- if (colConfig != null) {
- colConfig.processChildren(COLLECTION, new ConfigurationCallback() {
- public void process(Configuration cfg) throws XindiceException {
- // check for an existing Collection by name and, if found, skip creating a new Collection
- // else, create a new child Collection, configure it an add it
- // if the Collection already exists in our collections list,
- // creating a new one will cause the old one to be discarded
- // while holding open file handles, etc.
- Collection col = (Collection) collections.get(cfg.getAttribute(NAME));
- if (col == null) {
- col = new Collection((Collection) CollectionManager.this);
- col.setConfig(cfg);
- collections.put(col.getName(), col);
- }
- // else, assume col is configured elsewhere...
- // I'm not sure this should be happening, but it does
- // it is not safe to call col.setConfig again since it does a bunch
- // of stuff (like creating a new Filer and overwriting the existing one, etc.)
- }
- });
- }
- }
+ Configuration colConfig = config.getChild(COLLECTIONS);
+ if (colConfig != null) {
+ colConfig.processChildren(COLLECTION, new ConfigurationCallback() {
+ public void process(Configuration cfg) throws XindiceException {
+ // check for an existing Collection by name and, if found, skip creating a new Collection
+ // else, create a new child Collection, configure it an add it
+ // if the Collection already exists in our collections list,
+ // creating a new one will cause the old one to be discarded
+ // while holding open file handles, etc.
+ Collection col = (Collection) collections.get(cfg.getAttribute(NAME));
+ if (col == null) {
+ col = new Collection((Collection) CollectionManager.this);
+ col.setConfig(cfg);
+ collections.put(col.getName(), col);
+ }
+ // else, assume col is configured elsewhere...
+ // I'm not sure this should be happening, but it does
+ // it is not safe to call col.setConfig again since it does a bunch
+ // of stuff (like creating a new Filer and overwriting the existing one, etc.)
+ }
+ });
+ }
+ }
}
1.15 +12 -12 xml-xindice/java/src/org/apache/xindice/core/SystemCollection.java
Index: SystemCollection.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/SystemCollection.java,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- SystemCollection.java 14 Jul 2003 19:08:16 -0000 1.14
+++ SystemCollection.java 15 Jul 2003 15:44:35 -0000 1.15
@@ -96,19 +96,19 @@
String SysCol = "<collection name=\"" + SYSCOL + "\">"
// System Collections
- +" <collections>"
+ +" <collections>"
// Symbol Tables Collection
- +" <collection name=\"" + SYMBOLS + "\" compressed=\"true\">" + " <filer class=\"org.apache.xindice.core.filer.BTreeFiler\" />"
+ +" <collection name=\"" + SYMBOLS + "\" compressed=\"true\">" + " <filer class=\"org.apache.xindice.core.filer.BTreeFiler\" />"
// Textual Representation of Hard-coded Symbol Table
- +SymbolTableSymbols.getDefinition() + " </collection>"
+ +SymbolTableSymbols.getDefinition() + " </collection>"
// System Configuration Collection
- +" <collection name=\""
- + CONFIGS
- + "\" compressed=\"false\">"
- + " <filer class=\"org.apache.xindice.core.filer.BTreeFiler\" />"
- + " </collection>"
- + " </collections>"
- + "</collection>";
+ +" <collection name=\""
+ + CONFIGS
+ + "\" compressed=\"false\">"
+ + " <filer class=\"org.apache.xindice.core.filer.BTreeFiler\" />"
+ + " </collection>"
+ + " </collections>"
+ + "</collection>";
try {
Document sysDoc = DOMParser.toDocument(SysCol);
@@ -119,7 +119,7 @@
if (log.isFatalEnabled()) {
log.fatal("FATAL ERROR: Generating System Collection '" + SYSCOL + "'", e);
}
-
+
// TODO: System.exit() CANNOT be good here.
System.exit(1);
}
1.22 +5 -13 xml-xindice/java/src/org/apache/xindice/core/Collection.java
Index: Collection.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/Collection.java,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- Collection.java 14 Jul 2003 19:07:15 -0000 1.21
+++ Collection.java 15 Jul 2003 15:44:35 -0000 1.22
@@ -181,9 +181,7 @@
return new ColContainer(key, DOMParser.toDocument(val));
}
catch (Exception e) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
+ log.warn(e);
}
}
}
@@ -369,9 +367,7 @@
((Collection) this).close();
}
catch (Exception e) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
+ log.warn(e);
}
}
@@ -847,9 +843,7 @@
return obj;
}
catch (Exception e) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
+ log.warn(e);
}
}
}
@@ -1431,9 +1425,7 @@
indexManager.setConfig(idxConfig);
}
catch (Exception e) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
+ log.warn(e);
}
}
1.8 +231 -243 xml-xindice/java/src/org/apache/xindice/core/filer/FSFiler.java
Index: FSFiler.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/filer/FSFiler.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- FSFiler.java 14 Jul 2003 13:58:17 -0000 1.7
+++ FSFiler.java 15 Jul 2003 15:44:35 -0000 1.8
@@ -59,6 +59,16 @@
* $Id$
*/
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileOutputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.xindice.core.DBException;
import org.apache.xindice.core.FaultCodes;
import org.apache.xindice.core.data.Key;
@@ -71,259 +81,237 @@
import org.apache.xindice.util.SimpleConfigurable;
import org.apache.xindice.util.XindiceException;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileOutputStream;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.StringTokenizer;
-
/**
* FSFiler allows you to use existing file systems withing Xindice.
*/
public final class FSFiler extends SimpleConfigurable implements Filer {
- private static final String LOCATION = "location";
- private static final String EXT = "ext";
- private static final String READONLY = "readonly";
-
- private static Log log = LogFactory.getLog("org.apache.xindice.core");
-
- private FileCache cache = new FileCache();
- private LockManager locks = new LockManager(16);
-
- private Set extensions = null;
-
- private String location;
- private File dir;
- private boolean opened = false;
- private boolean readOnly = false;
-
- public FSFiler() {
- }
-
- public String getName() {
- return "FSFiler";
- }
-
- public void setLocation(File root, String location) {
- }
-
- public void setConfig(Configuration config) throws XindiceException {
- super.setConfig(config);
- location = config.getAttribute(LOCATION);
- readOnly = config.getBooleanAttribute(READONLY, readOnly);
- String exts = config.getAttribute(EXT);
- if ( exts != null && exts.trim().length() > 0 ) {
- extensions = new HashSet();
- StringTokenizer st = new StringTokenizer(exts);
- while ( st.hasMoreTokens() )
- extensions.add(st.nextToken());
- }
- dir = new File(location);
- opened = false;
- }
-
- private void checkOpened() throws DBException {
- if ( !opened )
- throw new FilerException(FaultCodes.COL_COLLECTION_CLOSED, "Filer is closed");
- }
-
- private void checkReadOnly() throws DBException {
- if ( readOnly )
- throw new FilerException(FaultCodes.COL_COLLECTION_READ_ONLY, "Filer is read-only");
- }
-
- public boolean close() {
- opened = false;
- return true;
- }
-
- public boolean open() {
- opened = (dir.exists() && dir.isDirectory());
- return opened;
- }
-
- public boolean drop() {
- opened = false;
- return true;
- }
-
- public boolean isOpened() {
- return opened;
- }
-
- public boolean exists() {
- return dir.exists();
- }
-
- public boolean create() {
- if ( !dir.exists() )
- return dir.mkdirs();
- else
- return true;
- }
-
- public void flush() {
- }
-
- public Record readRecord(Key key) throws DBException {
- if ( key == null || key.equals("") ) {
- return null;
- }
- checkOpened();
-
- String fname = key.toString();
- if ( !isExtensionValid(fname) )
- return null;
-
- File file = new File(dir, fname);
- try {
- locks.acquireSharedLock(file);
-
- HashMap meta = new HashMap(2);
- meta.put(Record.MODIFIED, new Long(file.lastModified()));
-
- byte[] valueData = cache.getFile(file);
- if ( valueData != null )
- return new Record(key, new Value(valueData), meta);
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- finally {
- locks.releaseSharedLock(file);
- }
- return null;
- }
-
- public boolean writeRecord(Key key, Value value) throws DBException {
- if ( key == null || key.equals("") ) {
- throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid key: '" + key + "'");
- }
- if (value == null ) {
- throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid null value");
- }
- checkOpened();
- checkReadOnly();
-
- String fname = key.toString();
- if ( !isExtensionValid(fname) )
- return false;
-
- File file = new File(dir, fname);
- try {
- locks.acquireExclusiveLock(file);
- FileOutputStream fos = new FileOutputStream(file);
- value.streamTo(fos);
- fos.close();
- return true;
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- finally {
- locks.releaseExclusiveLock(file);
- }
- return true;
- }
-
- public boolean deleteRecord(Key key) throws DBException {
- if ( key == null || key.equals("") ) {
- return false;
- }
- checkOpened();
- checkReadOnly();
-
- String fname = key.toString();
- if ( !isExtensionValid(fname) )
- return false;
-
- File file = new File(dir, fname);
- try {
- locks.acquireExclusiveLock(file);
- return file.delete();
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- finally {
- locks.releaseExclusiveLock(file);
- }
- return true;
- }
-
- public long getRecordCount() throws DBException {
- checkOpened();
-
- File[] files = dir.listFiles(new FileFilter() {
- public boolean accept(File file) {
- return file.isFile() && isExtensionValid(file.getName());
- }
- });
- return files.length;
- }
-
- public RecordSet getRecordSet() throws DBException {
- checkOpened();
- return new FSRecordSet();
- }
-
- private boolean isExtensionValid(String fname) {
- if ( extensions != null ) {
- int idx = fname.lastIndexOf('.');
- if ( idx == -1 )
+ private static final String LOCATION = "location";
+ private static final String EXT = "ext";
+ private static final String READONLY = "readonly";
+
+ private static Log log = LogFactory.getLog("org.apache.xindice.core");
+
+ private FileCache cache = new FileCache();
+ private LockManager locks = new LockManager(16);
+
+ private Set extensions = null;
+
+ private String location;
+ private File dir;
+ private boolean opened = false;
+ private boolean readOnly = false;
+
+ public FSFiler() {}
+
+ public String getName() {
+ return "FSFiler";
+ }
+
+ public void setLocation(File root, String location) {}
+
+ public void setConfig(Configuration config) throws XindiceException {
+ super.setConfig(config);
+ location = config.getAttribute(LOCATION);
+ readOnly = config.getBooleanAttribute(READONLY, readOnly);
+ String exts = config.getAttribute(EXT);
+ if (exts != null && exts.trim().length() > 0) {
+ extensions = new HashSet();
+ StringTokenizer st = new StringTokenizer(exts);
+ while (st.hasMoreTokens())
+ extensions.add(st.nextToken());
+ }
+ dir = new File(location);
+ opened = false;
+ }
+
+ private void checkOpened() throws DBException {
+ if (!opened)
+ throw new FilerException(FaultCodes.COL_COLLECTION_CLOSED, "Filer is closed");
+ }
+
+ private void checkReadOnly() throws DBException {
+ if (readOnly)
+ throw new FilerException(FaultCodes.COL_COLLECTION_READ_ONLY, "Filer is read-only");
+ }
+
+ public boolean close() {
+ opened = false;
+ return true;
+ }
+
+ public boolean open() {
+ opened = (dir.exists() && dir.isDirectory());
+ return opened;
+ }
+
+ public boolean drop() {
+ opened = false;
+ return true;
+ }
+
+ public boolean isOpened() {
+ return opened;
+ }
+
+ public boolean exists() {
+ return dir.exists();
+ }
+
+ public boolean create() {
+ if (!dir.exists())
+ return dir.mkdirs();
+ else
+ return true;
+ }
+
+ public void flush() {}
+
+ public Record readRecord(Key key) throws DBException {
+ if (key == null || key.equals("")) {
+ return null;
+ }
+ checkOpened();
+
+ String fname = key.toString();
+ if (!isExtensionValid(fname))
+ return null;
+
+ File file = new File(dir, fname);
+ try {
+ locks.acquireSharedLock(file);
+
+ HashMap meta = new HashMap(2);
+ meta.put(Record.MODIFIED, new Long(file.lastModified()));
+
+ byte[] valueData = cache.getFile(file);
+ if (valueData != null)
+ return new Record(key, new Value(valueData), meta);
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ finally {
+ locks.releaseSharedLock(file);
+ }
+ return null;
+ }
+
+ public boolean writeRecord(Key key, Value value) throws DBException {
+ if (key == null || key.equals("")) {
+ throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid key: '" + key + "'");
+ }
+ if (value == null) {
+ throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid null value");
+ }
+ checkOpened();
+ checkReadOnly();
+
+ String fname = key.toString();
+ if (!isExtensionValid(fname))
return false;
- String ext = fname.substring(idx + 1);
- if ( !extensions.contains(ext) )
+
+ File file = new File(dir, fname);
+ try {
+ locks.acquireExclusiveLock(file);
+ FileOutputStream fos = new FileOutputStream(file);
+ value.streamTo(fos);
+ fos.close();
+ return true;
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ finally {
+ locks.releaseExclusiveLock(file);
+ }
+ return true;
+ }
+
+ public boolean deleteRecord(Key key) throws DBException {
+ if (key == null || key.equals("")) {
return false;
- }
- return true;
- }
+ }
+ checkOpened();
+ checkReadOnly();
+ String fname = key.toString();
+ if (!isExtensionValid(fname))
+ return false;
- /**
- * FSRecordSet
- */
+ File file = new File(dir, fname);
+ try {
+ locks.acquireExclusiveLock(file);
+ return file.delete();
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ finally {
+ locks.releaseExclusiveLock(file);
+ }
+ return true;
+ }
- private class FSRecordSet implements RecordSet {
- public File[] files;
- public int pos = 0;
+ public long getRecordCount() throws DBException {
+ checkOpened();
- public FSRecordSet() {
- files = dir.listFiles(new FileFilter() {
+ File[] files = dir.listFiles(new FileFilter() {
public boolean accept(File file) {
- return file.isFile() && isExtensionValid(file.getName());
+ return file.isFile() && isExtensionValid(file.getName());
}
- });
- }
-
- public synchronized boolean hasMoreRecords() {
- return pos < files.length;
- }
-
- public synchronized Record getNextRecord() throws DBException {
- File file = files[pos++];
- return readRecord(new Key(file.getName()));
- }
-
- public synchronized Value getNextValue() throws DBException {
- return getNextRecord().getValue();
- }
-
- public synchronized Key getNextKey() {
- return new Key(files[pos++].getName());
- }
- }
+ });
+ return files.length;
+ }
+
+ public RecordSet getRecordSet() throws DBException {
+ checkOpened();
+ return new FSRecordSet();
+ }
+
+ private boolean isExtensionValid(String fname) {
+ if (extensions != null) {
+ int idx = fname.lastIndexOf('.');
+ if (idx == -1)
+ return false;
+ String ext = fname.substring(idx + 1);
+ if (!extensions.contains(ext))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * FSRecordSet
+ */
+
+ private class FSRecordSet implements RecordSet {
+ public File[] files;
+ public int pos = 0;
+
+ public FSRecordSet() {
+ files = dir.listFiles(new FileFilter() {
+ public boolean accept(File file) {
+ return file.isFile() && isExtensionValid(file.getName());
+ }
+ });
+ }
+
+ public synchronized boolean hasMoreRecords() {
+ return pos < files.length;
+ }
+
+ public synchronized Record getNextRecord() throws DBException {
+ File file = files[pos++];
+ return readRecord(new Key(file.getName()));
+ }
+
+ public synchronized Value getNextValue() throws DBException {
+ return getNextRecord().getValue();
+ }
+
+ public synchronized Key getNextKey() {
+ return new Key(files[pos++].getName());
+ }
+ }
}
-
1.11 +918 -927 xml-xindice/java/src/org/apache/xindice/core/filer/BTree.java
Index: BTree.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/filer/BTree.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- BTree.java 22 Nov 2002 10:15:34 -0000 1.10
+++ BTree.java 15 Jul 2003 15:44:35 -0000 1.11
@@ -104,956 +104,947 @@
*/
public class BTree extends Paged {
- protected static final byte LEAF = 1;
- protected static final byte BRANCH = 2;
- protected static final byte STREAM = 3;
-
- private static Log log = LogFactory.getLog("org.apache.xindice.core");
-
- private Map cache = new WeakHashMap();
-
- private BTreeFileHeader fileHeader;
- private BTreeRootInfo rootInfo;
- private BTreeNode rootNode;
-
- public BTree() {
- super();
- fileHeader = (BTreeFileHeader)getFileHeader();
- fileHeader.setPageCount(1);
- fileHeader.setTotalCount(1);
- }
-
- public BTree(File file) {
- this();
- setFile(file);
- }
-
- public boolean open() throws DBException {
- if ( super.open() ) {
- long p = fileHeader.getRootPage();
- rootInfo = new BTreeRootInfo(p);
- rootNode = getBTreeNode(rootInfo, p, null);
- return true;
- }
- else
- return false;
- }
-
- public boolean create() throws DBException {
- if ( super.create() ) {
- try {
- open();
+ protected static final byte LEAF = 1;
+ protected static final byte BRANCH = 2;
+ protected static final byte STREAM = 3;
+
+ private static Log log = LogFactory.getLog("org.apache.xindice.core");
+
+ private Map cache = new WeakHashMap();
+
+ private BTreeFileHeader fileHeader;
+ private BTreeRootInfo rootInfo;
+ private BTreeNode rootNode;
+
+ public BTree() {
+ super();
+ fileHeader = (BTreeFileHeader) getFileHeader();
+ fileHeader.setPageCount(1);
+ fileHeader.setTotalCount(1);
+ }
+
+ public BTree(File file) {
+ this();
+ setFile(file);
+ }
+
+ public boolean open() throws DBException {
+ if (super.open()) {
long p = fileHeader.getRootPage();
rootInfo = new BTreeRootInfo(p);
- rootNode = new BTreeNode(rootInfo, getPage(p));
- rootNode.ph.setStatus(LEAF);
- rootNode.setValues(new Value[0]);
- rootNode.setPointers(new long[0]);
- rootNode.write();
- close();
+ rootNode = getBTreeNode(rootInfo, p, null);
return true;
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
- return false;
- }
-
- /**
- * addValue adds a Value to the BTree and associates a pointer with
- * it. The pointer can be used for referencing any type of data, it
- * just so happens that Xindice uses it for referencing pages of
- * associated data in the BTree file or other files.
- *
- * @param value The Value to add
- * @param pointer The pointer to associate with it
- * @return The previous value for the pointer (or -1)
- */
- public long addValue(Value value, long pointer) throws IOException, BTreeException {
- return getRootNode().addValue(value, pointer);
- }
-
- /**
- * addValue adds a Value to the BTree and associates a pointer with
- * it. The pointer can be used for referencing any type of data, it
- * just so happens that Xindice uses it for referencing pages of
- * associated data in the BTree file or other files.
- *
- * @param root The BTree's root information (for nested trees)
- * @param value The Value to add
- * @param pointer The pointer to associate with it
- * @return The previous value for the pointer (or -1)
- */
- public long addValue(BTreeRootInfo root, Value value, long pointer) throws IOException, BTreeException {
- return getRootNode(root).addValue(value, pointer);
- }
-
- /**
- * removeValue removes a Value from the BTree and returns the
- * associated pointer for it.
- *
- * @param value The Value to remove
- * @return The pointer that was associated with it
- */
- public long removeValue(Value value) throws IOException, BTreeException {
- return getRootNode().removeValue(value);
- }
-
- /**
- * removeValue removes a Value from the BTree and returns the
- * associated pointer for it.
- *
- * @param root The BTree's root information (for nested trees)
- * @param value The Value to remove
- * @return The pointer that was associated with it
- */
- public long removeValue(BTreeRootInfo root, Value value) throws IOException, BTreeException {
- return getRootNode(root).removeValue(value);
- }
-
- /**
- * findValue finds a Value in the BTree and returns the associated
- * pointer for it.
- *
- * @param value The Value to find
- * @return The pointer that was associated with it
- */
- public long findValue(Value value) throws IOException, BTreeException {
- return getRootNode().findValue(value);
- }
-
- /**
- * findValue finds a Value in the BTree and returns the associated
- * pointer for it.
- *
- * @param root The BTree's root information (for nested trees)
- * @param value The Value to find
- * @return The pointer that was associated with it
- */
- public long findValue(BTreeRootInfo root, Value value) throws IOException, BTreeException {
- return getRootNode(root).findValue(value);
- }
-
- /**
- * query performs a query against the BTree and performs callback
- * operations to report the search results.
- *
- * @param query The IndexQuery to use (or null for everything)
- * @param callback The callback instance
- */
- public void query(IndexQuery query, BTreeCallback callback) throws IOException, BTreeException {
- getRootNode().query(query, callback);
- }
-
- /**
- * query performs a query against the BTree and performs callback
- * operations to report the search results.
- *
- * @param root The BTree's root information (for nested trees)
- * @param query The IndexQuery to use (or null for everything)
- * @param callback The callback instance
- */
- public void query(BTreeRootInfo root, IndexQuery query, BTreeCallback callback) throws IOException, BTreeException {
- getRootNode(root).query(query, callback);
- }
-
- /**
- * createBTreeRoot creates a new BTree root node in the BTree file
- * based on the provided value for the main tree.
- *
- * @param v The sub-tree Value to create
- * @return The new BTreeRootInfo instance
- */
- protected final BTreeRootInfo createBTreeRoot(Value v) throws IOException, BTreeException {
- BTreeNode n = createBTreeNode(rootInfo, BTree.LEAF, null);
- n.write();
-
- long position = n.page.getPageNum();
- addValue(v, position);
- return new BTreeRootInfo(v, position);
- }
-
- /**
- * createBTreeRoot creates a new BTree root node in the BTree file
- * based on the provided root information, and value for the tree.
- *
- * @param root The BTreeRootInfo to build off of
- * @param v The sub-tree Value to create
- * @return The new BTreeRootInfo instance
- */
- protected final BTreeRootInfo createBTreeRoot(BTreeRootInfo root, Value v) throws IOException, BTreeException {
- BTreeNode n = createBTreeNode(root, BTree.LEAF, null);
- n.write();
-
- long position = n.page.getPageNum();
- addValue(v, position);
- return new BTreeRootInfo(root, v, position);
- }
-
- /**
- * findBTreeRoot searches for a BTreeRoot in the file and returns
- * the BTreeRootInfo for the specified value based on the main tree.
- *
- * @param v The sub-tree Value to search for
- * @return The new BTreeRootInfo instance
- */
- protected final BTreeRootInfo findBTreeRoot(Value v) throws IOException, BTreeException {
- long position = findValue(v);
- return new BTreeRootInfo(v, position);
- }
-
- /**
- * findBTreeRoot searches for a BTreeRoot in the file and returns
- * the BTreeRootInfo for the specified value based on the provided
- * BTreeRootInfo value.
- *
- * @param root The BTreeRootInfo to search from
- * @param v The sub-tree Value to search for
- * @return The new BTreeRootInfo instance
- */
- protected final BTreeRootInfo findBTreeRoot(BTreeRootInfo root, Value v) throws IOException, BTreeException {
- long position = findValue(root, v);
- return new BTreeRootInfo(root, v, position);
- }
-
- /**
- * setRootNode resets the root for the specified root object to the
- * provided BTreeNode's page number.
- *
- * @param root The root to reset
- * @param newRoot the new root node to use
- */
- protected final void setRootNode(BTreeRootInfo root, BTreeNode newRoot) throws IOException, BTreeException {
- BTreeRootInfo parent = root.getParent();
- if ( parent == null ) {
- rootNode = newRoot;
- long p = rootNode.page.getPageNum();
- rootInfo.setPage(p);
- fileHeader.setRootPage(p);
- }
- else {
- long p = newRoot.page.getPageNum();
- root.setPage(p);
- addValue(parent, root.name, p);
- }
- }
-
- /**
- * setRootNode resets the file's root to the provided
- * BTreeNode's page number.
- *
- * @param rootNode the new root node to use
- */
- protected final void setRootNode(BTreeNode rootNode) throws IOException, BTreeException {
- setRootNode(rootInfo, rootNode);
- }
-
- /**
- * getRootNode retreives the BTree node for the specified
- * root object.
- *
- * @param root The root object to retrieve with
- * @return The root node
- */
- protected final BTreeNode getRootNode(BTreeRootInfo root) {
- if ( root.page == rootInfo.page )
- return rootNode;
- else
- return getBTreeNode(root, root.getPage(), null);
- }
-
- /**
- * getRootNode retreives the BTree node for the file's root.
- *
- * @return The root node
- */
- protected final BTreeNode getRootNode() {
- return rootNode;
- }
-
- private BTreeNode getBTreeNode(BTreeRootInfo root, long page, BTreeNode parent) {
- try {
- BTreeNode node;
- synchronized ( this ) {
- Long pNum = new Long(page);
- node = (BTreeNode)cache.get(pNum);
- if ( node == null ) {
- Page p = getPage(pNum);
- node = new BTreeNode(root, p, parent);
+ }
+ else
+ return false;
+ }
+
+ public boolean create() throws DBException {
+ if (super.create()) {
+ try {
+ open();
+ long p = fileHeader.getRootPage();
+ rootInfo = new BTreeRootInfo(p);
+ rootNode = new BTreeNode(rootInfo, getPage(p));
+ rootNode.ph.setStatus(LEAF);
+ rootNode.setValues(new Value[0]);
+ rootNode.setPointers(new long[0]);
+ rootNode.write();
+ close();
+ return true;
}
- else {
- node.root = root;
- node.parent = parent;
+ catch (Exception e) {
+ log.warn(e);
}
- }
- synchronized ( node ) {
- if ( !node.isLoaded() ) {
- node.read();
- node.setLoaded(true);
- }
- }
- return node;
- }
- catch ( Exception e ) {
- return null;
- }
- }
-
- private BTreeNode createBTreeNode(BTreeRootInfo root, byte status, BTreeNode parent) {
- try {
- Page p = getFreePage();
- BTreeNode node = new BTreeNode(root, p, parent);
- node.ph.setStatus(status);
- node.setValues(new Value[0]);
- node.setPointers(new long[0]);
- return node;
- }
- catch ( Exception e ) {
- return null;
- }
- }
-
-
- /**
- * BTreeRootInfo
- */
-
- public final class BTreeRootInfo {
- private BTreeRootInfo parent;
- private Value name;
- private long page;
-
- public BTreeRootInfo(BTreeRootInfo parent, String name, long page) {
- this.parent = parent;
- this.name = new Value(name);
- this.page = page;
- }
-
- public BTreeRootInfo(BTreeRootInfo parent, Value name, long page) {
- this.parent = parent;
- this.name = name;
- this.page = page;
- }
-
- public BTreeRootInfo(String name, long page) {
- this.parent = rootInfo;
- this.name = new Value(name);
- this.page = page;
- }
-
- public BTreeRootInfo(Value name, long page) {
- this.parent = rootInfo;
- this.name = name;
- this.page = page;
- }
-
- private BTreeRootInfo(long page) {
- parent = null;
- name = null;
- this.page = page;
- }
-
- public synchronized BTreeRootInfo getParent() {
- return parent;
- }
-
- public synchronized Value getName() {
- return name;
- }
-
- public synchronized long getPage() {
- return page;
- }
-
- public synchronized void setPage(long page) {
- this.page = page;
- }
- }
-
-
- /**
- * BTreeNode
- */
-
- private final class BTreeNode {
- private BTreeRootInfo root;
- private Page page;
- private BTreePageHeader ph;
- private Value[] values;
- private long[] ptrs;
- private BTreeNode parent;
- private boolean loaded;
-
- public BTreeNode(BTreeRootInfo root, Page page, BTreeNode parent) {
- this.root = root;
- this.page = page;
- this.parent = parent;
- ph = (BTreePageHeader)page.getPageHeader();
- }
-
- public BTreeNode(BTreeRootInfo root, Page page) {
- this.root = root;
- this.page = page;
- ph = (BTreePageHeader)page.getPageHeader();
- }
-
- public synchronized void setValues(Value[] values) {
- this.values = values;
- ph.setValueCount((short)values.length);
- }
-
- public synchronized Value[] getValues() {
- return values;
- }
-
- public synchronized void setPointers(long[] ptrs) {
- this.ptrs = ptrs;
- }
-
- public synchronized long[] getPointers() {
- return ptrs;
- }
-
- public synchronized boolean isLoaded() {
- return loaded;
- }
-
- public synchronized void setLoaded(boolean loaded) {
- this.loaded = loaded;
- }
-
- public synchronized void read() throws IOException {
- Value v = readValue(page);
- DataInputStream is = new DataInputStream(v.getInputStream());
-
- // Read in the Values
- values = new Value[ph.getValueCount()];
- for ( int i = 0; i < values.length; i++ ) {
- short valSize = is.readShort();
- byte[] b = new byte[valSize];
-
- is.read(b);
- values[i] = new Value(b);
- }
-
- // Read in the pointers
- ptrs = new long[ph.getPointerCount()];
- for ( int i = 0; i < ptrs.length; i++ )
- ptrs[i] = is.readLong();
-
- cache.put(new Long(page.getPageNum()), this);
- }
-
- public synchronized void write() throws IOException {
- ByteArrayOutputStream bos = new ByteArrayOutputStream((int)fileHeader.getWorkSize());
- DataOutputStream os = new DataOutputStream(bos);
-
- // Write out the Values
- for ( int i = 0; i < values.length; i++ ) {
- os.writeShort(values[i].getLength());
- values[i].streamTo(os);
- }
-
- // Write out the pointers
- for ( int i = 0; i < ptrs.length; i++ )
- os.writeLong(ptrs[i]);
-
- writeValue(page, new Value(bos.toByteArray()));
-
- cache.put(new Long(page.getPageNum()), this);
- }
-
- public BTreeNode getChildNode(int idx) throws IOException {
- boolean load;
- BTreeRootInfo loadNode;
- long loadPtr;
- synchronized ( this ) {
- if ( ph.getStatus() == BRANCH && idx >= 0 && idx < ptrs.length ) {
- load = true;
- loadNode = root;
- loadPtr = ptrs[idx];
+ }
+ return false;
+ }
+
+ /**
+ * addValue adds a Value to the BTree and associates a pointer with
+ * it. The pointer can be used for referencing any type of data, it
+ * just so happens that Xindice uses it for referencing pages of
+ * associated data in the BTree file or other files.
+ *
+ * @param value The Value to add
+ * @param pointer The pointer to associate with it
+ * @return The previous value for the pointer (or -1)
+ */
+ public long addValue(Value value, long pointer) throws IOException, BTreeException {
+ return getRootNode().addValue(value, pointer);
+ }
+
+ /**
+ * addValue adds a Value to the BTree and associates a pointer with
+ * it. The pointer can be used for referencing any type of data, it
+ * just so happens that Xindice uses it for referencing pages of
+ * associated data in the BTree file or other files.
+ *
+ * @param root The BTree's root information (for nested trees)
+ * @param value The Value to add
+ * @param pointer The pointer to associate with it
+ * @return The previous value for the pointer (or -1)
+ */
+ public long addValue(BTreeRootInfo root, Value value, long pointer) throws IOException, BTreeException {
+ return getRootNode(root).addValue(value, pointer);
+ }
+
+ /**
+ * removeValue removes a Value from the BTree and returns the
+ * associated pointer for it.
+ *
+ * @param value The Value to remove
+ * @return The pointer that was associated with it
+ */
+ public long removeValue(Value value) throws IOException, BTreeException {
+ return getRootNode().removeValue(value);
+ }
+
+ /**
+ * removeValue removes a Value from the BTree and returns the
+ * associated pointer for it.
+ *
+ * @param root The BTree's root information (for nested trees)
+ * @param value The Value to remove
+ * @return The pointer that was associated with it
+ */
+ public long removeValue(BTreeRootInfo root, Value value) throws IOException, BTreeException {
+ return getRootNode(root).removeValue(value);
+ }
+
+ /**
+ * findValue finds a Value in the BTree and returns the associated
+ * pointer for it.
+ *
+ * @param value The Value to find
+ * @return The pointer that was associated with it
+ */
+ public long findValue(Value value) throws IOException, BTreeException {
+ return getRootNode().findValue(value);
+ }
+
+ /**
+ * findValue finds a Value in the BTree and returns the associated
+ * pointer for it.
+ *
+ * @param root The BTree's root information (for nested trees)
+ * @param value The Value to find
+ * @return The pointer that was associated with it
+ */
+ public long findValue(BTreeRootInfo root, Value value) throws IOException, BTreeException {
+ return getRootNode(root).findValue(value);
+ }
+
+ /**
+ * query performs a query against the BTree and performs callback
+ * operations to report the search results.
+ *
+ * @param query The IndexQuery to use (or null for everything)
+ * @param callback The callback instance
+ */
+ public void query(IndexQuery query, BTreeCallback callback) throws IOException, BTreeException {
+ getRootNode().query(query, callback);
+ }
+
+ /**
+ * query performs a query against the BTree and performs callback
+ * operations to report the search results.
+ *
+ * @param root The BTree's root information (for nested trees)
+ * @param query The IndexQuery to use (or null for everything)
+ * @param callback The callback instance
+ */
+ public void query(BTreeRootInfo root, IndexQuery query, BTreeCallback callback) throws IOException, BTreeException {
+ getRootNode(root).query(query, callback);
+ }
+
+ /**
+ * createBTreeRoot creates a new BTree root node in the BTree file
+ * based on the provided value for the main tree.
+ *
+ * @param v The sub-tree Value to create
+ * @return The new BTreeRootInfo instance
+ */
+ protected final BTreeRootInfo createBTreeRoot(Value v) throws IOException, BTreeException {
+ BTreeNode n = createBTreeNode(rootInfo, BTree.LEAF, null);
+ n.write();
+
+ long position = n.page.getPageNum();
+ addValue(v, position);
+ return new BTreeRootInfo(v, position);
+ }
+
+ /**
+ * createBTreeRoot creates a new BTree root node in the BTree file
+ * based on the provided root information, and value for the tree.
+ *
+ * @param root The BTreeRootInfo to build off of
+ * @param v The sub-tree Value to create
+ * @return The new BTreeRootInfo instance
+ */
+ protected final BTreeRootInfo createBTreeRoot(BTreeRootInfo root, Value v) throws IOException, BTreeException {
+ BTreeNode n = createBTreeNode(root, BTree.LEAF, null);
+ n.write();
+
+ long position = n.page.getPageNum();
+ addValue(v, position);
+ return new BTreeRootInfo(root, v, position);
+ }
+
+ /**
+ * findBTreeRoot searches for a BTreeRoot in the file and returns
+ * the BTreeRootInfo for the specified value based on the main tree.
+ *
+ * @param v The sub-tree Value to search for
+ * @return The new BTreeRootInfo instance
+ */
+ protected final BTreeRootInfo findBTreeRoot(Value v) throws IOException, BTreeException {
+ long position = findValue(v);
+ return new BTreeRootInfo(v, position);
+ }
+
+ /**
+ * findBTreeRoot searches for a BTreeRoot in the file and returns
+ * the BTreeRootInfo for the specified value based on the provided
+ * BTreeRootInfo value.
+ *
+ * @param root The BTreeRootInfo to search from
+ * @param v The sub-tree Value to search for
+ * @return The new BTreeRootInfo instance
+ */
+ protected final BTreeRootInfo findBTreeRoot(BTreeRootInfo root, Value v) throws IOException, BTreeException {
+ long position = findValue(root, v);
+ return new BTreeRootInfo(root, v, position);
+ }
+
+ /**
+ * setRootNode resets the root for the specified root object to the
+ * provided BTreeNode's page number.
+ *
+ * @param root The root to reset
+ * @param newRoot the new root node to use
+ */
+ protected final void setRootNode(BTreeRootInfo root, BTreeNode newRoot) throws IOException, BTreeException {
+ BTreeRootInfo parent = root.getParent();
+ if (parent == null) {
+ rootNode = newRoot;
+ long p = rootNode.page.getPageNum();
+ rootInfo.setPage(p);
+ fileHeader.setRootPage(p);
+ }
+ else {
+ long p = newRoot.page.getPageNum();
+ root.setPage(p);
+ addValue(parent, root.name, p);
+ }
+ }
+
+ /**
+ * setRootNode resets the file's root to the provided
+ * BTreeNode's page number.
+ *
+ * @param rootNode the new root node to use
+ */
+ protected final void setRootNode(BTreeNode rootNode) throws IOException, BTreeException {
+ setRootNode(rootInfo, rootNode);
+ }
+
+ /**
+ * getRootNode retreives the BTree node for the specified
+ * root object.
+ *
+ * @param root The root object to retrieve with
+ * @return The root node
+ */
+ protected final BTreeNode getRootNode(BTreeRootInfo root) {
+ if (root.page == rootInfo.page)
+ return rootNode;
+ else
+ return getBTreeNode(root, root.getPage(), null);
+ }
+
+ /**
+ * getRootNode retreives the BTree node for the file's root.
+ *
+ * @return The root node
+ */
+ protected final BTreeNode getRootNode() {
+ return rootNode;
+ }
+
+ private BTreeNode getBTreeNode(BTreeRootInfo root, long page, BTreeNode parent) {
+ try {
+ BTreeNode node;
+ synchronized (this) {
+ Long pNum = new Long(page);
+ node = (BTreeNode) cache.get(pNum);
+ if (node == null) {
+ Page p = getPage(pNum);
+ node = new BTreeNode(root, p, parent);
+ }
+ else {
+ node.root = root;
+ node.parent = parent;
+ }
}
- else {
- load = false;
- loadNode = null;
- loadPtr = 0;
- }
- }
- if ( load )
- return getBTreeNode(loadNode, loadPtr, this);
- else
+ synchronized (node) {
+ if (!node.isLoaded()) {
+ node.read();
+ node.setLoaded(true);
+ }
+ }
+ return node;
+ }
+ catch (Exception e) {
return null;
- }
+ }
+ }
- public synchronized void getChildStream(int idx, Streamable stream) throws IOException {
- if ( ph.getStatus() == LEAF && idx >= 0 && idx < ptrs.length ) {
- Value v = readValue(ptrs[idx]);
- DataInputStream dis = new DataInputStream(v.getInputStream());
- stream.read(dis);
- }
- }
-
- public synchronized long removeValue(Value value) throws IOException, BTreeException {
- int idx = Arrays.binarySearch(values, value);
- switch ( ph.getStatus() ) {
- case BRANCH:
- idx = idx < 0 ? -(idx + 1) : idx + 1;
- return getChildNode(idx).removeValue(value);
-
- case LEAF:
- if ( idx < 0 )
- throw new BTreeNotFoundException("Value '" + value.toString() + "' doesn't exist");
- else {
- long oldPtr = ptrs[idx];
-
- setValues(deleteArrayValue(values, idx));
- setPointers(deleteArrayLong(ptrs, idx));
-
- write();
- return oldPtr;
- }
-
- default:
- throw new BTreeCorruptException("Invalid Page Type In removeValue");
- }
- }
-
- public synchronized long addValue(Value value, long pointer) throws IOException, BTreeException {
- if (value == null) {
- throw new BTreeException(FaultCodes.DBE_CANNOT_CREATE, "Can't add a null Value");
- }
-
- int idx = Arrays.binarySearch(values, value);
-
- switch ( ph.getStatus() ) {
- case BRANCH:
- idx = idx < 0 ? -(idx + 1) : idx + 1;
- return getChildNode(idx).addValue(value, pointer);
-
- case LEAF:
- if ( idx >= 0 ) {
- // Value was found... Overwrite
- long oldPtr = ptrs[idx];
- ptrs[idx] = pointer;
-
- setValues(values);
- setPointers(ptrs);
-
- write();
- return oldPtr;
- }
- else {
- // Value was not found
- idx = -(idx + 1);
-
- // Check to see if we've exhausted the block
- boolean split = ph.getDataLen() + 6 + value.getLength() > fileHeader.getWorkSize();
-
- setValues(insertArrayValue(values, value, idx));
- setPointers(insertArrayLong(ptrs, pointer, idx));
-
- if ( split )
- split();
- else
- write();
- }
- return -1;
-
- default:
- throw new BTreeCorruptException("Invalid Page Type In addValue");
- }
- }
-
- public synchronized void promoteValue(Value value, long rightPointer) throws IOException, BTreeException {
- // Check to see if we've exhausted the block
- boolean split = ph.getDataLen() + 6 + value.getLength() > fileHeader.getWorkSize();
-
- int idx = Arrays.binarySearch(values, value);
- idx = idx < 0 ? -(idx + 1) : idx + 1;
-
- setValues(insertArrayValue(values, value, idx));
- setPointers(insertArrayLong(ptrs, rightPointer, idx + 1));
-
- if ( split )
- split();
- else
- write();
- }
-
- public Value getSeparator(Value value1, Value value2) {
- int idx = value1.compareTo(value2);
- byte[] b = new byte[Math.abs(idx)];
- System.arraycopy(value2.getData(), 0, b, 0, b.length);
- return new Value(b);
- }
-
- public synchronized void split() throws IOException, BTreeException {
- Value[] leftVals;
- Value[] rightVals;
- long[] leftPtrs;
- long[] rightPtrs;
- Value separator;
-
- short vc = ph.getValueCount();
- int pivot = vc / 2;
-
- // Split the node into two nodes
- switch ( ph.getStatus() ) {
- case BRANCH:
- leftVals = new Value[pivot];
- leftPtrs = new long[leftVals.length + 1];
- rightVals = new Value[vc - (pivot + 1)];
- rightPtrs = new long[rightVals.length + 1];
-
- System.arraycopy(values, 0, leftVals, 0, leftVals.length);
- System.arraycopy(ptrs, 0, leftPtrs, 0, leftPtrs.length);
- System.arraycopy(values, leftVals.length + 1, rightVals, 0, rightVals.length);
- System.arraycopy(ptrs, leftPtrs.length, rightPtrs, 0, rightPtrs.length);
-
- separator = values[leftVals.length];
- break;
-
- case LEAF:
- leftVals = new Value[pivot];
- leftPtrs = new long[leftVals.length];
- rightVals = new Value[vc - pivot];
- rightPtrs = new long[rightVals.length];
-
- System.arraycopy(values, 0, leftVals, 0, leftVals.length);
- System.arraycopy(ptrs, 0, leftPtrs, 0, leftPtrs.length);
- System.arraycopy(values, leftVals.length, rightVals, 0, rightVals.length);
- System.arraycopy(ptrs, leftPtrs.length, rightPtrs, 0, rightPtrs.length);
-
- separator = getSeparator(leftVals[leftVals.length - 1], rightVals[0]);
- break;
-
- default:
- throw new BTreeCorruptException("Invalid Page Type In split");
- }
-
- setValues(leftVals);
- setPointers(leftPtrs);
-
- // Promote the pivot to the parent branch
- if ( parent == null ) {
- // This can only happen if this is the root
- BTreeNode np = createBTreeNode(root, BRANCH, null);
-
- BTreeNode rNode = createBTreeNode(root, ph.getStatus(), np);
- rNode.setValues(rightVals);
- rNode.setPointers(rightPtrs);
-
- np.setValues(new Value[]{separator});
- np.setPointers(new long[]{page.getPageNum(), rNode.page.getPageNum()});
-
- parent = np;
-
- setRootNode(root, np);
-
- write();
- rNode.write();
- np.write();
- }
- else {
- BTreeNode rNode = createBTreeNode(root, ph.getStatus(), parent);
- rNode.setValues(rightVals);
- rNode.setPointers(rightPtrs);
-
- write();
- rNode.write();
- parent.promoteValue(separator, rNode.page.getPageNum());
- }
- }
-
- /////////////////////////////////////////////////////////////////
-
- public synchronized long findValue(Value value) throws IOException, BTreeException {
- if (value == null) {
- throw new BTreeNotFoundException("Can't search on null Value");
- }
-
- int idx = Arrays.binarySearch(values, value);
-
- switch ( ph.getStatus() ) {
- case BRANCH:
- idx = idx < 0 ? -(idx + 1) : idx + 1;
- return getChildNode(idx).findValue(value);
-
- case LEAF:
- if ( idx < 0 )
- throw new BTreeNotFoundException("Value '" + value.toString() + "' doesn't exist");
- else
- return ptrs[idx];
-
- default:
- throw new BTreeCorruptException("Invalid Page Type In findValue");
- }
- }
-
- // query is a BEAST of a method
- public synchronized void query(IndexQuery query, BTreeCallback callback) throws IOException, BTreeException {
- if ( query != null && query.getOperator() != IndexQuery.ANY ) {
- Value[] qvals = query.getValues();
- int leftIdx = Arrays.binarySearch(values, qvals[0]);
- int rightIdx = qvals.length > 1 ? Arrays.binarySearch(values, qvals[qvals.length - 1])
- : leftIdx;
-
- switch ( ph.getStatus() ) {
- case BRANCH:
- leftIdx = leftIdx < 0 ? -(leftIdx + 1) : leftIdx + 1;
- rightIdx = rightIdx < 0 ? -(rightIdx + 1) : rightIdx + 1;
-
- switch ( query.getOperator() ) {
- case IndexQuery.BWX:
- case IndexQuery.BW:
- case IndexQuery.IN:
- case IndexQuery.SW:
- for ( int i = 0; i < ptrs.length; i++ )
- if ( i >= leftIdx && i <= rightIdx )
- getChildNode(i).query(query, callback);
- break;
+ private BTreeNode createBTreeNode(BTreeRootInfo root, byte status, BTreeNode parent) {
+ try {
+ Page p = getFreePage();
+ BTreeNode node = new BTreeNode(root, p, parent);
+ node.ph.setStatus(status);
+ node.setValues(new Value[0]);
+ node.setPointers(new long[0]);
+ return node;
+ }
+ catch (Exception e) {
+ return null;
+ }
+ }
- case IndexQuery.NBWX:
- case IndexQuery.NBW:
- case IndexQuery.NIN:
- case IndexQuery.NSW:
- for ( int i = 0; i < ptrs.length; i++ )
- if ( i <= leftIdx || i >= rightIdx )
- getChildNode(i).query(query, callback);
- break;
+ /**
+ * BTreeRootInfo
+ */
+
+ public final class BTreeRootInfo {
+ private BTreeRootInfo parent;
+ private Value name;
+ private long page;
+
+ public BTreeRootInfo(BTreeRootInfo parent, String name, long page) {
+ this.parent = parent;
+ this.name = new Value(name);
+ this.page = page;
+ }
+
+ public BTreeRootInfo(BTreeRootInfo parent, Value name, long page) {
+ this.parent = parent;
+ this.name = name;
+ this.page = page;
+ }
+
+ public BTreeRootInfo(String name, long page) {
+ this.parent = rootInfo;
+ this.name = new Value(name);
+ this.page = page;
+ }
+
+ public BTreeRootInfo(Value name, long page) {
+ this.parent = rootInfo;
+ this.name = name;
+ this.page = page;
+ }
+
+ private BTreeRootInfo(long page) {
+ parent = null;
+ name = null;
+ this.page = page;
+ }
+
+ public synchronized BTreeRootInfo getParent() {
+ return parent;
+ }
+
+ public synchronized Value getName() {
+ return name;
+ }
+
+ public synchronized long getPage() {
+ return page;
+ }
+
+ public synchronized void setPage(long page) {
+ this.page = page;
+ }
+ }
+
+ /**
+ * BTreeNode
+ */
+
+ private final class BTreeNode {
+ private BTreeRootInfo root;
+ private Page page;
+ private BTreePageHeader ph;
+ private Value[] values;
+ private long[] ptrs;
+ private BTreeNode parent;
+ private boolean loaded;
+
+ public BTreeNode(BTreeRootInfo root, Page page, BTreeNode parent) {
+ this.root = root;
+ this.page = page;
+ this.parent = parent;
+ ph = (BTreePageHeader) page.getPageHeader();
+ }
+
+ public BTreeNode(BTreeRootInfo root, Page page) {
+ this.root = root;
+ this.page = page;
+ ph = (BTreePageHeader) page.getPageHeader();
+ }
+
+ public synchronized void setValues(Value[] values) {
+ this.values = values;
+ ph.setValueCount((short) values.length);
+ }
+
+ public synchronized Value[] getValues() {
+ return values;
+ }
+
+ public synchronized void setPointers(long[] ptrs) {
+ this.ptrs = ptrs;
+ }
+
+ public synchronized long[] getPointers() {
+ return ptrs;
+ }
+
+ public synchronized boolean isLoaded() {
+ return loaded;
+ }
+
+ public synchronized void setLoaded(boolean loaded) {
+ this.loaded = loaded;
+ }
+
+ public synchronized void read() throws IOException {
+ Value v = readValue(page);
+ DataInputStream is = new DataInputStream(v.getInputStream());
+
+ // Read in the Values
+ values = new Value[ph.getValueCount()];
+ for (int i = 0; i < values.length; i++) {
+ short valSize = is.readShort();
+ byte[] b = new byte[valSize];
- case IndexQuery.EQ:
- getChildNode(leftIdx).query(query, callback);
- break;
+ is.read(b);
+ values[i] = new Value(b);
+ }
- case IndexQuery.LT:
- case IndexQuery.LEQ:
- for ( int i = 0; i < ptrs.length; i++ )
- if ( i <= leftIdx )
- getChildNode(i).query(query, callback);
- break;
+ // Read in the pointers
+ ptrs = new long[ph.getPointerCount()];
+ for (int i = 0; i < ptrs.length; i++)
+ ptrs[i] = is.readLong();
+
+ cache.put(new Long(page.getPageNum()), this);
+ }
+
+ public synchronized void write() throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream((int) fileHeader.getWorkSize());
+ DataOutputStream os = new DataOutputStream(bos);
+
+ // Write out the Values
+ for (int i = 0; i < values.length; i++) {
+ os.writeShort(values[i].getLength());
+ values[i].streamTo(os);
+ }
- case IndexQuery.GT:
- case IndexQuery.GEQ:
- for ( int i = 0; i < ptrs.length; i++ )
- if ( i >= rightIdx )
- getChildNode(i).query(query, callback);
- break;
+ // Write out the pointers
+ for (int i = 0; i < ptrs.length; i++)
+ os.writeLong(ptrs[i]);
+
+ writeValue(page, new Value(bos.toByteArray()));
+
+ cache.put(new Long(page.getPageNum()), this);
+ }
+
+ public BTreeNode getChildNode(int idx) throws IOException {
+ boolean load;
+ BTreeRootInfo loadNode;
+ long loadPtr;
+ synchronized (this) {
+ if (ph.getStatus() == BRANCH && idx >= 0 && idx < ptrs.length) {
+ load = true;
+ loadNode = root;
+ loadPtr = ptrs[idx];
+ }
+ else {
+ load = false;
+ loadNode = null;
+ loadPtr = 0;
+ }
+ }
+ if (load)
+ return getBTreeNode(loadNode, loadPtr, this);
+ else
+ return null;
+ }
+
+ public synchronized void getChildStream(int idx, Streamable stream) throws IOException {
+ if (ph.getStatus() == LEAF && idx >= 0 && idx < ptrs.length) {
+ Value v = readValue(ptrs[idx]);
+ DataInputStream dis = new DataInputStream(v.getInputStream());
+ stream.read(dis);
+ }
+ }
- case IndexQuery.NEQ:
- default:
- for ( int i = 0; i < ptrs.length; i++ )
- getChildNode(i).query(query, callback);
- break;
- }
- break;
+ public synchronized long removeValue(Value value) throws IOException, BTreeException {
+ int idx = Arrays.binarySearch(values, value);
+ switch (ph.getStatus()) {
+ case BRANCH :
+ idx = idx < 0 ? - (idx + 1) : idx + 1;
+ return getChildNode(idx).removeValue(value);
+
+ case LEAF :
+ if (idx < 0)
+ throw new BTreeNotFoundException("Value '" + value.toString() + "' doesn't exist");
+ else {
+ long oldPtr = ptrs[idx];
+
+ setValues(deleteArrayValue(values, idx));
+ setPointers(deleteArrayLong(ptrs, idx));
+
+ write();
+ return oldPtr;
+ }
- case LEAF:
- switch ( query.getOperator() ) {
- case IndexQuery.EQ:
- if ( leftIdx >= 0 )
- callback.indexInfo(values[leftIdx], ptrs[leftIdx]);
- break;
+ default :
+ throw new BTreeCorruptException("Invalid Page Type In removeValue");
+ }
+ }
- case IndexQuery.NEQ:
- for ( int i = 0; i < ptrs.length; i++ )
- if ( i != leftIdx )
- callback.indexInfo(values[i], ptrs[i]);
- break;
+ public synchronized long addValue(Value value, long pointer) throws IOException, BTreeException {
+ if (value == null) {
+ throw new BTreeException(FaultCodes.DBE_CANNOT_CREATE, "Can't add a null Value");
+ }
- case IndexQuery.BWX:
- case IndexQuery.BW:
- case IndexQuery.SW:
- case IndexQuery.IN:
- if ( leftIdx < 0 )
- leftIdx = -(leftIdx + 1);
- if ( rightIdx < 0 )
- rightIdx = -(rightIdx + 1);
- for ( int i = 0; i < ptrs.length; i++ )
- if ( i >= leftIdx && i <= rightIdx && query.testValue(values[i]) )
- callback.indexInfo(values[i], ptrs[i]);
- break;
+ int idx = Arrays.binarySearch(values, value);
- case IndexQuery.NBWX:
- case IndexQuery.NBW:
- case IndexQuery.NSW:
- if ( leftIdx < 0 )
- leftIdx = -(leftIdx + 1);
- if ( rightIdx < 0 )
- rightIdx = -(rightIdx + 1);
- for ( int i = 0; i < ptrs.length; i++ )
- if ( (i <= leftIdx || i >= rightIdx) && query.testValue(values[i]) )
- callback.indexInfo(values[i], ptrs[i]);
- break;
+ switch (ph.getStatus()) {
+ case BRANCH :
+ idx = idx < 0 ? - (idx + 1) : idx + 1;
+ return getChildNode(idx).addValue(value, pointer);
+
+ case LEAF :
+ if (idx >= 0) {
+ // Value was found... Overwrite
+ long oldPtr = ptrs[idx];
+ ptrs[idx] = pointer;
+
+ setValues(values);
+ setPointers(ptrs);
+
+ write();
+ return oldPtr;
+ }
+ else {
+ // Value was not found
+ idx = - (idx + 1);
+
+ // Check to see if we've exhausted the block
+ boolean split = ph.getDataLen() + 6 + value.getLength() > fileHeader.getWorkSize();
+
+ setValues(insertArrayValue(values, value, idx));
+ setPointers(insertArrayLong(ptrs, pointer, idx));
+
+ if (split)
+ split();
+ else
+ write();
+ }
+ return -1;
- case IndexQuery.LT:
- case IndexQuery.LEQ:
- if ( leftIdx < 0 )
- leftIdx = -(leftIdx + 1);
- for ( int i = 0; i < ptrs.length; i++ )
- if ( i <= leftIdx && query.testValue(values[i]) )
- callback.indexInfo(values[i], ptrs[i]);
- break;
+ default :
+ throw new BTreeCorruptException("Invalid Page Type In addValue");
+ }
+ }
+
+ public synchronized void promoteValue(Value value, long rightPointer) throws IOException, BTreeException {
+ // Check to see if we've exhausted the block
+ boolean split = ph.getDataLen() + 6 + value.getLength() > fileHeader.getWorkSize();
+
+ int idx = Arrays.binarySearch(values, value);
+ idx = idx < 0 ? - (idx + 1) : idx + 1;
+
+ setValues(insertArrayValue(values, value, idx));
+ setPointers(insertArrayLong(ptrs, rightPointer, idx + 1));
+
+ if (split)
+ split();
+ else
+ write();
+ }
+
+ public Value getSeparator(Value value1, Value value2) {
+ int idx = value1.compareTo(value2);
+ byte[] b = new byte[Math.abs(idx)];
+ System.arraycopy(value2.getData(), 0, b, 0, b.length);
+ return new Value(b);
+ }
+
+ public synchronized void split() throws IOException, BTreeException {
+ Value[] leftVals;
+ Value[] rightVals;
+ long[] leftPtrs;
+ long[] rightPtrs;
+ Value separator;
+
+ short vc = ph.getValueCount();
+ int pivot = vc / 2;
+
+ // Split the node into two nodes
+ switch (ph.getStatus()) {
+ case BRANCH :
+ leftVals = new Value[pivot];
+ leftPtrs = new long[leftVals.length + 1];
+ rightVals = new Value[vc - (pivot + 1)];
+ rightPtrs = new long[rightVals.length + 1];
+
+ System.arraycopy(values, 0, leftVals, 0, leftVals.length);
+ System.arraycopy(ptrs, 0, leftPtrs, 0, leftPtrs.length);
+ System.arraycopy(values, leftVals.length + 1, rightVals, 0, rightVals.length);
+ System.arraycopy(ptrs, leftPtrs.length, rightPtrs, 0, rightPtrs.length);
+
+ separator = values[leftVals.length];
+ break;
+
+ case LEAF :
+ leftVals = new Value[pivot];
+ leftPtrs = new long[leftVals.length];
+ rightVals = new Value[vc - pivot];
+ rightPtrs = new long[rightVals.length];
+
+ System.arraycopy(values, 0, leftVals, 0, leftVals.length);
+ System.arraycopy(ptrs, 0, leftPtrs, 0, leftPtrs.length);
+ System.arraycopy(values, leftVals.length, rightVals, 0, rightVals.length);
+ System.arraycopy(ptrs, leftPtrs.length, rightPtrs, 0, rightPtrs.length);
+
+ separator = getSeparator(leftVals[leftVals.length - 1], rightVals[0]);
+ break;
+
+ default :
+ throw new BTreeCorruptException("Invalid Page Type In split");
+ }
+
+ setValues(leftVals);
+ setPointers(leftPtrs);
+
+ // Promote the pivot to the parent branch
+ if (parent == null) {
+ // This can only happen if this is the root
+ BTreeNode np = createBTreeNode(root, BRANCH, null);
+
+ BTreeNode rNode = createBTreeNode(root, ph.getStatus(), np);
+ rNode.setValues(rightVals);
+ rNode.setPointers(rightPtrs);
+
+ np.setValues(new Value[] { separator });
+ np.setPointers(new long[] { page.getPageNum(), rNode.page.getPageNum()});
+
+ parent = np;
+
+ setRootNode(root, np);
+
+ write();
+ rNode.write();
+ np.write();
+ }
+ else {
+ BTreeNode rNode = createBTreeNode(root, ph.getStatus(), parent);
+ rNode.setValues(rightVals);
+ rNode.setPointers(rightPtrs);
+
+ write();
+ rNode.write();
+ parent.promoteValue(separator, rNode.page.getPageNum());
+ }
+ }
- case IndexQuery.GT:
- case IndexQuery.GEQ:
- if ( rightIdx < 0 )
- rightIdx = -(rightIdx + 1);
- for ( int i = 0; i < ptrs.length; i++ )
- if ( i >= rightIdx && query.testValue(values[i]) )
- callback.indexInfo(values[i], ptrs[i]);
+ /////////////////////////////////////////////////////////////////
+
+ public synchronized long findValue(Value value) throws IOException, BTreeException {
+ if (value == null) {
+ throw new BTreeNotFoundException("Can't search on null Value");
+ }
+
+ int idx = Arrays.binarySearch(values, value);
+
+ switch (ph.getStatus()) {
+ case BRANCH :
+ idx = idx < 0 ? - (idx + 1) : idx + 1;
+ return getChildNode(idx).findValue(value);
+
+ case LEAF :
+ if (idx < 0)
+ throw new BTreeNotFoundException("Value '" + value.toString() + "' doesn't exist");
+ else
+ return ptrs[idx];
+
+ default :
+ throw new BTreeCorruptException("Invalid Page Type In findValue");
+ }
+ }
+
+ // query is a BEAST of a method
+ public synchronized void query(IndexQuery query, BTreeCallback callback) throws IOException, BTreeException {
+ if (query != null && query.getOperator() != IndexQuery.ANY) {
+ Value[] qvals = query.getValues();
+ int leftIdx = Arrays.binarySearch(values, qvals[0]);
+ int rightIdx = qvals.length > 1 ? Arrays.binarySearch(values, qvals[qvals.length - 1]) : leftIdx;
+
+ switch (ph.getStatus()) {
+ case BRANCH :
+ leftIdx = leftIdx < 0 ? - (leftIdx + 1) : leftIdx + 1;
+ rightIdx = rightIdx < 0 ? - (rightIdx + 1) : rightIdx + 1;
+
+ switch (query.getOperator()) {
+ case IndexQuery.BWX :
+ case IndexQuery.BW :
+ case IndexQuery.IN :
+ case IndexQuery.SW :
+ for (int i = 0; i < ptrs.length; i++)
+ if (i >= leftIdx && i <= rightIdx)
+ getChildNode(i).query(query, callback);
+ break;
+
+ case IndexQuery.NBWX :
+ case IndexQuery.NBW :
+ case IndexQuery.NIN :
+ case IndexQuery.NSW :
+ for (int i = 0; i < ptrs.length; i++)
+ if (i <= leftIdx || i >= rightIdx)
+ getChildNode(i).query(query, callback);
+ break;
+
+ case IndexQuery.EQ :
+ getChildNode(leftIdx).query(query, callback);
+ break;
+
+ case IndexQuery.LT :
+ case IndexQuery.LEQ :
+ for (int i = 0; i < ptrs.length; i++)
+ if (i <= leftIdx)
+ getChildNode(i).query(query, callback);
+ break;
+
+ case IndexQuery.GT :
+ case IndexQuery.GEQ :
+ for (int i = 0; i < ptrs.length; i++)
+ if (i >= rightIdx)
+ getChildNode(i).query(query, callback);
+ break;
+
+ case IndexQuery.NEQ :
+ default :
+ for (int i = 0; i < ptrs.length; i++)
+ getChildNode(i).query(query, callback);
+ break;
+ }
+ break;
+
+ case LEAF :
+ switch (query.getOperator()) {
+ case IndexQuery.EQ :
+ if (leftIdx >= 0)
+ callback.indexInfo(values[leftIdx], ptrs[leftIdx]);
+ break;
+
+ case IndexQuery.NEQ :
+ for (int i = 0; i < ptrs.length; i++)
+ if (i != leftIdx)
+ callback.indexInfo(values[i], ptrs[i]);
+ break;
+
+ case IndexQuery.BWX :
+ case IndexQuery.BW :
+ case IndexQuery.SW :
+ case IndexQuery.IN :
+ if (leftIdx < 0)
+ leftIdx = - (leftIdx + 1);
+ if (rightIdx < 0)
+ rightIdx = - (rightIdx + 1);
+ for (int i = 0; i < ptrs.length; i++)
+ if (i >= leftIdx && i <= rightIdx && query.testValue(values[i]))
+ callback.indexInfo(values[i], ptrs[i]);
+ break;
+
+ case IndexQuery.NBWX :
+ case IndexQuery.NBW :
+ case IndexQuery.NSW :
+ if (leftIdx < 0)
+ leftIdx = - (leftIdx + 1);
+ if (rightIdx < 0)
+ rightIdx = - (rightIdx + 1);
+ for (int i = 0; i < ptrs.length; i++)
+ if ((i <= leftIdx || i >= rightIdx) && query.testValue(values[i]))
+ callback.indexInfo(values[i], ptrs[i]);
+ break;
+
+ case IndexQuery.LT :
+ case IndexQuery.LEQ :
+ if (leftIdx < 0)
+ leftIdx = - (leftIdx + 1);
+ for (int i = 0; i < ptrs.length; i++)
+ if (i <= leftIdx && query.testValue(values[i]))
+ callback.indexInfo(values[i], ptrs[i]);
+ break;
+
+ case IndexQuery.GT :
+ case IndexQuery.GEQ :
+ if (rightIdx < 0)
+ rightIdx = - (rightIdx + 1);
+ for (int i = 0; i < ptrs.length; i++)
+ if (i >= rightIdx && query.testValue(values[i]))
+ callback.indexInfo(values[i], ptrs[i]);
+ break;
+
+ case IndexQuery.NIN :
+ default :
+ for (int i = 0; i < ptrs.length; i++)
+ if (query.testValue(values[i]))
+ callback.indexInfo(values[i], ptrs[i]);
+ break;
+ }
+ break;
+
+ default :
+ throw new BTreeCorruptException("Invalid Page Type In query");
+ }
+
+ }
+ else {
+ // No Query - Just Walk The Tree
+ switch (ph.getStatus()) {
+ case BRANCH :
+ for (int i = 0; i < ptrs.length; i++)
+ getChildNode(i).query(query, callback);
break;
- case IndexQuery.NIN:
- default:
- for ( int i = 0; i < ptrs.length; i++ )
- if ( query.testValue(values[i]) )
- callback.indexInfo(values[i], ptrs[i]);
+ case LEAF :
+ for (int i = 0; i < values.length; i++)
+ callback.indexInfo(values[i], ptrs[i]);
break;
- }
- break;
- default:
- throw new BTreeCorruptException("Invalid Page Type In query");
+ default :
+ throw new BTreeCorruptException("Invalid Page Type In query");
+ }
}
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////
+
+ public FileHeader createFileHeader() {
+ return new BTreeFileHeader();
+ }
+
+ public FileHeader createFileHeader(boolean read) throws IOException {
+ return new BTreeFileHeader(read);
+ }
+
+ public FileHeader createFileHeader(long pageCount) {
+ return new BTreeFileHeader(pageCount);
+ }
+
+ public FileHeader createFileHeader(long pageCount, int pageSize) {
+ return new BTreeFileHeader(pageCount, pageSize);
+ }
+
+ public PageHeader createPageHeader() {
+ return new BTreePageHeader();
+ }
+
+ /**
+ * BTreeFileHeader
+ */
+
+ protected class BTreeFileHeader extends FileHeader {
+ private long rootPage = 0;
- }
- else {
- // No Query - Just Walk The Tree
- switch ( ph.getStatus() ) {
- case BRANCH:
- for ( int i = 0; i < ptrs.length; i++ )
- getChildNode(i).query(query, callback);
- break;
-
- case LEAF:
- for ( int i = 0; i < values.length; i++ )
- callback.indexInfo(values[i], ptrs[i]);
- break;
-
- default:
- throw new BTreeCorruptException("Invalid Page Type In query");
- }
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////////
-
- public FileHeader createFileHeader() {
- return new BTreeFileHeader();
- }
-
- public FileHeader createFileHeader(boolean read) throws IOException {
- return new BTreeFileHeader(read);
- }
-
- public FileHeader createFileHeader(long pageCount) {
- return new BTreeFileHeader(pageCount);
- }
-
- public FileHeader createFileHeader(long pageCount, int pageSize) {
- return new BTreeFileHeader(pageCount, pageSize);
- }
-
- public PageHeader createPageHeader() {
- return new BTreePageHeader();
- }
-
-
- /**
- * BTreeFileHeader
- */
-
- protected class BTreeFileHeader extends FileHeader {
- private long rootPage = 0;
-
- public BTreeFileHeader() {
- }
-
- public BTreeFileHeader(long pageCount) {
- super(pageCount);
- }
-
- public BTreeFileHeader(long pageCount, int pageSize) {
- super(pageCount, pageSize);
- }
-
- public BTreeFileHeader(boolean read) throws IOException {
- super(read);
- }
-
- public synchronized void read(RandomAccessFile raf) throws IOException {
- super.read(raf);
- rootPage = raf.readLong();
- }
-
- public synchronized void write(RandomAccessFile raf) throws IOException {
- super.write(raf);
- raf.writeLong(rootPage);
- }
-
- /** The root page of the storage tree */
- public synchronized final void setRootPage(long rootPage) {
- this.rootPage = rootPage;
- setDirty();
- }
-
- /** The root page of the storage tree */
- public synchronized final long getRootPage() {
- return rootPage;
- }
- }
-
-
- /**
- * BTreePageHeader
- */
-
- protected class BTreePageHeader extends PageHeader {
- private short valueCount = 0;
-
- public BTreePageHeader() {
- }
-
- public BTreePageHeader(DataInputStream dis) throws IOException {
- super(dis);
- }
-
- public synchronized void read(DataInputStream dis) throws IOException {
- super.read(dis);
-
- if ( getStatus() == UNUSED )
- return;
-
- valueCount = dis.readShort();
- }
-
- public synchronized void write(DataOutputStream dos) throws IOException {
- super.write(dos);
- dos.writeShort(valueCount);
- }
-
- /** The number of values stored by this page */
- public synchronized final void setValueCount(short valueCount) {
- this.valueCount = valueCount;
- setDirty();
- }
-
- /** The number of values stored by this page */
- public synchronized final short getValueCount() {
- return valueCount;
- }
-
- /** The number of pointers stored by this page */
- public synchronized final short getPointerCount() {
- if ( getStatus() == BRANCH )
- return (short)(valueCount + 1);
- else
+ public BTreeFileHeader() {}
+
+ public BTreeFileHeader(long pageCount) {
+ super(pageCount);
+ }
+
+ public BTreeFileHeader(long pageCount, int pageSize) {
+ super(pageCount, pageSize);
+ }
+
+ public BTreeFileHeader(boolean read) throws IOException {
+ super(read);
+ }
+
+ public synchronized void read(RandomAccessFile raf) throws IOException {
+ super.read(raf);
+ rootPage = raf.readLong();
+ }
+
+ public synchronized void write(RandomAccessFile raf) throws IOException {
+ super.write(raf);
+ raf.writeLong(rootPage);
+ }
+
+ /** The root page of the storage tree */
+ public synchronized final void setRootPage(long rootPage) {
+ this.rootPage = rootPage;
+ setDirty();
+ }
+
+ /** The root page of the storage tree */
+ public synchronized final long getRootPage() {
+ return rootPage;
+ }
+ }
+
+ /**
+ * BTreePageHeader
+ */
+
+ protected class BTreePageHeader extends PageHeader {
+ private short valueCount = 0;
+
+ public BTreePageHeader() {}
+
+ public BTreePageHeader(DataInputStream dis) throws IOException {
+ super(dis);
+ }
+
+ public synchronized void read(DataInputStream dis) throws IOException {
+ super.read(dis);
+
+ if (getStatus() == UNUSED)
+ return;
+
+ valueCount = dis.readShort();
+ }
+
+ public synchronized void write(DataOutputStream dos) throws IOException {
+ super.write(dos);
+ dos.writeShort(valueCount);
+ }
+
+ /** The number of values stored by this page */
+ public synchronized final void setValueCount(short valueCount) {
+ this.valueCount = valueCount;
+ setDirty();
+ }
+
+ /** The number of values stored by this page */
+ public synchronized final short getValueCount() {
return valueCount;
- }
- }
+ }
+
+ /** The number of pointers stored by this page */
+ public synchronized final short getPointerCount() {
+ if (getStatus() == BRANCH)
+ return (short) (valueCount + 1);
+ else
+ return valueCount;
+ }
+ }
}
1.11 +431 -450 xml-xindice/java/src/org/apache/xindice/core/filer/HashFiler.java
Index: HashFiler.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/filer/HashFiler.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- HashFiler.java 6 Apr 2003 05:56:03 -0000 1.10
+++ HashFiler.java 15 Jul 2003 15:44:35 -0000 1.11
@@ -59,18 +59,6 @@
* $Id$
*/
-import org.apache.xindice.core.DBException;
-import org.apache.xindice.core.FaultCodes;
-import org.apache.xindice.core.data.Key;
-import org.apache.xindice.core.data.Record;
-import org.apache.xindice.core.data.RecordSet;
-import org.apache.xindice.core.data.Value;
-import org.apache.xindice.util.Configurable;
-import org.apache.xindice.util.Configuration;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
@@ -81,6 +69,17 @@
import java.util.Iterator;
import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.xindice.core.DBException;
+import org.apache.xindice.core.FaultCodes;
+import org.apache.xindice.core.data.Key;
+import org.apache.xindice.core.data.Record;
+import org.apache.xindice.core.data.RecordSet;
+import org.apache.xindice.core.data.Value;
+import org.apache.xindice.util.Configurable;
+import org.apache.xindice.util.Configuration;
+
/**
* HashFiler is a Filer implementation based on the Paged class. By
* extending Paged, HashFiler inherits the ability to maintain Record
@@ -93,465 +92,447 @@
**/
public final class HashFiler extends Paged implements Configurable, Filer {
- protected static final byte RECORD = 1;
+ protected static final byte RECORD = 1;
+
+ private static final String PAGECOUNT = "pagecount";
+ private static final String PAGESIZE = "pagesize";
+ private static final String MAXKEYSIZE = "maxkeysize";
+
+ private static Log log = LogFactory.getLog("org.apache.xindice.core");
+
+ private Configuration config;
+ private HashFileHeader fileHeader;
+ //private BTree btree;
+
+ public HashFiler() {
+ super();
+ fileHeader = (HashFileHeader) getFileHeader();
+ }
+
+ public void setConfig(Configuration config) {
+ this.config = config;
+ }
+
+ public Configuration getConfig() {
+ return config;
+ }
+
+ public void setLocation(File root, String location) {
+ setFile(new File(root, location + ".tbl"));
+ // btree = new BTree(new File(root, location + ".pkx"));
+ }
+
+ public String getName() {
+ return "HashFiler";
+ }
+
+ public boolean open() throws DBException {
+ if (super.open()) {
+ // These are the only properties that can be changed after creation
+ fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
+ // btree.open();
+ return true;
+ }
+ else
+ return false;
+ }
+
+ public boolean create() throws DBException {
+ fileHeader.setPageCount(config.getLongAttribute(PAGECOUNT, fileHeader.getPageCount()));
+ fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
+ fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
+ //btree.create();
+ return super.create();
+ }
+
+ private Page seekRecordPage(Key key) throws IOException {
+ int hash = key.getHash();
+ long pageNum = hash % fileHeader.getPageCount();
+ Page p = null;
+ HashPageHeader ph = null;
+ while (true) {
+ p = getPage(pageNum);
+ ph = (HashPageHeader) p.getPageHeader();
+ if (ph.getStatus() == RECORD && ph.getKeyHash() == key.getHash() && p.getKey().equals(key)) {
+ return p;
+ }
- private static final String PAGECOUNT = "pagecount";
- private static final String PAGESIZE = "pagesize";
- private static final String MAXKEYSIZE = "maxkeysize";
-
- private static Log log = LogFactory.getLog("org.apache.xindice.core");
-
- private Configuration config;
- private HashFileHeader fileHeader;
- //private BTree btree;
-
- public HashFiler() {
- super();
- fileHeader = (HashFileHeader)getFileHeader();
- }
-
- public void setConfig(Configuration config) {
- this.config = config;
- }
-
- public Configuration getConfig() {
- return config;
- }
-
- public void setLocation(File root, String location) {
- setFile(new File(root, location + ".tbl"));
- // btree = new BTree(new File(root, location + ".pkx"));
- }
-
- public String getName() {
- return "HashFiler";
- }
-
- public boolean open() throws DBException {
- if ( super.open() ) {
- // These are the only properties that can be changed after creation
- fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
- // btree.open();
- return true;
- }
- else
- return false;
- }
-
- public boolean create() throws DBException {
- fileHeader.setPageCount(config.getLongAttribute(PAGECOUNT, fileHeader.getPageCount()));
- fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
- fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
- //btree.create();
- return super.create();
- }
-
- private Page seekRecordPage(Key key) throws IOException {
- int hash = key.getHash();
- long pageNum = hash % fileHeader.getPageCount();
- Page p = null;
- HashPageHeader ph = null;
- while ( true ) {
- p = getPage(pageNum);
- ph = (HashPageHeader)p.getPageHeader();
- if ( ph.getStatus() == RECORD
- && ph.getKeyHash() == key.getHash()
- && p.getKey().equals(key) ) {
- return p;
- }
+ pageNum = ph.getNextCollision();
+ if (pageNum == -1)
+ return null;
+ }
+ }
+
+ private Page seekInsertionPage(Key key) throws IOException {
+ int hash = key.getHash();
+ long pageNum = hash % fileHeader.getPageCount();
+
+ log.trace("Hash page " + pageNum);
+
+ Page p = null;
+ HashPageHeader ph = null;
+ while (true) {
+ p = getPage(pageNum);
+ ph = (HashPageHeader) p.getPageHeader();
+ if ((ph.getStatus() == UNUSED || ph.getStatus() == DELETED) || (ph.getStatus() == RECORD && ph.getKeyHash() == key.getHash() && p.getKey().equals(key)))
+ return p;
+ pageNum = ph.getNextCollision();
+ if (pageNum == -1) {
+ Page np = getFreePage();
+ ph.setNextCollision(np.getPageNum());
+ p.write();
+ return np;
+ }
+ }
+ }
- pageNum = ph.getNextCollision();
- if ( pageNum == -1 )
+ public Record readRecord(Key key) throws DBException {
+ if (key == null || key.equals("")) {
return null;
- }
- }
+ }
+ checkOpened();
+ try {
+ Page startPage = seekRecordPage(key);
+ if (startPage != null) {
+ Value v = readValue(startPage);
+ HashPageHeader sph = (HashPageHeader) startPage.getPageHeader();
+
+ HashMap meta = new HashMap(2);
+ meta.put(Record.CREATED, new Long(sph.getCreated()));
+ meta.put(Record.MODIFIED, new Long(sph.getModified()));
- private Page seekInsertionPage(Key key) throws IOException {
- int hash = key.getHash();
- long pageNum = hash % fileHeader.getPageCount();
-
- log.trace("Hash page " + pageNum);
-
- Page p = null;
- HashPageHeader ph = null;
- while ( true ) {
- p = getPage(pageNum);
- ph = (HashPageHeader)p.getPageHeader();
- if ( (ph.getStatus() == UNUSED || ph.getStatus() == DELETED)
- || (ph.getStatus() == RECORD
- && ph.getKeyHash() == key.getHash()
- && p.getKey().equals(key)) )
- return p;
- pageNum = ph.getNextCollision();
- if ( pageNum == -1 ) {
- Page np = getFreePage();
- ph.setNextCollision(np.getPageNum());
- p.write();
- return np;
- }
- }
- }
-
- public Record readRecord(Key key) throws DBException {
- if ( key == null || key.equals("") ) {
- return null;
- }
- checkOpened();
- try {
- Page startPage = seekRecordPage(key);
- if ( startPage != null ) {
- Value v = readValue(startPage);
- HashPageHeader sph = (HashPageHeader)startPage.getPageHeader();
-
- HashMap meta = new HashMap(2);
- meta.put(Record.CREATED, new Long(sph.getCreated()));
- meta.put(Record.MODIFIED, new Long(sph.getModified()));
-
- return new Record(key, v, meta);
- }
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- return null;
- }
-
- public boolean writeRecord(Key key, Value value) throws DBException {
- if ( key == null || key.equals("") ) {
- throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid key: '" + key + "'");
- }
- if (value == null ) {
- throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid null value");
- }
- checkOpened();
- try {
- Page p = seekInsertionPage(key);
- HashPageHeader ph = (HashPageHeader)p.getPageHeader();
+ return new Record(key, v, meta);
+ }
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ return null;
+ }
+
+ public boolean writeRecord(Key key, Value value) throws DBException {
+ if (key == null || key.equals("")) {
+ throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid key: '" + key + "'");
+ }
+ if (value == null) {
+ throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid null value");
+ }
+ checkOpened();
+ try {
+ Page p = seekInsertionPage(key);
+ HashPageHeader ph = (HashPageHeader) p.getPageHeader();
- long t = System.currentTimeMillis();
+ long t = System.currentTimeMillis();
- // if ( ph.getStatus() == UNUSED ) {
+ // if ( ph.getStatus() == UNUSED ) {
// This is a new Record
fileHeader.incRecordCount();
- // btree.addValue(key, p.getPageNum());
+ // btree.addValue(key, p.getPageNum());
ph.setCreated(t);
- // }
+ // }
- ph.setModified(t);
- ph.setStatus(RECORD);
+ ph.setModified(t);
+ ph.setStatus(RECORD);
- p.setKey(key);
- writeValue(p, value);
+ p.setKey(key);
+ writeValue(p, value);
- flush();
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- return true;
- }
-
- public boolean deleteRecord(Key key) throws DBException {
- if ( key == null || key.equals("") ) {
- return false;
- }
- checkOpened();
- try {
- int hash = key.getHash();
- long pageNum = hash % fileHeader.getPageCount();
- Page prev = null;
- Page page = null;
-
- HashPageHeader prevHead = null;
- HashPageHeader pageHead = null;
-
- while ( true ) {
- page = getPage(pageNum);
- pageHead = (HashPageHeader)page.getPageHeader();
- if ( pageHead.getStatus() == RECORD
- && pageHead.getKeyHash() == key.getHash()
- && page.getKey().equals(key) )
- break;
- pageNum = pageHead.getNextCollision();
- if ( pageNum == -1 )
- return false;
- prev = page;
- prevHead = pageHead;
- }
+ flush();
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ return true;
+ }
- if ( page == null )
+ public boolean deleteRecord(Key key) throws DBException {
+ if (key == null || key.equals("")) {
return false;
+ }
+ checkOpened();
+ try {
+ int hash = key.getHash();
+ long pageNum = hash % fileHeader.getPageCount();
+ Page prev = null;
+ Page page = null;
+
+ HashPageHeader prevHead = null;
+ HashPageHeader pageHead = null;
+
+ while (true) {
+ page = getPage(pageNum);
+ pageHead = (HashPageHeader) page.getPageHeader();
+ if (pageHead.getStatus() == RECORD && pageHead.getKeyHash() == key.getHash() && page.getKey().equals(key))
+ break;
+ pageNum = pageHead.getNextCollision();
+ if (pageNum == -1)
+ return false;
+ prev = page;
+ prevHead = pageHead;
+ }
- if ( prev != null ) {
- prevHead.setNextCollision(pageHead.nextCollision);
- prev.write();
- }
-
- //btree.removeValue(key);
- unlinkPages(page);
-
- fileHeader.decRecordCount();
-
- flush();
-
- return true;
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- return false;
- }
-
- public long getRecordCount() throws DBException {
- checkOpened();
- return fileHeader.getRecordCount();
- }
-
- public RecordSet getRecordSet() throws DBException {
- checkOpened();
- return new HashFilerRecordSet();
- }
-
- public void flush() throws DBException {
- super.flush();
- }
-
- /**
- * HashFilerRecordSet that does not use a BTree.
- */
- private class HashFilerRecordSet implements RecordSet {
- private List keys = new ArrayList();
- private Iterator enum;
-
- public HashFilerRecordSet() {
- try {
- Page p = null;
- HashPageHeader ph = null;
- long pageNum = 0;
-
- while ( pageNum < fileHeader.getTotalCount() ) {
- p = getPage(pageNum);
- ph = (HashPageHeader)p.getPageHeader();
- if ( ph.getStatus() == RECORD ) {
- keys.add(p.getKey());
- }
+ if (page == null)
+ return false;
- pageNum++;
+ if (prev != null) {
+ prevHead.setNextCollision(pageHead.nextCollision);
+ prev.write();
}
- enum = keys.iterator();
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
+ //btree.removeValue(key);
+ unlinkPages(page);
+
+ fileHeader.decRecordCount();
- public synchronized Key getNextKey() {
- return (Key)enum.next();
- }
-
- public synchronized Record getNextRecord() throws DBException {
- return readRecord((Key)enum.next());
- }
-
- public synchronized Value getNextValue() throws DBException {
- return getNextRecord().getValue();
- }
-
- public synchronized boolean hasMoreRecords() {
- return enum.hasNext();
- }
- }
-
- /**
- * HashFilerRecordSet
- */
-/* private class HashFilerRecordSet implements RecordSet, BTreeCallback {
- private List keys = new ArrayList();
- private Iterator enum;
-
- public HashFilerRecordSet() {
- try {
- btree.query(null, this);
- enum = keys.iterator();
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
+ flush();
+
+ return true;
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ return false;
+ }
+
+ public long getRecordCount() throws DBException {
+ checkOpened();
+ return fileHeader.getRecordCount();
+ }
+
+ public RecordSet getRecordSet() throws DBException {
+ checkOpened();
+ return new HashFilerRecordSet();
+ }
+
+ public void flush() throws DBException {
+ super.flush();
+ }
+
+ /**
+ * HashFilerRecordSet that does not use a BTree.
+ */
+ private class HashFilerRecordSet implements RecordSet {
+ private List keys = new ArrayList();
+ private Iterator enum;
+
+ public HashFilerRecordSet() {
+ try {
+ Page p = null;
+ HashPageHeader ph = null;
+ long pageNum = 0;
+
+ while (pageNum < fileHeader.getTotalCount()) {
+ p = getPage(pageNum);
+ ph = (HashPageHeader) p.getPageHeader();
+ if (ph.getStatus() == RECORD) {
+ keys.add(p.getKey());
+ }
+
+ pageNum++;
+ }
+
+ enum = keys.iterator();
+ }
+ catch (Exception e) {
+ log.warn(e);
}
- }
- }
+ }
- public synchronized boolean indexInfo(Value value, long pointer) {
- keys.add(new Key(value));
- return true;
- }
-
- public synchronized Key getNextKey() {
- return (Key)enum.next();
- }
-
- public synchronized Record getNextRecord() throws DBException {
- return readRecord((Key)enum.next());
- }
-
- public synchronized Value getNextValue() throws DBException {
- return getNextRecord().getValue();
- }
-
- public synchronized boolean hasMoreRecords() {
- return enum.hasNext();
- }
- }*/
-
- ////////////////////////////////////////////////////////////////////
-
- public FileHeader createFileHeader() {
- return new HashFileHeader();
- }
-
- public FileHeader createFileHeader(boolean read) throws IOException {
- return new HashFileHeader(read);
- }
-
- public FileHeader createFileHeader(long pageCount) {
- return new HashFileHeader(pageCount);
- }
-
- public FileHeader createFileHeader(long pageCount, int pageSize) {
- return new HashFileHeader(pageCount, pageSize);
- }
-
- public PageHeader createPageHeader() {
- return new HashPageHeader();
- }
-
-
- /**
- * HashFileHeader
- */
-
- private final class HashFileHeader extends FileHeader {
- private long totalBytes = 0;
-
- public HashFileHeader() {
- }
-
- public HashFileHeader(long pageCount) {
- super(pageCount);
- }
-
- public HashFileHeader(long pageCount, int pageSize) {
- super(pageCount, pageSize);
- }
-
- public HashFileHeader(boolean read) throws IOException {
- super(read);
- }
-
- public synchronized void read(RandomAccessFile raf) throws IOException {
- super.read(raf);
- totalBytes = raf.readLong();
- }
-
- public synchronized void write(RandomAccessFile raf) throws IOException {
- super.write(raf);
- raf.writeLong(totalBytes);
- }
-
- /** The total number of bytes in use by the file */
- public synchronized void setTotalBytes(long totalBytes) {
- this.totalBytes = totalBytes;
- setDirty();
- }
-
- /** The total number of bytes in use by the file */
- public synchronized long getTotalBytes() {
- return totalBytes;
- }
- }
-
- /**
- * HashPageHeader
- */
-
- private final class HashPageHeader extends PageHeader {
- private long created = 0;
- private long modified = 0;
- private long nextCollision = -1;
-
- public HashPageHeader() {
- }
-
- public HashPageHeader(DataInputStream dis) throws IOException {
- super(dis);
- }
-
- public synchronized void read(DataInputStream dis) throws IOException {
- super.read(dis);
-
- if ( getStatus() == UNUSED )
- return;
-
- created = dis.readLong();
- modified = dis.readLong();
- nextCollision = dis.readLong();
- }
-
- public synchronized void write(DataOutputStream dos) throws IOException {
- super.write(dos);
- dos.writeLong(created);
- dos.writeLong(modified);
- dos.writeLong(nextCollision);
- }
-
- public synchronized void setRecordLen(int recordLen) {
- fileHeader.setTotalBytes((fileHeader.totalBytes - getRecordLen()) + recordLen);
- super.setRecordLen(recordLen);
- }
-
- /** UNIX-time when this record was created */
- public synchronized void setCreated(long created) {
- this.created = created;
- setDirty();
- }
-
- /** UNIX-time when this record was created */
- public synchronized long getCreated() {
- return created;
- }
-
- /** UNIX-time when this record was last modified */
- public synchronized void setModified(long modified) {
- this.modified = modified;
- setDirty();
- }
-
- /** UNIX-time when this record was last modified */
- public synchronized long getModified() {
- return modified;
- }
-
- /** The next page for a Record collision (if any) */
- public synchronized void setNextCollision(long nextCollision) {
- this.nextCollision = nextCollision;
- setDirty();
- }
-
- /** The next page for a Record collision (if any) */
- public synchronized long getNextCollision() {
- return nextCollision;
- }
- }
+ public synchronized Key getNextKey() {
+ return (Key) enum.next();
+ }
+
+ public synchronized Record getNextRecord() throws DBException {
+ return readRecord((Key) enum.next());
+ }
+
+ public synchronized Value getNextValue() throws DBException {
+ return getNextRecord().getValue();
+ }
+
+ public synchronized boolean hasMoreRecords() {
+ return enum.hasNext();
+ }
+ }
+
+ /**
+ * HashFilerRecordSet
+ */
+ /* private class HashFilerRecordSet implements RecordSet, BTreeCallback {
+ private List keys = new ArrayList();
+ private Iterator enum;
+
+ public HashFilerRecordSet() {
+ try {
+ btree.query(null, this);
+ enum = keys.iterator();
+ }
+ catch ( Exception e ) {
+ if (log.isDebugEnabled()) {
+ log.debug("No message", e);
+ }
+ }
+ }
+
+ public synchronized boolean indexInfo(Value value, long pointer) {
+ keys.add(new Key(value));
+ return true;
+ }
+
+ public synchronized Key getNextKey() {
+ return (Key)enum.next();
+ }
+
+ public synchronized Record getNextRecord() throws DBException {
+ return readRecord((Key)enum.next());
+ }
+
+ public synchronized Value getNextValue() throws DBException {
+ return getNextRecord().getValue();
+ }
+
+ public synchronized boolean hasMoreRecords() {
+ return enum.hasNext();
+ }
+ }*/
+
+ ////////////////////////////////////////////////////////////////////
+
+ public FileHeader createFileHeader() {
+ return new HashFileHeader();
+ }
+
+ public FileHeader createFileHeader(boolean read) throws IOException {
+ return new HashFileHeader(read);
+ }
+
+ public FileHeader createFileHeader(long pageCount) {
+ return new HashFileHeader(pageCount);
+ }
+
+ public FileHeader createFileHeader(long pageCount, int pageSize) {
+ return new HashFileHeader(pageCount, pageSize);
+ }
+
+ public PageHeader createPageHeader() {
+ return new HashPageHeader();
+ }
+
+ /**
+ * HashFileHeader
+ */
+
+ private final class HashFileHeader extends FileHeader {
+ private long totalBytes = 0;
+
+ public HashFileHeader() {}
+
+ public HashFileHeader(long pageCount) {
+ super(pageCount);
+ }
+
+ public HashFileHeader(long pageCount, int pageSize) {
+ super(pageCount, pageSize);
+ }
+
+ public HashFileHeader(boolean read) throws IOException {
+ super(read);
+ }
+
+ public synchronized void read(RandomAccessFile raf) throws IOException {
+ super.read(raf);
+ totalBytes = raf.readLong();
+ }
+
+ public synchronized void write(RandomAccessFile raf) throws IOException {
+ super.write(raf);
+ raf.writeLong(totalBytes);
+ }
+
+ /** The total number of bytes in use by the file */
+ public synchronized void setTotalBytes(long totalBytes) {
+ this.totalBytes = totalBytes;
+ setDirty();
+ }
+
+ /** The total number of bytes in use by the file */
+ public synchronized long getTotalBytes() {
+ return totalBytes;
+ }
+ }
+
+ /**
+ * HashPageHeader
+ */
+
+ private final class HashPageHeader extends PageHeader {
+ private long created = 0;
+ private long modified = 0;
+ private long nextCollision = -1;
+
+ public HashPageHeader() {}
+
+ public HashPageHeader(DataInputStream dis) throws IOException {
+ super(dis);
+ }
+
+ public synchronized void read(DataInputStream dis) throws IOException {
+ super.read(dis);
+
+ if (getStatus() == UNUSED)
+ return;
+
+ created = dis.readLong();
+ modified = dis.readLong();
+ nextCollision = dis.readLong();
+ }
+
+ public synchronized void write(DataOutputStream dos) throws IOException {
+ super.write(dos);
+ dos.writeLong(created);
+ dos.writeLong(modified);
+ dos.writeLong(nextCollision);
+ }
+
+ public synchronized void setRecordLen(int recordLen) {
+ fileHeader.setTotalBytes((fileHeader.totalBytes - getRecordLen()) + recordLen);
+ super.setRecordLen(recordLen);
+ }
+
+ /** UNIX-time when this record was created */
+ public synchronized void setCreated(long created) {
+ this.created = created;
+ setDirty();
+ }
+
+ /** UNIX-time when this record was created */
+ public synchronized long getCreated() {
+ return created;
+ }
+
+ /** UNIX-time when this record was last modified */
+ public synchronized void setModified(long modified) {
+ this.modified = modified;
+ setDirty();
+ }
+
+ /** UNIX-time when this record was last modified */
+ public synchronized long getModified() {
+ return modified;
+ }
+
+ /** The next page for a Record collision (if any) */
+ public synchronized void setNextCollision(long nextCollision) {
+ this.nextCollision = nextCollision;
+ setDirty();
+ }
+
+ /** The next page for a Record collision (if any) */
+ public synchronized long getNextCollision() {
+ return nextCollision;
+ }
+ }
}
1.9 +330 -344 xml-xindice/java/src/org/apache/xindice/core/filer/BTreeFiler.java
Index: BTreeFiler.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/filer/BTreeFiler.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- BTreeFiler.java 19 Nov 2002 05:16:58 -0000 1.8
+++ BTreeFiler.java 15 Jul 2003 15:44:35 -0000 1.9
@@ -59,18 +59,6 @@
* $Id$
*/
-import org.apache.xindice.core.DBException;
-import org.apache.xindice.core.FaultCodes;
-import org.apache.xindice.core.data.Key;
-import org.apache.xindice.core.data.Record;
-import org.apache.xindice.core.data.RecordSet;
-import org.apache.xindice.core.data.Value;
-import org.apache.xindice.util.Configurable;
-import org.apache.xindice.util.Configuration;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
@@ -81,346 +69,344 @@
import java.util.Iterator;
import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.xindice.core.DBException;
+import org.apache.xindice.core.FaultCodes;
+import org.apache.xindice.core.data.Key;
+import org.apache.xindice.core.data.Record;
+import org.apache.xindice.core.data.RecordSet;
+import org.apache.xindice.core.data.Value;
+import org.apache.xindice.util.Configurable;
+import org.apache.xindice.util.Configuration;
+
/**
* BTreeFiler is a Filer implementation based on the BTree class.
*/
public final class BTreeFiler extends BTree implements Configurable, Filer {
- protected static final byte RECORD = 20;
+ protected static final byte RECORD = 20;
- private static final String PAGESIZE = "pagesize";
- private static final String MAXKEYSIZE = "maxkeysize";
+ private static final String PAGESIZE = "pagesize";
+ private static final String MAXKEYSIZE = "maxkeysize";
- private static Log log = LogFactory.getLog("org.apache.xindice.core");
+ private static Log log = LogFactory.getLog("org.apache.xindice.core");
- private Configuration config;
- private BTreeFilerHeader fileHeader;
-
- public BTreeFiler() {
- super();
- fileHeader = (BTreeFilerHeader)getFileHeader();
- }
-
- public void setConfig(Configuration config) {
- this.config = config;
- }
-
- public Configuration getConfig() {
- return config;
- }
-
- public void setLocation(File root, String location) {
- setFile(new File(root, location + ".tbl"));
- }
-
- public String getName() {
- return "BTreeFiler";
- }
-
- public boolean open() throws DBException {
- if ( super.open() ) {
- // These are the only properties that can be changed after creation
- fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
- return true;
- }
- else
- return false;
- }
-
- public boolean create() throws DBException {
- fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
- fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
- return super.create();
- }
-
- public Record readRecord(Key key) throws DBException {
- if ( key == null || key.equals("") ) {
- return null;
- }
- checkOpened();
- try {
- long pos = findValue(key);
- Page startPage = getPage(pos);
- Value v = readValue(startPage);
- BTreeFilerPageHeader sph = (BTreeFilerPageHeader)startPage.getPageHeader();
-
- HashMap meta = new HashMap(2);
- meta.put(Record.CREATED, new Long(sph.getCreated()));
- meta.put(Record.MODIFIED, new Long(sph.getModified()));
-
- return new Record(key, v, meta);
- }
- catch ( BTreeNotFoundException e ) {
- }
- catch ( BTreeException e ) {
- throw e;
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- return null;
- }
-
- public boolean writeRecord(Key key, Value value) throws DBException {
- if ( key == null || key.equals("") ) {
- throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid key: '" + key + "'");
- }
- if (value == null ) {
- throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid null value");
- }
- checkOpened();
- try {
- Page p;
- try {
+ private Configuration config;
+ private BTreeFilerHeader fileHeader;
+
+ public BTreeFiler() {
+ super();
+ fileHeader = (BTreeFilerHeader) getFileHeader();
+ }
+
+ public void setConfig(Configuration config) {
+ this.config = config;
+ }
+
+ public Configuration getConfig() {
+ return config;
+ }
+
+ public void setLocation(File root, String location) {
+ setFile(new File(root, location + ".tbl"));
+ }
+
+ public String getName() {
+ return "BTreeFiler";
+ }
+
+ public boolean open() throws DBException {
+ if (super.open()) {
+ // These are the only properties that can be changed after creation
+ fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
+ return true;
+ }
+ else
+ return false;
+ }
+
+ public boolean create() throws DBException {
+ fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
+ fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
+ return super.create();
+ }
+
+ public Record readRecord(Key key) throws DBException {
+ if (key == null || key.equals("")) {
+ return null;
+ }
+ checkOpened();
+ try {
long pos = findValue(key);
- p = getPage(pos);
- }
- catch ( BTreeNotFoundException e ) {
- p = getFreePage();
- addValue(key, p.getPageNum());
- fileHeader.incRecordCount();
- }
- BTreeFilerPageHeader ph = (BTreeFilerPageHeader)p.getPageHeader();
-
- long t = System.currentTimeMillis();
- if ( ph.getStatus() == UNUSED )
- ph.setCreated(t);
-
- ph.setModified(t);
- ph.setStatus(RECORD);
-
- writeValue(p, value);
-
- flush();
- }
- catch ( DBException e ) {
- throw e;
- }
- catch ( IOException e ) {
- throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, e.getMessage(), e);
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- return true;
- }
-
- public boolean deleteRecord(Key key) throws DBException {
- if ( key == null || key.equals("") ) {
- return false;
- }
- checkOpened();
- try {
- long pos = findValue(key);
- Page p = getPage(pos);
-
- removeValue(key);
- unlinkPages(p.getPageNum());
-
- fileHeader.decRecordCount();
-
- flush();
-
- return true;
- }
- catch ( BTreeNotFoundException e ) {
- }
- catch ( BTreeException e ) {
- throw e;
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- return false;
- }
-
- public long getRecordCount() throws DBException {
- checkOpened();
- return fileHeader.getRecordCount();
- }
-
- public RecordSet getRecordSet() throws DBException {
- checkOpened();
- return new BTreeFilerRecordSet();
- }
-
- public void flush() throws DBException {
- super.flush();
- }
-
-
- /**
- * BTreeFilerRecordSet
- */
-
- private class BTreeFilerRecordSet implements RecordSet, BTreeCallback {
- private List keys = new ArrayList();
- private Iterator enum;
-
- public BTreeFilerRecordSet() throws DBException {
- try {
- query(null, this);
- enum = keys.iterator();
- }
- catch ( IOException e ) {
- throw new FilerException(FaultCodes.GEN_CRITICAL_ERROR, "Error generating RecordSet", e);
- }
- }
-
- public synchronized boolean indexInfo(Value value, long pointer) {
- keys.add(new Key(value));
- return true;
- }
-
- public synchronized Key getNextKey() {
- return (Key)enum.next();
- }
-
- public synchronized Record getNextRecord() throws DBException {
- return readRecord((Key)enum.next());
- }
-
- public synchronized Value getNextValue() throws DBException {
- return getNextRecord().getValue();
- }
-
- public synchronized boolean hasMoreRecords() {
- return enum.hasNext();
- }
- }
-
- ////////////////////////////////////////////////////////////////////
-
- public FileHeader createFileHeader() {
- return new BTreeFilerHeader();
- }
-
- public FileHeader createFileHeader(boolean read) throws IOException {
- return new BTreeFilerHeader(read);
- }
-
- public FileHeader createFileHeader(long pageCount) {
- return new BTreeFilerHeader(pageCount);
- }
-
- public FileHeader createFileHeader(long pageCount, int pageSize) {
- return new BTreeFilerHeader(pageCount, pageSize);
- }
-
- public PageHeader createPageHeader() {
- return new BTreeFilerPageHeader();
- }
-
-
- /**
- * BTreeFilerHeader
- */
-
- private final class BTreeFilerHeader extends BTreeFileHeader {
- private long totalBytes = 0;
-
- public BTreeFilerHeader() {
- }
-
- public BTreeFilerHeader(long pageCount) {
- super(pageCount);
- }
-
- public BTreeFilerHeader(long pageCount, int pageSize) {
- super(pageCount, pageSize);
- }
-
- public BTreeFilerHeader(boolean read) throws IOException {
- super(read);
- }
-
- public synchronized void read(RandomAccessFile raf) throws IOException {
- super.read(raf);
- totalBytes = raf.readLong();
- }
-
- public synchronized void write(RandomAccessFile raf) throws IOException {
- super.write(raf);
- raf.writeLong(totalBytes);
- }
-
- /** The total number of bytes in use by the file */
- public synchronized void setTotalBytes(long totalBytes) {
- this.totalBytes = totalBytes;
- setDirty();
- }
-
- /** The total number of bytes in use by the file */
- public synchronized long getTotalBytes() {
- return totalBytes;
- }
- }
-
- /**
- * BTreeFilerPageHeader
- */
-
- private final class BTreeFilerPageHeader extends BTreePageHeader {
- private long created = 0;
- private long modified = 0;
-
- public BTreeFilerPageHeader() {
- }
-
- public BTreeFilerPageHeader(DataInputStream dis) throws IOException {
- super(dis);
- }
-
- public synchronized void read(DataInputStream dis) throws IOException {
- super.read(dis);
-
- if ( getStatus() == UNUSED )
- return;
-
- created = dis.readLong();
- modified = dis.readLong();
- }
-
- public synchronized void write(DataOutputStream dos) throws IOException {
- super.write(dos);
- dos.writeLong(created);
- dos.writeLong(modified);
- }
-
- public synchronized void setRecordLen(int recordLen) {
- fileHeader.setTotalBytes((fileHeader.totalBytes - getRecordLen()) + recordLen);
- super.setRecordLen(recordLen);
- }
-
- /** UNIX-time when this record was created */
- public synchronized void setCreated(long created) {
- this.created = created;
- setDirty();
- }
-
- /** UNIX-time when this record was created */
- public synchronized long getCreated() {
- return created;
- }
-
- /** UNIX-time when this record was last modified */
- public synchronized void setModified(long modified) {
- this.modified = modified;
- setDirty();
- }
-
- /** UNIX-time when this record was last modified */
- public synchronized long getModified() {
- return modified;
- }
- }
-}
+ Page startPage = getPage(pos);
+ Value v = readValue(startPage);
+ BTreeFilerPageHeader sph = (BTreeFilerPageHeader) startPage.getPageHeader();
+
+ HashMap meta = new HashMap(2);
+ meta.put(Record.CREATED, new Long(sph.getCreated()));
+ meta.put(Record.MODIFIED, new Long(sph.getModified()));
+
+ return new Record(key, v, meta);
+ }
+ catch (BTreeNotFoundException e) {}
+ catch (BTreeException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ return null;
+ }
+
+ public boolean writeRecord(Key key, Value value) throws DBException {
+ if (key == null || key.equals("")) {
+ throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid key: '" + key + "'");
+ }
+ if (value == null) {
+ throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid null value");
+ }
+ checkOpened();
+ try {
+ Page p;
+ try {
+ long pos = findValue(key);
+ p = getPage(pos);
+ }
+ catch (BTreeNotFoundException e) {
+ p = getFreePage();
+ addValue(key, p.getPageNum());
+ fileHeader.incRecordCount();
+ }
+ BTreeFilerPageHeader ph = (BTreeFilerPageHeader) p.getPageHeader();
+
+ long t = System.currentTimeMillis();
+ if (ph.getStatus() == UNUSED)
+ ph.setCreated(t);
+
+ ph.setModified(t);
+ ph.setStatus(RECORD);
+
+ writeValue(p, value);
+
+ flush();
+ }
+ catch (DBException e) {
+ throw e;
+ }
+ catch (IOException e) {
+ throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, e.getMessage(), e);
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ return true;
+ }
+
+ public boolean deleteRecord(Key key) throws DBException {
+ if (key == null || key.equals("")) {
+ return false;
+ }
+ checkOpened();
+ try {
+ long pos = findValue(key);
+ Page p = getPage(pos);
+
+ removeValue(key);
+ unlinkPages(p.getPageNum());
+ fileHeader.decRecordCount();
+ flush();
+ return true;
+ }
+ catch (BTreeNotFoundException e) {
+ log.warn(e);
+ }
+ catch (BTreeException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ return false;
+ }
+
+ public long getRecordCount() throws DBException {
+ checkOpened();
+ return fileHeader.getRecordCount();
+ }
+
+ public RecordSet getRecordSet() throws DBException {
+ checkOpened();
+ return new BTreeFilerRecordSet();
+ }
+
+ public void flush() throws DBException {
+ super.flush();
+ }
+
+ /**
+ * BTreeFilerRecordSet
+ */
+
+ private class BTreeFilerRecordSet implements RecordSet, BTreeCallback {
+ private List keys = new ArrayList();
+ private Iterator enum;
+
+ public BTreeFilerRecordSet() throws DBException {
+ try {
+ query(null, this);
+ enum = keys.iterator();
+ }
+ catch (IOException e) {
+ throw new FilerException(FaultCodes.GEN_CRITICAL_ERROR, "Error generating RecordSet", e);
+ }
+ }
+
+ public synchronized boolean indexInfo(Value value, long pointer) {
+ keys.add(new Key(value));
+ return true;
+ }
+
+ public synchronized Key getNextKey() {
+ return (Key) enum.next();
+ }
+
+ public synchronized Record getNextRecord() throws DBException {
+ return readRecord((Key) enum.next());
+ }
+
+ public synchronized Value getNextValue() throws DBException {
+ return getNextRecord().getValue();
+ }
+
+ public synchronized boolean hasMoreRecords() {
+ return enum.hasNext();
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////
+
+ public FileHeader createFileHeader() {
+ return new BTreeFilerHeader();
+ }
+
+ public FileHeader createFileHeader(boolean read) throws IOException {
+ return new BTreeFilerHeader(read);
+ }
+
+ public FileHeader createFileHeader(long pageCount) {
+ return new BTreeFilerHeader(pageCount);
+ }
+
+ public FileHeader createFileHeader(long pageCount, int pageSize) {
+ return new BTreeFilerHeader(pageCount, pageSize);
+ }
+
+ public PageHeader createPageHeader() {
+ return new BTreeFilerPageHeader();
+ }
+
+ /**
+ * BTreeFilerHeader
+ */
+
+ private final class BTreeFilerHeader extends BTreeFileHeader {
+ private long totalBytes = 0;
+
+ public BTreeFilerHeader() {}
+
+ public BTreeFilerHeader(long pageCount) {
+ super(pageCount);
+ }
+
+ public BTreeFilerHeader(long pageCount, int pageSize) {
+ super(pageCount, pageSize);
+ }
+
+ public BTreeFilerHeader(boolean read) throws IOException {
+ super(read);
+ }
+
+ public synchronized void read(RandomAccessFile raf) throws IOException {
+ super.read(raf);
+ totalBytes = raf.readLong();
+ }
+
+ public synchronized void write(RandomAccessFile raf) throws IOException {
+ super.write(raf);
+ raf.writeLong(totalBytes);
+ }
+
+ /** The total number of bytes in use by the file */
+ public synchronized void setTotalBytes(long totalBytes) {
+ this.totalBytes = totalBytes;
+ setDirty();
+ }
+
+ /** The total number of bytes in use by the file */
+ public synchronized long getTotalBytes() {
+ return totalBytes;
+ }
+ }
+
+ /**
+ * BTreeFilerPageHeader
+ */
+
+ private final class BTreeFilerPageHeader extends BTreePageHeader {
+ private long created = 0;
+ private long modified = 0;
+
+ public BTreeFilerPageHeader() {}
+
+ public BTreeFilerPageHeader(DataInputStream dis) throws IOException {
+ super(dis);
+ }
+
+ public synchronized void read(DataInputStream dis) throws IOException {
+ super.read(dis);
+
+ if (getStatus() == UNUSED)
+ return;
+
+ created = dis.readLong();
+ modified = dis.readLong();
+ }
+
+ public synchronized void write(DataOutputStream dos) throws IOException {
+ super.write(dos);
+ dos.writeLong(created);
+ dos.writeLong(modified);
+ }
+
+ public synchronized void setRecordLen(int recordLen) {
+ fileHeader.setTotalBytes((fileHeader.totalBytes - getRecordLen()) + recordLen);
+ super.setRecordLen(recordLen);
+ }
+
+ /** UNIX-time when this record was created */
+ public synchronized void setCreated(long created) {
+ this.created = created;
+ setDirty();
+ }
+
+ /** UNIX-time when this record was created */
+ public synchronized long getCreated() {
+ return created;
+ }
+
+ /** UNIX-time when this record was last modified */
+ public synchronized void setModified(long modified) {
+ this.modified = modified;
+ setDirty();
+ }
+
+ /** UNIX-time when this record was last modified */
+ public synchronized long getModified() {
+ return modified;
+ }
+ }
+}
1.8 +119 -121 xml-xindice/java/src/org/apache/xindice/core/xupdate/XUpdateQueryResolver.java
Index: XUpdateQueryResolver.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/xupdate/XUpdateQueryResolver.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- XUpdateQueryResolver.java 17 Jun 2003 02:39:12 -0000 1.7
+++ XUpdateQueryResolver.java 15 Jul 2003 15:44:35 -0000 1.8
@@ -86,124 +86,122 @@
* XUpdateQueryResolver
*/
public class XUpdateQueryResolver extends SimpleConfigurable implements QueryResolver {
- private static final String XUPDATE_XPATH_PROP = "org.xmldb.common.xml.queries.XPathQueryFactory";
- private static final String XUPDATE_XPATH_IMPL = "org.apache.xindice.core.xupdate.XPathQueryFactoryImpl";
- static {
- System.setProperty(XUPDATE_XPATH_PROP, XUPDATE_XPATH_IMPL);
- }
-
- private static Log log = LogFactory.getLog("org.apache.xindice.core");
-
- public static final String STYLE_XUPDATE = "XUpdate";
-
- private QueryEngine engine;
-
- public void setConfig(Configuration config) throws XindiceException {
- super.setConfig(config);
- }
-
- public String getQueryStyle() {
- return STYLE_XUPDATE;
- }
-
- public void setQueryEngine(QueryEngine engine) {
- this.engine = engine;
- }
-
- public Query compileQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
- return new XUpdateQuery(context, query, nsMap, keys);
- }
-
- public NodeSet query(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
- XUpdateQuery xq = new XUpdateQuery(context, query, nsMap, keys);
- return xq.execute();
- }
-
- /**
- * XUpdateQuery
- */
-
- private class XUpdateQuery implements Query {
- public Collection context;
- public String query;
- public NamespaceMap nsMap;
- public XUpdateImpl xu;
- public Key[] keys;
-
- public XUpdateQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
- this.context = context;
- this.query = query;
- this.nsMap = nsMap;
- this.keys = keys;
-
- try {
- xu = new XUpdateImpl();
- xu.setQString(query);
- xu.setNamespaceMap(nsMap);
- }
- catch (Exception e) {
- if (e instanceof QueryException) {
- throw (QueryException) e.fillInStackTrace();
- }
- throw new CompilationException("Error Compiling XUpdate Query", e);
- }
- }
-
- public String getQueryStyle() {
- return STYLE_XUPDATE;
- }
-
- public Collection getQueryContext() {
- return context;
- }
-
- public String getQueryString() {
- return query;
- }
-
- public NamespaceMap getNamespaceMap() {
- return nsMap;
- }
-
- public Key[] getKeySet() {
- return keys;
- }
-
- public NodeSet execute() throws QueryException {
- try {
- if (keys != null) {
- try {
- for (int i = 0; i < keys.length; i++) {
- Document doc = context.getDocument(keys[i]);
- xu.execute(doc.getDocumentElement());
- context.setDocument(keys[i], doc);
- }
- }
- catch (Exception e) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
- else {
- xu.execute(context);
- }
-
- DocumentImpl doc = new DocumentImpl();
- Element elem = doc.createElementNS(NodeSource.SOURCE_NS, "src:" + NodeSource.SOURCE_MODIFIED);
- elem.setAttribute(NodeImpl.XMLNS_PREFIX + ":src", NodeSource.SOURCE_NS);
- doc.appendChild(elem);
- Text count = doc.createTextNode(Integer.toString(xu.getModifiedCount()));
- elem.appendChild(count);
-
- return new NodeListSet(doc.getChildNodes());
- }
- catch (Exception e) {
- if (e instanceof QueryException) {
- throw (QueryException) e.fillInStackTrace();
- }
- throw new ProcessingException("Error executing XUpdate query", e);
- }
- }
- }
+ private static final String XUPDATE_XPATH_PROP = "org.xmldb.common.xml.queries.XPathQueryFactory";
+ private static final String XUPDATE_XPATH_IMPL = "org.apache.xindice.core.xupdate.XPathQueryFactoryImpl";
+ static {
+ System.setProperty(XUPDATE_XPATH_PROP, XUPDATE_XPATH_IMPL);
+ }
+
+ private static Log log = LogFactory.getLog("org.apache.xindice.core");
+
+ public static final String STYLE_XUPDATE = "XUpdate";
+
+ private QueryEngine engine;
+
+ public void setConfig(Configuration config) throws XindiceException {
+ super.setConfig(config);
+ }
+
+ public String getQueryStyle() {
+ return STYLE_XUPDATE;
+ }
+
+ public void setQueryEngine(QueryEngine engine) {
+ this.engine = engine;
+ }
+
+ public Query compileQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
+ return new XUpdateQuery(context, query, nsMap, keys);
+ }
+
+ public NodeSet query(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
+ XUpdateQuery xq = new XUpdateQuery(context, query, nsMap, keys);
+ return xq.execute();
+ }
+
+ /**
+ * XUpdateQuery
+ */
+
+ private class XUpdateQuery implements Query {
+ public Collection context;
+ public String query;
+ public NamespaceMap nsMap;
+ public XUpdateImpl xu;
+ public Key[] keys;
+
+ public XUpdateQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
+ this.context = context;
+ this.query = query;
+ this.nsMap = nsMap;
+ this.keys = keys;
+
+ try {
+ xu = new XUpdateImpl();
+ xu.setQString(query);
+ xu.setNamespaceMap(nsMap);
+ }
+ catch (Exception e) {
+ if (e instanceof QueryException) {
+ throw (QueryException) e.fillInStackTrace();
+ }
+ throw new CompilationException("Error Compiling XUpdate Query", e);
+ }
+ }
+
+ public String getQueryStyle() {
+ return STYLE_XUPDATE;
+ }
+
+ public Collection getQueryContext() {
+ return context;
+ }
+
+ public String getQueryString() {
+ return query;
+ }
+
+ public NamespaceMap getNamespaceMap() {
+ return nsMap;
+ }
+
+ public Key[] getKeySet() {
+ return keys;
+ }
+
+ public NodeSet execute() throws QueryException {
+ try {
+ if (keys != null) {
+ try {
+ for (int i = 0; i < keys.length; i++) {
+ Document doc = context.getDocument(keys[i]);
+ xu.execute(doc.getDocumentElement());
+ context.setDocument(keys[i], doc);
+ }
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+ else {
+ xu.execute(context);
+ }
+
+ DocumentImpl doc = new DocumentImpl();
+ Element elem = doc.createElementNS(NodeSource.SOURCE_NS, "src:" + NodeSource.SOURCE_MODIFIED);
+ elem.setAttribute(NodeImpl.XMLNS_PREFIX + ":src", NodeSource.SOURCE_NS);
+ doc.appendChild(elem);
+ Text count = doc.createTextNode(Integer.toString(xu.getModifiedCount()));
+ elem.appendChild(count);
+
+ return new NodeListSet(doc.getChildNodes());
+ }
+ catch (Exception e) {
+ if (e instanceof QueryException) {
+ throw (QueryException) e.fillInStackTrace();
+ }
+ throw new ProcessingException("Error executing XUpdate query", e);
+ }
+ }
+ }
}
1.4 +55 -58 xml-xindice/java/src/org/apache/xindice/xml/jaxp/DocumentBuilderImpl.java
Index: DocumentBuilderImpl.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/jaxp/DocumentBuilderImpl.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- DocumentBuilderImpl.java 31 Oct 2002 07:02:23 -0000 1.3
+++ DocumentBuilderImpl.java 15 Jul 2003 15:44:35 -0000 1.4
@@ -59,76 +59,73 @@
* $Id$
*/
-import org.apache.xindice.xml.dom.DOMImplementationImpl;
-import org.apache.xindice.xml.dom.DOMParser;
-import org.apache.xindice.xml.dom.DocumentImpl;
+import java.io.IOException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
-import org.w3c.dom.*;
+import org.apache.xindice.xml.dom.DOMImplementationImpl;
+import org.apache.xindice.xml.dom.DOMParser;
+import org.apache.xindice.xml.dom.DocumentImpl;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
-import java.io.IOException;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.ParserConfigurationException;
-
/**
* DocumentBuilderImpl
*/
public class DocumentBuilderImpl extends DocumentBuilder {
- private static Log log = LogFactory.getLog("org.apache.xindice.xml");
+ private static Log log = LogFactory.getLog("org.apache.xindice.xml");
- private DOMParser parser = null;
- private ErrorHandler errors = null;
- private EntityResolver entities = null;
-
- protected DocumentBuilderImpl() throws ParserConfigurationException {
- try {
- parser = new DOMParser();
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- public DOMImplementation getDOMImplementation() {
- return DOMImplementationImpl.getInstance();
- }
-
- public boolean isNamespaceAware() {
- return true;
- }
-
- public boolean isValidating() {
- return false;
- }
-
- public void setErrorHandler(ErrorHandler errors) {
- this.errors = errors;
- }
-
- public void setEntityResolver(EntityResolver entities) {
- this.entities = entities;
- }
-
- public Document parse(InputSource source) throws SAXException, IOException, IllegalArgumentException {
- if ( source == null )
- throw new IllegalArgumentException();
- else
- parser.parse(source);
- return parser.getDocument();
- }
-
- public Document newDocument() {
- return new DocumentImpl();
- }
+ private DOMParser parser = null;
+ private ErrorHandler errors = null;
+ private EntityResolver entities = null;
+
+ protected DocumentBuilderImpl() throws ParserConfigurationException {
+ try {
+ parser = new DOMParser();
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ public DOMImplementation getDOMImplementation() {
+ return DOMImplementationImpl.getInstance();
+ }
+
+ public boolean isNamespaceAware() {
+ return true;
+ }
+
+ public boolean isValidating() {
+ return false;
+ }
+
+ public void setErrorHandler(ErrorHandler errors) {
+ this.errors = errors;
+ }
+
+ public void setEntityResolver(EntityResolver entities) {
+ this.entities = entities;
+ }
+
+ public Document parse(InputSource source) throws SAXException, IOException, IllegalArgumentException {
+ if (source == null)
+ throw new IllegalArgumentException();
+ else
+ parser.parse(source);
+ return parser.getDocument();
+ }
+
+ public Document newDocument() {
+ return new DocumentImpl();
+ }
}
-
1.12 +514 -546 xml-xindice/java/src/org/apache/xindice/core/indexer/IndexManager.java
Index: IndexManager.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/indexer/IndexManager.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- IndexManager.java 22 Nov 2002 10:15:35 -0000 1.11
+++ IndexManager.java 15 Jul 2003 15:44:35 -0000 1.12
@@ -59,6 +59,17 @@
* $Id$
*/
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.WeakHashMap;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.xindice.core.Collection;
import org.apache.xindice.core.DBException;
import org.apache.xindice.core.data.Key;
@@ -74,571 +85,528 @@
import org.apache.xindice.xml.dom.DocumentImpl;
import org.apache.xindice.xml.sax.CompressionHandler;
import org.apache.xindice.xml.sax.SAXEventGenerator;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.w3c.dom.*;
+import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.WeakHashMap;
-
/**
* IndexManager is a class that manages Indexes. Good description, eh?
* I should win a Pulitzer Prize for that one.
*/
public final class IndexManager extends SimpleConfigurable {
- private static final String[] EmptyStrings = new String[0];
- private static final IndexerInfo[] EmptyIndexerInfo = new IndexerInfo[0];
+ private static final String[] EmptyStrings = new String[0];
+ private static final IndexerInfo[] EmptyIndexerInfo = new IndexerInfo[0];
- private static final String INDEX = "index";
- private static final String NAME = "name";
- private static final String CLASS = "class";
-
- private static final int STATUS_READY = 0;
- private static final int STATUS_BUSY = 1;
- // private static final int STATUS_DELETED = 2;
-
- private static final int ACTION_CREATE = 0;
- private static final int ACTION_UPDATE = 1;
- private static final int ACTION_DELETE = 2;
-
- private static Log log = LogFactory.getLog("org.apache.xindice.core");
-
- private static final Timer indexTimer = new Timer( true );
-
- private Map patternMap = new HashMap(); // IndexPattern to IndexerInfo
- private Map indexes = new HashMap(); // String to IndexerInfo
- private Map bestIndexers = new HashMap(); // String to SoftRefTab
- // of IndexPattern to Indexer
-
- private IndexerInfo[] idxList = EmptyIndexerInfo;
-
- private Collection collection;
- private SymbolTable symbols;
- private List newIndexers = new ArrayList(); // of IndexerInfo
-
- public IndexManager(Collection collection) {
- this.collection = collection;
- try {
- symbols = collection.getSymbols();
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- public void setConfig(Configuration config) throws XindiceException {
- super.setConfig(config);
-
- try {
- config.processChildren(INDEX,
- new ConfigurationCallback() {
- public void process(Configuration cfg) {
- String className = cfg.getAttribute(CLASS);
- try {
- register(Class.forName(className), cfg);
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
- });
- }
- catch ( Exception e ) {
- if (log.isWarnEnabled()) {
- log.warn("setConfig", e);
- }
- }
- }
-
- /**
- * list returns a list of the Indexers that this IndexerManager has
- * registered.
- *
- * @return An array containing the Indexer names
- */
- public String[] list() {
- return (String[])indexes.keySet().toArray(EmptyStrings);
- }
-
- /**
- * drop physically removes the specified Indexer and any
- * associated system resources that the Indexer uses.
- *
- * @param name The Indexer to drop
- * @return Whether or not the Indexer was dropped
- */
- public boolean drop(final String name) {
- Indexer idx = get(name);
- unregister(name);
- config.processChildren(INDEX,
- new ConfigurationCallback() {
+ private static final String INDEX = "index";
+ private static final String NAME = "name";
+ private static final String CLASS = "class";
+
+ private static final int STATUS_READY = 0;
+ private static final int STATUS_BUSY = 1;
+ // private static final int STATUS_DELETED = 2;
+
+ private static final int ACTION_CREATE = 0;
+ private static final int ACTION_UPDATE = 1;
+ private static final int ACTION_DELETE = 2;
+
+ private static Log log = LogFactory.getLog("org.apache.xindice.core");
+
+ private static final Timer indexTimer = new Timer(true);
+
+ private Map patternMap = new HashMap(); // IndexPattern to IndexerInfo
+ private Map indexes = new HashMap(); // String to IndexerInfo
+ private Map bestIndexers = new HashMap(); // String to SoftRefTab
+ // of IndexPattern to Indexer
+
+ private IndexerInfo[] idxList = EmptyIndexerInfo;
+
+ private Collection collection;
+ private SymbolTable symbols;
+ private List newIndexers = new ArrayList(); // of IndexerInfo
+
+ public IndexManager(Collection collection) {
+ this.collection = collection;
+ try {
+ symbols = collection.getSymbols();
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ public void setConfig(Configuration config) throws XindiceException {
+ super.setConfig(config);
+
+ try {
+ config.processChildren(INDEX, new ConfigurationCallback() {
+ public void process(Configuration cfg) {
+ String className = cfg.getAttribute(CLASS);
+ try {
+ register(Class.forName(className), cfg);
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+ });
+ }
+ catch (Exception e) {
+ if (log.isWarnEnabled()) {
+ log.warn("setConfig", e);
+ }
+ }
+ }
+
+ /**
+ * list returns a list of the Indexers that this IndexerManager has
+ * registered.
+ *
+ * @return An array containing the Indexer names
+ */
+ public String[] list() {
+ return (String[]) indexes.keySet().toArray(EmptyStrings);
+ }
+
+ /**
+ * drop physically removes the specified Indexer and any
+ * associated system resources that the Indexer uses.
+ *
+ * @param name The Indexer to drop
+ * @return Whether or not the Indexer was dropped
+ */
+ public boolean drop(final String name) {
+ Indexer idx = get(name);
+ unregister(name);
+ config.processChildren(INDEX, new ConfigurationCallback() {
public void process(Configuration cfg) {
- try {
- if ( cfg.getAttribute(NAME).equals(name) )
- cfg.delete();
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
- });
-
- boolean res = false;
- try {
- res = idx.drop();
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- return res;
- }
-
- /**
- * create creates a new Indexer object and any associated
- * system resources that the Indexer will need.
- *
- * @param cfg The Indexer's configuration
- * @return The Indexer that was created
- */
- public Indexer create(Configuration cfg) throws DBException {
- String className = cfg.getAttribute(CLASS);
- try {
- // Check for duplicates
- String name = cfg.getAttribute(NAME);
- Configuration[] cfgs = config.getChildren();
- for ( int i = 0; i < cfgs.length; i++ )
- if ( cfgs[i].getAttribute(NAME).equals(name) )
- throw new DuplicateIndexException("Duplicate Index '"+name+"'");
-
- config.add(cfg);
-
- Class c = Class.forName(className);
- Indexer idx = register(c, cfg);
-
- return idx;
- }
- catch ( DBException e ) {
- throw e;
- }
- catch ( Exception e ) {
- throw new CannotCreateException("Cannot create Index", e);
- }
- }
-
- public Indexer register(Class c, Configuration cfg) throws DBException {
- String name = null;
- try {
- Indexer idx = (Indexer)c.newInstance();
- initialize(idx, cfg);
- name = idx.getName();
-
- if ( name == null || name.trim().equals("") )
- throw new CannotCreateException("No name specified");
-
- IndexPattern pattern = new IndexPattern(symbols, idx.getPattern(), null);
- String style = idx.getIndexStyle();
- IndexerInfo info = new IndexerInfo(name, style, pattern, idx);
-
- if ( !idx.exists() ) {
- info.status = STATUS_BUSY;
- synchronized ( newIndexers ) {
- newIndexers.add(info);
- }
- indexTimer.schedule( new PopulateIndexersTimerTask( this ), 0 );
- }
- else {
- info.status = STATUS_READY;
- idx.open();
- }
+ try {
+ if (cfg.getAttribute(NAME).equals(name))
+ cfg.delete();
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+ });
+
+ boolean res = false;
+ try {
+ res = idx.drop();
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ return res;
+ }
+
+ /**
+ * create creates a new Indexer object and any associated
+ * system resources that the Indexer will need.
+ *
+ * @param cfg The Indexer's configuration
+ * @return The Indexer that was created
+ */
+ public Indexer create(Configuration cfg) throws DBException {
+ String className = cfg.getAttribute(CLASS);
+ try {
+ // Check for duplicates
+ String name = cfg.getAttribute(NAME);
+ Configuration[] cfgs = config.getChildren();
+ for (int i = 0; i < cfgs.length; i++)
+ if (cfgs[i].getAttribute(NAME).equals(name))
+ throw new DuplicateIndexException("Duplicate Index '" + name + "'");
+
+ config.add(cfg);
+
+ Class c = Class.forName(className);
+ Indexer idx = register(c, cfg);
+
+ return idx;
+ }
+ catch (DBException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ throw new CannotCreateException("Cannot create Index", e);
+ }
+ }
+
+ public Indexer register(Class c, Configuration cfg) throws DBException {
+ String name = null;
+ try {
+ Indexer idx = (Indexer) c.newInstance();
+ initialize(idx, cfg);
+ name = idx.getName();
+
+ if (name == null || name.trim().equals(""))
+ throw new CannotCreateException("No name specified");
+
+ IndexPattern pattern = new IndexPattern(symbols, idx.getPattern(), null);
+ String style = idx.getIndexStyle();
+ IndexerInfo info = new IndexerInfo(name, style, pattern, idx);
+
+ if (!idx.exists()) {
+ info.status = STATUS_BUSY;
+ synchronized (newIndexers) {
+ newIndexers.add(info);
+ }
+ indexTimer.schedule(new PopulateIndexersTimerTask(this), 0);
+ }
+ else {
+ info.status = STATUS_READY;
+ idx.open();
+ }
- indexes.put(name, info);
- patternMap.put(pattern, info);
+ indexes.put(name, info);
+ patternMap.put(pattern, info);
- Map tbl = (Map)bestIndexers.get(style);
- if ( tbl == null ) {
+ Map tbl = (Map) bestIndexers.get(style);
+ if (tbl == null) {
+ tbl = new WeakHashMap();
+ bestIndexers.put(style, tbl);
+ }
+ tbl.clear();
+ idxList = (IndexerInfo[]) indexes.values().toArray(EmptyIndexerInfo);
+
+ return idx;
+ }
+ catch (DBException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ throw new CannotCreateException("Cannot create Index '" + name + "'", e);
+ }
+ }
+
+ public void unregister(String name) {
+ IndexerInfo idx = (IndexerInfo) indexes.remove(name);
+ String style = idx.style;
+ patternMap.remove(idx.pattern);
+
+ Map tbl = (Map) bestIndexers.get(style);
+ if (tbl == null) {
tbl = new WeakHashMap();
bestIndexers.put(style, tbl);
- }
- tbl.clear();
- idxList = (IndexerInfo[])indexes.values().toArray(EmptyIndexerInfo);
-
- return idx;
- }
- catch ( DBException e ) {
- throw e;
- }
- catch ( Exception e ) {
- throw new CannotCreateException("Cannot create Index '"+name+"'", e);
- }
- }
-
- public void unregister(String name) {
- IndexerInfo idx = (IndexerInfo)indexes.remove(name);
- String style = idx.style;
- patternMap.remove(idx.pattern);
-
- Map tbl = (Map)bestIndexers.get(style);
- if ( tbl == null ) {
- tbl = new WeakHashMap();
- bestIndexers.put(style, tbl);
- }
- tbl.clear();
-
- idxList = (IndexerInfo[])indexes.values().toArray(EmptyIndexerInfo);
- }
-
- private void initialize(Indexer idx, Configuration cfg) throws XindiceException {
- idx.setCollection(collection);
- idx.setConfig(cfg);
- }
-
- private void populateNewIndexers() throws DBException {
- IndexerInfo[] list = null;
- synchronized ( newIndexers ) {
- list = (IndexerInfo[])newIndexers.toArray(EmptyIndexerInfo);
- newIndexers.clear();
- }
-
- if ( list.length > 0 ) {
- if ( true ) {
- if (log.isDebugEnabled()) {
- for ( int i = 0; i < list.length; i++ ) {
- log.debug("Index Creation: "+list[i].indexer.getName());
- }
- }
- }
-
-org.apache.xindice.Stopwatch sw = new org.apache.xindice.Stopwatch("Populated Indexes", true);
- for ( int i = 0; i < list.length; i++ ) {
- try {
- if ( !list[i].indexer.exists() )
- list[i].indexer.create();
- list[i].indexer.open();
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- RecordSet rs = collection.getFiler().getRecordSet();
- while ( rs.hasMoreRecords() ) {
- Record rec = rs.getNextRecord();
-
- if ( rec == null )
- continue;
-
- Key key = rec.getKey();
- Document doc = new DocumentImpl(rec.getValue().getData(), symbols, new NodeSource(collection, key));
- try {
- new SAXHandler(key, doc, ACTION_CREATE, list);
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
+ }
+ tbl.clear();
- for ( int i = 0; i < list.length; i++ ) {
- try {
- list[i].indexer.flush();
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- list[i].status = STATUS_READY;
- }
-sw.stop();
-
- if ( true ) {
- if (log.isDebugEnabled()) {
- for ( int i = 0; i < list.length; i++ ) {
- log.debug("Index Complete: "+list[i].indexer.getName());
- }
- log.debug(sw.toString());
- }
- }
- }
- }
-
- /**
- * get retrieves an Indexer by name.
- *
- * @param name The Indexer name
- * @return The Indexer
- */
- public Indexer get(String name) {
- IndexerInfo info = (IndexerInfo)indexes.get(name);
- return info != null ? info.indexer
- : null;
- }
-
- /**
- * getBestIndexer retrieves the best Indexer to use for the specified
- * IndexPattern.
- *
- * @param style The Indexer Style (ex: Node, Value)
- * @param pattern The IndexPattern to use
- * @return The best Indexer (or null)
- */
- public Indexer getBestIndexer(String style, IndexPattern pattern) {
- Map tbl = (Map)bestIndexers.get(style);
- if ( tbl == null ) {
- tbl = new WeakHashMap();
- bestIndexers.put(style, tbl);
- }
- Indexer idx = (Indexer)tbl.get(pattern);
- if ( idx == null ) {
- int highScore = 0;
- Iterator enum = indexes.values().iterator();
- while ( enum.hasNext() ) {
- IndexerInfo info = (IndexerInfo)enum.next();
- if ( info.status != STATUS_READY
- || !info.indexer.getIndexStyle().equals(style) )
- continue;
- int score = pattern.getMatchLevel(info.pattern);
- if ( score > highScore ) {
- idx = info.indexer;
- highScore = score;
- }
- }
- tbl.put(pattern, idx);
- }
- return idx;
- }
-
- public void addDocument(Key key, Document doc) {
- if ( idxList.length > 0 ) {
- new SAXHandler(key, doc, ACTION_CREATE);
- for ( int i = 0; i < idxList.length; i++ ) {
- try {
- idxList[i].indexer.flush();
- }
- catch ( Exception e ) {
- }
- }
- }
- }
-
- public void removeDocument(Key key, Document doc) {
- if ( idxList.length > 0 ) {
- new SAXHandler(key, doc, ACTION_DELETE);
- for ( int i = 0; i < idxList.length; i++ ) {
- try {
- idxList[i].indexer.flush();
- }
- catch ( Exception e ) {
- }
- }
- }
- }
-
-
- /**
- * IndexerInfo
- */
-
- private class IndexerInfo {
- public String name;
- public String style;
- public IndexPattern pattern;
- public Indexer indexer;
- public int status;
-
- public IndexerInfo(String name, String style, IndexPattern pattern, Indexer indexer) {
- this.name = name;
- this.style = style;
- this.pattern = pattern;
- this.indexer = indexer;
- }
- }
-
-
- /**
- * SAXHandler actually performs the work of adding and removing Indexer
- * entries.
- */
-
- private class SAXHandler implements ContentHandler, CompressionHandler {
- private ObjectStack stack = new ObjectStack();
- private IndexerInfo[] list;
-
- public Key key;
- public Document doc;
- public int action;
-
- public StackInfo info; // Current State
-
- public SAXHandler(Key key, Document doc, int action, IndexerInfo[] list) {
- this.list = list;
- this.key = key;
- this.doc = doc;
- this.action = action;
-
- try {
- SAXEventGenerator events = new SAXEventGenerator(doc);
- events.setContentHandler(this);
- events.setProperty(HANDLER, this);
- events.start();
-
- if ( action == ACTION_CREATE || action == ACTION_UPDATE ) {
- try {
- collection.flushSymbolTable();
- }
- catch ( Exception e ) {
- }
- }
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- public SAXHandler(Key key, Document doc, int action) {
- this(key, doc, action, idxList);
- }
-
- // These are all NO-OPs
- public void setDocumentLocator(Locator locator) {}
- public void startDocument() {}
- public void endDocument() {}
- public void startPrefixMapping(String prefix, String uri) {}
- public void endPrefixMapping(String prefix) {}
- public void ignorableWhitespace(char ch[], int start, int length) {}
- public void processingInstruction(String target, String data) {}
- public void skippedEntity(String name) {}
- public void symbols(SymbolTable symbols) {}
- public void dataBytes(byte[] data) {}
-
- public void processEntry(IndexPattern pattern, String value, int pos, int len) {
- for ( int i = 0; i < list.length; i++ ) {
- if ( pattern.getMatchLevel(list[i].pattern) > 0 ) {
- try {
- switch ( action ) {
- case ACTION_CREATE:
- case ACTION_UPDATE:
- list[i].indexer.add(value, key, pos, len, pattern.getElementID(), pattern.getAttributeID());
- break;
- case ACTION_DELETE:
- list[i].indexer.remove(value, key, pos, len, pattern.getElementID(), pattern.getAttributeID());
- break;
- }
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
- }
- }
-
- public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
- // Modify the stack info to normalize the symbolID
- if ( namespaceURI != null && namespaceURI.length() > 0 ) {
- String elemNSID = SymbolTable.getNormalizedLocalName(localName, namespaceURI);
- info.symbolID = symbols.getSymbol(elemNSID, namespaceURI, true);
- }
-
- int size = atts.getLength();
- for ( int i = 0; i < size; i++ ) {
- String nsURI = atts.getURI(i);
- if ( nsURI != null && nsURI.length() > 0 ) {
- String attrNSID = "ns"+Integer.toString(nsURI.hashCode())+":"+atts.getLocalName(i);
- short id = symbols.getSymbol(attrNSID, nsURI, true);
- processEntry(new IndexPattern(symbols, info.symbolID, id), atts.getValue(i), info.pos, info.len);
- }
- else {
- short id = symbols.getSymbol(atts.getQName(i));
- processEntry(new IndexPattern(symbols, info.symbolID, id), atts.getValue(i), info.pos, info.len);
- }
- }
- }
+ idxList = (IndexerInfo[]) indexes.values().toArray(EmptyIndexerInfo);
+ }
- public void endElement(String namespaceURI, String localName, String qName) {
- if ( info.sb != null )
- processEntry(new IndexPattern(symbols, info.symbolID), info.sb.toString(), info.pos, info.len);
- info = (StackInfo)stack.pop();
- }
-
- public void characters(char ch[], int start, int length) {
- String val = new String(ch).trim();
- if ( info.sb == null )
- info.sb = new StringBuffer(ch.length);
- else if ( info.sb.length() > 0 )
- info.sb.append(' ');
- info.sb.append(val);
- }
-
- public void symbolID(short symbolID) {
- if ( info != null )
- stack.push(info);
- info = new StackInfo(symbolID);
- }
-
- public void dataLocation(int pos, int len) {
- info.pos = pos;
- info.len = len;
- }
- }
-
-
- /**
- * StackInfo
- */
-
- private class StackInfo {
- public short symbolID;
- public StringBuffer sb = null;
- public int pos = -1;
- public int len = -1;
-
- public StackInfo(short symbolID) {
- this.symbolID = symbolID;
- }
- }
+ private void initialize(Indexer idx, Configuration cfg) throws XindiceException {
+ idx.setCollection(collection);
+ idx.setConfig(cfg);
+ }
+
+ private void populateNewIndexers() throws DBException {
+ IndexerInfo[] list = null;
+ synchronized (newIndexers) {
+ list = (IndexerInfo[]) newIndexers.toArray(EmptyIndexerInfo);
+ newIndexers.clear();
+ }
+
+ if (list.length > 0) {
+ if (true) {
+ if (log.isDebugEnabled()) {
+ for (int i = 0; i < list.length; i++) {
+ log.debug("Index Creation: " + list[i].indexer.getName());
+ }
+ }
+ }
+
+ org.apache.xindice.Stopwatch sw = new org.apache.xindice.Stopwatch("Populated Indexes", true);
+ for (int i = 0; i < list.length; i++) {
+ try {
+ if (!list[i].indexer.exists())
+ list[i].indexer.create();
+ list[i].indexer.open();
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ RecordSet rs = collection.getFiler().getRecordSet();
+ while (rs.hasMoreRecords()) {
+ Record rec = rs.getNextRecord();
+
+ if (rec == null)
+ continue;
+
+ Key key = rec.getKey();
+ Document doc = new DocumentImpl(rec.getValue().getData(), symbols, new NodeSource(collection, key));
+ try {
+ new SAXHandler(key, doc, ACTION_CREATE, list);
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ for (int i = 0; i < list.length; i++) {
+ try {
+ list[i].indexer.flush();
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ list[i].status = STATUS_READY;
+ }
+ sw.stop();
+
+ if (true) {
+ if (log.isDebugEnabled()) {
+ for (int i = 0; i < list.length; i++) {
+ log.debug("Index Complete: " + list[i].indexer.getName());
+ }
+ log.debug(sw.toString());
+ }
+ }
+ }
+ }
+
+ /**
+ * get retrieves an Indexer by name.
+ *
+ * @param name The Indexer name
+ * @return The Indexer
+ */
+ public Indexer get(String name) {
+ IndexerInfo info = (IndexerInfo) indexes.get(name);
+ return info != null ? info.indexer : null;
+ }
+
+ /**
+ * getBestIndexer retrieves the best Indexer to use for the specified
+ * IndexPattern.
+ *
+ * @param style The Indexer Style (ex: Node, Value)
+ * @param pattern The IndexPattern to use
+ * @return The best Indexer (or null)
+ */
+ public Indexer getBestIndexer(String style, IndexPattern pattern) {
+ Map tbl = (Map) bestIndexers.get(style);
+ if (tbl == null) {
+ tbl = new WeakHashMap();
+ bestIndexers.put(style, tbl);
+ }
+ Indexer idx = (Indexer) tbl.get(pattern);
+ if (idx == null) {
+ int highScore = 0;
+ Iterator enum = indexes.values().iterator();
+ while (enum.hasNext()) {
+ IndexerInfo info = (IndexerInfo) enum.next();
+ if (info.status != STATUS_READY || !info.indexer.getIndexStyle().equals(style))
+ continue;
+ int score = pattern.getMatchLevel(info.pattern);
+ if (score > highScore) {
+ idx = info.indexer;
+ highScore = score;
+ }
+ }
+ tbl.put(pattern, idx);
+ }
+ return idx;
+ }
+
+ public void addDocument(Key key, Document doc) {
+ if (idxList.length > 0) {
+ new SAXHandler(key, doc, ACTION_CREATE);
+ for (int i = 0; i < idxList.length; i++) {
+ try {
+ idxList[i].indexer.flush();
+ }
+ catch (Exception e) {}
+ }
+ }
+ }
+
+ public void removeDocument(Key key, Document doc) {
+ if (idxList.length > 0) {
+ new SAXHandler(key, doc, ACTION_DELETE);
+ for (int i = 0; i < idxList.length; i++) {
+ try {
+ idxList[i].indexer.flush();
+ }
+ catch (Exception e) {}
+ }
+ }
+ }
+
+ /**
+ * IndexerInfo
+ */
+
+ private class IndexerInfo {
+ public String name;
+ public String style;
+ public IndexPattern pattern;
+ public Indexer indexer;
+ public int status;
+
+ public IndexerInfo(String name, String style, IndexPattern pattern, Indexer indexer) {
+ this.name = name;
+ this.style = style;
+ this.pattern = pattern;
+ this.indexer = indexer;
+ }
+ }
+
+ /**
+ * SAXHandler actually performs the work of adding and removing Indexer
+ * entries.
+ */
+
+ private class SAXHandler implements ContentHandler, CompressionHandler {
+ private ObjectStack stack = new ObjectStack();
+ private IndexerInfo[] list;
+
+ public Key key;
+ public Document doc;
+ public int action;
+
+ public StackInfo info; // Current State
+
+ public SAXHandler(Key key, Document doc, int action, IndexerInfo[] list) {
+ this.list = list;
+ this.key = key;
+ this.doc = doc;
+ this.action = action;
+ try {
+ SAXEventGenerator events = new SAXEventGenerator(doc);
+ events.setContentHandler(this);
+ events.setProperty(HANDLER, this);
+ events.start();
+
+ if (action == ACTION_CREATE || action == ACTION_UPDATE) {
+ try {
+ collection.flushSymbolTable();
+ }
+ catch (Exception e) {}
+ }
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ public SAXHandler(Key key, Document doc, int action) {
+ this(key, doc, action, idxList);
+ }
+
+ // These are all NO-OPs
+ public void setDocumentLocator(Locator locator) {}
+ public void startDocument() {}
+ public void endDocument() {}
+ public void startPrefixMapping(String prefix, String uri) {}
+ public void endPrefixMapping(String prefix) {}
+ public void ignorableWhitespace(char ch[], int start, int length) {}
+ public void processingInstruction(String target, String data) {}
+ public void skippedEntity(String name) {}
+ public void symbols(SymbolTable symbols) {}
+ public void dataBytes(byte[] data) {}
+
+ public void processEntry(IndexPattern pattern, String value, int pos, int len) {
+ for (int i = 0; i < list.length; i++) {
+ if (pattern.getMatchLevel(list[i].pattern) > 0) {
+ try {
+ switch (action) {
+ case ACTION_CREATE :
+ case ACTION_UPDATE :
+ list[i].indexer.add(value, key, pos, len, pattern.getElementID(), pattern.getAttributeID());
+ break;
+ case ACTION_DELETE :
+ list[i].indexer.remove(value, key, pos, len, pattern.getElementID(), pattern.getAttributeID());
+ break;
+ }
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+ }
+ }
+
+ public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
+ // Modify the stack info to normalize the symbolID
+ if (namespaceURI != null && namespaceURI.length() > 0) {
+ String elemNSID = SymbolTable.getNormalizedLocalName(localName, namespaceURI);
+ info.symbolID = symbols.getSymbol(elemNSID, namespaceURI, true);
+ }
+
+ int size = atts.getLength();
+ for (int i = 0; i < size; i++) {
+ String nsURI = atts.getURI(i);
+ if (nsURI != null && nsURI.length() > 0) {
+ String attrNSID = "ns" + Integer.toString(nsURI.hashCode()) + ":" + atts.getLocalName(i);
+ short id = symbols.getSymbol(attrNSID, nsURI, true);
+ processEntry(new IndexPattern(symbols, info.symbolID, id), atts.getValue(i), info.pos, info.len);
+ }
+ else {
+ short id = symbols.getSymbol(atts.getQName(i));
+ processEntry(new IndexPattern(symbols, info.symbolID, id), atts.getValue(i), info.pos, info.len);
+ }
+ }
+ }
+
+ public void endElement(String namespaceURI, String localName, String qName) {
+ if (info.sb != null)
+ processEntry(new IndexPattern(symbols, info.symbolID), info.sb.toString(), info.pos, info.len);
+ info = (StackInfo) stack.pop();
+ }
+
+ public void characters(char ch[], int start, int length) {
+ String val = new String(ch).trim();
+ if (info.sb == null)
+ info.sb = new StringBuffer(ch.length);
+ else if (info.sb.length() > 0)
+ info.sb.append(' ');
+ info.sb.append(val);
+ }
+
+ public void symbolID(short symbolID) {
+ if (info != null)
+ stack.push(info);
+ info = new StackInfo(symbolID);
+ }
+
+ public void dataLocation(int pos, int len) {
+ info.pos = pos;
+ info.len = len;
+ }
+ }
+
+ /**
+ * StackInfo
+ */
+
+ private class StackInfo {
+ public short symbolID;
+ public StringBuffer sb = null;
+ public int pos = -1;
+ public int len = -1;
+
+ public StackInfo(short symbolID) {
+ this.symbolID = symbolID;
+ }
+ }
private static class PopulateIndexersTimerTask extends TimerTask {
- private IndexManager mgr;
- public PopulateIndexersTimerTask( IndexManager mgr ) {
- this.mgr = mgr;
- }
- public void run() {
- try {
- mgr.populateNewIndexers();
- }
- catch ( DBException e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
+ private IndexManager mgr;
+ public PopulateIndexersTimerTask(IndexManager mgr) {
+ this.mgr = mgr;
+ }
+ public void run() {
+ try {
+ mgr.populateNewIndexers();
+ }
+ catch (DBException e) {
+ log.warn(e);
+
+ }
+ }
}
}
1.8 +121 -136 xml-xindice/java/src/org/apache/xindice/core/indexer/NameIndexer.java
Index: NameIndexer.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/indexer/NameIndexer.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- NameIndexer.java 19 Nov 2002 05:16:58 -0000 1.7
+++ NameIndexer.java 15 Jul 2003 15:44:36 -0000 1.8
@@ -59,6 +59,13 @@
* $Id$
*/
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.xindice.core.Collection;
import org.apache.xindice.core.DBException;
import org.apache.xindice.core.data.Key;
@@ -69,14 +76,6 @@
import org.apache.xindice.util.Configuration;
import org.apache.xindice.xml.SymbolTable;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* NameIndexer is a basic implementation of the Indexer interface.
* It is used for maintaining element and element@attribute unique
@@ -84,133 +83,119 @@
*/
public final class NameIndexer extends BTree implements Indexer {
- private static final IndexMatch[] EmptyMatches = new IndexMatch[0];
+ private static final IndexMatch[] EmptyMatches = new IndexMatch[0];
- private static final String NAME = "name";
- private static final String PATTERN = "pattern";
- private static final String PAGESIZE = "pagesize";
- private static final String MAXKEYSIZE = "maxkeysize";
-
- private static Log log = LogFactory.getLog("org.apache.xindice.core");
-
- private Configuration config;
- private Collection collection;
- private SymbolTable symbols;
-
- private String name;
- private String pattern;
- private boolean wildcard = false;
-
- private FileHeader fileHeader;
-
- public NameIndexer() {
- super();
- fileHeader = getFileHeader();
- }
-
- public void setConfig(Configuration config) {
- this.config = config;
- try {
- name = config.getAttribute(NAME);
-
- pattern = config.getAttribute(PATTERN);
- wildcard = pattern.indexOf('*') != -1;
-
- fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
- fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
-
- setLocation(name);
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- public Configuration getConfig() {
- return config;
- }
-
- public String getName() {
- return name;
- }
-
- public void setLocation(String location) {
- setFile(new File(collection.getCollectionRoot(), location+".idx"));
- }
-
- public void setCollection(Collection collection) {
- try {
- this.collection = collection;
- symbols = collection.getSymbols();
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- public String getIndexStyle() {
- return STYLE_NODENAME;
- }
-
- public String getPattern() {
- return pattern;
- }
-
- public void remove(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
- try {
- removeValue(key);
- }
- catch ( IOException e ) {
- throw new BTreeCorruptException("Corruption detected on remove", e);
- }
- }
-
- public void add(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
- try {
- addValue(key, 0);
- }
- catch ( IOException e ) {
- throw new BTreeCorruptException("Corruption detected on add", e);
- }
- }
-
- public void flush() throws DBException {
- super.flush();
- }
-
- public IndexMatch[] queryMatches(final IndexQuery query) throws DBException {
- final List results = new ArrayList();
- final IndexPattern pattern = query.getPattern();
-
- try {
- query(query, new BTreeCallback() {
- public boolean indexInfo(Value value, long pos) {
- results.add(new IndexMatch(new Key(value), pattern));
- return true;
- }
- });
- }
- catch ( DBException e ) {
- throw e;
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
+ private static final String NAME = "name";
+ private static final String PATTERN = "pattern";
+ private static final String PAGESIZE = "pagesize";
+ private static final String MAXKEYSIZE = "maxkeysize";
+
+ private static Log log = LogFactory.getLog("org.apache.xindice.core");
+
+ private Configuration config;
+ private Collection collection;
+ private SymbolTable symbols;
+
+ private String name;
+ private String pattern;
+ private boolean wildcard = false;
+
+ private FileHeader fileHeader;
+
+ public NameIndexer() {
+ super();
+ fileHeader = getFileHeader();
+ }
+
+ public void setConfig(Configuration config) {
+ this.config = config;
+ try {
+ name = config.getAttribute(NAME);
+
+ pattern = config.getAttribute(PATTERN);
+ wildcard = pattern.indexOf('*') != -1;
+
+ fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
+ fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
+
+ setLocation(name);
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ public Configuration getConfig() {
+ return config;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setLocation(String location) {
+ setFile(new File(collection.getCollectionRoot(), location + ".idx"));
+ }
+
+ public void setCollection(Collection collection) {
+ try {
+ this.collection = collection;
+ symbols = collection.getSymbols();
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ public String getIndexStyle() {
+ return STYLE_NODENAME;
+ }
+
+ public String getPattern() {
+ return pattern;
+ }
+
+ public void remove(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
+ try {
+ removeValue(key);
+ }
+ catch (IOException e) {
+ throw new BTreeCorruptException("Corruption detected on remove", e);
+ }
+ }
+
+ public void add(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
+ try {
+ addValue(key, 0);
+ }
+ catch (IOException e) {
+ throw new BTreeCorruptException("Corruption detected on add", e);
+ }
+ }
+
+ public void flush() throws DBException {
+ super.flush();
+ }
+
+ public IndexMatch[] queryMatches(final IndexQuery query) throws DBException {
+ final List results = new ArrayList();
+ final IndexPattern pattern = query.getPattern();
+
+ try {
+ query(query, new BTreeCallback() {
+ public boolean indexInfo(Value value, long pos) {
+ results.add(new IndexMatch(new Key(value), pattern));
+ return true;
+ }
+ });
+ }
+ catch (DBException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
- return (IndexMatch[])results.toArray(EmptyMatches);
- }
+ return (IndexMatch[]) results.toArray(EmptyMatches);
+ }
}
-
-
-
-
-
-
-
-
1.7 +346 -351 xml-xindice/java/src/org/apache/xindice/core/indexer/ValueIndexer.java
Index: ValueIndexer.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/indexer/ValueIndexer.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- ValueIndexer.java 19 Nov 2002 05:16:58 -0000 1.6
+++ ValueIndexer.java 15 Jul 2003 15:44:36 -0000 1.7
@@ -59,6 +59,13 @@
* $Id$
*/
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.xindice.core.Collection;
import org.apache.xindice.core.DBException;
import org.apache.xindice.core.data.Key;
@@ -71,14 +78,6 @@
import org.apache.xindice.util.Configuration;
import org.apache.xindice.xml.SymbolTable;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* ValueIndexer is a basic implementation of the Indexer interface.
* It is used for maintaining element and element@attribute value
@@ -86,352 +85,348 @@
*/
public final class ValueIndexer extends BTree implements Indexer {
- private static final IndexMatch[] EmptyMatches = new IndexMatch[0];
- private static final Value EmptyValue = new Value(new byte[0]);
+ private static final IndexMatch[] EmptyMatches = new IndexMatch[0];
+ private static final Value EmptyValue = new Value(new byte[0]);
- private static final long MATCH_INFO = -1000;
+ private static final long MATCH_INFO = -1000;
- private static final String NAME = "name";
- private static final String PATTERN = "pattern";
- private static final String TYPE = "type";
- private static final String PAGESIZE = "pagesize";
- private static final String MAXKEYSIZE = "maxkeysize";
-
- private static final int STRING = 0;
- private static final int TRIMMED = 1;
- private static final int INTEGER = 2;
- private static final int FLOAT = 3;
- private static final int BYTE = 4;
- private static final int CHAR = 5;
- private static final int BOOLEAN = 6;
-
- private static final int[] sizes = { -1, -1, 8, 8, 1, 2, 1 };
-
- private static final String STRING_VAL = "string";
- private static final String TRIMMED_VAL = "trimmed";
- private static final String SHORT_VAL = "short";
- private static final String INT_VAL = "int";
- private static final String LONG_VAL = "long";
- private static final String FLOAT_VAL = "float";
- private static final String DOUBLE_VAL = "double";
- private static final String BYTE_VAL = "byte";
- private static final String CHAR_VAL = "char";
- private static final String BOOLEAN_VAL = "boolean";
-
- private static Log log = LogFactory.getLog("org.apache.xindice.core");
-
- private Configuration config;
- private Collection collection;
- private SymbolTable symbols;
-
- private String name;
- private String pattern;
- private int type;
- private int typeSize = 32;
- private boolean wildcard = false;
-
- private FileHeader fileHeader;
-
- public ValueIndexer() {
- super();
- fileHeader = getFileHeader();
- fileHeader.setPageSize(1024);
- }
-
- public void setConfig(Configuration config) {
- this.config = config;
- try {
- name = config.getAttribute(NAME);
-
- pattern = config.getAttribute(PATTERN);
- wildcard = pattern.indexOf('*') != -1;
-
- // Determine the Index Type
- String tv = config.getAttribute(TYPE, STRING_VAL).toLowerCase();
- if ( tv.equals(STRING_VAL) ) type = STRING;
- else if ( tv.equals(TRIMMED_VAL) ) type = TRIMMED;
- else if ( tv.equals(SHORT_VAL) ) type = INTEGER;
- else if ( tv.equals(INT_VAL) ) type = INTEGER;
- else if ( tv.equals(LONG_VAL) ) type = INTEGER;
- else if ( tv.equals(FLOAT_VAL) ) type = FLOAT;
- else if ( tv.equals(DOUBLE_VAL) ) type = FLOAT;
- else if ( tv.equals(BYTE_VAL) ) type = BYTE;
- else if ( tv.equals(CHAR_VAL) ) type = CHAR;
- else if ( tv.equals(BOOLEAN_VAL) ) type = BOOLEAN;
- else {
- if ( pattern.indexOf('@') != -1 )
- type = STRING;
- else
- type = TRIMMED;
- }
-
- typeSize = sizes[type];
-
- fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
- fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
-
- setLocation(name);
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- public Configuration getConfig() {
- return config;
- }
-
- public String getName() {
- return name;
- }
-
- public void setLocation(String location) {
- setFile(new File(collection.getCollectionRoot(), location+".idx"));
- }
-
- public void setCollection(Collection collection) {
- try {
- this.collection = collection;
- symbols = collection.getSymbols();
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- public String getIndexStyle() {
- return STYLE_NODEVALUE;
- }
-
- public String getPattern() {
- return pattern;
- }
-
- public Value getTypedValue(String value) {
- if ( type != STRING && type != TRIMMED ) {
- value = value.trim();
-
- if ( value.length() == 0 )
- return EmptyValue;
-
- byte[] b = new byte[typeSize];
- try {
- switch ( type ) {
- case INTEGER:
- long l = Long.parseLong(value);
- b[0] = (byte)((l >>> 56) & 0xFF);
- b[1] = (byte)((l >>> 48) & 0xFF);
- b[2] = (byte)((l >>> 40) & 0xFF);
- b[3] = (byte)((l >>> 32) & 0xFF);
- b[4] = (byte)((l >>> 24) & 0xFF);
- b[5] = (byte)((l >>> 16) & 0xFF);
- b[6] = (byte)((l >>> 8) & 0xFF);
- b[7] = (byte)((l >>> 0) & 0xFF);
- break;
- case FLOAT:
- double d = Double.parseDouble(value);
- int i1 = (int)Math.round(d);
- int i2 = (int)Math.round((d-i1)*1000000000);
- b[0] = (byte)((i1 >>> 24) & 0xFF);
- b[1] = (byte)((i1 >>> 16) & 0xFF);
- b[2] = (byte)((i1 >>> 8) & 0xFF);
- b[3] = (byte)((i1 >>> 0) & 0xFF);
- b[4] = (byte)((i2 >>> 24) & 0xFF);
- b[5] = (byte)((i2 >>> 16) & 0xFF);
- b[6] = (byte)((i2 >>> 8) & 0xFF);
- b[7] = (byte)((i2 >>> 0) & 0xFF);
- break;
- case BYTE:
- b[0] = Byte.parseByte(value);
- break;
- case CHAR:
- char c = value.charAt(0);
- b[0] = (byte)((c >>> 8) & 0xFF);
- b[1] = (byte)((c >>> 0) & 0xFF);
- break;
- case BOOLEAN:
- if ( "[true][yes][1][y][on]".indexOf("["+value.toString().toLowerCase()+"]") != -1 )
- b[0] = 1;
- else if ( "[false][no][0][n][off]".indexOf("["+value.toString().toLowerCase()+"]") != -1 )
- b[0] = 0;
- else
- return EmptyValue;
- break;
+ private static final String NAME = "name";
+ private static final String PATTERN = "pattern";
+ private static final String TYPE = "type";
+ private static final String PAGESIZE = "pagesize";
+ private static final String MAXKEYSIZE = "maxkeysize";
+
+ private static final int STRING = 0;
+ private static final int TRIMMED = 1;
+ private static final int INTEGER = 2;
+ private static final int FLOAT = 3;
+ private static final int BYTE = 4;
+ private static final int CHAR = 5;
+ private static final int BOOLEAN = 6;
+
+ private static final int[] sizes = { -1, -1, 8, 8, 1, 2, 1 };
+
+ private static final String STRING_VAL = "string";
+ private static final String TRIMMED_VAL = "trimmed";
+ private static final String SHORT_VAL = "short";
+ private static final String INT_VAL = "int";
+ private static final String LONG_VAL = "long";
+ private static final String FLOAT_VAL = "float";
+ private static final String DOUBLE_VAL = "double";
+ private static final String BYTE_VAL = "byte";
+ private static final String CHAR_VAL = "char";
+ private static final String BOOLEAN_VAL = "boolean";
+
+ private static Log log = LogFactory.getLog("org.apache.xindice.core");
+
+ private Configuration config;
+ private Collection collection;
+ private SymbolTable symbols;
+
+ private String name;
+ private String pattern;
+ private int type;
+ private int typeSize = 32;
+ private boolean wildcard = false;
+
+ private FileHeader fileHeader;
+
+ public ValueIndexer() {
+ super();
+ fileHeader = getFileHeader();
+ fileHeader.setPageSize(1024);
+ }
+
+ public void setConfig(Configuration config) {
+ this.config = config;
+ try {
+ name = config.getAttribute(NAME);
+
+ pattern = config.getAttribute(PATTERN);
+ wildcard = pattern.indexOf('*') != -1;
+
+ // Determine the Index Type
+ String tv = config.getAttribute(TYPE, STRING_VAL).toLowerCase();
+ if (tv.equals(STRING_VAL))
+ type = STRING;
+ else if (tv.equals(TRIMMED_VAL))
+ type = TRIMMED;
+ else if (tv.equals(SHORT_VAL))
+ type = INTEGER;
+ else if (tv.equals(INT_VAL))
+ type = INTEGER;
+ else if (tv.equals(LONG_VAL))
+ type = INTEGER;
+ else if (tv.equals(FLOAT_VAL))
+ type = FLOAT;
+ else if (tv.equals(DOUBLE_VAL))
+ type = FLOAT;
+ else if (tv.equals(BYTE_VAL))
+ type = BYTE;
+ else if (tv.equals(CHAR_VAL))
+ type = CHAR;
+ else if (tv.equals(BOOLEAN_VAL))
+ type = BOOLEAN;
+ else {
+ if (pattern.indexOf('@') != -1)
+ type = STRING;
+ else
+ type = TRIMMED;
}
- return new Value(b);
- }
- catch ( Exception e ) {
- return EmptyValue;
- }
- }
-
- if ( type == TRIMMED )
- value = QueryEngine.normalizeString(value);
-
- return new Value(value);
- }
-
- private Value getCombinedValue(Key key, int pos, int len, short elemID, short attrID) {
- Value result;
- try {
- int l = key.getLength();
- byte[] b = new byte[l+13];
-
- // Write the key
- System.arraycopy(key.getData(), 0, b, 0, l);
- b[l] = 0;
-
- // Write the pos
- b[l+1] = (byte)((pos >>> 24) & 0xFF);
- b[l+2] = (byte)((pos >>> 16) & 0xFF);
- b[l+3] = (byte)((pos >>> 8) & 0xFF);
- b[l+4] = (byte)((pos >>> 0) & 0xFF);
-
- // Write the len
- b[l+5] = (byte)((len >>> 24) & 0xFF);
- b[l+6] = (byte)((len >>> 16) & 0xFF);
- b[l+7] = (byte)((len >>> 8) & 0xFF);
- b[l+8] = (byte)((len >>> 0) & 0xFF);
-
- // Write the elemID
- b[l+9] = (byte)((elemID >>> 8) & 0xFF);
- b[l+10] = (byte)((elemID >>> 0) & 0xFF);
-
- // Write the attrID
- b[l+11] = (byte)((attrID >>> 8) & 0xFF);
- b[l+12] = (byte)((attrID >>> 0) & 0xFF);
-
- result = new Value(b);
- }
- catch ( Exception e ) {
- result = null; // This will never happen
- }
- return result;
- }
-
- private IndexMatch getIndexMatch(Value v) {
- byte[] b = v.getData();
- int l = b.length-13;
- Key key = new Key(b, 0, b.length-13);
-
- int pos = ((b[l+1] << 24) | (b[l+2] << 16) | (b[l+3] << 8) | b[l+4]);
- int len = ((b[l+5] << 24) | (b[l+6] << 16) | (b[l+7] << 8) | b[l+8]);
- short elemID = (short)((b[l+9] << 8) | b[l+10]);
- short attrID = (short)((b[l+11] << 8) | b[l+12]);
-
- return new IndexMatch(key, pos, len, elemID, attrID);
- }
-
- public void remove(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
- Value v = getTypedValue(value);
- if ( type != STRING && type != TRIMMED && v.getLength() == 0 )
- return;
-
- try {
- BTreeRootInfo root = findBTreeRoot(v);
- Value cv = getCombinedValue(key, pos, len, elemID, attrID);
- removeValue(root, cv);
- }
- catch ( DBException e ) {
- throw e;
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- public void add(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
- Value v = getTypedValue(value);
- if ( type != STRING && type != TRIMMED && v.getLength() == 0 )
- return;
-
- try {
- BTreeRootInfo root;
-
- try {
- root = findBTreeRoot(v);
- }
- catch ( BTreeNotFoundException e ) {
- root = createBTreeRoot(v);
- }
-
- Value cv = getCombinedValue(key, pos, len, elemID, attrID);
- addValue(root, cv, MATCH_INFO);
- }
- catch ( DBException e ) {
- throw e;
- }
- catch ( IOException e ) {
- throw new BTreeCorruptException("Corruption detected on add", e);
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- public void flush() throws DBException {
- super.flush();
- }
-
- public IndexMatch[] queryMatches(final IndexQuery query) throws DBException {
- // Pre-process the value-set for typing and trimming
- if ( type != STRING ) {
- Value[] vals = query.getValues();
- for ( int i = 0; i < vals.length; i++ )
- vals[i] = getTypedValue(vals[i].toString());
- }
-
- // Now issue the query
- final List results = new ArrayList();
-
- try {
- query(query, new BTreeCallback() {
- public boolean indexInfo(Value value, long pos) {
- try {
- if ( pos == MATCH_INFO ) {
- IndexMatch match = getIndexMatch(value);
- if ( !wildcard )
- results.add(match);
- else {
- IndexPattern pt = new IndexPattern(symbols, match.getElement(), match.getAttribute());
- if ( pt.getMatchLevel(query.getPattern()) > 0 )
- results.add(match);
- }
- }
- else {
- BTreeRootInfo root = new BTreeRootInfo(value, pos);
- query(root, null, this);
- }
- return true;
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- return true;
+
+ typeSize = sizes[type];
+
+ fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
+ fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
+
+ setLocation(name);
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ public Configuration getConfig() {
+ return config;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setLocation(String location) {
+ setFile(new File(collection.getCollectionRoot(), location + ".idx"));
+ }
+
+ public void setCollection(Collection collection) {
+ try {
+ this.collection = collection;
+ symbols = collection.getSymbols();
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ public String getIndexStyle() {
+ return STYLE_NODEVALUE;
+ }
+
+ public String getPattern() {
+ return pattern;
+ }
+
+ public Value getTypedValue(String value) {
+ if (type != STRING && type != TRIMMED) {
+ value = value.trim();
+
+ if (value.length() == 0)
+ return EmptyValue;
+
+ byte[] b = new byte[typeSize];
+ try {
+ switch (type) {
+ case INTEGER :
+ long l = Long.parseLong(value);
+ b[0] = (byte) ((l >>> 56) & 0xFF);
+ b[1] = (byte) ((l >>> 48) & 0xFF);
+ b[2] = (byte) ((l >>> 40) & 0xFF);
+ b[3] = (byte) ((l >>> 32) & 0xFF);
+ b[4] = (byte) ((l >>> 24) & 0xFF);
+ b[5] = (byte) ((l >>> 16) & 0xFF);
+ b[6] = (byte) ((l >>> 8) & 0xFF);
+ b[7] = (byte) ((l >>> 0) & 0xFF);
+ break;
+ case FLOAT :
+ double d = Double.parseDouble(value);
+ int i1 = (int) Math.round(d);
+ int i2 = (int) Math.round((d - i1) * 1000000000);
+ b[0] = (byte) ((i1 >>> 24) & 0xFF);
+ b[1] = (byte) ((i1 >>> 16) & 0xFF);
+ b[2] = (byte) ((i1 >>> 8) & 0xFF);
+ b[3] = (byte) ((i1 >>> 0) & 0xFF);
+ b[4] = (byte) ((i2 >>> 24) & 0xFF);
+ b[5] = (byte) ((i2 >>> 16) & 0xFF);
+ b[6] = (byte) ((i2 >>> 8) & 0xFF);
+ b[7] = (byte) ((i2 >>> 0) & 0xFF);
+ break;
+ case BYTE :
+ b[0] = Byte.parseByte(value);
+ break;
+ case CHAR :
+ char c = value.charAt(0);
+ b[0] = (byte) ((c >>> 8) & 0xFF);
+ b[1] = (byte) ((c >>> 0) & 0xFF);
+ break;
+ case BOOLEAN :
+ if ("[true][yes][1][y][on]".indexOf("[" + value.toString().toLowerCase() + "]") != -1)
+ b[0] = 1;
+ else if ("[false][no][0][n][off]".indexOf("[" + value.toString().toLowerCase() + "]") != -1)
+ b[0] = 0;
+ else
+ return EmptyValue;
+ break;
+ }
+ return new Value(b);
}
- });
- }
- catch ( IOException e ) {
- throw new BTreeCorruptException("Corruption detected on query", e);
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
+ catch (Exception e) {
+ return EmptyValue;
+ }
+ }
- return (IndexMatch[])results.toArray(EmptyMatches);
- }
-}
+ if (type == TRIMMED)
+ value = QueryEngine.normalizeString(value);
+
+ return new Value(value);
+ }
+ private Value getCombinedValue(Key key, int pos, int len, short elemID, short attrID) {
+ Value result;
+ try {
+ int l = key.getLength();
+ byte[] b = new byte[l + 13];
+
+ // Write the key
+ System.arraycopy(key.getData(), 0, b, 0, l);
+ b[l] = 0;
+
+ // Write the pos
+ b[l + 1] = (byte) ((pos >>> 24) & 0xFF);
+ b[l + 2] = (byte) ((pos >>> 16) & 0xFF);
+ b[l + 3] = (byte) ((pos >>> 8) & 0xFF);
+ b[l + 4] = (byte) ((pos >>> 0) & 0xFF);
+
+ // Write the len
+ b[l + 5] = (byte) ((len >>> 24) & 0xFF);
+ b[l + 6] = (byte) ((len >>> 16) & 0xFF);
+ b[l + 7] = (byte) ((len >>> 8) & 0xFF);
+ b[l + 8] = (byte) ((len >>> 0) & 0xFF);
+
+ // Write the elemID
+ b[l + 9] = (byte) ((elemID >>> 8) & 0xFF);
+ b[l + 10] = (byte) ((elemID >>> 0) & 0xFF);
+
+ // Write the attrID
+ b[l + 11] = (byte) ((attrID >>> 8) & 0xFF);
+ b[l + 12] = (byte) ((attrID >>> 0) & 0xFF);
+
+ result = new Value(b);
+ }
+ catch (Exception e) {
+ result = null; // This will never happen
+ }
+ return result;
+ }
+
+ private IndexMatch getIndexMatch(Value v) {
+ byte[] b = v.getData();
+ int l = b.length - 13;
+ Key key = new Key(b, 0, b.length - 13);
+
+ int pos = ((b[l + 1] << 24) | (b[l + 2] << 16) | (b[l + 3] << 8) | b[l + 4]);
+ int len = ((b[l + 5] << 24) | (b[l + 6] << 16) | (b[l + 7] << 8) | b[l + 8]);
+ short elemID = (short) ((b[l + 9] << 8) | b[l + 10]);
+ short attrID = (short) ((b[l + 11] << 8) | b[l + 12]);
+
+ return new IndexMatch(key, pos, len, elemID, attrID);
+ }
+
+ public void remove(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
+ Value v = getTypedValue(value);
+ if (type != STRING && type != TRIMMED && v.getLength() == 0)
+ return;
+
+ try {
+ BTreeRootInfo root = findBTreeRoot(v);
+ Value cv = getCombinedValue(key, pos, len, elemID, attrID);
+ removeValue(root, cv);
+ }
+ catch (DBException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ public void add(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
+ Value v = getTypedValue(value);
+ if (type != STRING && type != TRIMMED && v.getLength() == 0)
+ return;
+ try {
+ BTreeRootInfo root;
+
+ try {
+ root = findBTreeRoot(v);
+ }
+ catch (BTreeNotFoundException e) {
+ root = createBTreeRoot(v);
+ }
+
+ Value cv = getCombinedValue(key, pos, len, elemID, attrID);
+ addValue(root, cv, MATCH_INFO);
+ }
+ catch (DBException e) {
+ throw e;
+ }
+ catch (IOException e) {
+ throw new BTreeCorruptException("Corruption detected on add", e);
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ public void flush() throws DBException {
+ super.flush();
+ }
+
+ public IndexMatch[] queryMatches(final IndexQuery query) throws DBException {
+ // Pre-process the value-set for typing and trimming
+ if (type != STRING) {
+ Value[] vals = query.getValues();
+ for (int i = 0; i < vals.length; i++)
+ vals[i] = getTypedValue(vals[i].toString());
+ }
+
+ // Now issue the query
+ final List results = new ArrayList();
+
+ try {
+ query(query, new BTreeCallback() {
+ public boolean indexInfo(Value value, long pos) {
+ try {
+ if (pos == MATCH_INFO) {
+ IndexMatch match = getIndexMatch(value);
+ if (!wildcard)
+ results.add(match);
+ else {
+ IndexPattern pt = new IndexPattern(symbols, match.getElement(), match.getAttribute());
+ if (pt.getMatchLevel(query.getPattern()) > 0)
+ results.add(match);
+ }
+ }
+ else {
+ BTreeRootInfo root = new BTreeRootInfo(value, pos);
+ query(root, null, this);
+ }
+ return true;
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ return true;
+ }
+ });
+ }
+ catch (IOException e) {
+ throw new BTreeCorruptException("Corruption detected on query", e);
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+
+ return (IndexMatch[]) results.toArray(EmptyMatches);
+ }
+}
1.8 +925 -938 xml-xindice/java/src/org/apache/xindice/util/Configuration.java
Index: Configuration.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/util/Configuration.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- Configuration.java 22 Nov 2002 10:15:35 -0000 1.7
+++ Configuration.java 15 Jul 2003 15:44:36 -0000 1.8
@@ -59,14 +59,19 @@
* $Id$
*/
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.w3c.dom.*;
-
import java.util.ArrayList;
import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
/**
* Configuration is a utility class that allows Configurable objects to
* easily manage configuration information in a simple and consistent
@@ -76,64 +81,64 @@
*/
public final class Configuration {
- private static final Configuration[] EmptySet = new Configuration[0];
+ private static final Configuration[] EmptySet = new Configuration[0];
// commented out 2002-07-16: not used
//private static final Map Modified = Collections.synchronizedMap(new HashMap()); // Temporary HACK
- private static Log log = LogFactory.getLog("org.apache.xindice.util");
+ private static Log log = LogFactory.getLog("org.apache.xindice.util");
- private Element config = null;
- private boolean readOnly = true;
+ private Element config = null;
+ private boolean readOnly = true;
- public Configuration(Element config, boolean readOnly) {
- this.config = config;
- this.readOnly = readOnly;
- }
-
- public Configuration(Document config, boolean readOnly) {
- this(config.getDocumentElement(), readOnly);
- }
-
- public Configuration(Element config) {
- this(config, true);
- }
-
- public Configuration(Document config) {
- this(config.getDocumentElement());
- }
-
- /**
- * getElement returns the Element being managed by this
- * Configuration.
- *
- * @return The Configuration Element
- * @throws ReadOnlyException If the Configuration is Read-only
- */
- public Element getElement() throws ReadOnlyException {
- if ( readOnly )
- throw new ReadOnlyException();
- return config;
- }
-
- /**
- * getName returns the name of the Configuration node.
- *
- * @return The Node name
- */
- public String getName() {
- return config.getNodeName();
- }
-
- /**
- * hasAttributes returns whether or not the Configuration node has any
- * attributes associated with it.
- *
- * @return Whether or not attributes exist
- */
- public boolean hasAttributes() {
- return config.getAttributes().getLength() > 0;
- }
+ public Configuration(Element config, boolean readOnly) {
+ this.config = config;
+ this.readOnly = readOnly;
+ }
+
+ public Configuration(Document config, boolean readOnly) {
+ this(config.getDocumentElement(), readOnly);
+ }
+
+ public Configuration(Element config) {
+ this(config, true);
+ }
+
+ public Configuration(Document config) {
+ this(config.getDocumentElement());
+ }
+
+ /**
+ * getElement returns the Element being managed by this
+ * Configuration.
+ *
+ * @return The Configuration Element
+ * @throws ReadOnlyException If the Configuration is Read-only
+ */
+ public Element getElement() throws ReadOnlyException {
+ if (readOnly)
+ throw new ReadOnlyException();
+ return config;
+ }
+
+ /**
+ * getName returns the name of the Configuration node.
+ *
+ * @return The Node name
+ */
+ public String getName() {
+ return config.getNodeName();
+ }
+
+ /**
+ * hasAttributes returns whether or not the Configuration node has any
+ * attributes associated with it.
+ *
+ * @return Whether or not attributes exist
+ */
+ public boolean hasAttributes() {
+ return config.getAttributes().getLength() > 0;
+ }
/*
// commented out 2002-07-16: not doing anything
@@ -142,884 +147,866 @@
}
*/
- /**
- * getAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @param defValue The default value
- * @return The attribute value
- */
- public String getAttribute(String name, String defValue) {
- String value = config.getAttribute(name);
- if ( value == null || value.length() == 0 )
- value = defValue;
- return value;
- }
-
- /**
- * getAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @return The attribute value
- */
- public String getAttribute(String name) {
- return getAttribute(name, "");
- }
-
- /**
- * getBooleanAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @param defValue The default value
- * @return The attribute value
- */
- public boolean getBooleanAttribute(String name, boolean defValue) {
- try {
- return "[true][yes][1][y][on]".indexOf("["+getAttribute(name, defValue ? "1" : "0").toLowerCase()+"]") != -1;
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getBooleanAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @return The attribute value
- */
- public boolean getBooleanAttribute(String name) {
- return getBooleanAttribute(name, false);
- }
-
- /**
- * getIntAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @param defValue The default value
- * @return The attribute value
- */
- public int getIntAttribute(String name, int defValue) {
- try {
- return Integer.parseInt(config.getAttribute(name));
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getIntAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @return The attribute value
- */
- public int getIntAttribute(String name) {
- return getIntAttribute(name, 0);
- }
-
- /**
- * getShortAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @param defValue The default value
- * @return The attribute value
- */
- public short getShortAttribute(String name, short defValue) {
- try {
- return Short.parseShort(config.getAttribute(name));
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getShortAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @return The attribute value
- */
- public short getShortAttribute(String name) {
- return getShortAttribute(name, (short)0);
- }
-
- /**
- * getLongAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @param defValue The default value
- * @return The attribute value
- */
- public long getLongAttribute(String name, long defValue) {
- try {
- return Long.parseLong(config.getAttribute(name));
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getLongAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @return The attribute value
- */
- public long getLongAttribute(String name) {
- return getLongAttribute(name, (long)0);
- }
-
- /**
- * getFloatAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @param defValue The default value
- * @return The attribute value
- */
- public float getFloatAttribute(String name, float defValue) {
- try {
- return Float.parseFloat(config.getAttribute(name));
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getFloatAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @return The attribute value
- */
- public float getFloatAttribute(String name) {
- return getFloatAttribute(name, (float)0.0);
- }
-
- /**
- * getDoubleAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @param defValue The default value
- * @return The attribute value
- */
- public double getDoubleAttribute(String name, double defValue) {
- try {
- return Double.parseDouble(config.getAttribute(name));
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getDoubleAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @return The attribute value
- */
- public double getDoubleAttribute(String name) {
- return getDoubleAttribute(name, (double)0.0);
- }
-
- /**
- * getByteAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @param defValue The default value
- * @return The attribute value
- */
- public byte getByteAttribute(String name, byte defValue) {
- try {
- return Byte.parseByte(config.getAttribute(name));
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getByteAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @return The attribute value
- */
- public byte getByteAttribute(String name) {
- return getByteAttribute(name, (byte)0);
- }
-
- /**
- * getCharAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @param defValue The default value
- * @return The attribute value
- */
- public char getCharAttribute(String name, char defValue) {
- try {
- return config.getAttribute(name).charAt(0);
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getCharAttribute returns an attribute from the Configuration node.
- *
- * @param name The attribute name
- * @return The attribute value
- */
- public char getCharAttribute(String name) {
- return getCharAttribute(name, '\0');
- }
-
- /**
- * listAttributes returns a list of the attribute names that exist for
- * this Configuration node.
- *
- * @return The Attribute names
- */
- public String[] listAttributes() {
- NamedNodeMap map = config.getAttributes();
- String[] result = new String[map.getLength()];
- int size = map.getLength();
- for ( int i = 0; i < size; i++ )
- result[i] = ((Attr)map.item(i)).getName();
- return result;
- }
-
- /**
- * hasValue returns whether or not the Configuration node has a textual
- * value associated with it.
- *
- * @return Whether or not the node has a text value
- */
- public boolean hasValue() {
- NodeList list = config.getChildNodes();
- return ( list.getLength() > 0 && list.item(0).getNodeType() == Node.TEXT_NODE );
- }
-
- /**
- * getValue returns the value from the Configuration node.
- *
- * @param defValue The default value
- * @return The value
- */
- public String getValue(String defValue) {
- NodeList list = config.getChildNodes();
- if ( list.getLength() == 1 && list.item(0).getNodeType() == Node.TEXT_NODE )
- return list.item(0).getNodeValue();
- else
- return defValue;
- }
-
- /**
- * getValue returns the value from the Configuration node.
- *
- * @return The value
- */
- public String getValue() {
- return getValue("");
- }
-
- /**
- * getBooleanValue returns the value from the Configuration node.
- *
- * @param defValue The default value
- * @return The value
- */
- public boolean getBooleanValue(boolean defValue) {
- try {
- return "[true][yes][1][y][on]".indexOf("["+getValue().toLowerCase()+"]") != -1;
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getBooleanValue returns the value from the Configuration node.
- *
- * @return The value
- */
- public boolean getBooleanValue() {
- return getBooleanValue(false);
- }
-
- /**
- * getIntValue returns the value from the Configuration node.
- *
- * @param defValue The default value
- * @return The value
- */
- public int getIntValue(int defValue) {
- try {
- return Integer.parseInt(getValue());
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getIntValue returns the value from the Configuration node.
- *
- * @return The value
- */
- public int getIntValue() {
- return getIntValue(0);
- }
-
- /**
- * getShortValue returns the value from the Configuration node.
- *
- * @param defValue The default value
- * @return The value
- */
- public short getShortValue(short defValue) {
- try {
- return Short.parseShort(getValue());
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getShortValue returns the value from the Configuration node.
- *
- * @return The value
- */
- public short getShortValue() {
- return getShortValue((short)0);
- }
-
- /**
- * getLongValue returns the value from the Configuration node.
- *
- * @param defValue The default value
- * @return The value
- */
- public long getLongValue(long defValue) {
- try {
- return Long.parseLong(getValue());
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getLongValue returns the value from the Configuration node.
- *
- * @return The value
- */
- public long getLongValue() {
- return getLongValue(0);
- }
-
- /**
- * getFloatValue returns the value from the Configuration node.
- *
- * @param defValue The default value
- * @return The value
- */
- public float getFloatValue(float defValue) {
- try {
- return Float.parseFloat(getValue());
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getFloatValue returns the value from the Configuration node.
- *
- * @return The value
- */
- public float getFloatValue() {
- return getFloatValue((float)0.0);
- }
-
- /**
- * getDoubleValue returns the value from the Configuration node.
- *
- * @param defValue The default value
- * @return The value
- */
- public double getDoubleValue(double defValue) {
- try {
- return Double.parseDouble(getValue());
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getDoubleValue returns the value from the Configuration node.
- *
- * @return The value
- */
- public double getDoubleValue() {
- return getDoubleValue((double)0.0);
- }
-
- /**
- * getByteValue returns the value from the Configuration node.
- *
- * @param defValue The default value
- * @return The value
- */
- public byte getByteValue(byte defValue) {
- try {
- return Byte.parseByte(getValue());
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getByteValue returns the value from the Configuration node.
- *
- * @return The value
- */
- public byte getByteValue() {
- return getByteValue((byte)0);
- }
-
- /**
- * getCharValue returns the value from the Configuration node.
- *
- * @param defValue The default value
- * @return The value
- */
- public char getCharValue(char defValue) {
- try {
- return getValue().charAt(0);
- }
- catch ( Exception e ) {
- return defValue;
- }
- }
-
- /**
- * getCharValue returns the value from the Configuration node.
- *
- * @return The value
- */
- public char getCharValue() {
- return getCharValue('\0');
- }
-
-
-
-
-
-
- /**
- * hasChildren returns whether or not the Configuration node has child
- * Configuration elements.
- *
- * @return Whether or not children exist
- */
- public boolean hasChildren() {
- NodeList list = config.getChildNodes();
- int size = list.getLength();
- for ( int i = 0; i < size; i++ )
- if ( list.item(i).getNodeType() == Node.ELEMENT_NODE )
- return true;
- return false;
- }
-
- /**
- * getChildren returns the child Configuration nodes for this Configuration
- * node.
- *
- * @return The children
- */
- public Configuration[] getChildren() {
- NodeList list = config.getChildNodes();
- if ( list == null )
- return EmptySet;
- List tmp = new ArrayList();
- int size = list.getLength();
- for ( int i = 0; i < size; i++ )
- if ( list.item(i).getNodeType() == Node.ELEMENT_NODE )
- tmp.add(new Configuration((Element)list.item(i), readOnly));
- return (Configuration[])tmp.toArray(EmptySet);
- }
-
- /**
- * processChildren runs through the children of this Configuration and
- * performs prcessing callbacks to the ConfigurationCallback object.
- *
- * @param callback The callback object
- */
- public void processChildren(ConfigurationCallback callback) {
- NodeList list = config.getChildNodes();
- if ( list == null )
- return;
- int size = list.getLength();
- try {
- for ( int i = 0; i < size; i++ )
- if ( list.item(i).getNodeType() == Node.ELEMENT_NODE )
- callback.process(new Configuration((Element)list.item(i), readOnly));
- }
- catch (Exception e) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- /**
- * processChildren runs through the children of this Configuration and
- * performs prcessing callbacks to the ConfigurationCallback object.
- *
- * @param callback The callback object
- * @param name The Configuration name to process
- */
- public void processChildren(String name, ConfigurationCallback callback) {
- NodeList list = config.getChildNodes();
- if ( list == null )
- return;
-
- Node[] nl = new Node[list.getLength()];
- for ( int i = 0; i < nl.length; i++ )
- nl[i] = list.item(i);
-
- int size = nl.length;
-
- try {
- for ( int i = 0; i < size; i++ )
- if ( nl[i].getNodeType() == Node.ELEMENT_NODE && nl[i].getNodeName().equals(name))
- callback.process(new Configuration((Element)nl[i], readOnly));
- }
- catch (Exception e) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- /**
- * getChild returns the first child Configuration node that matches the
- * specified name.
- *
- * @param name The Configuration node name
- * @param create Create Configuration if it doesn't exist
- * @return The child Configuration
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public Configuration getChild(String name, boolean create) throws ReadOnlyException {
- NodeList list = config.getChildNodes();
- int size = list.getLength();
-
- for ( int i = 0; i < size; i++ )
- if ( list.item(i).getNodeType() == Node.ELEMENT_NODE && list.item(i).getNodeName().equals(name) )
- return new Configuration((Element)list.item(i), readOnly);
- if ( create )
- return add(name);
- else
- return null;
- }
-
- /**
- * getChild returns the first child Configuration node that matches the
- * specified name.
- *
- * @param name The Configuration node name
- * @return The child Configuration
- */
- public Configuration getChild(String name) {
- try {
- return getChild(name, false);
- }
- catch( Exception e ) {
- return null;
- }
- }
-
-
-
- /**
- * isReadOnly returns whether or not this Configuration node is a
- * read-only node.
- *
- * @return The read-only status
- */
- public boolean isReadOnly() {
- return readOnly;
- }
-
- /**
- * add adds a new Configuration node to this Configuration node.
- *
- * @param name The name of the Configuration node
- * @return The new Configuration node
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public Configuration add(String name) throws ReadOnlyException {
- if ( readOnly )
- throw new ReadOnlyException();
- Element elem = config.getOwnerDocument().createElement(name);
- config.appendChild(elem);
- //setDirty();
- return new Configuration(elem, readOnly);
- }
-
- /**
- * add adds an existing Configuration node to this Configuration node.
- * Note! This method does NOT perform a deep copy on the DOM Node that
- * newConfig manages.
- *
- * @param newConfig The Configuration node to add
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void add(Configuration newConfig) throws ReadOnlyException {
- if ( readOnly )
- throw new ReadOnlyException();
- Node imported = config.getOwnerDocument().importNode(newConfig.config, true);
- config.appendChild(imported);
- newConfig.config = (Element)imported;
- //setDirty();
- }
-
- /**
- * delete deletes this Configuration node from its parent Configuration.
- *
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void delete() throws ReadOnlyException {
- if ( readOnly )
- throw new ReadOnlyException();
- if ( config.getParentNode() != null )
- config.getParentNode().removeChild(config);
- //setDirty();
- }
-
- /**
- * removeAttribute removes the named attribute from this Configuration.
- *
- * @param name The attribute name
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void removeAttribute(String name) throws ReadOnlyException {
- if ( readOnly )
- throw new ReadOnlyException();
- config.removeAttribute(name);
- //setDirty();
- }
-
-
-
-
- /**
- * setAttribute sets the attribute value for this Configuration.
- *
- * @param name The attribute name
- * @param value The attribute value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setAttribute(String name, String value) throws ReadOnlyException {
- if ( readOnly )
- throw new ReadOnlyException();
- config.setAttribute(name, value);
- //setDirty();
- }
-
- /**
- * setAttribute sets the attribute value for this Configuration.
- *
- * @param name The attribute name
- * @param value The attribute value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setAttribute(String name, boolean value) throws ReadOnlyException {
- setAttribute( name, String.valueOf( value ) );
- }
-
- /**
- * setAttribute sets the attribute value for this Configuration.
- *
- * @param name The attribute name
- * @param value The attribute value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setAttribute(String name, int value) throws ReadOnlyException {
- setAttribute( name, String.valueOf( value ) );
- }
-
- /**
- * setAttribute sets the attribute value for this Configuration.
- *
- * @param name The attribute name
- * @param value The attribute value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setAttribute(String name, short value) throws ReadOnlyException {
- setAttribute( name, String.valueOf( value ) );
- }
-
- /**
- * setAttribute sets the attribute value for this Configuration.
- *
- * @param name The attribute name
- * @param value The attribute value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setAttribute(String name, long value) throws ReadOnlyException {
- setAttribute( name, String.valueOf( value ) );
- }
-
- /**
- * setAttribute sets the attribute value for this Configuration.
- *
- * @param name The attribute name
- * @param value The attribute value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setAttribute(String name, float value) throws ReadOnlyException {
- setAttribute( name, String.valueOf( value ) );
- }
-
- /**
- * setAttribute sets the attribute value for this Configuration.
- *
- * @param name The attribute name
- * @param value The attribute value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setAttribute(String name, double value) throws ReadOnlyException {
- setAttribute( name, String.valueOf( value ) );
- }
-
- /**
- * setAttribute sets the attribute value for this Configuration.
- *
- * @param name The attribute name
- * @param value The attribute value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setAttribute(String name, byte value) throws ReadOnlyException {
- setAttribute( name, String.valueOf( value ) );
- }
-
- /**
- * setAttribute sets the attribute value for this Configuration.
- *
- * @param name The attribute name
- * @param value The attribute value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setAttribute(String name, char value) throws ReadOnlyException {
- setAttribute( name, String.valueOf( value ) );
- }
-
-
-
-
- /**
- * setValue sets the value of the Configuration node.
- *
- * @param value The New Value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setValue(String value) throws ReadOnlyException {
- if ( readOnly )
- throw new ReadOnlyException();
- NodeList list = config.getChildNodes();
- if ( list.getLength() == 1 && list.item(0).getNodeType() == Node.TEXT_NODE )
- list.item(0).setNodeValue(value);
- else {
- Text text = config.getOwnerDocument().createTextNode(value);
- config.appendChild(text);
- }
- //setDirty();
- }
-
- /**
- * setValue sets the value of the Configuration node.
- *
- * @param value The New Value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setValue(boolean value) throws ReadOnlyException {
- setValue( String.valueOf( value ) );
- }
-
- /**
- * setValue sets the value of the Configuration node.
- *
- * @param value The New Value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setValue(int value) throws ReadOnlyException {
- setValue(String.valueOf(value));
- }
-
- /**
- * setValue sets the value of the Configuration node.
- *
- * @param value The New Value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setValue(short value) throws ReadOnlyException {
- setValue(String.valueOf(value));
- }
-
- /**
- * setValue sets the value of the Configuration node.
- *
- * @param value The New Value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setValue(long value) throws ReadOnlyException {
- setValue(String.valueOf(value));
- }
-
- /**
- * setValue sets the value of the Configuration node.
- *
- * @param value The New Value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setValue(float value) throws ReadOnlyException {
- setValue(String.valueOf(value));
- }
-
- /**
- * setValue sets the value of the Configuration node.
- *
- * @param value The New Value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setValue(double value) throws ReadOnlyException {
- setValue(String.valueOf(value));
- }
-
- /**
- * setValue sets the value of the Configuration node.
- *
- * @param value The New Value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setValue(byte value) throws ReadOnlyException {
- setValue(String.valueOf(value));
- }
-
- /**
- * setValue sets the value of the Configuration node.
- *
- * @param value The New Value
- * @throws ReadOnlyException if the Configuration is read-only
- */
- public void setValue(char value) throws ReadOnlyException {
- setValue(String.valueOf(value));
- }
+ /**
+ * getAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @param defValue The default value
+ * @return The attribute value
+ */
+ public String getAttribute(String name, String defValue) {
+ String value = config.getAttribute(name);
+ if (value == null || value.length() == 0)
+ value = defValue;
+ return value;
+ }
+
+ /**
+ * getAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @return The attribute value
+ */
+ public String getAttribute(String name) {
+ return getAttribute(name, "");
+ }
+
+ /**
+ * getBooleanAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @param defValue The default value
+ * @return The attribute value
+ */
+ public boolean getBooleanAttribute(String name, boolean defValue) {
+ try {
+ return "[true][yes][1][y][on]".indexOf("[" + getAttribute(name, defValue ? "1" : "0").toLowerCase() + "]") != -1;
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getBooleanAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @return The attribute value
+ */
+ public boolean getBooleanAttribute(String name) {
+ return getBooleanAttribute(name, false);
+ }
+
+ /**
+ * getIntAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @param defValue The default value
+ * @return The attribute value
+ */
+ public int getIntAttribute(String name, int defValue) {
+ try {
+ return Integer.parseInt(config.getAttribute(name));
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getIntAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @return The attribute value
+ */
+ public int getIntAttribute(String name) {
+ return getIntAttribute(name, 0);
+ }
+
+ /**
+ * getShortAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @param defValue The default value
+ * @return The attribute value
+ */
+ public short getShortAttribute(String name, short defValue) {
+ try {
+ return Short.parseShort(config.getAttribute(name));
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getShortAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @return The attribute value
+ */
+ public short getShortAttribute(String name) {
+ return getShortAttribute(name, (short) 0);
+ }
+
+ /**
+ * getLongAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @param defValue The default value
+ * @return The attribute value
+ */
+ public long getLongAttribute(String name, long defValue) {
+ try {
+ return Long.parseLong(config.getAttribute(name));
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getLongAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @return The attribute value
+ */
+ public long getLongAttribute(String name) {
+ return getLongAttribute(name, (long) 0);
+ }
+
+ /**
+ * getFloatAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @param defValue The default value
+ * @return The attribute value
+ */
+ public float getFloatAttribute(String name, float defValue) {
+ try {
+ return Float.parseFloat(config.getAttribute(name));
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getFloatAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @return The attribute value
+ */
+ public float getFloatAttribute(String name) {
+ return getFloatAttribute(name, (float) 0.0);
+ }
+
+ /**
+ * getDoubleAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @param defValue The default value
+ * @return The attribute value
+ */
+ public double getDoubleAttribute(String name, double defValue) {
+ try {
+ return Double.parseDouble(config.getAttribute(name));
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getDoubleAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @return The attribute value
+ */
+ public double getDoubleAttribute(String name) {
+ return getDoubleAttribute(name, (double) 0.0);
+ }
+
+ /**
+ * getByteAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @param defValue The default value
+ * @return The attribute value
+ */
+ public byte getByteAttribute(String name, byte defValue) {
+ try {
+ return Byte.parseByte(config.getAttribute(name));
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getByteAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @return The attribute value
+ */
+ public byte getByteAttribute(String name) {
+ return getByteAttribute(name, (byte) 0);
+ }
+
+ /**
+ * getCharAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @param defValue The default value
+ * @return The attribute value
+ */
+ public char getCharAttribute(String name, char defValue) {
+ try {
+ return config.getAttribute(name).charAt(0);
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getCharAttribute returns an attribute from the Configuration node.
+ *
+ * @param name The attribute name
+ * @return The attribute value
+ */
+ public char getCharAttribute(String name) {
+ return getCharAttribute(name, '\0');
+ }
+
+ /**
+ * listAttributes returns a list of the attribute names that exist for
+ * this Configuration node.
+ *
+ * @return The Attribute names
+ */
+ public String[] listAttributes() {
+ NamedNodeMap map = config.getAttributes();
+ String[] result = new String[map.getLength()];
+ int size = map.getLength();
+ for (int i = 0; i < size; i++)
+ result[i] = ((Attr) map.item(i)).getName();
+ return result;
+ }
+
+ /**
+ * hasValue returns whether or not the Configuration node has a textual
+ * value associated with it.
+ *
+ * @return Whether or not the node has a text value
+ */
+ public boolean hasValue() {
+ NodeList list = config.getChildNodes();
+ return (list.getLength() > 0 && list.item(0).getNodeType() == Node.TEXT_NODE);
+ }
+
+ /**
+ * getValue returns the value from the Configuration node.
+ *
+ * @param defValue The default value
+ * @return The value
+ */
+ public String getValue(String defValue) {
+ NodeList list = config.getChildNodes();
+ if (list.getLength() == 1 && list.item(0).getNodeType() == Node.TEXT_NODE)
+ return list.item(0).getNodeValue();
+ else
+ return defValue;
+ }
+
+ /**
+ * getValue returns the value from the Configuration node.
+ *
+ * @return The value
+ */
+ public String getValue() {
+ return getValue("");
+ }
+
+ /**
+ * getBooleanValue returns the value from the Configuration node.
+ *
+ * @param defValue The default value
+ * @return The value
+ */
+ public boolean getBooleanValue(boolean defValue) {
+ try {
+ return "[true][yes][1][y][on]".indexOf("[" + getValue().toLowerCase() + "]") != -1;
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getBooleanValue returns the value from the Configuration node.
+ *
+ * @return The value
+ */
+ public boolean getBooleanValue() {
+ return getBooleanValue(false);
+ }
+
+ /**
+ * getIntValue returns the value from the Configuration node.
+ *
+ * @param defValue The default value
+ * @return The value
+ */
+ public int getIntValue(int defValue) {
+ try {
+ return Integer.parseInt(getValue());
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getIntValue returns the value from the Configuration node.
+ *
+ * @return The value
+ */
+ public int getIntValue() {
+ return getIntValue(0);
+ }
+
+ /**
+ * getShortValue returns the value from the Configuration node.
+ *
+ * @param defValue The default value
+ * @return The value
+ */
+ public short getShortValue(short defValue) {
+ try {
+ return Short.parseShort(getValue());
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getShortValue returns the value from the Configuration node.
+ *
+ * @return The value
+ */
+ public short getShortValue() {
+ return getShortValue((short) 0);
+ }
+
+ /**
+ * getLongValue returns the value from the Configuration node.
+ *
+ * @param defValue The default value
+ * @return The value
+ */
+ public long getLongValue(long defValue) {
+ try {
+ return Long.parseLong(getValue());
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getLongValue returns the value from the Configuration node.
+ *
+ * @return The value
+ */
+ public long getLongValue() {
+ return getLongValue(0);
+ }
+
+ /**
+ * getFloatValue returns the value from the Configuration node.
+ *
+ * @param defValue The default value
+ * @return The value
+ */
+ public float getFloatValue(float defValue) {
+ try {
+ return Float.parseFloat(getValue());
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getFloatValue returns the value from the Configuration node.
+ *
+ * @return The value
+ */
+ public float getFloatValue() {
+ return getFloatValue((float) 0.0);
+ }
+
+ /**
+ * getDoubleValue returns the value from the Configuration node.
+ *
+ * @param defValue The default value
+ * @return The value
+ */
+ public double getDoubleValue(double defValue) {
+ try {
+ return Double.parseDouble(getValue());
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getDoubleValue returns the value from the Configuration node.
+ *
+ * @return The value
+ */
+ public double getDoubleValue() {
+ return getDoubleValue((double) 0.0);
+ }
+
+ /**
+ * getByteValue returns the value from the Configuration node.
+ *
+ * @param defValue The default value
+ * @return The value
+ */
+ public byte getByteValue(byte defValue) {
+ try {
+ return Byte.parseByte(getValue());
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getByteValue returns the value from the Configuration node.
+ *
+ * @return The value
+ */
+ public byte getByteValue() {
+ return getByteValue((byte) 0);
+ }
+
+ /**
+ * getCharValue returns the value from the Configuration node.
+ *
+ * @param defValue The default value
+ * @return The value
+ */
+ public char getCharValue(char defValue) {
+ try {
+ return getValue().charAt(0);
+ }
+ catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ /**
+ * getCharValue returns the value from the Configuration node.
+ *
+ * @return The value
+ */
+ public char getCharValue() {
+ return getCharValue('\0');
+ }
+
+ /**
+ * hasChildren returns whether or not the Configuration node has child
+ * Configuration elements.
+ *
+ * @return Whether or not children exist
+ */
+ public boolean hasChildren() {
+ NodeList list = config.getChildNodes();
+ int size = list.getLength();
+ for (int i = 0; i < size; i++)
+ if (list.item(i).getNodeType() == Node.ELEMENT_NODE)
+ return true;
+ return false;
+ }
+
+ /**
+ * getChildren returns the child Configuration nodes for this Configuration
+ * node.
+ *
+ * @return The children
+ */
+ public Configuration[] getChildren() {
+ NodeList list = config.getChildNodes();
+ if (list == null)
+ return EmptySet;
+ List tmp = new ArrayList();
+ int size = list.getLength();
+ for (int i = 0; i < size; i++)
+ if (list.item(i).getNodeType() == Node.ELEMENT_NODE)
+ tmp.add(new Configuration((Element) list.item(i), readOnly));
+ return (Configuration[]) tmp.toArray(EmptySet);
+ }
+
+ /**
+ * processChildren runs through the children of this Configuration and
+ * performs prcessing callbacks to the ConfigurationCallback object.
+ *
+ * @param callback The callback object
+ */
+ public void processChildren(ConfigurationCallback callback) {
+ NodeList list = config.getChildNodes();
+ if (list == null)
+ return;
+ int size = list.getLength();
+ try {
+ for (int i = 0; i < size; i++)
+ if (list.item(i).getNodeType() == Node.ELEMENT_NODE)
+ callback.process(new Configuration((Element) list.item(i), readOnly));
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ /**
+ * processChildren runs through the children of this Configuration and
+ * performs prcessing callbacks to the ConfigurationCallback object.
+ *
+ * @param callback The callback object
+ * @param name The Configuration name to process
+ */
+ public void processChildren(String name, ConfigurationCallback callback) {
+ NodeList list = config.getChildNodes();
+ if (list == null)
+ return;
+
+ Node[] nl = new Node[list.getLength()];
+ for (int i = 0; i < nl.length; i++)
+ nl[i] = list.item(i);
+
+ int size = nl.length;
+
+ try {
+ for (int i = 0; i < size; i++)
+ if (nl[i].getNodeType() == Node.ELEMENT_NODE && nl[i].getNodeName().equals(name))
+ callback.process(new Configuration((Element) nl[i], readOnly));
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ /**
+ * getChild returns the first child Configuration node that matches the
+ * specified name.
+ *
+ * @param name The Configuration node name
+ * @param create Create Configuration if it doesn't exist
+ * @return The child Configuration
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public Configuration getChild(String name, boolean create) throws ReadOnlyException {
+ NodeList list = config.getChildNodes();
+ int size = list.getLength();
+
+ for (int i = 0; i < size; i++)
+ if (list.item(i).getNodeType() == Node.ELEMENT_NODE && list.item(i).getNodeName().equals(name))
+ return new Configuration((Element) list.item(i), readOnly);
+ if (create)
+ return add(name);
+ else
+ return null;
+ }
+
+ /**
+ * getChild returns the first child Configuration node that matches the
+ * specified name.
+ *
+ * @param name The Configuration node name
+ * @return The child Configuration
+ */
+ public Configuration getChild(String name) {
+ try {
+ return getChild(name, false);
+ }
+ catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * isReadOnly returns whether or not this Configuration node is a
+ * read-only node.
+ *
+ * @return The read-only status
+ */
+ public boolean isReadOnly() {
+ return readOnly;
+ }
+
+ /**
+ * add adds a new Configuration node to this Configuration node.
+ *
+ * @param name The name of the Configuration node
+ * @return The new Configuration node
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public Configuration add(String name) throws ReadOnlyException {
+ if (readOnly)
+ throw new ReadOnlyException();
+ Element elem = config.getOwnerDocument().createElement(name);
+ config.appendChild(elem);
+ //setDirty();
+ return new Configuration(elem, readOnly);
+ }
+
+ /**
+ * add adds an existing Configuration node to this Configuration node.
+ * Note! This method does NOT perform a deep copy on the DOM Node that
+ * newConfig manages.
+ *
+ * @param newConfig The Configuration node to add
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void add(Configuration newConfig) throws ReadOnlyException {
+ if (readOnly)
+ throw new ReadOnlyException();
+ Node imported = config.getOwnerDocument().importNode(newConfig.config, true);
+ config.appendChild(imported);
+ newConfig.config = (Element) imported;
+ //setDirty();
+ }
+
+ /**
+ * delete deletes this Configuration node from its parent Configuration.
+ *
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void delete() throws ReadOnlyException {
+ if (readOnly)
+ throw new ReadOnlyException();
+ if (config.getParentNode() != null)
+ config.getParentNode().removeChild(config);
+ //setDirty();
+ }
+
+ /**
+ * removeAttribute removes the named attribute from this Configuration.
+ *
+ * @param name The attribute name
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void removeAttribute(String name) throws ReadOnlyException {
+ if (readOnly)
+ throw new ReadOnlyException();
+ config.removeAttribute(name);
+ //setDirty();
+ }
+
+ /**
+ * setAttribute sets the attribute value for this Configuration.
+ *
+ * @param name The attribute name
+ * @param value The attribute value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setAttribute(String name, String value) throws ReadOnlyException {
+ if (readOnly)
+ throw new ReadOnlyException();
+ config.setAttribute(name, value);
+ //setDirty();
+ }
+
+ /**
+ * setAttribute sets the attribute value for this Configuration.
+ *
+ * @param name The attribute name
+ * @param value The attribute value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setAttribute(String name, boolean value) throws ReadOnlyException {
+ setAttribute(name, String.valueOf(value));
+ }
+
+ /**
+ * setAttribute sets the attribute value for this Configuration.
+ *
+ * @param name The attribute name
+ * @param value The attribute value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setAttribute(String name, int value) throws ReadOnlyException {
+ setAttribute(name, String.valueOf(value));
+ }
+
+ /**
+ * setAttribute sets the attribute value for this Configuration.
+ *
+ * @param name The attribute name
+ * @param value The attribute value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setAttribute(String name, short value) throws ReadOnlyException {
+ setAttribute(name, String.valueOf(value));
+ }
+
+ /**
+ * setAttribute sets the attribute value for this Configuration.
+ *
+ * @param name The attribute name
+ * @param value The attribute value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setAttribute(String name, long value) throws ReadOnlyException {
+ setAttribute(name, String.valueOf(value));
+ }
+
+ /**
+ * setAttribute sets the attribute value for this Configuration.
+ *
+ * @param name The attribute name
+ * @param value The attribute value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setAttribute(String name, float value) throws ReadOnlyException {
+ setAttribute(name, String.valueOf(value));
+ }
+
+ /**
+ * setAttribute sets the attribute value for this Configuration.
+ *
+ * @param name The attribute name
+ * @param value The attribute value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setAttribute(String name, double value) throws ReadOnlyException {
+ setAttribute(name, String.valueOf(value));
+ }
+
+ /**
+ * setAttribute sets the attribute value for this Configuration.
+ *
+ * @param name The attribute name
+ * @param value The attribute value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setAttribute(String name, byte value) throws ReadOnlyException {
+ setAttribute(name, String.valueOf(value));
+ }
+
+ /**
+ * setAttribute sets the attribute value for this Configuration.
+ *
+ * @param name The attribute name
+ * @param value The attribute value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setAttribute(String name, char value) throws ReadOnlyException {
+ setAttribute(name, String.valueOf(value));
+ }
+
+ /**
+ * setValue sets the value of the Configuration node.
+ *
+ * @param value The New Value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setValue(String value) throws ReadOnlyException {
+ if (readOnly)
+ throw new ReadOnlyException();
+ NodeList list = config.getChildNodes();
+ if (list.getLength() == 1 && list.item(0).getNodeType() == Node.TEXT_NODE)
+ list.item(0).setNodeValue(value);
+ else {
+ Text text = config.getOwnerDocument().createTextNode(value);
+ config.appendChild(text);
+ }
+ //setDirty();
+ }
+
+ /**
+ * setValue sets the value of the Configuration node.
+ *
+ * @param value The New Value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setValue(boolean value) throws ReadOnlyException {
+ setValue(String.valueOf(value));
+ }
+
+ /**
+ * setValue sets the value of the Configuration node.
+ *
+ * @param value The New Value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setValue(int value) throws ReadOnlyException {
+ setValue(String.valueOf(value));
+ }
+
+ /**
+ * setValue sets the value of the Configuration node.
+ *
+ * @param value The New Value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setValue(short value) throws ReadOnlyException {
+ setValue(String.valueOf(value));
+ }
+
+ /**
+ * setValue sets the value of the Configuration node.
+ *
+ * @param value The New Value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setValue(long value) throws ReadOnlyException {
+ setValue(String.valueOf(value));
+ }
+
+ /**
+ * setValue sets the value of the Configuration node.
+ *
+ * @param value The New Value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setValue(float value) throws ReadOnlyException {
+ setValue(String.valueOf(value));
+ }
+
+ /**
+ * setValue sets the value of the Configuration node.
+ *
+ * @param value The New Value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setValue(double value) throws ReadOnlyException {
+ setValue(String.valueOf(value));
+ }
+
+ /**
+ * setValue sets the value of the Configuration node.
+ *
+ * @param value The New Value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setValue(byte value) throws ReadOnlyException {
+ setValue(String.valueOf(value));
+ }
+
+ /**
+ * setValue sets the value of the Configuration node.
+ *
+ * @param value The New Value
+ * @throws ReadOnlyException if the Configuration is read-only
+ */
+ public void setValue(char value) throws ReadOnlyException {
+ setValue(String.valueOf(value));
+ }
}
-
1.10 +432 -443 xml-xindice/java/src/org/apache/xindice/core/request/URIMapper.java
Index: URIMapper.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/request/URIMapper.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- URIMapper.java 19 Nov 2002 05:16:58 -0000 1.9
+++ URIMapper.java 15 Jul 2003 15:44:36 -0000 1.10
@@ -59,6 +59,15 @@
* $Id$
*/
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.xindice.core.Collection;
import org.apache.xindice.core.Container;
import org.apache.xindice.core.DBException;
@@ -68,18 +77,7 @@
import org.apache.xindice.util.Poolable;
import org.apache.xindice.util.XindiceException;
import org.apache.xindice.xml.TextWriter;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.w3c.dom.*;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.Properties;
+import org.w3c.dom.Document;
/**
* URIMapper maps a URI (from whence it came) to a Xindice object. Xindice
@@ -90,443 +88,434 @@
public final class URIMapper extends URLConnection implements Poolable {
- public static final int UNKNOWN = -1;
- public static final int APPLICATION = 1;
- public static final int COLLECTION = 2;
- public static final int DOCUMENT = 3;
+ public static final int UNKNOWN = -1;
+ public static final int APPLICATION = 1;
+ public static final int COLLECTION = 2;
+ public static final int DOCUMENT = 3;
public static final String DEFAULT_ENCODING = "UTF-8";
- private static Log log = LogFactory.getLog("org.apache.xindice.core");
-
- private ObjectPool pool = null;
- private String uri = null;
- private int type = 0;
-
- private byte[] buf = null;
- private int pos = 0;
- private char lastChar = 0;
-
- private Database db = null;
- private Collection collection = null;
- private Document document = null;
- private String method = null;
- private Container container = null;
+ private static Log log = LogFactory.getLog("org.apache.xindice.core");
- private Properties params = null;
- private String[] args = null;
-
- private String urlresult = null; // Holds the value of the URL resolution results (XML doc or XMLObject call results )
- private boolean inputstreamset = false; // Flag to tell if the input stream has been initialized
-
- /** Constructor for creating URIMapper instance using a standard URL
- */
- public URIMapper(URL u) {
- super(u);
- try {
- setURI(u.toString());
- }
- catch ( Exception e) {
- // Put error code here!
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- /** Constructor for older URIMapper instances
- */
- public URIMapper(String uri) throws XindiceException {
- super(null);
- setURI(uri);
- }
-
- /** Constructor for older URIMapper instances
- */
- public URIMapper() {
- super(null);
- }
-
- /**
- Opens a communications link to the resource referenced by this URL,
- if such a connection has not already been established.
- */
- public void connect() {
- this.connected=true;
- }
-
- /**
- Returns an input stream that reads from this open connection.
- */
- public InputStream getInputStream() throws IOException {
-
- String output = null ;
-
- // Check if the inputstream has already been initialized, if not do now, else return the contents of urlresult
- if ( ! inputstreamset ) {
- try {
- switch ( type ) {
-
- case URIMapper.DOCUMENT:
- output = TextWriter.toString( getDocument() );
- break;
-
- default:
- // Document type not found, output error message
- throw new Exception("Content type unsupported");
+ private ObjectPool pool = null;
+ private String uri = null;
+ private int type = 0;
+
+ private byte[] buf = null;
+ private int pos = 0;
+ private char lastChar = 0;
+
+ private Database db = null;
+ private Collection collection = null;
+ private Document document = null;
+ private String method = null;
+ private Container container = null;
+
+ private Properties params = null;
+ private String[] args = null;
+
+ private String urlresult = null; // Holds the value of the URL resolution results (XML doc or XMLObject call results )
+ private boolean inputstreamset = false; // Flag to tell if the input stream has been initialized
+
+ /** Constructor for creating URIMapper instance using a standard URL
+ */
+ public URIMapper(URL u) {
+ super(u);
+ try {
+ setURI(u.toString());
+ }
+ catch (Exception e) {
+ // Put error code here!
+ log.warn(e);
+ }
+ }
+
+ /** Constructor for older URIMapper instances
+ */
+ public URIMapper(String uri) throws XindiceException {
+ super(null);
+ setURI(uri);
+ }
+
+ /** Constructor for older URIMapper instances
+ */
+ public URIMapper() {
+ super(null);
+ }
+
+ /**
+ Opens a communications link to the resource referenced by this URL,
+ if such a connection has not already been established.
+ */
+ public void connect() {
+ this.connected = true;
+ }
+
+ /**
+ Returns an input stream that reads from this open connection.
+ */
+ public InputStream getInputStream() throws IOException {
+
+ String output = null;
+
+ // Check if the inputstream has already been initialized, if not do now, else return the contents of urlresult
+ if (!inputstreamset) {
+ try {
+ switch (type) {
+
+ case URIMapper.DOCUMENT :
+ output = TextWriter.toString(getDocument());
+ break;
+
+ default :
+ // Document type not found, output error message
+ throw new Exception("Content type unsupported");
+ }
}
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
+ catch (Exception e) {
+ log.warn(e);
}
- }
- }
- // Inputstream already initialized, set output to be value of urlresult
- else {
- output=urlresult ;
- }
-
- // Save the value of output into local variable urlresult
- urlresult = output ;
- // Set inpustreamset flag to signal that url has already been resolved
- inputstreamset = true ;
-
- // Send the result to the client, sending blank string if NULL
- if ( output == null) {
- return new ByteArrayInputStream( new byte[0] );
- } else {
- return new ByteArrayInputStream( output.getBytes( DEFAULT_ENCODING ) );
- }
- }
-
- /**
- * Returns the value of the content-encoding header field.
- * Returns:
- * the content encoding of the resource that the URL references, or null if not known.
- */
- public String getContentEncoding() {
- return DEFAULT_ENCODING;
- }
-
- /**
- * Returns the value of the content-type header field.
- * Returns:
- * the content type of the resource that the URL references, or null if not known.
- */
- public String getContentType() {
- // Return the docuement's content type, for now this can only be "text/xml"
- return new String("text/xml");
- }
-
- /**
- * Returns the value of the content-length header field.
- * Returns:
- * the content length of the resource that this connection's URL references, or -1 if the content length is not known.
- */
- public int getContentLength() {
- // Check to see if this document has already been resolved, if not call getInputStream
- if ( ! inputstreamset ) {
- try {
- this.getInputStream();
- }
- catch ( IOException e ) {
- return 0;
- }
- }
-
- // Return the lenght of this document/XMLObject call
- return urlresult.length();
- }
-
- /**
- * Returns the value of the last-modified header field. The result is the number of milliseconds since January 1, 1970 GMT.
- * Returns:
- * the date the resource referenced by this URLConnection was last modified, or 0 if not known.
- */
- public long getLastModified() {
- // For now this functionality is not available, return 0
- return 0 ;
- }
-
- public void setPool(ObjectPool pool) {
- this.pool = pool;
- }
-
- public void reclaim() {
- reset();
- if ( pool != null )
- pool.putObject(this);
- }
-
- /**
- * reset resets the state of the URIMapper.
- */
- private void reset() {
- type = UNKNOWN;
- lastChar = 0;
- method = "";
- db = null;
- collection = null;
- document = null;
- params = null;
- args = null;
- container = null;
-
- // reset urlresult and inputstreamset
- urlresult = null ;
- inputstreamset = false ;
- }
-
- /**
- * setURI sets the URI for the URIMapper and parses it. The parsed
- * components of a URI can be retrieved using getObjectType and any
- * of the get<component> methods.
- *
- * @param uri The URI
- */
- public void setURI(String uri) throws XindiceException {
- this.uri = uri;
- reset();
- parse();
- }
-
- /**
- * parseName parses an identifier up to any of the specified delimiters.
- *
- * @param delims The delimiters to use
- * @return The parsed name
- */
- private String parseName(String delims) {
- int start = pos;
- while ( pos < buf.length ) {
- lastChar = (char)buf[pos++];
- if ( delims.indexOf(lastChar) != -1 )
- break;
- }
- if ( pos == buf.length && delims.indexOf(lastChar) == -1 )
- pos++;
- return pos > start ? new String(buf, start, pos-start-1)
- : "";
- }
-
- /**
- * parseParams parses a parameter set and produces either a Properties or
- * String[] Object representing those parameters.
- */
- private void parseParams() {
- if ( lastChar == '?' ) {
- // Query String param list
- params = new Properties();
- String name;
- String value;
- String temp;
- while ( true ) {
- name = parseName("=");
- if ( name.length() == 0 )
- break;
- value = parseName("?&;");
- temp = params.getProperty(name);
- if( temp != null ) {
- StringBuffer sb = new StringBuffer(32);
- sb.append(temp);
- sb.append('\u0001');
- sb.append(value);
- value = sb.toString();
+ }
+ // Inputstream already initialized, set output to be value of urlresult
+ else {
+ output = urlresult;
+ }
+
+ // Save the value of output into local variable urlresult
+ urlresult = output;
+ // Set inpustreamset flag to signal that url has already been resolved
+ inputstreamset = true;
+
+ // Send the result to the client, sending blank string if NULL
+ if (output == null) {
+ return new ByteArrayInputStream(new byte[0]);
+ }
+ else {
+ return new ByteArrayInputStream(output.getBytes(DEFAULT_ENCODING));
+ }
+ }
+
+ /**
+ * Returns the value of the content-encoding header field.
+ * Returns:
+ * the content encoding of the resource that the URL references, or null if not known.
+ */
+ public String getContentEncoding() {
+ return DEFAULT_ENCODING;
+ }
+
+ /**
+ * Returns the value of the content-type header field.
+ * Returns:
+ * the content type of the resource that the URL references, or null if not known.
+ */
+ public String getContentType() {
+ // Return the docuement's content type, for now this can only be "text/xml"
+ return new String("text/xml");
+ }
+
+ /**
+ * Returns the value of the content-length header field.
+ * Returns:
+ * the content length of the resource that this connection's URL references, or -1 if the content length is not known.
+ */
+ public int getContentLength() {
+ // Check to see if this document has already been resolved, if not call getInputStream
+ if (!inputstreamset) {
+ try {
+ this.getInputStream();
}
- params.setProperty(name, value);
- }
- }
- else
- params = new Properties();
- }
-
- /**
- * parse parses the URI.
- */
- private void parse() throws XindiceException {
- buf = uri.getBytes();
- pos = 0;
- String tmp;
-
- if ( buf.length == 0 ) {
- throw new DBException(FaultCodes.URI_EMPTY);
- }
-
- // TODO: Be Able To Handle Remote URIs
- if ( (char)buf[0] != '/' ) {
- parseName(":"); // Ignore Protocol
- parseName("/"); // Ignore Slash
- parseName("/"); // Ignore Slash
- parseName("/:"); // Ignore Host (For Now)
- if ( lastChar == ':' )
- parseName("/"); // Ignore Port
- }
- else
- pos = 1;
-
- // Database check
- tmp = parseName("/");
- if ( tmp == null )
- return;
-
- db = Database.getDatabase(tmp);
- if ( db == null )
- return;
-
- type = APPLICATION;
- tmp = parseName("/(?");
-
-
- int objType = getParsedObjectType(db, tmp);
- // If unknown then this URI just points to db and we're done.
- // Otherwise we need to keep walking down the URI.
- if (objType != UNKNOWN) {
- type = walkURI(db, tmp, objType);
- }
-
- if ( lastChar == '?' ) {
- parseParams();
- return;
- }
- }
-
- /**
- * Recursive method to handle the parse of the URI and setup the instance
- * objects.
- */
- protected int walkURI(Collection col, String name, int objType)
- throws XindiceException {
- switch (objType) {
- case DOCUMENT:
- container = col.getContainer(name);
- document = container.getDocument();
- return DOCUMENT;
-
- case COLLECTION:
- Collection c = col.getCollection(name);
- if ( c != null ) {
- collection = c;
- String tmp = parseName("/(?");
- // If we have another name recurse to handle it.
- if (! tmp.equals("")) {
- return walkURI(c, tmp, getParsedObjectType(c, tmp));
- }
-
- return COLLECTION;
+ catch (IOException e) {
+ return 0;
}
- }
+ }
- return UNKNOWN;
- }
-
- /**
- * Determine the type of object. If more then one object has the same name
- * the order of precedence is COLLECTION - XMLOBJECT - DOCUMENT
- */
- protected int getParsedObjectType(Collection col, String name)
- throws XindiceException {
-
- if (col.getCollection(name) != null) {
- return COLLECTION;
- }
- else if ((col.getFiler() != null) && (col.getContainer(name) != null)) {
- return DOCUMENT;
- }
- else {
- return UNKNOWN;
- }
- }
-
- /**
- * getObjectType returns the type of Object that was identified in the
- * parsing of the URI. This method will return one of the following
- * values: UNKNOWN, APPLICATION, DATABASE, COLLECTION, DOCUMENT or
- * XMLOBJECT.
- *
- * @return The object type
- */
- public int getObjectType() {
- return type;
- }
-
- /**
- * getDatabase returns the Database that was resolved in the
- * parsing of this URI.
- *
- * @return The Database
- */
- public Database getDatabase() {
- return db;
- }
-
- /**
- * getCollection returns the Collection object that was resolved in the
- * parsing of the URI. If no Collection was resolved, this method will
- * return null.
- *
- * @return The Collection
- */
- public Collection getCollection() {
- return collection;
- }
-
- /**
- * getDocument returns the Document object that was resolved in the
- * parsing of the URI. If no Document was resolved, this method will
- * return null.
- *
- * @return The Document
- */
- public Document getDocument() {
- return document;
- }
-
- /**
- * getContainer returns the Document Container that was resolved in
- * the parsing of the URI. If no Container was resolved, this method
- * will return null.
- *
- * @return The Container
- */
- public Container getContainer() {
- return container;
- }
-
- /**
- * getMethod returns the method name that was resolved in the parsing
- * of the URI. Method names are associated with XMLObjects.
- * If no method name was resolved, this method will return null.
- *
- * @return The method name
- */
- public String getMethod() {
- return method;
- }
-
- /**
- * getProperties returns the Properties object that was produced in
- * parsing the URI's Query String. Properties are passed into methods
- * that are associated with XMLObjects. This method will return null if
- * no Properties were resolved.
- *
- * @return The Query String Properties
- */
- public Properties getProperties() {
- return params;
- }
-
- /**
- * getArguments returns method arguments in the form of a String array.
- * Method arguments are passed to a method in the order that they are
- * specified in the URI. If no arguments were parsed, this method will
- * return null.
- *
- * @return The method arguments
- */
- public String[] getArguments() {
- return args;
- }
+ // Return the lenght of this document/XMLObject call
+ return urlresult.length();
+ }
+
+ /**
+ * Returns the value of the last-modified header field. The result is the number of milliseconds since January 1, 1970 GMT.
+ * Returns:
+ * the date the resource referenced by this URLConnection was last modified, or 0 if not known.
+ */
+ public long getLastModified() {
+ // For now this functionality is not available, return 0
+ return 0;
+ }
+
+ public void setPool(ObjectPool pool) {
+ this.pool = pool;
+ }
+
+ public void reclaim() {
+ reset();
+ if (pool != null)
+ pool.putObject(this);
+ }
+
+ /**
+ * reset resets the state of the URIMapper.
+ */
+ private void reset() {
+ type = UNKNOWN;
+ lastChar = 0;
+ method = "";
+ db = null;
+ collection = null;
+ document = null;
+ params = null;
+ args = null;
+ container = null;
+
+ // reset urlresult and inputstreamset
+ urlresult = null;
+ inputstreamset = false;
+ }
+
+ /**
+ * setURI sets the URI for the URIMapper and parses it. The parsed
+ * components of a URI can be retrieved using getObjectType and any
+ * of the get<component> methods.
+ *
+ * @param uri The URI
+ */
+ public void setURI(String uri) throws XindiceException {
+ this.uri = uri;
+ reset();
+ parse();
+ }
+
+ /**
+ * parseName parses an identifier up to any of the specified delimiters.
+ *
+ * @param delims The delimiters to use
+ * @return The parsed name
+ */
+ private String parseName(String delims) {
+ int start = pos;
+ while (pos < buf.length) {
+ lastChar = (char) buf[pos++];
+ if (delims.indexOf(lastChar) != -1)
+ break;
+ }
+ if (pos == buf.length && delims.indexOf(lastChar) == -1)
+ pos++;
+ return pos > start ? new String(buf, start, pos - start - 1) : "";
+ }
+
+ /**
+ * parseParams parses a parameter set and produces either a Properties or
+ * String[] Object representing those parameters.
+ */
+ private void parseParams() {
+ if (lastChar == '?') {
+ // Query String param list
+ params = new Properties();
+ String name;
+ String value;
+ String temp;
+ while (true) {
+ name = parseName("=");
+ if (name.length() == 0)
+ break;
+ value = parseName("?&;");
+ temp = params.getProperty(name);
+ if (temp != null) {
+ StringBuffer sb = new StringBuffer(32);
+ sb.append(temp);
+ sb.append('\u0001');
+ sb.append(value);
+ value = sb.toString();
+ }
+ params.setProperty(name, value);
+ }
+ }
+ else
+ params = new Properties();
+ }
+
+ /**
+ * parse parses the URI.
+ */
+ private void parse() throws XindiceException {
+ buf = uri.getBytes();
+ pos = 0;
+ String tmp;
+
+ if (buf.length == 0) {
+ throw new DBException(FaultCodes.URI_EMPTY);
+ }
+
+ // TODO: Be Able To Handle Remote URIs
+ if ((char) buf[0] != '/') {
+ parseName(":"); // Ignore Protocol
+ parseName("/"); // Ignore Slash
+ parseName("/"); // Ignore Slash
+ parseName("/:"); // Ignore Host (For Now)
+ if (lastChar == ':')
+ parseName("/"); // Ignore Port
+ }
+ else
+ pos = 1;
+
+ // Database check
+ tmp = parseName("/");
+ if (tmp == null)
+ return;
+
+ db = Database.getDatabase(tmp);
+ if (db == null)
+ return;
+
+ type = APPLICATION;
+ tmp = parseName("/(?");
+
+ int objType = getParsedObjectType(db, tmp);
+ // If unknown then this URI just points to db and we're done.
+ // Otherwise we need to keep walking down the URI.
+ if (objType != UNKNOWN) {
+ type = walkURI(db, tmp, objType);
+ }
+
+ if (lastChar == '?') {
+ parseParams();
+ return;
+ }
+ }
+
+ /**
+ * Recursive method to handle the parse of the URI and setup the instance
+ * objects.
+ */
+ protected int walkURI(Collection col, String name, int objType) throws XindiceException {
+ switch (objType) {
+ case DOCUMENT :
+ container = col.getContainer(name);
+ document = container.getDocument();
+ return DOCUMENT;
+
+ case COLLECTION :
+ Collection c = col.getCollection(name);
+ if (c != null) {
+ collection = c;
+ String tmp = parseName("/(?");
+ // If we have another name recurse to handle it.
+ if (!tmp.equals("")) {
+ return walkURI(c, tmp, getParsedObjectType(c, tmp));
+ }
+
+ return COLLECTION;
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ /**
+ * Determine the type of object. If more then one object has the same name
+ * the order of precedence is COLLECTION - XMLOBJECT - DOCUMENT
+ */
+ protected int getParsedObjectType(Collection col, String name) throws XindiceException {
+
+ if (col.getCollection(name) != null) {
+ return COLLECTION;
+ }
+ else if ((col.getFiler() != null) && (col.getContainer(name) != null)) {
+ return DOCUMENT;
+ }
+ else {
+ return UNKNOWN;
+ }
+ }
+
+ /**
+ * getObjectType returns the type of Object that was identified in the
+ * parsing of the URI. This method will return one of the following
+ * values: UNKNOWN, APPLICATION, DATABASE, COLLECTION, DOCUMENT or
+ * XMLOBJECT.
+ *
+ * @return The object type
+ */
+ public int getObjectType() {
+ return type;
+ }
+
+ /**
+ * getDatabase returns the Database that was resolved in the
+ * parsing of this URI.
+ *
+ * @return The Database
+ */
+ public Database getDatabase() {
+ return db;
+ }
+
+ /**
+ * getCollection returns the Collection object that was resolved in the
+ * parsing of the URI. If no Collection was resolved, this method will
+ * return null.
+ *
+ * @return The Collection
+ */
+ public Collection getCollection() {
+ return collection;
+ }
+
+ /**
+ * getDocument returns the Document object that was resolved in the
+ * parsing of the URI. If no Document was resolved, this method will
+ * return null.
+ *
+ * @return The Document
+ */
+ public Document getDocument() {
+ return document;
+ }
+
+ /**
+ * getContainer returns the Document Container that was resolved in
+ * the parsing of the URI. If no Container was resolved, this method
+ * will return null.
+ *
+ * @return The Container
+ */
+ public Container getContainer() {
+ return container;
+ }
+
+ /**
+ * getMethod returns the method name that was resolved in the parsing
+ * of the URI. Method names are associated with XMLObjects.
+ * If no method name was resolved, this method will return null.
+ *
+ * @return The method name
+ */
+ public String getMethod() {
+ return method;
+ }
+
+ /**
+ * getProperties returns the Properties object that was produced in
+ * parsing the URI's Query String. Properties are passed into methods
+ * that are associated with XMLObjects. This method will return null if
+ * no Properties were resolved.
+ *
+ * @return The Query String Properties
+ */
+ public Properties getProperties() {
+ return params;
+ }
+
+ /**
+ * getArguments returns method arguments in the form of a String array.
+ * Method arguments are passed to a method in the order that they are
+ * specified in the URI. If no arguments were parsed, this method will
+ * return null.
+ *
+ * @return The method arguments
+ */
+ public String[] getArguments() {
+ return args;
+ }
}
-
-
1.4 +281 -287 xml-xindice/java/src/org/apache/xindice/core/query/QueryEngine.java
Index: QueryEngine.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/query/QueryEngine.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- QueryEngine.java 31 Oct 2002 06:59:58 -0000 1.3
+++ QueryEngine.java 15 Jul 2003 15:44:36 -0000 1.4
@@ -59,6 +59,15 @@
* $Id$
*/
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.xindice.core.Collection;
import org.apache.xindice.core.DBException;
import org.apache.xindice.core.Database;
@@ -71,16 +80,6 @@
import org.apache.xindice.util.XindiceException;
import org.apache.xindice.xml.NamespaceMap;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
/**
* QueryEngine is the Xindice Query Engine. Its purpose is to orchestrate
* query operations against the Xindice repository. The QueryEngine
@@ -89,293 +88,288 @@
*/
public class QueryEngine extends SimpleConfigurable {
- private static final String[] EmptyStrings = new String[0];
- private static final Key[] EmptyKeys = new Key[0];
+ private static final String[] EmptyStrings = new String[0];
+ private static final Key[] EmptyKeys = new Key[0];
- private static final String RESOLVER = "resolver";
- private static final String CLASS = "class";
+ private static final String RESOLVER = "resolver";
+ private static final String CLASS = "class";
- private static Log log = LogFactory.getLog("org.apache.xindice.core");
+ private static Log log = LogFactory.getLog("org.apache.xindice.core");
- private Database db;
- private Map resolvers = new HashMap();
+ private Database db;
+ private Map resolvers = new HashMap();
- public QueryEngine(Database db) {
- this.db = db;
- }
+ public QueryEngine(Database db) {
+ this.db = db;
+ }
- public void setConfig(Configuration config) throws XindiceException {
- super.setConfig(config);
- config.processChildren(RESOLVER,
- new ConfigurationCallback() {
+ public void setConfig(Configuration config) throws XindiceException {
+ super.setConfig(config);
+ config.processChildren(RESOLVER, new ConfigurationCallback() {
public void process(Configuration cfg) {
- String className = cfg.getAttribute(CLASS);
- try {
- QueryResolver res = (QueryResolver)Class.forName(className).newInstance();
- res.setConfig(cfg);
- res.setQueryEngine(QueryEngine.this);
- resolvers.put(res.getQueryStyle(), res);
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
+ String className = cfg.getAttribute(CLASS);
+ try {
+ QueryResolver res = (QueryResolver) Class.forName(className).newInstance();
+ res.setConfig(cfg);
+ res.setQueryEngine(QueryEngine.this);
+ resolvers.put(res.getQueryStyle(), res);
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
}
- });
- }
+ });
+ }
- public Database getDatabase() {
- return db;
- }
-
- /**
- * listStyles returns a list of styles supported by the
- * QueryEngine (ex: XPath, XUpdate)
- *
- * @return The supported styles
- */
- public String[] listStyles() {
- return (String[])resolvers.keySet().toArray(EmptyStrings);
- }
-
- private QueryResolver getResolver(String style) throws QueryException {
- QueryResolver res = (QueryResolver)resolvers.get(style);
- if ( res == null )
- throw new StyleNotFoundException("No Resolver available for '"+style+"' queries");
- return res;
- }
-
- /**
- * query performs the specified query and returns a NodeSet with
- * any possible results from that query. The query is performed
- * in the context of a Collection.
- *
- * @param col The Collection context
- * @param style The query style (XPath, Fulltext, etc...)
- * @param query The Query
- * @param nsMap The namespace Map (if any)
- * @param keys The initial Key set to use (if any)
- * @return A NodeSet with the query results
- */
- public NodeSet query(Collection col, String style, String query, NamespaceMap nsMap, Key[] keys) throws DBException, QueryException {
- QueryResolver res = getResolver(style);
- return res.query(col, query, nsMap, keys);
- }
-
- /**
- * compileQuery compiles a Query against the specified Collection
- * context and returns the compiled Query. This DOES NOT actually
- * run the query, merely just parses it and primes any possible
- * Indexers that the query might need.
- *
- * @param col The Collection context
- * @param style The query style (XPath, Fulltext, etc...)
- * @param query The Query
- * @param nsMap The namespace Map (if any)
- * @param keys The initial Key set to use (if any)
- * @return The compiled Query
- */
- public Query compileQuery(Collection col, String style, String query, NamespaceMap nsMap, Key[] keys) throws DBException, QueryException {
- QueryResolver res = getResolver(style);
- return res.compileQuery(col, query, nsMap, keys);
- }
-
-
- // Utility methods
-
- /**
- * getUniqueKeys takes a set of IndexMatch objects and extracts
- * all of its unique Keys in sorted order.
- *
- * @param matches The Match Set
- * @return The unique Keys in order
- */
- public static Key[] getUniqueKeys(IndexMatch[] matches) {
- SortedSet set = new TreeSet();
- for ( int i = 0; i < matches.length; i++ )
- set.add(matches[i].getKey());
- return (Key[])set.toArray(EmptyKeys);
- }
-
- /**
- * andKeySets takes several sets of unique Keys and returns the
- * ANDed set (elements that exist in all sets). The first dimension
- * of the array holds the individual sets, the second holds the
- * actual Keys.
- *
- * @param keySets 2-dimensional set of Keys
- * @return The ANDed set of Keys in order
- */
- public static Key[] andKeySets(Key[][] keySets) {
- int[] ptrs;
-
- if ( keySets.length == 0 )
- return EmptyKeys;
- else if ( keySets.length == 1 )
- return keySets[0];
- else {
- ptrs = new int[keySets.length];
- for ( int i = 0; i < keySets.length; i++ )
- if ( keySets[i].length == 0 )
- return EmptyKeys;
- else
- ptrs[i] = 0;
- }
-
- SortedSet set = new TreeSet();
- boolean done = false;
- List highs = new ArrayList();
- Key highest = null;
- while ( !done ) {
- boolean eq = true;
-
- for ( int i = 0; i < ptrs.length; i++ ) {
- Key comp = keySets[i][ptrs[i]];
- if ( highest == null ) {
- highest = comp;
- highs.add(new Integer(i));
+ public Database getDatabase() {
+ return db;
+ }
+
+ /**
+ * listStyles returns a list of styles supported by the
+ * QueryEngine (ex: XPath, XUpdate)
+ *
+ * @return The supported styles
+ */
+ public String[] listStyles() {
+ return (String[]) resolvers.keySet().toArray(EmptyStrings);
+ }
+
+ private QueryResolver getResolver(String style) throws QueryException {
+ QueryResolver res = (QueryResolver) resolvers.get(style);
+ if (res == null)
+ throw new StyleNotFoundException("No Resolver available for '" + style + "' queries");
+ return res;
+ }
+
+ /**
+ * query performs the specified query and returns a NodeSet with
+ * any possible results from that query. The query is performed
+ * in the context of a Collection.
+ *
+ * @param col The Collection context
+ * @param style The query style (XPath, Fulltext, etc...)
+ * @param query The Query
+ * @param nsMap The namespace Map (if any)
+ * @param keys The initial Key set to use (if any)
+ * @return A NodeSet with the query results
+ */
+ public NodeSet query(Collection col, String style, String query, NamespaceMap nsMap, Key[] keys) throws DBException, QueryException {
+ QueryResolver res = getResolver(style);
+ return res.query(col, query, nsMap, keys);
+ }
+
+ /**
+ * compileQuery compiles a Query against the specified Collection
+ * context and returns the compiled Query. This DOES NOT actually
+ * run the query, merely just parses it and primes any possible
+ * Indexers that the query might need.
+ *
+ * @param col The Collection context
+ * @param style The query style (XPath, Fulltext, etc...)
+ * @param query The Query
+ * @param nsMap The namespace Map (if any)
+ * @param keys The initial Key set to use (if any)
+ * @return The compiled Query
+ */
+ public Query compileQuery(Collection col, String style, String query, NamespaceMap nsMap, Key[] keys) throws DBException, QueryException {
+ QueryResolver res = getResolver(style);
+ return res.compileQuery(col, query, nsMap, keys);
+ }
+
+ // Utility methods
+
+ /**
+ * getUniqueKeys takes a set of IndexMatch objects and extracts
+ * all of its unique Keys in sorted order.
+ *
+ * @param matches The Match Set
+ * @return The unique Keys in order
+ */
+ public static Key[] getUniqueKeys(IndexMatch[] matches) {
+ SortedSet set = new TreeSet();
+ for (int i = 0; i < matches.length; i++)
+ set.add(matches[i].getKey());
+ return (Key[]) set.toArray(EmptyKeys);
+ }
+
+ /**
+ * andKeySets takes several sets of unique Keys and returns the
+ * ANDed set (elements that exist in all sets). The first dimension
+ * of the array holds the individual sets, the second holds the
+ * actual Keys.
+ *
+ * @param keySets 2-dimensional set of Keys
+ * @return The ANDed set of Keys in order
+ */
+ public static Key[] andKeySets(Key[][] keySets) {
+ int[] ptrs;
+
+ if (keySets.length == 0)
+ return EmptyKeys;
+ else if (keySets.length == 1)
+ return keySets[0];
+ else {
+ ptrs = new int[keySets.length];
+ for (int i = 0; i < keySets.length; i++)
+ if (keySets[i].length == 0)
+ return EmptyKeys;
+ else
+ ptrs[i] = 0;
+ }
+
+ SortedSet set = new TreeSet();
+ boolean done = false;
+ List highs = new ArrayList();
+ Key highest = null;
+ while (!done) {
+ boolean eq = true;
+
+ for (int i = 0; i < ptrs.length; i++) {
+ Key comp = keySets[i][ptrs[i]];
+ if (highest == null) {
+ highest = comp;
+ highs.add(new Integer(i));
+ }
+ else {
+ int c = highest.compareTo(comp);
+ if (c != 0)
+ eq = false;
+ if (c < 0) {
+ highest = comp;
+ highs.clear();
+ highs.add(new Integer(i));
+ }
+ else if (c == 0)
+ highs.add(new Integer(i));
+ }
}
- else {
- int c = highest.compareTo(comp);
- if ( c != 0 )
- eq = false;
- if ( c < 0 ) {
- highest = comp;
- highs.clear();
- highs.add(new Integer(i));
- }
- else if ( c == 0 )
- highs.add(new Integer(i));
+ if (eq) {
+ set.add(highest);
+ highs.clear();
+ highest = null;
+ }
+ for (int i = 0; i < ptrs.length; i++) {
+ if (!highs.contains(new Integer(i)))
+ ptrs[i]++;
+ if (ptrs[i] >= keySets[i].length)
+ done = true;
}
- }
- if ( eq ) {
- set.add(highest);
- highs.clear();
- highest = null;
- }
- for ( int i = 0; i < ptrs.length; i++ ) {
- if ( !highs.contains(new Integer(i)) )
- ptrs[i]++;
- if ( ptrs[i] >= keySets[i].length )
- done = true;
- }
- if ( !eq )
- highs.clear();
- }
-
- return (Key[])set.toArray(EmptyKeys);
- }
-
- /**
- * orKeySets takes several sets of unique Keys and returns the
- * ORed set (all unique elements). The first dimension of the
- * array holds the individual sets, the second holds the actual
- * Keys.
- *
- * @param keySets 2-dimensional set of Keys
- * @return The ORed set of Keys in order
- */
- public static Key[] orKeySets(Key[][] keySets) {
- if ( keySets.length == 0 )
- return EmptyKeys;
- else if ( keySets.length == 1 )
- return keySets[0];
- else if ( keySets.length == 2 ) {
- // Optimization since most ORs will be 2 sets only
- if ( keySets[1].length == 0 )
+ if (!eq)
+ highs.clear();
+ }
+
+ return (Key[]) set.toArray(EmptyKeys);
+ }
+
+ /**
+ * orKeySets takes several sets of unique Keys and returns the
+ * ORed set (all unique elements). The first dimension of the
+ * array holds the individual sets, the second holds the actual
+ * Keys.
+ *
+ * @param keySets 2-dimensional set of Keys
+ * @return The ORed set of Keys in order
+ */
+ public static Key[] orKeySets(Key[][] keySets) {
+ if (keySets.length == 0)
+ return EmptyKeys;
+ else if (keySets.length == 1)
return keySets[0];
- else if ( keySets[0].length == 0 )
- return keySets[1];
- }
-
- SortedSet set = new TreeSet();
-
- for ( int i = 0; i < keySets.length; i++ )
- for ( int j = 0; j < keySets[i].length; j++ )
- set.add(keySets[i][j]);
-
- return (Key[])set.toArray(EmptyKeys);
- }
-
- /**
- * normalizeString normalizes the specific String by stripping
- * all leading, trailing, and continuous runs of white space.
- *
- * @param value The value to normalize
- * @return The result
- */
- public static String normalizeString(String value) {
- char[] c = value.toCharArray();
- char[] n = new char[c.length];
- boolean white = true;
- int pos = 0;
- for ( int i = 0; i < c.length; i++ ) {
- if ( " \t\n\r".indexOf(c[i]) != -1 ) {
- if ( !white ) {
- n[pos++] = ' ';
- white = true;
+ else if (keySets.length == 2) {
+ // Optimization since most ORs will be 2 sets only
+ if (keySets[1].length == 0)
+ return keySets[0];
+ else if (keySets[0].length == 0)
+ return keySets[1];
+ }
+
+ SortedSet set = new TreeSet();
+
+ for (int i = 0; i < keySets.length; i++)
+ for (int j = 0; j < keySets[i].length; j++)
+ set.add(keySets[i][j]);
+
+ return (Key[]) set.toArray(EmptyKeys);
+ }
+
+ /**
+ * normalizeString normalizes the specific String by stripping
+ * all leading, trailing, and continuous runs of white space.
+ *
+ * @param value The value to normalize
+ * @return The result
+ */
+ public static String normalizeString(String value) {
+ char[] c = value.toCharArray();
+ char[] n = new char[c.length];
+ boolean white = true;
+ int pos = 0;
+ for (int i = 0; i < c.length; i++) {
+ if (" \t\n\r".indexOf(c[i]) != -1) {
+ if (!white) {
+ n[pos++] = ' ';
+ white = true;
+ }
}
- }
- else {
- n[pos++] = c[i];
- white = false;
- }
- }
- if ( white && pos > 0 )
- pos--;
- return new String(n, 0, pos);
- }
-
- /**
- * expandEntities expands the String's pre-defined XML entities
- * (<, >, etc...) into their actual character representations.
- *
- * @param value The value to expand entities for
- * @return The expanded String
- */
- public static String expandEntities(String value) {
- int idx = value.indexOf('&');
- if ( idx == -1 )
- return value;
-
- StringBuffer sb = new StringBuffer(value.length());
- int pos = 0;
- while ( pos < value.length() ) {
- if ( idx != -1 ) {
- if ( idx > pos )
- sb.append(value.substring(pos, idx));
-
- int end = value.indexOf(';', idx)+1;
- if ( end == 0 )
- // Some sort of error
- return value;
-
- String token = value.substring(idx+1, end-1);
- if ( token.equals("apos") )
- sb.append("'");
- else if ( token.equals("quot") )
- sb.append("\"");
- else if ( token.equals("amp") )
- sb.append("&");
- else if ( token.equals("lt") )
- sb.append("<");
- else if ( token.equals("gt") )
- sb.append(">");
- else
- // Some sort of error
- return value;
-
- pos = end;
- idx = value.indexOf('&', pos);
- }
- else {
- sb.append(value.substring(pos));
- break;
- }
- }
- return sb.toString();
- }
+ else {
+ n[pos++] = c[i];
+ white = false;
+ }
+ }
+ if (white && pos > 0)
+ pos--;
+ return new String(n, 0, pos);
+ }
+
+ /**
+ * expandEntities expands the String's pre-defined XML entities
+ * (<, >, etc...) into their actual character representations.
+ *
+ * @param value The value to expand entities for
+ * @return The expanded String
+ */
+ public static String expandEntities(String value) {
+ int idx = value.indexOf('&');
+ if (idx == -1)
+ return value;
+
+ StringBuffer sb = new StringBuffer(value.length());
+ int pos = 0;
+ while (pos < value.length()) {
+ if (idx != -1) {
+ if (idx > pos)
+ sb.append(value.substring(pos, idx));
+
+ int end = value.indexOf(';', idx) + 1;
+ if (end == 0)
+ // Some sort of error
+ return value;
+
+ String token = value.substring(idx + 1, end - 1);
+ if (token.equals("apos"))
+ sb.append("'");
+ else if (token.equals("quot"))
+ sb.append("\"");
+ else if (token.equals("amp"))
+ sb.append("&");
+ else if (token.equals("lt"))
+ sb.append("<");
+ else if (token.equals("gt"))
+ sb.append(">");
+ else
+ // Some sort of error
+ return value;
-}
+ pos = end;
+ idx = value.indexOf('&', pos);
+ }
+ else {
+ sb.append(value.substring(pos));
+ break;
+ }
+ }
+ return sb.toString();
+ }
+}
1.13 +991 -989 xml-xindice/java/src/org/apache/xindice/core/query/XPathQueryResolver.java
Index: XPathQueryResolver.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/query/XPathQueryResolver.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- XPathQueryResolver.java 5 May 2003 16:18:22 -0000 1.12
+++ XPathQueryResolver.java 15 Jul 2003 15:44:36 -0000 1.13
@@ -117,1012 +117,1014 @@
*/
public final class XPathQueryResolver extends SimpleConfigurable implements QueryResolver {
- private static final Key[] EmptyKeys = new Key[0];
- private static final Key[][] EmptyKeySet = new Key[0][0];
- private static final String WILDCARD = "*";
- // private static final String THISNODE = ".";
- // private static final String PARENTNODE = "..";
-
- private static final String AUTOINDEX = "autoindex";
-
- public static final String STYLE_XPATH = "XPath";
-
- private static Log log = LogFactory.getLog("org.apache.xindice.core");
-
- // Maps Xalan Comparisons To IndexQuery
- private static final int[] OpMap = { IndexQuery.NEQ,
- IndexQuery.EQ,
- IndexQuery.LEQ,
- IndexQuery.LT,
- IndexQuery.GEQ,
- IndexQuery.GT };
-
- // Maps XPath Functions To Internal IDs (These are Xalan IDs)
- public static final int FUNC_NOT = 11;
- public static final int FUNC_TRUE = 12;
- public static final int FUNC_FALSE = 13;
- public static final int FUNC_BOOLEAN = 14;
- public static final int FUNC_NUMBER = 15;
- public static final int FUNC_FLOOR = 16;
- public static final int FUNC_CEILING = 17;
- public static final int FUNC_ROUND = 18;
- public static final int FUNC_STRING = 20;
- public static final int FUNC_STARTS_WITH = 21;
- public static final int FUNC_CONTAINS = 22;
- public static final int FUNC_SUBSTRING_BEFORE = 23;
- public static final int FUNC_SUBSTRING_AFTER = 24;
- public static final int FUNC_NORMALIZE_SPACE = 25;
- public static final int FUNC_TRANSLATE = 26;
- public static final int FUNC_CONCAT = 27;
- public static final int FUNC_SUBSTRING = 29;
- public static final int FUNC_STRING_LENGTH = 30;
-
- private QueryEngine engine;
- private DefaultErrorHandler errorListener = new DefaultErrorHandler();
- private boolean autoIndex = false;
-
- public void setConfig(Configuration config) throws XindiceException {
- super.setConfig(config);
- autoIndex = config.getBooleanAttribute(AUTOINDEX, autoIndex);
- }
-
- public String getQueryStyle() {
- return STYLE_XPATH;
- }
-
- public void setQueryEngine(QueryEngine engine) {
- this.engine = engine;
- }
-
- public Query compileQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
- return new XPathQuery(context, query, nsMap, keys);
- }
-
- public NodeSet query(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
- XPathQuery xq = new XPathQuery(context, query, nsMap, keys);
- return xq.execute();
- }
-
-
- /**
- * XPathQuery
- */
-
- private class XPathQuery implements Query {
- public Collection context;
- public IndexManager idxMgr;
- public NamespaceMap nsMap;
- public PrefixResolver pr;
- public SymbolTable symbols;
- public String query;
- public Compiler cmp;
- public XPath xp;
- public Key[] keys;
-
- public XPathQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
- this.context = context;
- this.query = query;
- this.nsMap = nsMap;
- this.keys = keys;
-
- Expression ex = null;
-
- try {
- if ( nsMap != null ) {
- Node n = nsMap.getContextNode();
- pr = new PrefixResolverDefault(n);
- }
-
- XPathParser parser = new XPathParser(errorListener, null);
- cmp = new Compiler(errorListener, null);
- parser.initXPath(cmp, query, pr);
- ex = cmp.compile(0);
-
- symbols = context.getSymbols();
- idxMgr = context.getIndexManager();
- }
- catch ( Exception e ) {
- throw new CompilationException("Error Compiling XPath Expression", e);
- }
- if ( ex == null )
- throw new CompilationException("Error Compiling XPath Expression: XPath Compiler.compile returned null");
- }
-
- public String getQueryStyle() {
- return STYLE_XPATH;
- }
-
- public String getQueryString() {
- return query;
- }
-
- public Collection getQueryContext() {
- return context;
- }
-
- public NamespaceMap getNamespaceMap() {
- return nsMap;
- }
-
- public Key[] getKeySet() {
- return keys;
- }
-
- public NodeSet execute() throws QueryException {
- try {
- Key[] keySet = keys;
-
- // TODO: Add logic to do an indexed check on provided
- // keySets that are larger than a certain minimum
-
- if ( keys == null && idxMgr != null ) {
- // Issue the query using Indexes
- try {
- Object obj = evaluate(null, 0);
- if ( obj instanceof NamedKeys )
- keySet = ((NamedKeys)obj).keys;
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- if ( keySet == null ) {
- // Fall back to a Collection scan
- SortedSet set = new TreeSet();
- RecordSet rs = context.getFiler().getRecordSet();
- while ( rs.hasMoreRecords() )
- set.add(rs.getNextKey());
- keySet = (Key[])set.toArray(EmptyKeys);
- }
-
- return new ResultSet(context, pr, keySet, query);
- }
- catch ( Exception e ) {
- if( e instanceof QueryException ) {
- throw (QueryException) e.fillInStackTrace();
- }
- throw new ProcessingException("Error executing XPath query");
- }
- }
-
- private Key[] andKeys(List list) {
- if ( !list.isEmpty() ) {
- if ( list.size() > 1 ) {
- Key[][] keys = (Key[][])list.toArray(EmptyKeySet);
- return QueryEngine.andKeySets(keys);
+ private static final Key[] EmptyKeys = new Key[0];
+ private static final Key[][] EmptyKeySet = new Key[0][0];
+ private static final String WILDCARD = "*";
+ // private static final String THISNODE = ".";
+ // private static final String PARENTNODE = "..";
+
+ private static final String AUTOINDEX = "autoindex";
+
+ public static final String STYLE_XPATH = "XPath";
+
+ private static Log log = LogFactory.getLog("org.apache.xindice.core");
+
+ // Maps Xalan Comparisons To IndexQuery
+ private static final int[] OpMap = { IndexQuery.NEQ, IndexQuery.EQ, IndexQuery.LEQ, IndexQuery.LT, IndexQuery.GEQ, IndexQuery.GT };
+
+ // Maps XPath Functions To Internal IDs (These are Xalan IDs)
+ public static final int FUNC_NOT = 11;
+ public static final int FUNC_TRUE = 12;
+ public static final int FUNC_FALSE = 13;
+ public static final int FUNC_BOOLEAN = 14;
+ public static final int FUNC_NUMBER = 15;
+ public static final int FUNC_FLOOR = 16;
+ public static final int FUNC_CEILING = 17;
+ public static final int FUNC_ROUND = 18;
+ public static final int FUNC_STRING = 20;
+ public static final int FUNC_STARTS_WITH = 21;
+ public static final int FUNC_CONTAINS = 22;
+ public static final int FUNC_SUBSTRING_BEFORE = 23;
+ public static final int FUNC_SUBSTRING_AFTER = 24;
+ public static final int FUNC_NORMALIZE_SPACE = 25;
+ public static final int FUNC_TRANSLATE = 26;
+ public static final int FUNC_CONCAT = 27;
+ public static final int FUNC_SUBSTRING = 29;
+ public static final int FUNC_STRING_LENGTH = 30;
+
+ private QueryEngine engine;
+ private DefaultErrorHandler errorListener = new DefaultErrorHandler();
+ private boolean autoIndex = false;
+
+ public void setConfig(Configuration config) throws XindiceException {
+ super.setConfig(config);
+ autoIndex = config.getBooleanAttribute(AUTOINDEX, autoIndex);
+ }
+
+ public String getQueryStyle() {
+ return STYLE_XPATH;
+ }
+
+ public void setQueryEngine(QueryEngine engine) {
+ this.engine = engine;
+ }
+
+ public Query compileQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
+ return new XPathQuery(context, query, nsMap, keys);
+ }
+
+ public NodeSet query(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
+ XPathQuery xq = new XPathQuery(context, query, nsMap, keys);
+ return xq.execute();
+ }
+
+ /**
+ * XPathQuery
+ */
+
+ private class XPathQuery implements Query {
+ public Collection context;
+ public IndexManager idxMgr;
+ public NamespaceMap nsMap;
+ public PrefixResolver pr;
+ public SymbolTable symbols;
+ public String query;
+ public Compiler cmp;
+ public XPath xp;
+ public Key[] keys;
+
+ public XPathQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
+ this.context = context;
+ this.query = query;
+ this.nsMap = nsMap;
+ this.keys = keys;
+
+ Expression ex = null;
+
+ try {
+ if (nsMap != null) {
+ Node n = nsMap.getContextNode();
+ pr = new PrefixResolverDefault(n);
+ }
+
+ XPathParser parser = new XPathParser(errorListener, null);
+ cmp = new Compiler(errorListener, null);
+ parser.initXPath(cmp, query, pr);
+ ex = cmp.compile(0);
+
+ symbols = context.getSymbols();
+ idxMgr = context.getIndexManager();
+ }
+ catch (Exception e) {
+ throw new CompilationException("Error Compiling XPath Expression", e);
+ }
+ if (ex == null)
+ throw new CompilationException("Error Compiling XPath Expression: XPath Compiler.compile returned null");
+ }
+
+ public String getQueryStyle() {
+ return STYLE_XPATH;
+ }
+
+ public String getQueryString() {
+ return query;
+ }
+
+ public Collection getQueryContext() {
+ return context;
+ }
+
+ public NamespaceMap getNamespaceMap() {
+ return nsMap;
+ }
+
+ public Key[] getKeySet() {
+ return keys;
+ }
+
+ public NodeSet execute() throws QueryException {
+ try {
+ Key[] keySet = keys;
+
+ // TODO: Add logic to do an indexed check on provided
+ // keySets that are larger than a certain minimum
+
+ if (keys == null && idxMgr != null) {
+ // Issue the query using Indexes
+ try {
+ Object obj = evaluate(null, 0);
+ if (obj instanceof NamedKeys)
+ keySet = ((NamedKeys) obj).keys;
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+
+ if (keySet == null) {
+ // Fall back to a Collection scan
+ SortedSet set = new TreeSet();
+ RecordSet rs = context.getFiler().getRecordSet();
+ while (rs.hasMoreRecords())
+ set.add(rs.getNextKey());
+ keySet = (Key[]) set.toArray(EmptyKeys);
+ }
+
+ return new ResultSet(context, pr, keySet, query);
+ }
+ catch (Exception e) {
+ if (e instanceof QueryException) {
+ throw (QueryException) e.fillInStackTrace();
+ }
+ throw new ProcessingException("Error executing XPath query");
+ }
+ }
+
+ private Key[] andKeys(List list) {
+ if (!list.isEmpty()) {
+ if (list.size() > 1) {
+ Key[][] keys = (Key[][]) list.toArray(EmptyKeySet);
+ return QueryEngine.andKeySets(keys);
+ }
+ else
+ return (Key[]) list.get(0);
}
else
- return (Key[])list.get(0);
- }
- else
- return null;
- }
-
-
- // Evaluation Methods
-
- /**
- * evaluate does a partial evaluation of the XPath in
- * order to determine the optimal indexes to prepare for
- * the query and retrieve the Document subset that will be
- * used for the actual XPath query.
- * <br><br>
- * This will return an instance of one of the following classes:
- * <pre>
- * String If the sub-expression resolves to a Node Name
- * XNumber If the sub-expression resolves to a Number
- * XString If the sub-expression resolves to a String
- * XBoolean If the sub-expression resolves to a Boolean
- * NamedKeys If the sub-expression resolves to a Key set
- * </pre>
- *
- * @param owner The parent node name for this context
- * @param pos The position to start at (recursively called)
- * @return Some Object result
- */
- private Object evaluate(String owner, int pos) throws Exception {
- int op = cmp.getOp(pos);
- if ( op == -1 )
- return null;
-
- switch ( op ) {
-
- case OpCodes.OP_LOCATIONPATH:
- return evalLocationPath(owner, pos);
-
- case OpCodes.OP_ARGUMENT:
- case OpCodes.OP_XPATH:
- case OpCodes.OP_PREDICATE:
- return evaluate(owner, Compiler.getFirstChildPos(pos));
-
- case OpCodes.OP_OR:
- case OpCodes.OP_AND:
- return evalSetComparison(op, owner, pos);
-
- case OpCodes.OP_NOTEQUALS:
- case OpCodes.OP_EQUALS:
- case OpCodes.OP_LTE:
- case OpCodes.OP_LT:
- case OpCodes.OP_GTE:
- case OpCodes.OP_GT:
- return evalValComparison(op, owner, pos);
-
- case OpCodes.OP_PLUS:
- case OpCodes.OP_MINUS:
- case OpCodes.OP_MULT:
- case OpCodes.OP_DIV:
- case OpCodes.OP_MOD:
- case OpCodes.OP_QUO:
- return evalMathOperation(op, owner, pos);
-
- case OpCodes.OP_NEG:
- case OpCodes.OP_STRING:
- case OpCodes.OP_BOOL:
- case OpCodes.OP_NUMBER:
- return evalUnaryOperation(op, owner, pos);
-
- case OpCodes.OP_UNION:
- return evalUnion(owner, pos);
-
- case OpCodes.OP_VARIABLE:
- break;
-
- case OpCodes.OP_GROUP:
- return evaluate(owner, Compiler.getFirstChildPos(pos));
-
- case OpCodes.OP_EXTFUNCTION:
- break;
-
- case OpCodes.OP_FUNCTION:
- return evalFunction(owner, pos);
-
- case OpCodes.FROM_ANCESTORS:
- case OpCodes.FROM_ANCESTORS_OR_SELF:
- case OpCodes.FROM_ATTRIBUTES:
- case OpCodes.FROM_CHILDREN:
- case OpCodes.FROM_DESCENDANTS:
- case OpCodes.FROM_DESCENDANTS_OR_SELF:
- case OpCodes.FROM_FOLLOWING:
- case OpCodes.FROM_FOLLOWING_SIBLINGS:
- case OpCodes.FROM_PARENT:
- case OpCodes.FROM_PRECEDING:
- case OpCodes.FROM_PRECEDING_SIBLINGS:
- case OpCodes.FROM_NAMESPACE:
- case OpCodes.FROM_SELF:
- case OpCodes.FROM_ROOT:
- return evalAxis(op, owner, pos);
-
- case OpCodes.NODENAME:
- case OpCodes.OP_LITERAL:
- case OpCodes.OP_NUMBERLIT:
- return evalLiteral(owner, pos);
-
- case OpCodes.NODETYPE_TEXT:
- case OpCodes.NODETYPE_NODE:
- return owner;
-
- case OpCodes.NODETYPE_ANYELEMENT:
- case OpCodes.ELEMWILDCARD:
- return WILDCARD;
-
- case OpCodes.NODETYPE_ROOT:
- case OpCodes.NODETYPE_COMMENT:
- case OpCodes.NODETYPE_PI:
- case OpCodes.NODETYPE_FUNCTEST:
- break;
-
- default:
- if (log.isWarnEnabled()) {
- log.warn("Unknown: "+op);
- }
-
- }
- return null;
- }
-
- private Object evalLocationPath(String owner, int pos) throws Exception {
- int lp = Compiler.getFirstChildPos(pos);
- List ks = new ArrayList();
- String name = null;
- boolean attr = false;
- while ( cmp.getOp(lp) != -1 ) {
- Object obj = evaluate(owner, lp);
- if ( obj instanceof NamedKeys ) {
- NamedKeys nk = (NamedKeys)obj;
- if ( nk.name != null ) {
- attr = nk.attribute;
- if ( attr && name != null ) {
- StringBuffer sb = new StringBuffer(32);
- sb.append(name);
- sb.append('@');
- sb.append(nk.name);
- name = sb.toString();
- }
- else
- name = nk.name;
- }
- if ( nk.keys != null )
- ks.add(nk.keys);
- else if ( name != null ) {
- // Try to use a NameIndex to resolve the path component
- IndexPattern pattern = new IndexPattern(symbols, name, nsMap);
- Indexer idx = context.getIndexManager().getBestIndexer(Indexer.STYLE_NODENAME, pattern);
- if ( idx != null ) {
- IndexMatch[] matches = idx.queryMatches(new IndexQueryANY(pattern));
- Key[] keys = QueryEngine.getUniqueKeys(matches);
- ks.add(keys);
- }
- }
- }
- lp = cmp.getNextOpPos(lp);
- }
- return new NamedKeys(name, attr, andKeys(ks));
- }
-
- private Object evalUnion(String owner, int pos) throws Exception {
- int l = Compiler.getFirstChildPos(pos);
- int r = cmp.getNextOpPos(l);
- Object left = evaluate(owner, l);
-
- if ( left instanceof NamedKeys &&
- ((NamedKeys)left).keys != null)
- {
- Object right = evaluate(owner, r);
-
-
-
- if ( right instanceof NamedKeys &&
- ((NamedKeys)right).keys != null)
- {
- Key[][] keys = new Key[][] { ((NamedKeys)left).keys, ((NamedKeys)right).keys };
- return new NamedKeys(null, false, QueryEngine.orKeySets(keys));
- }
- }
- // no index query of left part of union
- // or no index query of right part of union => must do
- /// collection scan
- return null;
- }
-
- private Object evalSetComparison(int op, String owner, int pos) throws Exception {
- int l = Compiler.getFirstChildPos(pos);
- int r = cmp.getNextOpPos(l);
- Object left = evaluate(owner, l);
- Object right = evaluate(owner, r);
-
- NamedKeys nkl = left instanceof NamedKeys ? (NamedKeys)left : null;
- NamedKeys nkr = right instanceof NamedKeys ? (NamedKeys)right : null;
- if ( nkl != null && nkr != null && nkl.keys != null && nkr.keys != null ) {
- Key[][] keys = new Key[][] { nkl.keys, nkr.keys };
- if ( op == OpCodes.OP_OR )
- return new NamedKeys(null, false, QueryEngine.orKeySets(keys));
- else
- return new NamedKeys(null, false, QueryEngine.andKeySets(keys));
- }
- else if ( op == OpCodes.OP_AND ) {
- if ( nkl != null && nkl.keys != null )
- return new NamedKeys(null, false, nkl.keys);
- else if ( nkr != null && nkr.keys != null )
- return new NamedKeys(null, false, nkr.keys);
- }
- return null;
- }
-
- private Object evalValComparison(int op, String owner, int pos) throws Exception {
- int l = Compiler.getFirstChildPos(pos);
- int r = cmp.getNextOpPos(l);
- Object left = evaluate(owner, l);
- Object right = evaluate(owner, r);
-
- if ( ( left instanceof XObject ) && ( right instanceof XObject ) ) {
- switch ( op ) {
- case OpCodes.OP_NOTEQUALS: return new XBoolean(((XObject)left).notEquals((XObject)right));
- case OpCodes.OP_EQUALS: return new XBoolean(((XObject)left).equals((XObject)right));
- case OpCodes.OP_LTE: return new XBoolean(((XObject)left).lessThanOrEqual((XObject)right));
- case OpCodes.OP_LT: return new XBoolean(((XObject)left).lessThan((XObject)right));
- case OpCodes.OP_GTE: return new XBoolean(((XObject)left).greaterThanOrEqual((XObject)right));
- case OpCodes.OP_GT: return new XBoolean(((XObject)left).greaterThan((XObject)right));
- default: return null; // Won't happen
- }
- }
- else
- return queryComparison(op, owner, left, right);
- }
-
- private strictfp Object evalMathOperation(int op, String owner, int pos) throws Exception {
- int lc = Compiler.getFirstChildPos(pos);
- int rc = cmp.getNextOpPos(lc);
- XObject left = (XObject)evaluate(owner, lc);
- XObject right = (XObject)evaluate(owner, rc);
-
- switch ( op ) {
- case OpCodes.OP_PLUS: return new XNumber(left.num() + right.num());
- case OpCodes.OP_MINUS: return new XNumber(left.num() - right.num());
- case OpCodes.OP_MULT: return new XNumber(left.num() * right.num());
- case OpCodes.OP_DIV: return new XNumber(left.num() / right.num());
- case OpCodes.OP_MOD: return new XNumber(left.num() % right.num());
- case OpCodes.OP_QUO: return new XNumber(left.num() / right.num());
- default: return null; // Won't happen
- }
- }
-
- private Object evalUnaryOperation(int op, String owner, int pos) throws Exception {
- XObject val = (XObject)evaluate(owner, Compiler.getFirstChildPos(pos));
- switch ( op ) {
- case OpCodes.OP_NEG: return new XNumber(-val.num());
- case OpCodes.OP_STRING: return new XString(val.str());
- case OpCodes.OP_BOOL: return new XBoolean(val.bool());
- case OpCodes.OP_NUMBER: return new XNumber(val.num());
- default: return null; // Won't happen
- }
- }
-
- private Object evalFunction(String owner, int pos) throws Exception {
- int idx = Compiler.getFirstChildPos(pos);
- int id = cmp.getOp(idx);
- int endFunc = cmp.getOp(pos +1) - 1;
-
- List args = new ArrayList();
- int lp = idx+1;
- while ( lp < endFunc ) {
- args.add(evaluate(owner, lp));
- lp = cmp.getNextOpPos(lp);
- }
-
- switch ( id ) {
- case FUNC_BOOLEAN:
- return funcBoolean(args);
- case FUNC_CEILING:
- return funcCeiling(args);
- case FUNC_CONCAT:
- return funcConcat(args);
- case FUNC_CONTAINS:
- return funcContains(args);
- case FUNC_FALSE:
- return XBoolean.S_FALSE;
- case FUNC_FLOOR:
- return funcFloor(args);
- case FUNC_NORMALIZE_SPACE:
- return funcNormalizeSpace(args);
- case FUNC_NOT:
- return funcNot(args);
- case FUNC_NUMBER:
- return funcNumber(args);
- case FUNC_ROUND:
- return funcRound(args);
- case FUNC_STARTS_WITH:
- return funcStartsWith(owner, args);
- case FUNC_STRING:
- return funcString(args);
- case FUNC_STRING_LENGTH:
- return funcStringLength(args);
- case FUNC_SUBSTRING:
- return funcSubstring(args);
- case FUNC_SUBSTRING_AFTER:
- return funcSubstringAfter(args);
- case FUNC_SUBSTRING_BEFORE:
- return funcSubstringBefore(args);
- case FUNC_TRANSLATE:
- return funcTranslate(args);
- case FUNC_TRUE:
- return XBoolean.S_TRUE;
- default:
- return null;
- }
- }
-
- private Object evalAxis(int op, String owner, int pos) throws Exception {
- String nsURI = cmp.getStepNS(pos);
- owner = (String)evaluate(owner, Compiler.getFirstChildPosOfStep(pos));
- //owner = cmp.getStepLocalName(pos);
-
- if ( nsURI != null && nsMap != null ) {
- // We have to determine the prefix that was used
- // There has to be an easier way to do this with Xalan
- String pfx = null;
- Iterator i = nsMap.keySet().iterator();
- while ( i.hasNext() ) {
- String p = (String)i.next();
- if ( nsMap.getNamespaceURI(p).equals(nsURI) ) {
- pfx = p;
- break;
- }
- }
- if ( pfx != null ) {
- StringBuffer sb = new StringBuffer(32);
- sb.append(pfx);
- sb.append(':');
- sb.append(owner);
- owner = sb.toString();
- }
- }
-
- int rp = cmp.getFirstPredicateOpPos(pos);
-
- List ks = new ArrayList();
- while ( rp < pos+cmp.getOp(pos+1) ) {
- Object obj = evaluate(owner, rp);
- if ( obj instanceof NamedKeys ) {
- NamedKeys nk = (NamedKeys)obj;
- if ( nk.keys != null )
- ks.add(nk.keys);
- }
- rp = cmp.getNextOpPos(rp);
- }
- return new NamedKeys(owner, (op == OpCodes.FROM_ATTRIBUTES), andKeys(ks));
- }
-
- private Object evalLiteral(String owner, int pos) throws Exception {
- int idx = cmp.getOp(Compiler.getFirstChildPos(pos));
- switch ( idx ) {
- case OpCodes.EMPTY:
- return owner;
- case OpCodes.ELEMWILDCARD:
- return WILDCARD;
- default:
- return cmp.getToken(idx);
- }
- }
-
-
- // XPath Functions
-
- private Object funcBoolean(List args) throws Exception {
- if ( args.size() == 1 ) {
- Object o = args.get(0);
- if ( o instanceof XObject ) {
- if ( ((XObject)o).bool() )
- return XBoolean.S_TRUE;
- else
- return XBoolean.S_FALSE;
+ return null;
+ }
+
+ // Evaluation Methods
+
+ /**
+ * evaluate does a partial evaluation of the XPath in
+ * order to determine the optimal indexes to prepare for
+ * the query and retrieve the Document subset that will be
+ * used for the actual XPath query.
+ * <br><br>
+ * This will return an instance of one of the following classes:
+ * <pre>
+ * String If the sub-expression resolves to a Node Name
+ * XNumber If the sub-expression resolves to a Number
+ * XString If the sub-expression resolves to a String
+ * XBoolean If the sub-expression resolves to a Boolean
+ * NamedKeys If the sub-expression resolves to a Key set
+ * </pre>
+ *
+ * @param owner The parent node name for this context
+ * @param pos The position to start at (recursively called)
+ * @return Some Object result
+ */
+ private Object evaluate(String owner, int pos) throws Exception {
+ int op = cmp.getOp(pos);
+ if (op == -1)
+ return null;
+
+ switch (op) {
+
+ case OpCodes.OP_LOCATIONPATH :
+ return evalLocationPath(owner, pos);
+
+ case OpCodes.OP_ARGUMENT :
+ case OpCodes.OP_XPATH :
+ case OpCodes.OP_PREDICATE :
+ return evaluate(owner, Compiler.getFirstChildPos(pos));
+
+ case OpCodes.OP_OR :
+ case OpCodes.OP_AND :
+ return evalSetComparison(op, owner, pos);
+
+ case OpCodes.OP_NOTEQUALS :
+ case OpCodes.OP_EQUALS :
+ case OpCodes.OP_LTE :
+ case OpCodes.OP_LT :
+ case OpCodes.OP_GTE :
+ case OpCodes.OP_GT :
+ return evalValComparison(op, owner, pos);
+
+ case OpCodes.OP_PLUS :
+ case OpCodes.OP_MINUS :
+ case OpCodes.OP_MULT :
+ case OpCodes.OP_DIV :
+ case OpCodes.OP_MOD :
+ case OpCodes.OP_QUO :
+ return evalMathOperation(op, owner, pos);
+
+ case OpCodes.OP_NEG :
+ case OpCodes.OP_STRING :
+ case OpCodes.OP_BOOL :
+ case OpCodes.OP_NUMBER :
+ return evalUnaryOperation(op, owner, pos);
+
+ case OpCodes.OP_UNION :
+ return evalUnion(owner, pos);
+
+ case OpCodes.OP_VARIABLE :
+ break;
+
+ case OpCodes.OP_GROUP :
+ return evaluate(owner, Compiler.getFirstChildPos(pos));
+
+ case OpCodes.OP_EXTFUNCTION :
+ break;
+
+ case OpCodes.OP_FUNCTION :
+ return evalFunction(owner, pos);
+
+ case OpCodes.FROM_ANCESTORS :
+ case OpCodes.FROM_ANCESTORS_OR_SELF :
+ case OpCodes.FROM_ATTRIBUTES :
+ case OpCodes.FROM_CHILDREN :
+ case OpCodes.FROM_DESCENDANTS :
+ case OpCodes.FROM_DESCENDANTS_OR_SELF :
+ case OpCodes.FROM_FOLLOWING :
+ case OpCodes.FROM_FOLLOWING_SIBLINGS :
+ case OpCodes.FROM_PARENT :
+ case OpCodes.FROM_PRECEDING :
+ case OpCodes.FROM_PRECEDING_SIBLINGS :
+ case OpCodes.FROM_NAMESPACE :
+ case OpCodes.FROM_SELF :
+ case OpCodes.FROM_ROOT :
+ return evalAxis(op, owner, pos);
+
+ case OpCodes.NODENAME :
+ case OpCodes.OP_LITERAL :
+ case OpCodes.OP_NUMBERLIT :
+ return evalLiteral(owner, pos);
+
+ case OpCodes.NODETYPE_TEXT :
+ case OpCodes.NODETYPE_NODE :
+ return owner;
+
+ case OpCodes.NODETYPE_ANYELEMENT :
+ case OpCodes.ELEMWILDCARD :
+ return WILDCARD;
+
+ case OpCodes.NODETYPE_ROOT :
+ case OpCodes.NODETYPE_COMMENT :
+ case OpCodes.NODETYPE_PI :
+ case OpCodes.NODETYPE_FUNCTEST :
+ break;
+
+ default :
+ if (log.isWarnEnabled()) {
+ log.warn("Unknown: " + op);
+ }
+
+ }
+ return null;
+ }
+
+ private Object evalLocationPath(String owner, int pos) throws Exception {
+ int lp = Compiler.getFirstChildPos(pos);
+ List ks = new ArrayList();
+ String name = null;
+ boolean attr = false;
+ while (cmp.getOp(lp) != -1) {
+ Object obj = evaluate(owner, lp);
+ if (obj instanceof NamedKeys) {
+ NamedKeys nk = (NamedKeys) obj;
+ if (nk.name != null) {
+ attr = nk.attribute;
+ if (attr && name != null) {
+ StringBuffer sb = new StringBuffer(32);
+ sb.append(name);
+ sb.append('@');
+ sb.append(nk.name);
+ name = sb.toString();
+ }
+ else
+ name = nk.name;
+ }
+ if (nk.keys != null)
+ ks.add(nk.keys);
+ else if (name != null) {
+ // Try to use a NameIndex to resolve the path component
+ IndexPattern pattern = new IndexPattern(symbols, name, nsMap);
+ Indexer idx = context.getIndexManager().getBestIndexer(Indexer.STYLE_NODENAME, pattern);
+ if (idx != null) {
+ IndexMatch[] matches = idx.queryMatches(new IndexQueryANY(pattern));
+ Key[] keys = QueryEngine.getUniqueKeys(matches);
+ ks.add(keys);
+ }
+ }
+ }
+ lp = cmp.getNextOpPos(lp);
+ }
+ return new NamedKeys(name, attr, andKeys(ks));
+ }
+
+ private Object evalUnion(String owner, int pos) throws Exception {
+ int l = Compiler.getFirstChildPos(pos);
+ int r = cmp.getNextOpPos(l);
+ Object left = evaluate(owner, l);
+
+ if (left instanceof NamedKeys && ((NamedKeys) left).keys != null) {
+ Object right = evaluate(owner, r);
+
+ if (right instanceof NamedKeys && ((NamedKeys) right).keys != null) {
+ Key[][] keys = new Key[][] {((NamedKeys) left).keys, ((NamedKeys) right).keys };
+ return new NamedKeys(null, false, QueryEngine.orKeySets(keys));
+ }
+ }
+ // no index query of left part of union
+ // or no index query of right part of union => must do
+ /// collection scan
+ return null;
+ }
+
+ private Object evalSetComparison(int op, String owner, int pos) throws Exception {
+ int l = Compiler.getFirstChildPos(pos);
+ int r = cmp.getNextOpPos(l);
+ Object left = evaluate(owner, l);
+ Object right = evaluate(owner, r);
+
+ NamedKeys nkl = left instanceof NamedKeys ? (NamedKeys) left : null;
+ NamedKeys nkr = right instanceof NamedKeys ? (NamedKeys) right : null;
+ if (nkl != null && nkr != null && nkl.keys != null && nkr.keys != null) {
+ Key[][] keys = new Key[][] { nkl.keys, nkr.keys };
+ if (op == OpCodes.OP_OR)
+ return new NamedKeys(null, false, QueryEngine.orKeySets(keys));
+ else
+ return new NamedKeys(null, false, QueryEngine.andKeySets(keys));
+ }
+ else if (op == OpCodes.OP_AND) {
+ if (nkl != null && nkl.keys != null)
+ return new NamedKeys(null, false, nkl.keys);
+ else if (nkr != null && nkr.keys != null)
+ return new NamedKeys(null, false, nkr.keys);
+ }
+ return null;
+ }
+
+ private Object evalValComparison(int op, String owner, int pos) throws Exception {
+ int l = Compiler.getFirstChildPos(pos);
+ int r = cmp.getNextOpPos(l);
+ Object left = evaluate(owner, l);
+ Object right = evaluate(owner, r);
+
+ if ((left instanceof XObject) && (right instanceof XObject)) {
+ switch (op) {
+ case OpCodes.OP_NOTEQUALS :
+ return new XBoolean(((XObject) left).notEquals((XObject) right));
+ case OpCodes.OP_EQUALS :
+ return new XBoolean(((XObject) left).equals((XObject) right));
+ case OpCodes.OP_LTE :
+ return new XBoolean(((XObject) left).lessThanOrEqual((XObject) right));
+ case OpCodes.OP_LT :
+ return new XBoolean(((XObject) left).lessThan((XObject) right));
+ case OpCodes.OP_GTE :
+ return new XBoolean(((XObject) left).greaterThanOrEqual((XObject) right));
+ case OpCodes.OP_GT :
+ return new XBoolean(((XObject) left).greaterThan((XObject) right));
+ default :
+ return null; // Won't happen
+ }
}
else
- return o;
- }
- return null;
- }
-
- private Object funcCeiling(List args) throws Exception {
- if ( args.size() == 1 ) {
- Object o = args.get(0);
- if ( o instanceof XObject )
- return new XNumber(Math.ceil(((XObject)o).num()));
- }
- return null;
- }
-
- private Object funcConcat(List args) {
- StringBuffer sb = new StringBuffer();
- for ( int i = 0; i < args.size(); i++ ) {
- Object o = args.get(i);
- if ( o instanceof XObject )
- sb.append(((XObject)o).str());
- }
- return new XString(sb.toString());
- }
-
- private Object funcContains(List args) {
- if ( args.size() == 2 ) {
- Object o = args.get(0);
- Object s = args.get(1);
- if ( o instanceof XObject && s instanceof XObject ) {
- if ( ((XObject)o).str().indexOf(((XObject)s).str()) != -1 )
- return XBoolean.S_TRUE;
- else
- return XBoolean.S_FALSE;
- }
- }
- return null;
- }
-
- private Object funcFloor(List args) throws Exception {
- if ( args.size() == 1 ) {
- Object o = args.get(0);
- if ( o instanceof XObject )
- return new XNumber(Math.floor(((XObject)o).num()));
- }
- return null;
- }
-
- private Object funcNormalizeSpace(List args) {
- if ( args.size() == 1 ) {
- Object o = args.get(0);
- if ( o instanceof XObject )
- return new XString(QueryEngine.normalizeString(((XObject)o).str()));
- else
- return o;
- }
- return null;
- }
-
- private Object funcNot(List args) throws Exception {
- if ( args.size() == 1 ) {
- Object o = args.get(0);
- if ( o instanceof XObject ) {
- if ( ((XObject)o).bool() )
- return XBoolean.S_FALSE;
- else
- return XBoolean.S_TRUE;
- }
- }
- return null;
- }
-
- private Object funcNumber(List args) throws Exception {
- if ( args.size() == 1 ) {
- Object o = args.get(0);
- if ( o instanceof XObject )
- return new XNumber(((XObject)o).num());
- else
- return o;
- }
- return null;
- }
-
- private Object funcRound(List args) throws Exception {
- if ( args.size() == 1 ) {
- Object o = args.get(0);
- if ( o instanceof XObject )
- return new XNumber(Math.round(((XObject)o).num()));
- }
- return null;
- }
-
- private Object funcStartsWith(String owner, List args) {
- if ( args.size() == 2 ) {
- Object o = args.get(0);
- Object s = args.get(1);
-
- if ( o instanceof XObject && s instanceof XObject ) {
- if ( ((XObject)o).str().startsWith(((XObject)s).str()) )
- return XBoolean.S_TRUE;
- else
- return XBoolean.S_FALSE;
- }
- else if ( o instanceof NamedKeys && s instanceof XObject ) {
- NamedKeys nk = (NamedKeys)o;
- String ps;
- if ( nk.attribute && nk.name.indexOf('@') == -1 )
- ps = owner+"@"+nk.name;
- else
- ps = nk.name;
-
- IndexPattern pattern = new IndexPattern(symbols, ps, nsMap);
-
- XObject obj = (XObject)s;
- Value val1 = new Value(obj.str());
-
- IndexQuery iq = new IndexQuerySW(pattern, val1);
- return queryIndexes(nk, iq, ps, obj.getType());
- }
- }
- return null;
- }
-
- private Object funcString(List args) {
- if ( args.size() == 1 ) {
- Object o = args.get(0);
- if ( o instanceof XObject )
- return new XString(((XObject)o).str());
- else
- return o;
- }
- return null;
- }
-
- private Object funcStringLength(List args) {
- if ( args.size() == 1 ) {
- Object o = args.get(0);
- if ( o instanceof XObject )
- return new XNumber(((XObject)o).str().length());
- }
- return null;
- }
-
- private Object funcSubstring(List args) throws Exception {
- if ( args.size() == 2 || args.size() == 3 ) {
- Object o = args.get(0);
- Object pos = args.get(1);
- Object len = args.get(2);
- if ( o instanceof XObject && pos instanceof XObject && (len == null || len instanceof XObject ) ) {
- int ipos = (int)((XObject)pos).num()-1;
- if ( len != null ) {
- int ilen = (int)((XObject)len).num();
- return new XString(((XObject)o).str().substring(ipos, ipos+ilen));
- }
- else
- return new XString(((XObject)o).str().substring(ipos));
- }
- }
- return null;
- }
-
- private Object funcSubstringAfter(List args) {
- if ( args.size() == 2 ) {
- Object o = args.get(0);
- Object s = args.get(1);
- if ( o instanceof XObject && s instanceof XObject ) {
- String val = ((XObject)o).str();
- String sub = ((XObject)s).str();
- int i = val.indexOf(sub);
- if ( i == -1 )
- return new XString("");
- else
- return new XString(val.substring(i+sub.length()));
- }
- }
- return null;
- }
-
- private Object funcSubstringBefore(List args) {
- if ( args.size() == 2 ) {
- Object o = args.get(0);
- Object s = args.get(1);
- if ( o instanceof XObject && s instanceof XObject ) {
- String val = ((XObject)o).str();
- String sub = ((XObject)s).str();
- int i = val.indexOf(sub);
- if ( i == -1 )
- return new XString("");
- else
- return new XString(val.substring(0, i));
- }
- }
- return null;
- }
-
- private Object funcTranslate(List args) {
- if ( args.size() == 3 ) {
- Object o = args.get(0);
- Object c1 = args.get(1);
- Object c2 = args.get(2);
- if ( o instanceof XObject && c1 instanceof XObject && c2 instanceof XObject) {
- char ch1 = ((XObject)c1).str().charAt(0);
- char ch2 = ((XObject)c2).str().charAt(0);
- return new XString(((XObject)o).str().replace(ch1, ch2));
- }
- }
- return null;
- }
-
-
- // The Actual Querying Methods
-
- /**
- * queryIndexes actually performs index-based querying on behalf of
- * the evaluation methods.
- *
- * @param nk The NamedKeys instance to use for matches
- * @param iq The actual IndexQuery to use for resolution
- * @param ps The pattern String to possibly use for index gen
- * @param objType The object type to possibly use for index gen
- * @return The resulting Keys (if any)
- */
- private Object queryIndexes(NamedKeys nk, IndexQuery iq, String ps, int objType) {
- try {
- // TODO: Add logic to use an EmptyKeySet if a name doesn't already
- // exist in the SymbolTable. This will eliminate the need
- // to do a collection scan in those cases where somebody
- // typed an element or attribute name incorrectly.
-
- IndexPattern pattern = iq.getPattern();
-
- Indexer idx = context.getIndexManager().getBestIndexer(Indexer.STYLE_NODEVALUE, pattern);
- if ( idx != null )
- return new NamedKeys(nk.name, nk.attribute, QueryEngine.getUniqueKeys(idx.queryMatches(iq)));
- else if ( autoIndex ) {
- // TODO: This has to *not* be hardcoded
- Element e = new DocumentImpl().createElement("index");
- e.setAttribute("class", "org.apache.xindice.core.indexer.ValueIndexer");
- e.setAttribute("name", "xp_"+ps);
- e.setAttribute("pattern", ps);
-
- // Set the type for the index
- String type = null;
- switch ( objType ) {
- case XObject.CLASS_BOOLEAN: type = "boolean"; break;
- case XObject.CLASS_NUMBER: type = "double"; break;
- case XObject.CLASS_STRING:
- if ( ps.indexOf('@') != -1 )
- type = "string";
- else
- type = "trimmed";
- break;
- }
- if ( type != null )
- e.setAttribute("type", type);
-
- idxMgr.create(new Configuration(e));
- }
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- return null;
- }
-
- /**
- * queryComparison performs a comparison query use the operands that
- * are passed to it, and returns the resulting Keys.
- *
- * @param op The Operator
- * @param owner The Owner Node
- * @param left The left Operand
- * @param right The right Operand
- * @return The resulting Keys (if any)
- */
- private Object queryComparison(int op, String owner, Object left, Object right) {
- if ( ! ( ( left instanceof NamedKeys ) && ( right instanceof XObject )
- || ( left instanceof XObject ) && ( right instanceof NamedKeys ) ) )
- return null; // How'd we get here?
-
- op = OpMap[op-OpCodes.OP_NOTEQUALS];
-
- if ( left instanceof XObject ) {
- // Check if we have to switch the operation
- if ( op == IndexQuery.GT
- || op == IndexQuery.LT
- || op == IndexQuery.GEQ
- || op == IndexQuery.LEQ )
- op = -op;
- // Swap the operands
- Object tmp = left;
- left = right;
- right = tmp;
- }
-
- NamedKeys nk = (NamedKeys)left;
- XObject obj = (XObject)right;
-
- String ps;
- if ( nk.attribute && nk.name.indexOf('@') == -1 )
- ps = owner+"@"+nk.name;
- else
- ps = nk.name;
-
- IndexQuery iq;
- IndexPattern pattern = new IndexPattern(symbols, ps, nsMap);
- String value = obj.str();
-
- switch ( op ) {
- case IndexQuery.NEQ: iq = new IndexQueryNEQ(pattern, value); break;
- case IndexQuery.EQ: iq = new IndexQueryEQ(pattern, value); break;
- case IndexQuery.LEQ: iq = new IndexQueryLEQ(pattern, value); break;
- case IndexQuery.LT: iq = new IndexQueryLT(pattern, value); break;
- case IndexQuery.GEQ: iq = new IndexQueryGEQ(pattern, value); break;
- case IndexQuery.GT: iq = new IndexQueryGT(pattern, value); break;
- default: iq = null; // Won't happen
- }
-
- return queryIndexes(nk, iq, ps, obj.getType());
- }
- }
-
-
- /**
- * NamedKeys
- */
-
- private class NamedKeys {
- public boolean attribute = false;
- public String name;
- public Key[] keys;
-
- public NamedKeys(String name, boolean attribute, Key[] keys) {
- this.name = name;
- this.attribute = attribute;
- this.keys = keys;
- }
- }
-
-
- /**
- * ResultSet
- */
-
- private class ResultSet implements NodeSet {
- public Collection context;
- public String query;
- public ErrorListener errors;
- public PrefixResolver pr;
- public XPath xp;
-
- public Key[] keySet;
- public int keyPos = 0;
- public NodeIterator ni;
- public Node node;
-
- public ResultSet(Collection context, PrefixResolver pr, Key[] keySet, String query) {
-//System.out.println("Query: "+query);
- this.context = context;
- this.pr = pr;
- this.keySet = keySet;
- this.query = query;
-
- errors = new ErrorListener() {
- public void fatalError(TransformerException te) {
- if (log.isFatalEnabled()) {
- log.fatal("No message", te);
- }
- }
-
- public void error(TransformerException te) {
- if (log.isErrorEnabled()) {
- log.error("No message", te);
- }
- }
-
- public void warning(TransformerException te) {
- if (log.isWarnEnabled()) {
- log.warn("No message", te);
- }
- }
- };
-
- prepareNextNode();
- }
-
- private void prepareNextNode() {
- node = null;
- while ( keyPos < keySet.length ) {
- try {
-//System.out.println(" Key: "+keySet[keyPos]);
- DBDocument d = (DBDocument)context.getDocument(keySet[keyPos++]);
- if ( d == null )
- continue;
-
- Node n = d.getDocumentElement();
-
- XPathContext xpc = new XPathContext();
- PrefixResolver pfx;
- if ( pr == null ) {
- pfx = new PrefixResolverDefault(d.getDocumentElement());
- xp = new XPath(query, null, pfx, XPath.SELECT, errors);
- }
- else {
- pfx = pr;
- if ( xp == null )
- xp = new XPath(query, null, pfx, XPath.SELECT, errors);
- }
-
- ni = xp.execute(xpc, n, pfx).nodeset();
-
- node = ni.nextNode();
- if ( node != null )
- break;
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
- }
-
- public boolean hasMoreNodes() {
- return node != null;
- }
+ return queryComparison(op, owner, left, right);
+ }
- public Node getNextNode() {
- Node n = node;
+ private strictfp Object evalMathOperation(int op, String owner, int pos) throws Exception {
+ int lc = Compiler.getFirstChildPos(pos);
+ int rc = cmp.getNextOpPos(lc);
+ XObject left = (XObject) evaluate(owner, lc);
+ XObject right = (XObject) evaluate(owner, rc);
+
+ switch (op) {
+ case OpCodes.OP_PLUS :
+ return new XNumber(left.num() + right.num());
+ case OpCodes.OP_MINUS :
+ return new XNumber(left.num() - right.num());
+ case OpCodes.OP_MULT :
+ return new XNumber(left.num() * right.num());
+ case OpCodes.OP_DIV :
+ return new XNumber(left.num() / right.num());
+ case OpCodes.OP_MOD :
+ return new XNumber(left.num() % right.num());
+ case OpCodes.OP_QUO :
+ return new XNumber(left.num() / right.num());
+ default :
+ return null; // Won't happen
+ }
+ }
+
+ private Object evalUnaryOperation(int op, String owner, int pos) throws Exception {
+ XObject val = (XObject) evaluate(owner, Compiler.getFirstChildPos(pos));
+ switch (op) {
+ case OpCodes.OP_NEG :
+ return new XNumber(-val.num());
+ case OpCodes.OP_STRING :
+ return new XString(val.str());
+ case OpCodes.OP_BOOL :
+ return new XBoolean(val.bool());
+ case OpCodes.OP_NUMBER :
+ return new XNumber(val.num());
+ default :
+ return null; // Won't happen
+ }
+ }
+
+ private Object evalFunction(String owner, int pos) throws Exception {
+ int idx = Compiler.getFirstChildPos(pos);
+ int id = cmp.getOp(idx);
+ int endFunc = cmp.getOp(pos + 1) - 1;
+
+ List args = new ArrayList();
+ int lp = idx + 1;
+ while (lp < endFunc) {
+ args.add(evaluate(owner, lp));
+ lp = cmp.getNextOpPos(lp);
+ }
+
+ switch (id) {
+ case FUNC_BOOLEAN :
+ return funcBoolean(args);
+ case FUNC_CEILING :
+ return funcCeiling(args);
+ case FUNC_CONCAT :
+ return funcConcat(args);
+ case FUNC_CONTAINS :
+ return funcContains(args);
+ case FUNC_FALSE :
+ return XBoolean.S_FALSE;
+ case FUNC_FLOOR :
+ return funcFloor(args);
+ case FUNC_NORMALIZE_SPACE :
+ return funcNormalizeSpace(args);
+ case FUNC_NOT :
+ return funcNot(args);
+ case FUNC_NUMBER :
+ return funcNumber(args);
+ case FUNC_ROUND :
+ return funcRound(args);
+ case FUNC_STARTS_WITH :
+ return funcStartsWith(owner, args);
+ case FUNC_STRING :
+ return funcString(args);
+ case FUNC_STRING_LENGTH :
+ return funcStringLength(args);
+ case FUNC_SUBSTRING :
+ return funcSubstring(args);
+ case FUNC_SUBSTRING_AFTER :
+ return funcSubstringAfter(args);
+ case FUNC_SUBSTRING_BEFORE :
+ return funcSubstringBefore(args);
+ case FUNC_TRANSLATE :
+ return funcTranslate(args);
+ case FUNC_TRUE :
+ return XBoolean.S_TRUE;
+ default :
+ return null;
+ }
+ }
+
+ private Object evalAxis(int op, String owner, int pos) throws Exception {
+ String nsURI = cmp.getStepNS(pos);
+ owner = (String) evaluate(owner, Compiler.getFirstChildPosOfStep(pos));
+ //owner = cmp.getStepLocalName(pos);
+
+ if (nsURI != null && nsMap != null) {
+ // We have to determine the prefix that was used
+ // There has to be an easier way to do this with Xalan
+ String pfx = null;
+ Iterator i = nsMap.keySet().iterator();
+ while (i.hasNext()) {
+ String p = (String) i.next();
+ if (nsMap.getNamespaceURI(p).equals(nsURI)) {
+ pfx = p;
+ break;
+ }
+ }
+ if (pfx != null) {
+ StringBuffer sb = new StringBuffer(32);
+ sb.append(pfx);
+ sb.append(':');
+ sb.append(owner);
+ owner = sb.toString();
+ }
+ }
+
+ int rp = cmp.getFirstPredicateOpPos(pos);
+
+ List ks = new ArrayList();
+ while (rp < pos + cmp.getOp(pos + 1)) {
+ Object obj = evaluate(owner, rp);
+ if (obj instanceof NamedKeys) {
+ NamedKeys nk = (NamedKeys) obj;
+ if (nk.keys != null)
+ ks.add(nk.keys);
+ }
+ rp = cmp.getNextOpPos(rp);
+ }
+ return new NamedKeys(owner, (op == OpCodes.FROM_ATTRIBUTES), andKeys(ks));
+ }
+
+ private Object evalLiteral(String owner, int pos) throws Exception {
+ int idx = cmp.getOp(Compiler.getFirstChildPos(pos));
+ switch (idx) {
+ case OpCodes.EMPTY :
+ return owner;
+ case OpCodes.ELEMWILDCARD :
+ return WILDCARD;
+ default :
+ return cmp.getToken(idx);
+ }
+ }
+
+ // XPath Functions
+
+ private Object funcBoolean(List args) throws Exception {
+ if (args.size() == 1) {
+ Object o = args.get(0);
+ if (o instanceof XObject) {
+ if (((XObject) o).bool())
+ return XBoolean.S_TRUE;
+ else
+ return XBoolean.S_FALSE;
+ }
+ else
+ return o;
+ }
+ return null;
+ }
- node = ni.nextNode();
- if ( node == null )
- prepareNextNode();
+ private Object funcCeiling(List args) throws Exception {
+ if (args.size() == 1) {
+ Object o = args.get(0);
+ if (o instanceof XObject)
+ return new XNumber(Math.ceil(((XObject) o).num()));
+ }
+ return null;
+ }
- return n;
- }
- }
-}
+ private Object funcConcat(List args) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < args.size(); i++) {
+ Object o = args.get(i);
+ if (o instanceof XObject)
+ sb.append(((XObject) o).str());
+ }
+ return new XString(sb.toString());
+ }
+
+ private Object funcContains(List args) {
+ if (args.size() == 2) {
+ Object o = args.get(0);
+ Object s = args.get(1);
+ if (o instanceof XObject && s instanceof XObject) {
+ if (((XObject) o).str().indexOf(((XObject) s).str()) != -1)
+ return XBoolean.S_TRUE;
+ else
+ return XBoolean.S_FALSE;
+ }
+ }
+ return null;
+ }
+
+ private Object funcFloor(List args) throws Exception {
+ if (args.size() == 1) {
+ Object o = args.get(0);
+ if (o instanceof XObject)
+ return new XNumber(Math.floor(((XObject) o).num()));
+ }
+ return null;
+ }
+
+ private Object funcNormalizeSpace(List args) {
+ if (args.size() == 1) {
+ Object o = args.get(0);
+ if (o instanceof XObject)
+ return new XString(QueryEngine.normalizeString(((XObject) o).str()));
+ else
+ return o;
+ }
+ return null;
+ }
+ private Object funcNot(List args) throws Exception {
+ if (args.size() == 1) {
+ Object o = args.get(0);
+ if (o instanceof XObject) {
+ if (((XObject) o).bool())
+ return XBoolean.S_FALSE;
+ else
+ return XBoolean.S_TRUE;
+ }
+ }
+ return null;
+ }
+ private Object funcNumber(List args) throws Exception {
+ if (args.size() == 1) {
+ Object o = args.get(0);
+ if (o instanceof XObject)
+ return new XNumber(((XObject) o).num());
+ else
+ return o;
+ }
+ return null;
+ }
+ private Object funcRound(List args) throws Exception {
+ if (args.size() == 1) {
+ Object o = args.get(0);
+ if (o instanceof XObject)
+ return new XNumber(Math.round(((XObject) o).num()));
+ }
+ return null;
+ }
+ private Object funcStartsWith(String owner, List args) {
+ if (args.size() == 2) {
+ Object o = args.get(0);
+ Object s = args.get(1);
+
+ if (o instanceof XObject && s instanceof XObject) {
+ if (((XObject) o).str().startsWith(((XObject) s).str()))
+ return XBoolean.S_TRUE;
+ else
+ return XBoolean.S_FALSE;
+ }
+ else if (o instanceof NamedKeys && s instanceof XObject) {
+ NamedKeys nk = (NamedKeys) o;
+ String ps;
+ if (nk.attribute && nk.name.indexOf('@') == -1)
+ ps = owner + "@" + nk.name;
+ else
+ ps = nk.name;
+
+ IndexPattern pattern = new IndexPattern(symbols, ps, nsMap);
+
+ XObject obj = (XObject) s;
+ Value val1 = new Value(obj.str());
+
+ IndexQuery iq = new IndexQuerySW(pattern, val1);
+ return queryIndexes(nk, iq, ps, obj.getType());
+ }
+ }
+ return null;
+ }
+ private Object funcString(List args) {
+ if (args.size() == 1) {
+ Object o = args.get(0);
+ if (o instanceof XObject)
+ return new XString(((XObject) o).str());
+ else
+ return o;
+ }
+ return null;
+ }
+ private Object funcStringLength(List args) {
+ if (args.size() == 1) {
+ Object o = args.get(0);
+ if (o instanceof XObject)
+ return new XNumber(((XObject) o).str().length());
+ }
+ return null;
+ }
+
+ private Object funcSubstring(List args) throws Exception {
+ if (args.size() == 2 || args.size() == 3) {
+ Object o = args.get(0);
+ Object pos = args.get(1);
+ Object len = args.get(2);
+ if (o instanceof XObject && pos instanceof XObject && (len == null || len instanceof XObject)) {
+ int ipos = (int) ((XObject) pos).num() - 1;
+ if (len != null) {
+ int ilen = (int) ((XObject) len).num();
+ return new XString(((XObject) o).str().substring(ipos, ipos + ilen));
+ }
+ else
+ return new XString(((XObject) o).str().substring(ipos));
+ }
+ }
+ return null;
+ }
+ private Object funcSubstringAfter(List args) {
+ if (args.size() == 2) {
+ Object o = args.get(0);
+ Object s = args.get(1);
+ if (o instanceof XObject && s instanceof XObject) {
+ String val = ((XObject) o).str();
+ String sub = ((XObject) s).str();
+ int i = val.indexOf(sub);
+ if (i == -1)
+ return new XString("");
+ else
+ return new XString(val.substring(i + sub.length()));
+ }
+ }
+ return null;
+ }
+
+ private Object funcSubstringBefore(List args) {
+ if (args.size() == 2) {
+ Object o = args.get(0);
+ Object s = args.get(1);
+ if (o instanceof XObject && s instanceof XObject) {
+ String val = ((XObject) o).str();
+ String sub = ((XObject) s).str();
+ int i = val.indexOf(sub);
+ if (i == -1)
+ return new XString("");
+ else
+ return new XString(val.substring(0, i));
+ }
+ }
+ return null;
+ }
+
+ private Object funcTranslate(List args) {
+ if (args.size() == 3) {
+ Object o = args.get(0);
+ Object c1 = args.get(1);
+ Object c2 = args.get(2);
+ if (o instanceof XObject && c1 instanceof XObject && c2 instanceof XObject) {
+ char ch1 = ((XObject) c1).str().charAt(0);
+ char ch2 = ((XObject) c2).str().charAt(0);
+ return new XString(((XObject) o).str().replace(ch1, ch2));
+ }
+ }
+ return null;
+ }
+
+ // The Actual Querying Methods
+
+ /**
+ * queryIndexes actually performs index-based querying on behalf of
+ * the evaluation methods.
+ *
+ * @param nk The NamedKeys instance to use for matches
+ * @param iq The actual IndexQuery to use for resolution
+ * @param ps The pattern String to possibly use for index gen
+ * @param objType The object type to possibly use for index gen
+ * @return The resulting Keys (if any)
+ */
+ private Object queryIndexes(NamedKeys nk, IndexQuery iq, String ps, int objType) {
+ try {
+ // TODO: Add logic to use an EmptyKeySet if a name doesn't already
+ // exist in the SymbolTable. This will eliminate the need
+ // to do a collection scan in those cases where somebody
+ // typed an element or attribute name incorrectly.
+
+ IndexPattern pattern = iq.getPattern();
+
+ Indexer idx = context.getIndexManager().getBestIndexer(Indexer.STYLE_NODEVALUE, pattern);
+ if (idx != null)
+ return new NamedKeys(nk.name, nk.attribute, QueryEngine.getUniqueKeys(idx.queryMatches(iq)));
+ else if (autoIndex) {
+ // TODO: This has to *not* be hardcoded
+ Element e = new DocumentImpl().createElement("index");
+ e.setAttribute("class", "org.apache.xindice.core.indexer.ValueIndexer");
+ e.setAttribute("name", "xp_" + ps);
+ e.setAttribute("pattern", ps);
+
+ // Set the type for the index
+ String type = null;
+ switch (objType) {
+ case XObject.CLASS_BOOLEAN :
+ type = "boolean";
+ break;
+ case XObject.CLASS_NUMBER :
+ type = "double";
+ break;
+ case XObject.CLASS_STRING :
+ if (ps.indexOf('@') != -1)
+ type = "string";
+ else
+ type = "trimmed";
+ break;
+ }
+ if (type != null)
+ e.setAttribute("type", type);
+
+ idxMgr.create(new Configuration(e));
+ }
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ return null;
+ }
+
+ /**
+ * queryComparison performs a comparison query use the operands that
+ * are passed to it, and returns the resulting Keys.
+ *
+ * @param op The Operator
+ * @param owner The Owner Node
+ * @param left The left Operand
+ * @param right The right Operand
+ * @return The resulting Keys (if any)
+ */
+ private Object queryComparison(int op, String owner, Object left, Object right) {
+ if (!((left instanceof NamedKeys) && (right instanceof XObject) || (left instanceof XObject) && (right instanceof NamedKeys)))
+ return null; // How'd we get here?
+
+ op = OpMap[op - OpCodes.OP_NOTEQUALS];
+
+ if (left instanceof XObject) {
+ // Check if we have to switch the operation
+ if (op == IndexQuery.GT || op == IndexQuery.LT || op == IndexQuery.GEQ || op == IndexQuery.LEQ)
+ op = -op;
+ // Swap the operands
+ Object tmp = left;
+ left = right;
+ right = tmp;
+ }
+
+ NamedKeys nk = (NamedKeys) left;
+ XObject obj = (XObject) right;
+
+ String ps;
+ if (nk.attribute && nk.name.indexOf('@') == -1)
+ ps = owner + "@" + nk.name;
+ else
+ ps = nk.name;
+
+ IndexQuery iq;
+ IndexPattern pattern = new IndexPattern(symbols, ps, nsMap);
+ String value = obj.str();
+
+ switch (op) {
+ case IndexQuery.NEQ :
+ iq = new IndexQueryNEQ(pattern, value);
+ break;
+ case IndexQuery.EQ :
+ iq = new IndexQueryEQ(pattern, value);
+ break;
+ case IndexQuery.LEQ :
+ iq = new IndexQueryLEQ(pattern, value);
+ break;
+ case IndexQuery.LT :
+ iq = new IndexQueryLT(pattern, value);
+ break;
+ case IndexQuery.GEQ :
+ iq = new IndexQueryGEQ(pattern, value);
+ break;
+ case IndexQuery.GT :
+ iq = new IndexQueryGT(pattern, value);
+ break;
+ default :
+ iq = null; // Won't happen
+ }
+
+ return queryIndexes(nk, iq, ps, obj.getType());
+ }
+ }
+
+ /**
+ * NamedKeys
+ */
+
+ private class NamedKeys {
+ public boolean attribute = false;
+ public String name;
+ public Key[] keys;
+
+ public NamedKeys(String name, boolean attribute, Key[] keys) {
+ this.name = name;
+ this.attribute = attribute;
+ this.keys = keys;
+ }
+ }
+
+ /**
+ * ResultSet
+ */
+
+ private class ResultSet implements NodeSet {
+ public Collection context;
+ public String query;
+ public ErrorListener errors;
+ public PrefixResolver pr;
+ public XPath xp;
+
+ public Key[] keySet;
+ public int keyPos = 0;
+ public NodeIterator ni;
+ public Node node;
+
+ public ResultSet(Collection context, PrefixResolver pr, Key[] keySet, String query) {
+ //System.out.println("Query: "+query);
+ this.context = context;
+ this.pr = pr;
+ this.keySet = keySet;
+ this.query = query;
+
+ errors = new ErrorListener() {
+ public void fatalError(TransformerException te) {
+ if (log.isFatalEnabled()) {
+ log.fatal("No message", te);
+ }
+ }
+
+ public void error(TransformerException te) {
+ if (log.isErrorEnabled()) {
+ log.error("No message", te);
+ }
+ }
+
+ public void warning(TransformerException te) {
+ if (log.isWarnEnabled()) {
+ log.warn("No message", te);
+ }
+ }
+ };
+
+ prepareNextNode();
+ }
+
+ private void prepareNextNode() {
+ node = null;
+ while (keyPos < keySet.length) {
+ try {
+ //System.out.println(" Key: "+keySet[keyPos]);
+ DBDocument d = (DBDocument) context.getDocument(keySet[keyPos++]);
+ if (d == null)
+ continue;
+
+ Node n = d.getDocumentElement();
+
+ XPathContext xpc = new XPathContext();
+ PrefixResolver pfx;
+ if (pr == null) {
+ pfx = new PrefixResolverDefault(d.getDocumentElement());
+ xp = new XPath(query, null, pfx, XPath.SELECT, errors);
+ }
+ else {
+ pfx = pr;
+ if (xp == null)
+ xp = new XPath(query, null, pfx, XPath.SELECT, errors);
+ }
+
+ ni = xp.execute(xpc, n, pfx).nodeset();
+
+ node = ni.nextNode();
+ if (node != null)
+ break;
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
+ }
+
+ public boolean hasMoreNodes() {
+ return node != null;
+ }
+
+ public Node getNextNode() {
+ Node n = node;
+
+ node = ni.nextNode();
+ if (node == null)
+ prepareNextNode();
+
+ return n;
+ }
+ }
+}
1.7 +246 -234 xml-xindice/java/src/org/apache/xindice/xml/TextWriter.java
Index: TextWriter.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/TextWriter.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- TextWriter.java 31 Oct 2002 07:02:22 -0000 1.6
+++ TextWriter.java 15 Jul 2003 15:44:36 -0000 1.7
@@ -59,11 +59,6 @@
* $Id$
*/
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.w3c.dom.*;
-
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
@@ -71,6 +66,16 @@
import java.io.StringWriter;
import java.io.Writer;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.ProcessingInstruction;
+
/**
* TextWriter takes a Document, DocumentFragment, or Element and
* streams it as text to an output source (or a String)
@@ -78,248 +83,255 @@
public final class TextWriter {
- private static Log log = LogFactory.getLog("org.apache.xindice.xml");
+ private static Log log = LogFactory.getLog("org.apache.xindice.xml");
- private Node node = null;
+ private Node node = null;
- public TextWriter(Node node) throws DOMException {
- this.node = node;
- }
-
- /**
- * write writes the node to the writer as text.
- *
- * @param writer The Writer to write to
- */
- public void write(Writer writer) throws IOException {
- write( node, writer );
- }
-
- /**
- * write writes the node to the OutputStream as text.
- *
- * @param output The OutputStream to write to
- */
- public void write(OutputStream output) throws IOException {
- write( node, output );
- }
-
- /**
- * toString returns the node as a String.
- *
- * @return The String value
- */
- public String toString() {
- return toString( node );
+ public TextWriter(Node node) throws DOMException {
+ this.node = node;
}
+ /**
+ * write writes the node to the writer as text.
+ *
+ * @param writer The Writer to write to
+ */
+ public void write(Writer writer) throws IOException {
+ write(node, writer);
+ }
+ /**
+ * write writes the node to the OutputStream as text.
+ *
+ * @param output The OutputStream to write to
+ */
+ public void write(OutputStream output) throws IOException {
+ write(node, output);
+ }
+ /**
+ * toString returns the node as a String.
+ *
+ * @return The String value
+ */
+ public String toString() {
+ return toString(node);
+ }
+ private static void writeNode(Writer writer, Node node) throws IOException {
+ short type = node.getNodeType();
+ switch (type) {
+
+ case Node.DOCUMENT_NODE :
+ {
+ writer.write("<?xml version=\"1.0\"?>\n");
+ writeChildren(writer, node);
+ break;
+ }
+
+ case Node.DOCUMENT_FRAGMENT_NODE :
+ {
+ writeChildren(writer, node);
+ break;
+ }
+
+ case Node.DOCUMENT_TYPE_NODE :
+ {
+ if (log.isErrorEnabled()) {
+ log.error("can't serialize doctype yet");
+ }
+ /*
+ DocumentType d = (DocumentType)node;
+ writer.write("<!DOCTYPE ");
+ writer.write(node.getOwnerDocument().getDocumentElement().getNodeName());
+ writer.write('>');
+ */
+ break;
+ }
+
+ case Node.ELEMENT_NODE :
+ {
+ Element e = (Element) node;
+ String n = e.getTagName();
+
+ writer.write('<');
+ writer.write(n);
+
+ NamedNodeMap a = e.getAttributes();
+ int size = a.getLength();
+ for (int i = 0; i < size; i++) {
+ Attr att = (Attr) a.item(i);
+ writer.write(' ');
+ writeNode(writer, att);
+ }
+
+ if (e.hasChildNodes()) {
+ writer.write('>');
+ writeChildren(writer, node);
+ writer.write("</");
+ writer.write(n);
+ writer.write('>');
+ }
+ else
+ writer.write(" />");
+ break;
+ }
+
+ case Node.ATTRIBUTE_NODE :
+ Attr a = (Attr) node;
+ writer.write(a.getName());
+ writer.write("=\"");
+ writeEscapedText(writer, a.getValue());
+ writer.write("\"");
+ break;
+
+ case Node.ENTITY_REFERENCE_NODE :
+ if (log.isErrorEnabled()) {
+ log.error("can't serialize reference ref yet");
+ }
+ break;
+
+ case Node.ENTITY_NODE :
+ if (log.isErrorEnabled()) {
+ log.error("can't serialize entity yet");
+ }
+ break;
+
+ case Node.NOTATION_NODE :
+ if (log.isErrorEnabled()) {
+ log.error("can't serialize notation yet");
+ }
+ break;
+
+ case Node.PROCESSING_INSTRUCTION_NODE :
+ {
+ ProcessingInstruction pi = (ProcessingInstruction) node;
+ writer.write("<?");
+ writer.write(pi.getTarget());
+ writer.write(" ");
+ writer.write(pi.getData());
+ writer.write("?>\n");
+ break;
+ }
+
+ case Node.TEXT_NODE :
+ {
+ writeEscapedText(writer, node.getNodeValue());
+ break;
+ }
+
+ case Node.CDATA_SECTION_NODE :
+ {
+ writer.write("<![CDATA[");
+ writer.write(node.getNodeValue());
+ writer.write("]]>");
+ break;
+ }
+
+ case Node.COMMENT_NODE :
+ {
+ writer.write("<!--");
+ writer.write(node.getNodeValue());
+ writer.write("-->");
+ break;
+ }
+ }
+ }
+ private static void writeChildren(Writer writer, Node node) throws IOException {
+ NodeList l = node.getChildNodes();
+ int size = l.getLength();
+ for (int i = 0; i < size; i++)
+ writeNode(writer, l.item(i));
+ }
- private static void writeNode(Writer writer, Node node) throws IOException {
- short type = node.getNodeType();
- switch ( type ) {
-
- case Node.DOCUMENT_NODE: {
- writer.write("<?xml version=\"1.0\"?>\n");
- writeChildren(writer, node);
- break;
- }
-
- case Node.DOCUMENT_FRAGMENT_NODE: {
- writeChildren(writer, node);
- break;
- }
-
- case Node.DOCUMENT_TYPE_NODE: {
- if (log.isErrorEnabled()) {
- log.error("can't serialize doctype yet");
- }
- /*
- DocumentType d = (DocumentType)node;
- writer.write("<!DOCTYPE ");
- writer.write(node.getOwnerDocument().getDocumentElement().getNodeName());
- writer.write('>');
- */
- break;
- }
-
- case Node.ELEMENT_NODE: {
- Element e = (Element)node;
- String n = e.getTagName();
-
- writer.write('<');
- writer.write(n);
-
- NamedNodeMap a = e.getAttributes();
- int size = a.getLength();
- for ( int i = 0; i < size; i++ ) {
- Attr att = (Attr)a.item(i);
- writer.write(' ');
- writeNode(writer, att);
+ private static void writeEscapedText(Writer writer, String text) throws IOException {
+ char[] value = text.toCharArray();
+ String outval = null;
+ int start = 0;
+ int len = 0;
+ for (int i = 0; i < value.length; i++) {
+ switch (value[i]) {
+ case '&' :
+ outval = "&";
+ break;
+ case '\'' :
+ outval = "'";
+ break;
+ case '\"' :
+ outval = """;
+ break;
+ case '<' :
+ outval = "<";
+ break;
+ case '>' :
+ outval = ">";
+ break;
+ default :
+ len++;
+ break;
}
- if ( e.hasChildNodes() ) {
- writer.write('>');
- writeChildren(writer, node);
- writer.write("</");
- writer.write(n);
- writer.write('>');
- }
- else
- writer.write(" />");
- break;
- }
-
- case Node.ATTRIBUTE_NODE:
- Attr a = (Attr)node;
- writer.write(a.getName());
- writer.write("=\"");
- writeEscapedText(writer, a.getValue());
- writer.write("\"");
- break;
-
- case Node.ENTITY_REFERENCE_NODE:
- if (log.isErrorEnabled()) {
- log.error("can't serialize reference ref yet");
+ if (outval != null) {
+ if (len > 0)
+ writer.write(value, start, len);
+ writer.write(outval);
+ start = i + 1;
+ len = 0;
+ outval = null;
}
- break;
+ }
+ if (len > 0)
+ writer.write(value, start, len);
+ }
- case Node.ENTITY_NODE:
- if (log.isErrorEnabled()) {
- log.error("can't serialize entity yet");
- }
- break;
+ /**
+ * write writes the specified node to the writer as text.
+ *
+ * @param node The Node to write
+ * @param writer The Writer to write to
+ */
+ public static void write(Node node, Writer writer) throws IOException {
+ try {
+ BufferedWriter buf = new BufferedWriter(writer, 4096);
+ writeNode(buf, node);
+ buf.flush();
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
- case Node.NOTATION_NODE:
- if (log.isErrorEnabled()) {
- log.error("can't serialize notation yet");
- }
- break;
+ /**
+ * write writes the specified node to the OutputStream as text.
+ *
+ * @param node The Node to write
+ * @param output The OutputStream to write to
+ */
+ public static void write(Node node, OutputStream output) throws IOException {
+ try {
+ OutputStreamWriter o = new OutputStreamWriter(output, "utf-8");
+ write(node, o);
+ }
+ catch (Exception e) {
+ log.warn(e);
+ }
+ }
- case Node.PROCESSING_INSTRUCTION_NODE: {
- ProcessingInstruction pi = (ProcessingInstruction)node;
- writer.write("<?");
- writer.write(pi.getTarget());
- writer.write(" ");
- writer.write(pi.getData());
- writer.write("?>\n");
- break;
- }
-
- case Node.TEXT_NODE: {
- writeEscapedText(writer, node.getNodeValue());
- break;
- }
-
- case Node.CDATA_SECTION_NODE: {
- writer.write("<![CDATA[");
- writer.write(node.getNodeValue());
- writer.write("]]>");
- break;
- }
-
- case Node.COMMENT_NODE: {
- writer.write("<!--");
- writer.write(node.getNodeValue());
- writer.write("-->");
- break;
- }
- }
- }
-
- private static void writeChildren(Writer writer, Node node) throws IOException {
- NodeList l = node.getChildNodes();
- int size = l.getLength();
- for ( int i = 0; i < size; i++ )
- writeNode(writer, l.item(i));
- }
-
- private static void writeEscapedText(Writer writer, String text) throws IOException {
- char[] value = text.toCharArray();
- String outval = null;
- int start = 0;
- int len = 0;
- for ( int i = 0; i < value.length; i++ ) {
- switch ( value[i] ) {
- case '&' : outval = "&"; break;
- case '\'' : outval = "'"; break;
- case '\"' : outval = """; break;
- case '<' : outval = "<"; break;
- case '>' : outval = ">"; break;
- default : len++; break;
- }
-
- if ( outval != null ) {
- if ( len > 0 )
- writer.write(value, start, len);
- writer.write(outval);
- start = i+1;
- len = 0;
- outval = null;
- }
- }
- if ( len > 0 )
- writer.write(value, start, len);
- }
-
- /**
- * write writes the specified node to the writer as text.
- *
- * @param node The Node to write
- * @param writer The Writer to write to
- */
- public static void write(Node node, Writer writer) throws IOException {
- try {
- BufferedWriter buf = new BufferedWriter(writer, 4096);
- writeNode(buf, node);
- buf.flush();
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- /**
- * write writes the specified node to the OutputStream as text.
- *
- * @param node The Node to write
- * @param output The OutputStream to write to
- */
- public static void write(Node node, OutputStream output) throws IOException {
- try {
- OutputStreamWriter o = new OutputStreamWriter(output, "utf-8");
- write( node, o);
- }
- catch ( Exception e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- }
- }
-
- /**
- * toString returns the node as a String.
- *
- * @param node The Node to convert
- * @return The String value
- **/
- public static String toString( Node node ) {
- StringWriter sw = new StringWriter();
- try {
- write( node, sw );
- }
- catch ( IOException e ) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
- //throw ex;
- }
- return sw.toString();
+ /**
+ * toString returns the node as a String.
+ *
+ * @param node The Node to convert
+ * @return The String value
+ **/
+ public static String toString(Node node) {
+ StringWriter sw = new StringWriter();
+ try {
+ write(node, sw);
+ }
+ catch (IOException e) {
+ log.warn(e);
+ }
+ return sw.toString();
}
}
-
1.7 +50 -55 xml-xindice/java/src/org/apache/xindice/tools/command/XPathQuery.java
Index: XPathQuery.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/tools/command/XPathQuery.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- XPathQuery.java 31 Oct 2002 07:01:15 -0000 1.6
+++ XPathQuery.java 15 Jul 2003 15:44:36 -0000 1.7
@@ -59,8 +59,10 @@
* $Id$
*/
-import org.apache.xindice.tools.XMLTools;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import org.apache.xindice.tools.XMLTools;
import org.xmldb.api.DatabaseManager;
import org.xmldb.api.base.Collection;
import org.xmldb.api.base.ResourceIterator;
@@ -69,86 +71,79 @@
import org.xmldb.api.modules.XMLResource;
import org.xmldb.api.modules.XPathQueryService;
-import java.util.Hashtable;
-import java.util.StringTokenizer;
-
/**
* SingleDocumentQuery is designed to enable the user/admin to XPathQuery a Collection for a Single Document.
*/
public class XPathQuery extends Command {
- public boolean execute(Hashtable table ) throws Exception {
+ public boolean execute(Hashtable table) throws Exception {
Collection col = null;
-
+
try {
-
- if ( (String)table.get(XMLTools.COLLECTION) == null ) {
+
+ if ((String) table.get(XMLTools.COLLECTION) == null) {
System.out.println("ERROR : Collection name and switch required");
return false;
}
- if ( (String)table.get(XMLTools.QUERY) == "" ) {
+ if ((String) table.get(XMLTools.QUERY) == "") {
System.out.println("ERROR : Query and switch required");
return false;
}
-
-
- String colstring = normalizeCollectionURI( (String)table.get(XMLTools.COLLECTION),
- (String) table.get(XMLTools.LOCAL) );
- String querystring = (String)table.get(XMLTools.QUERY);
+
+ String colstring = normalizeCollectionURI((String) table.get(XMLTools.COLLECTION), (String) table.get(XMLTools.LOCAL));
+ String querystring = (String) table.get(XMLTools.QUERY);
XPathQueryService service = null;
ResourceIterator results = null;
- col = DatabaseManager.getCollection( colstring );
-
- if ( col == null ) {
- System.out.println("ERROR : Collection not found!");
- return false;
- }
-
- service = (XPathQueryService)col.getService("XPathQueryService","1.0");
- addNamespaces(service, (String)table.get("namespaces"));
-
+ col = DatabaseManager.getCollection(colstring);
+
+ if (col == null) {
+ System.out.println("ERROR : Collection not found!");
+ return false;
+ }
+
+ service = (XPathQueryService) col.getService("XPathQueryService", "1.0");
+ addNamespaces(service, (String) table.get("namespaces"));
+
ResourceSet resultSet = service.query(querystring);
results = resultSet.getIterator();
-
- while (results.hasMoreResources() ) {
- XMLResource resource = (XMLResource)results.nextResource();
- String documentstr = (String)resource.getContent();
+
+ while (results.hasMoreResources()) {
+ XMLResource resource = (XMLResource) results.nextResource();
+ String documentstr = (String) resource.getContent();
System.out.println(documentstr);
}
-
- } catch (Exception e) {
- System.out.println("ERROR : " + e.getMessage() );
+
+ }
+ catch (Exception e) {
+ System.out.println("ERROR : " + e.getMessage());
if (table.get(XMLTools.VERBOSE).equals("true")) {
- if (log.isDebugEnabled()) {
- log.debug("No message", e);
- }
+ log.warn(e);
}
return false;
-
- } finally {
- if ( col != null ) {
+
+ }
+ finally {
+ if (col != null) {
col.close();
}
}
-
- return true;
- }
-
- private void addNamespaces(XPathQueryService service, String namespacesString) throws XMLDBException {
- if ((namespacesString != "") && (namespacesString != null)) {
- StringTokenizer st = new StringTokenizer(namespacesString, "=;");
- if (st.countTokens() % 2 != 0) {
- System.out.println("ERROR : mismatched namespace prefixes and uris");
- return;
- }
- while (st.hasMoreTokens()) {
- service.setNamespace(st.nextToken(), st.nextToken());
- }
- }
- }
-}
+ return true;
+ }
+ private void addNamespaces(XPathQueryService service, String namespacesString) throws XMLDBException {
+ if ((namespacesString != "") && (namespacesString != null)) {
+ StringTokenizer st = new StringTokenizer(namespacesString, "=;");
+ if (st.countTokens() % 2 != 0) {
+ System.out.println("ERROR : mismatched namespace prefixes and uris");
+ return;
+ }
+ while (st.hasMoreTokens()) {
+ service.setNamespace(st.nextToken(), st.nextToken());
+ }
+ }
+ }
+}