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 na...@apache.org on 2007/08/10 01:40:05 UTC

svn commit: r564424 - /xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/

Author: natalia
Date: Thu Aug  9 16:40:03 2007
New Revision: 564424

URL: http://svn.apache.org/viewvc?view=rev&rev=564424
Log:
Additional events can be received by indexers, an indexer may have more than one pattern.
This is for full text indexer.

Added:
    xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/BasicIndexerEventHandler.java   (with props)
    xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/DocumentHandler.java   (with props)
    xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexerEventHandler.java   (with props)
Modified:
    xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexManager.java
    xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexMatch.java
    xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexQuery.java
    xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/Indexer.java
    xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/MemValueIndexer.java
    xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/NameIndexer.java
    xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/ValueIndexer.java

Added: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/BasicIndexerEventHandler.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/BasicIndexerEventHandler.java?view=auto&rev=564424
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/BasicIndexerEventHandler.java (added)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/BasicIndexerEventHandler.java Thu Aug  9 16:40:03 2007
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id$
+ */
+
+package org.apache.xindice.core.indexer;
+
+import org.apache.xindice.core.data.Key;
+import org.apache.xindice.core.DBException;
+
+/**
+ * Empty implementation of IndexerEventHandler that does nothing.
+ *
+ * @version $Revision$, $Date$
+ */
+public abstract class BasicIndexerEventHandler implements IndexerEventHandler {
+
+    public void onDocumentAdded(Key key) throws DBException {
+    }
+
+    public void onDocumentDeleted(Key key) throws DBException {
+    }
+
+    public void onNameAdded(IndexPattern pattern, Key key, short elemID, short attrID) throws DBException {
+    }
+
+    public void onNameDeleted(IndexPattern pattern, Key key, short elemID, short attrID) throws DBException {
+    }
+
+    public void onValueAdded(IndexPattern pattern, String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
+    }
+
+    public void onValueDeleted(IndexPattern pattern, String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
+    }
+}

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/BasicIndexerEventHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/BasicIndexerEventHandler.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision Author Date

Added: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/DocumentHandler.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/DocumentHandler.java?view=auto&rev=564424
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/DocumentHandler.java (added)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/DocumentHandler.java Thu Aug  9 16:40:03 2007
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id$
+ */
+
+package org.apache.xindice.core.indexer;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.Attributes;
+import org.apache.xindice.xml.sax.CompressionHandler;
+import org.apache.xindice.xml.sax.SAXEventGenerator;
+import org.apache.xindice.xml.SymbolTable;
+import org.apache.xindice.util.ObjectStack;
+import org.apache.xindice.core.data.Key;
+import org.apache.xindice.core.DBException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Document;
+
+/**
+ * DocumentHandler actually performs the work of adding and removing Indexer
+ * entries by calling appropiate methods of IndexerEventHandler.
+ *
+ * @version $Revision$, $Date$
+ */
+class DocumentHandler implements ContentHandler, CompressionHandler {
+    static final int ACTION_CREATE = 0;
+    static final int ACTION_DELETE = 1;
+
+    private ObjectStack stack = new ObjectStack();
+    private Indexer[] indexers;
+    private IndexerEventHandler[] handlers;
+
+    public Key key;
+    public Document doc;
+    public int action;
+    private SymbolTable symbols;
+
+    public StackInfo info; // Current State
+
+    private static final Log log = LogFactory.getLog(DocumentHandler.class);
+
+    public DocumentHandler(SymbolTable symbols, Key key, Document doc, int action, Indexer[] list) {
+        this.symbols = symbols;
+        this.key = key;
+        this.doc = doc;
+        this.action = action;
+        this.indexers = list;
+
+        handlers = new IndexerEventHandler[list.length];
+        for (int i = 0; i < list.length; i++) {
+            handlers[i] = list[i].getIndexerEventHandler();
+        }
+
+        try {
+            SAXEventGenerator events = new SAXEventGenerator(symbols, doc);
+            events.setContentHandler(this);
+            events.setProperty(HANDLER, this);
+            events.start();
+        } catch (Exception e) {
+            if (log.isWarnEnabled()) {
+                log.warn("ignored exception", e);
+            }
+        }
+    }
+
+    // These are all NO-OPs
+    public void setDocumentLocator(Locator locator) {
+    }
+
+    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 startDocument() {
+    }
+
+    public void endDocument() {
+        for (int i = 0; i < handlers.length; i++ ) {
+            try {
+                switch (action) {
+                    case ACTION_CREATE:
+                        handlers[i].onDocumentAdded(key);
+                        break;
+                    case ACTION_DELETE:
+                        handlers[i].onDocumentDeleted(key);
+                        break;
+                    default:
+                        if (log.isWarnEnabled()) {
+                            log.warn("invalid action : " + action);
+                        }
+                }
+            } catch (Exception e) {
+                if (log.isWarnEnabled()) {
+                    log.warn("ignored exception", e);
+                }
+            }
+        }
+    }
+
+    public void processEntry(IndexPattern pattern, String value, int pos, int len) {
+        for (int i = 0; i < handlers.length; i++ ) {
+            try {
+                switch (action) {
+                    case ACTION_CREATE:
+                        add(i, pattern, value, key, pos, len);
+                        break;
+                    case ACTION_DELETE:
+                        delete(i, pattern, value, key, pos, len);
+                        break;
+                    default:
+                        if (log.isWarnEnabled()) {
+                            log.warn("invalid action : " + action);
+                        }
+                }
+            } catch (Exception e) {
+                if (log.isWarnEnabled()) {
+                    log.warn("ignored exception", e);
+                }
+            }
+        }
+    }
+
+    public void add(int n, IndexPattern ptrn, String value, Key key, int pos, int len) throws DBException {
+        IndexPattern[] patterns = indexers[n].getPatterns();
+        for (int i = 0; i < patterns.length; i++) {
+            if (ptrn.getMatchLevel(patterns[i]) > 0) {
+                handlers[n].onNameAdded(patterns[i], key, ptrn.getElementID(), ptrn.getAttributeID());
+                handlers[n].onValueAdded(patterns[i], value, key, pos, len, ptrn.getElementID(), ptrn.getAttributeID());
+            }
+        }
+    }
+
+    public void delete(int n, IndexPattern ptrn, String value, Key key, int pos, int len) throws DBException {
+        IndexPattern[] patterns = indexers[n].getPatterns();
+        for (int i = 0; i < patterns.length; i++) {
+            if (ptrn.getMatchLevel(patterns[i]) > 0) {
+                handlers[n].onNameDeleted(patterns[i], key, ptrn.getElementID(), ptrn.getAttributeID());
+                handlers[n].onValueDeleted(patterns[i], value, key, pos, len, ptrn.getElementID(), ptrn.getAttributeID());
+            }
+        }
+    }
+
+    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);
+            short id;
+            if (nsURI != null && nsURI.length() > 0) {
+                String attrNSID = "ns" + Integer.toString(nsURI.hashCode()) + ":" + atts.getLocalName(i);
+                id = symbols.getSymbol(attrNSID, nsURI, true);
+            } else {
+                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) {
+        StringBuffer sb = info.sb;
+        processEntry(new IndexPattern(symbols, info.symbolID), sb.toString(), info.pos, info.len);
+        info = (StackInfo) stack.pop();
+        if (info != null) {
+            info.sb.append(sb);
+        }
+    }
+
+    public void characters(char ch[], int start, int length) {
+        info.sb.append(ch, start, length);
+    }
+
+    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 = new StringBuffer();
+        public int pos = -1;
+        public int len = -1;
+
+        public StackInfo(short symbolID) {
+            this.symbolID = symbolID;
+        }
+    }
+}
+

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/DocumentHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/DocumentHandler.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision Author Date

Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexManager.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexManager.java?view=diff&rev=564424&r1=564423&r2=564424
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexManager.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexManager.java Thu Aug  9 16:40:03 2007
@@ -29,17 +29,11 @@
 import org.apache.xindice.core.data.RecordSet;
 import org.apache.xindice.util.Configuration;
 import org.apache.xindice.util.ConfigurationCallback;
-import org.apache.xindice.util.ObjectStack;
 import org.apache.xindice.util.SimpleConfigurable;
 import org.apache.xindice.util.XindiceException;
 import org.apache.xindice.xml.SymbolTable;
-import org.apache.xindice.xml.sax.CompressionHandler;
-import org.apache.xindice.xml.sax.SAXEventGenerator;
 
 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;
@@ -61,29 +55,23 @@
     private static final Log log = LogFactory.getLog(IndexManager.class);
 
     private static final String[] EMPTY_STRINGS = new String[0];
-    private static final IndexerInfo[] EMPTY_INDEXERS = new IndexerInfo[0];
+    private static final Indexer[] EMPTY_INDEXERS = new Indexer[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 Integer STATUS_READY = new Integer(0);
+    private static final Integer STATUS_BUSY = new Integer(1);
 
-    private static final int ACTION_CREATE = 0;
-    private static final int ACTION_UPDATE = 1;
-    private static final int ACTION_DELETE = 2;
-
-    private Map patternMap = new HashMap();   // IndexPattern to IndexerInfo
-    private Map indexes = new HashMap();      // String to IndexerInfo
+    private Map indexes = new HashMap();      // Name to Indexer
+    private Map status = new HashMap();       // Name to Status
     private Map bestIndexers = new HashMap(); // String to Map of IndexPattern to Indexer
 
-    private IndexerInfo[] idxList = EMPTY_INDEXERS;
-
     private Collection collection;
     private Timer timer;
     private SymbolTable symbols;
-    private final List newIndexers = new ArrayList(); // of IndexerInfo
+    private final List newIndexers = new ArrayList(); // of Indexers
 
     private int taskCount;                      // counter of scheduled tasks
     private final Object lock = new Object();   // lock object for manipulating taskCounter
@@ -175,12 +163,9 @@
      * Drop all indexers
      */
     public synchronized void drop() {
-        // Get a copy of idxList
-        IndexerInfo[] idx = idxList;
-
         // Drop indexes
-        for (int i = 0; i < idx.length; i++) {
-            drop(idx[i].name);
+        for (Iterator i = indexes.keySet().iterator(); i.hasNext(); ) {
+            drop((String) i.next());
         }
     }
 
@@ -229,12 +214,13 @@
             }
         }
         // close all indexers
-        for (int i = 0; i < idxList.length; i++) {
+        for (Iterator i = indexes.values().iterator(); i.hasNext(); ) {
+            Indexer idx = (Indexer) i.next();
             try {
-                idxList[i].indexer.close();
+                idx.close();
             } catch (DBException e) {
                 if (log.isWarnEnabled()) {
-                    log.warn("Failed to close indexer " + idxList[i].name + " on collection " + collection.getCanonicalName(), e);
+                    log.warn("Failed to close indexer " + idx.getName() + " on collection " + collection.getCanonicalName(), e);
                 }
             }
         }
@@ -251,17 +237,13 @@
                 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()) {
                 idx.create();
                 idx.open();
 
-                info.status = STATUS_BUSY;
+                status.put(name, STATUS_BUSY);
                 synchronized (newIndexers) {
-                    newIndexers.add(info);
+                    newIndexers.add(idx);
                 }
 
                 synchronized (lock) {
@@ -284,18 +266,15 @@
                     }
                 }
             } else {
-                info.status = STATUS_READY;
+                status.put(name, STATUS_BUSY);
                 idx.open();
             }
+            indexes.put(name, idx);
 
-            indexes.put(name, info);
-            patternMap.put(pattern, info);
-
-            Map tbl = (Map) bestIndexers.get(style);
+            Map tbl = (Map) bestIndexers.get(idx.getIndexStyle());
             if (tbl != null) {
                 tbl.clear();
             }
-            idxList = (IndexerInfo[]) indexes.values().toArray(EMPTY_INDEXERS);
 
             return idx;
         } catch (DBException e) {
@@ -306,16 +285,14 @@
     }
 
     public synchronized void unregister(String name) {
-        IndexerInfo idx = (IndexerInfo) indexes.remove(name);
-        String style = idx.style;
-        patternMap.remove(idx.pattern);
+        Indexer idx = (Indexer) indexes.remove(name);
+        status.remove(name);
 
+        String style = idx.getIndexStyle();
         Map tbl = (Map) bestIndexers.get(style);
         if (tbl != null) {
             tbl.clear();
         }
-
-        idxList = (IndexerInfo[]) indexes.values().toArray(EMPTY_INDEXERS);
     }
 
     private void initialize(Indexer idx, Configuration cfg) throws XindiceException {
@@ -324,16 +301,16 @@
     }
 
     private void populateNewIndexers() throws DBException {
-        IndexerInfo[] list;
+        Indexer[] list;
         synchronized (newIndexers) {
-            list = (IndexerInfo[]) newIndexers.toArray(EMPTY_INDEXERS);
+            list = (Indexer[]) newIndexers.toArray(EMPTY_INDEXERS);
             newIndexers.clear();
         }
 
         if (list.length > 0) {
             if (log.isTraceEnabled()) {
                 for (int i = 0; i < list.length; i++) {
-                    log.trace("Index Creation: " + list[i].indexer.getName());
+                    log.trace("Index Creation: " + list[i].getName());
                 }
             }
 
@@ -345,7 +322,7 @@
                 Entry entry = collection.getEntry(key);
                 if (entry.getEntryType() == Entry.DOCUMENT) {
                     try {
-                        new SAXHandler(key, (Document) entry.getValue(), ACTION_CREATE, list);
+                        new DocumentHandler(symbols, key, (Document) entry.getValue(), DocumentHandler.ACTION_CREATE, list);
                     } catch (Exception e) {
                         if (log.isWarnEnabled()) {
                             log.warn("Failed to index document " + key, e);
@@ -356,19 +333,19 @@
 
             for (int i = 0; i < list.length; i++) {
                 try {
-                    list[i].indexer.flush();
+                    list[i].flush();
                 } catch (Exception e) {
                     if (log.isWarnEnabled()) {
                         log.warn("ignored exception", e);
                     }
                 }
-                list[i].status = STATUS_READY;
+                status.put(list[i].getName(), STATUS_READY);
             }
             sw.stop();
 
             if (log.isDebugEnabled()) {
                 for (int i = 0; i < list.length; i++) {
-                    log.debug("Index Complete: " + list[i].indexer.getName());
+                    log.debug("Index Complete: " + list[i].getName());
                 }
                 log.debug(sw.toString());
             }
@@ -382,8 +359,7 @@
      * @return The Indexer
      */
     public synchronized Indexer get(String name) {
-        IndexerInfo info = (IndexerInfo) indexes.get(name);
-        return info != null ? info.indexer : null;
+        return (Indexer) indexes.get(name);
     }
 
     /**
@@ -406,15 +382,26 @@
             int highScore = 0;
             Iterator i = indexes.values().iterator();
             while (i.hasNext()) {
-                IndexerInfo info = (IndexerInfo) i.next();
-                if (info.status != STATUS_READY || !info.indexer.getIndexStyle().equals(style)) {
+                Indexer index = (Indexer) i.next();
+                if (!status.get(index.getName()).equals(STATUS_READY) || !index.getIndexStyle().equals(style)) {
                     continue;
                 }
-                int score = pattern.getMatchLevel(info.pattern);
-                if (score > highScore) {
-                    idx = info.indexer;
-                    highScore = score;
+
+                // TODO: should it check patterns?
+                // there can be only one full text index for a collection
+                if (style.equals(Indexer.STYLE_FULLTEXT) && index.getIndexStyle().equals(style)) {
+                    return index;
                 }
+
+                for (int j = 0; j < index.getPatterns().length; j++) {
+                    int score = pattern.getMatchLevel(index.getPatterns()[j]);
+
+                    if (score > highScore) {
+                        idx = index;
+                        highScore = score;
+                    }
+                }
+
             }
             tbl.put(pattern, idx);
         }
@@ -422,11 +409,12 @@
     }
 
     public void addDocument(Key key, Document doc) {
-        if (idxList.length > 0) {
-            new SAXHandler(key, doc, ACTION_CREATE);
+        if (indexes.size() > 0) {
+            Indexer[] idxList = (Indexer[]) indexes.values().toArray(EMPTY_INDEXERS);
+            new DocumentHandler(symbols, key, doc, DocumentHandler.ACTION_CREATE, idxList);
             for (int i = 0; i < idxList.length; i++) {
                 try {
-                    idxList[i].indexer.flush();
+                    idxList[i].flush();
                 } catch (Exception e) {
                     if (log.isWarnEnabled()) {
                         log.warn("ignored exception", e);
@@ -437,194 +425,18 @@
     }
 
     public void removeDocument(Key key, Document doc) {
-        if (idxList.length > 0) {
-            new SAXHandler(key, doc, ACTION_DELETE);
+        if (indexes.size() > 0) {
+            Indexer[] idxList = (Indexer[]) indexes.values().toArray(EMPTY_INDEXERS);
+            new DocumentHandler(symbols, key, doc, DocumentHandler.ACTION_DELETE, idxList);
             for (int i = 0; i < idxList.length; i++) {
                 try {
-                    idxList[i].indexer.flush();
+                    idxList[i].flush();
                 } catch (Exception e) {
                     if (log.isWarnEnabled()) {
                         log.warn("ignored 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(symbols, doc);
-                events.setContentHandler(this);
-                events.setProperty(HANDLER, this);
-                events.start();
-
-                if (action == ACTION_CREATE || action == ACTION_UPDATE) {
-                    collection.flushSymbolTable();
-                }
-            } catch (Exception e) {
-                if (log.isWarnEnabled()) {
-                    log.warn("ignored exception", 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;
-                            default:
-                                if (log.isWarnEnabled()) {
-                                    log.warn("invalid action : " + action);
-                                }
-                        }
-                    } catch (Exception e) {
-                        if (log.isWarnEnabled()) {
-                            log.warn("ignored exception", 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) {
-            StringBuffer sb = info.sb;
-            processEntry(new IndexPattern(symbols, info.symbolID), sb.toString(), info.pos, info.len);
-
-            info = (StackInfo) stack.pop();
-            if (info != null) {
-                info.sb.append(sb);
-            }
-        }
-
-        public void characters(char ch[], int start, int length) {
-            info.sb.append(ch, start, length);
-        }
-
-        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 = new StringBuffer();
-        public int pos = -1;
-        public int len = -1;
-
-        public StackInfo(short symbolID) {
-            this.symbolID = symbolID;
         }
     }
 

Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexMatch.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexMatch.java?view=diff&rev=564424&r1=564423&r2=564424
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexMatch.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexMatch.java Thu Aug  9 16:40:03 2007
@@ -69,6 +69,14 @@
         attr = pattern.getAttributeID();
     }
 
+    public IndexMatch(Key key, short elem, short attr) {
+        this.key = key;
+        pos = -1;
+        len = -1;
+        this.elem = elem;
+        this.attr = attr;
+    }
+
     /**
      * getKey returns the Document Key for the IndexMatch.
      *

Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexQuery.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexQuery.java?view=diff&rev=564424&r1=564423&r2=564424
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexQuery.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexQuery.java Thu Aug  9 16:40:03 2007
@@ -64,6 +64,8 @@
     public static final int SW = 7;    // Starts-with
     public static final int NSW = -7;  // Not Starts-with
 
+    public static final int TQ = 8;    // Text query
+
 
     protected final IndexPattern pattern;
     protected final int op;

Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/Indexer.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/Indexer.java?view=diff&rev=564424&r1=564423&r2=564424
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/Indexer.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/Indexer.java Thu Aug  9 16:40:03 2007
@@ -22,7 +22,6 @@
 import org.apache.xindice.core.Collection;
 import org.apache.xindice.core.DBException;
 import org.apache.xindice.core.DBObject;
-import org.apache.xindice.core.data.Key;
 import org.apache.xindice.util.Configurable;
 import org.apache.xindice.util.Named;
 
@@ -61,7 +60,7 @@
     String getIndexStyle();
 
     /**
-     * getPattern returns the pattern recognized by this Indexer.  Patterns
+     * getPatterns returns the patterns recognized by this Indexer.  Patterns
      * must be in the form of (elem|*)[@(attr|*)] to tell the IndexManager
      * which element types to send to it, so for example:
      * <pre>
@@ -73,43 +72,19 @@
      *    *@*           Indexes all attributes of all elements
      * </pre>
      * These patterns are used by the IndexManager when handling SAX events.
-     * All events that match the specified pattern will result in an add or
-     * remove call to the Indexer.
+     * All events that match the any of specified patterns will result in an
+     * call to the Indexer's event handler.
      *
-     * @return The Pattern used
+     * @return The Patterns used
      */
-    String getPattern();
-
-    /**
-     * remove removes all references to the specified Key from the Indexer.
-     *
-     * @param value The value to remove
-     * @param key The Object ID
-     * @param pos The offset into the stream the Element occurs at
-     * @param len The length of the substream for the Element
-     * @param elemID The Element ID of the value
-     * @param attrID The Attribute ID of the value (if any, else -1)
-     */
-    void remove(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException;
-
-    /**
-     * add adds a Document to the Indexer.
-     *
-     * @param value The value to remove
-     * @param key The Object ID
-     * @param pos The offset into the stream the Element occurs at
-     * @param len The length of the substream for the Element
-     * @param elemID The Element ID of the value
-     * @param attrID The Attribute ID of the value (if any, else -1)
-     */
-    void add(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException;
+    IndexPattern[] getPatterns();
 
     /**
      * queryMatches retrieves a set of IndexMatch instances that match
-     * the supplied query.  The matches are then used by the  QueryEngine
-     * in co-sequential processing.  If this indexer doesn't support the
-     * passed value, it should return 'null'.  If no matches are found,
-     * it should return an empty set.  queryMatches will typically be
+     * the supplied query.  The matches are then used by the QueryEngine
+     * in co-sequential processing. If this indexer doesn't support the
+     * passed value, it should return 'null'. If no matches are found,
+     * it should return an empty set. queryMatches will typically be
      * used in XPath processing.
      *
      * @param query The IndexQuery to use
@@ -121,4 +96,15 @@
      * flush forcefully flushes any unwritten buffers to disk.
      */
     void flush() throws DBException;
+
+    /**
+     * getIndexerEventHandler returns an instance of IndexerEventHandler that
+     * handles Indexer-specific events. This method is called once per
+     * document, and all events for one document will be processed by the same
+     * handler.
+     *
+     * @return IndexerEventHandler that will handle document processing
+     * @see IndexerEventHandler
+     */
+    public IndexerEventHandler getIndexerEventHandler();
 }

Added: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexerEventHandler.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexerEventHandler.java?view=auto&rev=564424
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexerEventHandler.java (added)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexerEventHandler.java Thu Aug  9 16:40:03 2007
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id$
+ */
+
+package org.apache.xindice.core.indexer;
+
+import org.apache.xindice.core.data.Key;
+import org.apache.xindice.core.DBException;
+
+/**
+ * IndexerEventHandler represents an event handler for Indexer-specific events.
+ * It is used by Indexers to manage adding and removing data.
+ *
+ * @see Indexer
+ * @version $Revision$, $Date$
+ */
+public interface IndexerEventHandler {
+    /**
+     * onDocumentAdded method is called after document is added and all its
+     * elements are processed. This method will be called regardless of
+     * Indexer patterns, even if no elements/attributes in that document
+     * matches any of Indexer patterns.
+     *
+     * @param key Document key
+     * @throws DBException
+     */
+    void onDocumentAdded(Key key) throws DBException;
+
+    /**
+     * onDocumentDeleted method is called after document is deleted and all its
+     * elements are processed. This method will be called regardless of Indexer
+     * patterns, even if no elements/attributes in that document matches any of
+     * Indexer patterns.
+     *
+     * @param key Document key
+     * @throws DBException
+     */
+    void onDocumentDeleted(Key key) throws DBException;
+
+    /**
+     * onNameAdded called for every element/attribute in the document being added
+     * that matches any of the Indexer pattern.
+     *
+     * @param pattern Indexer pattern that matches the element/attribute
+     * @param key     Document key
+     * @param elemID  Element ID that matches the pattern
+     * @param attrID  Attribute ID that matches the pattern
+     * @throws DBException
+     */
+    void onNameAdded(IndexPattern pattern, Key key, short elemID, short attrID) throws DBException;
+
+    /**
+     * onNameDeleted called for every element/attribute in the document being deleted
+     * that matches any of the Indexer pattern.
+     *
+     * @param pattern Indexer pattern that matches the element/attribute
+     * @param key     Document key
+     * @param elemID  Element ID that matches the pattern
+     * @param attrID  Attribute ID that matches the pattern
+     * @throws DBException
+     */
+    void onNameDeleted(IndexPattern pattern, Key key, short elemID, short attrID) throws DBException;
+
+    /**
+     * onValueAdded called for every element/attribute in the document being added
+     * that matches any of the Indexer pattern.
+     *
+     * @param pattern Indexer pattern that matches the element/attribute
+     * @param value   Element/attribute value to add
+     * @param key     Document key
+     * @param pos     The offset into the stream the Element occurs at
+     * @param len     The length of the substream for the Element
+     * @param elemID  Element ID that matches the pattern
+     * @param attrID  Attribute ID that matches the pattern
+     * @throws DBException
+     */
+    void onValueAdded(IndexPattern pattern, String value, Key key, int pos, int len, short elemID, short attrID) throws DBException;
+
+    /**
+     * onValueDeleted called for every element/attribute in the document being deleted
+     * that matches any of the Indexer pattern.
+     *
+     * @param pattern Indexer pattern that matches the element/attribute
+     * @param value   Element/attribute value to delete
+     * @param key     Document key
+     * @param pos     The offset into the stream the Element occurs at
+     * @param len     The length of the substream for the Element
+     * @param elemID  Element ID that matches the pattern
+     * @param attrID  Attribute ID that matches the pattern
+     * @throws DBException
+     */
+    void onValueDeleted(IndexPattern pattern, String value, Key key, int pos, int len, short elemID, short attrID) throws DBException;
+}

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexerEventHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/IndexerEventHandler.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision Author Date

Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/MemValueIndexer.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/MemValueIndexer.java?view=diff&rev=564424&r1=564423&r2=564424
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/MemValueIndexer.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/MemValueIndexer.java Thu Aug  9 16:40:03 2007
@@ -112,7 +112,7 @@
     /**
      * pattern for this index
      */
-    private String itsPattern;
+    private IndexPattern itsPattern;
 
     /**
      * TODO: Unused: indicates if wildcard index
@@ -143,6 +143,8 @@
      * tracks the open/closed state for open(), close(), and isOpened()
      */
     private boolean itsOpen = false;
+    private org.apache.xindice.core.Collection itsCollection;
+    private IndexerEventHandler handler;
 
 
     /**
@@ -151,7 +153,7 @@
      * @param theCollection The owner Collection
      */
     public void setCollection(org.apache.xindice.core.Collection theCollection) {
-        // TODO: Unused: itsCollection = theCollection;
+        itsCollection = theCollection;
     }
 
     /**
@@ -165,6 +167,14 @@
         return STYLE_NODEVALUE;
     }
 
+    public void addDocument(Key key) throws DBException {
+
+    }
+
+    public void removeDocument(Key key) throws DBException {
+
+    }
+
     /**
      * Provides the pattern recognized by this Indexer.  Patterns
      * must be in the form of (elem|*)[@(attr|*)] to tell the IndexManager
@@ -183,89 +193,8 @@
      *
      * @return the pattern used by this index
      */
-    public String getPattern() {
-        return itsPattern;
-    }
-
-    /**
-     * Removes the specified value reference from the index.
-     *
-     * @param theValue The value to remove
-     * @param theKey The Object ID
-     * @param thePosition The offset into the stream the Element occurs at
-     * @param theLength The length of the substream for the Element
-     * @param theElementID The Element ID of the value
-     * @param theAttributeID The Attribute ID of the value (if any, else -1)
-     */
-    public synchronized void remove(String theValue, Key theKey, int thePosition, int theLength,
-                                    short theElementID, short theAttributeID) throws DBException {
-        Object aValue;
-
-        if (itsValueType != STRING) {
-            // convert from String to the primitive container object
-            // type (e.g. Integer, Double, etc.) we store
-            aValue = getTypedValue(theValue);
-        } else {
-            aValue = theValue;
-        }
-
-        // get the set of locations for the value being added
-        TreeSet aLocatorSet = (TreeSet) itsValues.get(aValue);
-
-        // if found locator set, try to remove locator for value being removed
-        if (aLocatorSet != null) {
-            if (aLocatorSet.remove(new ValueLocator(theKey, thePosition, theLength, theElementID, theAttributeID))) {
-                // removed a ValueLocator
-                // set could now be empty
-                // if so, remove empty set from value-locatorset map
-                if (aLocatorSet.size() == 0) {
-                    itsValues.remove(theValue);
-                }
-
-                // keep track of how many locators we manage
-                --itsValueLocatorCount;
-            }
-        }
-    }
-
-    /**
-     * Adds a value reference to the index.
-     *
-     * @param theValue The value to add
-     * @param theKey The Object ID
-     * @param thePosition The offset into the stream the Element occurs at
-     * @param theLength The length of the substream for the Element
-     * @param theElementID The Element ID of the value
-     * @param theAttributeID The Attribute ID of the value (if any, else -1)
-     */
-    public synchronized void add(String theValue, Key theKey, int thePosition, int theLength,
-                                 short theElementID, short theAttributeID) throws DBException {
-        Object aValue;
-
-        if (itsValueType != STRING) {
-            // convert from String to the primitive container object
-            // type (e.g. Integer, Double, etc.) we store
-            aValue = getTypedValue(theValue);
-        } else {
-            aValue = theValue;
-        }
-
-        // get the set of locations for the value being added
-        TreeSet aLocatorSet = (TreeSet) itsValues.get(aValue);
-
-        // if not found, create a new the set of locations for the value being added
-        if (aLocatorSet == null) {
-            aLocatorSet = new TreeSet();
-
-            // add new set to the value-locators map
-            itsValues.put(aValue, aLocatorSet);
-        }
-
-        // add a value locator to the set of locations for the value being added
-        aLocatorSet.add(new ValueLocator(theKey, thePosition, theLength, theElementID, theAttributeID));
-
-        // keep track of how many locators we manage
-        ++itsValueLocatorCount;
+    public IndexPattern[] getPatterns() {
+        return new IndexPattern[] { itsPattern };
     }
 
     /**
@@ -795,6 +724,10 @@
         // nothing to flush to...
     }
 
+    public IndexerEventHandler getIndexerEventHandler() {
+        return handler;
+    }
+
     // org.apache.xindice.util.Configurable facet
 
     /**
@@ -807,7 +740,7 @@
         itsConfig = theConfig;
         try {
             itsName = theConfig.getAttribute(NAME);
-            itsPattern = theConfig.getAttribute(PATTERN);
+            String itsPattern = theConfig.getAttribute(PATTERN);
             // TODO: Unused: itsWildcard = itsPattern.indexOf('*') != -1;
 
             // Determine the Index Type
@@ -841,9 +774,77 @@
                     itsValueType = TRIMMED;
                 }
             }
+
+            this.itsPattern = new IndexPattern(itsCollection.getSymbols(), itsPattern, null);
+            setupHandler();
         } catch (Exception e) {
             log.warn("Exception while setting configuration", e);
         }
+    }
+
+    private void setupHandler() {
+        handler = new BasicIndexerEventHandler() {
+            public synchronized void onValueAdded(IndexPattern pattern, String value, Key key, int pos, int len,
+                                                  short elemID, short attrID) {
+
+                Object aValue;
+                if (itsValueType != STRING) {
+                    // convert from String to the primitive container object
+                    // type (e.g. Integer, Double, etc.) we store
+                    aValue = getTypedValue(value);
+                } else {
+                    aValue = value;
+                }
+
+                // get the set of locations for the value being added
+                TreeSet aLocatorSet = (TreeSet) itsValues.get(aValue);
+
+                // if not found, create a new the set of locations for the value being added
+                if (aLocatorSet == null) {
+                    aLocatorSet = new TreeSet();
+
+                    // add new set to the value-locators map
+                    itsValues.put(aValue, aLocatorSet);
+                }
+
+                // add a value locator to the set of locations for the value being added
+                aLocatorSet.add(new ValueLocator(key, pos, len, elemID, attrID));
+
+                // keep track of how many locators we manage
+                ++itsValueLocatorCount;
+            }
+
+            public synchronized void onValueDeleted(IndexPattern pattern, String value, Key key, int pos, int len,
+                                                    short elemID, short attrID) {
+                Object aValue;
+
+                if (itsValueType != STRING) {
+                    // convert from String to the primitive container object
+                    // type (e.g. Integer, Double, etc.) we store
+                    aValue = getTypedValue(value);
+                } else {
+                    aValue = value;
+                }
+
+                // get the set of locations for the value being added
+                TreeSet aLocatorSet = (TreeSet) itsValues.get(aValue);
+
+                // if found locator set, try to remove locator for value being removed
+                if (aLocatorSet != null) {
+                    if (aLocatorSet.remove(new ValueLocator(key, pos, len, elemID, attrID))) {
+                        // removed a ValueLocator
+                        // set could now be empty
+                        // if so, remove empty set from value-locatorset map
+                        if (aLocatorSet.size() == 0) {
+                            itsValues.remove(value);
+                        }
+
+                        // keep track of how many locators we manage
+                        --itsValueLocatorCount;
+                    }
+                }
+            }
+        };
     }
 
     /**

Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/NameIndexer.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/NameIndexer.java?view=diff&rev=564424&r1=564423&r2=564424
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/NameIndexer.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/NameIndexer.java Thu Aug  9 16:40:03 2007
@@ -56,8 +56,9 @@
     private SymbolTable symbols;
 
     private String name;
-    private String pattern;
+    private IndexPattern pattern;
     private boolean wildcard;
+    private IndexerEventHandler handler;
 
 
     public NameIndexer() {
@@ -69,10 +70,12 @@
         try {
             name = config.getAttribute(NAME);
 
-            pattern = config.getAttribute(PATTERN);
+            String pattern = config.getAttribute(PATTERN);
             wildcard = pattern.indexOf('*') != -1;
+            this.pattern = new IndexPattern(collection.getSymbols(), pattern, null);
 
             setLocation(name);
+            setupHandler();
         } catch (Exception e) {
             if (log.isWarnEnabled()) {
                 log.warn("ignored exception", e);
@@ -80,6 +83,26 @@
         }
     }
 
+    private void setupHandler() {
+        handler = new BasicIndexerEventHandler() {
+            public void onNameAdded(IndexPattern pattern, Key key, short elemID, short attrID) throws DBException {
+                try {
+                    addValue(getCombinedValue(key, elemID, attrID), 0);
+                } catch (IOException e) {
+                    throw new BTreeCorruptException("Corruption detected on add", e);
+                }
+            }
+
+            public void onNameDeleted(IndexPattern pattern, Key key, short elemID, short attrID) throws DBException {
+                try {
+                    removeValue(getCombinedValue(key, elemID, attrID));
+                } catch (IOException e) {
+                    throw new BTreeCorruptException("Corruption detected on remove", e);
+                }
+            }
+        };
+    }
+
     public String getName() {
         return name;
     }
@@ -103,55 +126,27 @@
         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(getCombinedValue(key, pos, len, elemID, attrID));
-        } catch (IOException e) {
-            throw new BTreeCorruptException("Corruption detected on remove", e);
-        }
+    public IndexPattern[] getPatterns() {
+        return new IndexPattern[] { pattern };
     }
 
-    public void add(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
-        try {
-            addValue(getCombinedValue(key, pos, len, elemID, attrID), 0);
-        } catch (IOException e) {
-            throw new BTreeCorruptException("Corruption detected on add", e);
-        }
-    }
-
-    private Value getCombinedValue(Key key, int pos, int len, short elemID, short attrID) {
+    private Value getCombinedValue(Key key, short elemID, short attrID) {
         Value result;
         try {
             int l = key.getLength();
-            byte[] b = new byte[l + 13];
+            byte[] b = new byte[l + 5];
 
             // Write the key
             key.copyTo(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         & 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         & 0xFF);
-
             // Write the elemID
-            b[l + 9] = (byte) ((elemID >>> 8) & 0xFF);
-            b[l + 10] = (byte) ( elemID       & 0xFF);
+            b[l + 1] = (byte) ((elemID >>> 8) & 0xFF);
+            b[l + 2] = (byte) ( elemID       & 0xFF);
 
             // Write the attrID
-            b[l + 11] = (byte) ((attrID >>> 8) & 0xFF);
-            b[l + 12] = (byte) ( attrID        & 0xFF);
+            b[l + 3] = (byte) ((attrID >>> 8) & 0xFF);
+            b[l + 4] = (byte) ( attrID        & 0xFF);
 
             result = new Value(b);
         } catch (Exception e) {
@@ -162,15 +157,13 @@
 
     private IndexMatch getIndexMatch(Value v) {
         byte[] b = v.getData();
-        int l = b.length - 13;
-        Key key = new Key(b, 0, b.length - 13);
+        int l = b.length - 5;
+        Key key = new Key(b, 0, b.length - 5);
 
-        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]);
+        short elemID = (short) ((b[l + 1] << 8) | b[l + 2]);
+        short attrID = (short) ((b[l + 3] << 8) | b[l + 4]);
 
-        return new IndexMatch(key, pos, len, elemID, attrID);
+        return new IndexMatch(key, elemID, attrID);
     }
 
     public IndexMatch[] queryMatches(final IndexQuery query) throws DBException {
@@ -201,5 +194,9 @@
         }
 
         return (IndexMatch[]) results.toArray(EmptyMatches);
+    }
+
+    public IndexerEventHandler getIndexerEventHandler() {
+        return handler;
     }
 }

Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/ValueIndexer.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/ValueIndexer.java?view=diff&rev=564424&r1=564423&r2=564424
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/ValueIndexer.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/ValueIndexer.java Thu Aug  9 16:40:03 2007
@@ -84,10 +84,11 @@
     private SymbolTable symbols;
 
     private String name;
-    private String pattern;
+    private IndexPattern pattern;
     private int type;
     private int typeSize = 32;
     private boolean wildcard;
+    private IndexerEventHandler handler;
 
 
     public ValueIndexer() {
@@ -108,7 +109,7 @@
         try {
             name = config.getAttribute(NAME);
 
-            pattern = config.getAttribute(PATTERN);
+            String pattern = config.getAttribute(PATTERN);
             wildcard = pattern.indexOf('*') != -1;
 
             // Determine the Index Type
@@ -141,9 +142,11 @@
                 }
             }
 
+            this.pattern = new IndexPattern(collection.getSymbols(), pattern, null);
             typeSize = sizes[type];
 
             setLocation(name);
+            setupHandler();
         } catch (Exception e) {
             if (log.isWarnEnabled()) {
                 log.warn("ignored exception", e);
@@ -151,6 +154,57 @@
         }
     }
 
+    private void setupHandler() {
+        handler = new BasicIndexerEventHandler() {
+            public void onValueAdded(IndexPattern pattern, 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.isWarnEnabled()) {
+                        log.warn("ignored exception", e);
+                    }
+                }
+            }
+
+            public void onValueDeleted(IndexPattern pattern, 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.isWarnEnabled()) {
+                        log.warn("ignored exception", e);
+                    }
+                }
+            }
+        };
+    }
+
     public String getName() {
         return name;
     }
@@ -174,8 +228,8 @@
         return STYLE_NODEVALUE;
     }
 
-    public String getPattern() {
-        return pattern;
+    public IndexPattern[] getPatterns() {
+        return new IndexPattern[] { pattern };
     }
 
     /**
@@ -351,53 +405,6 @@
         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.isWarnEnabled()) {
-                log.warn("ignored exception", 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.isWarnEnabled()) {
-                log.warn("ignored exception", e);
-            }
-        }
-    }
-
     public IndexMatch[] queryMatches(final IndexQuery query) throws DBException {
         // Pre-process the value-set for typing and trimming
         if (type != STRING) {
@@ -446,5 +453,9 @@
         }
 
         return (IndexMatch[]) results.toArray(EmptyMatches);
+    }
+
+    public IndexerEventHandler getIndexerEventHandler() {
+        return handler;
     }
 }



Re: svn commit: r564424 - /xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/

Posted by Natalia Shilenkova <ns...@gmail.com>.
On 8/9/07, Vadim Gritsenko <va...@reverycodes.com> wrote:
> natalia@apache.org wrote:
> > @@ -175,12 +163,9 @@
> >       * Drop all indexers
> >       */
> >      public synchronized void drop() {
> > -        // Get a copy of idxList
> > -        IndexerInfo[] idx = idxList;
> > -
> >          // Drop indexes
> > -        for (int i = 0; i < idx.length; i++) {
> > -            drop(idx[i].name);
> > +        for (Iterator i = indexes.keySet().iterator(); i.hasNext(); ) {
> > +            drop((String) i.next());
> >          }
> >      }
>
> This causes concurrent modification exception: call to drop(String) modifies
> indexes collection.

Oops... Thanks.

> Hmm, test suite needs some improvement ;)

I am not sure that there should be a testcase for that specific issue :)

Natalia

Re: svn commit: r564424 - /xml/xindice/trunk/java/src/org/apache/xindice/core/indexer/

Posted by Vadim Gritsenko <va...@reverycodes.com>.
natalia@apache.org wrote:
> @@ -175,12 +163,9 @@
>       * Drop all indexers
>       */
>      public synchronized void drop() {
> -        // Get a copy of idxList
> -        IndexerInfo[] idx = idxList;
> -
>          // Drop indexes
> -        for (int i = 0; i < idx.length; i++) {
> -            drop(idx[i].name);
> +        for (Iterator i = indexes.keySet().iterator(); i.hasNext(); ) {
> +            drop((String) i.next());
>          }
>      }

This causes concurrent modification exception: call to drop(String) modifies 
indexes collection.

Hmm, test suite needs some improvement ;)

Vadim