content: 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");
      props.put("multiValued", "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()
     */
    @Override
    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]);
    }
  }
  