/*
 * 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.
 */
package org.apache.solr.schema;

import java.io.IOException;
import java.io.Writer;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.google.common.collect.ImmutableSet;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.DelegatingAnalyzerWrapper;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.queries.payloads.PayloadDecoder;
import org.apache.lucene.search.similarities.Similarity;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.Version;
import org.apache.solr.common.ConfigNode;
import org.apache.solr.common.MapSerializable;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.cloud.SolrClassLoader;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.Cache;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.Pair;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.core.ConfigSetService;
import org.apache.solr.core.SolrCore;
import org.apache.solr.core.SolrResourceLoader;
import org.apache.solr.request.LocalSolrQueryRequest;
import org.apache.solr.response.SchemaXmlWriter;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.search.similarities.SchemaSimilarityFactory;
import org.apache.solr.uninverting.UninvertingReader;
import org.apache.solr.util.ConcurrentLRUCache;
import org.apache.solr.common.util.DOMUtil;
import org.apache.solr.util.PayloadUtils;
import org.apache.solr.util.plugin.SolrCoreAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;

/**
 * <code>IndexSchema</code> contains information about the valid fields in an index
 * and the types of those fields.
 *
 *
 */
public class IndexSchema {
  public static final String COPY_FIELD = "copyField";
  public static final String COPY_FIELDS = COPY_FIELD + "s";
  public static final String DEFAULT_SCHEMA_FILE = "schema.xml";
  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 MAX_CHARS = "maxChars";
  public static final String NAME = "name";
  public static final String NEST_PARENT_FIELD_NAME = "_nest_parent_";
  public static final String NEST_PATH_FIELD_NAME = "_nest_path_";
  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 SOURCE = "source";
  public static final String TYPE = "type";
  public static final String TYPES = "types";
  public static final String ROOT_FIELD_NAME = "_root_";
  public static final String UNIQUE_KEY = "uniqueKey";
  public static final String VERSION = "version";

  private static final String DESTINATION_DYNAMIC_BASE = "destDynamicBase";
  private static final String SOURCE_DYNAMIC_BASE = "sourceDynamicBase";
  private static final String SOURCE_EXPLICIT_FIELDS = "sourceExplicitFields";

  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
  protected String resourceName;
  protected String name;
  protected final Version luceneVersion;
  protected float version;
  protected final SolrResourceLoader loader;
  protected final SolrClassLoader solrClassLoader;
  protected final Properties substitutableProperties;

  protected Map<String,SchemaField> fields = new HashMap<>();
  protected Map<String,FieldType> fieldTypes = new HashMap<>();

  protected List<SchemaField> fieldsWithDefaultValue = new ArrayList<>();
  protected Collection<SchemaField> requiredFields = new HashSet<>();
  protected DynamicField[] dynamicFields = new DynamicField[] {};

  public DynamicField[] getDynamicFields() { return dynamicFields; }

  private static final Set<String> FIELDTYPE_KEYS = ImmutableSet.of("fieldtype", "fieldType");
  private static final Set<String> FIELD_KEYS = ImmutableSet.of("dynamicField", "field");

  @SuppressWarnings({"unchecked", "rawtypes"})
  protected Cache<String, SchemaField> dynamicFieldCache = new ConcurrentLRUCache(10000, 8000, 9000,100, false,false, null);

  private Analyzer indexAnalyzer;
  private Analyzer queryAnalyzer;

  protected List<SchemaAware> schemaAware = new ArrayList<>();

  protected Map<String, List<CopyField>> copyFieldsMap = new HashMap<>();
  public Map<String,List<CopyField>> getCopyFieldsMap() { return Collections.unmodifiableMap(copyFieldsMap); }

  protected DynamicCopy[] dynamicCopyFields = new DynamicCopy[] {};
  public DynamicCopy[] getDynamicCopyFields() { return dynamicCopyFields; }

  private Map<FieldType, PayloadDecoder> decoders = new HashMap<>();  // cache to avoid scanning token filters repeatedly, unnecessarily

  /**
   * keys are all fields copied to, count is num of copyField
   * directives that target them.
   */
  protected Map<SchemaField, Integer> copyFieldTargetCounts = new HashMap<>();
  private ConfigNode rootNode;


  /**
   * Constructs a schema using the specified resource name and stream.
   * By default, this follows the normal config path directory searching rules.
   * @see SolrResourceLoader#openResource
   */
  public IndexSchema(String name, ConfigSetService.ConfigResource schemaResource, Version luceneVersion, SolrResourceLoader resourceLoader, Properties substitutableProperties) {
    this(luceneVersion, resourceLoader, substitutableProperties);

    this.resourceName = Objects.requireNonNull(name);
    ConfigNode.SUBSTITUTES.set(key -> substitutableProperties == null ?
        null :
        substitutableProperties.getProperty(key));
    try {
      readSchema(schemaResource);
      loader.inform(loader);
    } catch (IOException e) {
      throw new RuntimeException(e);
    } finally {
      ConfigNode.SUBSTITUTES.remove();
    }
  }

  protected IndexSchema(Version luceneVersion, SolrResourceLoader loader, Properties substitutableProperties) {
    this.luceneVersion = Objects.requireNonNull(luceneVersion);
    this.loader = loader;
    this.solrClassLoader = loader.getSchemaLoader() == null ? loader : loader.getSchemaLoader();
    this.substitutableProperties = substitutableProperties;
  }

  /**
   * The resource loader to be used to load components related to the schema when the schema is loading
   * / initialising.
   * It should <em>not</em> be used for any other purpose or time;
   * consider {@link SolrCore#getResourceLoader()} instead.
   * @since solr 1.4
   */
  public SolrResourceLoader getResourceLoader() {
    //TODO consider asserting the schema has not finished loading somehow?
    return loader;
  }

  /** Gets the name of the resource used to instantiate this schema. */
  public String getResourceName() {
    return resourceName;
  }

  public SolrClassLoader getSolrClassLoader() {
    return solrClassLoader;
  }

  /** 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;
  }

  /** The Default Lucene Match Version for this IndexSchema */
  public Version getDefaultLuceneMatchVersion() {
    return luceneVersion;
  }

  public float getVersion() {
    return version;
  }


  /**
   * Provides direct access to the Map containing all explicit
   * (ie: non-dynamic) fields in the index, keyed on field name.
   *
   * <p>
   * Modifying this Map (or any item in it) will affect the real schema
   * </p>
   *
   * <p>
   * NOTE: this function is not thread safe.  However, it is safe to use within the standard
   * <code>inform( SolrCore core )</code> function for <code>SolrCoreAware</code> classes.
   * Outside <code>inform</code>, this could potentially throw a ConcurrentModificationException
   * </p>
   */
  public Map<String,SchemaField> getFields() { return fields; }

  /**
   * Provides direct access to the Map containing all Field Types
   * in the index, keyed on field type name.
   *
   * <p>
   * Modifying this Map (or any item in it) will affect the real schema.  However if you
   * make any modifications, be sure to call {@link IndexSchema#refreshAnalyzers()} to
   * update the Analyzers for the registered fields.
   * </p>
   *
   * <p>
   * NOTE: this function is not thread safe.  However, it is safe to use within the standard
   * <code>inform( SolrCore core )</code> function for <code>SolrCoreAware</code> classes.
   * Outside <code>inform</code>, this could potentially throw a ConcurrentModificationException
   * </p>
   */
  public Map<String,FieldType> getFieldTypes() { return fieldTypes; }

  /**
   * Provides direct access to the List containing all fields with a default value
   */
  public List<SchemaField> getFieldsWithDefaultValue() { return fieldsWithDefaultValue; }

  /**
   * Provides direct access to the List containing all required fields.  This
   * list contains all fields with default values.
   */
  public Collection<SchemaField> getRequiredFields() { return requiredFields; }

  protected Similarity similarity;

  /**
   * Returns the Similarity used for this index
   */
  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
   *
   * <p>
   * This Analyzer is field (and dynamic field) name aware, and delegates to
   * a field specific Analyzer based on the field type.
   * </p>
   */
  public Analyzer getIndexAnalyzer() { return indexAnalyzer; }

  /**
   * Returns the Analyzer used when searching this index
   *
   * <p>
   * This Analyzer is field (and dynamic field) name aware, and delegates to
   * a field specific Analyzer based on the field type.
   * </p>
   */
  public Analyzer getQueryAnalyzer() { return queryAnalyzer; }


  protected SchemaField uniqueKeyField;

  /**
   * Unique Key field specified in the schema file
   * @return null if this schema has no unique key field
   */
  public SchemaField getUniqueKeyField() { return uniqueKeyField; }

  protected String uniqueKeyFieldName;
  protected FieldType uniqueKeyFieldType;

  /**
   * The raw (field type encoded) value of the Unique Key field for
   * the specified Document
   * @return null if this schema has no unique key field
   * @see #printableUniqueKey
   */
  public IndexableField getUniqueKeyField(org.apache.lucene.document.Document doc) {
    return doc.getField(uniqueKeyFieldName);  // this should return null if name is null
  }

  /**
   * The printable value of the Unique Key field for
   * the specified Document
   * @return null if this schema has no unique key field
   */
  public String printableUniqueKey(org.apache.lucene.document.Document doc) {
    IndexableField f = doc.getField(uniqueKeyFieldName);
    return f==null ? null : uniqueKeyFieldType.toExternal(f);
  }

  /** Like {@link #printableUniqueKey(org.apache.lucene.document.Document)} */
  public String printableUniqueKey(SolrDocument solrDoc) {
    Object val = solrDoc.getFieldValue(uniqueKeyFieldName);
    if (val == null) {
      return null;
    } else if (val instanceof IndexableField) {
      return uniqueKeyFieldType.toExternal((IndexableField) val);
    } else {
      return val.toString();
    }
  }

  /** Like {@link #printableUniqueKey(org.apache.lucene.document.Document)} */
  public String printableUniqueKey(SolrInputDocument solrDoc) {
    Object val = solrDoc.getFieldValue(uniqueKeyFieldName);
    if (val == null) {
      return null;
    } else {
      return val.toString();
    }
  }

  /** Given an indexable uniqueKey value, return the readable/printable version */
  public String printableUniqueKey(BytesRef idBytes) {
    return uniqueKeyFieldType.indexedToReadable(idBytes.utf8ToString());
  }

  /** Given a readable/printable uniqueKey value, return an indexable version */
  public BytesRef indexableUniqueKey(String idStr) {
    return new BytesRef(uniqueKeyFieldType.toInternal(idStr));
  }

  private SchemaField getIndexedField(String fname) {
    SchemaField f = getFields().get(fname);
    if (f==null) {
      throw new RuntimeException("unknown field '" + fname + "'");
    }
    if (!f.indexed()) {
      throw new RuntimeException("'"+fname+"' is not an indexed field:" + f);
    }
    return f;
  }

  /**
   * This will re-create the Analyzers.  If you make any modifications to
   * the Field map ({@link IndexSchema#getFields()}, this function is required
   * to synch the internally cached field analyzers.
   *
   * @since solr 1.3
   */
  public void refreshAnalyzers() {
    indexAnalyzer = new SolrIndexAnalyzer();
    queryAnalyzer = new SolrQueryAnalyzer();
  }

  /** @see UninvertingReader */
  public Function<String, UninvertingReader.Type> getUninversionMapper() {
    return name -> {
      SchemaField sf = getFieldOrNull(name);
      if (sf == null) {
        return null;
      }

      if (sf.isUninvertible()) {
        return sf.getType().getUninversionType(sf);
      }
      // else...

      // It would be nice to throw a helpful error here, with a good useful message for the user,
      // but unfortunately, inspite of the UninvertingReader class jdoc claims that the uninversion
      // process is lazy, that doesn't mean it's lazy as of "When a caller attempts ot use doc values"
      //
      // The *mapping* function is consulted on LeafReader init/wrap for every FieldInfos found w/o docValues.
      //
      // So if we throw an error here instead of returning null, the act of just opening a
      // newSearcher will trigger that error for any field, even if no one ever attempts to uninvert it
      return null;
    };
  }

  /**
   * 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 SolrParams args = (new ModifiableSolrParams()).set("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 DelegatingAnalyzerWrapper {
    protected final HashMap<String, Analyzer> analyzers;

    SolrIndexAnalyzer() {
      super(PER_FIELD_REUSE_STRATEGY);
      analyzers = analyzerCache();
    }

    protected HashMap<String, Analyzer> analyzerCache() {
      HashMap<String, Analyzer> cache = new HashMap<>();
      for (SchemaField f : getFields().values()) {
        Analyzer analyzer = f.getType().getIndexAnalyzer();
        cache.put(f.getName(), analyzer);
      }
      return cache;
    }

    @Override
    protected Analyzer getWrappedAnalyzer(String fieldName) {
      Analyzer analyzer = analyzers.get(fieldName);
      return analyzer != null ? analyzer : getDynamicFieldType(fieldName).getIndexAnalyzer();
    }

  }

  private class SolrQueryAnalyzer extends SolrIndexAnalyzer {
    SolrQueryAnalyzer() {}

    @Override
    protected HashMap<String, Analyzer> analyzerCache() {
      HashMap<String, Analyzer> cache = new HashMap<>();
      for (SchemaField f : getFields().values()) {
        Analyzer analyzer = f.getType().getQueryAnalyzer();
        cache.put(f.getName(), analyzer);
      }
      return cache;
    }

    @Override
    protected Analyzer getWrappedAnalyzer(String fieldName) {
      Analyzer analyzer = analyzers.get(fieldName);
      return analyzer != null ? analyzer : getDynamicFieldType(fieldName).getQueryAnalyzer();
    }
  }

  protected void readSchema(ConfigSetService.ConfigResource is) {
    assert null != is : "schema InputSource should never be null";
    try {
      rootNode = is.get();
      name = rootNode.attributes().get("name");
      StringBuilder sb = new StringBuilder();
      // Another case where the initialization from the test harness is different than the "real world"
      if (name==null) {
        sb.append("schema has no name!");
        log.warn("{}", sb);
      } else {
        sb.append("Schema ");
        sb.append(NAME);
        sb.append("=");
        sb.append(name);
        log.info("{}", sb);
      }

      version =  Float.parseFloat(rootNode.attributes().get("version","1.0f"));

      // load the Field Types
      final FieldTypePluginLoader typeLoader = new FieldTypePluginLoader(this, fieldTypes, schemaAware);

      List<ConfigNode> fTypes = rootNode.getAll(null, FIELDTYPE_KEYS);
      ConfigNode types = rootNode.child(TYPES);
      if(types != null) fTypes.addAll(types.getAll(null, FIELDTYPE_KEYS));
      typeLoader.load(solrClassLoader, fTypes);

      // load the fields
      Map<String,Boolean> explicitRequiredProp = loadFields(rootNode);


      similarityFactory = readSimilarity(solrClassLoader, rootNode.child(SIMILARITY));
      if (similarityFactory == null) {
        final Class<?> simClass = SchemaSimilarityFactory.class;
        // use the loader to ensure proper SolrCoreAware handling
        similarityFactory = solrClassLoader.newInstance(simClass.getName(), SimilarityFactory.class);
        similarityFactory.init(new ModifiableSolrParams());
      } 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);
          }
        }
      }

      ConfigNode node = rootNode.child("defaultSearchField");
      if (node != null) {
        throw new SolrException(ErrorCode.SERVER_ERROR, "Setting defaultSearchField in schema not supported since Solr 7");
      }

      node = rootNode.child(it -> it.attributes().get("defaultOperator") != null, "solrQueryParser");
      if (node != null) {
        throw new SolrException(ErrorCode.SERVER_ERROR, "Setting default operator in schema (solrQueryParser/@defaultOperator) not supported");
      }

      node = rootNode.child(UNIQUE_KEY);

      if (node==null) {
        log.warn("no {} specified in schema.", UNIQUE_KEY);
      } else {
        uniqueKeyField=getIndexedField(node.txt().trim());
        uniqueKeyFieldName=uniqueKeyField.getName();
        uniqueKeyFieldType=uniqueKeyField.getType();

        // we fail on init if the ROOT field is *explicitly* defined as incompatible with uniqueKey
        // we don't want ot fail if there happens to be a dynamicField matching ROOT, (ie: "*")
        // because the user may not care about child docs at all.  The run time code
        // related to child docs can catch that if it happens
        if (fields.containsKey(ROOT_FIELD_NAME) && ! isUsableForChildDocs()) {
          String msg = ROOT_FIELD_NAME + " field must be defined using the exact same fieldType as the " +
              UNIQUE_KEY + " field ("+uniqueKeyFieldName+") uses: " + uniqueKeyFieldType.getTypeName();
          log.error(msg);
          throw new SolrException(ErrorCode.SERVER_ERROR, msg);
        }

        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);
        }

        if (!uniqueKeyField.stored()) {
          log.warn("{} is not stored - distributed search and MoreLikeThis will not work", UNIQUE_KEY);
        }
        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);
        }

        if (uniqueKeyField.getType().isPointField()) {
          String msg = UNIQUE_KEY + " field ("+uniqueKeyFieldName+
              ") can not be configured to use a Points based FieldType: " + uniqueKeyField.getType().getTypeName();
          log.error(msg);
          throw new SolrException(ErrorCode.SERVER_ERROR, msg);
        }

        // 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";

      dynamicCopyFields = new DynamicCopy[] {};
      loadCopyFields(rootNode);

      postReadInform();

    } catch (SolrException e) {
      throw new SolrException(ErrorCode.getErrorCode(e.code()),
          "Can't load schema " + loader.resourceLocation(resourceName) + ": " + e.getMessage(), e);
    } catch(Exception e) {
      // unexpected exception...
      throw new SolrException(ErrorCode.SERVER_ERROR,
          "Can't load schema " + loader.resourceLocation(resourceName) + ": " + e.getMessage(), e);
    }

    // create the field analyzers
    refreshAnalyzers();

    log.info("Loaded schema {}/{} with uniqueid field {}", name, version, uniqueKeyFieldName);
  }

  protected void postReadInform() {
    //Run the callbacks on SchemaAware now that everything else is done
    for (SchemaAware aware : schemaAware) {
      aware.inform(this);
    }
  }

  /**
   * Loads fields and dynamic fields.
   *
   * @return a map from field name to explicit required value
   */
  protected synchronized Map<String,Boolean> loadFields(ConfigNode n) {
    // 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<>();

    ArrayList<DynamicField> dFields = new ArrayList<>();

    List<ConfigNode> nodes = n.getAll(null,  FIELD_KEYS);
    ConfigNode child = n.child(FIELDS);
    if(child != null) {
      nodes.addAll(child.getAll(null, FIELD_KEYS));
    }

    for (ConfigNode node : nodes) {
      String name = DOMUtil.getAttr(node, NAME, "field definition");
      log.trace("reading field def {}", name);
      String type = DOMUtil.getAttr(node, 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(node, NAME, TYPE);
      if (null != args.get(REQUIRED)) {
        explicitRequiredProp.put(name, Boolean.valueOf(args.get(REQUIRED)));
      }

      SchemaField f = SchemaField.create(name, ft, args);

      if (node.name().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) {
          if (log.isDebugEnabled()) {
            log.debug("{} contains default value {}", name, f.getDefaultValue());
          }
          fieldsWithDefaultValue.add(f);
        }
        if (f.isRequired()) {
          log.debug("{} is required in this schema", name);
          requiredFields.add(f);
        }
      } else if (node.name().equals(DYNAMIC_FIELD)) {
        if (isValidDynamicField(dFields, f)) {
          addDynamicFieldNoDupCheck(dFields, f);
        }
      } 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);

    dynamicFields = dynamicFieldListToSortedArray(dFields);

    return explicitRequiredProp;
  }

  /**
   * Sort the dynamic fields and stuff them in a normal array for faster access.
   */
  protected static DynamicField[] dynamicFieldListToSortedArray(List<DynamicField> dynamicFieldList) {
    // Avoid creating the array twice by converting to an array first and using Arrays.sort(),
    // rather than Collections.sort() then converting to an array, since Collections.sort()
    // copies to an array first, then sets each collection member from the array.
    DynamicField[] dFields = dynamicFieldList.toArray(new DynamicField[dynamicFieldList.size()]);
    Arrays.sort(dFields);

    if (log.isTraceEnabled()) {
      log.trace("Dynamic Field Ordering: {}", Arrays.toString(dFields));
    }

    return dFields;
  }

  /**
   * Loads the copy fields
   */
  protected synchronized void loadCopyFields(ConfigNode n) {
    List<ConfigNode> nodes = n.getAll(COPY_FIELD);
    ConfigNode f = n.child(FIELDS);
    if (f != null) {
      nodes = new ArrayList<>(nodes);
      nodes.addAll(f.getAll(COPY_FIELD));
    }
    for (ConfigNode node : nodes) {

      String source = DOMUtil.getAttr(node, SOURCE, COPY_FIELD + " definition");
      String dest   = DOMUtil.getAttr(node, DESTINATION,  COPY_FIELD + " definition");
      String maxChars = DOMUtil.getAttr(node, MAX_CHARS, null);

      int maxCharsInt = CopyField.UNLIMITED;
      if (maxChars != null) {
        try {
          maxCharsInt = Integer.parseInt(maxChars);
        } catch (NumberFormatException e) {
          log.warn("Couldn't parse {} attribute for '{}' from '{}' to '{}' as integer. The whole field will be copied."
              , MAX_CHARS, COPY_FIELD, source, dest);
        }
      }

      if (dest.equals(uniqueKeyFieldName)) {
        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()) {
      if (entry.getValue() > 1 && !entry.getKey().multiValued())  {
        log.warn("Field {} is not multivalued and destination for multiople {} ({})"
            , entry.getKey().name, COPY_FIELDS, entry.getValue());
      }
    }
  }

  /** Returns true if the given name has exactly one asterisk either at the start or end of the name */
  protected 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;
      if (1 == count) return true;
    }
    return false;
  }

  protected boolean isValidDynamicField(List<DynamicField> dFields, SchemaField f) {
    String glob = f.getName();
    if (f.getDefaultValue() != null) {
      throw new SolrException(ErrorCode.SERVER_ERROR,
          DYNAMIC_FIELD + " can not have a default value: " + glob);
    }
    if (f.isRequired()) {
      throw new SolrException(ErrorCode.SERVER_ERROR,
          DYNAMIC_FIELD + " can not be required: " + glob);
    }
    if ( ! isValidFieldGlob(glob)) {
      String msg = "Dynamic field name '" + glob
          + "' should have either a leading or a trailing asterisk, and no others.";
      throw new SolrException(ErrorCode.SERVER_ERROR, msg);
    }
    if (isDuplicateDynField(dFields, f)) {
      String msg = "[schema.xml] Duplicate DynamicField definition for '" + glob + "'";
      throw new SolrException(ErrorCode.SERVER_ERROR, msg);
    }
    return true;
  }


  /**
   * Register one or more new Dynamic Fields with the Schema.
   * @param fields The sequence of {@link org.apache.solr.schema.SchemaField}
   */
  public void registerDynamicFields(SchemaField... fields) {
    List<DynamicField> dynFields = new ArrayList<>(asList(dynamicFields));
    for (SchemaField field : fields) {
      if (isDuplicateDynField(dynFields, field)) {
        if (log.isDebugEnabled()) {
          log.debug("dynamic field already exists: dynamic field: [{}]", field.getName());
        }
      } else {
        if (log.isDebugEnabled()) {
          log.debug("dynamic field creation for schema field: {}", field.getName());
        }
        addDynamicFieldNoDupCheck(dynFields, field);
      }
    }
    dynamicFields = dynamicFieldListToSortedArray(dynFields);
  }

  private void addDynamicFieldNoDupCheck(List<DynamicField> dFields, SchemaField f) {
    dFields.add(new DynamicField(f));
    log.debug("dynamic field defined: {}", f);
  }

  protected boolean isDuplicateDynField(List<DynamicField> dFields, SchemaField f) {
    for (DynamicField df : dFields) {
      if (df.getRegex().equals(f.name)) return true;
    }
    return false;
  }

  public void registerCopyField( String source, String dest ) {
    registerCopyField(source, dest, CopyField.UNLIMITED);
  }

  /**
   * <p>
   * NOTE: this function is not thread safe.  However, it is safe to use within the standard
   * <code>inform( SolrCore core )</code> function for <code>SolrCoreAware</code> classes.
   * Outside <code>inform</code>, this could potentially throw a ConcurrentModificationException
   * </p>
   *
   * @see SolrCoreAware
   */
  public void registerCopyField(String source, String dest, int maxChars) {
    log.debug("{} {}='{}' {}='{}' {}='{}'", COPY_FIELD, SOURCE, source, DESTINATION, dest
        ,MAX_CHARS, maxChars);

    DynamicField destDynamicField = null;
    SchemaField destSchemaField = fields.get(dest);
    SchemaField sourceSchemaField = fields.get(source);

    DynamicField sourceDynamicBase = null;
    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 && ! 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 && ! sourceIsExplicitFieldGlob) {
          if (dynamicField.matches(source)) {
            sourceIsDynamicFieldReference = true;
            if ( ! source.equals(dynamicField.getRegex())) {
              sourceDynamicBase = dynamicField;
            }
          }
        }
        if (null == destSchemaField) {
          if (dest.equals(dynamicField.getRegex())) {
            destDynamicField = dynamicField;
            destSchemaField = dynamicField.prototype;
          } else if (dynamicField.matches(dest)) {
            destSchemaField = dynamicField.makeSchemaField(dest);
            destDynamicField = new DynamicField(destSchemaField);
            destDynamicBase = dynamicField;
          }
        }
        if (null != destSchemaField
            && (null != sourceSchemaField || sourceIsDynamicFieldReference || sourceIsExplicitFieldGlob)) {
          break;
        }
      }
    }
    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 (sourceIsGlob) {
      if (null != destDynamicField) { // source: glob ; dest: dynamic field ref
        registerDynamicCopyField(new DynamicCopy(source, destDynamicField, maxChars, sourceDynamicBase, destDynamicBase));
        incrementCopyFieldTargetCount(destSchemaField);
      } else {                        // source: glob ; dest: explicit field
        destDynamicField = new DynamicField(destSchemaField);
        registerDynamicCopyField(new DynamicCopy(source, destDynamicField, maxChars, sourceDynamicBase, null));
        incrementCopyFieldTargetCount(destSchemaField);
      }
    } else if (sourceIsDynamicFieldReference) {
      if (null != destDynamicField) {  // source: no-asterisk dynamic field ref ; dest: dynamic field ref
        registerDynamicCopyField(new DynamicCopy(source, destDynamicField, maxChars, sourceDynamicBase, destDynamicBase));
        incrementCopyFieldTargetCount(destSchemaField);
      } else {                        // source: no-asterisk dynamic field ref ; dest: explicit field
        sourceSchemaField = getField(source);
        registerExplicitSrcAndDestFields(source, maxChars, destSchemaField, sourceSchemaField);
      }
    } else {
      if (null != destDynamicField) { // source: explicit field ; dest: dynamic field reference
        if (destDynamicField.pattern instanceof DynamicReplacement.DynamicPattern.NameEquals) {
          // Dynamic dest with no asterisk is acceptable
          registerDynamicCopyField(new DynamicCopy(source, destDynamicField, maxChars, sourceDynamicBase, destDynamicBase));
          incrementCopyFieldTargetCount(destSchemaField);
        } else {                    // source: explicit field ; dest: dynamic field with an asterisk
          String msg = "copyField only supports a dynamic destination with an asterisk "
              + "if the source also has an asterisk";
          throw new SolrException(ErrorCode.SERVER_ERROR, msg);
        }
      } else {                        // source & dest: explicit fields
        registerExplicitSrcAndDestFields(source, maxChars, destSchemaField, sourceSchemaField);
      }
    }
  }

  protected void registerExplicitSrcAndDestFields(String source, int maxChars, SchemaField destSchemaField, SchemaField sourceSchemaField) {
    List<CopyField> copyFieldList = copyFieldsMap.get(source);
    if (copyFieldList == null) {
      copyFieldList = new ArrayList<>();
      copyFieldsMap.put(source, copyFieldList);
    }
    copyFieldList.add(new CopyField(sourceSchemaField, destSchemaField, maxChars));
    incrementCopyFieldTargetCount(destSchemaField);
  }

  private void incrementCopyFieldTargetCount(SchemaField dest) {
    copyFieldTargetCounts.put(dest, copyFieldTargetCounts.containsKey(dest) ? copyFieldTargetCounts.get(dest) + 1 : 1);
  }

  private void registerDynamicCopyField(DynamicCopy dcopy) {
    DynamicCopy[] temp = new DynamicCopy[dynamicCopyFields.length + 1];
    System.arraycopy(dynamicCopyFields, 0, temp, 0, dynamicCopyFields.length);
    temp[temp.length - 1] = dcopy;
    dynamicCopyFields = temp;
  }

  static SimilarityFactory readSimilarity(SolrClassLoader loader, ConfigNode node) {
    if (node==null) {
      return null;
    } else {
      SimilarityFactory similarityFactory;
      final String classArg = node.attributes().get(SimilarityFactory.CLASS_NAME);
      final Object obj = loader.newInstance(classArg, Object.class, "search.similarities.");
      if (obj instanceof SimilarityFactory) {
        // configure a factory, get a similarity back
        final NamedList<Object> namedList = DOMUtil.childNodesToNamedList(node);
        namedList.add(SimilarityFactory.CLASS_NAME, classArg);
        SolrParams params = namedList.toSolrParams();
        similarityFactory = (SimilarityFactory)obj;
        similarityFactory.init(params);
      } else {
        // just like always, assume it's a Similarity and get a ClassCastException - reasonable error handling
        similarityFactory = new SimilarityFactory() {
          @Override
          public Similarity getSimilarity() {
            return (Similarity) obj;
          }
        };
      }
      return similarityFactory;
    }
  }


  public static abstract class DynamicReplacement implements Comparable<DynamicReplacement> {
    abstract protected static class DynamicPattern {
      protected final String regex;
      protected final String fixedStr;

      protected DynamicPattern(String regex, String fixedStr) { this.regex = regex; this.fixedStr = fixedStr; }

      static DynamicPattern createPattern(String regex) {
        if (regex.startsWith("*")) { return new NameEndsWith(regex); }
        else if (regex.endsWith("*")) { return new NameStartsWith(regex); }
        else { return new NameEquals(regex);
        }
      }

      /** Returns true if the given name matches this pattern */
      abstract boolean matches(String name);

      /** Returns the remainder of the given name after removing this pattern's fixed string component */
      abstract String remainder(String name);

      /** Returns the result of combining this pattern's fixed string component with the given replacement */
      abstract String subst(String replacement);

      /** Returns the length of the original regex, including the asterisk, if any. */
      public int length() { return regex.length(); }

      private static class NameStartsWith extends DynamicPattern {
        NameStartsWith(String regex) { super(regex, regex.substring(0, regex.length() - 1)); }
        boolean matches(String name) { return name.startsWith(fixedStr); }
        String remainder(String name) { return name.substring(fixedStr.length()); }
        String subst(String replacement) { return fixedStr + replacement; }
      }
      private static class NameEndsWith extends DynamicPattern {
        NameEndsWith(String regex) { super(regex, regex.substring(1)); }
        boolean matches(String name) { return name.endsWith(fixedStr); }
        String remainder(String name) { return name.substring(0, name.length() - fixedStr.length()); }
        String subst(String replacement) { return replacement + fixedStr; }
      }
      private static class NameEquals extends DynamicPattern {
        NameEquals(String regex) { super(regex, regex); }
        boolean matches(String name) { return regex.equals(name); }
        String remainder(String name) { return ""; }
        String subst(String replacement) { return fixedStr; }
      }
    }

    protected DynamicPattern pattern;

    public boolean matches(String name) { return pattern.matches(name); }

    protected DynamicReplacement(String regex) {
      pattern = DynamicPattern.createPattern(regex);
    }

    /**
     * Sort order is based on length of regex.  Longest comes first.
     * @param other The object to compare to.
     * @return a negative integer, zero, or a positive integer
     * as this object is less than, equal to, or greater than
     * the specified object.
     */
    @Override
    public int compareTo(DynamicReplacement other) {
      return other.pattern.length() - pattern.length();
    }

    /** Returns the regex used to create this instance's pattern */
    public String getRegex() {
      return pattern.regex;
    }
  }


  public final static class DynamicField extends DynamicReplacement {
    private final SchemaField prototype;
    public SchemaField getPrototype() { return prototype; }

    DynamicField(SchemaField prototype) {
      super(prototype.name);
      this.prototype=prototype;
    }

    SchemaField makeSchemaField(String name) {
      // could have a cache instead of returning a new one each time, but it might
      // not be worth it.
      // Actually, a higher level cache could be worth it to avoid too many
      // .startsWith() and .endsWith() comparisons.  it depends on how many
      // dynamic fields there are.
      return new SchemaField(prototype, name);
    }

    @Override
    public String toString() {
      return prototype.toString();
    }
  }

  public static class DynamicCopy extends DynamicReplacement {
    private final DynamicField destination;

    private final int maxChars;
    public int getMaxChars() { return maxChars; }

    final DynamicField sourceDynamicBase;
    public DynamicField getSourceDynamicBase() { return sourceDynamicBase; }

    final DynamicField destDynamicBase;
    public DynamicField getDestDynamicBase() { return destDynamicBase; }

    DynamicCopy(String sourceRegex, DynamicField destination, int maxChars,
                DynamicField sourceDynamicBase, DynamicField destDynamicBase) {
      super(sourceRegex);
      this.destination = destination;
      this.maxChars = maxChars;
      this.sourceDynamicBase = sourceDynamicBase;
      this.destDynamicBase = destDynamicBase;
    }

    public DynamicField getDestination() { return destination; }

    public String getDestFieldName() { return destination.getRegex(); }

    /**
     *  Generates a destination field name based on this source pattern,
     *  by substituting the remainder of this source pattern into the
     *  the given destination pattern.
     */
    public SchemaField getTargetField(String sourceField) {
      String remainder = pattern.remainder(sourceField);
      String targetFieldName = destination.pattern.subst(remainder);
      return destination.makeSchemaField(targetFieldName);
    }


    @Override
    public String toString() {
      return destination.prototype.toString();
    }
  }

  public SchemaField[] getDynamicFieldPrototypes() {
    SchemaField[] df = new SchemaField[dynamicFields.length];
    for (int i=0;i<dynamicFields.length;i++) {
      df[i] = dynamicFields[i].prototype;
    }
    return df;
  }

  public String getDynamicPattern(String fieldName) {
    for (DynamicField df : dynamicFields) {
      if (df.matches(fieldName)) return df.getRegex();
    }
    return  null;
  }

  /**
   * Does the schema explicitly define the specified field, i.e. not as a result
   * of a copyField declaration?  We consider it explicitly defined if it matches
   * a field name or a dynamicField name.
   * @return true if explicitly declared in the schema.
   */
  public boolean hasExplicitField(String fieldName) {
    if (fields.containsKey(fieldName)) {
      return true;
    }

    for (DynamicField df : dynamicFields) {
      if (fieldName.equals(df.getRegex())) return true;
    }

    return false;
  }

  /**
   * Is the specified field dynamic or not.
   * @return true if the specified field is dynamic
   */
  public boolean isDynamicField(String fieldName) {
    if(fields.containsKey(fieldName)) {
      return false;
    }

    for (DynamicField df : dynamicFields) {
      if (df.matches(fieldName)) return true;
    }

    return false;
  }

  /**
   * Returns the SchemaField that should be used for the specified field name, or
   * null if none exists.
   *
   * @param fieldName may be an explicitly defined field or a name that
   * matches a dynamic field.
   * @see #getFieldType
   * @see #getField(String)
   * @return The {@link org.apache.solr.schema.SchemaField}
   */
  public SchemaField getFieldOrNull(String fieldName) {
    SchemaField f = fields.get(fieldName);
    if (f != null) return f;
    f = dynamicFieldCache.get(fieldName);
    if (f != null) return f;

    for (DynamicField df : dynamicFields) {
      if (df.matches(fieldName)) {
        dynamicFieldCache.put(fieldName, f = df.makeSchemaField(fieldName));
        break;
      }
    }

    return f;
  }

  /**
   * Returns the SchemaField that should be used for the specified field name
   *
   * @param fieldName may be an explicitly defined field or a name that
   * matches a dynamic field.
   * @throws SolrException if no such field exists
   * @see #getFieldType
   * @see #getFieldOrNull(String)
   * @return The {@link SchemaField}
   */
  public SchemaField getField(String fieldName) {
    SchemaField f = getFieldOrNull(fieldName);
    if (f != null) return f;


    // Hmmm, default field could also be implemented with a dynamic field of "*".
    // It would have to be special-cased and only used if nothing else matched.
    /***  REMOVED -YCS
     if (defaultFieldType != null) return new SchemaField(fieldName,defaultFieldType);
     ***/
    throw new SolrException(ErrorCode.BAD_REQUEST,"undefined field: \""+fieldName+"\"");
  }

  /**
   * Returns the FieldType for the specified field name.
   *
   * <p>
   * This method exists because it can be more efficient then
   * {@link #getField} for dynamic fields if a full SchemaField isn't needed.
   * </p>
   *
   * @param fieldName may be an explicitly created field, or a name that
   *  excercises a dynamic field.
   * @throws SolrException if no such field exists
   * @see #getField(String)
   * @see #getFieldTypeNoEx
   */
  public FieldType getFieldType(String fieldName) {
    SchemaField f = fields.get(fieldName);
    if (f != null) return f.getType();

    return getDynamicFieldType(fieldName);
  }

  /**
   * Given the name of a {@link org.apache.solr.schema.FieldType} (not to be confused with {@link #getFieldType(String)} which
   * takes in the name of a field), return the {@link org.apache.solr.schema.FieldType}.
   * @param fieldTypeName The name of the {@link org.apache.solr.schema.FieldType}
   * @return The {@link org.apache.solr.schema.FieldType} or null.
   */
  public FieldType getFieldTypeByName(String fieldTypeName){
    return fieldTypes.get(fieldTypeName);
  }

  /**
   * Returns the FieldType for the specified field name.
   *
   * <p>
   * This method exists because it can be more efficient then
   * {@link #getField} for dynamic fields if a full SchemaField isn't needed.
   * </p>
   *
   * @param fieldName may be an explicitly created field, or a name that
   * exercises a dynamic field.
   * @return null if field is not defined.
   * @see #getField(String)
   * @see #getFieldTypeNoEx
   */
  public FieldType getFieldTypeNoEx(String fieldName) {
    SchemaField f = fields.get(fieldName);
    if (f != null) return f.getType();
    return dynFieldType(fieldName);
  }


  /**
   * Returns the FieldType of the best matching dynamic field for
   * the specified field name
   *
   * @param fieldName may be an explicitly created field, or a name that
   * exercises a dynamic field.
   * @throws SolrException if no such field exists
   * @see #getField(String)
   * @see #getFieldTypeNoEx
   */
  public FieldType getDynamicFieldType(String fieldName) {
    for (DynamicField df : dynamicFields) {
      if (df.matches(fieldName)) return df.prototype.getType();
    }
    throw new SolrException(ErrorCode.BAD_REQUEST,"undefined field "+fieldName);
  }

  private FieldType dynFieldType(String fieldName) {
    for (DynamicField df : dynamicFields) {
      if (df.matches(fieldName)) return df.prototype.getType();
    }
    return null;
  }


  /**
   * Get all copy fields, both the static and the dynamic ones.
   * @return Array of fields copied into this field
   */

  public List<String> getCopySources(String destField) {
    SchemaField f = getField(destField);
    if (!isCopyFieldTarget(f)) {
      return Collections.emptyList();
    }
    List<String> fieldNames = new ArrayList<>();
    for (Map.Entry<String, List<CopyField>> cfs : copyFieldsMap.entrySet()) {
      for (CopyField copyField : cfs.getValue()) {
        if (copyField.getDestination().getName().equals(destField)) {
          fieldNames.add(copyField.getSource().getName());
        }
      }
    }
    for (DynamicCopy dynamicCopy : dynamicCopyFields) {
      if (dynamicCopy.getDestFieldName().equals(destField)) {
        fieldNames.add(dynamicCopy.getRegex());
      }
    }
    return fieldNames;
  }

  /**
   * Get all copy fields for a specified source field, both static
   * and dynamic ones.
   * @return List of CopyFields to copy to.
   * @since solr 1.4
   */
  // This is useful when we need the maxSize param of each CopyField
  public List<CopyField> getCopyFieldsList(final String sourceField){
    final List<CopyField> result = new ArrayList<>();
    for (DynamicCopy dynamicCopy : dynamicCopyFields) {
      if (dynamicCopy.matches(sourceField)) {
        result.add(new CopyField(getField(sourceField), dynamicCopy.getTargetField(sourceField), dynamicCopy.maxChars));
      }
    }
    List<CopyField> fixedCopyFields = copyFieldsMap.get(sourceField);
    if (null != fixedCopyFields) {
      result.addAll(fixedCopyFields);
    }

    return result;
  }

  /**
   * Check if a field is used as the destination of a copyField operation
   *
   * @since solr 1.3
   */
  public boolean isCopyFieldTarget( SchemaField f ) {
    return copyFieldTargetCounts.containsKey( f );
  }

  /**
   * Get a map of property name -&gt; value for the whole schema.
   */
  @SuppressWarnings({"unchecked", "rawtypes"})
  public Map getNamedPropertyValues() {
    return getNamedPropertyValues(null, new MapSolrParams(Collections.EMPTY_MAP));
  }

  public static class SchemaProps implements MapSerializable {
    private static final String SOURCE_FIELD_LIST = IndexSchema.SOURCE + "." + CommonParams.FL;
    private static final String DESTINATION_FIELD_LIST = IndexSchema.DESTINATION + "." + CommonParams.FL;
    public final String name;
    private final SolrParams params;
    private final IndexSchema schema;
    boolean showDefaults, includeDynamic;
    Set<String> requestedFields;
    private Set<String> requestedSourceFields;
    private Set<String> requestedDestinationFields;


    public enum Handler {
      NAME(IndexSchema.NAME, sp -> sp.schema.getSchemaName()),
      VERSION(IndexSchema.VERSION, sp -> sp.schema.getVersion()),
      UNIQUE_KEY(IndexSchema.UNIQUE_KEY, sp -> sp.schema.uniqueKeyFieldName),
      SIMILARITY(IndexSchema.SIMILARITY, sp -> sp.schema.isExplicitSimilarity ?
          sp.schema.similarityFactory.getNamedPropertyValues() :
          null),
      FIELD_TYPES(IndexSchema.FIELD_TYPES, sp -> new TreeMap<>(sp.schema.fieldTypes)
          .values().stream()
          .map(it -> it.getNamedPropertyValues(sp.showDefaults))
          .collect(Collectors.toList())),

      @SuppressWarnings({"unchecked", "rawtypes"})
      FIELDS(IndexSchema.FIELDS, sp -> {
        List<SimpleOrderedMap> result = (sp.requestedFields != null ? sp.requestedFields : new TreeSet<>(sp.schema.fields.keySet()))
            .stream()
            .map(sp.schema::getFieldOrNull)
            .filter(it -> it != null)
            .filter(it -> sp.includeDynamic || !sp.schema.isDynamicField(it.name))
            .map(sp::getProperties)
            .collect(Collectors.toList());
        if (sp.includeDynamic && sp.requestedFields == null) {
          result.addAll(sp.applyDynamic());
        }
        return result;
      }),
      DYNAMIC_FIELDS(IndexSchema.DYNAMIC_FIELDS, sp -> Stream.of(sp.schema.dynamicFields)
          .filter(it -> !it.getRegex().startsWith(INTERNAL_POLY_FIELD_PREFIX))
          .filter(it -> sp.requestedFields == null || sp.requestedFields.contains(it.getPrototype().getName()))
          .map(it -> sp.getProperties(it.getPrototype()))
          .collect(Collectors.toList())),


      COPY_FIELDS(IndexSchema.COPY_FIELDS, sp -> sp.schema.getCopyFieldProperties(false,
          sp.requestedSourceFields, sp.requestedDestinationFields));

      final Function<SchemaProps, Object> fun;
      public final String realName, nameLower;
      Handler(String name, Function<SchemaProps, Object> fun) {
        this.fun = fun;
        this.realName = name;
        nameLower = name.toLowerCase(Locale.ROOT);

      }
      public String getRealName(){
        return realName;
      }
      public String getNameLower(){
        return nameLower;

      }
    }


    SchemaProps(String name, SolrParams params, IndexSchema schema) {
      this.name = name;
      this.params = params;
      this.schema = schema;
      showDefaults = params.getBool("showDefaults", false);
      includeDynamic = params.getBool("includeDynamic", false);
      requestedSourceFields = readMultiVals(SOURCE_FIELD_LIST);
      requestedDestinationFields = readMultiVals(DESTINATION_FIELD_LIST);
      requestedFields = readMultiVals(CommonParams.FL);

    }
    @SuppressWarnings({"rawtypes"})
    public Collection applyDynamic(){
      return (Collection) Handler.DYNAMIC_FIELDS.fun.apply(this);
    }

    private Set<String> readMultiVals(String name) {
      String flParam = params.get(name);
      if (null != flParam) {
        String[] fields = flParam.trim().split("[,\\s]+");
        if (fields.length > 0)
          return new LinkedHashSet<>(Stream.of(fields)
              .filter(it -> !it.trim().isEmpty())
              .collect(Collectors.toList()));

      }

      return null;
    }


    @SuppressWarnings({"rawtypes"})
    SimpleOrderedMap getProperties(SchemaField sf) {
      SimpleOrderedMap<Object> result = sf.getNamedPropertyValues(showDefaults);
      if (schema.isDynamicField(sf.name)) {
        String dynamicBase = schema.getDynamicPattern(sf.getName());
        // Add dynamicBase property if it's different from the field name.
        if (!sf.getName().equals(dynamicBase)) {
          result.add("dynamicBase", dynamicBase);
        }
      }
      return result;
    }


    @Override
    public Map<String, Object> toMap(Map<String, Object> map) {
      return Stream.of(Handler.values())
          .filter(it -> name == null || it.nameLower.equals(name))
          .map(it -> new Pair<>(it.realName, it.fun.apply(this)))
          .filter(it->it.second() != null)
          .collect(Collectors.toMap(
              Pair::first,
              Pair::second,
              (v1, v2) -> v2,
              LinkedHashMap::new));
    }
  }

  public static Map<String,String> nameMapping = Collections.unmodifiableMap(Stream.of(SchemaProps.Handler.values())
      .collect(Collectors.toMap(SchemaProps.Handler::getNameLower , SchemaProps.Handler::getRealName)));


  public Map<String, Object> getNamedPropertyValues(String name, SolrParams params) {
    return new SchemaProps(name, params, this).toMap(new LinkedHashMap<>());

  }


  /**
   * 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<>();
    SortedMap<String,List<CopyField>> sortedCopyFields = new TreeMap<>(copyFieldsMap);
    for (List<CopyField> copyFields : sortedCopyFields.values()) {
      copyFields = new ArrayList<>(copyFields);
      Collections.sort(copyFields, (cf1, cf2) -> {
        // sources are all 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<>();
          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<>();

        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<>();
            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;
  }

  /**
   * Copies this schema, adds the given field to the copy
   * Requires synchronizing on the object returned by
   * {@link #getSchemaUpdateLock()}.
   *
   * @param newField the SchemaField to add
   * @param persist to persist the schema or not
   * @return a new IndexSchema based on this schema with newField added
   * @see #newField(String, String, Map)
   */
  public IndexSchema addField(SchemaField newField, boolean persist) {
    return addFields(Collections.singletonList(newField), Collections.emptyMap(), persist);
  }

  public IndexSchema addField(SchemaField newField) {
    return addField(newField, true);
  }

  /**
   * Copies this schema, adds the given field to the copy
   *  Requires synchronizing on the object returned by
   * {@link #getSchemaUpdateLock()}.
   *
   * @param newField the SchemaField to add
   * @param copyFieldNames 0 or more names of targets to copy this field to.  The targets must already exist.
   * @return a new IndexSchema based on this schema with newField added
   * @see #newField(String, String, Map)
   */
  public IndexSchema addField(SchemaField newField, Collection<String> copyFieldNames) {
    return addFields(singletonList(newField), singletonMap(newField.getName(), copyFieldNames), true);
  }

  /**
   * Copies this schema, adds the given fields to the copy.
   * Requires synchronizing on the object returned by
   * {@link #getSchemaUpdateLock()}.
   *
   * @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) {
    return addFields(newFields, Collections.<String, Collection<String>>emptyMap(), true);
  }

  /**
   * Copies this schema, adds the given fields to the copy
   * Requires synchronizing on the object returned by
   * {@link #getSchemaUpdateLock()}.
   *
   * @param newFields the SchemaFields to add
   * @param copyFieldNames 0 or more names of targets to copy this field to.  The target fields must already exist.
   * @param persist Persist the schema or not
   * @return a new IndexSchema based on this schema with newFields added
   * @see #newField(String, String, Map)
   */
  public IndexSchema addFields(Collection<SchemaField> newFields, Map<String, Collection<String>> copyFieldNames, boolean persist) {
    String msg = "This IndexSchema is not mutable.";
    log.error(msg);
    throw new SolrException(ErrorCode.SERVER_ERROR, msg);
  }


  /**
   * Copies this schema, deletes the named fields from the copy.
   * <p>
   * The schema will not be persisted.
   * <p>
   * Requires synchronizing on the object returned by
   * {@link #getSchemaUpdateLock()}.
   *
   * @param names the names of the fields to delete
   * @return a new IndexSchema based on this schema with the named fields deleted
   */
  public IndexSchema deleteFields(Collection<String> names) {
    String msg = "This IndexSchema is not mutable.";
    log.error(msg);
    throw new SolrException(ErrorCode.SERVER_ERROR, msg);
  }

  /**
   * Copies this schema, deletes the named field from the copy, creates a new field
   * with the same name using the given args, then rebinds any referring copy fields
   * to the replacement field.
   *
   * <p>
   * The schema will not be persisted.
   * <p>
   * Requires synchronizing on the object returned by {@link #getSchemaUpdateLock()}.
   *
   * @param fieldName The name of the field to be replaced
   * @param replacementFieldType  The field type of the replacement field
   * @param replacementArgs Initialization params for the replacement field
   * @return a new IndexSchema based on this schema with the named field replaced
   */
  public IndexSchema replaceField(String fieldName, FieldType replacementFieldType, Map<String,?> replacementArgs) {
    String msg = "This IndexSchema is not mutable.";
    log.error(msg);
    throw new SolrException(ErrorCode.SERVER_ERROR, msg);
  }

  /**
   * Copies this schema, adds the given dynamic fields to the copy,
   * Requires synchronizing on the object returned by
   * {@link #getSchemaUpdateLock()}.
   *
   * @param newDynamicFields the SchemaFields to add
   * @param copyFieldNames 0 or more names of targets to copy this field to.  The target fields must already exist.
   * @param persist to persist the schema or not
   * @return a new IndexSchema based on this schema with newDynamicFields added
   * @see #newDynamicField(String, String, Map)
   */
  public IndexSchema addDynamicFields
  (Collection<SchemaField> newDynamicFields,
   Map<String, Collection<String>> copyFieldNames,
   boolean persist) {
    String msg = "This IndexSchema is not mutable.";
    log.error(msg);
    throw new SolrException(ErrorCode.SERVER_ERROR, msg);
  }

  /**
   * Copies this schema, deletes the named dynamic fields from the copy.
   * <p>
   * The schema will not be persisted.
   * <p>
   * Requires synchronizing on the object returned by
   * {@link #getSchemaUpdateLock()}.
   *
   * @param fieldNamePatterns the names of the dynamic fields to delete
   * @return a new IndexSchema based on this schema with the named dynamic fields deleted
   */
  public IndexSchema deleteDynamicFields(Collection<String> fieldNamePatterns) {
    String msg = "This IndexSchema is not mutable.";
    log.error(msg);
    throw new SolrException(ErrorCode.SERVER_ERROR, msg);
  }

  /**
   * Copies this schema, deletes the named dynamic field from the copy, creates a new dynamic
   * field with the same field name pattern using the given args, then rebinds any referring
   * dynamic copy fields to the replacement dynamic field.
   *
   * <p>
   * The schema will not be persisted.
   * <p>
   * Requires synchronizing on the object returned by {@link #getSchemaUpdateLock()}.
   *
   * @param fieldNamePattern The glob for the dynamic field to be replaced
   * @param replacementFieldType  The field type of the replacement dynamic field
   * @param replacementArgs Initialization params for the replacement dynamic field
   * @return a new IndexSchema based on this schema with the named dynamic field replaced
   */
  public ManagedIndexSchema replaceDynamicField
  (String fieldNamePattern, FieldType replacementFieldType, Map<String,?> replacementArgs) {
    String msg = "This IndexSchema is not mutable.";
    log.error(msg);
    throw new SolrException(ErrorCode.SERVER_ERROR, msg);
  }

  /**
   * Copies this schema and adds the new copy fields to the copy
   * Requires synchronizing on the object returned by
   * {@link #getSchemaUpdateLock()}.
   *
   * @see #addCopyFields(String,Collection,int) to limit the number of copied characters.
   *
   * @param copyFields Key is the name of the source field name, value is a collection of target field names.  Fields must exist.
   * @param persist to persist the schema or not
   * @return The new Schema with the copy fields added
   */
  public IndexSchema addCopyFields(Map<String, Collection<String>> copyFields, boolean persist) {
    String msg = "This IndexSchema is not mutable.";
    log.error(msg);
    throw new SolrException(ErrorCode.SERVER_ERROR, msg);
  }

  /**
   * Copies this schema and adds the new copy fields to the copy.
   *
   * Requires synchronizing on the object returned by
   * {@link #getSchemaUpdateLock()}
   *
   * @param source source field name
   * @param destinations collection of target field names
   * @param maxChars max number of characters to copy from the source to each
   *                 of the destinations.  Use {@link CopyField#UNLIMITED}
   *                 if you don't want to limit the number of copied chars.
   * @return The new Schema with the copy fields added
   */
  public IndexSchema addCopyFields(String source, Collection<String> destinations, int maxChars) {
    String msg = "This IndexSchema is not mutable.";
    log.error(msg);
    throw new SolrException(ErrorCode.SERVER_ERROR, msg);
  }

  /**
   * Copies this schema and deletes the given copy fields from the copy.
   * <p>
   * The schema will not be persisted.
   * <p>
   * Requires synchronizing on the object returned by
   * {@link #getSchemaUpdateLock()}.
   *
   * @param copyFields Key is the name of the source field name, value is a collection of target field names.
   *                   Each corresponding copy field directives must exist.
   * @return The new Schema with the copy fields deleted
   */
  public IndexSchema deleteCopyFields(Map<String, Collection<String>> copyFields) {
    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);
  }

  /**
   * Returns a SchemaField if the given dynamic field glob 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 fieldNamePattern the pattern for the dynamic 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 newDynamicField(String fieldNamePattern, String fieldType, Map<String,?> options) {
    String msg = "This IndexSchema is not mutable.";
    log.error(msg);
    throw new SolrException(ErrorCode.SERVER_ERROR, msg);
  }

  /**
   * Returns the schema update lock that should be synchronized on
   * to update the schema.  Only applicable to mutable schemas.
   *
   * @return the schema update lock object to synchronize on
   */
  public Object getSchemaUpdateLock() {
    String msg = "This IndexSchema is not mutable.";
    log.error(msg);
    throw new SolrException(ErrorCode.SERVER_ERROR, msg);
  }

  /**
   * Copies this schema, adds the given field type to the copy,
   * Requires synchronizing on the object returned by
   * {@link #getSchemaUpdateLock()}.
   *
   * @param fieldTypeList a list of FieldTypes to add
   * @param persist to persist the schema or not
   * @return a new IndexSchema based on this schema with the new types added
   * @see #newFieldType(String, String, Map)
   */
  public IndexSchema addFieldTypes(List<FieldType> fieldTypeList, boolean persist) {
    String msg = "This IndexSchema is not mutable.";
    log.error(msg);
    throw new SolrException(ErrorCode.SERVER_ERROR, msg);
  }

  /**
   * Copies this schema, deletes the named field types from the copy.
   * <p>
   * The schema will not be persisted.
   * <p>
   * Requires synchronizing on the object returned by {@link #getSchemaUpdateLock()}.
   *
   * @param names the names of the field types to delete
   * @return a new IndexSchema based on this schema with the named field types deleted
   */
  public IndexSchema deleteFieldTypes(Collection<String> names) {
    String msg = "This IndexSchema is not mutable.";
    log.error(msg);
    throw new SolrException(ErrorCode.SERVER_ERROR, msg);
  }

  /**
   * Copies this schema, deletes the named field type from the copy, creates a new field type
   * with the same name using the given args, rebuilds fields and dynamic fields of the given
   * type, then rebinds any referring copy fields to the rebuilt fields.
   *
   * <p>
   * The schema will not be persisted.
   * <p>
   * Requires synchronizing on the object returned by {@link #getSchemaUpdateLock()}.
   *
   * @param typeName The name of the field type to be replaced
   * @param replacementClassName The class name of the replacement field type
   * @param replacementArgs Initialization params for the replacement field type
   * @return a new IndexSchema based on this schema with the named field type replaced
   */
  public IndexSchema replaceFieldType(String typeName, String replacementClassName, Map<String,Object> replacementArgs) {
    String msg = "This IndexSchema is not mutable.";
    log.error(msg);
    throw new SolrException(ErrorCode.SERVER_ERROR, msg);
  }

  /**
   * Returns a FieldType if the given typeName does not already
   * exist in this schema. The resulting FieldType can be used in a call
   * to {@link #addFieldTypes(java.util.List, boolean)}.
   *
   * @param typeName the name of the type to add
   * @param className the name of the FieldType class
   * @param options the options to use when creating the FieldType
   * @return The created FieldType
   * @see #addFieldTypes(java.util.List, boolean)
   */
  public FieldType newFieldType(String typeName, String className, Map<String,?> options) {
    String msg = "This IndexSchema is not mutable.";
    log.error(msg);
    throw new SolrException(ErrorCode.SERVER_ERROR, msg);
  }


  /**
   * Helper method that returns <code>true</code> if the {@link #ROOT_FIELD_NAME} uses the exact
   * same 'type' as the {@link #getUniqueKeyField()}
   *
   * @lucene.internal
   */
  public boolean isUsableForChildDocs() {
    //TODO make this boolean a field so it needn't be looked up each time?
    FieldType rootType = getFieldTypeNoEx(ROOT_FIELD_NAME);
    return (null != uniqueKeyFieldType &&
        null != rootType &&
        rootType.getTypeName().equals(uniqueKeyFieldType.getTypeName()));
  }

  public PayloadDecoder getPayloadDecoder(String field) {
    FieldType ft = getFieldType(field);
    if (ft == null)
      return null;
    return decoders.computeIfAbsent(ft, f -> PayloadUtils.getPayloadDecoder(ft));
  }

}
