// Path: src/main/java/com/lumata/lib/lupa/ReadableResource.java
// public interface ReadableResource {
// 
// 	URL getUrl();
// 
// 	/**
// 	 * Move the current URL to the redirection path and set the specified url as the actual resource url.
// 	 * 
// 	 * @param url
// 	 *            the redirectionUrl
// 	 */
// 	void makeRedirection(URL url);
// 
// 	Optional<URL[]> getRedirectionPath();
// 
// 	Optional<MediaType> getContentType();
// 
// 	InputStream read() throws IOException;
// 
// 	void discard();
// }
// 
// Path: src/main/java/com/lumata/lib/lupa/content/WebContent.java
// public abstract class WebContent {
// 
// 	public static enum Type {
// 		WEBPAGE,
// 		IMAGE,
// 		VIDEO,
// 		AUDIO,
// 		FEED
// 	}
// 
// 	private final String url;
// 	private final String[] aliasUrls;
// 	private Set<String> keywords;
// 
// 	WebContent(String url, String... aliasUrls) {
// 		this.url = url;
// 		this.aliasUrls = aliasUrls;
// 	}
// 
// 	/**
// 	 * Gets the preferred URL of this content
// 	 * 
// 	 * @return the url
// 	 */
// 	public String getUrl() {
// 		return url;
// 	}
// 
// 	/**
// 	 * Gets the known alias URLs where this content can be also located. The order is defined by the redirection path.
// 	 * 
// 	 * @return the referingUrls
// 	 */
// 	public String[] getAliasUrls() {
// 		return aliasUrls;
// 	}
// 
// 	/**
// 	 * @return the type of this web content.
// 	 */
// 	public abstract Type getType();
// 
// 	/**
// 	 * @return the keywords of this web content.
// 	 */
// 	public Set<String> getKeywords() {
// 		return keywords;
// 	}
// 
// 	/**
// 	 * @param keywords
// 	 *            the keywords to set
// 	 */
// 	public void setKeywords(Set<String> keywords) {
// 		this.keywords = keywords;
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		return Objects.hashCode(url, getType());
// 	}
// 
// 	@Override
// 	public boolean equals(Object obj) {
// 		if (obj == null || !(obj instanceof WebContent)) {
// 			return false;
// 		}
// 		WebContent that = (WebContent) obj;
// 		return Objects.equal(this.url, that.url) && Objects.equal(this.getType(), that.getType())
// 				&& Arrays.equals(this.aliasUrls, that.aliasUrls) && Objects.equal(this.keywords, that.keywords);
// 	}
// 
// 	protected ToStringHelper toStringHelper(Object instance) {
// 		return Objects.toStringHelper(this).omitNullValues().add("url", url)
// 				.add("aliasUrls", Arrays.toString(aliasUrls)).add("keywords", keywords);
// 	}
// 
// }
// 
// Path: src/main/java/com/lumata/lib/lupa/extractor/ContentExtractor.java
// public interface ContentExtractor<E extends WebContent> {
// 
// 	E extractContent(ReadableResource resource, ServiceLocator serviceLocator) throws IOException;
// 
// 	void setConfiguration(Map<String, String> config);
// 
// 	Class<E> getExtractableWebContentType();
// 
// }


import java.util.Map;
import org.apache.commons.collections.MapUtils;
import com.google.common.base.Objects;
import com.google.common.net.MediaType;
import com.lumata.lib.lupa.ReadableResource;
import com.lumata.lib.lupa.content.WebContent;
import com.lumata.lib.lupa.extractor.ContentExtractor;
/**
 * Copyright (c) 2013 Lumata
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.lumata.lib.lupa.extractor.internal;




class ContentExtractorMatcher<E extends WebContent> implements
		Comparable<ContentExtractorMatcher<? extends WebContent>> {

	private final ContentExtractor<E> contentExtractor;
	Map<String, String> constraints;
	int priority;
	static final String CONTENT_TYPE = "type";
	static final String URL = "url";

	ContentExtractorMatcher(ContentExtractor<E> contentExtractor, Map<String, String> constraints, int priority) {
		this.contentExtractor = contentExtractor;
		this.constraints = constraints;
		this.priority = priority;
	}

	/**
	 * @return the contentExtractor
	 */
	public ContentExtractor<E> getContentExtractor() {
		return contentExtractor;
	}

	public boolean isCaplableOfExtracting(Class<? extends WebContent> webContentType) {
		return contentExtractor.getExtractableWebContentType().isAssignableFrom(webContentType);
	}

// Path: src/main/java/com/lumata/lib/lupa/ReadableResource.java
// public interface ReadableResource {
// 
// 	URL getUrl();
// 
// 	/**
// 	 * Move the current URL to the redirection path and set the specified url as the actual resource url.
// 	 * 
// 	 * @param url
// 	 *            the redirectionUrl
// 	 */
// 	void makeRedirection(URL url);
// 
// 	Optional<URL[]> getRedirectionPath();
// 
// 	Optional<MediaType> getContentType();
// 
// 	InputStream read() throws IOException;
// 
// 	void discard();
// }
// 
// Path: src/main/java/com/lumata/lib/lupa/content/WebContent.java
// public abstract class WebContent {
// 
// 	public static enum Type {
// 		WEBPAGE,
// 		IMAGE,
// 		VIDEO,
// 		AUDIO,
// 		FEED
// 	}
// 
// 	private final String url;
// 	private final String[] aliasUrls;
// 	private Set<String> keywords;
// 
// 	WebContent(String url, String... aliasUrls) {
// 		this.url = url;
// 		this.aliasUrls = aliasUrls;
// 	}
// 
// 	/**
// 	 * Gets the preferred URL of this content
// 	 * 
// 	 * @return the url
// 	 */
// 	public String getUrl() {
// 		return url;
// 	}
// 
// 	/**
// 	 * Gets the known alias URLs where this content can be also located. The order is defined by the redirection path.
// 	 * 
// 	 * @return the referingUrls
// 	 */
// 	public String[] getAliasUrls() {
// 		return aliasUrls;
// 	}
// 
// 	/**
// 	 * @return the type of this web content.
// 	 */
// 	public abstract Type getType();
// 
// 	/**
// 	 * @return the keywords of this web content.
// 	 */
// 	public Set<String> getKeywords() {
// 		return keywords;
// 	}
// 
// 	/**
// 	 * @param keywords
// 	 *            the keywords to set
// 	 */
// 	public void setKeywords(Set<String> keywords) {
// 		this.keywords = keywords;
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		return Objects.hashCode(url, getType());
// 	}
// 
// 	@Override
// 	public boolean equals(Object obj) {
// 		if (obj == null || !(obj instanceof WebContent)) {
// 			return false;
// 		}
// 		WebContent that = (WebContent) obj;
// 		return Objects.equal(this.url, that.url) && Objects.equal(this.getType(), that.getType())
// 				&& Arrays.equals(this.aliasUrls, that.aliasUrls) && Objects.equal(this.keywords, that.keywords);
// 	}
// 
// 	protected ToStringHelper toStringHelper(Object instance) {
// 		return Objects.toStringHelper(this).omitNullValues().add("url", url)
// 				.add("aliasUrls", Arrays.toString(aliasUrls)).add("keywords", keywords);
// 	}
// 
// }
// 
// Path: src/main/java/com/lumata/lib/lupa/extractor/ContentExtractor.java
// public interface ContentExtractor<E extends WebContent> {
// 
// 	E extractContent(ReadableResource resource, ServiceLocator serviceLocator) throws IOException;
// 
// 	void setConfiguration(Map<String, String> config);
// 
// 	Class<E> getExtractableWebContentType();
// 
// }


// Path: src/main/java/com/lumata/lib/lupa/extractor/internal/ContentExtractorMatcher.java
import java.util.Map;
import org.apache.commons.collections.MapUtils;
import com.google.common.base.Objects;
import com.google.common.net.MediaType;
import com.lumata.lib.lupa.ReadableResource;
import com.lumata.lib.lupa.content.WebContent;
import com.lumata.lib.lupa.extractor.ContentExtractor;

/**
 * Copyright (c) 2013 Lumata
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.lumata.lib.lupa.extractor.internal;




class ContentExtractorMatcher<E extends WebContent> implements
		Comparable<ContentExtractorMatcher<? extends WebContent>> {

	private final ContentExtractor<E> contentExtractor;
	Map<String, String> constraints;
	int priority;
	static final String CONTENT_TYPE = "type";
	static final String URL = "url";

	ContentExtractorMatcher(ContentExtractor<E> contentExtractor, Map<String, String> constraints, int priority) {
		this.contentExtractor = contentExtractor;
		this.constraints = constraints;
		this.priority = priority;
	}

	/**
	 * @return the contentExtractor
	 */
	public ContentExtractor<E> getContentExtractor() {
		return contentExtractor;
	}

	public boolean isCaplableOfExtracting(Class<? extends WebContent> webContentType) {
		return contentExtractor.getExtractableWebContentType().isAssignableFrom(webContentType);
	}

	boolean matches(ReadableResource res) {