package tr.com.srdc.mdr.core.store.query; import java.util.ArrayList; import java.util.List; import tr.com.srdc.mdr.core.impl.ai.DataElementImpl; import tr.com.srdc.mdr.core.impl.ai.EnumeratedConceptualDomainImpl; import tr.com.srdc.mdr.core.impl.ai.EnumeratedValueDomainImpl; import tr.com.srdc.mdr.core.impl.ai.NonEnumeratedConceptualDomainImpl; import tr.com.srdc.mdr.core.impl.ai.NonEnumeratedValueDomainImpl; import tr.com.srdc.mdr.core.impl.ai.PropertyImpl; import tr.com.srdc.mdr.core.model.Util; import tr.com.srdc.mdr.core.model.iso11179.ConceptualDomainResource; import tr.com.srdc.mdr.core.model.iso11179.DataElementResource; import tr.com.srdc.mdr.core.model.iso11179.PropertyResource; import tr.com.srdc.mdr.core.model.iso11179.ValueDomainResource; import tr.com.srdc.mdr.core.store.MDRDatabase; import com.hp.hpl.jena.ontology.OntClass; import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.query.QueryExecution; import com.hp.hpl.jena.query.QueryExecutionFactory; import com.hp.hpl.jena.query.QuerySolution; import com.hp.hpl.jena.query.ResultSet; public class TDBQueryFactory extends ResourceQueryFactory { private static final String PREFIX_PF = "PREFIX pf: <http://jena.hpl.hp.com/ARQ/property#> "; public TDBQueryFactory(MDRDatabase mdrDatabase) { super(mdrDatabase); } @Override protected QueryExecution createQueryExecution(String queryString, OntModel ontModel) { return QueryExecutionFactory.create(queryString, this.mdrDatabase.getOntModel()); } @Override public int getNumberOfDataElementSearch(String keyword, String contextURI, TextSearchType searchType) { StringBuilder queryString = new StringBuilder(PREFIX_MDR) .append(PREFIX_PF) .append(PREFIX_RDFS) .append("SELECT (COUNT (DISTINCT ?de) as ?count) FROM <") .append(MDRDatabase.BASE_URI) .append("> WHERE {") .append("?de rdfs:subClassOf mdr:DataElement .") .append("?de mdr:having ?aic .") .append("?aic mdr:administeredItemContextTerminologicalEntry ?te .") .append("?te mdr:containingTerminologicalEntryLanguage ?ls .") .append("?ls mdr:containingNameEntry ?designation .") .append("?designation mdr:name ?name ."); if (!Util.isNull(contextURI)) { queryString.append("?aic mdr:administeredItemContextContext <") .append(contextURI).append("> ."); } if (keyword.matches("\\s*")) { return 0; } if (searchType == null || searchType.equals(TextSearchType.Exact)) { queryString.append(exactMatchKeyword(keyword)); } else if (searchType.equals(TextSearchType.WildCard)) { queryString.append(atLeastOneKeyword(keyword)); } else { queryString.append(allWordsKeyword(keyword)); } queryString.append(" .}"); QueryExecution qexec = this.createQueryExecution( queryString.toString(), this.mdrDatabase.getOntModel()); int size = 0; try { ResultSet rs = qexec.execSelect(); while (rs.hasNext()) { QuerySolution qs = rs.next(); size = qs.getLiteral("count").getInt(); } } finally { qexec.close(); } return size; } @Override public List<? super DataElementResource> searchDataElement(String keyword, String contextURI, TextSearchType searchType, int limit, int offset) { List<DataElementResource> dataElementList = new ArrayList<DataElementResource>(); StringBuilder queryString = new StringBuilder(PREFIX_MDR) .append(PREFIX_PF) .append(PREFIX_RDFS) .append("SELECT ?de FROM <") .append(MDRDatabase.BASE_URI) .append("> WHERE {") .append("?de rdfs:subClassOf mdr:DataElement .") .append("?de mdr:having ?aic .") .append("?aic mdr:administeredItemContextTerminologicalEntry ?te .") .append("?te mdr:containingTerminologicalEntryLanguage ?ls .") .append("?ls mdr:containingNameEntry ?designation .") .append("?designation mdr:name ?name ."); if (!Util.isNull(contextURI)) { queryString.append("?aic mdr:administeredItemContextContext <") .append(contextURI).append("> ."); } if (keyword.matches("\\s*")) { return dataElementList; } if (searchType == null || searchType.equals(TextSearchType.Exact)) { queryString.append(exactMatchKeyword(keyword)); } else if (searchType.equals(TextSearchType.WildCard)) { queryString.append(atLeastOneKeyword(keyword)); } else { queryString.append(allWordsKeyword(keyword)); } queryString.append(" .} ORDER BY ?score LIMIT ").append(limit) .append(" OFFSET ").append(offset); QueryExecution qexec = this.createQueryExecution( queryString.toString(), this.mdrDatabase.getOntModel()); try { ResultSet rs = qexec.execSelect(); while (rs.hasNext()) { QuerySolution qs = rs.next(); DataElementResource de = new DataElementImpl( qs.getResource("de"), mdrDatabase); dataElementList.add(de); } } finally { qexec.close(); } return dataElementList; } @Override public List<? super PropertyResource> searchProperty(String keyword, String contextURI, TextSearchType searchType) { List<PropertyResource> propertyList = new ArrayList<PropertyResource>(); StringBuilder queryString = new StringBuilder(PREFIX_MDR) .append(PREFIX_PF) .append(PREFIX_RDFS) .append("SELECT ?property FROM <") .append(MDRDatabase.BASE_URI) .append("> WHERE {") .append("?property rdfs:subClassOf mdr:Property .") .append("?property mdr:having ?aic .") .append("?aic mdr:administeredItemContextTerminologicalEntry ?te .") .append("?te mdr:containingTerminologicalEntryLanguage ?ls .") .append("?ls mdr:containingNameEntry ?designation .") .append("?designation mdr:name ?name ."); if (!Util.isNull(contextURI)) { queryString.append("?aic mdr:administeredItemContextContext <") .append(contextURI).append("> . "); } if (keyword.matches("\\s*")) { return propertyList; } if (searchType == null || searchType.equals(TextSearchType.Exact)) { queryString.append(exactMatchKeyword(keyword)); } else if (searchType.equals(TextSearchType.WildCard)) { queryString.append(atLeastOneKeyword(keyword)); } else { queryString.append(allWordsKeyword(keyword)); } queryString.append(" .}"); QueryExecution qexec = this.createQueryExecution( queryString.toString(), this.mdrDatabase.getOntModel()); try { ResultSet rs = qexec.execSelect(); while (rs.hasNext()) { QuerySolution qs = rs.next(); PropertyResource prop = new PropertyImpl( qs.getResource("property"), mdrDatabase); propertyList.add(prop); } } finally { qexec.close(); } return propertyList; } @Override public List<? super ConceptualDomainResource> searchConceptualDomain( String keyword, String contextURI, TextSearchType searchType) { List<ConceptualDomainResource> cdList = new ArrayList<ConceptualDomainResource>(); StringBuilder queryString = new StringBuilder(PREFIX_MDR) .append(PREFIX_PF) .append(PREFIX_RDFS) .append("SELECT ?cd FROM <") .append(MDRDatabase.BASE_URI) .append("> WHERE {") .append("?cdClass rdfs:subClassOf mdr:ConceptualDomain .") .append("?cd rdfs:subClassOf ?cdClass .") .append("?cd mdr:having ?aic .") .append("?aic mdr:administeredItemContextTerminologicalEntry ?te .") .append("?te mdr:containingTerminologicalEntryLanguage ?ls .") .append("?ls mdr:containingNameEntry ?designation .") .append("?designation mdr:name ?name ."); if (!Util.isNull(contextURI)) { queryString.append("?aic mdr:administeredItemContextContext <") .append(contextURI).append("> ."); } if (keyword.matches("\\s*")) { return cdList; } if (searchType == null || searchType.equals(TextSearchType.Exact)) { queryString.append(exactMatchKeyword(keyword)); } else if (searchType.equals(TextSearchType.WildCard)) { queryString.append(atLeastOneKeyword(keyword)); } else { queryString.append(allWordsKeyword(keyword)); } queryString.append(" .}"); QueryExecution qexec = this.createQueryExecution( queryString.toString(), this.mdrDatabase.getOntModel()); try { ResultSet rs = qexec.execSelect(); while (rs.hasNext()) { QuerySolution qs = rs.next(); // here conceptualDomain is checked whether its enumerated or // not, proper instantiation is done OntClass res = qs.getResource("cd").as(OntClass.class); if (res.hasSuperClass(mdrDatabase.getVocabulary().EnumeratedConceptualDomain)) { cdList.add(new EnumeratedConceptualDomainImpl(res, mdrDatabase)); } else { cdList.add(new NonEnumeratedConceptualDomainImpl(res, mdrDatabase)); } } } finally { qexec.close(); } return cdList; } @Override public List<? super ValueDomainResource> searchValueDomain(String keyword, String contextURI, TextSearchType searchType) { List<ValueDomainResource> vdList = new ArrayList<ValueDomainResource>(); StringBuilder queryString = new StringBuilder(PREFIX_MDR) .append(PREFIX_PF) .append(PREFIX_RDFS) .append("SELECT ?cd FROM <") .append(MDRDatabase.BASE_URI) .append("> WHERE {") .append("?cdClass rdfs:subClassOf mdr:ValueDomain .") .append("?cd rdfs:subClassOf ?cdClass .") .append("?cd mdr:having ?aic .") .append("?aic mdr:administeredItemContextTerminologicalEntry ?te .") .append("?te mdr:containingTerminologicalEntryLanguage ?ls .") .append("?ls mdr:containingNameEntry ?designation .") .append("?designation mdr:name ?name ."); if (!Util.isNull(contextURI)) { queryString.append("?aic mdr:administeredItemContextContext <") .append(contextURI).append("> ."); } if (keyword.matches("\\s*")) { return vdList; } if (searchType == null || searchType.equals(TextSearchType.Exact)) { queryString.append(exactMatchKeyword(keyword)); } else if (searchType.equals(TextSearchType.WildCard)) { queryString.append(atLeastOneKeyword(keyword)); } else { queryString.append(allWordsKeyword(keyword)); } queryString.append(" .}"); QueryExecution qexec = this.createQueryExecution( queryString.toString(), this.mdrDatabase.getOntModel()); try { ResultSet rs = qexec.execSelect(); while (rs.hasNext()) { QuerySolution qs = rs.next(); // here conceptualDomain is checked whether its enumerated or // not, proper instantiation is done OntClass res = qs.getResource("cd").as(OntClass.class); if (res.hasSuperClass(mdrDatabase.getVocabulary().EnumeratedValueDomain)) { vdList.add(new EnumeratedValueDomainImpl(res, mdrDatabase)); } else { vdList.add(new NonEnumeratedValueDomainImpl(res, mdrDatabase)); } } } finally { qexec.close(); } return vdList; } /** * Creates a text match keyword for exact match according to LARQ query * syntax. * * @param keyword * Query keywords seperated from each other with whitespaces * @return */ private String exactMatchKeyword(String keyword) { String[] keywords = keyword.split("\\s+"); StringBuilder queryString = new StringBuilder(); queryString.append("(?name ?score) pf:textMatch '\""); for (int i = 0; i < keywords.length - 1; i++) { queryString.append(keywords[i]).append(" "); } queryString.append(keywords[keywords.length - 1]).append(" \"~0' "); return queryString.toString(); } /** * Creates a text match keyword for matching all words according to LARQ * query syntax. * * @param keyword * Query keywords seperated from each other with whitespaces * @return */ private String allWordsKeyword(String keyword) { String[] keywords = keyword.split("\\s+"); StringBuilder queryString = new StringBuilder(); queryString.append("(?name ?score) pf:textMatch '"); for (int i = 0; i < keywords.length - 1; i++) { queryString.append(keywords[i]).append(" AND "); } queryString.append(keywords[keywords.length - 1]).append(" '"); return queryString.toString(); } /** * Creates a text match keyword for wildcard matching according to LARQ * query syntax. * * @param keyword * Query keywords seperated from each other with whitespaces * @return */ private String atLeastOneKeyword(String keyword) { String[] keywords = keyword.split("\\s+"); StringBuilder queryString = new StringBuilder(); queryString.append("(?name ?score) pf:textMatch '"); for (int i = 0; i < keywords.length - 1; i++) { queryString.append(keywords[i]).append(" "); } queryString.append(keywords[keywords.length - 1]).append("* ' "); return queryString.toString(); } }