/*
 * 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.uima.fit.factory;

import static java.util.Arrays.asList;
import static org.apache.uima.UIMAFramework.getXMLParser;
import static org.apache.uima.fit.internal.MetaDataUtil.scanDescriptors;
import static org.apache.uima.fit.internal.ReflectionUtil.getInheritableAnnotation;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.WeakHashMap;

import org.apache.commons.logging.LogFactory;
import org.apache.uima.fit.descriptor.FsIndex;
import org.apache.uima.fit.descriptor.FsIndexKey;
import org.apache.uima.fit.internal.ClassLoaderUtils;
import org.apache.uima.fit.internal.MetaDataType;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.resource.metadata.FsIndexCollection;
import org.apache.uima.resource.metadata.FsIndexDescription;
import org.apache.uima.resource.metadata.FsIndexKeyDescription;
import org.apache.uima.resource.metadata.Import;
import org.apache.uima.resource.metadata.impl.FsIndexCollection_impl;
import org.apache.uima.resource.metadata.impl.FsIndexDescription_impl;
import org.apache.uima.resource.metadata.impl.FsIndexKeyDescription_impl;
import org.apache.uima.resource.metadata.impl.Import_impl;
import org.apache.uima.util.InvalidXMLException;
import org.apache.uima.util.XMLInputSource;

/**
 */
public final class FsIndexFactory {
  /**
   * Comparator that orders FeatureStructures according to the standard order of their key features.
   * For integer and float values, this is the standard linear order, and for strings it is
   * lexicographic order.
   */
  public static final int STANDARD_COMPARE = FsIndexKeyDescription.STANDARD_COMPARE;

  /**
   * Comparator that orders FeatureStructures according to the reverse order of their key features
   * (the opposite order as that defined by STANDARD_COMPARE).
   */
  public static final int REVERSE_STANDARD_COMPARE = FsIndexKeyDescription.REVERSE_STANDARD_COMPARE;

  private static final Object SCAN_LOCK = new Object();

  private static final Object CREATE_LOCK = new Object();

  private static WeakHashMap<ClassLoader, String[]> fsIndexLocationsByClassloader;

  private static WeakHashMap<ClassLoader, FsIndexCollection> fsIndexCollectionsByClassloader;

  static {
    fsIndexLocationsByClassloader = new WeakHashMap<>();
    fsIndexCollectionsByClassloader = new WeakHashMap<>();
  }

  private FsIndexFactory() {
    // Factory class
  }

  /**
   * Create index configuration data for a given class definition using reflection and the
   * configuration parameter annotation.
   *
   * @param componentClass
   *          the class to analyze
   * @return the index collection
   */
  public static FsIndexCollection createFsIndexCollection(Class<?> componentClass) {
    List<FsIndex> anFsIndexList = new ArrayList<>();

    // Check FsIndexCollection annotation
    org.apache.uima.fit.descriptor.FsIndexCollection anIndexCollection = getInheritableAnnotation(
            org.apache.uima.fit.descriptor.FsIndexCollection.class, componentClass);
    if (anIndexCollection != null) {
      anFsIndexList.addAll(asList(anIndexCollection.fsIndexes()));
    }

    // Check FsIndex annotation
    org.apache.uima.fit.descriptor.FsIndex anFsIndex = getInheritableAnnotation(FsIndex.class,
            componentClass);
    if (anFsIndex != null) {
      if (anIndexCollection != null) {
        throw new IllegalStateException(
                "Class [" + componentClass.getName() + "] must not " + "declare "
                        + org.apache.uima.fit.descriptor.FsIndexCollection.class.getSimpleName()
                        + " and " + FsIndex.class.getSimpleName() + " at the same time.");
      }

      anFsIndexList.add(anFsIndex);
    }

    FsIndexCollection_impl fsIndexCollection = new FsIndexCollection_impl();

    // Process collected FsIndex annotations
    for (FsIndex anIdx : anFsIndexList) {
      // Collect index keys
      List<FsIndexKeyDescription> keys = new ArrayList<>();
      for (FsIndexKey anIndexKey : anIdx.keys()) {
        keys.add(createFsIndexKeyDescription(anIndexKey.featureName(), anIndexKey.comparator()));
      }

      // type and typeName must not be set at the same time
      if (!anIdx.typeName().equals(FsIndex.NO_NAME_TYPE_SET)
              && anIdx.type() != FsIndex.NoClassSet.class) {
        throw new IllegalStateException("Class [" + componentClass.getName() + "] must not "
                + "declare an " + org.apache.uima.fit.descriptor.FsIndex.class.getSimpleName()
                + " with type and typeName both set at the same time.");
      }

      String typeName;
      if (!anIdx.typeName().equals(FsIndex.NO_NAME_TYPE_SET)) {
        typeName = anIdx.typeName();
      } else if (anIdx.type() != FsIndex.NoClassSet.class) {
        typeName = anIdx.type().getName();
      } else {
        throw new IllegalStateException("Class [" + componentClass.getName() + "] must not "
                + "declare an " + org.apache.uima.fit.descriptor.FsIndex.class.getSimpleName()
                + " with neither type nor typeName set.");
      }

      fsIndexCollection.addFsIndex(createFsIndexDescription(anIdx.label(), anIdx.kind(), typeName,
              anIdx.typePriorities(), keys.toArray(new FsIndexKeyDescription[keys.size()])));
    }

    return fsIndexCollection;
  }

  /**
   * @param label
   *          the index label
   * @param kind
   *          the type of index
   * @param typeName
   *          the indexed feature structure type
   * @param useTypePriorities
   *          whether to respect type priorities
   * @param keys
   *          the index keys
   * @return the index description
   */
  public static FsIndexDescription createFsIndexDescription(String label, String kind,
          String typeName, boolean useTypePriorities, FsIndexKeyDescription... keys) {
    FsIndexDescription_impl fsIndexDescription = new FsIndexDescription_impl();
    fsIndexDescription.setLabel(label);
    fsIndexDescription.setKind(kind);
    fsIndexDescription.setTypeName(typeName);
    fsIndexDescription.setKeys(keys);
    return fsIndexDescription;
  }

  /**
   * Create a index collection from a set of descriptions.
   *
   * @param descriptions
   *          the index descriptions
   * @return the index collection
   */
  public static FsIndexCollection createFsIndexCollection(FsIndexDescription... descriptions) {
    FsIndexCollection_impl fsIndexCollection = new FsIndexCollection_impl();
    fsIndexCollection.setFsIndexes(descriptions);
    return fsIndexCollection;
  }

  /**
   * @param featureName
   *          the feature to index
   * @return the index key description
   */
  public static FsIndexKeyDescription createFsIndexKeyDescription(String featureName) {
    return createFsIndexKeyDescription(featureName, STANDARD_COMPARE);
  }

  /**
   * @param featureName
   *          the feature to index
   * @param comparator
   *          the index comparator
   * @return the index key description
   */
  public static FsIndexKeyDescription createFsIndexKeyDescription(String featureName,
          int comparator) {
    FsIndexKeyDescription_impl key = new FsIndexKeyDescription_impl();
    key.setFeatureName(featureName);
    key.setComparator(comparator);
    key.setTypePriority(false);
    return key;
  }

  /**
   * Creates a {@link FsIndexCollection} from descriptor names.
   *
   * @param descriptorNames
   *          The fully qualified, Java-style, dotted descriptor names.
   * @return a {@link FsIndexCollection} that includes the indexes from all of the specified files.
   */
  public static FsIndexCollection createFsIndexCollection(String... descriptorNames) {
    List<Import> imports = new ArrayList<>();
    for (String descriptorName : descriptorNames) {
      Import imp = new Import_impl();
      imp.setName(descriptorName);
      imports.add(imp);
    }
    Import[] importArray = new Import[imports.size()];

    FsIndexCollection fsIndexCollection = new FsIndexCollection_impl();
    fsIndexCollection.setImports(imports.toArray(importArray));
    return fsIndexCollection;
  }

  /**
   * Creates a {@link FsIndexCollection} from a descriptor file
   *
   * @param descriptorURIs
   *          The descriptor file paths.
   * @return A {@link FsIndexCollection} that includes the indexes from all of the specified files.
   */
  public static FsIndexCollection createTypeSystemDescriptionFromPath(String... descriptorURIs) {
    List<Import> imports = new ArrayList<>();
    for (String descriptorURI : descriptorURIs) {
      Import imp = new Import_impl();
      imp.setLocation(descriptorURI);
      imports.add(imp);
    }
    Import[] importArray = new Import[imports.size()];

    FsIndexCollection fsIndexCollection = new FsIndexCollection_impl();
    fsIndexCollection.setImports(imports.toArray(importArray));
    return fsIndexCollection;
  }

  /**
   * Creates a {@link FsIndexCollection} from all index descriptions that can be found via the
   * pattern specified in the system property {@code org.apache.uima.fit.fsindex.import_pattern} or
   * via the {@code META-INF/org.apache.uima.fit/fsindexes.txt} files in the classpath.
   *
   * @return the auto-scanned indexes.
   * @throws ResourceInitializationException
   *           if the index collection could not be assembled
   */
  public static FsIndexCollection createFsIndexCollection() throws ResourceInitializationException {
    ClassLoader cl = ClassLoaderUtils.findClassloader();
    FsIndexCollection aggFsIdxCol = fsIndexCollectionsByClassloader.get(cl);
    if (aggFsIdxCol == null) {
      synchronized (CREATE_LOCK) {
        List<FsIndexDescription> fsIndexList = new ArrayList<>();
        for (String location : scanIndexDescriptors()) {
          try {
            XMLInputSource xmlInput = new XMLInputSource(location);
            FsIndexCollection fsIdxCol = getXMLParser().parseFsIndexCollection(xmlInput);
            fsIdxCol.resolveImports();
            fsIndexList.addAll(asList(fsIdxCol.getFsIndexes()));
            LogFactory.getLog(FsIndexFactory.class).debug("Detected index at [" + location + "]");
          } catch (IOException e) {
            throw new ResourceInitializationException(e);
          } catch (InvalidXMLException e) {
            LogFactory.getLog(FsIndexFactory.class)
            .warn("[" + location + "] is not a index descriptor file. Ignoring.", e);
          }
        }

        aggFsIdxCol = createFsIndexCollection(
                fsIndexList.toArray(new FsIndexDescription[fsIndexList.size()]));
        fsIndexCollectionsByClassloader.put(cl, aggFsIdxCol);
      }
    }

    return (FsIndexCollection) aggFsIdxCol.clone();
  }

  /**
   * Get all currently accessible index descriptor locations. A scan is actually only performed on
   * the first call and the locations are cached. To force a re-scan use
   * {@link #forceIndexDescriptorsScan()}.
   *
   * @return an array of locations.
   * @throws ResourceInitializationException
   *           if the locations could not be resolved.
   */
  public static String[] scanIndexDescriptors() throws ResourceInitializationException {
    synchronized (SCAN_LOCK) {
      ClassLoader cl = ClassLoaderUtils.findClassloader();
      String[] indexLocations = fsIndexLocationsByClassloader.get(cl);
      if (indexLocations == null) {
        indexLocations = scanDescriptors(MetaDataType.FS_INDEX);
        fsIndexLocationsByClassloader.put(cl, indexLocations);
      }
      return indexLocations;
    }
  }

  /**
   * Force rescan of index descriptors. The next call to {@link #scanIndexDescriptors()} will rescan
   * all auto-import locations.
   */
  public static void forceIndexDescriptorsScan() {
    synchronized (SCAN_LOCK) {
      fsIndexLocationsByClassloader.clear();
      fsIndexCollectionsByClassloader.clear();
    }
  }
}
