/*
* Carrot2 project.
*
* Copyright (C) 2002-2016, Dawid Weiss, Stanisław Osiński.
* All rights reserved.
*
* Refer to the full license file "carrot2.LICENSE"
* in the root folder of the repository checkout or at:
* http://www.carrot2.org/carrot2.LICENSE
*/
package org.carrot2.core.test;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import org.carrot2.core.Controller;
import org.carrot2.core.Document;
import org.carrot2.core.IDocumentSource;
import org.carrot2.core.ProcessingResult;
import org.carrot2.core.attribute.AttributeNames;
import org.carrot2.util.attribute.Bindable;
import org.carrot2.util.attribute.BindableMetadata;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
import org.carrot2.shaded.guava.common.base.Function;
import static org.junit.Assert.*;
/**
* Simple baseline tests that apply to a generic data sources.
*/
public abstract class DocumentSourceTestBase<T extends IDocumentSource> extends
ProcessingComponentTestBase<T>
{
/**
* Result of the last call to any of the {@link #runQuery()} methods.
*/
protected ProcessingResult result;
/**
* Processing components should be bindable, so their metadata should
* always be available.
*/
@Test
public void testMetadataAvailable()
{
Class<? extends IDocumentSource> c = getComponentClass();
Assume.assumeTrue(c.getAnnotation(Bindable.class) != null);
BindableMetadata metadata = BindableMetadata.forClassWithParents(c);
assertNotNull(metadata);
assertNotNull(metadata.getAttributeMetadata());
}
/**
* Runs a query without specifying any additional attributes. The query is run using
* a simple {@link Controller}.
*
* @return Returns the number of fetched documents. Access
* {@link #resultAttributes} map to get hold of the actual documents.
*/
protected int runQuery()
{
return runQuery(getSimpleController(initAttributes));
}
/**
* Runs a query without specifying any additional attributes. The query is run using
* a {@link Controller} with caching.
*
* @return Returns the number of fetched documents. Access
* {@link #resultAttributes} map to get hold of the actual documents.
*/
@SuppressWarnings("unchecked")
protected int runQueryInCachingController()
{
return runQuery(getCachingController(initAttributes));
}
/**
* Runs a query without specifying any additional attributes.
*
* @param controller the {@link Controller} to perform the query
* @return Returns the number of fetched documents. Access
* {@link #resultAttributes} map to get hold of the actual documents.
*/
@SuppressWarnings("unchecked")
protected int runQuery(Controller controller)
{
result = controller.process(processingAttributes, getComponentClass());
resultAttributes = result.getAttributes();
final List<Document> documents = (List<Document>) resultAttributes.get(AttributeNames.DOCUMENTS);
assertNotNull(result.getDocuments());
assertThat(result.getDocuments()).isEqualTo(documents);
return documents.size();
}
/**
* Runs a <code>query</code> and asks for <code>results</code> results. The query is
* run using a simple {@link Controller}.
*
* @return Returns the number of fetched documents. Access
* {@link #resultAttributes} map to get hold of the actual documents.
*/
protected final int runQuery(String query, int results)
{
if (query != null)
{
processingAttributes.put(AttributeNames.QUERY, query);
}
processingAttributes.put(AttributeNames.RESULTS, results);
return runQuery();
}
/**
* Checks if values of a given field in a collection of {@link Document}s are unique.
*/
protected final void assertFieldUnique(Collection<Document> result, String fieldName)
{
final HashMap<Object, Integer> values = new HashMap<Object, Integer>();
final StringBuilder builder = new StringBuilder();
int i = 0;
for (final Document d : result)
{
final Object key = d.getField(fieldName);
if (values.containsKey(key))
{
builder.append("Key: " + key + ", in docs: " + values.get(key) + ", " + i
+ "\n");
}
else
{
values.put(key, i);
}
i++;
}
if (builder.length() > 0)
{
Assert.fail("Field values are not unique, offending fields: \n"
+ builder.toString());
}
}
/**
* Transforms {@link Document}s to their individual fields.
*/
protected static class DocumentToFieldTransformer implements
Function<Document, Object>
{
/** Field name */
private final String fieldName;
/**
* Builds a transformer with the provided field name.
*/
public DocumentToFieldTransformer(String fieldName)
{
this.fieldName = fieldName;
}
public Object apply(Document document)
{
return document.getField(fieldName);
}
}
/**
* Transforms {@link Document}s to their titles.
*/
protected static final DocumentToFieldTransformer DOCUMENT_TO_TITLE = new DocumentToFieldTransformer(
Document.TITLE);
/**
* Transforms {@link Document}s to their summaries.
*/
protected static final DocumentToFieldTransformer DOCUMENT_TO_SUMMARY = new DocumentToFieldTransformer(
Document.SUMMARY);
/**
* Transforms {@link Document}s to their content URLs.
*/
protected static final DocumentToFieldTransformer DOCUMENT_TO_CONTENT_URL = new DocumentToFieldTransformer(
Document.CONTENT_URL);
}