package org.apache.solr.schema; /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import org.apache.solr.common.SolrException; import org.apache.solr.common.params.MapSolrParams; import org.apache.solr.common.params.SolrParams; import org.apache.solr.search.QParser; import org.apache.lucene.search.Query; import java.util.HashMap; import java.util.Map; /** * An abstract base class for FieldTypes that delegate work to another {@link org.apache.solr.schema.FieldType}. * The sub type can be obtained by either specifying the subFieldType attribute or the subFieldSuffix. In the former * case, a new dynamic field will be injected into the schema automatically with the name of {@link #POLY_FIELD_SEPARATOR}. * In the latter case, it will use an existing dynamic field definition to get the type. See the example schema and the * use of the {@link org.apache.solr.schema.PointType} for more details. * **/ public abstract class AbstractSubTypeFieldType extends FieldType implements SchemaAware { protected FieldType subType; public static final String SUB_FIELD_SUFFIX = "subFieldSuffix"; public static final String SUB_FIELD_TYPE = "subFieldType"; protected String suffix; protected int dynFieldProps; protected String[] suffixes; protected IndexSchema schema; // needed for retrieving SchemaFields public FieldType getSubType() { return subType; } @Override protected void init(IndexSchema schema, Map<String, String> args) { this.schema = schema; //it's not a first class citizen for the IndexSchema SolrParams p = new MapSolrParams(args); String subFT = p.get(SUB_FIELD_TYPE); String subSuffix = p.get(SUB_FIELD_SUFFIX); if (subFT != null) { args.remove(SUB_FIELD_TYPE); subType = schema.getFieldTypeByName(subFT.trim()); suffix = POLY_FIELD_SEPARATOR + subType.typeName; } else if (subSuffix != null) { args.remove(SUB_FIELD_SUFFIX); suffix = subSuffix; } else { throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "The field type: " + typeName + " must specify the " + SUB_FIELD_TYPE + " attribute or the " + SUB_FIELD_SUFFIX + " attribute."); } } /** * Helper method for creating a dynamic field SchemaField prototype. Returns a {@link SchemaField} with * the {@link FieldType} given and a name of "*" + {@link FieldType#POLY_FIELD_SEPARATOR} + {@link FieldType#typeName} * and props of indexed=true, stored=false. * * @param schema the IndexSchema * @param type The {@link FieldType} of the prototype. * @return The {@link SchemaField} */ static SchemaField registerPolyFieldDynamicPrototype(IndexSchema schema, FieldType type) { String name = "*" + FieldType.POLY_FIELD_SEPARATOR + type.typeName; Map<String, String> props = new HashMap<String, String>(); //Just set these, delegate everything else to the field type props.put("indexed", "true"); props.put("stored", "false"); int p = SchemaField.calcProps(name, type, props); SchemaField proto = SchemaField.create(name, type, p, null); schema.registerDynamicField(proto); return proto; } public void inform(IndexSchema schema) { //Can't do this until here b/c the Dynamic Fields are not initialized until here. if (subType != null) { SchemaField proto = registerPolyFieldDynamicPrototype(schema, subType); dynFieldProps = proto.getProperties(); } } /** * Throws UnsupportedOperationException() */ public Query getFieldQuery(QParser parser, SchemaField field, String externalVal) { throw new UnsupportedOperationException(); } protected void createSuffixCache(int size) { suffixes = new String[size]; for (int i=0; i<size; i++) { suffixes[i] = "_" + i + suffix; } } protected SchemaField subField(SchemaField base, int i) { return schema.getField(base.getName() + suffixes[i]); } }