You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2005/02/22 17:35:10 UTC
svn commit: r154873 - in
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core: ./
nodetype/ search/ search/lucene/
Author: mreutegg
Date: Tue Feb 22 08:35:06 2005
New Revision: 154873
URL: http://svn.apache.org/viewcvs?view=rev&rev=154873
Log:
Implement coercing of String literals into JCR PropertyTypes.
Added:
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PropertyTypeRegistry.java (with props)
Modified:
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AbstractQueryHandler.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryHandler.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java?view=diff&r1=154872&r2=154873
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java Tue Feb 22 08:35:06 2005
@@ -904,7 +904,7 @@
// no search index configured
return null;
}
- searchMgr = new SearchManager(getSystemSession(), config.getSearchConfig());
+ searchMgr = new SearchManager(getSystemSession(), config.getSearchConfig(), ntReg);
}
return searchMgr;
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java?view=diff&r1=154872&r2=154873
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java Tue Feb 22 08:35:06 2005
@@ -24,8 +24,10 @@
import org.apache.jackrabbit.core.observation.SynchronousEventListener;
import org.apache.jackrabbit.core.search.QueryHandler;
import org.apache.jackrabbit.core.search.QueryImpl;
+import org.apache.jackrabbit.core.search.PropertyTypeRegistry;
import org.apache.jackrabbit.core.state.ItemStateException;
import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
import org.apache.log4j.Logger;
import javax.jcr.NamespaceException;
@@ -96,7 +98,7 @@
*/
private final QueryHandler handler;
- public SearchManager(SessionImpl session, SearchConfig config)
+ public SearchManager(SessionImpl session, SearchConfig config, NodeTypeRegistry ntReg)
throws RepositoryException {
this.session = session;
this.hmgr = session.getHierarchyManager();
@@ -123,12 +125,14 @@
nsReg.registerNamespace(NS_JCRFN_PREFIX, NS_JCRFN_URI);
}
+ PropertyTypeRegistry propRegistry = new PropertyTypeRegistry(ntReg);
+ ntReg.addListener(propRegistry);
// initialize query handler
try {
Class handlerClass = Class.forName(config.getHandlerClassName());
handler = (QueryHandler) handlerClass.newInstance();
NodeId rootId = (NodeId) session.hierMgr.resolvePath(Path.ROOT);
- handler.init(fs, session.getItemStateManager(), rootId.getUUID());
+ handler.init(fs, session.getItemStateManager(), rootId.getUUID(), propRegistry);
} catch (Exception e) {
throw new RepositoryException(e.getMessage(), e);
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java?view=diff&r1=154872&r2=154873
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java Tue Feb 22 08:35:06 2005
@@ -391,7 +391,7 @@
* @param listener the new listener to be informed on (un)registration
* of node types
*/
- void addListener(NodeTypeRegistryListener listener) {
+ public void addListener(NodeTypeRegistryListener listener) {
if (!listeners.containsKey(listener)) {
listeners.put(listener, listener);
}
@@ -402,7 +402,7 @@
*
* @param listener an existing listener
*/
- void removeListener(NodeTypeRegistryListener listener) {
+ public void removeListener(NodeTypeRegistryListener listener) {
listeners.remove(listener);
}
@@ -822,9 +822,12 @@
}
/**
- * @return
+ * Returns the names of all registered node types. That includes primary
+ * and mixin node types.
+ *
+ * @return the names of all registered node types.
*/
- synchronized QName[] getRegisteredNodeTypes() {
+ public synchronized QName[] getRegisteredNodeTypes() {
return (QName[]) registeredNTDefs.keySet().toArray(new QName[registeredNTDefs.size()]);
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AbstractQueryHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AbstractQueryHandler.java?view=diff&r1=154872&r2=154873
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AbstractQueryHandler.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AbstractQueryHandler.java Tue Feb 22 08:35:06 2005
@@ -37,6 +37,11 @@
private ItemStateManager stateProvider;
/**
+ * PropertyType registry to look up the type of a property with a given name.
+ */
+ private PropertyTypeRegistry propRegistry;
+
+ /**
* The UUID of the root node.
*/
private String rootUUID;
@@ -49,12 +54,17 @@
* <code>QueryHandler</code> may use to store its index.
* @param stateProvider provides persistent item states.
* @param rootUUID the uuid of the root node.
+ * @param registry the property type registry.
*/
- public final void init(FileSystem fs, ItemStateManager stateProvider, String rootUUID)
+ public final void init(FileSystem fs,
+ ItemStateManager stateProvider,
+ String rootUUID,
+ PropertyTypeRegistry registry)
throws IOException {
this.fs = fs;
this.stateProvider = stateProvider;
this.rootUUID = rootUUID;
+ this.propRegistry = registry;
doInit();
}
@@ -92,5 +102,13 @@
*/
protected String getRootUUID() {
return rootUUID;
+ }
+
+ /**
+ * Returns the PropertyTypeRegistry for this repository.
+ * @return the PropertyTypeRegistry for this repository.
+ */
+ protected PropertyTypeRegistry getPropertyTypeRegistry() {
+ return propRegistry;
}
}
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PropertyTypeRegistry.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PropertyTypeRegistry.java?view=auto&rev=154873
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PropertyTypeRegistry.java (added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PropertyTypeRegistry.java Tue Feb 22 08:35:06 2005
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Licensed 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.core.search;
+
+import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.Constants;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistryListener;
+import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
+import org.apache.jackrabbit.core.nodetype.PropDef;
+import org.apache.log4j.Logger;
+
+import javax.jcr.PropertyType;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * The <code>PropertyTypeRegistry</code> keeps track of registered node type
+ * definitions and its property types. It provides a fast type lookup for a
+ * given property name.
+ */
+public class PropertyTypeRegistry implements NodeTypeRegistryListener {
+
+ /** The logger instance for this class */
+ private static final Logger log = Logger.getLogger(PropertyTypeRegistry.class);
+
+ /** '*' denoting residual child item definition */
+ protected static final QName ANY_NAME = new QName(Constants.NS_DEFAULT_URI, "*");
+
+ /**
+ * Empty <code>TypeMapping</code> array as return value if no type is
+ * found
+ */
+ private static final TypeMapping[] EMPTY = new TypeMapping[0];
+
+ /** The NodeTypeRegistry */
+ private final NodeTypeRegistry registry;
+
+ /** Property QName to TypeMapping[] mapping */
+ private final Map typeMapping = new HashMap();
+
+ /**
+ * Creates a new <code>PropertyTypeRegistry</code> instance. This instance
+ * is *not* registered as listener to the NodeTypeRegistry in the constructor!
+ * @param reg the <code>NodeTypeRegistry</code> where to read the property
+ * type information.
+ */
+ public PropertyTypeRegistry(NodeTypeRegistry reg) {
+ this.registry = reg;
+ fillCache();
+ }
+
+ /**
+ * Returns an array of type mappings for a given property name
+ * <code>propName</code>. If <code>propName</code> is not defined as a property
+ * in any registered node type an empty array is returned.
+ * @param propName the name of the property.
+ * @return an array of <code>TypeMapping</code> instances.
+ */
+ public TypeMapping[] getPropertyTypes(QName propName) {
+ synchronized (typeMapping) {
+ TypeMapping[] types = (TypeMapping[]) typeMapping.get(propName);
+ return (types != null) ? types : EMPTY;
+ }
+ }
+
+ public void nodeTypeRegistered(QName ntName) {
+ try {
+ NodeTypeDef def = registry.getNodeTypeDef(ntName);
+ PropDef[] propDefs = def.getPropertyDefs();
+ synchronized (typeMapping) {
+ for (int i = 0; i < propDefs.length; i++) {
+ QName name = propDefs[i].getName();
+ int type = propDefs[i].getRequiredType();
+ if (!ANY_NAME.equals(name) && type != PropertyType.UNDEFINED) {
+ // only remember defined property types
+ TypeMapping[] types = (TypeMapping[]) typeMapping.get(name);
+ if (types == null) {
+ types = new TypeMapping[1];
+ } else {
+ TypeMapping[] tmp = new TypeMapping[types.length + 1];
+ System.arraycopy(types, 0, tmp, 0, types.length);
+ types = tmp;
+ }
+ types[types.length - 1] = new TypeMapping(type, ntName);
+ typeMapping.put(name, types);
+ }
+ }
+ }
+ } catch (NoSuchNodeTypeException e) {
+ log.error("Unable to get newly registered node type definition for name: " + ntName);
+ }
+ }
+
+ public void nodeTypeReRegistered(QName ntName) {
+ nodeTypeUnregistered(ntName);
+ nodeTypeRegistered(ntName);
+ }
+
+ public void nodeTypeUnregistered(QName ntName) {
+ // remove all TypeMapping instances refering to this ntName
+ synchronized (typeMapping) {
+ Map modified = new HashMap();
+ for (Iterator it = typeMapping.keySet().iterator(); it.hasNext();) {
+ QName propName = (QName) it.next();
+ TypeMapping[] mapping = (TypeMapping[]) typeMapping.get(propName);
+ List remove = null;
+ for (int i = 0; i < mapping.length; i++) {
+ if (mapping[i].ntName.equals(ntName)) {
+ if (remove == null) {
+ // not yet created
+ remove = new ArrayList(mapping.length);
+ }
+ remove.add(mapping[i]);
+ }
+ }
+ if (remove != null) {
+ it.remove();
+ if (mapping.length == remove.size()) {
+ // all removed -> done
+ } else {
+ // only some removed
+ List remaining = new ArrayList(Arrays.asList(mapping));
+ remaining.removeAll(remove);
+ modified.put(propName, remaining.toArray(new TypeMapping[remaining.size()]));
+ }
+ }
+ }
+ // finally re-add the modified mappings
+ typeMapping.putAll(modified);
+ }
+ }
+
+ /**
+ * Initially fills the cache of this registry with property type definitions
+ * from the {@link org.apache.jackrabbit.core.nodetype.NodeTypeRegistry}.
+ */
+ private void fillCache() {
+ QName[] ntNames = registry.getRegisteredNodeTypes();
+ for (int i = 0; i < ntNames.length; i++) {
+ nodeTypeRegistered(ntNames[i]);
+ }
+ }
+
+ public static class TypeMapping {
+
+ /** The property type as an integer */
+ public final int type;
+
+ /** The QName of the node type where this type mapping originated */
+ final QName ntName;
+
+ private TypeMapping(int type, QName ntName) {
+ this.type = type;
+ this.ntName = ntName;
+ }
+ }
+}
Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PropertyTypeRegistry.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryHandler.java?view=diff&r1=154872&r2=154873
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryHandler.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryHandler.java Tue Feb 22 08:35:06 2005
@@ -22,10 +22,8 @@
import org.apache.jackrabbit.core.ItemManager;
import org.apache.jackrabbit.core.fs.FileSystem;
-import javax.jcr.query.Query;
import javax.jcr.query.InvalidQueryException;
import javax.jcr.RepositoryException;
-import javax.jcr.Node;
import java.io.IOException;
/**
@@ -44,11 +42,13 @@
* <code>QueryHandler</code> may use to store its index.
* @param stateProvider provides persistent item states.
* @param rootUUID the UUID of the root node.
+ * @param registry the property type registry.
* @throws IOException if an error occurs during initialization.
*/
public void init(FileSystem fs,
ItemStateManager stateProvider,
- String rootUUID) throws IOException;
+ String rootUUID,
+ PropertyTypeRegistry registry) throws IOException;
/**
* Adds a <code>Node</code> to the search index.
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java?view=diff&r1=154872&r2=154873
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java Tue Feb 22 08:35:06 2005
@@ -29,6 +29,8 @@
import javax.jcr.NamespaceException;
import javax.jcr.RepositoryException;
+import javax.jcr.PropertyType;
+import javax.jcr.util.ISO8601;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeIterator;
import javax.jcr.nodetype.NodeTypeManager;
@@ -37,6 +39,7 @@
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
+import java.util.Calendar;
/**
* Implements a query builder that takes an abstract query tree and creates
@@ -75,6 +78,11 @@
* The analyzer instance to use for contains function query parsing
*/
private Analyzer analyzer;
+
+ /**
+ * The property type registry.
+ */
+ private PropertyTypeRegistry propRegistry;
/**
* Exceptions thrown during tree translation
@@ -88,15 +96,18 @@
* @param session of the user executing this query.
* @param nsMappings namespace resolver for internal prefixes.
* @param analyzer for parsing the query statement of the contains function.
+ * @param propReg the property type registry.
*/
private LuceneQueryBuilder(QueryRootNode root,
SessionImpl session,
NamespaceMappings nsMappings,
- Analyzer analyzer) {
+ Analyzer analyzer,
+ PropertyTypeRegistry propReg) {
this.root = root;
this.session = session;
this.nsMappings = nsMappings;
this.analyzer = analyzer;
+ this.propRegistry = propReg;
}
/**
@@ -107,17 +118,19 @@
* @param session of the user executing the query.
* @param nsMappings namespace resolver for internal prefixes.
* @param analyzer for parsing the query statement of the contains function.
+ * @param propReg the property type registry to lookup type information.
* @return the lucene query tree.
* @throws RepositoryException if an error occurs during the translation.
*/
public static Query createQuery(QueryRootNode root,
SessionImpl session,
NamespaceMappings nsMappings,
- Analyzer analyzer)
+ Analyzer analyzer,
+ PropertyTypeRegistry propReg)
throws RepositoryException {
LuceneQueryBuilder builder = new LuceneQueryBuilder(root,
- session, nsMappings, analyzer);
+ session, nsMappings, analyzer, propReg);
Query q = builder.createLuceneQuery();
if (builder.exceptions.size() > 0) {
@@ -396,22 +409,28 @@
public Object visit(RelationQueryNode node, Object data) {
Query query;
- String stringValue = null;
+ String stringValues[] = new String[1];
switch (node.getValueType()) {
case 0:
// not set: either IS NULL or IS NOT NULL
break;
case QueryConstants.TYPE_DATE:
- stringValue = DateField.dateToString(node.getDateValue());
+ stringValues[0] = DateField.dateToString(node.getDateValue());
break;
case QueryConstants.TYPE_DOUBLE:
- stringValue = DoubleField.doubleToString(node.getDoubleValue());
+ stringValues[0] = DoubleField.doubleToString(node.getDoubleValue());
break;
case QueryConstants.TYPE_LONG:
- stringValue = LongField.longToString(node.getLongValue());
+ stringValues[0] = LongField.longToString(node.getLongValue());
break;
case QueryConstants.TYPE_STRING:
- stringValue = node.getStringValue();
+ if (node.getOperation() == QueryConstants.OPERATION_LIKE
+ || node.getOperation() == QueryConstants.OPERATION_NULL
+ || node.getOperation() == QueryConstants.OPERATION_NOT_NULL) {
+ stringValues[0] = node.getStringValue();
+ } else {
+ stringValues = getStringValues(node.getProperty(), node.getStringValue());
+ }
break;
default:
throw new IllegalArgumentException("Unknown relation type: "
@@ -439,38 +458,84 @@
switch (node.getOperation()) {
case QueryConstants.OPERATION_EQ_VALUE: // =
- query = new TermQuery(new Term(field, stringValue));
+ if (stringValues.length == 1) {
+ query = new TermQuery(new Term(field, stringValues[0]));
+ } else {
+ BooleanQuery or = new BooleanQuery();
+ for (int i = 0; i < stringValues.length; i++) {
+ or.add(new TermQuery(new Term(field, stringValues[i])), false, false);
+ }
+ query = or;
+ }
break;
case QueryConstants.OPERATION_EQ_GENERAL: // =
// search in single and multi valued properties
BooleanQuery or = new BooleanQuery();
- or.add(new TermQuery(new Term(field, stringValue)), false, false);
- or.add(new TermQuery(new Term(mvpField, stringValue)), false, false);
+ for (int i = 0; i < stringValues.length; i++) {
+ or.add(new TermQuery(new Term(field, stringValues[i])), false, false);
+ or.add(new TermQuery(new Term(mvpField, stringValues[i])), false, false);
+ }
query = or;
break;
case QueryConstants.OPERATION_GE_VALUE: // >=
- query = new RangeQuery(new Term(field, stringValue), null, true);
+ if (stringValues.length == 1) {
+ query = new RangeQuery(new Term(field, stringValues[0]), null, true);
+ } else {
+ or = new BooleanQuery();
+ for (int i = 0; i < stringValues.length; i++) {
+ or.add(new RangeQuery(new Term(field, stringValues[i]), null, true), false, false);
+ }
+ query = or;
+ }
break;
case QueryConstants.OPERATION_GT_VALUE: // >
- query = new RangeQuery(new Term(field, stringValue), null, false);
+ if (stringValues.length == 1) {
+ query = new RangeQuery(new Term(field, stringValues[0]), null, false);
+ } else {
+ or = new BooleanQuery();
+ for (int i = 0; i < stringValues.length; i++) {
+ or.add(new RangeQuery(new Term(field, stringValues[i]), null, false), false, false);
+ }
+ query = or;
+ }
break;
case QueryConstants.OPERATION_LE_VALUE: // <=
- query = new RangeQuery(null, new Term(field, stringValue), true);
+ if (stringValues.length == 1) {
+ query = new RangeQuery(null, new Term(field, stringValues[0]), true);
+ } else {
+ or = new BooleanQuery();
+ for (int i = 0; i < stringValues.length; i++) {
+ or.add(new RangeQuery(null, new Term(field, stringValues[i]), true), false, false);
+ }
+ query = or;
+ }
break;
case QueryConstants.OPERATION_LIKE: // LIKE
- if (stringValue.equals("%")) {
+ // the like operation always has one string value.
+ // no coercing, see above
+ if (stringValues[0].equals("%")) {
query = new MatchAllQuery(field);
} else {
- query = new WildcardQuery(new Term(field, stringValue));
+ query = new WildcardQuery(new Term(field, stringValues[0]));
}
break;
case QueryConstants.OPERATION_LT_VALUE: // <
- query = new RangeQuery(null, new Term(field, stringValue), false);
+ if (stringValues.length == 1) {
+ query = new RangeQuery(null, new Term(field, stringValues[0]), false);
+ } else {
+ or = new BooleanQuery();
+ for (int i = 0; i < stringValues.length; i++) {
+ or.add(new RangeQuery(null, new Term(field, stringValues[i]), false), false, false);
+ }
+ query = or;
+ }
break;
case QueryConstants.OPERATION_NE_VALUE: // !=
BooleanQuery notQuery = new BooleanQuery();
notQuery.add(new MatchAllQuery(field), false, false);
- notQuery.add(new TermQuery(new Term(field, stringValue)), false, true);
+ for (int i = 0; i < stringValues.length; i++) {
+ notQuery.add(new TermQuery(new Term(field, stringValues[i])), false, true);
+ }
query = notQuery;
break;
case QueryConstants.OPERATION_NE_GENERAL: // !=
@@ -478,8 +543,10 @@
notQuery = new BooleanQuery();
notQuery.add(new MatchAllQuery(field), false, false);
notQuery.add(new MatchAllQuery(mvpField), false, false);
- notQuery.add(new TermQuery(new Term(field, stringValue)), false, true);
- notQuery.add(new TermQuery(new Term(mvpField, stringValue)), false, true);
+ for (int i = 0; i < stringValues.length; i++) {
+ notQuery.add(new TermQuery(new Term(field, stringValues[i])), false, true);
+ notQuery.add(new TermQuery(new Term(mvpField, stringValues[i])), false, true);
+ }
query = notQuery;
break;
case QueryConstants.OPERATION_NULL:
@@ -500,5 +567,131 @@
public Object visit(OrderQueryNode node, Object data) {
return data;
+ }
+
+ //---------------------------< internal >-----------------------------------
+
+ /**
+ * Returns an array of String values to be used as a term to lookup the search index
+ * for a String <code>literal</code> of a certain property name. This method
+ * will lookup the <code>propertyName</code> in the node type registry
+ * trying to find out the {@link javax.jcr.PropertyType}s.
+ * If no property type is found looking up node type information, this
+ * method will guess the property type.
+ * @param propertyName the name of the property in the relation.
+ * @param literal the String literal in the relation.
+ * @return the String values to use as term for the query.
+ */
+ private String[] getStringValues(QName propertyName, String literal) {
+ PropertyTypeRegistry.TypeMapping[] types = propRegistry.getPropertyTypes(propertyName);
+ List values = new ArrayList();
+ for (int i = 0; i < types.length; i++) {
+ switch (types[i].type) {
+ case PropertyType.NAME:
+ // try to translate name
+ try {
+ values.add(nsMappings.translatePropertyName(literal, session.getNamespaceResolver()));
+ log.debug("Coerced " + literal + " into NAME.");
+ } catch (IllegalNameException e) {
+ log.warn("Unable to coerce '" + literal + "' into a NAME: " + e.toString());
+ } catch (UnknownPrefixException e) {
+ log.warn("Unable to coerce '" + literal + "' into a NAME: " + e.toString());
+ }
+ break;
+ case PropertyType.PATH:
+ // try to translate path
+ try {
+ Path p = Path.create(literal, session.getNamespaceResolver(), false);
+ values.add(p.toJCRPath(nsMappings));
+ log.debug("Coerced " + literal + " into PATH.");
+ } catch (MalformedPathException e) {
+ log.warn("Unable to coerce '" + literal + "' into a PATH: " + e.toString());
+ } catch (NoPrefixDeclaredException e) {
+ log.warn("Unable to coerce '" + literal + "' into a PATH: " + e.toString());
+ }
+ break;
+ case PropertyType.DATE:
+ // try to parse date
+ Calendar c = ISO8601.parse(literal);
+ if (c != null) {
+ values.add(DateField.timeToString(c.getTimeInMillis()));
+ log.debug("Coerced " + literal + " into DATE.");
+ } else {
+ log.warn("Unable to coerce '" + literal + "' into a DATE.");
+ }
+ break;
+ case PropertyType.DOUBLE:
+ // try to parse double
+ try {
+ double d = Double.parseDouble(literal);
+ values.add(DoubleField.doubleToString(d));
+ log.debug("Coerced " + literal + " into DOUBLE.");
+ } catch (NumberFormatException e) {
+ log.warn("Unable to coerce '" + literal + "' into a DOUBLE: " + e.toString());
+ }
+ break;
+ case PropertyType.LONG:
+ // try to parse long
+ try {
+ long l = Long.parseLong(literal);
+ values.add(LongField.longToString(l));
+ log.debug("Coerced " + literal + " into LONG.");
+ } catch (NumberFormatException e) {
+ log.warn("Unable to coerce '" + literal + "' into a LONG: " + e.toString());
+ }
+ break;
+ case PropertyType.STRING:
+ values.add(literal);
+ log.debug("Using literal " + literal + " as is.");
+ break;
+ }
+ }
+ if (values.size() == 0) {
+ // try to guess property type
+ if (literal.indexOf('/') > -1) {
+ // might be a path
+ try {
+ values.add(Path.create(literal, session.getNamespaceResolver(), false).toJCRPath(nsMappings));
+ log.debug("Coerced " + literal + " into PATH.");
+ } catch (Exception e) {
+ // not a path
+ }
+ } else if (literal.indexOf(':') > -1) {
+ // might be a name
+ try {
+ values.add(QName.fromJCRName(literal, session.getNamespaceResolver()));
+ log.debug("Coerced " + literal + " into NAME.");
+ } catch (Exception e) {
+ // not a name
+ // is it a date?
+ Calendar c = ISO8601.parse(literal);
+ if (c != null) {
+ values.add(DateField.timeToString(c.getTimeInMillis()));
+ log.debug("Coerced " + literal + " into DATE.");
+ }
+ }
+ } else {
+ // long or double are possible at this point
+ try {
+ values.add(LongField.longToString(Long.parseLong(literal)));
+ log.debug("Coerced " + literal + " into LONG.");
+ } catch (NumberFormatException e) {
+ // not a long
+ // try double
+ try {
+ values.add(DoubleField.doubleToString(Double.parseDouble(literal)));
+ log.debug("Coerced " + literal + " into DOUBLE.");
+ } catch (NumberFormatException e1) {
+ // not a double
+ }
+ }
+ }
+ }
+ // if still no values use literal as is
+ if (values.size() == 0) {
+ values.add(literal);
+ log.debug("Using literal " + literal + " as is.");
+ }
+ return (String[]) values.toArray(new String[values.size()]);
}
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java?view=diff&r1=154872&r2=154873
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java Tue Feb 22 08:35:06 2005
@@ -28,6 +28,7 @@
import org.apache.jackrabbit.core.PropertyId;
import org.apache.jackrabbit.core.InternalValue;
import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.Path;
import javax.jcr.NamespaceException;
import javax.jcr.PropertyType;
@@ -229,9 +230,15 @@
false));
break;
case PropertyType.PATH:
- String path = internalValue.toString();
+ Path path = (Path) internalValue;
+ String pathString = path.toString();
+ try {
+ pathString = path.toJCRPath(mappings);
+ } catch (NoPrefixDeclaredException e) {
+ // will never happen
+ }
doc.add(new Field(fieldName,
- path,
+ pathString,
false,
true,
false));
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java?view=diff&r1=154872&r2=154873
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java Tue Feb 22 08:35:06 2005
@@ -65,11 +65,17 @@
private final SearchIndex index;
/**
+ * The property type registry for type lookup.
+ */
+ private final PropertyTypeRegistry propReg;
+
+ /**
* Creates a new query instance from a query string.
*
* @param session the session of the user executing this query.
* @param itemMgr the item manager of the session executing this query.
* @param index the search index.
+ * @param propReg the property type registry.
* @param statement the query statement.
* @param language the syntax of the query statement.
* @throws InvalidQueryException if the query statement is invalid according
@@ -78,11 +84,13 @@
public QueryImpl(SessionImpl session,
ItemManager itemMgr,
SearchIndex index,
+ PropertyTypeRegistry propReg,
String statement,
String language) throws InvalidQueryException {
this.session = session;
this.itemMgr = itemMgr;
this.index = index;
+ this.propReg = propReg;
// parse query according to language
// build query tree
this.root = QueryParser.parse(statement, language, session.getNamespaceResolver());
@@ -97,7 +105,7 @@
public QueryResult execute() throws RepositoryException {
// build lucene query
Query query = LuceneQueryBuilder.createQuery(root,
- session, index.getNamespaceMappings(), index.getAnalyzer());
+ session, index.getNamespaceMappings(), index.getAnalyzer(), propReg);
OrderQueryNode orderNode = root.getOrderNode();
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java?view=diff&r1=154872&r2=154873
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java Tue Feb 22 08:35:06 2005
@@ -196,7 +196,7 @@
String statement,
String language)
throws InvalidQueryException {
- return new QueryImpl(session, itemMgr, this, statement, language);
+ return new QueryImpl(session, itemMgr, this, getPropertyTypeRegistry(), statement, language);
}
/**