// Path: core/src/main/java/edu/tuberlin/dima/textmining/jedi/core/model/FoundFeature.java
// public class FoundFeature<T> {
// 
//     T entity1;
//     T entity2;
// 
//     String pattern;
//     String relation;
// 
//     public FoundFeature(T entity1, T entity2, String pattern) {
//         this.entity1 = entity1;
//         this.entity2 = entity2;
//         this.pattern = pattern;
//     }
// 
// 
//     public String getRelation() {
//         return relation;
//     }
// 
//     public void setRelation(String relation) {
//         this.relation = relation;
//     }
// 
//     public T getEntity1() {
//         return entity1;
//     }
// 
// 	public void setEntity1(T entity1) {
// 		this.entity1 = entity1;
// 	}
// 
// 	public T getEntity2() {
//         return entity2;
//     }
// 
// 	public void setEntity2(T entity2) {
// 		this.entity2 = entity2;
// 	}
// 
// 	public String getPattern() {
//         return pattern;
//     }
// 
// 	public void setPattern(String pattern) {
// 		this.pattern = pattern;
// 	}
// 
// 	@Override
//     public String toString() {
//         return "FoundFeature{" +
//                 "entity1=" + transformToString(entity1) +
//                 ", entity2=" + transformToString(entity2) +
//                 ", pattern='" + pattern + '\'' +
//                 ", relation='" + relation + '\'' +
//                 '}';
//     }
// 
//     private static <T> String transformToString(T input) {
//         if(input instanceof Annotation) {
//             return ((Annotation) input).getCoveredText();
//         } else {
//             return input.toString();
//         }
//     }
// }
// 
// Path: core/src/main/java/edu/tuberlin/dima/textmining/jedi/core/util/JCommanderClassConverter.java
// public class JCommanderClassConverter extends BaseConverter<Class> {
// 
//     public JCommanderClassConverter(String optionName) {
//         super(optionName);
//     }
// 
//     @Override
//     public Class convert(String value) {
//         try {
//             return Class.forName(value);
//         } catch (ClassNotFoundException e) {
//             throw new ParameterException(getErrorString(value, "a class"));
//         }
//     }
// }


import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import de.tudarmstadt.ukp.dkpro.core.api.lexmorph.type.pos.O;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Sentence;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token;
import de.tudarmstadt.ukp.dkpro.core.api.syntax.type.dependency.Dependency;
import edu.tuberlin.dima.textmining.jedi.core.model.FoundFeature;
import edu.tuberlin.dima.textmining.jedi.core.util.JCommanderClassConverter;
import org.apache.uima.UIMAException;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.jcas.JCas;
import org.apache.uima.jcas.tcas.Annotation;
import org.jgrapht.UndirectedGraph;
import org.jgrapht.graph.SimpleGraph;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
package edu.tuberlin.dima.textmining.jedi.core.features.detector;



/**
 */
public abstract class AbstractShortestPathFeatureExtractor {

    @Parameter(names = {"-lemmatize"}, description = "Lemmatize the pattern to remove times", required = false)
    private boolean lemmatize = false;

    @Parameter(names = {"-pickupSimilar"}, description = "If set, the token is expanded left and right with tokens of the same selectionType", required = false)
    private boolean pickupSimilar = false;

    @Parameter(names = {"-collapseMentions"}, description = "If set, similar mentions are collapsed", required = false)
    private boolean collapseMentions = false;

    @Parameter(names = {"-selectionType"}, description = "Class of selection Type (e.g. Named Entity)", required = true, converter = JCommanderClassConverter.class)
    private Class<? extends Annotation> selectionType;

    @Parameter(names = {"-additionalSelectionType"}, description = "AdditionalClass of selection Type (e.g. Named Entity)", required = false, converter = JCommanderClassConverter.class)
    private Class<? extends Annotation> additionalSelectionType;

    @Parameter(names = {"-resolveCoreferences"}, description = "Resolve Co-references for a given token", required = false)
    private boolean resolveCoreferences = false;

    private JCas jCas;

	@Parameter(names = {"-name"}, description = "The name of the extractor", required = false)
	private String name;

    public AbstractShortestPathFeatureExtractor(String options) throws UIMAException {

        JCommander jCommander = new JCommander(this);
        try {
            // parse options
            jCommander.parse(options.split(" "));

        } catch (ParameterException e) {
            StringBuilder out = new StringBuilder();
            jCommander.setProgramName(this.getClass().getSimpleName());
            jCommander.usage(out);
            // We wrap this exception in a Runtime exception so that
            // existing loaders that extend PigStorage don't break
            throw new RuntimeException(e.getMessage() + "\n" + "In: " + options + "\n" + out.toString());
        } catch (Exception e) {
            throw new RuntimeException("Error initializing " + this.getClass().getSimpleName(), e);
        }

    }

// Path: core/src/main/java/edu/tuberlin/dima/textmining/jedi/core/model/FoundFeature.java
// public class FoundFeature<T> {
// 
//     T entity1;
//     T entity2;
// 
//     String pattern;
//     String relation;
// 
//     public FoundFeature(T entity1, T entity2, String pattern) {
//         this.entity1 = entity1;
//         this.entity2 = entity2;
//         this.pattern = pattern;
//     }
// 
// 
//     public String getRelation() {
//         return relation;
//     }
// 
//     public void setRelation(String relation) {
//         this.relation = relation;
//     }
// 
//     public T getEntity1() {
//         return entity1;
//     }
// 
// 	public void setEntity1(T entity1) {
// 		this.entity1 = entity1;
// 	}
// 
// 	public T getEntity2() {
//         return entity2;
//     }
// 
// 	public void setEntity2(T entity2) {
// 		this.entity2 = entity2;
// 	}
// 
// 	public String getPattern() {
//         return pattern;
//     }
// 
// 	public void setPattern(String pattern) {
// 		this.pattern = pattern;
// 	}
// 
// 	@Override
//     public String toString() {
//         return "FoundFeature{" +
//                 "entity1=" + transformToString(entity1) +
//                 ", entity2=" + transformToString(entity2) +
//                 ", pattern='" + pattern + '\'' +
//                 ", relation='" + relation + '\'' +
//                 '}';
//     }
// 
//     private static <T> String transformToString(T input) {
//         if(input instanceof Annotation) {
//             return ((Annotation) input).getCoveredText();
//         } else {
//             return input.toString();
//         }
//     }
// }
// 
// Path: core/src/main/java/edu/tuberlin/dima/textmining/jedi/core/util/JCommanderClassConverter.java
// public class JCommanderClassConverter extends BaseConverter<Class> {
// 
//     public JCommanderClassConverter(String optionName) {
//         super(optionName);
//     }
// 
//     @Override
//     public Class convert(String value) {
//         try {
//             return Class.forName(value);
//         } catch (ClassNotFoundException e) {
//             throw new ParameterException(getErrorString(value, "a class"));
//         }
//     }
// }


// Path: core/src/main/java/edu/tuberlin/dima/textmining/jedi/core/features/detector/AbstractShortestPathFeatureExtractor.java
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import de.tudarmstadt.ukp.dkpro.core.api.lexmorph.type.pos.O;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Sentence;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token;
import de.tudarmstadt.ukp.dkpro.core.api.syntax.type.dependency.Dependency;
import edu.tuberlin.dima.textmining.jedi.core.model.FoundFeature;
import edu.tuberlin.dima.textmining.jedi.core.util.JCommanderClassConverter;
import org.apache.uima.UIMAException;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.jcas.JCas;
import org.apache.uima.jcas.tcas.Annotation;
import org.jgrapht.UndirectedGraph;
import org.jgrapht.graph.SimpleGraph;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

package edu.tuberlin.dima.textmining.jedi.core.features.detector;



/**
 */
public abstract class AbstractShortestPathFeatureExtractor {

    @Parameter(names = {"-lemmatize"}, description = "Lemmatize the pattern to remove times", required = false)
    private boolean lemmatize = false;

    @Parameter(names = {"-pickupSimilar"}, description = "If set, the token is expanded left and right with tokens of the same selectionType", required = false)
    private boolean pickupSimilar = false;

    @Parameter(names = {"-collapseMentions"}, description = "If set, similar mentions are collapsed", required = false)
    private boolean collapseMentions = false;

    @Parameter(names = {"-selectionType"}, description = "Class of selection Type (e.g. Named Entity)", required = true, converter = JCommanderClassConverter.class)
    private Class<? extends Annotation> selectionType;

    @Parameter(names = {"-additionalSelectionType"}, description = "AdditionalClass of selection Type (e.g. Named Entity)", required = false, converter = JCommanderClassConverter.class)
    private Class<? extends Annotation> additionalSelectionType;

    @Parameter(names = {"-resolveCoreferences"}, description = "Resolve Co-references for a given token", required = false)
    private boolean resolveCoreferences = false;

    private JCas jCas;

	@Parameter(names = {"-name"}, description = "The name of the extractor", required = false)
	private String name;

    public AbstractShortestPathFeatureExtractor(String options) throws UIMAException {

        JCommander jCommander = new JCommander(this);
        try {
            // parse options
            jCommander.parse(options.split(" "));

        } catch (ParameterException e) {
            StringBuilder out = new StringBuilder();
            jCommander.setProgramName(this.getClass().getSimpleName());
            jCommander.usage(out);
            // We wrap this exception in a Runtime exception so that
            // existing loaders that extend PigStorage don't break
            throw new RuntimeException(e.getMessage() + "\n" + "In: " + options + "\n" + out.toString());
        } catch (Exception e) {
            throw new RuntimeException("Error initializing " + this.getClass().getSimpleName(), e);
        }

    }

    public final List<FoundFeature<Annotation>> exec(JCas xmlDocument) throws IOException {