You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ja...@apache.org on 2013/05/30 09:53:46 UTC
svn commit: r1487777 [41/50] - in /lucene/dev/branches/security: ./
dev-tools/ dev-tools/eclipse/dot.settings/ dev-tools/idea/.idea/
dev-tools/idea/.idea/libraries/ dev-tools/idea/lucene/replicator/
dev-tools/maven/ dev-tools/maven/lucene/ dev-tools/ma...
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/IndexSchema.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/IndexSchema.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/IndexSchema.java Thu May 30 07:53:18 2013
@@ -27,8 +27,12 @@ import org.apache.lucene.util.Version;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.request.LocalSolrQueryRequest;
+import org.apache.solr.response.SchemaXmlWriter;
+import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.util.DOMUtil;
-import org.apache.solr.util.SystemIdResolver;
import org.apache.solr.core.SolrConfig;
import org.apache.solr.core.Config;
import org.apache.solr.core.SolrResourceLoader;
@@ -45,16 +49,26 @@ import org.xml.sax.InputSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
import java.io.IOException;
+import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
/**
* <code>IndexSchema</code> contains information about the valid fields in an index
@@ -62,66 +76,95 @@ import java.util.Map;
*
*
*/
-public final class IndexSchema {
+public class IndexSchema {
+ public static final String COPY_FIELD = "copyField";
+ public static final String COPY_FIELDS = COPY_FIELD + "s";
+ public static final String DEFAULT_OPERATOR = "defaultOperator";
public static final String DEFAULT_SCHEMA_FILE = "schema.xml";
+ public static final String DEFAULT_SEARCH_FIELD = "defaultSearchField";
+ public static final String DESTINATION = "dest";
+ public static final String DYNAMIC_FIELD = "dynamicField";
+ public static final String DYNAMIC_FIELDS = DYNAMIC_FIELD + "s";
+ public static final String FIELD = "field";
+ public static final String FIELDS = FIELD + "s";
+ public static final String FIELD_TYPE = "fieldType";
+ public static final String FIELD_TYPES = FIELD_TYPE + "s";
+ public static final String INTERNAL_POLY_FIELD_PREFIX = "*" + FieldType.POLY_FIELD_SEPARATOR;
public static final String LUCENE_MATCH_VERSION_PARAM = "luceneMatchVersion";
+ public static final String NAME = "name";
+ public static final String REQUIRED = "required";
+ public static final String SCHEMA = "schema";
+ public static final String SIMILARITY = "similarity";
+ public static final String SLASH = "/";
+ public static final String SOLR_QUERY_PARSER = "solrQueryParser";
+ public static final String SOURCE = "source";
+ public static final String TYPE = "type";
+ public static final String TYPES = "types";
+ public static final String UNIQUE_KEY = "uniqueKey";
+ public static final String VERSION = "version";
+
+ private static final String AT = "@";
+ private static final String DESTINATION_DYNAMIC_BASE = "destDynamicBase";
+ private static final String MAX_CHARS = "maxChars";
+ private static final String SOURCE_DYNAMIC_BASE = "sourceDynamicBase";
+ private static final String SOURCE_EXPLICIT_FIELDS = "sourceExplicitFields";
+ private static final String TEXT_FUNCTION = "text()";
+ private static final String XPATH_OR = " | ";
final static Logger log = LoggerFactory.getLogger(IndexSchema.class);
- private final SolrConfig solrConfig;
- private final String resourceName;
- private String name;
- private float version;
- private final SolrResourceLoader loader;
-
- private final HashMap<String, SchemaField> fields = new HashMap<String,SchemaField>();
-
-
- private final HashMap<String, FieldType> fieldTypes = new HashMap<String,FieldType>();
-
- private final List<SchemaField> fieldsWithDefaultValue = new ArrayList<SchemaField>();
- private final Collection<SchemaField> requiredFields = new HashSet<SchemaField>();
- private DynamicField[] dynamicFields;
+ protected final SolrConfig solrConfig;
+ protected String resourceName;
+ protected String name;
+ protected float version;
+ protected final SolrResourceLoader loader;
+
+ protected Map<String,SchemaField> fields = new HashMap<String,SchemaField>();
+ protected Map<String,FieldType> fieldTypes = new HashMap<String,FieldType>();
+
+ protected List<SchemaField> fieldsWithDefaultValue = new ArrayList<SchemaField>();
+ protected Collection<SchemaField> requiredFields = new HashSet<SchemaField>();
+ protected volatile DynamicField[] dynamicFields;
public DynamicField[] getDynamicFields() { return dynamicFields; }
private Analyzer analyzer;
private Analyzer queryAnalyzer;
- private String defaultSearchFieldName=null;
- private String queryParserDefaultOperator = "OR";
+ protected List<SchemaAware> schemaAware = new ArrayList<SchemaAware>();
+
+ protected String defaultSearchFieldName=null;
+ protected String queryParserDefaultOperator = "OR";
+ protected boolean isExplicitQueryParserDefaultOperator = false;
- private final Map<String, List<CopyField>> copyFieldsMap = new HashMap<String, List<CopyField>>();
+ protected Map<String, List<CopyField>> copyFieldsMap = new HashMap<String, List<CopyField>>();
public Map<String,List<CopyField>> getCopyFieldsMap() { return Collections.unmodifiableMap(copyFieldsMap); }
- private DynamicCopy[] dynamicCopyFields;
+ protected DynamicCopy[] dynamicCopyFields;
public DynamicCopy[] getDynamicCopyFields() { return dynamicCopyFields; }
/**
* keys are all fields copied to, count is num of copyField
* directives that target them.
*/
- private Map<SchemaField, Integer> copyFieldTargetCounts = new HashMap<SchemaField, Integer>();
+ protected Map<SchemaField, Integer> copyFieldTargetCounts = new HashMap<SchemaField, Integer>();
/**
* Constructs a schema using the specified resource name and stream.
- * If the is stream is null, the resource loader will load the schema resource by name.
* @see SolrResourceLoader#openSchema
* By default, this follows the normal config path directory searching rules.
* @see SolrResourceLoader#openResource
*/
public IndexSchema(SolrConfig solrConfig, String name, InputSource is) {
+ assert null != solrConfig : "SolrConfig should never be null";
+ assert null != name : "schema resource name should never be null";
+ assert null != is : "schema InputSource should never be null";
+
this.solrConfig = solrConfig;
- if (name == null)
- name = DEFAULT_SCHEMA_FILE;
this.resourceName = name;
loader = solrConfig.getResourceLoader();
try {
- if (is == null) {
- is = new InputSource(loader.openSchema(name));
- is.setSystemId(SystemIdResolver.createSystemIdFromResourceName(name));
- }
readSchema(is);
- loader.inform( loader );
+ loader.inform(loader);
} catch (IOException e) {
throw new RuntimeException(e);
}
@@ -138,7 +181,12 @@ public final class IndexSchema {
public String getResourceName() {
return resourceName;
}
-
+
+ /** Sets the name of the resource used to instantiate this schema. */
+ public void setResourceName(String resourceName) {
+ this.resourceName = resourceName;
+ }
+
/** Gets the name of the schema as specified in the schema resource. */
public String getSchemaName() {
return name;
@@ -149,7 +197,7 @@ public final class IndexSchema {
return solrConfig.luceneMatchVersion;
}
- float getVersion() {
+ public float getVersion() {
return version;
}
@@ -199,13 +247,25 @@ public final class IndexSchema {
*/
public Collection<SchemaField> getRequiredFields() { return requiredFields; }
- private Similarity similarity;
+ protected Similarity similarity;
/**
* Returns the Similarity used for this index
*/
- public Similarity getSimilarity() { return similarity; }
+ public Similarity getSimilarity() {
+ if (null == similarity) {
+ similarity = similarityFactory.getSimilarity();
+ }
+ return similarity;
+ }
+
+ protected SimilarityFactory similarityFactory;
+ protected boolean isExplicitSimilarity = false;
+
+ /** Returns the SimilarityFactory that constructed the Similarity for this index */
+ public SimilarityFactory getSimilarityFactory() { return similarityFactory; }
+
/**
* Returns the Analyzer used when indexing documents for this index
*
@@ -243,7 +303,7 @@ public final class IndexSchema {
return queryParserDefaultOperator;
}
- private SchemaField uniqueKeyField;
+ protected SchemaField uniqueKeyField;
/**
* Unique Key field specified in the schema file
@@ -297,6 +357,24 @@ public final class IndexSchema {
queryAnalyzer = new SolrQueryAnalyzer();
}
+ /**
+ * Writes the schema in schema.xml format to the given writer
+ */
+ void persist(Writer writer) throws IOException {
+ final SolrQueryResponse response = new SolrQueryResponse();
+ response.add(IndexSchema.SCHEMA, getNamedPropertyValues());
+ final NamedList args = new NamedList(Arrays.<Object>asList("indent", "on"));
+ final LocalSolrQueryRequest req = new LocalSolrQueryRequest(null, args);
+ final SchemaXmlWriter schemaXmlWriter = new SchemaXmlWriter(writer, req, response);
+ schemaXmlWriter.setEmitManagedSchemaDoNotEditWarning(true);
+ schemaXmlWriter.writeResponse();
+ schemaXmlWriter.close();
+ }
+
+ public boolean isMutable() {
+ return false;
+ }
+
private class SolrIndexAnalyzer extends AnalyzerWrapper {
protected final HashMap<String, Analyzer> analyzers;
@@ -343,235 +421,186 @@ public final class IndexSchema {
}
}
- private void readSchema(InputSource is) {
- log.info("Reading Solr Schema");
+ protected void readSchema(InputSource is) {
+ log.info("Reading Solr Schema from " + resourceName);
try {
// pass the config resource loader to avoid building an empty one for no reason:
// in the current case though, the stream is valid so we wont load the resource by name
- Config schemaConf = new Config(loader, "schema", is, "/schema/");
+ Config schemaConf = new Config(loader, SCHEMA, is, SLASH+SCHEMA+SLASH);
Document document = schemaConf.getDocument();
final XPath xpath = schemaConf.getXPath();
- final List<SchemaAware> schemaAware = new ArrayList<SchemaAware>();
- Node nd = (Node) xpath.evaluate("/schema/@name", document, XPathConstants.NODE);
+ String expression = stepsToPath(SCHEMA, AT + NAME);
+ Node nd = (Node) xpath.evaluate(expression, document, XPathConstants.NODE);
+ StringBuilder sb = new StringBuilder();
+ // Another case where the initialization from the test harness is different than the "real world"
+ sb.append("[");
+ if (loader.getCoreProperties() != null) {
+ sb.append(loader.getCoreProperties().getProperty(NAME));
+ } else {
+ sb.append("null");
+ }
+ sb.append("] ");
if (nd==null) {
- log.warn("schema has no name!");
+ sb.append("schema has no name!");
+ log.warn(sb.toString());
} else {
name = nd.getNodeValue();
- log.info("Schema name=" + name);
+ sb.append("Schema ");
+ sb.append(NAME);
+ sb.append("=");
+ sb.append(name);
+ log.info(sb.toString());
}
- version = schemaConf.getFloat("/schema/@version", 1.0f);
+ // /schema/@version
+ expression = stepsToPath(SCHEMA, AT + VERSION);
+ version = schemaConf.getFloat(expression, 1.0f);
// load the Field Types
- final FieldTypePluginLoader typeLoader
- = new FieldTypePluginLoader(this, fieldTypes, schemaAware);
-
- String expression = "/schema/types/fieldtype | /schema/types/fieldType";
- NodeList nodes = (NodeList) xpath.evaluate(expression, document,
- XPathConstants.NODESET);
- typeLoader.load( loader, nodes );
-
- // load the Fields
-
- // Hang on to the fields that say if they are required -- this lets us set a reasonable default for the unique key
- Map<String,Boolean> explicitRequiredProp = new HashMap<String, Boolean>();
- ArrayList<DynamicField> dFields = new ArrayList<DynamicField>();
- expression = "/schema/fields/field | /schema/fields/dynamicField";
- nodes = (NodeList) xpath.evaluate(expression, document, XPathConstants.NODESET);
-
- for (int i=0; i<nodes.getLength(); i++) {
- Node node = nodes.item(i);
-
- NamedNodeMap attrs = node.getAttributes();
-
- String name = DOMUtil.getAttr(attrs,"name","field definition");
- log.trace("reading field def "+name);
- String type = DOMUtil.getAttr(attrs,"type","field " + name);
-
- FieldType ft = fieldTypes.get(type);
- if (ft==null) {
- throw new SolrException(ErrorCode.BAD_REQUEST,"Unknown fieldtype '" + type + "' specified on field " + name);
- }
+ final FieldTypePluginLoader typeLoader = new FieldTypePluginLoader(this, fieldTypes, schemaAware);
- Map<String,String> args = DOMUtil.toMapExcept(attrs, "name", "type");
- if( args.get( "required" ) != null ) {
- explicitRequiredProp.put( name, Boolean.valueOf( args.get( "required" ) ) );
+ // /schema/types/fieldtype | /schema/types/fieldType
+ expression = stepsToPath(SCHEMA, TYPES, FIELD_TYPE.toLowerCase(Locale.ROOT)) // backcompat(?)
+ + XPATH_OR + stepsToPath(SCHEMA, TYPES, FIELD_TYPE);
+ NodeList nodes = (NodeList) xpath.evaluate(expression, document, XPathConstants.NODESET);
+ typeLoader.load(loader, nodes);
+
+ // load the fields
+ Map<String,Boolean> explicitRequiredProp = loadFields(document, xpath);
+
+ expression = stepsToPath(SCHEMA, SIMILARITY); // /schema/similarity
+ Node node = (Node) xpath.evaluate(expression, document, XPathConstants.NODE);
+ similarityFactory = readSimilarity(loader, node);
+ if (similarityFactory == null) {
+ similarityFactory = new DefaultSimilarityFactory();
+ } else {
+ isExplicitSimilarity = true;
+ }
+ if ( ! (similarityFactory instanceof SolrCoreAware)) {
+ // if the sim factory isn't SolrCoreAware (and hence schema aware),
+ // then we are responsible for erroring if a field type is trying to specify a sim.
+ for (FieldType ft : fieldTypes.values()) {
+ if (null != ft.getSimilarity()) {
+ String msg = "FieldType '" + ft.getTypeName()
+ + "' is configured with a similarity, but the global similarity does not support it: "
+ + similarityFactory.getClass();
+ log.error(msg);
+ throw new SolrException(ErrorCode.SERVER_ERROR, msg);
+ }
}
+ }
- SchemaField f = SchemaField.create(name,ft,args);
-
- if (node.getNodeName().equals("field")) {
- SchemaField old = fields.put(f.getName(),f);
- if( old != null ) {
- String msg = "[schema.xml] Duplicate field definition for '"
- + f.getName() + "' [[["+old.toString()+"]]] and [[["+f.toString()+"]]]";
- throw new SolrException(ErrorCode.SERVER_ERROR, msg );
- }
- log.debug("field defined: " + f);
- if( f.getDefaultValue() != null ) {
- log.debug(name+" contains default value: " + f.getDefaultValue());
- fieldsWithDefaultValue.add( f );
- }
- if (f.isRequired()) {
- log.debug(name+" is required in this schema");
- requiredFields.add(f);
- }
- } else if (node.getNodeName().equals("dynamicField")) {
- if (isValidDynamicFieldName(name)) {
- // make sure nothing else has the same path
- addDynamicField(dFields, f);
- } else {
- String msg = "Dynamic field name '" + name
- + "' should have either a leading or a trailing asterisk, and no others.";
+ // /schema/defaultSearchField/@text()
+ expression = stepsToPath(SCHEMA, DEFAULT_SEARCH_FIELD, TEXT_FUNCTION);
+ node = (Node) xpath.evaluate(expression, document, XPathConstants.NODE);
+ if (node==null) {
+ log.debug("no default search field specified in schema.");
+ } else {
+ defaultSearchFieldName=node.getNodeValue().trim();
+ // throw exception if specified, but not found or not indexed
+ if (defaultSearchFieldName!=null) {
+ SchemaField defaultSearchField = getFields().get(defaultSearchFieldName);
+ if ((defaultSearchField == null) || !defaultSearchField.indexed()) {
+ String msg = "default search field '" + defaultSearchFieldName + "' not defined or not indexed" ;
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
}
- } else {
- // we should never get here
- throw new RuntimeException("Unknown field type");
}
+ log.info("default search field in schema is "+defaultSearchFieldName);
}
-
- //fields with default values are by definition required
- //add them to required fields, and we only have to loop once
- // in DocumentBuilder.getDoc()
- requiredFields.addAll(getFieldsWithDefaultValue());
-
-
- // OK, now sort the dynamic fields largest to smallest size so we don't get
- // any false matches. We want to act like a compiler tool and try and match
- // the largest string possible.
- Collections.sort(dFields);
-
- log.trace("Dynamic Field Ordering:" + dFields);
- // stuff it in a normal array for faster access
- dynamicFields = dFields.toArray(new DynamicField[dFields.size()]);
+ // /schema/solrQueryParser/@defaultOperator
+ expression = stepsToPath(SCHEMA, SOLR_QUERY_PARSER, AT + DEFAULT_OPERATOR);
+ node = (Node) xpath.evaluate(expression, document, XPathConstants.NODE);
+ if (node==null) {
+ log.debug("using default query parser operator (OR)");
+ } else {
+ isExplicitQueryParserDefaultOperator = true;
+ queryParserDefaultOperator=node.getNodeValue().trim();
+ log.info("query parser default operator is "+queryParserDefaultOperator);
+ }
- Node node = (Node) xpath.evaluate("/schema/similarity", document, XPathConstants.NODE);
- SimilarityFactory simFactory = readSimilarity(loader, node);
- if (simFactory == null) {
- simFactory = new DefaultSimilarityFactory();
- }
- if (simFactory instanceof SchemaAware) {
- ((SchemaAware)simFactory).inform(this);
- } else {
- // if the sim facotry isn't schema aware, then we are responsible for
- // erroring if a field type is trying to specify a sim.
- for (FieldType ft : fieldTypes.values()) {
- if (null != ft.getSimilarity()) {
- String msg = "FieldType '" + ft.getTypeName() + "' is configured with a similarity, but the global similarity does not support it: " + simFactory.getClass();
+ // /schema/uniqueKey/text()
+ expression = stepsToPath(SCHEMA, UNIQUE_KEY, TEXT_FUNCTION);
+ node = (Node) xpath.evaluate(expression, document, XPathConstants.NODE);
+ if (node==null) {
+ log.warn("no " + UNIQUE_KEY + " specified in schema.");
+ } else {
+ uniqueKeyField=getIndexedField(node.getNodeValue().trim());
+ if (null != uniqueKeyField.getDefaultValue()) {
+ String msg = UNIQUE_KEY + " field ("+uniqueKeyFieldName+
+ ") can not be configured with a default value ("+
+ uniqueKeyField.getDefaultValue()+")";
log.error(msg);
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
}
- }
- }
- similarity = simFactory.getSimilarity();
- node = (Node) xpath.evaluate("/schema/defaultSearchField/text()", document, XPathConstants.NODE);
- if (node==null) {
- log.debug("no default search field specified in schema.");
- } else {
- defaultSearchFieldName=node.getNodeValue().trim();
- // throw exception if specified, but not found or not indexed
- if (defaultSearchFieldName!=null) {
- SchemaField defaultSearchField = getFields().get(defaultSearchFieldName);
- if ((defaultSearchField == null) || !defaultSearchField.indexed()) {
- String msg = "default search field '" + defaultSearchFieldName + "' not defined or not indexed" ;
+ if (!uniqueKeyField.stored()) {
+ log.warn(UNIQUE_KEY + " is not stored - distributed search and MoreLikeThis will not work");
+ }
+ if (uniqueKeyField.multiValued()) {
+ String msg = UNIQUE_KEY + " field ("+uniqueKeyFieldName+
+ ") can not be configured to be multivalued";
+ log.error(msg);
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
}
- }
- log.info("default search field in schema is "+defaultSearchFieldName);
- }
-
- node = (Node) xpath.evaluate("/schema/solrQueryParser/@defaultOperator", document, XPathConstants.NODE);
- if (node==null) {
- log.debug("using default query parser operator (OR)");
- } else {
- queryParserDefaultOperator=node.getNodeValue().trim();
- log.info("query parser default operator is "+queryParserDefaultOperator);
- }
-
- node = (Node) xpath.evaluate("/schema/uniqueKey/text()", document, XPathConstants.NODE);
- if (node==null) {
- log.warn("no uniqueKey specified in schema.");
- } else {
- uniqueKeyField=getIndexedField(node.getNodeValue().trim());
- if (null != uniqueKeyField.getDefaultValue()) {
- String msg = "uniqueKey field ("+uniqueKeyFieldName+
- ") can not be configured with a default value ("+
- uniqueKeyField.getDefaultValue()+")";
- log.error(msg);
- throw new SolrException(ErrorCode.SERVER_ERROR, msg);
- }
-
- if (!uniqueKeyField.stored()) {
- log.warn("uniqueKey is not stored - distributed search and MoreLikeThis will not work");
- }
- if (uniqueKeyField.multiValued()) {
- String msg = "uniqueKey field ("+uniqueKeyFieldName+
- ") can not be configured to be multivalued";
- log.error(msg);
- throw new SolrException(ErrorCode.SERVER_ERROR, msg);
- }
- uniqueKeyFieldName=uniqueKeyField.getName();
- uniqueKeyFieldType=uniqueKeyField.getType();
- log.info("unique key field: "+uniqueKeyFieldName);
+ uniqueKeyFieldName=uniqueKeyField.getName();
+ uniqueKeyFieldType=uniqueKeyField.getType();
+ log.info("unique key field: "+uniqueKeyFieldName);
- // Unless the uniqueKeyField is marked 'required=false' then make sure it exists
- if( Boolean.FALSE != explicitRequiredProp.get( uniqueKeyFieldName ) ) {
- uniqueKeyField.required = true;
- requiredFields.add(uniqueKeyField);
- }
- }
+ // Unless the uniqueKeyField is marked 'required=false' then make sure it exists
+ if( Boolean.FALSE != explicitRequiredProp.get( uniqueKeyFieldName ) ) {
+ uniqueKeyField.required = true;
+ requiredFields.add(uniqueKeyField);
+ }
+ }
- /////////////// parse out copyField commands ///////////////
- // Map<String,ArrayList<SchemaField>> cfields = new HashMap<String,ArrayList<SchemaField>>();
- // expression = "/schema/copyField";
+ /////////////// parse out copyField commands ///////////////
+ // Map<String,ArrayList<SchemaField>> cfields = new HashMap<String,ArrayList<SchemaField>>();
+ // expression = "/schema/copyField";
- dynamicCopyFields = new DynamicCopy[] {};
- expression = "//copyField";
- nodes = (NodeList) xpath.evaluate(expression, document, XPathConstants.NODESET);
+ dynamicCopyFields = new DynamicCopy[] {};
+ expression = "//" + COPY_FIELD;
+ nodes = (NodeList) xpath.evaluate(expression, document, XPathConstants.NODESET);
for (int i=0; i<nodes.getLength(); i++) {
node = nodes.item(i);
NamedNodeMap attrs = node.getAttributes();
- String source = DOMUtil.getAttr(attrs,"source","copyField definition");
- String dest = DOMUtil.getAttr(attrs,"dest", "copyField definition");
- String maxChars = DOMUtil.getAttr(attrs, "maxChars");
+ String source = DOMUtil.getAttr(attrs, SOURCE, COPY_FIELD + " definition");
+ String dest = DOMUtil.getAttr(attrs, DESTINATION, COPY_FIELD + " definition");
+ String maxChars = DOMUtil.getAttr(attrs, MAX_CHARS);
int maxCharsInt = CopyField.UNLIMITED;
if (maxChars != null) {
try {
maxCharsInt = Integer.parseInt(maxChars);
} catch (NumberFormatException e) {
- log.warn("Couldn't parse maxChars attribute for copyField from "
+ log.warn("Couldn't parse " + MAX_CHARS + " attribute for " + COPY_FIELD + " from "
+ source + " to " + dest + " as integer. The whole field will be copied.");
}
}
if (dest.equals(uniqueKeyFieldName)) {
- String msg = "uniqueKey field ("+uniqueKeyFieldName+
- ") can not be the dest of a copyField (src="+source+")";
+ String msg = UNIQUE_KEY + " field ("+uniqueKeyFieldName+
+ ") can not be the " + DESTINATION + " of a " + COPY_FIELD + "(" + SOURCE + "=" +source+")";
log.error(msg);
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
}
registerCopyField(source, dest, maxCharsInt);
- }
+ }
- for (Map.Entry<SchemaField, Integer> entry : copyFieldTargetCounts.entrySet()) {
+ for (Map.Entry<SchemaField, Integer> entry : copyFieldTargetCounts.entrySet()) {
if (entry.getValue() > 1 && !entry.getKey().multiValued()) {
log.warn("Field " + entry.getKey().name + " is not multivalued "+
- "and destination for multiple copyFields ("+
- entry.getValue()+")");
+ "and destination for multiple " + COPY_FIELDS + " ("+
+ entry.getValue()+")");
}
}
-
//Run the callbacks on SchemaAware now that everything else is done
for (SchemaAware aware : schemaAware) {
aware.inform(this);
@@ -587,8 +616,106 @@ public final class IndexSchema {
refreshAnalyzers();
}
+ /**
+ * Loads fields and dynamic fields.
+ *
+ * @return a map from field name to explicit required value
+ */
+ protected synchronized Map<String,Boolean> loadFields(Document document, XPath xpath) throws XPathExpressionException {
+ // Hang on to the fields that say if they are required -- this lets us set a reasonable default for the unique key
+ Map<String,Boolean> explicitRequiredProp = new HashMap<String,Boolean>();
+
+ ArrayList<DynamicField> dFields = new ArrayList<DynamicField>();
+
+ // /schema/fields/field | /schema/fields/dynamicField
+ String expression = stepsToPath(SCHEMA, FIELDS, FIELD)
+ + XPATH_OR + stepsToPath(SCHEMA, FIELDS, DYNAMIC_FIELD);
+ NodeList nodes = (NodeList)xpath.evaluate(expression, document, XPathConstants.NODESET);
+
+ for (int i=0; i<nodes.getLength(); i++) {
+ Node node = nodes.item(i);
+
+ NamedNodeMap attrs = node.getAttributes();
+
+ String name = DOMUtil.getAttr(attrs, NAME, "field definition");
+ log.trace("reading field def "+name);
+ String type = DOMUtil.getAttr(attrs, TYPE, "field " + name);
+
+ FieldType ft = fieldTypes.get(type);
+ if (ft==null) {
+ throw new SolrException
+ (ErrorCode.BAD_REQUEST, "Unknown " + FIELD_TYPE + " '" + type + "' specified on field " + name);
+ }
+
+ Map<String,String> args = DOMUtil.toMapExcept(attrs, NAME, TYPE);
+ if (null != args.get(REQUIRED)) {
+ explicitRequiredProp.put(name, Boolean.valueOf(args.get(REQUIRED)));
+ }
+
+ SchemaField f = SchemaField.create(name,ft,args);
+
+ if (node.getNodeName().equals(FIELD)) {
+ SchemaField old = fields.put(f.getName(),f);
+ if( old != null ) {
+ String msg = "[schema.xml] Duplicate field definition for '"
+ + f.getName() + "' [[["+old.toString()+"]]] and [[["+f.toString()+"]]]";
+ throw new SolrException(ErrorCode.SERVER_ERROR, msg );
+ }
+ log.debug("field defined: " + f);
+ if( f.getDefaultValue() != null ) {
+ log.debug(name+" contains default value: " + f.getDefaultValue());
+ fieldsWithDefaultValue.add( f );
+ }
+ if (f.isRequired()) {
+ log.debug(name+" is required in this schema");
+ requiredFields.add(f);
+ }
+ } else if (node.getNodeName().equals(DYNAMIC_FIELD)) {
+ if (isValidFieldGlob(name)) {
+ // make sure nothing else has the same path
+ addDynamicField(dFields, f);
+ } else {
+ String msg = "Dynamic field name '" + name
+ + "' should have either a leading or a trailing asterisk, and no others.";
+ throw new SolrException(ErrorCode.SERVER_ERROR, msg);
+ }
+ } else {
+ // we should never get here
+ throw new RuntimeException("Unknown field type");
+ }
+ }
+
+ //fields with default values are by definition required
+ //add them to required fields, and we only have to loop once
+ // in DocumentBuilder.getDoc()
+ requiredFields.addAll(fieldsWithDefaultValue);
+
+ // OK, now sort the dynamic fields largest to smallest size so we don't get
+ // any false matches. We want to act like a compiler tool and try and match
+ // the largest string possible.
+ Collections.sort(dFields);
+
+ log.trace("Dynamic Field Ordering:" + dFields);
+
+ // stuff it in a normal array for faster access
+ dynamicFields = dFields.toArray(new DynamicField[dFields.size()]);
+
+ return explicitRequiredProp;
+ }
+
+ /**
+ * Converts a sequence of path steps into a rooted path, by inserting slashes in front of each step.
+ * @param steps The steps to join with slashes to form a path
+ * @return a rooted path: a leading slash followed by the given steps joined with slashes
+ */
+ private String stepsToPath(String... steps) {
+ StringBuilder builder = new StringBuilder();
+ for (String step : steps) { builder.append(SLASH).append(step); }
+ return builder.toString();
+ }
+
/** Returns true if the given name has exactly one asterisk either at the start or end of the name */
- private boolean isValidDynamicFieldName(String name) {
+ private static boolean isValidFieldGlob(String name) {
if (name.startsWith("*") || name.endsWith("*")) {
int count = 0;
for (int pos = 0 ; pos < name.length() && -1 != (pos = name.indexOf('*', pos)) ; ++pos) ++count;
@@ -650,7 +777,8 @@ public final class IndexSchema {
* @see SolrCoreAware
*/
public void registerCopyField(String source, String dest, int maxChars) {
- log.debug("copyField source='" + source + "' dest='" + dest + "' maxChars=" + maxChars);
+ log.debug(COPY_FIELD + " " + SOURCE + "='" + source + "' " + DESTINATION + "='" + dest
+ + "' " + MAX_CHARS + "=" + maxChars);
DynamicField destDynamicField = null;
SchemaField destSchemaField = fields.get(dest);
@@ -660,11 +788,35 @@ public final class IndexSchema {
DynamicField destDynamicBase = null;
boolean sourceIsDynamicFieldReference = false;
+ boolean sourceIsExplicitFieldGlob = false;
+
+
+ final String invalidGlobMessage = "is an invalid glob: either it contains more than one asterisk,"
+ + " or the asterisk occurs neither at the start nor at the end.";
+ final boolean sourceIsGlob = isValidFieldGlob(source);
+ if (source.contains("*") && ! sourceIsGlob) {
+ String msg = "copyField source :'" + source + "' " + invalidGlobMessage;
+ throw new SolrException(ErrorCode.SERVER_ERROR, msg);
+ }
+ if (dest.contains("*") && ! isValidFieldGlob(dest)) {
+ String msg = "copyField dest :'" + dest + "' " + invalidGlobMessage;
+ throw new SolrException(ErrorCode.SERVER_ERROR, msg);
+ }
+
+ if (null == sourceSchemaField && sourceIsGlob) {
+ Pattern pattern = Pattern.compile(source.replace("*", ".*")); // glob->regex
+ for (String field : fields.keySet()) {
+ if (pattern.matcher(field).matches()) {
+ sourceIsExplicitFieldGlob = true;
+ break;
+ }
+ }
+ }
- if (null == destSchemaField || null == sourceSchemaField) {
+ if (null == destSchemaField || (null == sourceSchemaField && ! sourceIsExplicitFieldGlob)) {
// Go through dynamicFields array only once, collecting info for both source and dest fields, if needed
for (DynamicField dynamicField : dynamicFields) {
- if (null == sourceSchemaField && ! sourceIsDynamicFieldReference) {
+ if (null == sourceSchemaField && ! sourceIsDynamicFieldReference && ! sourceIsExplicitFieldGlob) {
if (dynamicField.matches(source)) {
sourceIsDynamicFieldReference = true;
if ( ! source.equals(dynamicField.getRegex())) {
@@ -682,22 +834,25 @@ public final class IndexSchema {
destDynamicBase = dynamicField;
}
}
- if (null != destSchemaField && (null != sourceSchemaField || sourceIsDynamicFieldReference)) break;
+ if (null != destSchemaField
+ && (null != sourceSchemaField || sourceIsDynamicFieldReference || sourceIsExplicitFieldGlob)) {
+ break;
+ }
}
}
- if (null == sourceSchemaField && ! sourceIsDynamicFieldReference) {
- String msg = "copyField source :'" + source + "' is not an explicit field and doesn't match a dynamicField.";
+ if (null == sourceSchemaField && ! sourceIsGlob && ! sourceIsDynamicFieldReference) {
+ String msg = "copyField source :'" + source + "' is not a glob and doesn't match any explicit field or dynamicField.";
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
}
if (null == destSchemaField) {
String msg = "copyField dest :'" + dest + "' is not an explicit field and doesn't match a dynamicField.";
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
}
- if (sourceIsDynamicFieldReference) {
- if (null != destDynamicField) { // source & dest: dynamic field references
+ if (sourceIsDynamicFieldReference || sourceIsGlob) {
+ if (null != destDynamicField) { // source: glob or no-asterisk dynamic field ref; dest: dynamic field ref
registerDynamicCopyField(new DynamicCopy(source, destDynamicField, maxChars, sourceDynamicBase, destDynamicBase));
incrementCopyFieldTargetCount(destSchemaField);
- } else { // source: dynamic field reference; dest: explicit field
+ } else { // source: glob or no-asterisk dynamic field ref; dest: explicit field
destDynamicField = new DynamicField(destSchemaField);
registerDynamicCopyField(new DynamicCopy(source, destDynamicField, maxChars, sourceDynamicBase, null));
incrementCopyFieldTargetCount(destSchemaField);
@@ -710,7 +865,7 @@ public final class IndexSchema {
incrementCopyFieldTargetCount(destSchemaField);
} else {
String msg = "copyField only supports a dynamic destination with an asterisk "
- + "if the source is also dynamic with an asterisk";
+ + "if the source also has an asterisk";
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
}
} else { // source & dest: explicit fields
@@ -747,10 +902,13 @@ public final class IndexSchema {
return null;
} else {
SimilarityFactory similarityFactory;
- final Object obj = loader.newInstance(((Element) node).getAttribute("class"), Object.class, "search.similarities.");
+ final String classArg = ((Element) node).getAttribute(SimilarityFactory.CLASS_NAME);
+ final Object obj = loader.newInstance(classArg, Object.class, "search.similarities.");
if (obj instanceof SimilarityFactory) {
// configure a factory, get a similarity back
- SolrParams params = SolrParams.toSolrParams(DOMUtil.childNodesToNamedList(node));
+ final NamedList<Object> namedList = DOMUtil.childNodesToNamedList(node);
+ namedList.add(SimilarityFactory.CLASS_NAME, classArg);
+ SolrParams params = SolrParams.toSolrParams(namedList);
similarityFactory = (SimilarityFactory)obj;
similarityFactory.init(params);
} else {
@@ -841,7 +999,8 @@ public final class IndexSchema {
public final static class DynamicField extends DynamicReplacement {
- final SchemaField prototype;
+ private final SchemaField prototype;
+ public SchemaField getPrototype() { return prototype; }
DynamicField(SchemaField prototype) {
super(prototype.name);
@@ -1079,25 +1238,25 @@ public final class IndexSchema {
* @return Array of fields copied into this field
*/
- public SchemaField[] getCopySources(String destField) {
+ public List<String> getCopySources(String destField) {
SchemaField f = getField(destField);
if (!isCopyFieldTarget(f)) {
- return new SchemaField[0];
+ return Collections.emptyList();
}
- List<SchemaField> sf = new ArrayList<SchemaField>();
+ List<String> fieldNames = new ArrayList<String>();
for (Map.Entry<String, List<CopyField>> cfs : copyFieldsMap.entrySet()) {
for (CopyField copyField : cfs.getValue()) {
if (copyField.getDestination().getName().equals(destField)) {
- sf.add(copyField.getSource());
+ fieldNames.add(copyField.getSource().getName());
}
}
}
for (DynamicCopy dynamicCopy : dynamicCopyFields) {
if (dynamicCopy.getDestFieldName().equals(destField)) {
- sf.add(getField(dynamicCopy.getRegex()));
+ fieldNames.add(dynamicCopy.getRegex());
}
}
- return sf.toArray(new SchemaField[sf.size()]);
+ return fieldNames;
}
/**
@@ -1130,4 +1289,181 @@ public final class IndexSchema {
public boolean isCopyFieldTarget( SchemaField f ) {
return copyFieldTargetCounts.containsKey( f );
}
+
+ /**
+ * Get a map of property name -> value for the whole schema.
+ */
+ public SimpleOrderedMap<Object> getNamedPropertyValues() {
+ SimpleOrderedMap<Object> topLevel = new SimpleOrderedMap<Object>();
+ topLevel.add(NAME, getSchemaName());
+ topLevel.add(VERSION, getVersion());
+ if (null != uniqueKeyFieldName) {
+ topLevel.add(UNIQUE_KEY, uniqueKeyFieldName);
+ }
+ if (null != defaultSearchFieldName) {
+ topLevel.add(DEFAULT_SEARCH_FIELD, defaultSearchFieldName);
+ }
+ if (isExplicitQueryParserDefaultOperator) {
+ SimpleOrderedMap<Object> solrQueryParserProperties = new SimpleOrderedMap<Object>();
+ solrQueryParserProperties.add(DEFAULT_OPERATOR, queryParserDefaultOperator);
+ topLevel.add(SOLR_QUERY_PARSER, solrQueryParserProperties);
+ }
+ if (isExplicitSimilarity) {
+ topLevel.add(SIMILARITY, similarityFactory.getNamedPropertyValues());
+ }
+ List<SimpleOrderedMap<Object>> fieldTypeProperties = new ArrayList<SimpleOrderedMap<Object>>();
+ SortedMap<String,FieldType> sortedFieldTypes = new TreeMap<String,FieldType>(fieldTypes);
+ for (FieldType fieldType : sortedFieldTypes.values()) {
+ fieldTypeProperties.add(fieldType.getNamedPropertyValues(false));
+ }
+ topLevel.add(FIELD_TYPES, fieldTypeProperties);
+ List<SimpleOrderedMap<Object>> fieldProperties = new ArrayList<SimpleOrderedMap<Object>>();
+ SortedSet<String> fieldNames = new TreeSet<String>(fields.keySet());
+ for (String fieldName : fieldNames) {
+ fieldProperties.add(fields.get(fieldName).getNamedPropertyValues(false));
+ }
+ topLevel.add(FIELDS, fieldProperties);
+ List<SimpleOrderedMap<Object>> dynamicFieldProperties = new ArrayList<SimpleOrderedMap<Object>>();
+ for (IndexSchema.DynamicField dynamicField : dynamicFields) {
+ if ( ! dynamicField.getRegex().startsWith(INTERNAL_POLY_FIELD_PREFIX)) { // omit internal polyfields
+ dynamicFieldProperties.add(dynamicField.getPrototype().getNamedPropertyValues(false));
+ }
+ }
+ topLevel.add(DYNAMIC_FIELDS, dynamicFieldProperties);
+ topLevel.add(COPY_FIELDS, getCopyFieldProperties(false, null, null));
+ return topLevel;
+ }
+
+ /**
+ * Returns a list of copyField directives, with optional details and optionally restricting to those
+ * directives that contain the requested source and/or destination field names.
+ *
+ * @param showDetails If true, source and destination dynamic bases, and explicit fields matched by source globs,
+ * will be added to dynamic copyField directives where appropriate
+ * @param requestedSourceFields If not null, output is restricted to those copyField directives
+ * with the requested source field names
+ * @param requestedDestinationFields If not null, output is restricted to those copyField directives
+ * with the requested destination field names
+ * @return a list of copyField directives
+ */
+ public List<SimpleOrderedMap<Object>> getCopyFieldProperties
+ (boolean showDetails, Set<String> requestedSourceFields, Set<String> requestedDestinationFields) {
+ List<SimpleOrderedMap<Object>> copyFieldProperties = new ArrayList<SimpleOrderedMap<Object>>();
+ SortedMap<String,List<CopyField>> sortedCopyFields = new TreeMap<String,List<CopyField>>(copyFieldsMap);
+ for (List<CopyField> copyFields : sortedCopyFields.values()) {
+ Collections.sort(copyFields, new Comparator<CopyField>() {
+ @Override
+ public int compare(CopyField cf1, CopyField cf2) {
+ // sources are all be the same, just sorting by destination here
+ return cf1.getDestination().getName().compareTo(cf2.getDestination().getName());
+ }
+ });
+ for (CopyField copyField : copyFields) {
+ final String source = copyField.getSource().getName();
+ final String destination = copyField.getDestination().getName();
+ if ( (null == requestedSourceFields || requestedSourceFields.contains(source))
+ && (null == requestedDestinationFields || requestedDestinationFields.contains(destination))) {
+ SimpleOrderedMap<Object> props = new SimpleOrderedMap<Object>();
+ props.add(SOURCE, source);
+ props.add(DESTINATION, destination);
+ if (0 != copyField.getMaxChars()) {
+ props.add(MAX_CHARS, copyField.getMaxChars());
+ }
+ copyFieldProperties.add(props);
+ }
+ }
+ }
+ for (IndexSchema.DynamicCopy dynamicCopy : dynamicCopyFields) {
+ final String source = dynamicCopy.getRegex();
+ final String destination = dynamicCopy.getDestFieldName();
+ if ( (null == requestedSourceFields || requestedSourceFields.contains(source))
+ && (null == requestedDestinationFields || requestedDestinationFields.contains(destination))) {
+ SimpleOrderedMap<Object> dynamicCopyProps = new SimpleOrderedMap<Object>();
+
+ dynamicCopyProps.add(SOURCE, dynamicCopy.getRegex());
+ if (showDetails) {
+ IndexSchema.DynamicField sourceDynamicBase = dynamicCopy.getSourceDynamicBase();
+ if (null != sourceDynamicBase) {
+ dynamicCopyProps.add(SOURCE_DYNAMIC_BASE, sourceDynamicBase.getRegex());
+ } else if (source.contains("*")) {
+ List<String> sourceExplicitFields = new ArrayList<String>();
+ Pattern pattern = Pattern.compile(source.replace("*", ".*")); // glob->regex
+ for (String field : fields.keySet()) {
+ if (pattern.matcher(field).matches()) {
+ sourceExplicitFields.add(field);
+ }
+ }
+ if (sourceExplicitFields.size() > 0) {
+ Collections.sort(sourceExplicitFields);
+ dynamicCopyProps.add(SOURCE_EXPLICIT_FIELDS, sourceExplicitFields);
+ }
+ }
+ }
+
+ dynamicCopyProps.add(DESTINATION, dynamicCopy.getDestFieldName());
+ if (showDetails) {
+ IndexSchema.DynamicField destDynamicBase = dynamicCopy.getDestDynamicBase();
+ if (null != destDynamicBase) {
+ dynamicCopyProps.add(DESTINATION_DYNAMIC_BASE, destDynamicBase.getRegex());
+ }
+ }
+
+ if (0 != dynamicCopy.getMaxChars()) {
+ dynamicCopyProps.add(MAX_CHARS, dynamicCopy.getMaxChars());
+ }
+
+ copyFieldProperties.add(dynamicCopyProps);
+ }
+ }
+ return copyFieldProperties;
+ }
+
+ protected IndexSchema(final SolrConfig solrConfig, final SolrResourceLoader loader) {
+ this.solrConfig = solrConfig;
+ this.loader = loader;
+ }
+
+ /**
+ * Copies this schema, adds the given field to the copy, then persists the new schema.
+ *
+ * @param newField the SchemaField to add
+ * @return a new IndexSchema based on this schema with newField added
+ * @see #newField(String, String, Map)
+ */
+ public IndexSchema addField(SchemaField newField) {
+ String msg = "This IndexSchema is not mutable.";
+ log.error(msg);
+ throw new SolrException(ErrorCode.SERVER_ERROR, msg);
+ }
+
+ /**
+ * Copies this schema, adds the given fields to the copy, then persists the new schema.
+ *
+ * @param newFields the SchemaFields to add
+ * @return a new IndexSchema based on this schema with newFields added
+ * @see #newField(String, String, Map)
+ */
+ public IndexSchema addFields(Collection<SchemaField> newFields) {
+ String msg = "This IndexSchema is not mutable.";
+ log.error(msg);
+ throw new SolrException(ErrorCode.SERVER_ERROR, msg);
+ }
+
+ /**
+ * Returns a SchemaField if the given fieldName does not already
+ * exist in this schema, and does not match any dynamic fields
+ * in this schema. The resulting SchemaField can be used in a call
+ * to {@link #addField(SchemaField)}.
+ *
+ * @param fieldName the name of the field to add
+ * @param fieldType the field type for the new field
+ * @param options the options to use when creating the SchemaField
+ * @return The created SchemaField
+ * @see #addField(SchemaField)
+ */
+ public SchemaField newField(String fieldName, String fieldType, Map<String,?> options) {
+ String msg = "This IndexSchema is not mutable.";
+ log.error(msg);
+ throw new SolrException(ErrorCode.SERVER_ERROR, msg);
+ }
}
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/JsonPreAnalyzedParser.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/JsonPreAnalyzedParser.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/JsonPreAnalyzedParser.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/JsonPreAnalyzedParser.java Thu May 30 07:53:18 2013
@@ -23,9 +23,9 @@ import org.apache.lucene.util.Attribute;
import org.apache.lucene.util.AttributeSource;
import org.apache.lucene.util.AttributeSource.State;
import org.apache.lucene.util.BytesRef;
-import org.apache.noggit.JSONUtil;
-import org.apache.noggit.JSONWriter;
-import org.apache.noggit.ObjectBuilder;
+import org.noggit.JSONUtil;
+import org.noggit.JSONWriter;
+import org.noggit.ObjectBuilder;
import org.apache.solr.common.util.Base64;
import org.apache.solr.schema.PreAnalyzedField.ParseResult;
import org.apache.solr.schema.PreAnalyzedField.PreAnalyzedParser;
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/LatLonType.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/LatLonType.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/LatLonType.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/LatLonType.java Thu May 30 07:53:18 2013
@@ -82,11 +82,11 @@ public class LatLonType extends Abstract
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
}
//latitude
- SchemaField lat = subField(field, i);
+ SchemaField lat = subField(field, i, schema);
f.add(lat.createField(String.valueOf(latLon[LAT]), lat.indexed() && !lat.omitNorms() ? boost : 1f));
i++;
//longitude
- SchemaField lon = subField(field, i);
+ SchemaField lon = subField(field, i, schema);
f.add(lon.createField(String.valueOf(latLon[LON]), lon.indexed() && !lon.omitNorms() ? boost : 1f));
}
@@ -114,7 +114,7 @@ public class LatLonType extends Abstract
}
BooleanQuery result = new BooleanQuery(true);
for (int i = 0; i < dimension; i++) {
- SchemaField subSF = subField(field, i);
+ SchemaField subSF = subField(field, i, parser.getReq().getSchema());
// points must currently be ordered... should we support specifying any two opposite corner points?
result.add(subSF.getType().getRangeQuery(parser, subSF, p1[i], p2[i], minInclusive, maxInclusive), BooleanClause.Occur.MUST);
}
@@ -134,7 +134,7 @@ public class LatLonType extends Abstract
}
BooleanQuery bq = new BooleanQuery(true);
for (int i = 0; i < dimension; i++) {
- SchemaField sf = subField(field, i);
+ SchemaField sf = subField(field, i, parser.getReq().getSchema());
Query tq = sf.getType().getFieldQuery(parser, sf, p1[i]);
bq.add(tq, BooleanClause.Occur.MUST);
}
@@ -173,9 +173,11 @@ public class LatLonType extends Abstract
lon2Max = 180;
}
+ IndexSchema schema = parser.getReq().getSchema();
+
// Now that we've figured out the ranges, build them!
- SchemaField latField = subField(options.field, LAT);
- SchemaField lonField = subField(options.field, LON);
+ SchemaField latField = subField(options.field, LAT, schema);
+ SchemaField lonField = subField(options.field, LON, schema);
SpatialDistanceQuery spatial = new SpatialDistanceQuery();
@@ -240,7 +242,7 @@ public class LatLonType extends Abstract
public ValueSource getValueSource(SchemaField field, QParser parser) {
ArrayList<ValueSource> vs = new ArrayList<ValueSource>(2);
for (int i = 0; i < 2; i++) {
- SchemaField sub = subField(field, i);
+ SchemaField sub = subField(field, i, parser.getReq().getSchema());
vs.add(sub.getType().getValueSource(sub, parser));
}
return new LatLonValueSource(field, vs);
@@ -498,6 +500,11 @@ class SpatialDistanceQuery extends Exten
return 1;
}
+ @Override
+ public long cost() {
+ return maxDoc;
+ }
+
public Explanation explain(int doc) throws IOException {
advance(doc);
boolean matched = this.doc == doc;
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/OpenExchangeRatesOrgProvider.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/OpenExchangeRatesOrgProvider.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/OpenExchangeRatesOrgProvider.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/OpenExchangeRatesOrgProvider.java Thu May 30 07:53:18 2013
@@ -24,7 +24,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
-import org.apache.noggit.JSONParser;
+import org.noggit.JSONParser;
import org.apache.lucene.analysis.util.ResourceLoader;
import org.apache.lucene.util.IOUtils;
import org.apache.solr.common.SolrException;
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/PointType.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/PointType.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/PointType.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/PointType.java Thu May 30 07:53:18 2013
@@ -55,7 +55,6 @@ public class PointType extends Coordinat
"The dimension must be > 0: " + dimension);
}
args.remove(DIMENSION);
- this.schema = schema;
super.init(schema, args);
// cache suffixes
@@ -83,7 +82,7 @@ public class PointType extends Coordinat
if (field.indexed()) {
for (int i=0; i<dimension; i++) {
- SchemaField sf = subField(field, i);
+ SchemaField sf = subField(field, i, schema);
f.add(sf.createField(point[i], sf.indexed() && !sf.omitNorms() ? boost : 1f));
}
}
@@ -102,7 +101,7 @@ public class PointType extends Coordinat
public ValueSource getValueSource(SchemaField field, QParser parser) {
ArrayList<ValueSource> vs = new ArrayList<ValueSource>(dimension);
for (int i=0; i<dimension; i++) {
- SchemaField sub = subField(field, i);
+ SchemaField sub = subField(field, i, schema);
vs.add(sub.getType().getValueSource(sub, parser));
}
return new PointTypeValueSource(field, vs);
@@ -146,7 +145,7 @@ public class PointType extends Coordinat
}
BooleanQuery result = new BooleanQuery(true);
for (int i = 0; i < dimension; i++) {
- SchemaField subSF = subField(field, i);
+ SchemaField subSF = subField(field, i, schema);
// points must currently be ordered... should we support specifying any two opposite corner points?
result.add(subSF.getType().getRangeQuery(parser, subSF, p1[i], p2[i], minInclusive, maxInclusive), BooleanClause.Occur.MUST);
}
@@ -164,7 +163,7 @@ public class PointType extends Coordinat
//TODO: should we assert that p1.length == dimension?
BooleanQuery bq = new BooleanQuery(true);
for (int i = 0; i < dimension; i++) {
- SchemaField sf = subField(field, i);
+ SchemaField sf = subField(field, i, schema);
Query tq = sf.getType().getFieldQuery(parser, sf, p1[i]);
bq.add(tq, BooleanClause.Occur.MUST);
}
@@ -186,11 +185,12 @@ public class PointType extends Coordinat
} catch (InvalidShapeException e) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
}
+ IndexSchema schema = parser.getReq().getSchema();
if (dimension == 1){
//TODO: Handle distance measures
String lower = String.valueOf(point[0] - options.distance);
String upper = String.valueOf(point[0] + options.distance);
- SchemaField subSF = subField(options.field, 0);
+ SchemaField subSF = subField(options.field, 0, schema);
// points must currently be ordered... should we support specifying any two opposite corner points?
result = subSF.getType().getRangeQuery(parser, subSF, lower, upper, true, true);
} else {
@@ -199,7 +199,7 @@ public class PointType extends Coordinat
double [] ur = DistanceUtils.vectorBoxCorner(point, null, options.distance, true);
double [] ll = DistanceUtils.vectorBoxCorner(point, null, options.distance, false);
for (int i = 0; i < ur.length; i++) {
- SchemaField subSF = subField(options.field, i);
+ SchemaField subSF = subField(options.field, i, schema);
Query range = subSF.getType().getRangeQuery(parser, subSF, String.valueOf(ll[i]), String.valueOf(ur[i]), true, true);
tmp.add(range, BooleanClause.Occur.MUST);
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java Thu May 30 07:53:18 2013
@@ -28,9 +28,8 @@ import java.util.Map;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.document.Field;
-import org.apache.lucene.index.GeneralField;
-import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.FieldInfo.IndexOptions;
import org.apache.lucene.search.SortField;
import org.apache.lucene.util.AttributeSource;
import org.apache.lucene.util.AttributeSource.State;
@@ -57,23 +56,27 @@ public class PreAnalyzedField extends Fi
private PreAnalyzedParser parser;
@Override
- protected void init(IndexSchema schema, Map<String, String> args) {
+ public void init(IndexSchema schema, Map<String, String> args) {
super.init(schema, args);
String implName = args.get(PARSER_IMPL);
if (implName == null) {
parser = new JsonPreAnalyzedParser();
} else {
- try {
- Class<?> implClazz = Class.forName(implName);
- if (!PreAnalyzedParser.class.isAssignableFrom(implClazz)) {
- throw new Exception("must implement " + PreAnalyzedParser.class.getName());
- }
- Constructor<?> c = implClazz.getConstructor(new Class<?>[0]);
- parser = (PreAnalyzedParser) c.newInstance(new Object[0]);
- } catch (Exception e) {
- LOG.warn("Can't use the configured PreAnalyzedParser class '" + implName + "' (" +
- e.getMessage() + "), using default " + DEFAULT_IMPL);
+ // short name
+ if ("json".equalsIgnoreCase(implName)) {
parser = new JsonPreAnalyzedParser();
+ } else if ("simple".equalsIgnoreCase(implName)) {
+ parser = new SimplePreAnalyzedParser();
+ } else {
+ try {
+ Class<? extends PreAnalyzedParser> implClazz = schema.getResourceLoader().findClass(implName, PreAnalyzedParser.class);
+ Constructor<?> c = implClazz.getConstructor(new Class<?>[0]);
+ parser = (PreAnalyzedParser) c.newInstance(new Object[0]);
+ } catch (Exception e) {
+ LOG.warn("Can't use the configured PreAnalyzedParser class '" + implName +
+ "', using default " + DEFAULT_IMPL, e);
+ parser = new JsonPreAnalyzedParser();
+ }
}
}
}
@@ -102,7 +105,7 @@ public class PreAnalyzedField extends Fi
try {
f = fromString(field, String.valueOf(value), boost);
} catch (Exception e) {
- e.printStackTrace();
+ LOG.warn("Error parsing pre-analyzed field '" + field.getName() + "'", e);
return null;
}
return f;
@@ -130,6 +133,36 @@ public class PreAnalyzedField extends Fi
}
/**
+ * Utility method to create a {@link org.apache.lucene.document.FieldType}
+ * based on the {@link SchemaField}
+ */
+ public static org.apache.lucene.document.FieldType createFieldType(SchemaField field) {
+ if (!field.indexed() && !field.stored()) {
+ if (log.isTraceEnabled())
+ log.trace("Ignoring unindexed/unstored field: " + field);
+ return null;
+ }
+ org.apache.lucene.document.FieldType newType = new org.apache.lucene.document.FieldType();
+ newType.setIndexed(field.indexed());
+ newType.setTokenized(field.isTokenized());
+ newType.setStored(field.stored());
+ newType.setOmitNorms(field.omitNorms());
+ IndexOptions options = IndexOptions.DOCS_AND_FREQS_AND_POSITIONS;
+ if (field.omitTermFreqAndPositions()) {
+ options = IndexOptions.DOCS_ONLY;
+ } else if (field.omitPositions()) {
+ options = IndexOptions.DOCS_AND_FREQS;
+ } else if (field.storeOffsetsWithPositions()) {
+ options = IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS;
+ }
+ newType.setIndexOptions(options);
+ newType.setStoreTermVectors(field.storeTermVector());
+ newType.setStoreTermVectorOffsets(field.storeTermOffsets());
+ newType.setStoreTermVectorPositions(field.storeTermPositions());
+ return newType;
+ }
+
+ /**
* This is a simple holder of a stored part and the collected states (tokens with attributes).
*/
public static class ParseResult {
@@ -167,19 +200,44 @@ public class PreAnalyzedField extends Fi
}
PreAnalyzedTokenizer parse = new PreAnalyzedTokenizer(new StringReader(val), parser);
parse.reset(); // consume
- Field f = (Field)super.createField(field, val, boost);
+ org.apache.lucene.document.FieldType type = createFieldType(field);
+ if (type == null) {
+ parse.close();
+ return null;
+ }
+ Field f = null;
if (parse.getStringValue() != null) {
- f.setStringValue(parse.getStringValue());
+ if (field.stored()) {
+ f = new Field(field.getName(), parse.getStringValue(), type);
+ } else {
+ type.setStored(false);
+ }
} else if (parse.getBinaryValue() != null) {
- f.setBytesValue(parse.getBinaryValue());
+ if (field.isBinary()) {
+ f = new Field(field.getName(), parse.getBinaryValue(), type);
+ }
} else {
- f.fieldType().setStored(false);
+ type.setStored(false);
}
if (parse.hasTokenStream()) {
- f.fieldType().setIndexed(true);
- f.fieldType().setTokenized(true);
- f.setTokenStream(parse);
+ if (field.indexed()) {
+ type.setIndexed(true);
+ type.setTokenized(true);
+ if (f != null) {
+ f.setTokenStream(parse);
+ } else {
+ f = new Field(field.getName(), parse, type);
+ }
+ } else {
+ if (f != null) {
+ f.fieldType().setIndexed(false);
+ f.fieldType().setTokenized(false);
+ }
+ }
+ }
+ if (f != null) {
+ f.setBoost(boost);
}
return f;
}
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/SchemaField.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/SchemaField.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/SchemaField.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/SchemaField.java Thu May 30 07:53:18 2013
@@ -21,7 +21,6 @@ import org.apache.solr.common.SolrExcept
import org.apache.lucene.index.StorableField;
import org.apache.lucene.search.SortField;
import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.solr.common.util.StrUtils;
import org.apache.solr.search.QParser;
import org.apache.solr.response.TextResponseWriter;
@@ -49,7 +48,7 @@ public final class SchemaField extends F
boolean required = false; // this can't be final since it may be changed dynamically
/** Declared field property overrides */
- Map<String,String> args = Collections.emptyMap();
+ Map<String,?> args = Collections.emptyMap();
/** Create a new SchemaField with the given name and type,
@@ -195,14 +194,14 @@ public final class SchemaField extends F
}
- static SchemaField create(String name, FieldType ft, Map<String,String> props) {
+ static SchemaField create(String name, FieldType ft, Map<String,?> props) {
String defaultValue = null;
if (props.containsKey(DEFAULT_VALUE)) {
- defaultValue = props.get(DEFAULT_VALUE);
+ defaultValue = (String)props.get(DEFAULT_VALUE);
}
SchemaField field = new SchemaField(name, ft, calcProps(name, ft, props), defaultValue);
- field.args = new HashMap<String,String>(props);
+ field.args = new HashMap<String,Object>(props);
return field;
}
@@ -220,9 +219,9 @@ public final class SchemaField extends F
return new SchemaField(name, ft, props, defValue);
}
- static int calcProps(String name, FieldType ft, Map<String, String> props) {
- int trueProps = parseProperties(props,true);
- int falseProps = parseProperties(props,false);
+ static int calcProps(String name, FieldType ft, Map<String,?> props) {
+ int trueProps = parseProperties(props,true,true);
+ int falseProps = parseProperties(props,false,true);
int p = ft.properties;
@@ -334,13 +333,14 @@ public final class SchemaField extends F
// The BINARY property is always false
// properties.add(getPropertyName(BINARY), isBinary());
} else {
- for (Map.Entry<String,String> arg : args.entrySet()) {
+ for (Map.Entry<String,?> arg : args.entrySet()) {
String key = arg.getKey();
- String value = arg.getValue();
+ Object value = arg.getValue();
if (key.equals(DEFAULT_VALUE)) {
properties.add(key, value);
} else {
- properties.add(key, StrUtils.parseBool(value, false));
+ boolean boolVal = value instanceof Boolean ? (Boolean)value : Boolean.parseBoolean(value.toString());
+ properties.add(key, boolVal);
}
}
}
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/SimilarityFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/SimilarityFactory.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/SimilarityFactory.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/SimilarityFactory.java Thu May 30 07:53:18 2013
@@ -17,10 +17,11 @@ package org.apache.solr.schema;
*/
import org.apache.lucene.search.similarities.Similarity;
-import org.apache.solr.schema.SchemaAware; // javadocs
-import org.apache.solr.schema.FieldType; // javadocs
+import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.common.params.SolrParams;
+import java.util.Iterator;
+
/**
* A factory interface for configuring a {@link Similarity} in the Solr
@@ -38,10 +39,50 @@ import org.apache.solr.common.params.Sol
* @see FieldType#getSimilarity
*/
public abstract class SimilarityFactory {
+ public static final String CLASS_NAME = "class";
+
protected SolrParams params;
public void init(SolrParams params) { this.params = params; }
public SolrParams getParams() { return params; }
public abstract Similarity getSimilarity();
+
+
+ /** Returns a serializable description of this similarity(factory) */
+ public SimpleOrderedMap<Object> getNamedPropertyValues() {
+ SimpleOrderedMap<Object> props = new SimpleOrderedMap<Object>();
+ props.add(CLASS_NAME, getClassArg());
+ if (null != params) {
+ Iterator<String> iter = params.getParameterNamesIterator();
+ while (iter.hasNext()) {
+ String key = iter.next();
+ if ( ! CLASS_NAME.equals(key)) {
+ props.add(key, params.get(key));
+ }
+ }
+ }
+ return props;
+ }
+
+ /**
+ * @return the string used to specify the concrete class name in a serialized representation: the class arg.
+ * If the concrete class name was not specified via a class arg, returns {@code getClass().getName()},
+ * unless this class is the anonymous similarity wrapper produced in {@link IndexSchema}, in which
+ * case the {@code getSimilarity().getClass().getName()} is returned.
+ */
+ public String getClassArg() {
+ if (null != params) {
+ String className = params.get(CLASS_NAME);
+ if (null != className) {
+ return className;
+ }
+ }
+ String className = getClass().getName();
+ if (className.startsWith("org.apache.solr.schema.IndexSchema$")) {
+ // If this class is just a no-params wrapper around a similarity class, use the similarity class
+ className = getSimilarity().getClass().getName();
+ }
+ return className;
+ }
}
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/SpatialPointVectorFieldType.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/SpatialPointVectorFieldType.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/SpatialPointVectorFieldType.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/SpatialPointVectorFieldType.java Thu May 30 07:53:18 2013
@@ -43,6 +43,14 @@ public class SpatialPointVectorFieldType
}
+ /**
+ * Adds X and Y fields to the given schema for each field with this class as its field type.
+ *
+ * {@inheritDoc}
+ *
+ * @param schema {@inheritDoc}
+ *
+ */
@Override
public void inform(IndexSchema schema) {
FieldType fieldType = schema.getFieldTypeByName(numberFieldName);
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/TextField.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/TextField.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/TextField.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/TextField.java Thu May 30 07:53:18 2013
@@ -137,7 +137,7 @@ public class TextField extends FieldType
}
public static BytesRef analyzeMultiTerm(String field, String part, Analyzer analyzerIn) {
- if (part == null) return null;
+ if (part == null || analyzerIn == null) return null;
TokenStream source;
try {
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/BitDocSet.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/BitDocSet.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/BitDocSet.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/BitDocSet.java Thu May 30 07:53:18 2013
@@ -292,6 +292,17 @@ public class BitDocSet extends DocSetBas
pos = bs.nextSetBit(target+base);
return adjustedDoc = (pos>=0 && pos<max) ? pos-base : NO_MORE_DOCS;
}
+
+ @Override
+ public long cost() {
+ // we don't want to actually compute cardinality, but
+ // if its already been computed, we use it
+ if (size != -1) {
+ return size;
+ } else {
+ return bs.capacity();
+ }
+ }
};
}
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/DocSetBase.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/DocSetBase.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/DocSetBase.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/DocSetBase.java Thu May 30 07:53:18 2013
@@ -186,6 +186,11 @@ abstract class DocSetBase implements Doc
pos = bs.nextSetBit(target+base);
return adjustedDoc = (pos>=0 && pos<max) ? pos-base : NO_MORE_DOCS;
}
+
+ @Override
+ public long cost() {
+ return bs.capacity();
+ }
};
}
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java Thu May 30 07:53:18 2013
@@ -812,7 +812,7 @@ public class ExtendedDismaxQParser exten
clause.raw = s.substring(start, pos);
// escape colons, except for "match all" query
if(!"*:*".equals(clause.raw)) {
- clause.raw = clause.raw.replaceAll(":", "\\\\:");
+ clause.raw = clause.raw.replaceAll("([^\\\\]):", "$1\\\\:");
}
} else {
clause.raw = s.substring(start, pos);
@@ -1442,10 +1442,10 @@ public class ExtendedDismaxQParser exten
public ExtendedDismaxConfiguration(SolrParams localParams,
SolrParams params, SolrQueryRequest req) {
solrParams = SolrParams.wrapDefaults(localParams, params);
- minShouldMatch = DisMaxQParser.parseMinShouldMatch(req.getSchema(), solrParams);
+ minShouldMatch = DisMaxQParser.parseMinShouldMatch(req.getSchema(), solrParams); // req.getSearcher() here causes searcher refcount imbalance
userFields = new UserFields(U.parseFieldBoosts(solrParams.getParams(DMP.UF)));
try {
- queryFields = DisMaxQParser.parseQueryFields(req.getSchema(), solrParams);
+ queryFields = DisMaxQParser.parseQueryFields(req.getSchema(), solrParams); // req.getSearcher() here causes searcher refcount imbalance
} catch (SyntaxError e) {
throw new RuntimeException();
}
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/JoinQParserPlugin.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/JoinQParserPlugin.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/JoinQParserPlugin.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/JoinQParserPlugin.java Thu May 30 07:53:18 2013
@@ -252,8 +252,7 @@ class JoinQuery extends Query {
// Although this set only includes live docs, other filters can be pushed down to queries.
DocIdSet readerSet = filter.getDocIdSet(context, acceptDocs);
- if (readerSet == null) readerSet=DocIdSet.EMPTY_DOCIDSET;
- return new JoinScorer(this, readerSet.iterator(), getBoost());
+ return new JoinScorer(this, readerSet == null ? DocIdSetIterator.empty() : readerSet.iterator(), getBoost());
}
@@ -519,7 +518,7 @@ class JoinQuery extends Query {
public JoinScorer(Weight w, DocIdSetIterator iter, float score) throws IOException {
super(w);
this.score = score;
- this.iter = iter==null ? DocIdSet.EMPTY_DOCIDSET.iterator() : iter;
+ this.iter = iter==null ? DocIdSetIterator.empty() : iter;
}
@Override
@@ -546,6 +545,11 @@ class JoinQuery extends Query {
public int advance(int target) throws IOException {
return iter.advance(target);
}
+
+ @Override
+ public long cost() {
+ return iter.cost();
+ }
}
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/LuceneQParserPlugin.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/LuceneQParserPlugin.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/LuceneQParserPlugin.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/LuceneQParserPlugin.java Thu May 30 07:53:18 2013
@@ -46,40 +46,6 @@ public class LuceneQParserPlugin extends
}
}
-class LuceneQParser extends QParser {
- SolrQueryParser lparser;
-
- public LuceneQParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
- super(qstr, localParams, params, req);
- }
-
-
- @Override
- public Query parse() throws SyntaxError {
- String qstr = getString();
- if (qstr == null || qstr.length()==0) return null;
-
- String defaultField = getParam(CommonParams.DF);
- if (defaultField==null) {
- defaultField = getReq().getSchema().getDefaultSearchFieldName();
- }
- lparser = new SolrQueryParser(this, defaultField);
-
- lparser.setDefaultOperator
- (QueryParsing.getQueryParserDefaultOperator(getReq().getSchema(),
- getParam(QueryParsing.OP)));
-
- return lparser.parse(qstr);
- }
-
-
- @Override
- public String[] getDefaultHighlightFields() {
- return lparser == null ? new String[]{} : new String[]{lparser.getDefaultField()};
- }
-
-}
-
class OldLuceneQParser extends LuceneQParser {
String sortStr;
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/QParserPlugin.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/QParserPlugin.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/QParserPlugin.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/QParserPlugin.java Thu May 30 07:53:18 2013
@@ -43,6 +43,7 @@ public abstract class QParserPlugin impl
JoinQParserPlugin.NAME, JoinQParserPlugin.class,
SurroundQParserPlugin.NAME, SurroundQParserPlugin.class,
SwitchQParserPlugin.NAME, SwitchQParserPlugin.class,
+ MaxScoreQParserPlugin.NAME, MaxScoreQParserPlugin.class
};
/** return a {@link QParser} */
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/QueryResultKey.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/QueryResultKey.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/QueryResultKey.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/QueryResultKey.java Thu May 30 07:53:18 2013
@@ -47,7 +47,7 @@ public final class QueryResultKey {
if (filters != null) {
for (Query filt : filters)
- h += filters.hashCode();
+ h += filt.hashCode();
}
sfields = (this.sort !=null) ? this.sort.getSort() : defaultSort;
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/ReturnFields.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/ReturnFields.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/ReturnFields.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/ReturnFields.java Thu May 30 07:53:18 2013
@@ -35,6 +35,13 @@ public abstract class ReturnFields {
*/
public abstract Set<String> getLuceneFieldNames();
+ /**
+ * The requested field names (includes pseudo fields)
+ * <p>
+ * @return Set of field names or <code>null</code> (all fields).
+ */
+ public abstract Set<String> getRequestedFieldNames();
+
/** Returns <code>true</code> if the specified field should be returned. */
public abstract boolean wantsField(String name);
@@ -44,6 +51,9 @@ public abstract class ReturnFields {
/** Returns <code>true</code> if the score should be returned. */
public abstract boolean wantsScore();
+ /** Returns <code>true</code> if the fieldnames should be picked with a pattern */
+ public abstract boolean hasPatternMatching();
+
/** Returns the DocTransformer used to modify documents, or <code>null</code> */
public abstract DocTransformer getTransformer();
}
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/SolrCacheBase.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/SolrCacheBase.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/SolrCacheBase.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/SolrCacheBase.java Thu May 30 07:53:18 2013
@@ -18,6 +18,8 @@
package org.apache.solr.search;
import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.net.URL;
import java.util.Map;
@@ -90,21 +92,13 @@ public abstract class SolrCacheBase {
* Returns a "Hit Ratio" (ie: max of 1.00, not a percentage) suitable for
* display purposes.
*/
- protected static String calcHitRatio(long lookups, long hits) {
- if (lookups==0) return "0.00";
- if (lookups==hits) return "1.00";
- int hundredths = (int)(hits*100/lookups); // rounded down
- if (hundredths < 10) return "0.0" + hundredths;
- return "0." + hundredths;
-
- /*** code to produce a percent, if we want it...
- int ones = (int)(hits*100 / lookups);
- int tenths = (int)(hits*1000 / lookups) - ones*10;
- return Integer.toString(ones) + '.' + tenths;
- ***/
+ protected static float calcHitRatio(long lookups, long hits) {
+ return (lookups == 0) ? 0.0f :
+ BigDecimal.valueOf((double) hits / (double) lookups)
+ .setScale(2, RoundingMode.HALF_EVEN)
+ .floatValue();
}
-
public String getVersion() {
return SolrCore.version;
}
Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/SolrConstantScoreQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/SolrConstantScoreQuery.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/SolrConstantScoreQuery.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/search/SolrConstantScoreQuery.java Thu May 30 07:53:18 2013
@@ -161,11 +161,11 @@ public class SolrConstantScoreQuery exte
this.acceptDocs = acceptDocs;
DocIdSet docIdSet = filter instanceof SolrFilter ? ((SolrFilter)filter).getDocIdSet(w.context, context, acceptDocs) : filter.getDocIdSet(context, acceptDocs);
if (docIdSet == null) {
- docIdSetIterator = DocIdSet.EMPTY_DOCIDSET.iterator();
+ docIdSetIterator = DocIdSetIterator.empty();
} else {
DocIdSetIterator iter = docIdSet.iterator();
if (iter == null) {
- docIdSetIterator = DocIdSet.EMPTY_DOCIDSET.iterator();
+ docIdSetIterator = DocIdSetIterator.empty();
} else {
docIdSetIterator = iter;
}
@@ -196,6 +196,11 @@ public class SolrConstantScoreQuery exte
public int advance(int target) throws IOException {
return docIdSetIterator.advance(target);
}
+
+ @Override
+ public long cost() {
+ return docIdSetIterator.cost();
+ }
}
@Override