You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2010/04/11 19:51:52 UTC

svn commit: r932958 [1/2] - in /jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3: observation/ query/ query/qom/

Author: thomasm
Date: Sun Apr 11 17:51:52 2010
New Revision: 932958

URL: http://svn.apache.org/viewvc?rev=932958&view=rev
Log:
Some code for a Jackrabbit 3 prototype

Added:
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddLock.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddMixin.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddNode.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddProperty.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventImpl.java
      - copied, changed from r928437, jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/Change.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventList.java
      - copied, changed from r928437, jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/ChangeList.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventModifyProperty.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventRemoveNode.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/ParserSQL2.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/QueryImpl.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/QueryManagerImpl.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/QueryResultImpl.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/RowImpl.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/RowIteratorImpl.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/qom/
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/qom/QueryObjectModelFactoryImpl.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/qom/QueryObjectModelImpl.java
Modified:
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventConsumer.java
    jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/ObservationManagerImpl.java

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddLock.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddLock.java?rev=932958&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddLock.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddLock.java Sun Apr 11 17:51:52 2010
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+package org.apache.jackrabbit.j3.observation;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.Event;
+import org.apache.jackrabbit.j3.SessionImpl;
+import org.apache.jackrabbit.j3.lock.LockImpl;
+
+
+/**
+ * Add a lock.
+ */
+public class EventAddLock extends EventImpl {
+    private final LockImpl lock;
+
+    public EventAddLock(SessionImpl session, LockImpl lock) {
+        super(session);
+        this.lock = lock;
+    }
+
+    public void apply() throws RepositoryException {
+        lock.getNode().doAddLock(lock);
+    }
+
+    public int getType() {
+        return Event.PROPERTY_ADDED;
+    }
+
+}

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddMixin.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddMixin.java?rev=932958&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddMixin.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddMixin.java Sun Apr 11 17:51:52 2010
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+package org.apache.jackrabbit.j3.observation;
+
+import javax.jcr.lock.LockException;
+import javax.jcr.observation.Event;
+import org.apache.jackrabbit.j3.NodeImpl;
+import org.apache.jackrabbit.j3.SessionImpl;
+import org.apache.jackrabbit.j3.mc.Val;
+
+/**
+ * Add a mixin.
+ */
+public class EventAddMixin extends EventImpl {
+    private final NodeImpl node;
+    private final Val mixin;
+
+    public EventAddMixin(SessionImpl session, NodeImpl node, Val mixin) {
+        super(session);
+        this.node = node;
+        this.mixin = mixin;
+    }
+
+    public void apply() throws LockException {
+        node.doAddMixin(mixin);
+    }
+
+    public int getType() {
+        return Event.PROPERTY_CHANGED;
+    }
+
+}

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddNode.java?rev=932958&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddNode.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddNode.java Sun Apr 11 17:51:52 2010
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+package org.apache.jackrabbit.j3.observation;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
+import javax.jcr.observation.Event;
+import org.apache.jackrabbit.j3.NodeImpl;
+import org.apache.jackrabbit.j3.SessionImpl;
+import org.apache.jackrabbit.j3.mc.Val;
+
+/**
+ * Add a node.
+ */
+public class EventAddNode extends EventImpl {
+    private final NodeImpl newNode;
+    private final Val childName;
+    private String path;
+
+    public EventAddNode(SessionImpl session, Val childName, NodeImpl newNode) {
+        super(session);
+        this.childName = childName;
+        this.newNode = newNode;
+    }
+
+    public void apply() throws LockException {
+        newNode.getParentNode().doAddNode(childName, newNode);
+    }
+
+    public int getType() {
+        return Event.NODE_ADDED;
+    }
+
+    public String getPath() throws RepositoryException {
+        if (path == null) {
+            path = newNode.getPath();
+        }
+        return path;
+    }
+
+}
\ No newline at end of file

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddProperty.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddProperty.java?rev=932958&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddProperty.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventAddProperty.java Sun Apr 11 17:51:52 2010
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.jackrabbit.j3.observation;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
+import javax.jcr.observation.Event;
+import org.apache.jackrabbit.j3.NodeImpl;
+import org.apache.jackrabbit.j3.SessionImpl;
+import org.apache.jackrabbit.j3.mc.Val;
+
+/**
+ * Add a property.
+ */
+public class EventAddProperty extends EventImpl {
+    private final NodeImpl node;
+    private final Val propertyName;
+    private final Val value;
+    private String path;
+
+    public EventAddProperty(SessionImpl session, NodeImpl node, Val propertyName, Val value) {
+        super(session);
+        this.node = node;
+        this.propertyName = propertyName;
+        this.value = value;
+    }
+
+    public void apply() throws LockException {
+        node.doSetProperty(propertyName, value);
+    }
+
+    public int getType() {
+        return Event.PROPERTY_ADDED;
+    }
+
+    public String getPath() throws RepositoryException {
+        if (path == null) {
+            path = node.getPath() + "/" + eventList.getSession().nameToString(propertyName);
+        }
+        return path;
+    }
+
+}
\ No newline at end of file

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventConsumer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventConsumer.java?rev=932958&r1=932957&r2=932958&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventConsumer.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventConsumer.java Sun Apr 11 17:51:52 2010
@@ -17,14 +17,13 @@
 package org.apache.jackrabbit.j3.observation;
 
 import java.util.HashSet;
-import java.util.Iterator;
 import javax.jcr.RepositoryException;
 import javax.jcr.observation.Event;
 import javax.jcr.observation.EventIterator;
 import javax.jcr.observation.EventListener;
-import org.apache.jackrabbit.j3.Change;
-import org.apache.jackrabbit.j3.ChangeList;
+import org.apache.jackrabbit.j3.RangeIteratorImpl;
 import org.apache.jackrabbit.j3.SessionImpl;
+import org.apache.jackrabbit.j3.util.Log;
 
 /**
  * A observation listener wrapper.
@@ -87,80 +86,36 @@ public class EventConsumer {
         return nodeTypeNameSet.contains(nodeTypeName);
     }
 
-    void dispatch(ChangeList events) {
+    void dispatch(EventList events) {
         if (noLocal && events.getSession() == session) {
             return;
         }
-        listener.onEvent(new FilteredEventIterator(events));
+        listener.onEvent(new FilteredEventIterator(events, session.getLog()));
     }
 
     /**
      * An event iterator that filters events for a given event listener.
      */
-    class FilteredEventIterator implements EventIterator {
+    class FilteredEventIterator extends RangeIteratorImpl<EventImpl> implements EventIterator {
 
-        private final Iterator<Change> iterator;
-        private Event next;
-        private int pos;
-
-        FilteredEventIterator(ChangeList events) {
-            iterator = events.getChangeList().iterator();
-            go();
-        }
-
-        private void go() {
-            try {
-                while (true) {
-                    if (!iterator.hasNext()) {
-                        next = null;
-                        return;
-                    }
-                    next = iterator.next();
-                    if (!matchesType(next.getType())) {
-                        continue;
-                    }
-                    if (!matchesIdentifier(next.getIdentifier())) {
-                        continue;
-                    }
-                    // TODO matchesNodeTypeName
-                    // TODO matchesPath
-                    return;
-                }
-            } catch (RepositoryException e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        public Event nextEvent() {
-            Event result = next;
-            go();
-            return result;
-        }
-
-        public long getPosition() {
-            return pos;
-        }
-
-        public long getSize() {
-            return -1;
+        FilteredEventIterator(EventList events, Log log) {
+            super(events.getChangeList().iterator(), -1, log);
         }
 
-        public void skip(long skipNum) {
-            for (int i = 0; i < skipNum; i++) {
-                go();
+        public boolean skip(EventImpl x) throws RepositoryException {
+            if (!matchesType(x.getType())) {
+                return true;
             }
+            if (!matchesIdentifier(x.getIdentifier())) {
+                return true;
+            }
+            return false;
         }
 
-        public boolean hasNext() {
-            return next != null;
-        }
-
-        public Object next() {
-            return nextEvent();
-        }
-
-        public void remove() {
-            throw new UnsupportedOperationException();
+        public Event nextEvent() {
+            EventImpl e = goNext();
+            log.codeAssign(e, this, "nextEvent");
+            return e;
         }
 
     }

Copied: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventImpl.java (from r928437, jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/Change.java)
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventImpl.java?p2=jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventImpl.java&p1=jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/Change.java&r1=928437&r2=932958&rev=932958&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/Change.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventImpl.java Sun Apr 11 17:51:52 2010
@@ -14,207 +14,69 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.j3;
+package org.apache.jackrabbit.j3.observation;
 
 import java.util.Collections;
 import java.util.Map;
 import javax.jcr.RepositoryException;
-import javax.jcr.lock.LockException;
 import javax.jcr.observation.Event;
-import org.apache.jackrabbit.j3.lock.LockImpl;
-import org.apache.jackrabbit.j3.mc.Val;
+import org.apache.jackrabbit.j3.SessionImpl;
+import org.apache.jackrabbit.j3.util.Log;
+import org.apache.jackrabbit.j3.util.LogObject;
 
 /**
- * A change.
+ * The implementation of the corresponding JCR interface.
  */
-public abstract class Change implements Event {
+public abstract class EventImpl implements Event, LogObject {
 
-    private final ChangeList changeList;
+    protected final EventList eventList;
 
-    Change(SessionImpl session) {
-        this.changeList = session.getChangeList();
+    EventImpl(SessionImpl session) {
+        this.eventList = session.getEventList();
     }
 
     abstract void apply() throws RepositoryException;
 
+    protected Log getLog() {
+        return eventList.getLog();
+    }
+
     public String getUserData() {
-        return changeList.getUserData();
+        getLog().code(this, "getUserData");
+        return eventList.getUserData();
     }
 
     public String getUserID() {
-        return changeList.getUserID();
+        getLog().code(this, "getUserID");
+        return eventList.getUserID();
     }
 
     public long getDate() {
-        return changeList.getPersistedDate();
+        getLog().code(this, "getDate");
+        return eventList.getPersistedDate();
     }
 
     public Map<String, String> getInfo() {
+        getLog().code(this, "getInfo");
         return Collections.emptyMap();
     }
 
     public String getIdentifier() {
+        getLog().code(this, "getIdentifier");
+        // TODO
         return null;
     }
 
     public String getPath() throws RepositoryException {
+        getLog().code(this, "getPath");
+        // TODO
         return null;
     }
 
-    public void applyAndAddChange() throws RepositoryException {
+    public void applyAndAdd() throws RepositoryException {
         apply();
-        changeList.add(this);
-    }
-
-}
-
-/**
- * Add a node.
- */
-class ChangeAddNode extends Change {
-    NodeImpl newNode;
-    Val childName;
-    private String path;
-
-    ChangeAddNode(SessionImpl session) {
-        super(session);
-    }
-
-    public void apply() throws LockException {
-        newNode.getParentNode().doAddNode(childName, newNode);
-    }
-
-    public int getType() {
-        return Event.NODE_ADDED;
-    }
-
-    public String getPath() throws RepositoryException {
-        if (path == null) {
-            path = newNode.getPath();
-        }
-        return path;
-    }
-
-}
-
-/**
- * Add a property.
- */
-class ChangeAddProperty extends Change {
-    NodeImpl node;
-    Val propertyName;
-    Val value;
-    private String path;
-
-    ChangeAddProperty(SessionImpl session) {
-        super(session);
-    }
-
-    public void apply() throws LockException {
-        node.doSetProperty(propertyName, value);
-    }
-
-    public int getType() {
-        return Event.PROPERTY_ADDED;
-    }
-
-    public String getPath() throws RepositoryException {
-        if (path == null) {
-            path = node.getPath() + "/" + node.getNodeState().nameToString(propertyName);
-        }
-        return path;
+        eventList.add(this);
     }
 
 }
 
-/**
- * Change a property.
- */
-class ChangeModifyProperty extends Change {
-    NodeImpl node;
-    Val propertyName;
-    Val value;
-    private String path;
-
-    ChangeModifyProperty(SessionImpl session) {
-        super(session);
-    }
-
-    public void apply() throws LockException {
-        node.doSetProperty(propertyName, value);
-    }
-
-    public int getType() {
-        return Event.PROPERTY_CHANGED;
-    }
-
-    public String getPath() throws RepositoryException {
-        if (path == null) {
-            path = node.getPath() + "/" + node.getNodeState().nameToString(propertyName);
-        }
-        return path;
-    }
-
-}
-
-/**
- * Remove a node.
- */
-class ChangeRemoveNode extends Change {
-    NodeImpl node;
-
-    ChangeRemoveNode(SessionImpl session) {
-        super(session);
-    }
-
-    public void apply() throws LockException {
-        // TODO remove all child nodes as well (maybe as a background process)
-        node.doRemove();
-    }
-
-    public int getType() {
-        return Event.NODE_REMOVED;
-    }
-
-}
-
-/**
- * Add a mixin.
- */
-class ChangeAddMixin extends Change {
-    NodeImpl node;
-    Val mixin;
-
-    ChangeAddMixin(SessionImpl session) {
-        super(session);
-    }
-
-    public void apply() throws LockException {
-        node.doAddMixin(mixin);
-    }
-
-    public int getType() {
-        return Event.PROPERTY_CHANGED;
-    }
-
-}
-
-/**
- * Add a lock.
- */
-class ChangeAddLock extends Change {
-    LockImpl lock;
-
-    ChangeAddLock(SessionImpl session) {
-        super(session);
-    }
-
-    public void apply() throws RepositoryException {
-        lock.getNode().doAddLock(lock);
-    }
-
-    public int getType() {
-        return Event.PROPERTY_ADDED;
-    }
-
-}
\ No newline at end of file

Copied: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventList.java (from r928437, jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/ChangeList.java)
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventList.java?p2=jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventList.java&p1=jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/ChangeList.java&r1=928437&r2=932958&rev=932958&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/ChangeList.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventList.java Sun Apr 11 17:51:52 2010
@@ -14,32 +14,40 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.j3;
+package org.apache.jackrabbit.j3.observation;
 
 import java.util.LinkedList;
 import javax.jcr.RepositoryException;
+import org.apache.jackrabbit.j3.SessionImpl;
+import org.apache.jackrabbit.j3.util.Log;
 
 /**
  * A list of changes.
  */
-public class ChangeList {
+public class EventList {
 
     private final SessionImpl session;
-    private final LinkedList<Change> changes = new LinkedList<Change>();
-    private final String userID;
+    private final Log log;
+    private final LinkedList<EventImpl> changes = new LinkedList<EventImpl>();
+    private final String userId;
     private long persistedDate;
     private String userData;
 
-    ChangeList(SessionImpl session) {
+    public EventList(SessionImpl session) {
         this.session = session;
-        this.userID = session.getUserID();
+        this.log = session.getLog();
+        this.userId = session.getUserId();
     }
 
     public SessionImpl getSession() {
         return session;
     }
 
-    void persisted() {
+    Log getLog() {
+        return log;
+    }
+
+    public void persisted() {
         persistedDate = System.currentTimeMillis();
         userData = session.getObservationUserData();
         session.getRepository().dispatchEvents(this);
@@ -50,12 +58,12 @@ public class ChangeList {
     }
 
     public void apply() throws RepositoryException {
-        for (Change c : changes) {
+        for (EventImpl c : changes) {
             c.apply();
         }
     }
 
-    public void add(Change change) {
+    public void add(EventImpl change) {
         changes.add(change);
     }
 
@@ -63,7 +71,7 @@ public class ChangeList {
         return "" + changes.size();
     }
 
-    public LinkedList<Change> getChangeList() {
+    public LinkedList<EventImpl> getChangeList() {
         return changes;
     }
 
@@ -72,7 +80,11 @@ public class ChangeList {
     }
 
     public String getUserID() {
-        return userID;
+        return userId;
+    }
+
+    public long size() {
+        return changes.size();
     }
 
 }

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventModifyProperty.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventModifyProperty.java?rev=932958&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventModifyProperty.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventModifyProperty.java Sun Apr 11 17:51:52 2010
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.jackrabbit.j3.observation;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
+import javax.jcr.observation.Event;
+import org.apache.jackrabbit.j3.NodeImpl;
+import org.apache.jackrabbit.j3.SessionImpl;
+import org.apache.jackrabbit.j3.mc.Val;
+
+/**
+ * Change a property.
+ */
+public class EventModifyProperty extends EventImpl {
+    private final NodeImpl node;
+    private final Val propertyName;
+    private final Val value;
+    private String path;
+
+    public EventModifyProperty(SessionImpl session, NodeImpl node, Val propertyName, Val value) {
+        super(session);
+        this.node = node;
+        this.propertyName = propertyName;
+        this.value = value;
+    }
+
+    public void apply() throws LockException {
+        node.doSetProperty(propertyName, value);
+    }
+
+    public int getType() {
+        return Event.PROPERTY_CHANGED;
+    }
+
+    public String getPath() throws RepositoryException {
+        if (path == null) {
+            path = node.getPath() + "/" + node.getNodeState().nameToString(propertyName);
+        }
+        return path;
+    }
+
+}
\ No newline at end of file

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventRemoveNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventRemoveNode.java?rev=932958&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventRemoveNode.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventRemoveNode.java Sun Apr 11 17:51:52 2010
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+package org.apache.jackrabbit.j3.observation;
+
+import javax.jcr.lock.LockException;
+import javax.jcr.observation.Event;
+import org.apache.jackrabbit.j3.NodeImpl;
+import org.apache.jackrabbit.j3.SessionImpl;
+
+/**
+ * Remove a node.
+ */
+public class EventRemoveNode extends EventImpl {
+    private final NodeImpl node;
+
+    public EventRemoveNode(SessionImpl session, NodeImpl node) {
+        super(session);
+        this.node = node;
+    }
+
+    public void apply() throws LockException {
+        // TODO remove all child nodes as well (maybe as a background process)
+        node.doRemove();
+    }
+
+    public int getType() {
+        return Event.NODE_REMOVED;
+    }
+
+}

Modified: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/ObservationManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/ObservationManagerImpl.java?rev=932958&r1=932957&r2=932958&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/ObservationManagerImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/ObservationManagerImpl.java Sun Apr 11 17:51:52 2010
@@ -17,38 +17,45 @@
 package org.apache.jackrabbit.j3.observation;
 
 import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.Collection;
 import javax.jcr.RepositoryException;
 import javax.jcr.observation.EventJournal;
 import javax.jcr.observation.EventListener;
 import javax.jcr.observation.EventListenerIterator;
 import javax.jcr.observation.ObservationManager;
-import org.apache.jackrabbit.j3.ChangeList;
+import org.apache.jackrabbit.j3.RangeIteratorImpl;
 import org.apache.jackrabbit.j3.SessionImpl;
+import org.apache.jackrabbit.j3.util.Log;
+import org.apache.jackrabbit.j3.util.LogObject;
 
 /**
- * The observation manager implementation.
+ * The implementation of the corresponding JCR interface.
  */
-public class ObservationManagerImpl implements ObservationManager {
+public class ObservationManagerImpl implements ObservationManager, LogObject {
 
     private final SessionImpl session;
+    private final Log log;
     private final ArrayList<EventConsumer> eventConsumers = new ArrayList<EventConsumer>();
 
     public ObservationManagerImpl(SessionImpl session) {
         this.session = session;
+        this.log = session.getLog();
     }
 
     public void setUserData(String userData) throws RepositoryException {
+        log.code(this, "setUserData", userData);
         session.setObservationUserData(userData);
     }
 
     public void addEventListener(EventListener listener, int eventTypes, String absPath, boolean isDeep, String[] uuid,
             String[] nodeTypeName, boolean noLocal) throws RepositoryException {
+        log.code(this, "addEventListener", listener, eventTypes, absPath, isDeep, uuid, nodeTypeName, noLocal);
         EventConsumer consumer = new EventConsumer(session, listener, eventTypes, absPath, isDeep, uuid, nodeTypeName, noLocal);
         eventConsumers.add(consumer);
     }
 
     public void removeEventListener(EventListener listener) throws RepositoryException {
+        log.code(this, "removeEventListener", listener);
         for (EventConsumer consumer : eventConsumers) {
             if (consumer.getListener() == listener) {
                 // TODO block until the listener has completed
@@ -59,16 +66,20 @@ public class ObservationManagerImpl impl
     }
 
     public EventListenerIterator getRegisteredEventListeners() throws RepositoryException {
-        return new EventListenerIteratorImpl();
+        EventListenerIteratorImpl e = new EventListenerIteratorImpl(eventConsumers, log);
+        log.codeAssign(e, this, "getRegisteredEventListeners");
+        return e;
     }
 
     public EventJournal getEventJournal() throws RepositoryException {
+        log.code(this, "getEventJournal");
         // TODO Auto-generated method stub
         return null;
     }
 
     public EventJournal getEventJournal(int eventTypes, String absPath, boolean isDeep, String[] uuid,
             String[] nodeTypeName) throws RepositoryException {
+        log.code(this, "getEventJournal", eventTypes, absPath, isDeep, uuid, nodeTypeName);
         // TODO Auto-generated method stub
         return null;
     }
@@ -76,49 +87,24 @@ public class ObservationManagerImpl impl
     /**
      * A event listener iterator implementation.
      */
-    class EventListenerIteratorImpl implements EventListenerIterator {
+    static class EventListenerIteratorImpl extends RangeIteratorImpl<EventConsumer> implements EventListenerIterator {
 
-        private final Iterator<EventConsumer> iterator;
-        private int pos;
-
-        EventListenerIteratorImpl() {
-            iterator = eventConsumers.iterator();
+        EventListenerIteratorImpl(Collection<EventConsumer> coll, Log log) {
+            super(coll.iterator(), coll.size(), log);
         }
 
         public EventListener nextEventListener() {
-            pos++;
-            return iterator.next().getListener();
-        }
-
-        public long getPosition() {
-            return pos;
-        }
-
-        public long getSize() {
-            return eventConsumers.size();
-        }
-
-        public void skip(long skipNum) {
-            for (long i = 0; i < skipNum; i++) {
-                next();
-            }
-        }
-
-        public boolean hasNext() {
-            return iterator.hasNext();
+            log.code(this, "nextEventListener");
+            return goNext().getListener();
         }
 
-        public Object next() {
+        public EventListener next() {
             return nextEventListener();
         }
 
-        public void remove() {
-            iterator.remove();
-        }
-
     }
 
-    public void dispatchEvents(ChangeList events) {
+    public void dispatchEvents(EventList events) {
         for (EventConsumer consumer : eventConsumers) {
             consumer.dispatch(events);
         }

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/ParserSQL2.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/ParserSQL2.java?rev=932958&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/ParserSQL2.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/ParserSQL2.java Sun Apr 11 17:51:52 2010
@@ -0,0 +1,1001 @@
+/*
+ * 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.
+ */
+package org.apache.jackrabbit.j3.query;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.query.qom.BindVariableValue;
+import javax.jcr.query.qom.Column;
+import javax.jcr.query.qom.Constraint;
+import javax.jcr.query.qom.DynamicOperand;
+import javax.jcr.query.qom.JoinCondition;
+import javax.jcr.query.qom.Literal;
+import javax.jcr.query.qom.Ordering;
+import javax.jcr.query.qom.PropertyExistence;
+import javax.jcr.query.qom.PropertyValue;
+import javax.jcr.query.qom.QueryObjectModel;
+import javax.jcr.query.qom.QueryObjectModelConstants;
+import javax.jcr.query.qom.QueryObjectModelFactory;
+import javax.jcr.query.qom.Selector;
+import javax.jcr.query.qom.Source;
+import javax.jcr.query.qom.StaticOperand;
+
+/**
+ * The SQL2 parser can convert a JCR-SQL2 query to a QueryObjectModel.
+ */
+public class ParserSQL2 {
+
+    // Character types, used during the tokenizer phase
+    private static final int CHAR_END = -1, CHAR_VALUE = 2, CHAR_QUOTED = 3;
+    private static final int CHAR_NAME = 4, CHAR_SPECIAL_1 = 5, CHAR_SPECIAL_2 = 6;
+    private static final int CHAR_STRING = 7, CHAR_DECIMAL = 8;
+
+    // Token types
+    private static final int KEYWORD = 1, IDENTIFIER = 2, PARAMETER = 3, END = 4, VALUE = 5;
+    private static final int MINUS = 12, PLUS = 13, OPEN = 14, CLOSE = 15;
+
+    // The query as an array of characters and character types
+    private String statement;
+    private char[] statementChars;
+    private int[] characterTypes;
+
+    // The current state of the parser
+    private int parseIndex;
+    private int currentTokenType;
+    private String currentToken;
+    private boolean currentTokenQuoted;
+    private Value currentValue;
+    private ArrayList<String> expected;
+
+    // The bind variables
+    private HashMap<String, BindVariableValue> bindVariables;
+
+    // The list of selectors of this query
+    private ArrayList<Selector> selectors;
+
+    // SQL injection protection: if disabled, literals are not allowed
+    private boolean allowTextLiterals = true, allowNumberLiterals = true;
+
+    private QueryObjectModelFactory factory;
+    private ValueFactory valueFactory;
+
+    /**
+     * Create a new parser. A parser can be re-used, but it is not thread safe.
+     *
+     * @param factory the query object model factory
+     * @param valueFactory the value factory
+     */
+    public ParserSQL2(QueryObjectModelFactory factory, ValueFactory valueFactory) {
+        this.factory = factory;
+        this.valueFactory = valueFactory;
+    }
+
+    /**
+     * Parse a JCR-SQL2 query and return the query object model
+     *
+     * @param query the query string
+     * @return the query object model
+     * @throws RepositoryException if parsing failed
+     */
+    public QueryObjectModel createQueryObjectModel(String query) throws RepositoryException {
+        initialize(query);
+        selectors = new ArrayList<Selector>();
+        expected = new ArrayList<String>();
+        bindVariables = new HashMap<String, BindVariableValue>();
+        read();
+        read("SELECT");
+        ArrayList<ColumnOrWildcard> list = parseColumns();
+        read("FROM");
+        Source source = parseSource();
+        Column[] columnArray = resolveColumns(list);
+        Constraint constraint = null;
+        if (readIf("WHERE")) {
+            constraint = parseConstraint();
+        }
+        Ordering[] orderings = null;
+        if (readIf("ORDER")) {
+            read("BY");
+            orderings = parseOrder();
+        }
+        if (currentToken.length() > 0) {
+            throw getSyntaxError("<end>");
+        }
+        return factory.createQuery(source, constraint, orderings, columnArray);
+    }
+
+    private Selector parseSelector() throws RepositoryException {
+        String nodeTypeName = readName();
+        if (readIf("AS")) {
+            String selectorName = readName();
+            return factory.selector(nodeTypeName, selectorName);
+        } else {
+            return factory.selector(nodeTypeName, nodeTypeName);
+        }
+    }
+
+    private String readName() throws RepositoryException {
+        if (readIf("[")) {
+            if (currentTokenType == VALUE) {
+                Value value = readString();
+                read("]");
+                return value.getString();
+            } else {
+                int level = 1;
+                StringBuilder buff = new StringBuilder();
+                while (true) {
+                    if (isToken("]")) {
+                        if (--level <= 0) {
+                            read();
+                            break;
+                        }
+                    } else if (isToken("[")) {
+                        level++;
+                    }
+                    buff.append(readAny());
+                }
+                return buff.toString();
+            }
+        } else {
+            return readAny();
+        }
+    }
+
+    private Source parseSource() throws RepositoryException {
+        Selector selector = parseSelector();
+        selectors.add(selector);
+        Source source = selector;
+        while (true) {
+            String joinType;
+            if (readIf("RIGHT")) {
+                read("OUTER");
+                joinType = QueryObjectModelConstants.JCR_JOIN_TYPE_RIGHT_OUTER;
+            } else if (readIf("LEFT")) {
+                read("OUTER");
+                joinType = QueryObjectModelConstants.JCR_JOIN_TYPE_LEFT_OUTER;
+            } else if (readIf("INNER")) {
+                joinType = QueryObjectModelConstants.JCR_JOIN_TYPE_INNER;
+            } else {
+                break;
+            }
+            read("JOIN");
+            selector = parseSelector();
+            selectors.add(selector);
+            read("ON");
+            JoinCondition on = parseJoinCondition();
+            source = factory.join(source, selector, joinType, on);
+        }
+        return source;
+    }
+
+    private JoinCondition parseJoinCondition() throws RepositoryException {
+        boolean identifier = currentTokenType == IDENTIFIER;
+        String name = readName();
+        JoinCondition c;
+        if (identifier && readIf("(")) {
+            if ("ISSAMENODE".equalsIgnoreCase(name)) {
+                String selector1 = readName();
+                read(",");
+                String selector2 = readName();
+                if (readIf(",")) {
+                    c = factory.sameNodeJoinCondition(selector1, selector2, readPath());
+                } else {
+                    // TODO verify "." is correct
+                    c = factory.sameNodeJoinCondition(selector1, selector2, ".");
+                }
+            } else if ("ISCHILDNODE".equalsIgnoreCase(name)) {
+                String childSelector = readName();
+                read(",");
+                c = factory.childNodeJoinCondition(childSelector, readName());
+            } else if ("ISDESCENDANTNODE".equalsIgnoreCase(name)) {
+                String descendantSelector = readName();
+                read(",");
+                c = factory.descendantNodeJoinCondition(descendantSelector, readName());
+            } else {
+                throw getSyntaxError("ISSAMENODE, ISCHILDNODE, or ISDESCENDANTNODE");
+            }
+            read(")");
+            return c;
+        } else {
+            String selector1 = name;
+            read(".");
+            String property1 = readName();
+            read("=");
+            String selector2 = readName();
+            read(".");
+            return factory.equiJoinCondition(selector1, property1, selector2, readName());
+        }
+    }
+
+    private Constraint parseConstraint() throws RepositoryException {
+        Constraint a = parseAnd();
+        while (readIf("OR")) {
+            a = factory.or(a, parseAnd());
+        }
+        return a;
+    }
+
+    private Constraint parseAnd() throws RepositoryException {
+        Constraint a = parseCondition();
+        while (readIf("AND")) {
+            a = factory.and(a, parseCondition());
+        }
+        return a;
+    }
+
+    private Constraint parseCondition() throws RepositoryException {
+        Constraint a;
+        if (readIf("NOT")) {
+            a = factory.not(parseConstraint());
+        } else if (readIf("(")) {
+            a = parseConstraint();
+            read(")");
+        } else if (currentTokenType == IDENTIFIER) {
+            String identifier = readName();
+            if (readIf("(")) {
+                a = parseConditionFuntionIf(identifier);
+                if (a == null) {
+                    DynamicOperand op = parseExpressionFunction(identifier);
+                    a = parseCondition(op);
+                }
+            } else if (readIf(".")) {
+                a = parseCondition(factory.propertyValue(identifier, readName()));
+            } else {
+                a = parseCondition(factory.propertyValue(getOnlySelectorName(), identifier));
+            }
+        } else if ("[".equals(currentToken)) {
+            String name = readName();
+            if (readIf(".")) {
+                a = parseCondition(factory.propertyValue(name, readName()));
+            } else {
+                a = parseCondition(factory.propertyValue(getOnlySelectorName(), name));
+            }
+        } else {
+            throw getSyntaxError();
+        }
+        return a;
+    }
+
+    private Constraint parseCondition(DynamicOperand left) throws RepositoryException {
+        Constraint c;
+
+        if (readIf("=")) {
+            String operator = QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO;
+            c = factory.comparison(left, operator, parseStaticOperand());
+        } else if (readIf("<>")) {
+            String operator = QueryObjectModelConstants.JCR_OPERATOR_NOT_EQUAL_TO;
+            c = factory.comparison(left, operator, parseStaticOperand());
+        } else if (readIf("<")) {
+            String operator = QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN;
+            c = factory.comparison(left, operator, parseStaticOperand());
+        } else if (readIf(">")) {
+            String operator = QueryObjectModelConstants.JCR_OPERATOR_GREATER_THAN;
+            c = factory.comparison(left, operator, parseStaticOperand());
+        } else if (readIf("<=")) {
+            String operator = QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO;
+            c = factory.comparison(left, operator, parseStaticOperand());
+        } else if (readIf(">=")) {
+            String operator = QueryObjectModelConstants.JCR_OPERATOR_GREATER_THAN_OR_EQUAL_TO;
+            c = factory.comparison(left, operator, parseStaticOperand());
+        } else if (readIf("LIKE")) {
+            String operator = QueryObjectModelConstants.JCR_OPERATOR_LIKE;
+            c = factory.comparison(left, operator, parseStaticOperand());
+        } else if (readIf("IS")) {
+            boolean not = readIf("NOT");
+            read("NULL");
+            if (!(left instanceof PropertyValue)) {
+                throw getSyntaxError("propertyName (NOT NULL is only supported for properties)");
+            }
+            PropertyValue p = (PropertyValue) left;
+            c = getPropertyExistence(p);
+            if (!not) {
+                c = factory.not(c);
+            }
+        } else if (readIf("NOT")) {
+            if (readIf("IS")) {
+                read("NULL");
+                if (!(left instanceof PropertyValue)) {
+                    throw new RepositoryException(
+                            "Only property values can be tested for NOT IS NULL; got: "
+                            + left.getClass().getName());
+                }
+                PropertyValue pv = (PropertyValue) left;
+                c = getPropertyExistence(pv);
+            } else {
+                read("LIKE");
+                String operator = QueryObjectModelConstants.JCR_OPERATOR_LIKE;
+                c = factory.comparison(left, operator, parseStaticOperand());
+                c = factory.not(c);
+            }
+        } else {
+            throw getSyntaxError();
+        }
+        return c;
+    }
+
+    private PropertyExistence getPropertyExistence(PropertyValue p) throws InvalidQueryException, RepositoryException {
+        return factory.propertyExistence(p.getSelectorName(), p.getPropertyName());
+    }
+
+    private Constraint parseConditionFuntionIf(String functionName) throws RepositoryException {
+        Constraint c;
+        if ("CONTAINS".equalsIgnoreCase(functionName)) {
+            String name = readName();
+            if (readIf(".")) {
+                if (readIf("*")) {
+                    read(",");
+                    c = factory.fullTextSearch(
+                            name, null, parseStaticOperand());
+                } else {
+                    String selector = name;
+                    name = readName();
+                    read(",");
+                    c = factory.fullTextSearch(
+                            selector, name, parseStaticOperand());
+                }
+            } else {
+                read(",");
+                c = factory.fullTextSearch(
+                        getOnlySelectorName(), name,
+                        parseStaticOperand());
+            }
+        } else if ("ISSAMENODE".equalsIgnoreCase(functionName)) {
+            String name = readName();
+            if (readIf(",")) {
+                c = factory.sameNode(name, readPath());
+            } else {
+                c = factory.sameNode(getOnlySelectorName(), name);
+            }
+        } else if ("ISCHILDNODE".equalsIgnoreCase(functionName)) {
+            String name = readName();
+            if (readIf(",")) {
+                c = factory.childNode(name, readPath());
+            } else {
+                c = factory.childNode(getOnlySelectorName(), name);
+            }
+        } else if ("ISDESCENDANTNODE".equalsIgnoreCase(functionName)) {
+            String name = readName();
+            if (readIf(",")) {
+                c = factory.descendantNode(name, readPath());
+            } else {
+                c = factory.descendantNode(getOnlySelectorName(), name);
+            }
+        } else {
+            return null;
+        }
+        read(")");
+        return c;
+    }
+
+    private String readPath() throws RepositoryException {
+        return readName();
+    }
+
+    private DynamicOperand parseDynamicOperand() throws RepositoryException {
+        boolean identifier = currentTokenType == IDENTIFIER;
+        String name = readName();
+        if (identifier && readIf("(")) {
+            return parseExpressionFunction(name);
+        } else {
+            return parsePropertyValue(name);
+        }
+    }
+
+    private DynamicOperand parseExpressionFunction(String functionName) throws RepositoryException {
+        DynamicOperand op;
+        if ("LENGTH".equalsIgnoreCase(functionName)) {
+            op = factory.length(parsePropertyValue(readName()));
+        } else if ("NAME".equalsIgnoreCase(functionName)) {
+            if (isToken(")")) {
+                op = factory.nodeName(getOnlySelectorName());
+            } else {
+                op = factory.nodeName(readName());
+            }
+        } else if ("LOCALNAME".equalsIgnoreCase(functionName)) {
+            if (isToken(")")) {
+                op = factory.nodeLocalName(getOnlySelectorName());
+            } else {
+                op = factory.nodeLocalName(readName());
+            }
+        } else if ("SCORE".equalsIgnoreCase(functionName)) {
+            if (isToken(")")) {
+                op = factory.fullTextSearchScore(getOnlySelectorName());
+            } else {
+                op = factory.fullTextSearchScore(readName());
+            }
+        } else if ("LOWER".equalsIgnoreCase(functionName)) {
+            op = factory.lowerCase(parseDynamicOperand());
+        } else if ("UPPER".equalsIgnoreCase(functionName)) {
+            op = factory.upperCase(parseDynamicOperand());
+        } else {
+            throw getSyntaxError("LENGTH, NAME, LOCALNAME, SCORE, LOWER, UPPER, or CAST");
+        }
+        read(")");
+        return op;
+    }
+
+    private PropertyValue parsePropertyValue(String name) throws RepositoryException {
+        if (readIf(".")) {
+            return factory.propertyValue(name, readName());
+        } else {
+            return factory.propertyValue(getOnlySelectorName(), name);
+        }
+    }
+
+    private StaticOperand parseStaticOperand() throws RepositoryException {
+        if (currentTokenType == PLUS) {
+            read();
+        } else if (currentTokenType == MINUS) {
+            read();
+            if (currentTokenType != VALUE) {
+                throw getSyntaxError("number");
+            }
+            int valueType = currentValue.getType();
+            switch (valueType) {
+            case PropertyType.LONG:
+                currentValue = valueFactory.createValue(-currentValue.getLong());
+                break;
+            case PropertyType.DOUBLE:
+                currentValue = valueFactory.createValue(-currentValue.getDouble());
+                break;
+            case PropertyType.BOOLEAN:
+                currentValue = valueFactory.createValue(!currentValue.getBoolean());
+                break;
+            case PropertyType.DECIMAL:
+                currentValue = valueFactory.createValue(currentValue.getDecimal().negate());
+                break;
+            default:
+                throw getSyntaxError("Illegal operation: -" + currentValue);
+            }
+        }
+        if (currentTokenType == VALUE) {
+            Literal literal = getUncastLiteral(currentValue);
+            read();
+            return literal;
+        } else if (currentTokenType == PARAMETER) {
+            read();
+            String name = readName();
+            if (readIf(":")) {
+                name = name + ":" + readName();
+            }
+            BindVariableValue var = bindVariables.get(name);
+            if (var == null) {
+                var = factory.bindVariable(name);
+                bindVariables.put(name, var);
+            }
+            return var;
+        } else if (readIf("TRUE")) {
+            Literal literal = getUncastLiteral(valueFactory.createValue(true));
+            return literal;
+        } else if (readIf("FALSE")) {
+            Literal literal = getUncastLiteral(valueFactory.createValue(false));
+            return literal;
+        } else if (readIf("CAST")) {
+            read("(");
+            StaticOperand op = parseStaticOperand();
+            if (!(op instanceof Literal)) {
+                throw getSyntaxError("literal");
+            }
+            Literal literal = (Literal) op;
+            Value value = literal.getLiteralValue();
+            read("AS");
+            value = parseCastAs(value);
+            read(")");
+            // CastLiteral
+            literal = factory.literal(value);
+            return literal;
+        } else {
+            throw getSyntaxError("static operand");
+        }
+    }
+
+    /**
+     * Create a literal from a parsed value.
+     *
+     * @param value the original value
+     * @return the literal
+     */
+    private Literal getUncastLiteral(Value value) throws RepositoryException {
+        return factory.literal(value);
+    }
+
+    private Value parseCastAs(Value value) throws RepositoryException {
+        if (readIf("STRING")) {
+            return valueFactory.createValue(value.getString());
+        } else if (readIf("BINARY")) {
+            return valueFactory.createValue(value.getBinary());
+        } else if (readIf("DATE")) {
+            return valueFactory.createValue(value.getDate());
+        } else if (readIf("LONG")) {
+            return valueFactory.createValue(value.getLong());
+        } else if (readIf("DOUBLE")) {
+            return valueFactory.createValue(value.getDouble());
+        } else if (readIf("DECIMAL")) {
+            return valueFactory.createValue(value.getDecimal());
+        } else if (readIf("BOOLEAN")) {
+            return valueFactory.createValue(value.getBoolean());
+        } else if (readIf("NAME")) {
+            return valueFactory.createValue(value.getString(), PropertyType.NAME);
+        } else if (readIf("PATH")) {
+            return valueFactory.createValue(value.getString(), PropertyType.PATH);
+        } else if (readIf("REFERENCE")) {
+            return valueFactory.createValue(value.getString(), PropertyType.REFERENCE);
+        } else if (readIf("WEAKREFERENCE")) {
+            return valueFactory.createValue(value.getString(), PropertyType.WEAKREFERENCE);
+        } else if (readIf("URI")) {
+            return valueFactory.createValue(value.getString(), PropertyType.URI);
+        } else {
+            throw getSyntaxError("data type (STRING|BINARY|...)");
+        }
+    }
+
+    private Ordering[] parseOrder() throws RepositoryException {
+        ArrayList<Ordering> orderList = new ArrayList<Ordering>();
+        do {
+            Ordering ordering;
+            DynamicOperand op = parseDynamicOperand();
+            if (readIf("DESC")) {
+                ordering = factory.descending(op);
+            } else {
+                readIf("ASC");
+                ordering = factory.ascending(op);
+            }
+            orderList.add(ordering);
+        } while (readIf(","));
+        Ordering[] orderings = new Ordering[orderList.size()];
+        orderList.toArray(orderings);
+        return orderings;
+    }
+
+    private ArrayList<ColumnOrWildcard> parseColumns() throws RepositoryException {
+        ArrayList<ColumnOrWildcard> list = new ArrayList<ColumnOrWildcard>();
+        if (readIf("*")) {
+            list.add(new ColumnOrWildcard());
+        } else {
+            do {
+                ColumnOrWildcard column = new ColumnOrWildcard();
+                column.propertyName = readName();
+                if (readIf(".")) {
+                    column.selectorName = column.propertyName;
+                    if (readIf("*")) {
+                        column.propertyName = null;
+                    } else {
+                        column.propertyName = readName();
+                        if (readIf("AS")) {
+                            column.columnName = readName();
+                        }
+                    }
+                } else {
+                    if (readIf("AS")) {
+                        column.columnName = readName();
+                    }
+                }
+                list.add(column);
+            } while (readIf(","));
+        }
+        return list;
+    }
+
+    private Column[] resolveColumns(ArrayList<ColumnOrWildcard> list) throws RepositoryException {
+        ArrayList<Column> columns = new ArrayList<Column>();
+        for (ColumnOrWildcard c : list) {
+            if (c.propertyName == null) {
+                for (Selector selector : selectors) {
+                    if (c.selectorName == null
+                            || c.selectorName
+                                    .equals(selector.getSelectorName())) {
+                        Column column = factory.column(selector
+                                .getSelectorName(), null, null);
+                        columns.add(column);
+                    }
+                }
+            } else {
+                Column column;
+                if (c.selectorName != null) {
+                    column = factory.column(c.selectorName, c.propertyName, c.columnName);
+                } else if (c.columnName != null) {
+                    column = factory.column(getOnlySelectorName(), c.propertyName, c.columnName);
+                } else {
+                    column = factory.column(getOnlySelectorName(), c.propertyName, c.propertyName);
+                }
+                columns.add(column);
+            }
+        }
+        Column[] array = new Column[columns.size()];
+        columns.toArray(array);
+        return array;
+    }
+
+    private boolean readIf(String token) throws RepositoryException {
+        if (isToken(token)) {
+            read();
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isToken(String token) {
+        boolean result = token.equalsIgnoreCase(currentToken) && !currentTokenQuoted;
+        if (result) {
+            return true;
+        }
+        addExpected(token);
+        return false;
+    }
+
+    private void read(String expected) throws RepositoryException {
+        if (!expected.equalsIgnoreCase(currentToken) || currentTokenQuoted) {
+            throw getSyntaxError(expected);
+        }
+        read();
+    }
+
+    private String readAny() throws RepositoryException {
+        if (currentTokenType == END) {
+            throw getSyntaxError("a token");
+        }
+        String s;
+        if (currentTokenType == VALUE) {
+            s = currentValue.getString();
+        } else {
+            s = currentToken;
+        }
+        read();
+        return s;
+    }
+
+    private Value readString() throws RepositoryException {
+        if (currentTokenType != VALUE) {
+            throw getSyntaxError("string value");
+        }
+        Value value = currentValue;
+        read();
+        return value;
+    }
+
+    private void addExpected(String token) {
+        if (expected != null) {
+            expected.add(token);
+        }
+    }
+
+    private void initialize(String query) throws InvalidQueryException {
+        if (query == null) {
+            query = "";
+        }
+        statement = query;
+        int len = query.length() + 1;
+        char[] command = new char[len];
+        int[] types = new int[len];
+        len--;
+        query.getChars(0, len, command, 0);
+        command[len] = ' ';
+        int startLoop = 0;
+        for (int i = 0; i < len; i++) {
+            char c = command[i];
+            int type = 0;
+            switch (c) {
+            case '/':
+            case '-':
+            case '(':
+            case ')':
+            case '{':
+            case '}':
+            case '*':
+            case ',':
+            case ';':
+            case '+':
+            case '%':
+            case '?':
+            case '$':
+            case '[':
+            case ']':
+                type = CHAR_SPECIAL_1;
+                break;
+            case '!':
+            case '<':
+            case '>':
+            case '|':
+            case '=':
+            case ':':
+                type = CHAR_SPECIAL_2;
+                break;
+            case '.':
+                type = CHAR_DECIMAL;
+                break;
+            case '\'':
+                type = CHAR_STRING;
+                types[i] = CHAR_STRING;
+                startLoop = i;
+                while (command[++i] != '\'') {
+                    checkRunOver(i, len, startLoop);
+                }
+                break;
+            case '\"':
+                type = CHAR_QUOTED;
+                types[i] = CHAR_QUOTED;
+                startLoop = i;
+                while (command[++i] != '\"') {
+                    checkRunOver(i, len, startLoop);
+                }
+                break;
+            case '_':
+                type = CHAR_NAME;
+                break;
+            default:
+                if (c >= 'a' && c <= 'z') {
+                    type = CHAR_NAME;
+                } else if (c >= 'A' && c <= 'Z') {
+                    type = CHAR_NAME;
+                } else if (c >= '0' && c <= '9') {
+                    type = CHAR_VALUE;
+                } else {
+                    if (Character.isJavaIdentifierPart(c)) {
+                        type = CHAR_NAME;
+                    }
+                }
+            }
+            types[i] = (byte) type;
+        }
+        statementChars = command;
+        types[len] = CHAR_END;
+        characterTypes = types;
+        parseIndex = 0;
+    }
+
+    private void checkRunOver(int i, int len, int startLoop) throws InvalidQueryException {
+        if (i >= len) {
+            parseIndex = startLoop;
+            throw getSyntaxError();
+        }
+    }
+
+    private void read() throws RepositoryException {
+        currentTokenQuoted = false;
+        if (expected != null) {
+            expected.clear();
+        }
+        int[] types = characterTypes;
+        int i = parseIndex;
+        int type = types[i];
+        while (type == 0) {
+            type = types[++i];
+        }
+        int start = i;
+        char[] chars = statementChars;
+        char c = chars[i++];
+        currentToken = "";
+        switch (type) {
+        case CHAR_NAME:
+            while (true) {
+                type = types[i];
+                if (type != CHAR_NAME && type != CHAR_VALUE) {
+                    c = chars[i];
+                    break;
+                }
+                i++;
+            }
+            currentToken = statement.substring(start, i);
+            if (currentToken.length() == 0) {
+                throw getSyntaxError();
+            }
+            currentTokenType = IDENTIFIER;
+            parseIndex = i;
+            return;
+        case CHAR_SPECIAL_2:
+            if (types[i] == CHAR_SPECIAL_2) {
+                i++;
+            }
+            // fall through
+        case CHAR_SPECIAL_1:
+            currentToken = statement.substring(start, i);
+            switch (c) {
+            case '$':
+                currentTokenType = PARAMETER;
+                break;
+            case '+':
+                currentTokenType = PLUS;
+                break;
+            case '-':
+                currentTokenType = MINUS;
+                break;
+            case '(':
+                currentTokenType = OPEN;
+                break;
+            case ')':
+                currentTokenType = CLOSE;
+                break;
+            default:
+                currentTokenType = KEYWORD;
+            }
+            parseIndex = i;
+            return;
+        case CHAR_VALUE:
+            long number = c - '0';
+            while (true) {
+                c = chars[i];
+                if (c < '0' || c > '9') {
+                    if (c == '.') {
+                        readDecimal(start, i);
+                        break;
+                    }
+                    if (c == 'E' || c == 'e') {
+                        readDecimal(start, i);
+                        break;
+                    }
+                    checkLiterals(false);
+                    currentValue = valueFactory.createValue(number);
+                    currentTokenType = VALUE;
+                    currentToken = "0";
+                    parseIndex = i;
+                    break;
+                }
+                number = number * 10 + (c - '0');
+                if (number > Integer.MAX_VALUE) {
+                    readDecimal(start, i);
+                    break;
+                }
+                i++;
+            }
+            return;
+        case CHAR_DECIMAL:
+            if (types[i] != CHAR_VALUE) {
+                currentTokenType = KEYWORD;
+                currentToken = ".";
+                parseIndex = i;
+                return;
+            }
+            readDecimal(i - 1, i);
+            return;
+        case CHAR_STRING:
+            readString(i, '\'');
+            return;
+        case CHAR_QUOTED:
+            readString(i, '\"');
+            return;
+        case CHAR_END:
+            currentToken = "";
+            currentTokenType = END;
+            parseIndex = i;
+            return;
+        default:
+            throw getSyntaxError();
+        }
+    }
+
+    private void readString(int i, char end) throws RepositoryException {
+        char[] chars = statementChars;
+        String result = null;
+        while (true) {
+            for (int begin = i;; i++) {
+                if (chars[i] == end) {
+                    if (result == null) {
+                        result = statement.substring(begin, i);
+                    } else {
+                        result += statement.substring(begin - 1, i);
+                    }
+                    break;
+                }
+            }
+            if (chars[++i] != end) {
+                break;
+            }
+            i++;
+        }
+        currentToken = "'";
+        checkLiterals(false);
+        currentValue = valueFactory.createValue(result);
+        parseIndex = i;
+        currentTokenType = VALUE;
+    }
+
+    private void checkLiterals(boolean text) throws InvalidQueryException {
+        if (text && !allowTextLiterals || (!text && !allowNumberLiterals)) {
+            throw getSyntaxError("bind variable (literals of this type not allowed)");
+        }
+    }
+
+    private void readDecimal(int start, int i) throws RepositoryException {
+        char[] chars = statementChars;
+        int[] types = characterTypes;
+        while (true) {
+            int t = types[i];
+            if (t != CHAR_DECIMAL && t != CHAR_VALUE) {
+                break;
+            }
+            i++;
+        }
+        if (chars[i] == 'E' || chars[i] == 'e') {
+            i++;
+            if (chars[i] == '+' || chars[i] == '-') {
+                i++;
+            }
+            if (types[i] != CHAR_VALUE) {
+                throw getSyntaxError();
+            }
+            while (types[++i] == CHAR_VALUE) {
+                // go until the first non-number
+            }
+        }
+        parseIndex = i;
+        String sub = statement.substring(start, i);
+        BigDecimal bd;
+        try {
+            bd = new BigDecimal(sub);
+        } catch (NumberFormatException e) {
+            throw new InvalidQueryException("Data conversion error converting " + sub + " to BigDecimal: " + e);
+        }
+        checkLiterals(false);
+
+        currentValue = valueFactory.createValue(bd);
+        currentTokenType = VALUE;
+    }
+
+    private InvalidQueryException getSyntaxError() {
+        if (expected == null || expected.size() == 0) {
+            return getSyntaxError(null);
+        } else {
+            StringBuilder buff = new StringBuilder();
+            for (String exp : expected) {
+                if (buff.length() > 0) {
+                    buff.append(", ");
+                }
+                buff.append(exp);
+            }
+            return getSyntaxError(buff.toString());
+        }
+    }
+
+    private InvalidQueryException getSyntaxError(String expected) {
+        int index = Math.min(parseIndex, statement.length() - 1);
+        String query = statement.substring(0, index) + "(*)" + statement.substring(index).trim();
+        if (expected != null) {
+            query += "; expected: " + expected;
+        }
+        return new InvalidQueryException("Query:\n" + query);
+    }
+
+    /**
+     * Represents a column or a wildcard in a SQL expression.
+     * This class is temporarily used during parsing.
+     */
+    private static class ColumnOrWildcard {
+        private String selectorName;
+        private String propertyName;
+        private String columnName;
+    }
+
+    /**
+     * Get the selector name if only one selector exists in the query.
+     * If more than one selector exists, an exception is thrown.
+     *
+     * @return the selector name
+     */
+    private String getOnlySelectorName() throws RepositoryException {
+        if (selectors.size() > 1) {
+            throw getSyntaxError("Need to specify the selector name because the query contains more than one selector.");
+        }
+        return selectors.get(0).getSelectorName();
+    }
+
+}

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/QueryImpl.java?rev=932958&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/QueryImpl.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/QueryImpl.java Sun Apr 11 17:51:52 2010
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+package org.apache.jackrabbit.j3.query;
+
+import javax.jcr.ItemExistsException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.Value;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryResult;
+import javax.jcr.query.qom.QueryObjectModel;
+import javax.jcr.version.VersionException;
+import org.apache.jackrabbit.j3.util.Log;
+import org.apache.jackrabbit.j3.util.LogObject;
+
+/**
+ * The implementation of the corresponding JCR interface.
+ */
+public class QueryImpl implements Query, LogObject {
+
+    private final QueryObjectModel qom;
+    private final Log log;
+
+    public QueryImpl(QueryObjectModel qom, Log log) {
+        this.qom = qom;
+        this.log = log;
+    }
+
+    public void bindValue(String varName, Value value) throws IllegalArgumentException, RepositoryException {
+        log.code(this, "bindValue", varName, value);
+        qom.bindValue(varName, value);
+    }
+
+    public QueryResult execute() throws InvalidQueryException, RepositoryException {
+        log.code(this, "execute");
+        return qom.execute();
+    }
+
+    public String[] getBindVariableNames() throws RepositoryException {
+        log.code(this, "getBindVariableNames");
+        return qom.getBindVariableNames();
+    }
+
+    public String getLanguage() {
+        log.code(this, "getLanguage");
+        return qom.getLanguage();
+    }
+
+    public String getStatement() {
+        log.code(this, "getStatement");
+        return qom.getStatement();
+    }
+
+    public String getStoredQueryPath() throws ItemNotFoundException, RepositoryException {
+        log.code(this, "getStoredQueryPath");
+        return qom.getStoredQueryPath();
+    }
+
+    public void setLimit(long limit) {
+        log.code(this, "setLimit", limit);
+        qom.setLimit(limit);
+    }
+
+    public void setOffset(long offset) {
+        log.code(this, "setOffset", offset);
+        qom.setOffset(offset);
+    }
+
+    public Node storeAsNode(String absPath) throws ItemExistsException, PathNotFoundException, VersionException,
+            ConstraintViolationException, LockException, UnsupportedRepositoryOperationException, RepositoryException {
+        log.code(this, "storeAsNode", absPath);
+        return qom.storeAsNode(absPath);
+    }
+
+}

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/QueryManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/QueryManagerImpl.java?rev=932958&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/QueryManagerImpl.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/QueryManagerImpl.java Sun Apr 11 17:51:52 2010
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+package org.apache.jackrabbit.j3.query;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+import javax.jcr.query.qom.QueryObjectModel;
+import org.apache.jackrabbit.j3.ValueFactoryImpl;
+import org.apache.jackrabbit.j3.query.qom.QueryObjectModelFactoryImpl;
+import org.apache.jackrabbit.j3.util.Log;
+import org.apache.jackrabbit.j3.util.LogObject;
+
+/**
+ * The implementation of the corresponding JCR interface.
+ */
+public class QueryManagerImpl implements QueryManager, LogObject {
+
+    private final QueryObjectModelFactoryImpl qomFactory;
+    private final ParserSQL2 parserSQL2;
+    private final Log log;
+
+    @SuppressWarnings("deprecation")
+    private static final String[] SUPPOERTED_QUERY_LANGUAGES = {
+        Query.JCR_JQOM,
+        Query.JCR_SQL2,
+        Query.SQL,
+        Query.XPATH
+    };
+
+    public QueryManagerImpl(QueryObjectModelFactoryImpl qomFactory, ValueFactoryImpl valueFactory, Log log) {
+        this.qomFactory = qomFactory;
+        this.log = log;
+        parserSQL2 = new ParserSQL2(qomFactory, valueFactory);
+    }
+
+    public Query createQuery(String statement, String language) throws InvalidQueryException, RepositoryException {
+        log.code(this, "createQuery", statement, language);
+        if (Query.JCR_SQL2.equals(language)) {
+            QueryObjectModel qom = parserSQL2.createQueryObjectModel(statement);
+            return new QueryImpl(qom, log);
+        }
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public QueryObjectModelFactoryImpl getQOMFactory() {
+        log.codeAssign(qomFactory, this, "getQOMFactory");
+        return qomFactory;
+    }
+
+    public Query getQuery(Node node) throws InvalidQueryException, RepositoryException {
+        log.code(this, "getQuery");
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String[] getSupportedQueryLanguages() throws RepositoryException {
+        log.code(this, "getSupportedQueryLanguages");
+        // TODO the list is mutable
+        return SUPPOERTED_QUERY_LANGUAGES;
+    }
+
+}

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/QueryResultImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/QueryResultImpl.java?rev=932958&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/QueryResultImpl.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/QueryResultImpl.java Sun Apr 11 17:51:52 2010
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+package org.apache.jackrabbit.j3.query;
+
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.query.QueryResult;
+import javax.jcr.query.RowIterator;
+import org.apache.jackrabbit.j3.util.Log;
+import org.apache.jackrabbit.j3.util.LogObject;
+
+/**
+ * The implementation of the corresponding JCR interface.
+ */
+public class QueryResultImpl implements QueryResult, LogObject {
+
+    private final Log log;
+
+    QueryResultImpl(Log log) {
+        this.log = log;
+    }
+
+    public String[] getColumnNames() throws RepositoryException {
+        log.code(this, "getColumnNames");
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public NodeIterator getNodes() throws RepositoryException {
+        log.code(this, "getNodes");
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public RowIterator getRows() throws RepositoryException {
+        log.code(this, "getRows");
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String[] getSelectorNames() throws RepositoryException {
+        log.code(this, "getSelectorNames");
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/RowImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/RowImpl.java?rev=932958&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/RowImpl.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/RowImpl.java Sun Apr 11 17:51:52 2010
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+package org.apache.jackrabbit.j3.query;
+
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.query.Row;
+import org.apache.jackrabbit.j3.util.Log;
+import org.apache.jackrabbit.j3.util.LogObject;
+
+/**
+ * The implementation of the corresponding JCR interface.
+ */
+public class RowImpl implements Row, LogObject {
+
+    private final Log log;
+
+    RowImpl(Log log) {
+        this.log = log;
+    }
+
+    public Node getNode() throws RepositoryException {
+        log.code(this, "getNode");
+        // TODO
+        return null;
+    }
+
+    public Node getNode(String selectorName) throws RepositoryException {
+        log.code(this, "getNode", selectorName);
+        // TODO
+        return null;
+    }
+
+    public String getPath() throws RepositoryException {
+        log.code(this, "getPath");
+        // TODO
+        return null;
+    }
+
+    public String getPath(String selectorName) throws RepositoryException {
+        log.code(this, "getPath", selectorName);
+        // TODO
+        return null;
+    }
+
+    public double getScore() throws RepositoryException {
+        log.code(this, "getScore");
+        // TODO
+        return 0;
+    }
+
+    public double getScore(String selectorName) throws RepositoryException {
+        log.code(this, "getScore", selectorName);
+        // TODO
+        return 0;
+    }
+
+    public Value getValue(String columnName) throws ItemNotFoundException, RepositoryException {
+        log.code(this, "getValue", columnName);
+        // TODO
+        return null;
+    }
+
+    public Value[] getValues() throws RepositoryException {
+        log.code(this, "getValues");
+        // TODO
+        return null;
+    }
+
+}

Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/RowIteratorImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/RowIteratorImpl.java?rev=932958&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/RowIteratorImpl.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/query/RowIteratorImpl.java Sun Apr 11 17:51:52 2010
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+package org.apache.jackrabbit.j3.query;
+
+import java.util.Collection;
+import javax.jcr.query.Row;
+import javax.jcr.query.RowIterator;
+import org.apache.jackrabbit.j3.RangeIteratorImpl;
+import org.apache.jackrabbit.j3.util.Log;
+
+/**
+ * The implementation of the corresponding JCR interface.
+ */
+public class RowIteratorImpl extends RangeIteratorImpl<Row> implements RowIterator {
+
+    protected RowIteratorImpl(Collection<Row> coll, long size, Log log) {
+        super(coll.iterator(), size, log);
+    }
+
+    public Row nextRow() {
+        log.code(this, "nextRow");
+        return goNext();
+    }
+
+}