/* * #! * 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.impl.rdbms; import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.Map; import net.ontopia.infoset.core.LocatorIF; import net.ontopia.infoset.impl.basic.URILocator; import net.ontopia.persistence.proxy.RDBMSStorage; import net.ontopia.persistence.proxy.StorageIF; import net.ontopia.topicmaps.core.AbstractTopicMapTest; import net.ontopia.topicmaps.core.AssociationIF; import net.ontopia.topicmaps.core.AssociationRoleIF; 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.core.TopicMapStoreIF; import net.ontopia.topicmaps.entry.TopicMapReferenceIF; import net.ontopia.topicmaps.query.utils.QueryUtils; import net.ontopia.topicmaps.query.core.QueryProcessorIF; import net.ontopia.topicmaps.query.core.QueryResultIF; import net.ontopia.topicmaps.query.core.InvalidQueryException; import net.ontopia.topicmaps.utils.ImportExportUtils; import net.ontopia.utils.OntopiaRuntimeException; import net.ontopia.utils.FileUtils; import net.ontopia.utils.TestFileUtils; import net.ontopia.utils.URIUtils; import junit.framework.TestCase; /** * INTERNAL: Tests that tests the prefetching code used with the * RDBMS Backend Connector and the in-memory tolog implementation. */ public class PrefetcherTests extends TestCase { private final static String testdataDirectory = "various"; public PrefetcherTests(String name) { super(name); } public void setUp() throws Exception { RDBMSTestFactory.checkDatabasePresence(); super.setUp(); } protected TopicIF getTopic(TopicMapIF tm, String psi) { try { return tm.getTopicBySubjectIdentifier(new URILocator(psi)); } catch (java.net.MalformedURLException e) { throw new OntopiaRuntimeException(e); } } protected long importTopicMap(String filename) throws IOException { // import sample topic map TopicMapStoreIF store = new RDBMSTopicMapStore(); // don't use storage TopicMapImporterIF importer = ImportExportUtils.getImporter(filename); importer.importInto(store.getTopicMap()); long topicmap_id = Long.parseLong(store.getTopicMap().getObjectId().substring(1)); store.commit(); store.close(); return topicmap_id; } protected TopicMapReferenceIF createReference(String id, String title, StorageIF storage, long topicmap_id, LocatorIF base_address) { RDBMSTopicMapSource source = new RDBMSTopicMapSource(); // create empty source just for supports methods source.setPropertyFile(System.getProperty("net.ontopia.topicmaps.impl.rdbms.PropertyFile")); source.setSupportsCreate(true); source.setSupportsDelete(true); RDBMSTopicMapReference ref = new RDBMSTopicMapReference(id, title, storage, topicmap_id, base_address); ref.setSource(source); return ref; } /** * INTERNAL: */ public void testAssociationPrefetching() throws IOException { // Test will add one association and one occurrence // verify that shared cache is enabled StorageIF storage = new RDBMSStorage(); if (!storage.isSharedCache()) { System.out.println("Shared cache disabled (skipping test)."); return; } // import topic map String filename = TestFileUtils.getTestInputFile(testdataDirectory, "prefetch.ltm"); LocatorIF base = URIUtils.getURI(filename); // create reference long topicmap_id = importTopicMap(filename); TopicMapReferenceIF ref = createReference("gcache", "Prefetcher test", storage, topicmap_id, null); try { TopicMapStoreIF store1 = ref.createStore(false); TopicMapStoreIF store2 = ref.createStore(false); TopicMapStoreIF store3 = ref.createStore(false); TopicMapIF tm1 = store1.getTopicMap(); // changing this one TopicMapIF tm2 = store2.getTopicMap(); TopicMapIF tm3 = store3.getTopicMap(); TopicMapBuilderIF b1 = tm1.getBuilder(); TopicMapBuilderIF b2 = tm2.getBuilder(); TopicMapBuilderIF b3 = tm3.getBuilder(); // add topics to #1 TopicIF at1 = getTopic(tm1, "test:har_sprak"); TopicIF rtA1 = getTopic(tm1, "test:objekt"); TopicIF rtB1 = getTopic(tm1, "test:feltverdi"); TopicIF rpA1 = b1.makeTopic(); String rpA_id = rpA1.getObjectId(); TopicIF rpB1 = b1.makeTopic(); String rpB_id = rpB1.getObjectId(); // run query in #1 Map props1 = Collections.singletonMap("net.ontopia.topicmaps.query.core.QueryProcessorIF", "in-memory"); QueryProcessorIF qp1 = QueryUtils.createQueryProcessor(tm1, base, props1); try { //! QueryResultIF qr1 = qp1.parse("select $SPRAK from har_sprak(%DOC% : objekt, $SPRAK : feltverdi)?").execute(Collections.singletonMap("DOC", rpA1)); QueryResultIF qr1 = qp1.parse("/* #OPTION: optimizer.reorder = false */ select $SPRAK from role-player($R1, %DOC%), association-role($A, $R1), type($A, har_sprak), association-role($A, $R2), role-player($R2, $SPRAK), $R1 /= $R2 order by $SPRAK?").execute(Collections.singletonMap("DOC", rpA1)); if (qr1.next()) { fail("Query returned no rows."); } } catch (InvalidQueryException e) { throw new OntopiaRuntimeException(e); } // add association to #1 AssociationIF a1 = b1.makeAssociation(at1); AssociationRoleIF rA1 = b1.makeAssociationRole(a1, rtA1, rpA1); AssociationRoleIF rB1 = b1.makeAssociationRole(a1, rtB1, rpB1); // run query in #1 try { //! QueryResultIF qr1 = qp1.parse("/* #OPTION: optimizer.reorder = false */ select $SPRAK from har_sprak(%DOC% : objekt, $SPRAK : feltverdi)?").execute(Collections.singletonMap("DOC", rpA1)); QueryResultIF qr1 = qp1.parse("/* #OPTION: optimizer.reorder = false */ select $SPRAK from role-player($R1, %DOC%), association-role($A, $R1), type($A, har_sprak), association-role($A, $R2), role-player($R2, $SPRAK), $R1 /= $R2 order by $SPRAK?").execute(Collections.singletonMap("DOC", rpA1)); if (qr1.next()) { TopicIF rvB = (TopicIF)qr1.getValue(0); assertTrue("rvB.id != rpB.id", rpB_id.equals(rvB.getObjectId())); assertTrue("rvB.roles.size != 1", rvB.getRoles().size() == 1); } else { fail("Query returned no rows."); } } catch (InvalidQueryException e) { throw new OntopiaRuntimeException(e); } // commit #1 store1.commit(); // run query in #2 Map props2 = Collections.singletonMap("net.ontopia.topicmaps.query.core.QueryProcessorIF", "in-memory"); QueryProcessorIF qp2 = QueryUtils.createQueryProcessor(tm2, base, props2); try { TopicIF rpA2 = (TopicIF)tm2.getObjectById(rpA_id); //! QueryResultIF qr2 = qp2.parse("/* #OPTION: optimizer.reorder = false */ select $SPRAK from har_sprak(%DOC% : objekt, $SPRAK : feltverdi)?").execute(Collections.singletonMap("DOC", rpA2)); // QueryResultIF qr2 = qp2.execute("select $SPRAK from har_sprak(@" + rpA_id + " : objekt, $SPRAK : feltverdi)?"); QueryResultIF qr2 = qp2.parse("/* #OPTION: optimizer.reorder = false */ select $SPRAK from role-player($R1, %DOC%), association-role($A, $R1), type($A, har_sprak), association-role($A, $R2), role-player($R2, $SPRAK), $R1 /= $R2 order by $SPRAK?").execute(Collections.singletonMap("DOC", rpA2)); if (qr2.next()) { TopicIF rvB = (TopicIF)qr2.getValue(0); assertTrue("rvB.id != rpB.id", rpB_id.equals(rvB.getObjectId())); assertTrue("rvB.roles.size != 1", rvB.getRoles().size() == 1); } else { fail("Query returned no rows."); } } catch (InvalidQueryException e) { throw new OntopiaRuntimeException(e); } // look up topics in #3 TopicIF rpA3 = (TopicIF)tm3.getObjectById(rpA_id); TopicIF rpB3 = (TopicIF)tm3.getObjectById(rpB_id); assertTrue("rvA.roles.size != 1", rpA3.getRoles().size() == 1); assertTrue("rvB.roles.size != 1", rpB3.getRoles().size() == 1); assertTrue("rvA.roles.association.roles.size != 2", ((AssociationRoleIF)rpA3.getRoles().iterator().next()).getAssociation().getRoles().size() == 2); assertTrue("rvB.roles.association.roles.size != 2", ((AssociationRoleIF)rpB3.getRoles().iterator().next()).getAssociation().getRoles().size() == 2); store1.close(); store2.close(); store3.close(); } finally { ref.delete(); } } }