// Path: src/main/java/com/asher_stern/crf/crf/filters/Filter.java
// public abstract class Filter<K,G> implements Serializable
// {
// 	private static final long serialVersionUID = 5563671313834518710L;
// 	
// 	public abstract int hashCode();
// 	public abstract boolean equals(Object obj);
// }
// 
// Path: src/main/java/com/asher_stern/crf/crf/filters/FilterFactory.java
// public interface FilterFactory<K, G> extends Serializable
// {
// 	/**
// 	 * Creates a set of filters for the given token,tag, and tag-of-previous-token.
// 	 * The convention is as follows:
// 	 * Let each feature f be a feature that <B>might</B> return non-zero for the given token,tag,previous-tag.
// 	 * That feature is encapsulated with a {@link Filter} in a {@link CrfFilteredFeature}. Let's call this filter "t".
// 	 * For that filter there exist one filter in the set returned by this function, name it "t'", such that "t'" equals to "t".
// 	 * 
// 	 * 
// 	 * @param sequence A sequence of tokens
// 	 * @param tokenIndex An index of a token in that sequence
// 	 * @param currentTag A tag for that token
// 	 * @param previousTag A tag for the token which immediately precedes that token.
// 	 * @return A set of filters as described above.
// 	 */
// 	public Set<Filter<K, G>> createFilters(K[] sequence, int tokenIndex, G currentTag, G previousTag);
// }
// 
// Path: src/main/java/com/asher_stern/crf/crf/filters/TwoTagsFilter.java
// public class TwoTagsFilter<K, G> extends Filter<K, G>
// {
// 	private static final long serialVersionUID = -4850947891058236177L;
// 	
// 	public TwoTagsFilter(G currentTag, G previousTag)
// 	{
// 		this.currentTag = currentTag;
// 		this.previousTag = previousTag;
// 	}
// 	
// 
// 
// 	@Override
// 	public int hashCode()
// 	{
// 		if (hashCodeCalculated)
// 		{
// 			return hashCodeValue;
// 		}
// 		else
// 		{
// 			final int prime = 31;
// 			int result = 1;
// 			result = prime * result
// 					+ ((currentTag == null) ? 0 : currentTag.hashCode());
// 			result = prime * result
// 					+ ((previousTag == null) ? 0 : previousTag.hashCode());
// 			hashCodeValue = result;
// 			hashCodeCalculated = true;
// 			return result;
// 		}
// 	}
// 	
// 	@Override
// 	public boolean equals(Object obj)
// 	{
// 		if (this == obj)
// 			return true;
// 		if (obj == null)
// 			return false;
// 		if (getClass() != obj.getClass())
// 			return false;
// 		TwoTagsFilter<?,?> other = (TwoTagsFilter<?,?>) obj;
// 		if (currentTag == null)
// 		{
// 			if (other.currentTag != null)
// 				return false;
// 		} else if (!currentTag.equals(other.currentTag))
// 			return false;
// 		if (previousTag == null)
// 		{
// 			if (other.previousTag != null)
// 				return false;
// 		} else if (!previousTag.equals(other.previousTag))
// 			return false;
// 		return true;
// 	}
// 
// 
// 
// 	private final G currentTag;
// 	private final G previousTag;
// 	
// 	private transient int hashCodeValue = 0;
// 	private transient boolean hashCodeCalculated = false;
// }


import java.util.LinkedHashSet;
import java.util.Set;
import com.asher_stern.crf.crf.filters.Filter;
import com.asher_stern.crf.crf.filters.FilterFactory;
import com.asher_stern.crf.crf.filters.TwoTagsFilter;
package com.asher_stern.crf.postagging.postaggers.crf.features;



/**
 * A {@link FilterFactory} for the features generated by the {@link StandardFeatureGenerator}.
 * 
 * @author Asher Stern
 * Date: Nov 11, 2014
 *
 */
public class StandardFilterFactory implements FilterFactory<String, String>
{
	private static final long serialVersionUID = 6283122214266870374L;

	@Override
	public Set<Filter<String, String>> createFilters(String[] sequence, int tokenIndex, String currentTag, String previousTag)
	{
		String token = sequence[tokenIndex];
		Set<Filter<String, String>> ret = new LinkedHashSet<Filter<String,String>>();
// Path: src/main/java/com/asher_stern/crf/crf/filters/Filter.java
// public abstract class Filter<K,G> implements Serializable
// {
// 	private static final long serialVersionUID = 5563671313834518710L;
// 	
// 	public abstract int hashCode();
// 	public abstract boolean equals(Object obj);
// }
// 
// Path: src/main/java/com/asher_stern/crf/crf/filters/FilterFactory.java
// public interface FilterFactory<K, G> extends Serializable
// {
// 	/**
// 	 * Creates a set of filters for the given token,tag, and tag-of-previous-token.
// 	 * The convention is as follows:
// 	 * Let each feature f be a feature that <B>might</B> return non-zero for the given token,tag,previous-tag.
// 	 * That feature is encapsulated with a {@link Filter} in a {@link CrfFilteredFeature}. Let's call this filter "t".
// 	 * For that filter there exist one filter in the set returned by this function, name it "t'", such that "t'" equals to "t".
// 	 * 
// 	 * 
// 	 * @param sequence A sequence of tokens
// 	 * @param tokenIndex An index of a token in that sequence
// 	 * @param currentTag A tag for that token
// 	 * @param previousTag A tag for the token which immediately precedes that token.
// 	 * @return A set of filters as described above.
// 	 */
// 	public Set<Filter<K, G>> createFilters(K[] sequence, int tokenIndex, G currentTag, G previousTag);
// }
// 
// Path: src/main/java/com/asher_stern/crf/crf/filters/TwoTagsFilter.java
// public class TwoTagsFilter<K, G> extends Filter<K, G>
// {
// 	private static final long serialVersionUID = -4850947891058236177L;
// 	
// 	public TwoTagsFilter(G currentTag, G previousTag)
// 	{
// 		this.currentTag = currentTag;
// 		this.previousTag = previousTag;
// 	}
// 	
// 
// 
// 	@Override
// 	public int hashCode()
// 	{
// 		if (hashCodeCalculated)
// 		{
// 			return hashCodeValue;
// 		}
// 		else
// 		{
// 			final int prime = 31;
// 			int result = 1;
// 			result = prime * result
// 					+ ((currentTag == null) ? 0 : currentTag.hashCode());
// 			result = prime * result
// 					+ ((previousTag == null) ? 0 : previousTag.hashCode());
// 			hashCodeValue = result;
// 			hashCodeCalculated = true;
// 			return result;
// 		}
// 	}
// 	
// 	@Override
// 	public boolean equals(Object obj)
// 	{
// 		if (this == obj)
// 			return true;
// 		if (obj == null)
// 			return false;
// 		if (getClass() != obj.getClass())
// 			return false;
// 		TwoTagsFilter<?,?> other = (TwoTagsFilter<?,?>) obj;
// 		if (currentTag == null)
// 		{
// 			if (other.currentTag != null)
// 				return false;
// 		} else if (!currentTag.equals(other.currentTag))
// 			return false;
// 		if (previousTag == null)
// 		{
// 			if (other.previousTag != null)
// 				return false;
// 		} else if (!previousTag.equals(other.previousTag))
// 			return false;
// 		return true;
// 	}
// 
// 
// 
// 	private final G currentTag;
// 	private final G previousTag;
// 	
// 	private transient int hashCodeValue = 0;
// 	private transient boolean hashCodeCalculated = false;
// }


// Path: src/main/java/com/asher_stern/crf/postagging/postaggers/crf/features/StandardFilterFactory.java
import java.util.LinkedHashSet;
import java.util.Set;
import com.asher_stern.crf.crf.filters.Filter;
import com.asher_stern.crf.crf.filters.FilterFactory;
import com.asher_stern.crf.crf.filters.TwoTagsFilter;

package com.asher_stern.crf.postagging.postaggers.crf.features;



/**
 * A {@link FilterFactory} for the features generated by the {@link StandardFeatureGenerator}.
 * 
 * @author Asher Stern
 * Date: Nov 11, 2014
 *
 */
public class StandardFilterFactory implements FilterFactory<String, String>
{
	private static final long serialVersionUID = 6283122214266870374L;

	@Override
	public Set<Filter<String, String>> createFilters(String[] sequence, int tokenIndex, String currentTag, String previousTag)
	{
		String token = sequence[tokenIndex];
		Set<Filter<String, String>> ret = new LinkedHashSet<Filter<String,String>>();
		ret.add(new TwoTagsFilter<String, String>(currentTag, previousTag));