/**
 * 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 com.datatorrent.lib.appdata.schemas;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.apex.malhar.lib.dimensions.aggregator.AggregatorRegistry;
import org.apache.apex.malhar.lib.dimensions.aggregator.IncrementalAggregator;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * The {@link DimensionalSchema} class represents the App Data dimensions schema. The App Data dimensions
 * schema is built from two sources: a {@link DimensionalConfigurationSchema} and an optional schema stub. The
 * {@link DimensionalConfigurationSchema} is responsible for defining the key, values, dimensions combinations,
 * and the aggregations performed for each dimensions combination. The schema stub defines the from and to
 * times for the App Data dimensions schema. For details on how to define the {@link DimensionalConfigurationSchema}
 * schema please the documentation for the {@link DimensionalConfigurationSchema} class. An example of a valid
 * schema stub which defines the from and to times is below:
 * <br/>
 * <br/>
 * {@code
 * {
 * "time":
 * {
 * "from":1123455556656,
 * "to":382390859384
 * }
 * }
 *
 * @since 3.1.0
 */
public class DimensionalSchema implements Schema
{
  /**
   * The type of the schema.
   */
  public static final String SCHEMA_TYPE = "dimensions";
  /**
   * The version of the schema.
   */
  public static final String SCHEMA_VERSION = "1.0";
  /**
   * The JSON key string corresponding to the from field.
   */
  public static final String FIELD_TIME_FROM = "from";
  /**
   * The JSON key string corresponding to the time field.
   */
  public static final String FIELD_TIME = "time";
  /**
   * The JSON key string corresponding to the to field.
   */
  public static final String FIELD_TIME_TO = "to";
  /**
   * The JSON key string corresponding to the buckets field.
   */
  public static final String FIELD_TIME_BUCKETS = "buckets";
  /**
   * The JSON key string corresponding to the slidingAggregateSupported field.
   */
  public static final String FIELD_SLIDING_AGGREGATE_SUPPORTED = "slidingAggregateSupported";
  /**
   * The JSON key string used to identify the tags.
   */
  //TODO To be removed when Malhar Library 3.3 becomes a dependency.
  private static final String FIELD_TAGS = "tags";

  public static final List<Fields> VALID_KEYS = ImmutableList.of(new Fields(Sets.newHashSet(FIELD_TIME)));
  public static final List<Fields> VALID_TIME_KEYS = ImmutableList.of(
      new Fields(Sets.newHashSet(FIELD_TIME_FROM, FIELD_TIME_TO)));

  public static final String FIELD_RESPONSE_DELAY_MILLS = "responseDelayMillis";

  /**
   * The from value for the schema. Null if there is no from value.
   */
  private Long from;
  /**
   * The to value for the schema. Null if there is no to value.
   */
  private Long to;
  /**
   * boolean flag indicating if any values in the schema have been changed.
   */
  private boolean changed = false;
  /**
   * boolean flag indicating if the from to fields in the schema have been changed.
   */
  private boolean changedFromTo = false;
  /**
   * boolean flag indicating if the schema keys have been updated for the schema.
   */
  private boolean changedSchemaKeys = false;
  /**
   * boolean flag indicating if the enum vals are updated.
   */
  private boolean areEnumsUpdated = false;
  /**
   * The AppData schema JSON string (which is returned in the schema query).
   */
  private String schemaJSON;
  /**
   * The {@link DimensionalConfigurationSchema} from which this {@link DimensionalSchema} was constructed.
   */
  private DimensionalConfigurationSchema configurationSchema;
  /**
   * The {@link JSONObject} representing the AppData dimensions schema.
   */
  private JSONObject schema;
  /**
   * The {@link JSONObject} representing the time section of the AppData dimensions schema.
   */
  private JSONObject time;
  /**
   * The {@link JSONObject} representing the keys section of the AppData dimensions schema.
   */
  private JSONArray keys;
  /**
   * This flag is true if there was a from and to time defined for this schema initially.
   */
  private boolean predefinedFromTo = false;
  /**
   * The schema keys for this schema.
   */
  private Map<String, String> schemaKeys;
  /**
   * The current enum vals for this schema.
   */
  private Map<String, List<Object>> currentEnumVals;
  /**
   * The schemaID assigned to this schema. This schemaID is only needed for operators
   * which need to host multiple schemas.
   */
  private int schemaID = Schema.DEFAULT_SCHEMA_ID;

  protected long responseDelayMillis;

  /**
   * Constructor for serialization
   */
  private DimensionalSchema()
  {
    //For kryo
  }

  /**
   * This creates a {@link DimensionalSchema} object from the given schema stub,
   * configuration schema, and schema keys.
   *
   * @param schemaStub          The schema stub to use when creating this {@link DimensionalSchema}.
   * @param configurationSchema The configuration schema to use when creating this {@link DimensionalSchema}.
   * @param schemaKeys          The schemaKeys to use when creating this {@link DimensionalSchema}.
   */
  public DimensionalSchema(String schemaStub,
      DimensionalConfigurationSchema configurationSchema,
      Map<String, String> schemaKeys,
      long responseDelayMillis)
  {
    this(configurationSchema,
        schemaKeys, responseDelayMillis);

    if (schemaStub != null) {
      predefinedFromTo = true;
      try {
        setSchemaStub(schemaStub);
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
  }

  /**
   * This creates a {@link DimensionalSchema} object from the given schemaID, schemaStrub,configurationSchema, and
   * schemaKeys.
   *
   * @param schemaID            The schemaID assigned to this schema.
   * @param schemaStub          The schema stub to use when creating this {@link DimensionalSchema}.
   * @param configurationSchema The configuration schema to use when creating this {@link DimensionalSchema}.
   * @param schemaKeys          The schemaKeys to use when creating this {@link DimensionalSchema}.
   */
  public DimensionalSchema(int schemaID,
      String schemaStub,
      DimensionalConfigurationSchema configurationSchema,
      Map<String, String> schemaKeys)
  {
    this(schemaStub,
        configurationSchema,
        schemaKeys, 0);

    this.schemaID = schemaID;
  }

  /**
   * This creates a {@link DimensionalSchema} from the given schemaStub and configuration schema.
   *
   * @param schemaStub          The schema stub to use when creating this {@link DimensionalSchema}.
   * @param configurationSchema The configuration schema to use when creating this {@link DimensionalSchema}.
   */
  public DimensionalSchema(String schemaStub,
      DimensionalConfigurationSchema configurationSchema,
      long responseDelayMillis)
  {
    this(schemaStub,
        configurationSchema,
        null, responseDelayMillis);
  }

  /**
   * This creates a {@link DimensionalSchema} from the given schemaID, schemaStub, and
   * configurationSchema.
   *
   * @param schemaID            The schemaID assigned to this schema.
   * @param schemaStub          The schema stub to use when creating this {@link DimensionalSchema}.
   * @param configurationSchema The configuration schema to use when creating this {@link DimensionalSchema}.
   */
  public DimensionalSchema(int schemaID,
      String schemaStub,
      DimensionalConfigurationSchema configurationSchema,
      long responseDelayMillis)
  {
    this(schemaStub,
        configurationSchema,
        responseDelayMillis);
    this.schemaID = schemaID;
  }

  /**
   * Creates a {@link DimensionalSchema} from the given configuration schema and schema keys.
   *
   * @param configurationSchema The configuration schema from which to construct this {@link DimensionalEventSchema}.
   * @param schemaKeys          The schemaKeys assigned to this schema.
   */
  public DimensionalSchema(DimensionalConfigurationSchema configurationSchema,
      Map<String, String> schemaKeys, long responseDelayMillis)
  {
    setConfigurationSchema(configurationSchema);
    setSchemaKeys(schemaKeys);
    this.responseDelayMillis = responseDelayMillis;
    try {
      initialize();
    } catch (JSONException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Creates a {@link DimensionalSchema} object from the given schemaID, configurationSchema,
   * and schemaKeys.
   *
   * @param schemaID            The schemaID assigned to this schema.
   * @param configurationSchema The configuration schema from which this schema was constructed.
   * @param schemaKeys          The schema keys assigned to this schema.
   */
  public DimensionalSchema(int schemaID,
      DimensionalConfigurationSchema configurationSchema,
      Map<String, String> schemaKeys)
  {
    this(configurationSchema,
        schemaKeys, 0);

    this.schemaID = schemaID;
  }

  /**
   * Creates a {@link DimensionalSchema} object from the given configuration schema.
   *
   * @param configurationSchema The configuration schema from which to construct this
   *                            schema.
   */
  public DimensionalSchema(DimensionalConfigurationSchema configurationSchema)
  {
    this(configurationSchema,
        null, 0);
  }

  /**
   * Creates a {@link DimensionalSchema} object with the given schema ID and
   * configuration schema.
   *
   * @param schemaID            The schemaID assigned to this schema.
   * @param configurationSchema The configuration schema from which this schema as constructed.
   */
  public DimensionalSchema(int schemaID,
      DimensionalConfigurationSchema configurationSchema)
  {
    this(configurationSchema);
    this.schemaID = schemaID;
  }

  /**
   * Returns the aggregator registry assigned to this schema object.
   *
   * @return The aggregator registry.
   */
  public AggregatorRegistry getAggregatorRegistry()
  {
    return configurationSchema.getAggregatorRegistry();
  }

  @Override
  public final void setSchemaKeys(Map<String, String> schemaKeys)
  {
    changed = true;
    changedSchemaKeys = true;

    if (schemaKeys == null) {
      this.schemaKeys = null;
      return;
    }

    for (Map.Entry<String, String> entry : schemaKeys.entrySet()) {
      Preconditions.checkNotNull(entry.getKey());
      Preconditions.checkNotNull(entry.getValue());
    }

    this.schemaKeys = Maps.newHashMap(schemaKeys);
  }

  /**
   * This is a helper method for setting the configuration schema.
   *
   * @param configurationSchema The configuration schema.
   */
  private void setConfigurationSchema(DimensionalConfigurationSchema configurationSchema)
  {
    this.configurationSchema = Preconditions.checkNotNull(configurationSchema, "eventSchema");
  }

  /**
   * This is a helper method extracts and validates the information contained in the schema stub for this schema.
   *
   * @param schemaStub The schema stub to extract information from and validate.
   * @throws JSONException This exception is thrown if there is an error processing the provided JSON schemaStub.
   */
  private void setSchemaStub(String schemaStub) throws JSONException
  {
    JSONObject jo = new JSONObject(schemaStub);
    SchemaUtils.checkValidKeysEx(jo, VALID_KEYS);

    JSONObject tempTime = jo.getJSONObject(FIELD_TIME);
    SchemaUtils.checkValidKeys(jo, VALID_TIME_KEYS);

    this.from = tempTime.getLong(FIELD_TIME_FROM);
    this.to = tempTime.getLong(FIELD_TIME_TO);
  }

  /**
   * Initializes the schema JSON and schema metadata.
   *
   * @throws JSONException This exception is thrown when there is an
   *                       exception building the schema for the AppData dimensions schema.
   */
  private void initialize() throws JSONException
  {
    schema = new JSONObject();

    if (schemaKeys != null) {
      schema.put(Schema.FIELD_SCHEMA_KEYS,
          SchemaUtils.createJSONObject(schemaKeys));
    }

    schema.put(SnapshotSchema.FIELD_SCHEMA_TYPE, DimensionalSchema.SCHEMA_TYPE);
    schema.put(SnapshotSchema.FIELD_SCHEMA_VERSION, DimensionalSchema.SCHEMA_VERSION);

    //responseDelayMillis
    if (responseDelayMillis > 0) {
      schema.put(FIELD_RESPONSE_DELAY_MILLS, responseDelayMillis);
    }

    if (!configurationSchema.getTags().isEmpty()) {
      schema.put(FIELD_TAGS, new JSONArray(configurationSchema.getTags()));
    }

    //time
    time = new JSONObject();
    schema.put(FIELD_TIME, time);
    JSONArray bucketsArray = new JSONArray(configurationSchema.getBucketsString());
    time.put(FIELD_TIME_BUCKETS, bucketsArray);
    time.put(FIELD_SLIDING_AGGREGATE_SUPPORTED, true);

    //keys
    keys = new JSONArray(configurationSchema.getKeysString());

    for (int keyIndex = 0; keyIndex < keys.length(); keyIndex++) {
      JSONObject keyJo = keys.getJSONObject(keyIndex);
      String keyName = keyJo.getString(DimensionalConfigurationSchema.FIELD_KEYS_NAME);
      List<String> tags = configurationSchema.getKeyToTags().get(keyName);

      if (!tags.isEmpty()) {
        keyJo.put(FIELD_TAGS, new JSONArray(tags));
      }
    }

    schema.put(DimensionalConfigurationSchema.FIELD_KEYS, keys);

    //values
    JSONArray values = new JSONArray();
    schema.put(SnapshotSchema.FIELD_VALUES, values);

    FieldsDescriptor inputValuesDescriptor = configurationSchema.getInputValuesDescriptor();
    Map<String, Map<String, Type>> allValueToAggregator = configurationSchema.getSchemaAllValueToAggregatorToType();

    for (Map.Entry<String, Map<String, Type>> entry : allValueToAggregator.entrySet()) {
      String valueName = entry.getKey();

      for (Map.Entry<String, Type> entryAggType : entry.getValue().entrySet()) {
        String aggregatorName = entryAggType.getKey();
        Type outputValueType = entryAggType.getValue();

        JSONObject value = new JSONObject();
        String combinedName = valueName +
            DimensionalConfigurationSchema.ADDITIONAL_VALUE_SEPERATOR +
            aggregatorName;
        value.put(SnapshotSchema.FIELD_VALUES_NAME, combinedName);
        value.put(SnapshotSchema.FIELD_VALUES_TYPE, outputValueType.getName());

        List<String> tags = configurationSchema.getValueToTags().get(valueName);

        if (!tags.isEmpty()) {
          value.put(FIELD_TAGS, new JSONArray(tags));
        }

        values.put(value);
      }
    }

    JSONArray dimensions = new JSONArray();

    for (int combinationID = 0;
        combinationID < configurationSchema.getDimensionsDescriptorIDToKeys().size();
        combinationID++) {

      //TODO: the auto-generated combination for computation of composite aggregator will be added.
      //should remove it.

      Fields fields = configurationSchema.getDimensionsDescriptorIDToKeys().get(combinationID);
      Map<String, Set<String>> fieldToAggregatorAdditionalValues =
          configurationSchema.getDimensionsDescriptorIDToFieldToAggregatorAdditionalValues().get(combinationID);

      JSONObject combination = new JSONObject();
      JSONArray combinationArray = new JSONArray();

      for (String field : fields.getFields()) {
        combinationArray.put(field);
      }

      combination.put(DimensionalConfigurationSchema.FIELD_DIMENSIONS_COMBINATIONS, combinationArray);

      if (!fieldToAggregatorAdditionalValues.isEmpty()) {
        JSONArray additionalValueArray = new JSONArray();

        for (Map.Entry<String, Set<String>> entry : fieldToAggregatorAdditionalValues.entrySet()) {
          String valueName = entry.getKey();

          for (String aggregatorName : entry.getValue()) {
            JSONObject additionalValueObject = new JSONObject();
            String combinedName = valueName
                + DimensionalConfigurationSchema.ADDITIONAL_VALUE_SEPERATOR
                + aggregatorName;
            Type inputValueType = inputValuesDescriptor.getType(valueName);

            if (!configurationSchema.getAggregatorRegistry().isAggregator(aggregatorName)) {
              if (aggregatorName == null) {
                LOG.error("{} is not a valid aggregator.", aggregatorName);
              }
            }

            Type outputValueType;

            if (configurationSchema.getAggregatorRegistry().isIncrementalAggregator(aggregatorName)) {
              IncrementalAggregator aggregator
                  = configurationSchema.getAggregatorRegistry().getNameToIncrementalAggregator().get(aggregatorName);

              outputValueType = aggregator.getOutputType(inputValueType);
            } else {
              outputValueType = configurationSchema.getAggregatorRegistry().getNameToOTFAggregators().get(
                  aggregatorName).getOutputType();
            }

            additionalValueObject.put(DimensionalConfigurationSchema.FIELD_VALUES_NAME, combinedName);
            additionalValueObject.put(DimensionalConfigurationSchema.FIELD_VALUES_TYPE, outputValueType.getName());
            additionalValueArray.put(additionalValueObject);
          }
        }

        combination.put(DimensionalConfigurationSchema.FIELD_DIMENSIONS_ADDITIONAL_VALUES, additionalValueArray);
      }

      dimensions.put(combination);
    }

    schema.put(DimensionalConfigurationSchema.FIELD_DIMENSIONS, dimensions);

    this.schemaJSON = this.schema.toString();
  }

  /**
   * Sets the from time for the schema.
   *
   * @param from The from time for the schema.
   */
  public void setFrom(Long from)
  {
    this.from = from;
    changed = true;
    changedFromTo = true;
  }

  /**
   * Sets the to time for the schema.
   *
   * @param to The to time for the schema.
   */
  public void setTo(Long to)
  {
    this.to = to;
    changed = true;
    changedFromTo = true;
  }

  /**
   * Sets the new enum lists for this schema. The sets in the provided maps are converted into lists.
   *
   * @param enums The new enum sets for this schema.
   */
  public void setEnumsSet(Map<String, Set<Object>> enums)
  {
    Preconditions.checkNotNull(enums);
    areEnumsUpdated = true;

    Map<String, List<Object>> enumsList = Maps.newHashMap();

    //Check that all the given keys are valid
    Preconditions.checkArgument(
        configurationSchema.getKeyDescriptor().getFields().getFields().containsAll(enums.keySet()),
        "The given map doesn't contain valid keys. Valid keys are %s and the provided keys are %s",
        configurationSchema.getKeyDescriptor().getFields().getFields(),
        enums.keySet());

    //Todo check the type of the objects, for now just set them on the enum.

    for (Map.Entry<String, Set<Object>> entry : enums.entrySet()) {
      String name = entry.getKey();
      Set<Object> vals = entry.getValue();

      Preconditions.checkNotNull(name);
      Preconditions.checkNotNull(vals);

      for (Object value : entry.getValue()) {
        Preconditions.checkNotNull(value);
      }

      List<Object> valsList = Lists.newArrayList(vals);
      enumsList.put(name, valsList);
    }

    currentEnumVals = Maps.newHashMap(enumsList);
  }

  /**
   * Sets the new enum lists for this schema. The sets in the provided maps are converted into lists, and
   * sorted according to their natural ordering.
   *
   * @param enums The new enum sets for this schema.
   */
  @SuppressWarnings({"rawtypes", "unchecked"})
  public void setEnumsSetComparable(Map<String, Set<Comparable>> enums)
  {
    Preconditions.checkNotNull(enums);
    areEnumsUpdated = true;

    Map<String, List<Object>> enumsList = Maps.newHashMap();

    //Check that all the given keys are valid
    Preconditions.checkArgument(
        configurationSchema.getKeyDescriptor().getFields().getFields().containsAll(enums.keySet()),
        "The given map doesn't contain valid keys. Valid keys are %s and the provided keys are %s",
        configurationSchema.getKeyDescriptor().getFields().getFields(),
        enums.keySet());

    //Todo check the type of the objects, for now just set them on the enum.
    for (Map.Entry<String, Set<Comparable>> entry : enums.entrySet()) {
      String name = entry.getKey();
      Set<Comparable> vals = entry.getValue();

      Preconditions.checkNotNull(name);
      Preconditions.checkNotNull(vals);

      for (Object value : entry.getValue()) {
        Preconditions.checkNotNull(value);
      }

      List<Comparable> valsListComparable = Lists.newArrayList(vals);
      Collections.sort(valsListComparable);
      List<Object> valsList = (List)valsListComparable;
      enumsList.put(name, valsList);
    }

    currentEnumVals = Maps.newHashMap(enumsList);
  }

  /**
   * Sets the new enum lists for this schema.
   *
   * @param enums The new enum lists for this schema.
   */
  public void setEnumsList(Map<String, List<Object>> enums)
  {
    Preconditions.checkNotNull(enums);
    areEnumsUpdated = true;

    //Check that all the given keys are valid
    Preconditions.checkArgument(
        configurationSchema.getKeyDescriptor().getFields().getFields().containsAll(enums.keySet()),
        "The given map doesn't contain valid keys. Valid keys are %s and the provided keys are %s",
        configurationSchema.getKeyDescriptor().getFields().getFields(),
        enums.keySet());

    //Todo check the type of the objects, for now just set them on the enum.
    for (Map.Entry<String, List<Object>> entry : enums.entrySet()) {
      Preconditions.checkNotNull(entry.getKey());
      Preconditions.checkNotNull(entry.getValue());
    }

    Map<String, List<Object>> tempEnums = Maps.newHashMap();

    for (Map.Entry<String, List<Object>> entry : enums.entrySet()) {
      String key = entry.getKey();
      List<?> enumValues = entry.getValue();
      List<Object> tempEnumValues = Lists.newArrayList();

      for (Object enumValue : enumValues) {
        tempEnumValues.add(enumValue);
      }

      tempEnums.put(key, tempEnumValues);
    }

    currentEnumVals = tempEnums;
  }

  @Override
  public String getSchemaJSON()
  {
    if (!changed && schemaJSON != null) {
      //If there are no changes, return the pre computed JSON
      return schemaJSON;
    }

    if (changedSchemaKeys) {
      //If the schema keys change, recompute the schema keys portion of the JSON
      changedSchemaKeys = false;

      if (schemaKeys == null) {
        schema.remove(Schema.FIELD_SCHEMA_KEYS);
      } else {
        try {
          schema.put(Schema.FIELD_SCHEMA_KEYS,
              SchemaUtils.createJSONObject(schemaKeys));
        } catch (JSONException ex) {
          throw new RuntimeException(ex);
        }
      }
    }

    if (changedFromTo) {
      //If the from to times have changed then recompute the time portion of the schema.
      changedFromTo = false;
      Preconditions.checkState(!(from == null ^ to == null),
          "Either both from and to should be set or both should be not set.");

      if (from != null) {
        Preconditions.checkState(to >= from, "to {} must be greater than or equal to from {}.", to, from);
      }

      if (from == null) {
        time.remove(FIELD_TIME_FROM);
        time.remove(FIELD_TIME_TO);
      } else {
        try {
          time.put(FIELD_TIME_FROM, from);
          time.put(FIELD_TIME_TO, to);
        } catch (JSONException ex) {
          throw new RuntimeException(ex);
        }
      }
    }

    if (this.areEnumsUpdated) {
      //If the enums have been updated, recompute the key portion of the schema.
      for (int keyIndex = 0;
          keyIndex < keys.length();
          keyIndex++) {
        JSONObject keyData;
        String name;

        try {
          keyData = keys.getJSONObject(keyIndex);
          name = keyData.getString(DimensionalConfigurationSchema.FIELD_KEYS_NAME);
        } catch (JSONException ex) {
          throw new RuntimeException(ex);
        }

        List<Object> enumVals = currentEnumVals.get(name);

        if (enumVals == null || enumVals.isEmpty()) {
          keyData.remove(DimensionalConfigurationSchema.FIELD_KEYS_ENUMVALUES);
          continue;
        }

        JSONArray newEnumValues = new JSONArray();

        for (Object enumVal : enumVals) {
          newEnumValues.put(enumVal);
        }

        try {
          keyData.put(DimensionalConfigurationSchema.FIELD_KEYS_ENUMVALUES, newEnumValues);
        } catch (JSONException ex) {
          throw new RuntimeException(ex);
        }
      }

      this.areEnumsUpdated = false;
    }

    //Rebuild the schema JSON string.
    schemaJSON = schema.toString();
    return schemaJSON;
  }

  /**
   * Gets the {@link DimensionalConfigurationSchema} from which this {@link DimensionalSchema}.
   *
   * @return The {@link DimensionalConfigurationSchema} from which this {@link DimensionalSchema} was
   * constructed.
   */
  public DimensionalConfigurationSchema getDimensionalConfigurationSchema()
  {
    return configurationSchema;
  }

  @Override
  public String getSchemaType()
  {
    return SCHEMA_TYPE;
  }

  @Override
  public String getSchemaVersion()
  {
    return SCHEMA_VERSION;
  }

  @Override
  public Map<String, String> getSchemaKeys()
  {
    return schemaKeys;
  }

  /**
   * @return the predefinedFromTo
   */
  public boolean isPredefinedFromTo()
  {
    return predefinedFromTo;
  }

  /**
   * Returns the schema ID for this schema. This is only relevant for operators which
   * host multiple schemas.
   *
   * @return The schema ID for this schema.
   */
  @Override
  public int getSchemaID()
  {
    return schemaID;
  }

  /**
   * Returns the current enum vals for the schema. The current enum vals for the
   * schema are expressed in a map whose keys are the names of the keys in the schema, and whose
   * values are a list of possible values for the key.
   *
   * @return the currentEnumVals The current enum vals for the schema.
   */
  public Map<String, List<Object>> getCurrentEnumVals()
  {
    return currentEnumVals;
  }

  private static final Logger LOG = LoggerFactory.getLogger(DimensionalSchema.class);
}
