jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ju...@apache.org
Subject svn commit: r1040084 [1/2] - in /jackrabbit/branches/2.2: ./ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/p...
Date Mon, 29 Nov 2010 12:24:49 GMT
Author: jukka
Date: Mon Nov 29 12:24:48 2010
New Revision: 1040084

URL: http://svn.apache.org/viewvc?rev=1040084&view=rev
Log:
2.2: Merged revisions from trunk.

Removed:
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryObjectModelImpl.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/TrackingInputStream.java
Modified:
    jackrabbit/branches/2.2/   (props changed)
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleReader.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ExecutableQuery.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryHandler.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryFactory.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/JoinMerger.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/OperandEvaluator.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/QueryEngine.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/SameNodeJoinMerger.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ValueComparator.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
    jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCAManagedConnection.java
    jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCAManagedConnectionFactory.java
    jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCARepositoryHandle.java
    jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/webdav/QueryUtil.java
    jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/Base64.java
    jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/Base64Test.java
    jackrabbit/branches/2.2/jackrabbit-jcr-servlet/   (props changed)
    jackrabbit/branches/2.2/jackrabbit-webapp/src/main/webapp/search.jsp
    jackrabbit/branches/2.2/test/compatibility/create11/   (props changed)
    jackrabbit/branches/2.2/test/compatibility/create12/   (props changed)
    jackrabbit/branches/2.2/test/compatibility/create13/   (props changed)
    jackrabbit/branches/2.2/test/compatibility/create14/   (props changed)
    jackrabbit/branches/2.2/test/compatibility/create15/   (props changed)
    jackrabbit/branches/2.2/test/compatibility/create16/   (props changed)
    jackrabbit/branches/2.2/test/compatibility/create20/   (props changed)
    jackrabbit/branches/2.2/test/compatibility/create21/   (props changed)
    jackrabbit/branches/2.2/test/performance/parent/pom.xml

Propchange: jackrabbit/branches/2.2/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 29 12:24:48 2010
@@ -2,3 +2,4 @@
 /jackrabbit/sandbox/JCR-1456:774917-886178
 /jackrabbit/sandbox/JCR-2170:812417-816332
 /jackrabbit/sandbox/tripod-JCR-2209:795441-795863
+/jackrabbit/trunk:1038201,1038203,1038205,1038657,1039064,1039347,1039408,1039422-1039423,1039888,1039946,1040033

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java Mon Nov 29 12:24:48 2010
@@ -16,11 +16,11 @@
  */
 package org.apache.jackrabbit.core.data.db;
 
+import org.apache.commons.io.input.CountingInputStream;
 import org.apache.jackrabbit.core.data.DataIdentifier;
 import org.apache.jackrabbit.core.data.DataRecord;
 import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.data.DataStoreException;
-import org.apache.jackrabbit.core.util.TrackingInputStream;
 import org.apache.jackrabbit.core.util.db.CheckSchemaOperation;
 import org.apache.jackrabbit.core.util.db.ConnectionFactory;
 import org.apache.jackrabbit.core.util.db.ConnectionHelper;
@@ -343,7 +343,7 @@ public class DbDataStore implements Data
             temporaryInUse.add(tempId);
             MessageDigest digest = getDigest();
             DigestInputStream dIn = new DigestInputStream(stream, digest);
-            TrackingInputStream in = new TrackingInputStream(dIn);
+            CountingInputStream in = new CountingInputStream(dIn);
             StreamWrapper wrapper;
             if (STORE_SIZE_MINUS_ONE.equals(storeStream)) {
                 wrapper = new StreamWrapper(in, -1);
@@ -360,7 +360,7 @@ public class DbDataStore implements Data
             // UPDATE DATASTORE SET DATA=? WHERE ID=?
             conHelper.exec(updateDataSQL, new Object[]{wrapper, tempId});
             now = System.currentTimeMillis();
-            long length = in.getPosition();
+            long length = in.getByteCount();
             DataIdentifier identifier = new DataIdentifier(digest.digest());
             usesIdentifier(identifier);
             id = identifier.toString();

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java Mon Nov 29 12:24:48 2010
@@ -74,7 +74,7 @@ public class NodeTypeRegistry implements
             "org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd";
 
     private static final String CUSTOM_NODETYPES_RESOURCE_NAME =
-            "nodetypes/custom_nodetypes.xml";
+            "/nodetypes/custom_nodetypes.xml";
 
     /**
      * resource holding custom node type definitions which are represented as

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java Mon Nov 29 12:24:48 2010
@@ -30,7 +30,6 @@ import org.apache.jackrabbit.core.persis
 import org.apache.jackrabbit.core.persistence.util.FileSystemBLOBStore;
 import org.apache.jackrabbit.core.persistence.util.NodePropBundle;
 import org.apache.jackrabbit.core.persistence.util.Serializer;
-import org.apache.jackrabbit.core.util.TrackingInputStream;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.id.PropertyId;
 import org.apache.jackrabbit.core.state.ItemStateException;
@@ -239,10 +238,7 @@ public class BundleFsPersistenceManager 
             }
             InputStream in = itemFs.getInputStream(path);
             try {
-                TrackingInputStream cin = new TrackingInputStream(in);
-                NodePropBundle bundle = binding.readBundle(cin, id);
-                bundle.setSize(cin.getPosition());
-                return bundle;
+                return binding.readBundle(in, id);
             } finally {
                 IOUtils.closeQuietly(in);
             }

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java Mon Nov 29 12:24:48 2010
@@ -25,8 +25,8 @@ import java.io.InputStream;
 import java.sql.Blob;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Types;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 
@@ -41,11 +41,11 @@ import org.apache.jackrabbit.core.id.Nod
 import org.apache.jackrabbit.core.id.PropertyId;
 import org.apache.jackrabbit.core.persistence.PMContext;
 import org.apache.jackrabbit.core.persistence.bundle.AbstractBundlePersistenceManager;
+import org.apache.jackrabbit.core.persistence.util.BLOBStore;
 import org.apache.jackrabbit.core.persistence.util.BundleBinding;
 import org.apache.jackrabbit.core.persistence.util.ErrorHandling;
-import org.apache.jackrabbit.core.persistence.util.NodePropBundle;
-import org.apache.jackrabbit.core.persistence.util.BLOBStore;
 import org.apache.jackrabbit.core.persistence.util.FileSystemBLOBStore;
+import org.apache.jackrabbit.core.persistence.util.NodePropBundle;
 import org.apache.jackrabbit.core.persistence.util.Serializer;
 import org.apache.jackrabbit.core.state.ChangeLog;
 import org.apache.jackrabbit.core.state.ItemStateException;
@@ -796,27 +796,20 @@ public class BundleDbPersistenceManager
 
                     // issuing 2nd statement to circumvent issue JCR-1474
                     ResultSet bRs = null;
-                    byte[] data = null;
                     try {
                         bRs = conHelper.exec(bundleSelectSQL, getKey(id), false, 0);
                         if (!bRs.next()) {
                             throw new SQLException("bundle cannot be retrieved?");
                         }
-                        Blob blob = bRs.getBlob(1);
-                        data = getBytes(blob);
+                        // parse and check bundle
+                        NodePropBundle bundle = readBundle(id, bRs, 1);
+                        checkBundleConsistency(id, bundle, fix, modifications);
+                    } catch (SQLException e) {
+                        log.error("Unable to parse bundle " + id, e);
                     } finally {
                         DbUtility.close(bRs);
                     }
 
-                    try {
-                        // parse and check bundle
-                        NodePropBundle bundle = binding.readBundle(
-                                new ByteArrayInputStream(data), id);
-                        checkBundleConsistency(id, bundle, fix, modifications);
-                    } catch (IOException e) {
-                        log.error("Unable to parse bundle " + id
-                                + ": " + Arrays.toString(data), e);
-                    }
                     count++;
                     if (count % 1000 == 0) {
                         log.info(name + ": checked " + count + "/" + total + " bundles...");
@@ -1021,55 +1014,57 @@ public class BundleDbPersistenceManager
     /**
      * {@inheritDoc}
      */
+    @Override
     protected NodePropBundle loadBundle(NodeId id) throws ItemStateException {
-        ResultSet rs = null;
         try {
-            rs = conHelper.exec(bundleSelectSQL, getKey(id), false, 0);
-            if (!rs.next()) {
-                return null;
-            }
-            byte[] bytes = getBytes(rs.getBlob(1));
-
+            ResultSet rs =
+                conHelper.exec(bundleSelectSQL, getKey(id), false, 0);
             try {
-                NodePropBundle bundle =
-                    binding.readBundle(new ByteArrayInputStream(bytes), id);
-                bundle.setSize(bytes.length);
-                return bundle;
-            } catch (IOException e) {
-                log.error("Unable to parse serialization of bundle " + id
-                        + ": " + Arrays.toString(bytes), e);
-                throw e;
+                if (rs.next()) {
+                    return readBundle(id, rs, 1);
+                } else {
+                    return null;
+                }
+            } finally {
+                rs.close();
             }
-        } catch (Exception e) {
+        } catch (SQLException e) {
             String msg = "failed to read bundle: " + id + ": " + e;
             log.error(msg);
             throw new ItemStateException(msg, e);
-        } finally {
-            DbUtility.close(rs);
         }
     }
 
     /**
-     * Reads the blob's bytes and returns it. this is a helper method to
-     * circumvent issue JCR-1039 and JCR-1474
-     * @param blob blob to read
-     * @return bytes of the blob
-     * @throws SQLException if an SQL error occurs
-     * @throws IOException if an I/O error occurs
+     * Reads and parses a bundle from the BLOB in the given column of the
+     * current row of the given result set. This is a helper method to
+     * circumvent issues JCR-1039 and JCR-1474.
+     *
+     * @param id bundle identifier
+     * @param rs result set
+     * @param column BLOB column
+     * @return parsed bundle
+     * @throws SQLException if the bundle can not be read or parsed
      */
-    private byte[] getBytes(Blob blob) throws SQLException, IOException {
-        InputStream in = null;
+    private NodePropBundle readBundle(NodeId id, ResultSet rs, int column)
+            throws SQLException {
         try {
-            long length = blob.length();
-            byte[] bytes = new byte[(int) length];
-            in = blob.getBinaryStream();
-            int read, pos = 0;
-            while ((read = in.read(bytes, pos, bytes.length - pos)) > 0) {
-                pos += read;
+            InputStream in;
+            if (rs.getMetaData().getColumnType(column) == Types.BLOB) {
+                in = rs.getBlob(column).getBinaryStream();
+            } else {
+                in = rs.getBinaryStream(column);
             }
-            return bytes;
-        } finally {
-            IOUtils.closeQuietly(in);
+            try {
+                return binding.readBundle(in, id);
+            } finally {
+                in.close();
+            }
+        } catch (IOException e) {
+            SQLException exception =
+                new SQLException("Failed to parse bundle " + id);
+            exception.initCause(e);
+            throw exception;
         }
     }
 

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java Mon Nov 29 12:24:48 2010
@@ -16,18 +16,9 @@
  */
 package org.apache.jackrabbit.core.persistence.pool;
 
-import java.io.InputStream;
-import java.sql.ResultSet;
 import java.sql.SQLException;
 
-import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.persistence.PMContext;
-import org.apache.jackrabbit.core.persistence.util.NodePropBundle;
-import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.util.TrackingInputStream;
-import org.apache.jackrabbit.core.util.db.DbUtility;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Extends the {@link BundleDbPersistenceManager} by PostgreSQL specific code.
@@ -49,12 +40,6 @@ import org.slf4j.LoggerFactory;
 public class PostgreSQLPersistenceManager extends BundleDbPersistenceManager {
 
     /**
-     * Logger instance.
-     */
-    private static Logger log =
-        LoggerFactory.getLogger(PostgreSQLPersistenceManager.class);
-
-    /**
      * {@inheritDoc}
      */
     public void init(PMContext context) throws Exception {
@@ -85,36 +70,4 @@ public class PostgreSQLPersistenceManage
         return SM_LONGLONG_KEYS;
     }
 
-    /**
-     * PostgreSQL needs slightly different handling of the binary value that is received:
-     * rs.getBinaryStream vs rs.getBlob in the super class.
-     * 
-     * {@inheritDoc}
-     */
-    @Override
-    protected NodePropBundle loadBundle(NodeId id) throws ItemStateException {
-        ResultSet rs = null;
-        try {
-            rs = conHelper.exec(bundleSelectSQL, getKey(id), false, 0);
-            if (rs.next()) {
-                InputStream input = rs.getBinaryStream(1);
-                try {
-                    TrackingInputStream cin = new TrackingInputStream(input);
-                    NodePropBundle bundle = binding.readBundle(cin, id);
-                    bundle.setSize(cin.getPosition());
-                    return bundle;
-                } finally {
-                    input.close();
-                }
-            } else {
-                return null;
-            }
-        } catch (Exception e) {
-            String msg = "failed to read bundle: " + id + ": " + e;
-            log.error(msg);
-            throw new ItemStateException(msg, e);
-        } finally {
-           DbUtility.close(rs);
-        }
-    }
 }

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleReader.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleReader.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleReader.java Mon Nov 29 12:24:48 2010
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.core.persi
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.apache.commons.io.input.CountingInputStream;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.id.PropertyId;
 import org.apache.jackrabbit.core.value.InternalValue;
@@ -89,6 +90,14 @@ class BundleReader {
 
     private final BundleBinding binding;
 
+    /**
+     * Counter for the number of bytes read from the input stream.
+     */
+    private final CountingInputStream cin;
+
+    /**
+     * Wrapper for reading structured data from the input stream.
+     */
     private final DataInputStream in;
 
     private final int version;
@@ -112,7 +121,8 @@ class BundleReader {
     public BundleReader(BundleBinding binding, InputStream stream)
             throws IOException {
         this.binding = binding;
-        this.in = new DataInputStream(stream);
+        this.cin = new CountingInputStream(stream);
+        this.in = new DataInputStream(cin);
         this.version = in.readUnsignedByte();
     }
 
@@ -124,12 +134,14 @@ class BundleReader {
      * @throws IOException if an I/O error occurs.
      */
     public NodePropBundle readBundle(NodeId id) throws IOException {
+        long start = cin.getByteCount();
         NodePropBundle bundle = new NodePropBundle(id);
         if (version >= BundleBinding.VERSION_3) {
             readBundleNew(bundle);
         } else {
             readBundleOld(bundle);
         }
+        bundle.setSize(cin.getByteCount() - start);
         return bundle;
     }
 

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ExecutableQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ExecutableQuery.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ExecutableQuery.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ExecutableQuery.java Mon Nov 29 12:24:48 2010
@@ -16,10 +16,7 @@
  */
 package org.apache.jackrabbit.core.query;
 
-import java.util.Map;
-
 import javax.jcr.RepositoryException;
-import javax.jcr.Value;
 import javax.jcr.query.QueryResult;
 
 /**
@@ -39,22 +36,4 @@ public interface ExecutableQuery {
      */
     QueryResult execute(long offset, long limit) throws RepositoryException;
 
-    /**
-     * Binds the given <code>value</code> to the variable named
-     * <code>varName</code>.
-     *
-     * @param varName name of variable in query
-     * @param value   value to bind
-     * @throws RepositoryException if <code>varName</code> is not a
-     *                             valid variable in this query.
-     */
-    void bindValue(String varName, Value value) throws RepositoryException;
-
-    /**
-     * Returns the bind variables of this query.
-     *
-     * @return bind variables
-     */
-    Map<String, Value> getBindVariables();
-
 }

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryHandler.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryHandler.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryHandler.java Mon Nov 29 12:24:48 2010
@@ -26,7 +26,6 @@ import org.apache.jackrabbit.core.fs.Fil
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.session.SessionContext;
 import org.apache.jackrabbit.core.state.NodeState;
-import org.apache.jackrabbit.spi.commons.query.qom.QueryObjectModelTree;
 
 /**
  * Defines an interface for the actual node indexing and query execution.
@@ -112,20 +111,6 @@ public interface QueryHandler {
             throws InvalidQueryException;
 
     /**
-     * Creates a new query by specifying the query object model. If the query
-     * object model is considered invalid for the implementing class, an
-     * InvalidQueryException is thrown.
-     *
-     * @param sessionContext component context of the current session
-     * @param qomTree query query object model tree.
-     * @return A <code>Query</code> object.
-     * @throws InvalidQueryException if the query object model tree is invalid.
-     */
-    ExecutableQuery createExecutableQuery(
-            SessionContext sessionContext, QueryObjectModelTree qomTree)
-            throws InvalidQueryException;
-    
-    /**
      * @return the name of the query class to use.
      */
     String getQueryClass();

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java Mon Nov 29 12:24:48 2010
@@ -21,7 +21,6 @@ import static org.apache.jackrabbit.spi.
 import static org.apache.jackrabbit.spi.commons.name.NameConstants.NT_QUERY;
 
 import java.text.NumberFormat;
-import java.util.Set;
 
 import javax.jcr.ItemExistsException;
 import javax.jcr.ItemNotFoundException;
@@ -97,7 +96,7 @@ public class QueryImpl extends AbstractQ
     /**
      * The offset in the total result set
      */
-    protected long offset;
+    protected long offset = 0;
 
     /**
      * @inheritDoc
@@ -210,29 +209,19 @@ public class QueryImpl extends AbstractQ
     /**
      * {@inheritDoc}
      */
-    public String[] getBindVariableNames() throws RepositoryException {
-        Set<String> names = query.getBindVariables().keySet();
-        return names.toArray(new String[names.size()]);
+    public String[] getBindVariableNames() {
+        return new String[0];
     }
 
     /**
-     * Binds the given <code>value</code> to the variable named
-     * <code>varName</code>.
+     * Throws an {@link IllegalArgumentException} as XPath and SQL1 queries
+     * have no bind variables.
      *
-     * @param varName name of variable in query
-     * @param value   value to bind
-     * @throws IllegalArgumentException      if <code>varName</code> is not a
-     *                                       valid variable in this query.
-     * @throws javax.jcr.RepositoryException if an error occurs.
+     * @throws IllegalArgumentException always thrown
      */
     public void bindValue(String varName, Value value)
-            throws IllegalArgumentException, RepositoryException {
-        checkInitialized();
-        try {
-            query.bindValue(varName, value);
-        } catch (NameException e) {
-            throw new RepositoryException(e.getMessage());
-        }
+            throws IllegalArgumentException {
+        throw new IllegalArgumentException("No such bind variable: " + varName);
     }
 
     /**

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java Mon Nov 29 12:24:48 2010
@@ -16,8 +16,6 @@
  */
 package org.apache.jackrabbit.core.query;
 
-import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_JOIN_TYPE_INNER;
-
 import java.util.HashMap;
 import java.util.Map;
 
@@ -28,17 +26,17 @@ import javax.jcr.query.InvalidQueryExcep
 import javax.jcr.query.QueryResult;
 import javax.jcr.query.qom.Column;
 import javax.jcr.query.qom.Constraint;
-import javax.jcr.query.qom.EquiJoinCondition;
-import javax.jcr.query.qom.Join;
 import javax.jcr.query.qom.Ordering;
 import javax.jcr.query.qom.QueryObjectModel;
-import javax.jcr.query.qom.QueryObjectModelConstants;
 import javax.jcr.query.qom.Source;
 
 import org.apache.jackrabbit.commons.query.QueryObjectModelBuilderRegistry;
+import org.apache.jackrabbit.core.query.lucene.LuceneQueryFactory;
+import org.apache.jackrabbit.core.query.lucene.SearchIndex;
 import org.apache.jackrabbit.core.query.lucene.join.QueryEngine;
 import org.apache.jackrabbit.core.session.SessionContext;
-import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.query.qom.BindVariableValueImpl;
+import org.apache.jackrabbit.spi.commons.query.qom.DefaultTraversingQOMTreeVisitor;
 import org.apache.jackrabbit.spi.commons.query.qom.QueryObjectModelTree;
 
 /**
@@ -51,6 +49,11 @@ public class QueryObjectModelImpl extend
      */
     protected QueryObjectModelTree qomTree;
 
+    /** Bind variables */
+    private final Map<String, Value> variables = new HashMap<String, Value>();
+
+    private LuceneQueryFactory lqf;
+
     /**
      * {@inheritDoc}
      * @throws UnsupportedOperationException always.
@@ -88,24 +91,46 @@ public class QueryObjectModelImpl extend
         this.qomTree = qomTree;
         this.node = node;
         this.statement = QueryObjectModelBuilderRegistry.getQueryObjectModelBuilder(language).toString(this);
-        this.query = handler.createExecutableQuery(sessionContext, qomTree);
+
+        try {
+            qomTree.accept(new DefaultTraversingQOMTreeVisitor() {
+                @Override
+                public Object visit(BindVariableValueImpl node, Object data) {
+                    variables.put(node.getBindVariableName(), null);
+                    return data;
+                }
+            }, null);
+        } catch (Exception ignore) {
+        }
+        this.lqf = new LuceneQueryFactory(
+                sessionContext.getSessionImpl(), (SearchIndex) handler,
+                variables);
         setInitialized();
     }
 
     public QueryResult execute() throws RepositoryException {
-        Source source = getSource();
-        if (source instanceof Join) {
-            Join join = (Join) source;
-            if (JCR_JOIN_TYPE_INNER.equals(join.getJoinType())
-                    && join.getJoinCondition() instanceof EquiJoinCondition) {
-                QueryEngine engine =
-                    new QueryEngine(sessionContext.getSessionImpl(), query.getBindVariables());
-                return engine.execute(
-                        getColumns(), getSource(), getConstraint(),
-                        getOrderings(), offset, limit);
-            }
+        QueryEngine engine = new QueryEngine(
+                sessionContext.getSessionImpl(), lqf, variables);
+        return engine.execute(
+                getColumns(), getSource(), getConstraint(),
+                getOrderings(), offset, limit);
+    }
+
+
+    @Override
+    public String[] getBindVariableNames() {
+        return variables.keySet().toArray(new String[variables.size()]);
+    }
+
+    @Override
+    public void bindValue(String varName, Value value)
+            throws IllegalArgumentException {
+        if (variables.containsKey(varName)) {
+            variables.put(varName, value);
+        } else {
+            throw new IllegalArgumentException(
+                    "No such bind variable: " + varName);
         }
-        return super.execute();
     }
 
     //-------------------------< QueryObjectModel >-----------------------------

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java Mon Nov 29 12:24:48 2010
@@ -16,10 +16,7 @@
  */
 package org.apache.jackrabbit.core.query.lucene;
 
-import java.util.Map;
-
 import javax.jcr.RepositoryException;
-import javax.jcr.Value;
 import javax.jcr.Workspace;
 import javax.jcr.query.qom.QueryObjectModelFactory;
 
@@ -54,10 +51,6 @@ public abstract class AbstractQueryImpl 
      */
     private boolean documentOrder = true;
 
-    /** Bind variables of this query */
-    private final Map<String, Value> variables;
-
-
     /**
      * Creates a new query instance from a query string.
      *
@@ -67,11 +60,10 @@ public abstract class AbstractQueryImpl 
      */
     public AbstractQueryImpl(
             SessionContext sessionContext, SearchIndex index,
-            PropertyTypeRegistry propReg, Map<String, Value> variables) {
+            PropertyTypeRegistry propReg) {
         this.sessionContext = sessionContext;
         this.index = index;
         this.propReg = propReg;
-        this.variables = variables;
     }
 
     /**
@@ -102,33 +94,6 @@ public abstract class AbstractQueryImpl 
     }
 
     /**
-     * Binds the given <code>value</code> to the variable named
-     * <code>varName</code>.
-     *
-     * @param varName name of variable in query
-     * @param value   value to bind
-     * @throws IllegalArgumentException if <code>varName</code> is not a valid
-     *                                  variable in this query.
-     * @throws RepositoryException      if an error occurs.
-     */
-    public void bindValue(String varName, Value value)
-            throws IllegalArgumentException, RepositoryException {
-        if (variables.containsKey(varName)) {
-            variables.put(varName, value);
-        } else {
-            throw new IllegalArgumentException(
-                    varName + " is not a valid variable in this query");
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Map<String, Value> getBindVariables() {
-        return variables;
-    }
-
-    /**
      * @return the query object model factory.
      * @throws RepositoryException if an error occurs.
      */

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryFactory.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryFactory.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryFactory.java Mon Nov 29 12:24:48 2010
@@ -17,9 +17,11 @@
 package org.apache.jackrabbit.core.query.lucene;
 
 import static javax.jcr.PropertyType.DATE;
+import static javax.jcr.PropertyType.DECIMAL;
 import static javax.jcr.PropertyType.DOUBLE;
 import static javax.jcr.PropertyType.LONG;
 import static javax.jcr.PropertyType.NAME;
+import static javax.jcr.PropertyType.PATH;
 import static javax.jcr.PropertyType.STRING;
 import static javax.jcr.PropertyType.UNDEFINED;
 import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO;
@@ -29,24 +31,41 @@ import static javax.jcr.query.qom.QueryO
 import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO;
 import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_LIKE;
 import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_NOT_EQUAL_TO;
+import static org.apache.jackrabbit.core.query.lucene.FieldNames.LOCAL_NAME;
+import static org.apache.jackrabbit.core.query.lucene.FieldNames.MVP;
+import static org.apache.jackrabbit.core.query.lucene.FieldNames.NAMESPACE_URI;
+import static org.apache.jackrabbit.core.query.lucene.FieldNames.PARENT;
 import static org.apache.jackrabbit.core.query.lucene.FieldNames.PROPERTIES;
+import static org.apache.jackrabbit.core.query.lucene.FieldNames.UUID;
+import static org.apache.jackrabbit.core.query.lucene.TransformConstants.TRANSFORM_LOWER_CASE;
+import static org.apache.jackrabbit.core.query.lucene.TransformConstants.TRANSFORM_NONE;
+import static org.apache.jackrabbit.core.query.lucene.TransformConstants.TRANSFORM_UPPER_CASE;
 import static org.apache.jackrabbit.spi.commons.name.NameConstants.JCR_MIXINTYPES;
 import static org.apache.jackrabbit.spi.commons.name.NameConstants.JCR_PRIMARYTYPE;
 import static org.apache.lucene.search.BooleanClause.Occur.MUST;
+import static org.apache.lucene.search.BooleanClause.Occur.MUST_NOT;
 import static org.apache.lucene.search.BooleanClause.Occur.SHOULD;
 
+import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.PathNotFoundException;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.UnsupportedRepositoryOperationException;
 import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.nodetype.NodeTypeIterator;
 import javax.jcr.nodetype.NodeTypeManager;
 import javax.jcr.nodetype.PropertyDefinition;
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.query.Row;
 import javax.jcr.query.qom.And;
 import javax.jcr.query.qom.ChildNode;
 import javax.jcr.query.qom.Comparison;
@@ -54,26 +73,35 @@ import javax.jcr.query.qom.Constraint;
 import javax.jcr.query.qom.DescendantNode;
 import javax.jcr.query.qom.DynamicOperand;
 import javax.jcr.query.qom.FullTextSearch;
+import javax.jcr.query.qom.FullTextSearchScore;
+import javax.jcr.query.qom.Length;
+import javax.jcr.query.qom.LowerCase;
+import javax.jcr.query.qom.NodeLocalName;
+import javax.jcr.query.qom.NodeName;
 import javax.jcr.query.qom.Not;
 import javax.jcr.query.qom.Or;
 import javax.jcr.query.qom.PropertyExistence;
 import javax.jcr.query.qom.PropertyValue;
 import javax.jcr.query.qom.SameNode;
+import javax.jcr.query.qom.Selector;
 import javax.jcr.query.qom.StaticOperand;
+import javax.jcr.query.qom.UpperCase;
 
-import org.apache.jackrabbit.core.HierarchyManager;
+import org.apache.jackrabbit.commons.predicate.Predicate;
+import org.apache.jackrabbit.commons.predicate.Predicates;
+import org.apache.jackrabbit.commons.predicate.RowPredicate;
+import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.query.lucene.join.OperandEvaluator;
+import org.apache.jackrabbit.core.query.lucene.join.SelectorRow;
+import org.apache.jackrabbit.core.query.lucene.join.ValueComparator;
 import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.conversion.IllegalNameException;
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
-import org.apache.jackrabbit.spi.commons.query.qom.DefaultQOMTreeVisitor;
 import org.apache.jackrabbit.spi.commons.query.qom.FullTextSearchImpl;
-import org.apache.jackrabbit.spi.commons.query.qom.JoinConditionImpl;
-import org.apache.jackrabbit.spi.commons.query.qom.JoinImpl;
 import org.apache.jackrabbit.spi.commons.query.qom.PropertyExistenceImpl;
-import org.apache.jackrabbit.spi.commons.query.qom.SelectorImpl;
-import org.apache.jackrabbit.spi.commons.query.qom.SourceImpl;
-import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.queryParser.ParseException;
 import org.apache.lucene.queryParser.QueryParser;
@@ -96,10 +124,8 @@ public class LuceneQueryFactory {
      */
     private final NodeTypeManager ntManager;
 
-    /**
-     * The hierarchy manager.
-     */
-    private final HierarchyManager hmgr;
+    /** Lucene search index */
+    private final SearchIndex index;
 
     /**
      * Namespace mappings to internal prefixes
@@ -111,21 +137,6 @@ public class LuceneQueryFactory {
      */
     private final NamePathResolver npResolver;
 
-    /**
-     * The analyzer instance to use for contains function query parsing
-     */
-    private final Analyzer analyzer;
-
-    /**
-     * The synonym provider or <code>null</code> if none is configured.
-     */
-    private final SynonymProvider synonymProvider;
-
-    /**
-     * The index format version.
-     */
-    private final IndexFormatVersion version;
-
     /** Operand evaluator */
     private final OperandEvaluator evaluator;
 
@@ -137,26 +148,16 @@ public class LuceneQueryFactory {
      * Creates a new lucene query factory.
      *
      * @param session         the session that executes the query.
-     * @param scs             the sort comparator source of the index.
-     * @param hmgr            the hierarchy manager of the workspace.
-     * @param nsMappings      the index internal namespace mappings.
-     * @param analyzer        the analyzer of the index.
-     * @param synonymProvider the synonym provider of the index.
-     * @param version         the version of the index format.
+     * @param index           the search index
      * @param bindVariables   the bind variable values of the query
      */
     public LuceneQueryFactory(
-            SessionImpl session, HierarchyManager hmgr,
-            NamespaceMappings nsMappings, Analyzer analyzer,
-            SynonymProvider synonymProvider, IndexFormatVersion version,
+            SessionImpl session, SearchIndex index,
             Map<String, Value> bindVariables) throws RepositoryException {
         this.session = session;
         this.ntManager = session.getWorkspace().getNodeTypeManager();
-        this.hmgr = hmgr;
-        this.nsMappings = nsMappings;
-        this.analyzer = analyzer;
-        this.synonymProvider = synonymProvider;
-        this.version = version;
+        this.index = index;
+        this.nsMappings = index.getNamespaceMappings();
         this.npResolver = NamePathResolverImpl.create(nsMappings);
         this.evaluator =
             new OperandEvaluator(session.getValueFactory(), bindVariables);
@@ -164,6 +165,51 @@ public class LuceneQueryFactory {
         this.primaryTypeField = nsMappings.translateName(JCR_PRIMARYTYPE);
     }
 
+    public List<Row> execute(
+            Map<String, PropertyValue> columns, Selector selector,
+            Constraint constraint) throws RepositoryException, IOException {
+        final IndexReader reader = index.getIndexReader(true);
+        try {
+            JackrabbitIndexSearcher searcher = new JackrabbitIndexSearcher(
+                    session, reader, index.getContext().getItemStateManager());
+            searcher.setSimilarity(index.getSimilarity());
+
+            Predicate filter = Predicate.TRUE;
+            BooleanQuery query = new BooleanQuery();
+            query.add(create(selector), MUST);
+            if (constraint != null) {
+                String name = selector.getSelectorName();
+                NodeType type =
+                    ntManager.getNodeType(selector.getNodeTypeName());
+                filter = mapConstraintToQueryAndFilter(
+                        query, constraint, Collections.singletonMap(name, type),
+                        searcher, reader);
+            }
+
+            List<Row> rows = new ArrayList<Row>();
+            QueryHits hits = searcher.evaluate(query);
+            ScoreNode node = hits.nextScoreNode();
+            while (node != null) {
+                try {
+                    Row row = new SelectorRow(
+                            columns, evaluator, selector.getSelectorName(),
+                            session.getNodeById(node.getNodeId()),
+                            node.getScore());
+                    if (filter.evaluate(row)) {
+                        rows.add(row);
+                    }
+                } catch (ItemNotFoundException e) {
+                    // skip the node
+                }
+                node = hits.nextScoreNode();
+            }
+            return rows;
+        } finally {
+            PerQueryCache.getInstance().dispose();
+            Util.closeOrRelease(reader);
+        }
+    }
+
     /**
      * Creates a lucene query for the given QOM selector.
      *
@@ -171,7 +217,7 @@ public class LuceneQueryFactory {
      * @return a lucene query for the given selector.
      * @throws RepositoryException if an error occurs while creating the query.
      */
-    public Query create(SelectorImpl selector) throws RepositoryException {
+    public Query create(Selector selector) throws RepositoryException {
         List<Term> terms = new ArrayList<Term>();
 
         String name = selector.getNodeTypeName();
@@ -229,7 +275,7 @@ public class LuceneQueryFactory {
             fieldname = tmp.toString();
         }
         QueryParser parser = new JackrabbitQueryParser(
-                fieldname, analyzer, synonymProvider);
+                fieldname, index.getTextAnalyzer(), index.getSynonymProvider());
         try {
             StaticOperand expr = fts.getFullTextSearchExpression();
             return parser.parse(evaluator.getValue(expr).getString());
@@ -247,168 +293,377 @@ public class LuceneQueryFactory {
      */
     public Query create(PropertyExistenceImpl prop) throws RepositoryException {
         String propName = npResolver.getJCRName(prop.getPropertyQName());
-        return Util.createMatchAllQuery(propName, version);
+        return Util.createMatchAllQuery(propName, index.getIndexFormatVersion());
     }
 
-    /**
-     * Creates a multi column query for the given QOM source.
-     *
-     * @param source the QOM source.
-     * @return a multi column query for the given source.
-     * @throws RepositoryException if an error occurs while creating the query.
-     */
-    public MultiColumnQuery create(SourceImpl source) throws RepositoryException {
-        // source is either selector or join
-        try {
-            return (MultiColumnQuery) source.accept(new DefaultQOMTreeVisitor() {
-                public Object visit(JoinImpl node, Object data) throws Exception {
-                    return create(node);
-                }
-
-                public Object visit(SelectorImpl node, Object data) throws Exception {
-                    return MultiColumnQueryAdapter.adapt(
-                            create(node), node.getSelectorQName());
+    private Predicate mapConstraintToQueryAndFilter(
+            BooleanQuery query, Constraint constraint,
+            Map<String, NodeType> selectorMap,
+            JackrabbitIndexSearcher searcher, IndexReader reader)
+            throws RepositoryException, IOException {
+        Predicate filter = Predicate.TRUE;
+        if (constraint instanceof And) {
+            And and = (And) constraint;
+            filter = mapConstraintToQueryAndFilter(
+                    query, and.getConstraint1(), selectorMap, searcher, reader);
+            Predicate other = mapConstraintToQueryAndFilter(
+                    query, and.getConstraint2(), selectorMap, searcher, reader);
+            if (filter == Predicate.TRUE) {
+                filter = other;
+            } else if (other != Predicate.TRUE) {
+                filter = Predicates.and(filter, other);
+            }
+        } else if (constraint instanceof Comparison) {
+            Comparison c = (Comparison) constraint;
+            Transform transform = new Transform(c.getOperand1());
+            DynamicOperand left = transform.operand;
+            final String operator = c.getOperator();
+            StaticOperand right = c.getOperand2();
+            if (left instanceof Length
+                    || left instanceof FullTextSearchScore
+                    || ((!JCR_OPERATOR_EQUAL_TO.equals(operator)
+                            || transform.transform != TRANSFORM_NONE)
+                            && (left instanceof NodeName
+                                    || left instanceof NodeLocalName))) {
+                try {
+                    int type = PropertyType.UNDEFINED;
+                    if (left instanceof Length) {
+                        type = PropertyType.LONG;
+                    } else if (left instanceof FullTextSearchScore) {
+                        type = PropertyType.DOUBLE;
+                    }
+                    final DynamicOperand operand = c.getOperand1();
+                    final Value value = evaluator.getValue(right, type);
+                    filter = new RowPredicate() {
+                        @Override
+                        protected boolean evaluate(Row row)
+                                throws RepositoryException {
+                            return new ValueComparator().evaluate(
+                                    operator,
+                                    evaluator.getValue(operand, row), value);
+                        }
+                    };
+                } catch (ValueFormatException e) {
+                    throw new InvalidQueryException(e);
                 }
-            }, null);
-        } catch (RepositoryException e) {
-            throw e;
-        } catch (Exception e) {
-            throw new RepositoryException(e);
+            } else {
+                Query cq = getComparisonQuery(
+                        left, transform.transform, operator, right, selectorMap);
+                query.add(cq, MUST);
+            }
+        } else {
+            query.add(create(constraint, selectorMap, searcher), MUST);
         }
+        return filter;
     }
 
-    /**
-     * Creates a multi column query for the given QOM join.
-     *
-     * @param join the QOM join.
-     * @return the multi column query for the given join.
-     * @throws RepositoryException if an error occurs while creating the query.
-     */
-    public MultiColumnQuery create(JoinImpl join) throws RepositoryException {
-        MultiColumnQuery left = create((SourceImpl) join.getLeft());
-        MultiColumnQuery right = create((SourceImpl) join.getRight());
-        return new JoinQuery(left, right, join.getJoinTypeInstance(),
-                (JoinConditionImpl) join.getJoinCondition(), nsMappings, hmgr);
-    }
-
-    public Query create(
-            Constraint constraint, Map<String, NodeType> selectorMap)
-            throws RepositoryException {
+    private Query create(
+            Constraint constraint, Map<String, NodeType> selectorMap,
+            JackrabbitIndexSearcher searcher)
+            throws RepositoryException, IOException {
         if (constraint instanceof And) {
-            return getAndQuery((And) constraint, selectorMap);
+            return getAndQuery((And) constraint, selectorMap, searcher);
         } else if (constraint instanceof Or) {
-            return getOrQuery((Or) constraint, selectorMap);
+            return getOrQuery((Or) constraint, selectorMap, searcher);
         } else if (constraint instanceof Not) {
-            return getNotQuery((Not) constraint, selectorMap);
+            return getNotQuery((Not) constraint, selectorMap, searcher);
         } else if (constraint instanceof PropertyExistence) {
             return getPropertyExistenceQuery((PropertyExistence) constraint);
         } else if (constraint instanceof Comparison) {
-            return getComparisonQuery((Comparison) constraint, selectorMap);
+            Comparison c = (Comparison) constraint;
+            Transform left = new Transform(c.getOperand1());
+            return getComparisonQuery(
+                    left.operand, left.transform, c.getOperator(),
+                    c.getOperand2(), selectorMap);
         } else if (constraint instanceof FullTextSearch) {
-            return null; // FIXME
+            return getFullTextSearchQuery((FullTextSearch) constraint);
         } else if (constraint instanceof SameNode) {
-            return null; // FIXME
+            SameNode sn = (SameNode) constraint;
+            return getNodeIdQuery(UUID, sn.getPath());
         } else if (constraint instanceof ChildNode) {
-            return null; // FIXME
+            ChildNode cn = (ChildNode) constraint;
+            return getNodeIdQuery(PARENT, cn.getParentPath());
         } else if (constraint instanceof DescendantNode) {
-            return null; // FIXME
+            DescendantNode dn = (DescendantNode) constraint;
+            return getDescendantNodeQuery(dn, searcher);
         } else {
             throw new UnsupportedRepositoryOperationException(
                     "Unknown constraint type: " + constraint);
         }
     }
 
-    private BooleanQuery getAndQuery(
-            And and, Map<String, NodeType> selectorMap)
-            throws RepositoryException {
+    private Query getDescendantNodeQuery(
+            DescendantNode dn, JackrabbitIndexSearcher searcher)
+            throws RepositoryException, IOException {
         BooleanQuery query = new BooleanQuery();
-        addBooleanConstraint(query, and.getConstraint1(), MUST, selectorMap);
-        addBooleanConstraint(query, and.getConstraint2(), MUST, selectorMap);
+
+        try {
+            LinkedList<NodeId> ids = new LinkedList<NodeId>();
+            NodeImpl ancestor = (NodeImpl) session.getNode(dn.getAncestorPath());
+            ids.add(ancestor.getNodeId());
+            while (!ids.isEmpty()) {
+                String id = ids.removeFirst().toString();
+                Query q = new JackrabbitTermQuery(new Term(FieldNames.PARENT, id));
+                QueryHits hits = searcher.evaluate(q);
+                ScoreNode sn = hits.nextScoreNode();
+                if (sn != null) {
+                    query.add(q, SHOULD);
+                    do {
+                        ids.add(sn.getNodeId());
+                        sn = hits.nextScoreNode();
+                    } while (sn != null);
+                }
+            }
+        } catch (PathNotFoundException e) {
+            query.add(new JackrabbitTermQuery(new Term(
+                    FieldNames.UUID, "invalid-node-id")), // never matches
+                    SHOULD);
+        }
+
         return query;
     }
 
-    private BooleanQuery getOrQuery(Or or, Map<String, NodeType> selectorMap)
+    private Query getFullTextSearchQuery(FullTextSearch fts)
             throws RepositoryException {
+        String field = FieldNames.FULLTEXT;
+        String property = fts.getPropertyName();
+        if (property != null) {
+            Name name = session.getQName(property);
+            field = nsMappings.getPrefix(name.getNamespaceURI()) + ":"
+                + FieldNames.FULLTEXT_PREFIX + name.getLocalName();
+        }
+
+        StaticOperand expression = fts.getFullTextSearchExpression();
+        String query = evaluator.getValue(expression).getString();
+        try {
+            QueryParser parser = new JackrabbitQueryParser(
+                    field, index.getTextAnalyzer(), index.getSynonymProvider());
+            return parser.parse(query);
+        } catch (ParseException e) {
+            throw new RepositoryException(
+                    "Invalid full text search expression: " + query, e);
+        }
+    }
+
+    private BooleanQuery getAndQuery(
+            And and, Map<String, NodeType> selectorMap,
+            JackrabbitIndexSearcher searcher)
+            throws RepositoryException, IOException {
+        BooleanQuery query = new BooleanQuery();
+        addBooleanConstraint(
+                query, and.getConstraint1(), MUST, selectorMap, searcher);
+        addBooleanConstraint(
+                query, and.getConstraint2(), MUST, selectorMap, searcher);
+        return query;
+    }
+
+    private BooleanQuery getOrQuery(
+            Or or, Map<String, NodeType> selectorMap,
+            JackrabbitIndexSearcher searcher)
+            throws RepositoryException, IOException {
         BooleanQuery query = new BooleanQuery();
-        addBooleanConstraint(query, or.getConstraint1(), SHOULD, selectorMap);
-        addBooleanConstraint(query, or.getConstraint2(), SHOULD, selectorMap);
+        addBooleanConstraint(
+                query, or.getConstraint1(), SHOULD, selectorMap, searcher);
+        addBooleanConstraint(
+                query, or.getConstraint2(), SHOULD, selectorMap, searcher);
         return query;
     }
 
     private void addBooleanConstraint(
             BooleanQuery query, Constraint constraint, Occur occur,
-            Map<String, NodeType> selectorMap) throws RepositoryException {
+            Map<String, NodeType> selectorMap, JackrabbitIndexSearcher searcher)
+            throws RepositoryException, IOException {
         if (occur == MUST && constraint instanceof And) {
             And and = (And) constraint;
-            addBooleanConstraint(query, and.getConstraint1(), occur, selectorMap);
-            addBooleanConstraint(query, and.getConstraint2(), occur, selectorMap);
+            addBooleanConstraint(
+                    query, and.getConstraint1(), occur, selectorMap, searcher);
+            addBooleanConstraint(
+                    query, and.getConstraint2(), occur, selectorMap, searcher);
         } else if (occur == SHOULD && constraint instanceof Or) {
             Or or = (Or) constraint;
-            addBooleanConstraint(query, or.getConstraint1(), occur, selectorMap);
-            addBooleanConstraint(query, or.getConstraint2(), occur, selectorMap);
+            addBooleanConstraint(
+                    query, or.getConstraint1(), occur, selectorMap, searcher);
+            addBooleanConstraint(
+                    query, or.getConstraint2(), occur, selectorMap, searcher);
         } else {
-            query.add(create(constraint, selectorMap), occur);
+            query.add(create(constraint, selectorMap, searcher), occur);
         }
     }
 
-    private NotQuery getNotQuery(Not not, Map<String, NodeType> selectorMap)
-            throws RepositoryException {
-        return new NotQuery(create(not.getConstraint(), selectorMap));
+    private NotQuery getNotQuery(
+            Not not, Map<String, NodeType> selectorMap,
+            JackrabbitIndexSearcher searcher)
+            throws RepositoryException, IOException {
+        return new NotQuery(create(not.getConstraint(), selectorMap, searcher));
     }
 
     private Query getPropertyExistenceQuery(PropertyExistence property)
             throws RepositoryException {
         String name = npResolver.getJCRName(session.getQName(
                 property.getPropertyName()));
-        return Util.createMatchAllQuery(name, version);
+        return Util.createMatchAllQuery(name, index.getIndexFormatVersion());
+    }
+
+    private static class Transform {
+
+        private final DynamicOperand operand;
+
+        private final int transform;
+
+        public Transform(DynamicOperand operand) {
+            // Check the transformation type
+            if (operand instanceof UpperCase) {
+                this.transform = TRANSFORM_UPPER_CASE;
+            } else if (operand instanceof LowerCase) {
+                this.transform = TRANSFORM_LOWER_CASE;
+            } else {
+                this.transform = TRANSFORM_NONE;
+            }
+
+            // Unwrap any nested transformations
+            while (true) {
+                if (operand instanceof UpperCase) {
+                    operand = ((UpperCase) operand).getOperand();
+                } else if (operand instanceof LowerCase) {
+                    operand = ((LowerCase) operand).getOperand();
+                } else {
+                    break;
+                }
+            }
+            this.operand = operand;
+        }
     }
 
     private Query getComparisonQuery(
-            Comparison comparison, Map<String, NodeType> selectorMap)
+            DynamicOperand left, int transform, String operator,
+            StaticOperand rigth, Map<String, NodeType> selectorMap)
             throws RepositoryException {
-        DynamicOperand operand = comparison.getOperand1();
-        if (operand instanceof PropertyValue) {
-            PropertyValue property = (PropertyValue) operand;
+        if (left instanceof PropertyValue) {
+            PropertyValue pv = (PropertyValue) left;
             String field = npResolver.getJCRName(session.getQName(
-                    property.getPropertyName()));
+                    pv.getPropertyName()));
             int type = PropertyType.UNDEFINED;
-            NodeType nt = selectorMap.get(property.getSelectorName());
+            NodeType nt = selectorMap.get(pv.getSelectorName());
             if (nt != null) {
                 for (PropertyDefinition pd : nt.getPropertyDefinitions()) {
-                    if (pd.getName().equals(property.getPropertyName())) {
+                    if (pd.getName().equals(pv.getPropertyName())) {
                         type = pd.getRequiredType();
                     }
                 }
             }
             return getPropertyValueQuery(
-                    field, comparison.getOperator(),
-                    evaluator.getValue(comparison.getOperand2()), type);
+                    field, operator, evaluator.getValue(rigth), type, transform);
+        } else if (left instanceof NodeName) {
+            return getNodeNameQuery(transform, operator, rigth);
+        } else if (left instanceof NodeLocalName) {
+            return getNodeLocalNameQuery(transform, operator, rigth);
         } else {
-            throw new UnsupportedRepositoryOperationException(); // FIXME
+            throw new UnsupportedRepositoryOperationException(
+                    "Unknown operand type: " + left); // FIXME
         }
     }
 
-    private Query getPropertyValueQuery(
-            String field, String operator, Value value, int type)
+    private Query getNodeNameQuery(
+            int transform, String operator, StaticOperand right)
             throws RepositoryException {
-        Term term = getTerm(field, getValueString(value, type));
+        if (transform != TRANSFORM_NONE
+                || !JCR_OPERATOR_EQUAL_TO.equals(operator)) {
+            throw new UnsupportedRepositoryOperationException();
+        }
+
+        Value value = evaluator.getValue(right);
+        int type = value.getType();
+        String string = value.getString();
+        if (type == PropertyType.URI && string.startsWith("./")) {
+            string = string.substring("./".length());
+        } else if (type == PropertyType.DOUBLE
+                || type == PropertyType.DECIMAL
+                || type == PropertyType.LONG
+                || type == PropertyType.BOOLEAN
+                || type == PropertyType.REFERENCE
+                || type == PropertyType.WEAKREFERENCE) {
+            throw new InvalidQueryException("Invalid name value: " + string);
+        }
+
+        try {
+            Name name = session.getQName(string);
+            Term uri = new Term(NAMESPACE_URI, name.getNamespaceURI());
+            Term local = new Term(LOCAL_NAME, name.getLocalName());
+
+            BooleanQuery query = new BooleanQuery();
+            query.add(new JackrabbitTermQuery(uri), MUST);
+            query.add(new JackrabbitTermQuery(local), MUST);
+            return query;
+        } catch (IllegalNameException e) {
+            throw new InvalidQueryException("Illegal name: " + string, e);
+        }
+    }
+
+    private Query getNodeLocalNameQuery(
+            int transform, String operator, StaticOperand right)
+            throws RepositoryException {
+        if (transform != TRANSFORM_NONE
+                || !JCR_OPERATOR_EQUAL_TO.equals(operator)) {
+            throw new UnsupportedRepositoryOperationException();
+        }
+
+        String name = evaluator.getValue(right).getString();
+        return new JackrabbitTermQuery(new Term(LOCAL_NAME, name));
+    }
+
+    private Query getNodeIdQuery(String field, String path)
+            throws RepositoryException {
+        String value;
+        try {
+            NodeImpl node = (NodeImpl) session.getNode(path);
+            value = node.getNodeId().toString();
+        } catch (PathNotFoundException e) {
+            value = "invalid-node-id"; // can never match a node
+        }
+        return new JackrabbitTermQuery(new Term(field, value));
+    }
+
+    private Query getPropertyValueQuery(
+            String field, String operator, Value value,
+            int type, int transform) throws RepositoryException {
+        String string = getValueString(value, type);
+        if (JCR_OPERATOR_LIKE.equals(operator)) {
+            return new WildcardQuery(PROPERTIES, field, string, transform);
+        }
+
+        Term term = getTerm(field, string);
         if (JCR_OPERATOR_EQUAL_TO.equals(operator)) {
-            return new JackrabbitTermQuery(term);
+            switch (transform) {
+            case TRANSFORM_UPPER_CASE:
+                return new CaseTermQuery.Upper(term);
+            case TRANSFORM_LOWER_CASE:
+                return new CaseTermQuery.Lower(term);
+            default:
+                return new JackrabbitTermQuery(term);
+            }
         } else if (JCR_OPERATOR_GREATER_THAN.equals(operator)) {
-            return new RangeQuery(term, getTerm(field, "\uFFFF"), false);
+            return new RangeQuery(term, getTerm(field, "\uFFFF"), false, transform);
         } else if (JCR_OPERATOR_GREATER_THAN_OR_EQUAL_TO.equals(operator)) {
-            return new RangeQuery(term, getTerm(field, "\uFFFF"), true);
+            return new RangeQuery(term, getTerm(field, "\uFFFF"), true, transform);
         } else if (JCR_OPERATOR_LESS_THAN.equals(operator)) {
-            return new RangeQuery(getTerm(field, ""), term, false);
+            return new RangeQuery(getTerm(field, ""), term, false, transform);
         } else if (JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO.equals(operator)) {
-            return new RangeQuery(getTerm(field, ""), term, true);
+            return new RangeQuery(getTerm(field, ""), term, true, transform);
         } else if (JCR_OPERATOR_NOT_EQUAL_TO.equals(operator)) {
-            BooleanQuery or = new BooleanQuery();
-            or.add(new RangeQuery(getTerm(field, ""), term, false), SHOULD);
-            or.add(new RangeQuery(term, getTerm(field, "\uFFFF"), false), SHOULD);
-            return or;
-        } else if (JCR_OPERATOR_LIKE.equals(operator)) {
-            throw new UnsupportedRepositoryOperationException(); // FIXME
+            BooleanQuery query = new BooleanQuery();
+            query.add(Util.createMatchAllQuery(
+                    field, index.getIndexFormatVersion()), SHOULD);
+            switch (transform) {
+            case TRANSFORM_UPPER_CASE:
+                query.add(new CaseTermQuery.Upper(term), MUST_NOT);
+            case TRANSFORM_LOWER_CASE:
+                query.add(new CaseTermQuery.Lower(term), MUST_NOT);
+            default:
+                query.add(new JackrabbitTermQuery(term), MUST_NOT);
+            }
+            // and exclude all nodes where 'field' is multi valued
+            query.add(new JackrabbitTermQuery(new Term(MVP, field)), MUST_NOT);
+            return query;
         } else {
             throw new UnsupportedRepositoryOperationException(); // FIXME
         }
@@ -427,8 +682,12 @@ public class LuceneQueryFactory {
             return DoubleField.doubleToString(value.getDouble());
         case LONG:
             return LongField.longToString(value.getLong());
+        case DECIMAL:
+            return DecimalField.decimalToString(value.getDecimal());
         case NAME:
             return npResolver.getJCRName(session.getQName(value.getString()));
+        case PATH:
+            return npResolver.getJCRPath(session.getQPath(value.getString()));
         default:
             String string = value.getString();
             if (type != UNDEFINED && type != STRING) {

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java Mon Nov 29 12:24:48 2010
@@ -88,8 +88,7 @@ public class QueryImpl extends AbstractQ
             SessionContext sessionContext, SearchIndex index,
             PropertyTypeRegistry propReg, String statement, String language,
             QueryNodeFactory factory) throws InvalidQueryException {
-        super(sessionContext, index, propReg,
-                Collections.<String, Value>emptyMap());
+        super(sessionContext, index, propReg);
         // parse query according to language
         // build query tree using the passed factory
         this.root = QueryParser.parse(

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java Mon Nov 29 12:24:48 2010
@@ -16,10 +16,9 @@
  */
 package org.apache.jackrabbit.core.query.lucene;
 
-import java.io.InputStream;
-
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -39,7 +38,6 @@ import javax.xml.parsers.DocumentBuilder
 import javax.xml.parsers.ParserConfigurationException;
 
 import org.apache.jackrabbit.core.HierarchyManager;
-import org.apache.jackrabbit.core.ItemManager;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemException;
@@ -60,12 +58,10 @@ import org.apache.jackrabbit.core.state.
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.PathFactory;
-import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
 import org.apache.jackrabbit.spi.commons.query.DefaultQueryNodeFactory;
 import org.apache.jackrabbit.spi.commons.query.qom.OrderingImpl;
-import org.apache.jackrabbit.spi.commons.query.qom.QueryObjectModelTree;
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.Token;
 import org.apache.lucene.document.Document;
@@ -683,28 +679,6 @@ public class SearchIndex extends Abstrac
     }
 
     /**
-     * Creates a new query by specifying the query object model. If the query
-     * object model is considered invalid for the implementing class, an
-     * InvalidQueryException is thrown.
-     *
-     * @param sessionContext component context of the current session
-     * @param qomTree query query object model tree.
-     * @return A <code>Query</code> object.
-     * @throws javax.jcr.query.InvalidQueryException
-     *          if the query object model tree is invalid.
-     * @see QueryHandler#createExecutableQuery(SessionImpl, ItemManager, QueryObjectModelTree)
-     */
-    public ExecutableQuery createExecutableQuery(
-            SessionContext sessionContext, QueryObjectModelTree qomTree)
-            throws InvalidQueryException {
-        QueryObjectModelImpl query = new QueryObjectModelImpl(
-                sessionContext, this, getContext().getPropertyTypeRegistry(),
-                qomTree);
-        query.setRespectDocumentOrder(documentOrder);
-        return query;
-    }
-
-    /**
      * {@inheritDoc}
      */
     public Iterable<NodeId> getWeaklyReferringNodes(NodeId id)

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/JoinMerger.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/JoinMerger.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/JoinMerger.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/JoinMerger.java Mon Nov 29 12:24:48 2010
@@ -17,7 +17,6 @@
 package org.apache.jackrabbit.core.query.lucene.join;
 
 import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_JOIN_TYPE_LEFT_OUTER;
-import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_JOIN_TYPE_RIGHT_OUTER;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -163,93 +162,47 @@ abstract class JoinMerger {
     public QueryResult merge(RowIterator leftRows, RowIterator rightRows)
             throws RepositoryException {
         RowIterator joinRows;
-        if (JCR_JOIN_TYPE_RIGHT_OUTER.equals(type)) {
-            Map<String, List<Row>> map = new HashMap<String, List<Row>>();
-            for (Row row : new RowIterable(leftRows)) {
-                for (String value : getLeftValues(row)) {
-                    List<Row> rows = map.get(value);
-                    if (rows == null) {
-                        rows = new ArrayList<Row>();
-                        map.put(value, rows);
-                    }
-                    rows.add(row);
-                }
-            }
-            joinRows = mergeRight(map, rightRows);
-        } else {
-            Map<String, List<Row>> map = new HashMap<String, List<Row>>();
-            for (Row row : new RowIterable(rightRows)) {
-                for (String value : getRightValues(row)) {
-                    List<Row> rows = map.get(value);
-                    if (rows == null) {
-                        rows = new ArrayList<Row>();
-                        map.put(value, rows);
-                    }
-                    rows.add(row);
+
+        Map<String, List<Row>> map = new HashMap<String, List<Row>>();
+        for (Row row : new RowIterable(rightRows)) {
+            for (String value : getRightValues(row)) {
+                List<Row> rows = map.get(value);
+                if (rows == null) {
+                    rows = new ArrayList<Row>();
+                    map.put(value, rows);
                 }
+                rows.add(row);
             }
-            boolean outer = JCR_JOIN_TYPE_LEFT_OUTER.equals(type);
-            joinRows = mergeLeft(leftRows, map, outer);
         }
-        return new SimpleQueryResult(columnNames, selectorNames, joinRows);
-    }
 
-    private RowIterator mergeLeft(
-            RowIterator leftRows, Map<String, List<Row>> rightRowMap,
-            boolean outer) throws RepositoryException {
-        if (!rightRowMap.isEmpty()) {
+        if (!map.isEmpty()) {
             List<Row> rows = new ArrayList<Row>();
             for (Row leftRow : new RowIterable(leftRows)) {
                 for (String value : getLeftValues(leftRow)) {
-                    List<Row> rightRows = rightRowMap.get(value);
-                    if (rightRows != null) {
-                        for (Row rightRow : rightRows) {
+                    List<Row> matchingRows = map.get(value);
+                    if (matchingRows != null) {
+                        for (Row rightRow : matchingRows) {
                             rows.add(mergeRow(leftRow, rightRow));
                         }
-                    } else if (outer) {
+                    } else if (JCR_JOIN_TYPE_LEFT_OUTER.equals(type)) {
+                        // No matches in an outer join -> add a null row
                         rows.add(mergeRow(leftRow, null));
                     }
                 }
             }
-            return new RowIteratorAdapter(rows);
-        } else if (outer) {
-            return new RowIteratorAdapter(leftRows) {
+            joinRows = new RowIteratorAdapter(rows);
+        } else if (JCR_JOIN_TYPE_LEFT_OUTER.equals(type)) {
+            joinRows = new RowIteratorAdapter(leftRows) {
                 @Override
                 public Object next() {
                     return mergeRow((Row) super.next(), null);
                 }
             };
         } else {
-            return new RowIteratorAdapter(Collections.emptySet());
+            joinRows = new RowIteratorAdapter(Collections.emptySet());
         }
-    }
 
-    private RowIterator mergeRight(
-            Map<String, List<Row>> leftRowMap, RowIterator rightRows)
-            throws RepositoryException {
-        if (leftRowMap.isEmpty()) {
-            List<Row> rows = new ArrayList<Row>();
-            for (Row rightRow : new RowIterable(rightRows)) {
-                for (String value : getRightValues(rightRow)) {
-                    List<Row> leftRows = leftRowMap.get(value);
-                    if (leftRows != null) {
-                        for (Row leftRow : leftRows) {
-                            rows.add(mergeRow(leftRow, rightRow));
-                        }
-                    } else {
-                        rows.add(mergeRow(null, rightRow));
-                    }
-                }
-            }
-            return new RowIteratorAdapter(rows);
-        } else {
-            return new RowIteratorAdapter(rightRows) {
-                @Override
-                public Object next() {
-                    return mergeRow(null, (Row) super.next());
-                }
-            };
-        }
+        return new SimpleQueryResult(columnNames, selectorNames, joinRows);
     }
 
     /**

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/OperandEvaluator.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/OperandEvaluator.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/OperandEvaluator.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/OperandEvaluator.java Mon Nov 29 12:24:48 2010
@@ -24,6 +24,7 @@ import java.util.Map;
 import javax.jcr.Node;
 import javax.jcr.PathNotFoundException;
 import javax.jcr.Property;
+import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.UnsupportedRepositoryOperationException;
 import javax.jcr.Value;
@@ -67,6 +68,21 @@ public class OperandEvaluator {
         this.variables = variables;
     }
 
+    public Value getValue(StaticOperand operand, int type) throws RepositoryException {
+        Value value = getValue(operand);
+        if (type == PropertyType.UNDEFINED || type == value.getType()) {
+            return value;
+        } if (type == PropertyType.LONG) {
+            return factory.createValue(value.getLong());
+        } if (type == PropertyType.DOUBLE) {
+            return factory.createValue(value.getDouble());
+        } if (type == PropertyType.DATE) {
+            return factory.createValue(value.getDate());
+        } else {
+            return factory.createValue(value.getString(), type);
+        }
+    }
+
     /**
      * Returns the value of the given static operand
      * ({@link Literal literal} or {@link BindVariableValue bind variable}).
@@ -280,11 +296,14 @@ public class OperandEvaluator {
      */
     private Property getProperty(PropertyValue operand, Row row)
             throws RepositoryException {
-        try {
-            String selector = operand.getSelectorName();
-            String property = operand.getPropertyName();
-            return row.getNode(selector).getProperty(property);
-        } catch (PathNotFoundException e) {
+        Node node = row.getNode(operand.getSelectorName());
+        if (node != null) {
+            try {
+                return node.getProperty(operand.getPropertyName());
+            } catch (PathNotFoundException e) {
+                return null;
+            }
+        } else {
             return null;
         }
     }



Mime
View raw message