/*
* #!
* Ontopia Engine
* #-
* Copyright (C) 2001 - 2013 The Ontopia Project
* #-
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* !#
*/
package net.ontopia.topicmaps.query.core;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.net.MalformedURLException;
import junit.framework.TestCase;
import net.ontopia.utils.OntopiaRuntimeException;
import net.ontopia.infoset.core.LocatorIF;
import net.ontopia.infoset.fulltext.impl.basic.DummyFulltextSearcherIF;
import net.ontopia.infoset.impl.basic.URILocator;
import net.ontopia.topicmaps.core.TMObjectIF;
import net.ontopia.topicmaps.core.TopicIF;
import net.ontopia.topicmaps.core.TopicMapBuilderIF;
import net.ontopia.topicmaps.core.TopicMapIF;
import net.ontopia.topicmaps.core.TopicMapImporterIF;
import net.ontopia.topicmaps.impl.basic.InMemoryTopicMapStore;
import net.ontopia.topicmaps.query.impl.basic.QueryProcessor;
import net.ontopia.topicmaps.query.utils.QueryUtils;
import net.ontopia.topicmaps.xml.XTMTopicMapReader;
import net.ontopia.topicmaps.utils.ImportExportUtils;
import net.ontopia.utils.TestFileUtils;
import net.ontopia.utils.URIUtils;
public abstract class AbstractQueryTest extends TestCase {
private final static String testdataDirectory = "query";
protected static final String OPT_TYPECHECK_OFF =
"/* #OPTION: compiler.typecheck = false */ ";
public LocatorIF base;
public TopicMapIF topicmap;
public TopicMapBuilderIF builder;
public QueryProcessorIF processor;
public AbstractQueryTest(String name) {
super(name);
}
// ===== Helper methods (topic maps)
protected TopicIF getTopicBySI(String uri) throws MalformedURLException {
return topicmap.getTopicBySubjectIdentifier(new URILocator(uri));
}
protected TopicIF getTopicById(String id) {
return (TopicIF) topicmap.getObjectByItemIdentifier(base.resolveAbsolute("#"+id));
}
protected TMObjectIF getObjectById(String id) {
return topicmap.getObjectByItemIdentifier(base.resolveAbsolute("#"+id));
}
protected void closeStore() {
if (topicmap != null)
topicmap.getStore().close();
base = null;
topicmap = null;
builder = null;
processor = null;
}
protected void load(String filename) throws IOException {
load(filename, false);
}
protected void load(String filename, boolean fulltext) throws IOException {
// IMPORTANT: This method is being overloaded by the RDBMS
// implementation to provide the right object implementations.
filename = TestFileUtils.getTestInputFile(testdataDirectory, filename);
File indexDirectory = null;
if (fulltext) {
indexDirectory = TestFileUtils.getTestOutputFile("indexes", filename.substring(filename.lastIndexOf("/")));
indexDirectory.mkdirs();
}
InMemoryTopicMapStore store = new InMemoryTopicMapStore();
topicmap = store.getTopicMap();
builder = store.getTopicMap().getBuilder();
base = URIUtils.getURI(filename);
TopicMapImporterIF importer = ImportExportUtils.getImporter(filename);
if (importer instanceof XTMTopicMapReader)
((XTMTopicMapReader) importer).setValidation(false);
importer.importInto(topicmap);
if (fulltext) {
new DummyFulltextSearcherIF(store);
}
processor = new QueryProcessor(topicmap, base);
}
protected void makeEmpty() {
makeEmpty(true);
}
protected void makeEmpty(boolean setbase) {
// IMPORTANT: This method is being overloaded by the RDBMS
// implementation to provide the right object implementations.
InMemoryTopicMapStore store = new InMemoryTopicMapStore();
if (setbase) {
try {
base = new URILocator("http://example.com");
store.setBaseAddress(base);
} catch (MalformedURLException e) {
throw new OntopiaRuntimeException(e);
}
}
topicmap = store.getTopicMap();
builder = store.getTopicMap().getBuilder();
processor = new QueryProcessor(topicmap);
}
// ===== Helper methods (query)
public void addMatch(List matches) {
Map match = new HashMap();
matches.add(match);
}
public void addMatch(List matches, String var1, Object obj1) {
Map match = new HashMap();
match.put(var1, obj1);
matches.add(match);
}
public void addMatch(List matches, String var1, Object obj1,
String var2, Object obj2) {
Map match = new HashMap();
match.put(var1, obj1);
match.put(var2, obj2);
matches.add(match);
}
public void addMatch(List matches, String var1, Object obj1,
String var2, Object obj2,
String var3, Object obj3) {
Map match = new HashMap();
match.put(var1, obj1);
match.put(var2, obj2);
match.put(var3, obj3);
matches.add(match);
}
public void addMatch(List matches, String var1, Object obj1,
String var2, Object obj2,
String var3, Object obj3,
String var4, Object obj4) {
Map match = new HashMap();
match.put(var1, obj1);
match.put(var2, obj2);
match.put(var3, obj3);
match.put(var4, obj4);
matches.add(match);
}
/**
* Tests whether the given query returns a single row with no columns,
* i.e. a query match with no unbound variables.
* @param query The query to test.
*/
protected void verifyQuery(String query) throws InvalidQueryException {
// verify that we do not get any parse or query errors
QueryResultIF result = processor.execute(query);
try {
assertTrue(result.next());
assertEquals(0, result.getWidth());
assertFalse(result.next());
} finally {
result.close();
}
}
protected void verifyQuery(List matches, String query)
throws InvalidQueryException {
verifyQuery(matches, query, null, null);
}
protected void verifyQuery(List matches, String query, Map args)
throws InvalidQueryException {
verifyQuery(matches, query, null, args);
}
protected void verifyQuery(List matches, String query, String ruleset)
throws InvalidQueryException {
verifyQuery(matches, query, ruleset, null);
}
protected void verifyQuery(List matches, String query, String ruleset, Map args)
throws InvalidQueryException {
matches = new ArrayList(matches); // avoid modifying caller's list
if (ruleset != null)
processor.load(ruleset);
QueryResultIF result = null;
if (args != null)
result = processor.parse(query).execute(args);
else
result = processor.execute(query);
//! System.out.println("____QUERY: " + query);
//! System.out.println(" MATCHES: " + matches);
//! int i=0;
try {
while (result.next()) {
//! i++;
//! System.out.println(" ROW " + i + ": " + Arrays.asList(result.getValues()));
Map match = getMatch(result);
assertTrue("match not found in expected results: " + match + " => " + matches,
matches.contains(match));
matches.remove(match);
//! System.out.println("____removing: " + match);
}
} finally {
result.close();
}
assertTrue("expected matches not found: " + matches,
matches.isEmpty());
}
protected void verifyQuerySubset(List matches, String query)
throws InvalidQueryException {
verifyQuerySubset(matches, query, null, null);
}
protected void verifyQuerySubset(List matches, String query, Map args)
throws InvalidQueryException {
verifyQuerySubset(matches, query, null, args);
}
protected void verifyQuerySubset(List matches, String query, String ruleset)
throws InvalidQueryException {
verifyQuerySubset(matches, query, ruleset, null);
}
protected void verifyQuerySubset(List matches, String query, String ruleset, Map args)
throws InvalidQueryException {
matches = new ArrayList(matches); // avoid modifying caller's list
if (ruleset != null)
processor.load(ruleset);
QueryResultIF result = null;
if (args != null)
result = processor.parse(query).execute(args);
else
result = processor.execute(query);
//! System.out.println("____QUERY: " + query);
//! System.out.println(" MATCHES: " + matches);
//! int i=0;
try {
while (result.next()) {
//! i++;
//! System.out.println(" ROW " + i + ": " + Arrays.asList(result.getValues()));
Map match = getMatch(result);
matches.remove(match);
//! System.out.println("____removing: " + match);
}
} finally {
result.close();
}
assertTrue("expected matches not found: " + matches,
matches.isEmpty());
}
protected void verifyQueryPre(List matches, String decls, String query)
throws InvalidQueryException {
// parse the declarations
DeclarationContextIF context = QueryUtils.parseDeclarations(topicmap, decls);
// run the query
QueryResultIF result = processor.execute(query, context);
//! System.out.println("____QUERY: " + query);
//! System.out.println(" MATCHES: " + matches);
//! int i=0;
try {
while (result.next()) {
//! i++;
//! System.out.println(" ROW " + i + ": " + Arrays.asList(result.getValues()));
Map match = getMatch(result);
assertTrue("match not found in expected results: " + match + " => " + matches,
matches.contains(match));
matches.remove(match);
//! System.out.println("____removing: " + match);
}
} finally {
result.close();
}
assertTrue("expected matches not found: " + matches,
matches.isEmpty());
}
protected void verifyQueryOrder(List matches, String query)
throws InvalidQueryException {
int pos = 0;
QueryResultIF result = processor.execute(query);
try {
while (result.next()) {
if (matches.size() <= pos)
fail("too many rows in query result");
Map match = getMatch(result);
assertTrue("match not found in position " + pos + ": " + match + " => " + matches.get(pos),
matches.get(pos).equals(match));
pos++;
}
} finally {
result.close();
}
assertTrue("bad number of matches returned: " + pos,
matches.size() == pos);
}
protected void findAny(String query) throws InvalidQueryException {
// verify that we do not get any parse or query errors
QueryResultIF result = processor.execute(query);
try {
while (result.next()) {
// just loop over rows for the sake of it
}
} finally {
result.close();
}
}
protected void findNothing(String query) throws InvalidQueryException {
QueryResultIF result = processor.execute(query);
try {
assertTrue("found values, but shouldn't have",
!result.next());
} finally {
result.close();
}
}
protected void findNothing(String query, Map args) throws InvalidQueryException {
QueryResultIF result = processor.execute(query, args);
try {
assertTrue("found values, but shouldn't have",
!result.next());
} finally {
result.close();
}
}
public DeclarationContextIF parseContext(String decls)
throws InvalidQueryException {
return QueryUtils.parseDeclarations(topicmap, decls);
}
public int update(String query) throws InvalidQueryException {
return processor.update(query);
}
public int update(String query, DeclarationContextIF context)
throws InvalidQueryException {
return processor.update(query, null, context);
}
public int update(String query, Map params) throws InvalidQueryException {
return processor.update(query, params);
}
public int update(String query, Map params, DeclarationContextIF context)
throws InvalidQueryException {
return processor.update(query, params, context);
}
public void updateError(String query) throws InvalidQueryException {
try {
update(query);
fail("No error from query");
} catch (InvalidQueryException e) {
// as expected
}
}
protected void getParseError(String query) {
getParseError(query, Collections.EMPTY_MAP);
}
protected void getParseError(String query, Map parameters) {
QueryResultIF result = null;
try {
result = processor.execute(query, parameters);
fail("query '" + query + "' parsed OK, but shouldn't have");
} catch (InvalidQueryException e) {
} finally {
if (result != null) result.close();
}
}
public ParsedQueryIF parse(String query) throws InvalidQueryException {
return processor.parse(query);
}
public Map getMatch(QueryResultIF result) {
Map match = new HashMap();
for (int ix = 0; ix < result.getWidth(); ix++) {
String vname = result.getColumnName(ix);
match.put(vname, result.getValue(ix));
}
return match;
}
public Set getMatchSet(QueryResultIF result) {
Set match = new HashSet();
for (int ix = 0; ix < result.getWidth(); ix++)
match.add(result.getValue(ix));
return match;
}
public Map makeArguments(String argument, String value) {
Map args = new HashMap();
args.put(argument, getTopicById(value));
return args;
}
public Map makeArguments(String argument, TMObjectIF value) {
Map args = new HashMap();
args.put(argument, value);
return args;
}
// --- test to check if query processor implementation is rdbms
public boolean isRDBMSTolog() {
return processor.getClass().getName().equals("net.ontopia.topicmaps.query.impl.rdbms.QueryProcessor");
}
public boolean isInMemoryTolog() {
return processor.getClass().getName().equals("net.ontopia.topicmaps.query.impl.basic.QueryProcessor");
}
}