package org.openbel.framework.api.internal; import org.openbel.framework.api.AnnotationFilterCriteria; import org.openbel.framework.api.FilterCriteria; import org.openbel.framework.api.Kam.KamEdge; import org.openbel.framework.common.bel.parser.BELParser; import org.openbel.framework.common.model.*; import org.openbel.framework.core.df.AbstractJdbcDAO; import org.openbel.framework.core.df.DBConnection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import static java.util.Arrays.asList; import static org.openbel.framework.common.BELUtilities.sizedHashMap; import static org.openbel.framework.common.enums.CitationType.fromString; /** * Implements a {@link KAMDao} that retrieves BEL evidence for one or more * edges. * * <p> * This implementation is in place to avoid the heavy use of caching in * {@link org.openbel.framework.api.internal.KAMStoreDaoImpl}. */ public class EvidenceDaoImpl extends AbstractJdbcDAO implements EvidenceDao { private static final String SQL = "select s.statement_id, s.bel_statement, ad.name, o.varchar_value " + "from @.kam_edge ke INNER JOIN @.kam_edge_statement_map kesm ON ke.kam_edge_id = kesm.kam_edge_id " + "INNER JOIN @.statement s ON kesm.statement_id = s.statement_id " + "LEFT JOIN @.statement_annotation_map sam ON s.statement_id = sam.statement_id " + "LEFT JOIN @.annotation a ON sam.annotation_id = a.annotation_id " + "LEFT JOIN @.annotation_definition ad ON a.annotation_definition_id = ad.annotation_definition_id " + "LEFT JOIN @.objects o ON a.value_oid = o.objects_id where ke.kam_edge_id = ? order by s.statement_id"; private static final SimpleDateFormat iso8601DateFormat = new SimpleDateFormat("yyyy-MM-dd"); public EvidenceDaoImpl(DBConnection dbConnection, String schemaName) throws SQLException { super(dbConnection, schemaName); } /** * {@inheritDoc} */ public Map<KamEdge, List<Statement>> evidence(Collection<KamEdge> edges) throws SQLException { if (edges == null) throw new IllegalArgumentException("edges is null"); PreparedStatement ps; ResultSet rs = null; Map<KamEdge, List<Statement>> results = new HashMap<KamEdge, List<Statement>>(); try { for (KamEdge edge : edges) { if (edge == null) continue; List<Statement> evidence = new ArrayList<Statement>(); ps = getPreparedStatement(SQL); ps.setInt(1, edge.getId()); rs = ps.executeQuery(); int id = -1; Statement stmt = null; Map<String, String> citation = new HashMap<String, String>(); while (rs.next()) { int next = rs.getInt(1); if (next != id ) { if (id != -1) { // iterating a different statement, // save previous if (stmt != null) { if (!citation.isEmpty()) { stmt.getAnnotationGroup().setCitation(fromMap(citation)); } evidence.add(stmt); citation.clear(); } } id = next; stmt = BELParser.parseStatement(rs.getString(2)); if (stmt == null) continue; } String name = rs.getString(3); String value = rs.getString(4); if (name != null) directAnnotation(name, value, stmt, citation); } // add set of rows for last statement if (stmt != null) { if (!citation.isEmpty()) stmt.getAnnotationGroup().setCitation(fromMap(citation)); evidence.add(stmt); citation.clear(); } close(rs); results.put(edge, evidence); } return results; } finally { close(rs); } } public Map<KamEdge, List<Statement>> evidence(Collection<KamEdge> edges, KAMCatalogDao.AnnotationFilter filter) throws SQLException { final Map<KamEdge, List<Statement>> results = evidence(edges); if (filter == null) { return results; } final List<FilterCriteria> criteria = filter.getFilterCriteria(); final Map<KAMStoreDaoImpl.AnnotationType, AnnotationFilterCriteria> amap = sizedHashMap(criteria.size()); for (final FilterCriteria c : criteria) { final AnnotationFilterCriteria afc = (AnnotationFilterCriteria) c; amap.put(afc.getAnnotationType(), afc); } for (Collection<Statement> stmts : results.values()) { final Iterator<Statement> stmtIt = stmts.iterator(); while (stmtIt.hasNext()) { final Statement stmt = stmtIt.next(); // guard against empty annotations if (stmt == null || stmt.getAnnotationGroup() == null || stmt.getAnnotationGroup().getAnnotations() == null) continue; final List<Annotation> annotations = stmt.getAnnotationGroup().getAnnotations(); for (final FilterCriteria c : criteria) { // criteria is invalid, continue if (c == null) { continue; } final AnnotationFilterCriteria afc = (AnnotationFilterCriteria) c; // criteria's annotation type is invalid, continue if (afc.getAnnotationType() == null) { continue; } Annotation matchedAnnotation = null; for (final Annotation annotation : annotations) { if (annotation.getDefinition().getId().equals(afc.getAnnotationType().getName())) { matchedAnnotation = annotation; } } if (matchedAnnotation == null) { if (c.isInclude()) { stmtIt.remove(); } } else { boolean valueMatch = afc.getValues().contains( matchedAnnotation.getValue()); if (valueMatch && !c.isInclude()) { stmtIt.remove(); } } } } } return results; } private void directAnnotation(String name, String value, Statement stmt, Map<String, String> citation) { if (stmt.getAnnotationGroup() == null) { AnnotationGroup group = new AnnotationGroup(); group.setAnnotations(new ArrayList<Annotation>()); stmt.setAnnotationGroup(group); } if (name.equals("CitationReference") || name.equals("CitationName") || name.equals("CitationType") || name.equals("CitationDate") || name.equals("CitationAuthors") || name.equals("CitationComment")) { citation.put(name, value); } else { Annotation a = new Annotation(value, new AnnotationDefinition(name)); stmt.getAnnotationGroup().getAnnotations().add(a); } } private Citation fromMap(Map<String, String> m) { String name = m.get("CitationName"); if (name == null) return null; Citation c = new Citation(name); c.setReference(m.get("CitationReference")); c.setType(fromString(m.get("CitationType"))); String date = m.get("CitationDate"); if (date != null) { try { Date d = iso8601DateFormat.parse(date); Calendar cal = Calendar.getInstance(); cal.setTime(d); c.setDate(cal); } catch (ParseException e) { // invalid date; do not set } } String authors = m.get("CitationAuthors"); if (authors != null) { String[] a = authors.split("\\s*,\\s*"); c.setAuthors(asList(a)); } c.setComment(m.get("CitationComment")); return c; } }