package annis.sqlgen;
import annis.model.QueryNode;
import annis.ql.parser.QueryData;
import annis.service.objects.SubgraphFilter;
import static annis.sqlgen.AbstractSqlGenerator.TABSTOP;
import static annis.sqlgen.TableAccessStrategy.COMPONENT_TABLE;
import static annis.sqlgen.TableAccessStrategy.CORPUS_TABLE;
import static annis.sqlgen.TableAccessStrategy.EDGE_ANNOTATION_TABLE;
import static annis.sqlgen.TableAccessStrategy.NODE_ANNOTATION_TABLE;
import static annis.sqlgen.TableAccessStrategy.NODE_TABLE;
import static annis.sqlgen.TableAccessStrategy.RANK_TABLE;
import annis.sqlgen.extensions.AnnotateQueryData;
import annis.sqlgen.extensions.LimitOffsetQueryData;
import static annis.test.TestUtils.uniqueAlphaString;
import static annis.test.TestUtils.uniqueInt;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import static java.util.Arrays.asList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import org.mockito.Mock;
import static org.mockito.MockitoAnnotations.initMocks;
import org.springframework.dao.DataAccessException;
public class TestAnnotateSqlGenerator
{
private class DummyAnnotateSqlGenerator extends AnnotateSqlGenerator<Integer> {
@Override
public Integer extractData(ResultSet arg0) throws SQLException,
DataAccessException
{
throw new UnsupportedOperationException();
}
@Override
public String selectClause(QueryData queryData,
List<QueryNode> alternative, String indent)
{
throw new UnsupportedOperationException();
}
@Override
public String fromClause(QueryData queryData,
List<QueryNode> alternative, String indent)
{
throw new UnsupportedOperationException();
}
@Override
public String getDocumentQuery(long toplevelCorpusID,
String documentName, List<String> nodeAnnoFilter)
{
throw new UnsupportedOperationException();
}
};
// class under test
private DummyAnnotateSqlGenerator generator = new DummyAnnotateSqlGenerator() {
protected TableAccessStrategy createTableAccessStrategy() {
return tableAccessStrategy;
};
protected SolutionKey<?> createSolutionKey() {
return solutionKey;
};
};
// dependencies
@Mock private TableAccessStrategy tableAccessStrategy;
@Mock private SolutionKey<?> solutionKey;
// test data
@Mock private QueryData queryData;
@Mock private AnnotateQueryData annotateQueryData;
@Mock private LimitOffsetQueryData limitOffsetQueryData;
private List<QueryNode> alternative = new ArrayList<>();
private static final String INDENT = TABSTOP;
@Before
public void setup()
{
initMocks(this);
given(queryData.getExtensions(AnnotateQueryData.class)).willReturn(asList(annotateQueryData));
setupOuterQueryFactsTableColumnAliases(generator);
}
public static void setupOuterQueryFactsTableColumnAliases(AnnotateExtractor<?> generator) {
Map<String, String> nodeColumns = new HashMap<>();
nodeColumns.put("namespace", "node_namespace");
nodeColumns.put("name", "node_name");
Map<String, String> nodeAnnotationColumns = new HashMap<>();
nodeAnnotationColumns.put("node_ref", "id");
nodeAnnotationColumns.put("namespace", "node_annotation_namespace");
nodeAnnotationColumns.put("name", "node_annotation_name");
nodeAnnotationColumns.put("value", "node_annotation_value");
Map<String, String> edgeAnnotationColumns = new HashMap<>();
nodeAnnotationColumns.put("rank_ref", "pre");
edgeAnnotationColumns.put("namespace", "edge_annotation_namespace");
edgeAnnotationColumns.put("name", "edge_annotation_name");
edgeAnnotationColumns.put("value", "edge_annotation_value");
Map<String, String> edgeColumns = new HashMap<>();
edgeColumns.put("node_ref", "id");
edgeColumns.put("id", "rank_id");
Map<String, String> componentColumns = new HashMap<>();
componentColumns.put("id", "component_id");
componentColumns.put("name", "edge_name");
componentColumns.put("namespace", "edge_namespace");
componentColumns.put("type", "edge_type");
edgeColumns.put("name", "edge_name");
edgeColumns.put("namespace", "edge_namespace");
Map<String, Map<String, String>> columnAliases =
new HashMap<>();
columnAliases.put(TableAccessStrategy.NODE_TABLE, nodeColumns);
columnAliases.put(TableAccessStrategy.NODE_ANNOTATION_TABLE,
nodeAnnotationColumns);
columnAliases.put(TableAccessStrategy.EDGE_ANNOTATION_TABLE,
edgeAnnotationColumns);
columnAliases.put(TableAccessStrategy.RANK_TABLE, edgeColumns);
columnAliases.put(TableAccessStrategy.COMPONENT_TABLE, componentColumns);
TableAccessStrategy outerQueryTableAccessStrategy = new TableAccessStrategy();
outerQueryTableAccessStrategy.setColumnAliases(columnAliases);
generator.setOuterQueryTableAccessStrategy(outerQueryTableAccessStrategy);
}
/**
* It is the responsibility of the code that uses this class to make sure
* that a fresh key management instance is generated when necessary.
*/
@Test(expected=UnsupportedOperationException.class)
public void shouldBailIfGetAnnisKeyMethodIsNotOverwritten()
{
// given
generator = new DummyAnnotateSqlGenerator();
// when
generator.createSolutionKey();
}
/**
* The result should be ordered by the solution key and the pre value of the node
*/
@Test
public void shouldOrderByKeyComponentAndPreValue()
{
// given
String edgeNameAlias = createColumnAlias(COMPONENT_TABLE, "name");
String preAlias = createColumnAlias(RANK_TABLE, "pre");
String idAlias = createColumnAlias(COMPONENT_TABLE, "id");
// when
String actual = generator.orderByClause(queryData, alternative, INDENT);
// then
String expected = "solutions.n, " + edgeNameAlias + ", " + idAlias + ", " + preAlias;
assertThat(actual, is(expected));
}
@Test
public void shouldAddIsTokenOnFilter()
{
given(annotateQueryData.getFilter()).willReturn(SubgraphFilter.token);
String isTokenAlias = createColumnAlias(NODE_TABLE, "is_token");
String expected = isTokenAlias + " IS TRUE";
Set<String> actualConditions = generator.whereConditions(queryData, alternative, "");
assertTrue("WHERE conditions must include \"" + expected + "\"", actualConditions.contains(expected));
}
// set up a column alias of the form "table.column"
private String createColumnAlias(String table, String column)
{
String columnAlias = table + "." + column;
given(tableAccessStrategy.aliasedColumn(table, column)).willReturn(columnAlias);
return columnAlias;
}
}