/* * #! * 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.infoset.fulltext.impl.lucene; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import junit.framework.TestCase; import net.ontopia.infoset.core.LocatorIF; import net.ontopia.infoset.fulltext.core.DocumentIF; import net.ontopia.infoset.fulltext.core.SearchResultIF; import net.ontopia.infoset.fulltext.core.SearcherIF; import net.ontopia.infoset.impl.basic.URILocator; import net.ontopia.topicmaps.core.OccurrenceIF; 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.TopicMapStoreIF; import net.ontopia.topicmaps.core.TopicNameIF; import net.ontopia.topicmaps.core.VariantNameIF; import net.ontopia.topicmaps.entry.StoreFactoryReference; import net.ontopia.topicmaps.impl.basic.InMemoryTopicMapStore; import net.ontopia.topicmaps.utils.SameStoreFactory; import net.ontopia.utils.TestFileUtils; public class LuceneTests extends TestCase { protected TopicMapIF topicmap; // topic map of object being tested protected TopicMapBuilderIF builder; // builder used for creating new objects protected String indexDir; protected SearcherIF searcher; private LuceneFulltextImplementation implementation; public LuceneTests(String name) { super(name); } @Override public void setUp() throws IOException { TopicMapStoreIF store = new InMemoryTopicMapStore(); StoreFactoryReference reference = new StoreFactoryReference("test", "test", new SameStoreFactory(store)); // manual installation of LuceneFulltextImplementation implementation = new LuceneFulltextImplementation(); implementation.install(reference); topicmap = store.getTopicMap(); builder = topicmap.getBuilder(); String root = TestFileUtils.getTestdataOutputDirectory(); indexDir = root + File.separator + "indexes" + File.separator; TestFileUtils.verifyDirectory(root, "indexes"); implementation.setDirectoryFile(new File(indexDir)); implementation.reindex(); implementation.storeOpened(store); searcher = implementation.getSearcher(); } @Override protected void tearDown() throws IOException { if (implementation != null) { implementation.close(); } } // ---- test cases public void testEmpty() throws IOException { index(); assertTrue("hits found in empty topic map", findNothing(topicmap, "stuff")); } public void testTopicName() throws IOException { TopicIF topic = builder.makeTopic(); TopicNameIF bn = builder.makeTopicName(topic, "bar"); index(); assertTrue("found non-existent base names in topic map", findNothing(topicmap, "foo")); SearchResultIF result = searcher.search("bar"); findSingle(result, bn, " bar"); result = searcher.search("bar AND class:B"); findSingle(result, bn, " in class:B"); assertTrue("found base names when searching for variant name", findNothing(topicmap, "bar AND class:V")); remove(bn); assertTrue("found removed base name", findNothing(topicmap, "bar")); } public void testTopicNameUnicode() throws IOException { TopicIF topic = builder.makeTopic(); String katakana = "\u30AB\u30BF\u30AB\u30CA"; TopicNameIF bn1 = builder.makeTopicName(topic, katakana); String norsk = "\u00E6\u00F8\u00E5\u00C6\u00D8\u00C5"; TopicNameIF bn2 = builder.makeTopicName(topic, norsk); index(); assertTrue("found non-existent base names in topic map", findNothing(topicmap, "foo")); SearchResultIF result = searcher.search(katakana); findSingle(result, bn1, " using Unicode characters"); result = searcher.search(katakana + " AND class:B"); findSingle(result, bn1, " in class:B using Unicode characters (katakana)"); result = searcher.search(norsk + " AND class:B"); findSingle(result, bn2, " in class:B using Unicode characters (norsk)"); assertTrue("found base names when searching for variant name", findNothing(topicmap, "bar AND class:V")); remove(bn1); remove(bn2); assertTrue("found removed base name", findNothing(topicmap, "bar")); } public void testVariantName() throws IOException { TopicIF topic = builder.makeTopic(); TopicNameIF bn = builder.makeTopicName(topic, "bar"); VariantNameIF vn = builder.makeVariantName(bn, "baz"); index(); assertTrue("found non-existent objects in topic map", findNothing(topicmap, "foo")); SearchResultIF result = searcher.search("baz"); findSingle(result, vn, ""); result = searcher.search("baz AND class:N"); findSingle(result, vn, " in class:N"); assertTrue("found variant names when searching for base name", findNothing(topicmap, "baz AND class:B")); remove(vn); assertTrue("found removed variant name", findNothing(topicmap, "baz")); } public void testVariantLocator() throws IOException { TopicIF topic = builder.makeTopic(); TopicNameIF bn = builder.makeTopicName(topic, "bar"); VariantNameIF vn = builder.makeVariantName(bn, makeLocator("http://www.ontopia.net")); index(); assertTrue("found non-existent objects in topic map", findNothing(topicmap, "foo")); SearchResultIF result = searcher.search("address:ontopia"); //SearchResultIF result = searcher.search("address:http://www.ontopia.net"); findSingle(result, vn, " with locator"); result = searcher.search("address:ontopia AND class:N"); findSingle(result, vn, " in class:N"); assertTrue("found variant names when searching for base name", findNothing(topicmap, "address:ontopia AND class:B")); remove(vn); assertTrue("found removed variant name", findNothing(topicmap, "address:ontopia")); } public void testOccurrence() throws IOException { TopicIF topic = builder.makeTopic(); TopicIF otype = builder.makeTopic(); OccurrenceIF occ = builder.makeOccurrence(topic, otype, "value"); index(); assertTrue("found non-existent objects in topic map", findNothing(topicmap, "foo")); SearchResultIF result = searcher.search("value"); findSingle(result, occ, " with inline value"); result = searcher.search("value AND class:O"); findSingle(result, occ, " in class:O"); assertTrue("found occurrences when searching for variant names", findNothing(topicmap, "value AND class:V")); remove(occ); assertTrue("found removed occurrence", findNothing(topicmap, "value")); } public void testOccurrenceLocator() throws IOException { TopicIF topic = builder.makeTopic(); TopicIF otype = builder.makeTopic(); OccurrenceIF occ = builder.makeOccurrence(topic, otype, makeLocator("http://www.ontopia.net")); index(); assertTrue("found non-existent objects in topic map", findNothing(topicmap, "foo")); SearchResultIF result = searcher.search("address:ontopia"); findSingle(result, occ, " with locator"); result = searcher.search("address:ontopia AND class:O"); findSingle(result, occ, " in class:O"); assertTrue("found occurrences when searching for variant names", findNothing(topicmap, "address:ontopia AND class:V")); remove(occ); assertTrue("found removed occurrence", findNothing(topicmap, "address:ontopia")); } public void testDeleteIndex() throws IOException { // Create a topic and an occurrence TopicIF topic = builder.makeTopic(); TopicIF otype = builder.makeTopic(); builder.makeOccurrence(topic, otype, makeLocator("http://www.ontopia.net")); index(); implementation.deleteIndex(); // Verify that index was deleted File idir = new File(indexDir); assertFalse("Index directory exists after LuceneIndexer.delete() was called.", idir.exists()); } // ---- utilities protected void index() throws IOException { implementation.synchronize(topicmap.getStore()); // reference is not AbstractOntopolyURLReference, so manual sync } protected void remove(TMObjectIF object) throws IOException { object.remove(); implementation.synchronize(topicmap.getStore()); // reference is not AbstractOntopolyURLReference, so manual sync } protected void findSingle(SearchResultIF result, TMObjectIF object, String m) throws IOException { assertTrue("wrong number of hits: " + result.hits() + m, result.hits() == 1); DocumentIF doc = result.getDocument(0); assertTrue("didn't find object" + m, doc.getField("object_id").getValue().equals(object.getObjectId())); } protected boolean findNothing(TopicMapIF topicmap, String query) throws IOException { SearchResultIF result = searcher.search(query); return result.hits() == 0; } protected LocatorIF makeLocator(String uri) { try { return new URILocator(uri); } catch (MalformedURLException e) { fail(e.toString()); return null; } } }