/**
   * Create a new instance configured with the provided FieldType options. See {@link
   * #DEFAULT_FIELDTYPE}. a field type is used to articulate the desired options (namely
   * pointValues, docValues, stored). Legacy numerics is configurable this way too.
   */
  public PointVectorStrategy(SpatialContext ctx, String fieldNamePrefix, FieldType fieldType) {
    super(ctx, fieldNamePrefix);
    this.fieldNameX = fieldNamePrefix + SUFFIX_X;
    this.fieldNameY = fieldNamePrefix + SUFFIX_Y;

    int numPairs = 0;
    if ((this.hasStored = fieldType.stored())) {
      numPairs++;
    }
    if ((this.hasDocVals = fieldType.docValuesType() != DocValuesType.NONE)) {
      numPairs++;
    }
    if ((this.hasPointVals = fieldType.pointDimensionCount() > 0)) {
      numPairs++;
    }
    if (fieldType.indexOptions() != IndexOptions.NONE && fieldType.numericType() != null) {
      if (hasPointVals) {
        throw new IllegalArgumentException(
            "pointValues and LegacyNumericType are mutually exclusive");
      }
      if (fieldType.numericType() != FieldType.LegacyNumericType.DOUBLE) {
        throw new IllegalArgumentException(
            getClass() + " does not support " + fieldType.numericType());
      }
      numPairs++;
      legacyNumericFieldType = new FieldType(LegacyDoubleField.TYPE_NOT_STORED);
      legacyNumericFieldType.setNumericPrecisionStep(fieldType.numericPrecisionStep());
      legacyNumericFieldType.freeze();
    } else {
      legacyNumericFieldType = null;
    }
    this.fieldsLen = numPairs * 2;
  }
 /** Create a new mutable FieldType with all of the properties from <code>ref</code> */
 public FieldType(FieldType ref) {
   this.indexed = ref.indexed();
   this.stored = ref.stored();
   this.tokenized = ref.tokenized();
   this.storeTermVectors = ref.storeTermVectors();
   this.storeTermVectorOffsets = ref.storeTermVectorOffsets();
   this.storeTermVectorPositions = ref.storeTermVectorPositions();
   this.storeTermVectorPayloads = ref.storeTermVectorPayloads();
   this.omitNorms = ref.omitNorms();
   this.indexOptions = ref.indexOptions();
   this.docValueType = ref.docValueType();
   this.numericType = ref.numericType();
   // Do not copy frozen!
 }
 /**
  * Create field with String value.
  *
  * @param name field name
  * @param value string value
  * @param type field type
  * @throws IllegalArgumentException if either the name or value is null, or if the field's type is
  *     neither indexed() nor stored(), or if indexed() is false but storeTermVectors() is true.
  * @throws NullPointerException if the type is null
  */
 public Field(String name, String value, FieldType type) {
   if (name == null) {
     throw new IllegalArgumentException("name cannot be null");
   }
   if (value == null) {
     throw new IllegalArgumentException("value cannot be null");
   }
   if (!type.stored() && !type.indexed()) {
     throw new IllegalArgumentException(
         "it doesn't make sense to have a field that " + "is neither indexed nor stored");
   }
   this.type = type;
   this.name = name;
   this.fieldsData = value;
 }
  /**
   * Create field with TokenStream value.
   *
   * @param name field name
   * @param tokenStream TokenStream value
   * @param type field type
   * @throws IllegalArgumentException if either the name or type is null, or if the field's type is
   *     stored(), or if tokenized() is false, or if indexed() is false.
   * @throws NullPointerException if the tokenStream is null
   */
  public Field(String name, TokenStream tokenStream, FieldType type) {
    if (name == null) {
      throw new IllegalArgumentException("name cannot be null");
    }
    if (tokenStream == null) {
      throw new NullPointerException("tokenStream cannot be null");
    }
    if (!type.indexed() || !type.tokenized()) {
      throw new IllegalArgumentException("TokenStream fields must be indexed and tokenized");
    }
    if (type.stored()) {
      throw new IllegalArgumentException("TokenStream fields cannot be stored");
    }

    this.name = name;
    this.fieldsData = null;
    this.tokenStream = tokenStream;
    this.type = type;
  }
  /**
   * Create field with Reader value.
   *
   * @param name field name
   * @param reader reader value
   * @param type field type
   * @throws IllegalArgumentException if either the name or type is null, or if the field's type is
   *     stored(), or if tokenized() is false.
   * @throws NullPointerException if the reader is null
   */
  public Field(String name, Reader reader, FieldType type) {
    if (name == null) {
      throw new IllegalArgumentException("name cannot be null");
    }
    if (type == null) {
      throw new IllegalArgumentException("type cannot be null");
    }
    if (reader == null) {
      throw new NullPointerException("reader cannot be null");
    }
    if (type.stored()) {
      throw new IllegalArgumentException("fields with a Reader value cannot be stored");
    }
    if (type.indexed() && !type.tokenized()) {
      throw new IllegalArgumentException("non-tokenized fields must use String values");
    }

    this.name = name;
    this.fieldsData = reader;
    this.type = type;
  }