package org.openbel.framework.test; import static java.sql.ResultSet.CONCUR_READ_ONLY; import static java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE; import static org.junit.Assert.*; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.openbel.framework.api.AnnotationFilterCriteria; import org.openbel.framework.api.BelDocumentFilterCriteria; import org.openbel.framework.api.CitationFilterCriteria; import org.openbel.framework.api.FilterCriteria; import org.openbel.framework.api.RelationshipTypeFilterCriteria; import org.openbel.framework.api.internal.KAMStoreDaoImpl; import org.openbel.framework.api.internal.KAMCatalogDao.KamFilter; import org.openbel.framework.api.internal.KAMCatalogDao.KamInfo; import org.openbel.framework.api.internal.KAMStoreDao.KamProtoNodesAndEdges; import org.openbel.framework.api.internal.KAMStoreDaoImpl.AnnotationDefinitionType; import org.openbel.framework.api.internal.KAMStoreDaoImpl.AnnotationType; import org.openbel.framework.api.internal.KAMStoreDaoImpl.Citation; import org.openbel.framework.api.internal.KAMStoreDaoImpl.KamProtoEdge; import org.openbel.framework.api.internal.KAMStoreDaoImpl.KamProtoNode; import org.openbel.framework.common.enums.CitationType; import org.openbel.framework.common.enums.RelationshipType; import org.openbel.framework.core.df.AbstractJdbcDAO; import org.openbel.framework.test.KAMFilterHelper; public class TestKAMStoreDaoImpl extends KAMStoreTest { private static KAMStoreDaoImpl dao = null; private static KAMFilterHelper kamFilterHelper; @Before public void setup() throws SQLException, NoSuchMethodException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { setupKamStore(Constants.SMALL_CORPUS_KAM_NAME); // Create an instance of the KAMStoreDaoImpl class to test. KamInfo kamInfo = testKam.getKamInfo(); dao = new KAMStoreDaoImpl(kamInfo.getKamDbObject().getSchemaName(), dbc); kamFilterHelper = new KAMFilterHelper(dao); reflectNecessaryCode(); } @After public void teardown() { teardownKamStore(); } @Test public void testGetKamWithAnnotationFilter() throws SQLException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { KamInfo kamInfo = testKam.getKamInfo(); KamFilter filter = kamInfo.createKamFilter(); AnnotationType[] types = new AnnotationType[] { annotationType.newInstance( 14, "HemicAndImmuneSystem", null, null, AnnotationDefinitionType.URL, "http://resource.belframework.org/belframework/1.0/annotation/mesh-hemic-and-immune-system.belanno"), annotationType.newInstance( 9, "UrogenitalSystem", null, null, AnnotationDefinitionType.URL, "http://resource.belframework.org/belframework/1.0/annotation/mesh-urogenital-system.belanno") }; AnnotationFilterCriteria ac1 = new AnnotationFilterCriteria(types[0]), ac2 = new AnnotationFilterCriteria(types[1]); ac1.add("Hematopoietic Stem Cells"); ac1.add("Blood"); ac1.add("Macrophages"); ac1.add("Monocytes"); ac2.add("Urinary Bladder"); ac1.setInclude(true); ac2.setInclude(false); filter.add(ac1); filter.add(ac2); testSameResultAsPreviousImplementation(filter); } @Test public void testGetKamWithOppositeFiltersReturnsNothing() throws SQLException { KamInfo kamInfo = testKam.getKamInfo(); KamFilter kamFilter = kamInfo.createKamFilter(); RelationshipTypeFilterCriteria c1 = new RelationshipTypeFilterCriteria(), c2 = new RelationshipTypeFilterCriteria(); c1.add(RelationshipType.INCREASES); c2.add(RelationshipType.DECREASES); kamFilter.add(c1); kamFilter.add(c2); KamProtoNodesAndEdges all = dao.getKamProtoNodesAndEdges(kamInfo, kamFilter); Map<Integer, KamProtoNode> nodes = all.getKamProtoNodes(); Map<Integer, KamProtoEdge> edges = all.getKamProtoEdges(); // The filtered KAM should contain nothing because opposite filters were applied. assertEquals(0, nodes.size()); assertEquals(0, edges.size()); } @Test public void testGetKamWithDuplicateFiltersIsIdempotent() throws SQLException { RelationshipTypeFilterCriteria c = new RelationshipTypeFilterCriteria(); c.add(RelationshipType.HAS_COMPONENT); testIdempotency(c); } @Test public void testGetKamIsCommutative() throws SQLException { RelationshipTypeFilterCriteria c1 = new RelationshipTypeFilterCriteria(), c2 = new RelationshipTypeFilterCriteria(); c1.add(RelationshipType.INCREASES); c2.add(RelationshipType.DECREASES); c2.setInclude(false); testCommutativity(c1, c2); } @Test public void testGetKamIsCorrect() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, SQLException, ParseException { KamFilter f = testKam.getKamInfo().createKamFilter(); RelationshipTypeFilterCriteria r = new RelationshipTypeFilterCriteria(); r.add(RelationshipType.ANALOGOUS); r.add(RelationshipType.INCLUDES); r.add(RelationshipType.INCREASES); r.setInclude(false); CitationFilterCriteria c = new CitationFilterCriteria(); Citation[] citations = new Citation[] { citation.newInstance( "Trends in molecular medicine", "12928037", "", null, Arrays.asList(StringUtils.split("de Nigris F|Lerman A|Ignarro LJ|Williams-Ignarro S|Sica V|Baker AH|Lerman LO|Geng YJ|Napoli C", '|')), CitationType.PUBMED), citation.newInstance( "Cell", "16962653", "", dateFormat.parse("2006-10-07"), Arrays.asList(StringUtils.split("Jacinto E|Facchinetti V|Liu D|Soto N|Wei S|Jung SY|Huang Q|Qin J|Su B", '|')), CitationType.PUBMED), citation.newInstance( "Trends in molecular medicine", "15350900", "", null, Arrays.asList(StringUtils.split("Barry RE|Krek W", '|')), CitationType.PUBMED), citation.newInstance( "Journal of clinical oncology : official journal of the American Society of Clinical Oncology", "16170185", "", null, Arrays.asList(StringUtils.split("Beeram M|Patnaik A|Rowinsky EK", '|')), CitationType.PUBMED), citation.newInstance( "The Biochemical journal", "12444918", "", null, Arrays.asList(StringUtils.split("Houslay MD|Adams DR", '|')), CitationType.PUBMED) }; for (Citation cit : citations) { c.add(cit); } f.add(r); f.add(c); testSameResultAsPreviousImplementation(f); } private static <T> void assertSame(Map<Integer, T> m1, Map<Integer, T> m2) { assertEquals(m1.size(), m2.size()); assertTrue(m1.keySet().containsAll(m2.keySet())); for (Integer key : m1.keySet()) { assertEquals(m1.get(key), m2.get(key)); } } private static void addFilterCriteria(KamFilter f, FilterCriteria c) { if (c instanceof CitationFilterCriteria) { f.add((CitationFilterCriteria) c); } else if (c instanceof AnnotationFilterCriteria) { f.add((AnnotationFilterCriteria) c); } else if (c instanceof RelationshipTypeFilterCriteria) { f.add((RelationshipTypeFilterCriteria) c); } else if (c instanceof BelDocumentFilterCriteria) { f.add((BelDocumentFilterCriteria) c); } } private void testIdempotency(FilterCriteria c) throws SQLException { KamInfo kamInfo = testKam.getKamInfo(); KamFilter f = kamInfo.createKamFilter(), f2 = kamInfo.createKamFilter(); addFilterCriteria(f, c); addFilterCriteria(f2, c); addFilterCriteria(f2, c); KamProtoNodesAndEdges all_f = dao.getKamProtoNodesAndEdges(kamInfo, f), all_f2 = dao.getKamProtoNodesAndEdges(kamInfo, f2); Map<Integer, KamProtoNode> nodes_f = all_f.getKamProtoNodes(), nodes_f2 = all_f2.getKamProtoNodes(); Map<Integer, KamProtoEdge> edges_f = all_f.getKamProtoEdges(), edges_f2 = all_f2.getKamProtoEdges(); assertSame(nodes_f, nodes_f2); assertSame(edges_f, edges_f2); } private void testCommutativity(FilterCriteria a, FilterCriteria b) throws SQLException { KamInfo kamInfo = testKam.getKamInfo(); KamFilter ab = kamInfo.createKamFilter(), ba = kamInfo.createKamFilter(); addFilterCriteria(ab, a); addFilterCriteria(ab, b); addFilterCriteria(ba, b); addFilterCriteria(ba, a); KamProtoNodesAndEdges all_ab = dao.getKamProtoNodesAndEdges(kamInfo, ab), all_ba = dao.getKamProtoNodesAndEdges(kamInfo, ba); Map<Integer, KamProtoNode> nodes_ab = all_ab.getKamProtoNodes(), nodes_ba = all_ba.getKamProtoNodes(); Map<Integer, KamProtoEdge> edges_ab = all_ab.getKamProtoEdges(), edges_ba = all_ba.getKamProtoEdges(); assertSame(nodes_ab, nodes_ba); assertSame(edges_ab, edges_ba); } private void testSameResultAsPreviousImplementation(KamFilter kamFilter) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, SQLException { // Test against the previous implementation. KamInfo kamInfo = testKam.getKamInfo(); Map<Integer, KamProtoNode> prevNodes = getKamProtoNodes(kamInfo, kamFilter); Map<Integer, KamProtoEdge> prevEdges = getKamProtoEdges(kamInfo, prevNodes, kamFilter); KamProtoNodesAndEdges current = dao.getKamProtoNodesAndEdges(kamInfo, kamFilter); Map<Integer, KamProtoNode> currentNodes = current.getKamProtoNodes(); Map<Integer, KamProtoEdge> currentEdges = current.getKamProtoEdges(); assertSame(prevNodes, currentNodes); assertSame(prevEdges, currentEdges); } private static Method getPreparedStatement = null, getPreparedStatement2 = null, close = null, getKamProtoNode = null; private static Constructor<KamProtoEdge> kamProtoEdge = null; private static Constructor<Citation> citation = null; private static Constructor<AnnotationType> annotationType = null; private static SimpleDateFormat dateFormat = null; private static String SELECT_PROTO_EDGES_SQL = null; private static String SELECT_PROTO_NODES_SQL = null; private static String SELECT_KAM_NODE_PARAMETERS_PREFIX_SQL = null; private static String SELECT_KAM_NODE_PARAMETERS_ORDER_SQL = null; private static void reflectNecessaryCode() throws NoSuchMethodException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { getPreparedStatement = AbstractJdbcDAO.class.getDeclaredMethod("getPreparedStatement", String.class); getPreparedStatement.setAccessible(true); getPreparedStatement2 = AbstractJdbcDAO.class.getDeclaredMethod( "getPreparedStatement", String.class, int.class, int.class); getPreparedStatement2.setAccessible(true); close = AbstractJdbcDAO.class.getDeclaredMethod("close", ResultSet.class); close.setAccessible(true); kamProtoEdge = KamProtoEdge.class.getDeclaredConstructor( Integer.class, KamProtoNode.class, RelationshipType.class, KamProtoNode.class); kamProtoEdge.setAccessible(true); citation = Citation.class.getDeclaredConstructor( String.class, String.class, String.class, Date.class, List.class, CitationType.class); citation.setAccessible(true); annotationType = AnnotationType.class.getDeclaredConstructor( Integer.class, String.class, String.class, String.class, AnnotationDefinitionType.class, String.class); annotationType.setAccessible(true); getKamProtoNode = KAMStoreDaoImpl.class.getDeclaredMethod("getKamProtoNode", ResultSet.class, ResultSet.class); getKamProtoNode.setAccessible(true); final Field dateFormatField = KAMStoreDaoImpl.class.getDeclaredField("dateFormat"); dateFormatField.setAccessible(true); dateFormat = (SimpleDateFormat) dateFormatField.get(null); final Field selectProtoEdgesSqlField = KAMStoreDaoImpl.class.getDeclaredField("SELECT_PROTO_EDGES_SQL"); selectProtoEdgesSqlField.setAccessible(true); SELECT_PROTO_EDGES_SQL = (String) selectProtoEdgesSqlField.get(null); final Field selectProtoNodesSqlField = KAMStoreDaoImpl.class.getDeclaredField("SELECT_PROTO_NODES_SQL"); selectProtoNodesSqlField.setAccessible(true); SELECT_PROTO_NODES_SQL = (String) selectProtoNodesSqlField.get(null); final Field selectKamNodeParametersPrefixSqlField = KAMStoreDaoImpl.class.getDeclaredField("SELECT_KAM_NODE_PARAMETERS_PREFIX_SQL"); selectKamNodeParametersPrefixSqlField.setAccessible(true); SELECT_KAM_NODE_PARAMETERS_PREFIX_SQL = (String) selectKamNodeParametersPrefixSqlField.get(null); final Field selectKamNodeParametersOrderSqlField = KAMStoreDaoImpl.class.getDeclaredField("SELECT_KAM_NODE_PARAMETERS_ORDER_SQL"); selectKamNodeParametersOrderSqlField.setAccessible(true); SELECT_KAM_NODE_PARAMETERS_ORDER_SQL = (String) selectKamNodeParametersOrderSqlField.get(null); } public Map<Integer, KamProtoEdge> getKamProtoEdges( @SuppressWarnings("unused") KamInfo kamInfo, Map<Integer, KamProtoNode> kamProtoNodeMap, KamFilter kamFilter) throws SQLException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { Map<Integer, KamProtoEdge> map = new HashMap<Integer, KamProtoEdge>(); ResultSet rset = null; try { PreparedStatement ps = (PreparedStatement) getPreparedStatement.invoke( dao, SELECT_PROTO_EDGES_SQL); rset = ps.executeQuery(); while (rset.next()) { Integer kamEdgeId = rset.getInt(1); KamProtoNode sourceKamProtoNode = kamProtoNodeMap.get(rset.getInt(2)); Integer relationshipTypeId = rset.getInt(3); KamProtoNode targetKamProtoNode = kamProtoNodeMap.get(rset.getInt(4)); // Sanity checks if (null == sourceKamProtoNode) { throw new SQLException(String.format("Source node for edge %d is missing.", kamEdgeId)); } if (null == targetKamProtoNode) { throw new SQLException(String.format("Target node for edge %d is missing.", kamEdgeId)); } map.put(kamEdgeId, kamProtoEdge.newInstance(kamEdgeId, sourceKamProtoNode, RelationshipType.fromValue(relationshipTypeId), targetKamProtoNode)); } //filter edges if a kam filter is specified if( kamFilter != null ) { kamFilterHelper.filter(kamProtoNodeMap, map, kamFilter); } } finally { close.invoke(dao, rset); } return map; } public Map<Integer, KamProtoNode> getKamProtoNodes( @SuppressWarnings("unused") KamInfo kamInfo, @SuppressWarnings("unused") KamFilter kamFilter) throws SQLException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Map<Integer, KamProtoNode> map = new HashMap<Integer, KamProtoNode>(); // FIXME: don't ignore 'kamFilter' ResultSet nodesRs = null; ResultSet paramsRs = null; try { PreparedStatement nps = (PreparedStatement) getPreparedStatement.invoke(dao, SELECT_PROTO_NODES_SQL); nodesRs = nps.executeQuery(); PreparedStatement pps = (PreparedStatement) getPreparedStatement2.invoke(dao, SELECT_KAM_NODE_PARAMETERS_PREFIX_SQL + SELECT_KAM_NODE_PARAMETERS_ORDER_SQL, TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY); paramsRs = pps.executeQuery(); while (nodesRs.next()) { KamProtoNode kamProtoNode = (KamProtoNode) getKamProtoNode.invoke( dao, nodesRs, paramsRs); map.put(kamProtoNode.getId(), kamProtoNode); } } finally { close.invoke(dao, nodesRs); close.invoke(dao, paramsRs); } return map; } }