// 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;
                    // this links comes from "outside" so assume we are the head
                    return token;
                }

                Token edgeSource = graph.getEdgeSource(dependencyEdge);
                Token edgeTarget = graph.getEdgeTarget(dependencyEdge);

                if(edgeSource.equals(token)) {
                    outDegree++;
                } else if(edgeTarget.equals(token)) {
                    inDegree++;
                }
            }
            // if ..
            if(inDegree == 0 && outDegree > 0) {
                candidate = token;
            }

        }

        if(candidate == null) {
            return Iterables.getFirst(tokens, null);
        }

        return candidate;

    }

    protected final List<FoundFeature<Annotation>> postProcess(List<FoundFeature<Annotation>> dataBag, UndirectedGraph<Token, DependencyEdge> graph) {

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

                    // this links comes from "outside" so assume we are the head
                    return token;
                }

                Token edgeSource = graph.getEdgeSource(dependencyEdge);
                Token edgeTarget = graph.getEdgeTarget(dependencyEdge);

                if(edgeSource.equals(token)) {
                    outDegree++;
                } else if(edgeTarget.equals(token)) {
                    inDegree++;
                }
            }
            // if ..
            if(inDegree == 0 && outDegree > 0) {
                candidate = token;
            }

        }

        if(candidate == null) {
            return Iterables.getFirst(tokens, null);
        }

        return candidate;

    }

    protected final List<FoundFeature<Annotation>> postProcess(List<FoundFeature<Annotation>> dataBag, UndirectedGraph<Token, DependencyEdge> graph) {

        List<FoundFeature<Annotation>> additional = Lists.newArrayList();