Java tutorial
/* * Copyright: (c) 2004-2010 Mayo Foundation for Medical Education and * Research (MFMER). All rights reserved. MAYO, MAYO CLINIC, and the * triple-shield Mayo logo are trademarks and service marks of MFMER. * * Except as contained in the copyright notice above, or as used to identify * MFMER as the author of this software, the trade names, trademarks, service * marks, or product names of the copyright holder shall not be used in * advertising, promotion or otherwise in connection with this software without * prior written authorization of the copyright holder. * * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html * */ package org.LexGrid.LexBIG.Impl.exporters; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URLClassLoader; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.logging.Logger; import org.LexGrid.LexBIG.DataModel.Collections.AssociationList; import org.LexGrid.LexBIG.DataModel.Collections.NameAndValueList; import org.LexGrid.LexBIG.DataModel.Collections.ResolvedConceptReferenceList; import org.LexGrid.LexBIG.DataModel.Core.AssociatedConcept; import org.LexGrid.LexBIG.DataModel.Core.Association; import org.LexGrid.LexBIG.DataModel.Core.CodingSchemeVersionOrTag; import org.LexGrid.LexBIG.DataModel.Core.ConceptReference; import org.LexGrid.LexBIG.DataModel.Core.NameAndValue; import org.LexGrid.LexBIG.DataModel.Core.ResolvedConceptReference; import org.LexGrid.LexBIG.DataModel.InterfaceElements.ExportStatus; import org.LexGrid.LexBIG.DataModel.InterfaceElements.types.ProcessState; import org.LexGrid.LexBIG.Exceptions.LBException; import org.LexGrid.LexBIG.Exceptions.LBResourceUnavailableException; import org.LexGrid.LexBIG.Extensions.Load.OntologyFormat; import org.LexGrid.LexBIG.Impl.LexBIGServiceImpl; import org.LexGrid.LexBIG.Impl.exporters.ExporterMessageDirector; import org.LexGrid.LexBIG.LexBIGService.CodedNodeGraph; import org.LexGrid.LexBIG.LexBIGService.CodedNodeSet; import org.LexGrid.LexBIG.LexBIGService.LexBIGService; import org.LexGrid.LexBIG.Utility.Constructors; import org.LexGrid.LexBIG.Utility.Iterators.ResolvedConceptReferencesIterator; import org.LexGrid.LexBIG.Utility.logging.LgMessageDirectorIF; import org.LexGrid.codingSchemes.CodingScheme; import org.LexGrid.commonTypes.Source; import org.LexGrid.commonTypes.types.EntityTypes; import org.LexGrid.concepts.Comment; import org.LexGrid.concepts.Definition; import org.LexGrid.concepts.Entity; import org.LexGrid.concepts.Presentation; import org.LexGrid.concepts.PropertyLink; import org.LexGrid.naming.SupportedAssociation; import org.LexGrid.naming.SupportedAssociationQualifier; import org.LexGrid.naming.SupportedNamespace; import org.LexGrid.naming.SupportedProperty; import org.LexGrid.relations.AssociationEntity; import org.apache.commons.lang.StringUtils; import org.lexevs.dao.database.utility.DaoUtility; import org.lexevs.locator.LexEvsServiceLocator; import org.lexgrid.exporter.owlrdf.LexRdf; import org.lexgrid.exporter.owlrdf.LexRdfConstants; import org.lexgrid.exporter.owlrdf.LexRdfMap; import org.lexgrid.exporter.owlrdf.Skos; import org.lexgrid.exporter.owlrdf.StringHelper; import com.hp.hpl.jena.ontology.AnnotationProperty; import com.hp.hpl.jena.ontology.ComplementClass; import com.hp.hpl.jena.ontology.IntersectionClass; import com.hp.hpl.jena.ontology.OntClass; import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntModelSpec; import com.hp.hpl.jena.ontology.OntProperty; import com.hp.hpl.jena.ontology.OntResource; import com.hp.hpl.jena.ontology.Ontology; import com.hp.hpl.jena.ontology.Restriction; import com.hp.hpl.jena.ontology.UnionClass; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; import com.hp.hpl.jena.rdf.model.Property; import com.hp.hpl.jena.rdf.model.RDFList; import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.RDFWriter; import com.hp.hpl.jena.rdf.model.ReifiedStatement; import com.hp.hpl.jena.rdf.model.Resource; import com.hp.hpl.jena.rdf.model.Statement; import com.hp.hpl.jena.sdb.SDBFactory; import com.hp.hpl.jena.sdb.Store; import com.hp.hpl.jena.sdb.StoreDesc; import com.hp.hpl.jena.sdb.sql.SDBConnection; import com.hp.hpl.jena.sdb.store.DatabaseType; import com.hp.hpl.jena.sdb.store.LayoutType; import com.hp.hpl.jena.vocabulary.DC; import com.hp.hpl.jena.vocabulary.OWL; import com.hp.hpl.jena.vocabulary.RDF; import com.hp.hpl.jena.vocabulary.RDFS; public class LexGridToOwlRdfConverter { private Store store_ = null; private String currentNamespace_; private OntModel model_; private CodingScheme cs_; private CodedNodeGraph cng_; private CodedNodeSet cns_; private OntologyFormat ontFormat_; private LgMessageDirectorIF messenger_; private Writer writer_; private int assnCounter = 0; // for dev only class DriverShim implements Driver { private Driver driver; DriverShim(Driver d) { this.driver = d; } public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } public boolean acceptsURL(String u) throws SQLException { return this.driver.acceptsURL(u); } public Connection connect(String u, Properties p) throws SQLException { return this.driver.connect(u, p); } public int getMajorVersion() { return this.driver.getMajorVersion(); } public int getMinorVersion() { return this.driver.getMinorVersion(); } public DriverPropertyInfo[] getPropertyInfo(String u, Properties p) throws SQLException { return this.driver.getPropertyInfo(u, p); } public boolean jdbcCompliant() { return this.driver.jdbcCompliant(); } } public LexGridToOwlRdfConverter() { } public Store getStore() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException { if (store_ != null) return store_; String url = LexEvsServiceLocator.getInstance().getSystemResourceService().getSystemVariables() .getAutoLoadDBURL(); String userName = LexEvsServiceLocator.getInstance().getSystemResourceService().getSystemVariables() .getAutoLoadDBUsername(); String password = LexEvsServiceLocator.getInstance().getSystemResourceService().getSystemVariables() .getAutoLoadDBPassword(); org.lexevs.dao.database.type.DatabaseType type = LexEvsServiceLocator.getInstance() .getLexEvsDatabaseOperations().getDatabaseType(); StoreDesc storeDesc = null; URLClassLoader loader = LexEvsServiceLocator.getInstance().getSystemResourceService().getClassLoader(); if (type.equals(org.lexevs.dao.database.type.DatabaseType.MYSQL)) { Driver d = (Driver) Class.forName("com.mysql.jdbc.Driver", true, loader).newInstance(); DriverManager.registerDriver(new DriverShim(d)); storeDesc = new StoreDesc(LayoutType.LayoutTripleNodesIndex, DatabaseType.MySQL); } else if (type.equals(org.lexevs.dao.database.type.DatabaseType.ORACLE)) { Driver d = (Driver) Class.forName("oracle.jdbc.driver.OracleDriver", true, loader).newInstance(); DriverManager.registerDriver(new DriverShim(d)); storeDesc = new StoreDesc(LayoutType.LayoutTripleNodesIndex, DatabaseType.Oracle); } else if (type.equals(org.lexevs.dao.database.type.DatabaseType.POSTGRES)) { Driver d = (Driver) Class.forName("org.postgresql.Driver", true, loader).newInstance(); DriverManager.registerDriver(new DriverShim(d)); storeDesc = new StoreDesc(LayoutType.LayoutTripleNodesIndex, DatabaseType.PostgreSQL); } else if (type.equals(org.lexevs.dao.database.type.DatabaseType.HSQL)) { Driver d = (Driver) Class.forName("org.hsqldb.jdbcDriver", true, loader).newInstance(); DriverManager.registerDriver(new DriverShim(d)); storeDesc = new StoreDesc(LayoutType.LayoutTripleNodesIndex, DatabaseType.HSQLDB); } else if (type.equals(org.lexevs.dao.database.type.DatabaseType.DB2)) { Driver d = (Driver) Class.forName("com.ibm.db2.jcc.DB2Driver", true, loader).newInstance(); DriverManager.registerDriver(new DriverShim(d)); storeDesc = new StoreDesc(LayoutType.LayoutTripleNodesIndex, DatabaseType.DB2); } SDBConnection conn = new SDBConnection(url, userName, password); store_ = SDBFactory.connectStore(conn, storeDesc); // If SDB tables do not exist, it will throw an exception. try { store_.getSize(); } catch (Exception e) { store_.getTableFormatter().create(); messenger_.info("create sdb tables."); return store_; } return store_; } public Model getBaseModel(String iri) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException { return SDBFactory.connectNamedModel(this.getStore(), iri); } private void codingSchemeMapping() throws SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { messenger_.info("processing coding scheme meta data."); Ontology ontology = model_.createOntology(cs_.getCodingSchemeURI()); String ncname_codingSchemeName = convertToNMTokenString(cs_.getCodingSchemeName()); ontology.addLabel(ncname_codingSchemeName, LexRdfConstants.ENGLISH); ontology.addVersionInfo(cs_.getRepresentsVersion()); if (cs_.getCopyright() != null) ontology.addProperty(DC.rights, cs_.getCopyright().getContent()); if (cs_.getFormalName() != null) ontology.addProperty(DC.title, cs_.getFormalName()); if (cs_.getDefaultLanguage() != null) ontology.addProperty(DC.language, cs_.getDefaultLanguage()); for (Source source : cs_.getSource()) { if (source.getContent() != null) ontology.addProperty(DC.source, source.getContent()); } // import namespaces this.initNamespace(); } private void entityMapping() throws LBResourceUnavailableException, SecurityException, IllegalArgumentException, LBException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { if (cns_ == null) return; messenger_.info("Processing entities ..."); List<Entity> instanceList = new ArrayList<Entity>(); ResolvedConceptReferencesIterator iterator = cns_.resolve(null, null, null, null, true); int counter = 0; while (iterator.hasNext()) { ResolvedConceptReference conRef = iterator.next(); Entity entity = conRef.getEntity(); counter++; if (counter % 1000 == 0) { messenger_.info("Processed " + counter + " entities"); } if (entity == null) continue; // handle the anonymous entity in association mapping, not here. if (entity.isIsAnonymous() != null && entity.isIsAnonymous() == true) continue; if (entity.getEntityType() == null || entity.getEntityType().length == 0 || entity.getEntityType().length > 1) { // map to skos:concept this.addSkosConcept(entity); } else if (entity.getEntityType()[0].equalsIgnoreCase(EntityTypes.CONCEPT.value())) { // map to owl:class this.addOwlClass(entity); } else if (entity.getEntityType()[0].equalsIgnoreCase(EntityTypes.ASSOCIATION.value())) { // map to owl:objectProperty/dataTypeProperty this.addOntProperty((AssociationEntity) entity); } else if (entity.getEntityType()[0].equalsIgnoreCase(EntityTypes.INSTANCE.value())) { // save instance into a list, process the instances later instanceList.add(entity); } } // at last, process the instance, since the instance maybe an instance // of owl:class processInstance(instanceList); messenger_.info("Processed entity total: " + Integer.toString(counter)); } private void associationMapping() throws NullPointerException, LBException, SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { if (cns_ == null || cng_ == null) { return; } messenger_.info("Processing associations ..."); ResolvedConceptReferencesIterator conIterator = cns_.resolve(null, null, null, null, false); while (conIterator.hasNext()) { ResolvedConceptReference focus = conIterator.next(); ResolvedConceptReferenceList localRcrl = cng_.resolveAsList(focus, true, false, 1, -1, null, null, null, null, -1); if (localRcrl == null) continue; Iterator<? extends ResolvedConceptReference> localIterator = localRcrl .iterateResolvedConceptReference(); while (localIterator.hasNext()) { ResolvedConceptReference sourceConRef = localIterator.next(); if (LexRdfMap.isMapped(sourceConRef, ontFormat_) == true) continue; this.processLgTargets(sourceConRef); } } messenger_.info("proccessed the total associations: " + Integer.toString(assnCounter)); } private SupportedAssociation getLgSupportedAssociation(String associationName) throws LBException { for (SupportedAssociation supportedAssn : cs_.getMappings().getSupportedAssociation()) { if (supportedAssn.getContent().equalsIgnoreCase(associationName) || supportedAssn.getLocalId().equalsIgnoreCase(associationName)) { return supportedAssn; } } return null; } private AnnotationProperty getAnnotationProeprty(String uri) { AnnotationProperty p = model_.getAnnotationProperty(uri); if (p == null) return model_.createAnnotationProperty(uri); else return p; } private void processLgQualifier(Resource s, Resource p, Resource o, String qualifierName, String qualifierValue) throws LBException { Statement statement = model_.createStatement(s, (Property) p, o); ReifiedStatement rs = model_.createReifiedStatement(statement); AnnotationProperty prop = this .getAnnotationProeprty(this.resolveNamespace(currentNamespace_) + qualifierName); prop.addSuperProperty(LexRdf.associationQualification); rs.addProperty(prop, qualifierValue); } private void processLgTargets(ResolvedConceptReference sourceConRef) throws NullPointerException, LBException, SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { String sourceUri = this.resolveNamespace(sourceConRef.getCodeNamespace()) + sourceConRef.getCode(); Resource source = null; assnCounter++; if (assnCounter % 1000 == 0) { messenger_.info("processed " + Integer.toString(assnCounter) + " associations"); } // only consider the anonymous target if (sourceConRef.getCode().startsWith("@")) { return; } if (sourceConRef.getEntity().getEntityTypeCount() > 0 && sourceConRef.getEntity().getEntityType()[0].equalsIgnoreCase(EntityTypes.INSTANCE.value())) { // do nothing for instance return; } else if (sourceConRef.getEntity().getEntityTypeCount() > 0 && sourceConRef.getEntity().getEntityType()[0].equalsIgnoreCase(EntityTypes.ASSOCIATION.value())) { // for association String uri = getLgPropertyUri(sourceConRef.getCodeNamespace(), sourceConRef.getCode()); if (uri != null) source = model_.getOntProperty( this.getLgPropertyUri(sourceConRef.getCodeNamespace(), sourceConRef.getCode())); else source = model_.getOntProperty( this.resolveNamespace(sourceConRef.getCodeNamespace()) + sourceConRef.getCode()); } else if (sourceConRef.getEntity().getEntityTypeCount() > 0 && sourceConRef.getEntity().getEntityType()[0].equalsIgnoreCase(EntityTypes.CONCEPT.value())) { // for concept source = model_.getOntClass(sourceUri); } if (source == null) { //We do not know the entity type of the entity....weird return; } AssociationList targetList = sourceConRef.getSourceOf(); if ((targetList != null) && (targetList.getAssociationCount() > 0)) { Iterator<? extends Association> targetsIterator = targetList.iterateAssociation(); while (targetsIterator.hasNext()) { Association targetAssociation = targetsIterator.next(); // get association entity according to the association name SupportedAssociation supportedAssn = this .getLgSupportedAssociation(targetAssociation.getAssociationName()); Property prop = null; if (supportedAssn == null) { throw new LBException( "cannot find the supported association for " + targetAssociation.getAssociationName()); } else { String propUri = null; if (supportedAssn.getEntityCode() == null) { propUri = this.getLgPropertyUri(supportedAssn.getEntityCodeNamespace(), supportedAssn.getLocalId()); } else { propUri = this.getLgPropertyUri(supportedAssn.getEntityCodeNamespace(), reformatCode(supportedAssn.getEntityCode())); } if (propUri != null) prop = model_.getProperty(propUri); if (prop == null) { // if it maps to owl/rdf properties, we don't need to // add it if (LexRdfMap.isMapped(null, supportedAssn.getLocalId(), ontFormat_) == true) return; propUri = this.resolveNamespace(currentNamespace_) + supportedAssn.getLocalId(); prop = model_.createOntProperty(propUri); } } Iterator<? extends AssociatedConcept> associatedTargetsIterator = targetAssociation .getAssociatedConcepts().iterateAssociatedConcept(); while (associatedTargetsIterator.hasNext()) { AssociatedConcept target = associatedTargetsIterator.next(); Resource targetRsc = model_ .getResource(this.resolveNamespace(target.getCodeNamespace()) + target.getCode()); if (target == null || target.getCode().startsWith("@@")) continue; if (target.getCode().startsWith("@")) { Resource r = processLgAnonymousTarget(target); if (r == null) continue; if (prop.getURI().equals(RDFS.subClassOf.getURI())) { this.createTriple(r, prop, source); } else this.createTriple(source, prop, r); continue; } // qualifier SupportedAssociationQualifier q = this.getLgQualifier(target); if (q != null && prop != null) { if (this.ontFormat_.equals(OntologyFormat.UMLS)) { this.processLgQualifier(source, prop, targetRsc, q.getLocalId(), q.getContent()); } } if (this.ontFormat_.equals(OntologyFormat.UMLS) == false && prop.getURI().equalsIgnoreCase(RDFS.subClassOf.getURI())) { targetRsc = model_.getOntClass(targetRsc.getURI()); this.createTriple(targetRsc, prop, source); } else if (this.ontFormat_.equals(OntologyFormat.UMLS) && prop.getURI().equalsIgnoreCase(RDFS.subClassOf.getURI())) { if (supportedAssn.getLocalId().equals("CHD")) { targetRsc = model_.getOntClass(targetRsc.getURI()); this.createTriple(targetRsc, prop, source); } else if (supportedAssn.getLocalId().equals("PAR")) { this.createTriple(source, prop, targetRsc); } } else this.createTriple(source, prop, targetRsc); } } } } /* * Get Uri according to the name space and code. Apply the hash map if it * isn't owl/rdf ontology */ private String getLgPropertyUri(String ns, String code) throws LBException { if (this.ontFormat_.equals(OntologyFormat.OWLRDF)) return this.resolveNamespace(ns) + code; else { if (LexRdfMap.get(code, ontFormat_) != null) return LexRdfMap.get(code, ontFormat_).getURI(); else return null; } } /** * Create enumerated class -- oneOf. According to the owl loader if there is * anonymous class does not have association target, it could be an * enumerated class. This method checks its property which specify the * enumerated type, and its entity description contains the list of * enumerated things, for instance {instanceA, instanceB, classC}. * * @param anonymousSource * @return * @throws LBException * @throws InvocationTargetException * @throws IllegalAccessException * @throws NoSuchMethodException * @throws IllegalArgumentException * @throws SecurityException */ private Resource createEnumeratedClassFromEmptyAnonymousSource(AssociatedConcept anonymousSource) throws LBException, SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { Entity en = anonymousSource.getEntity(); boolean isOneOf = false; for (org.LexGrid.commonTypes.Property lgProp : en.getProperty()) { if (!lgProp.getPropertyName().equalsIgnoreCase("type")) continue; StringHelper helper = new StringHelper(lgProp.getValue().getContent(), model_.getNsPrefixMap()); if (helper.getStrFormat().equals(StringHelper.StrFormat.PREFIX_TYPE)) { if (helper.getType() != null && helper.getType().getURI().equals(OWL.oneOf.getURI())) { isOneOf = true; break; } } } if (isOneOf == false) return null; if (en.getEntityDescription() != null && en.getEntityDescription().getContent().startsWith("{") && en.getEntityDescription().getContent().endsWith("}")) { String content = en.getEntityDescription().getContent(); content = content.substring(1, content.length() - 1); String[] elements = content.split(" "); if (elements.length == 0) return null; List<RDFNode> rdfList = new ArrayList<RDFNode>(); for (String e : elements) { String code = e.trim(); RDFNode rsc = model_.getResource(this.resolveNamespace(currentNamespace_) + code); rdfList.add(rsc); } return model_.createEnumeratedClass(null, model_.createList(rdfList.iterator())); } return null; } private Resource processLgAnonymousTarget(AssociatedConcept anonymousSource) throws SecurityException, IllegalArgumentException, LBException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { // AssociationList assnList = anonymousSource.getSourceOf(); // anonymous class's getsourceof does not work correct, use cng instead // for now ResolvedConceptReferenceList localRcrl = cng_.resolveAsList(anonymousSource, true, false, 1, -1, null, null, null, null, -1); if (localRcrl == null || localRcrl.getResolvedConceptReferenceCount() == 0) return null; AssociationList assnList = localRcrl.getResolvedConceptReference(0).getSourceOf(); if (assnList == null) { return createEnumeratedClassFromEmptyAnonymousSource(anonymousSource); } Iterator<? extends Association> iteratorAssociations = assnList.iterateAssociation(); // used for intersectionof or unionof List<RDFNode> rdfList = null; Class<?> classHolder = null; for (org.LexGrid.commonTypes.Property lgProp : anonymousSource.getEntity().getProperty()) { // if supported property change, it is not neccessary if (lgProp.getValue().getContent().equalsIgnoreCase(OWL.intersectionOf.getLocalName())) { rdfList = new ArrayList<RDFNode>(); classHolder = IntersectionClass.class; } else if (lgProp.getValue().getContent().equalsIgnoreCase(OWL.unionOf.getLocalName())) { rdfList = new ArrayList<RDFNode>(); classHolder = UnionClass.class; } else if (lgProp.getValue().getContent().equalsIgnoreCase(OWL.complementOf.getLocalName())) { classHolder = ComplementClass.class; } } while (iteratorAssociations.hasNext()) { Association assn = iteratorAssociations.next(); SupportedAssociation suppAssn = this.getLgSupportedAssociation(assn.getAssociationName()); Property localProp = null; if (suppAssn == null) { throw new LBException("no supported assocation found for " + assn.getAssociationName()); } else { localProp = model_.getProperty(this.getLgPropertyUri(suppAssn.getEntityCodeNamespace(), reformatCode(suppAssn.getEntityCode()))); } if (assn.getAssociatedConcepts() == null) continue; Iterator<? extends AssociatedConcept> iteratorConcepts = assn.getAssociatedConcepts() .iterateAssociatedConcept(); while (iteratorConcepts.hasNext()) { AssociatedConcept target = iteratorConcepts.next(); Resource targetRsc = model_ .getResource(this.resolveNamespace(target.getCodeNamespace()) + target.getCode()); if (target.getCode().startsWith("@@")) continue; if (target.getCode().startsWith("@") && anonymousSource.getCode().startsWith("@")) { // target is anonymous class, recursively call itself targetRsc = processLgAnonymousTarget(target); if (targetRsc == null) continue; if (localProp.getURI().equals(OWL.complementOf.getURI())) targetRsc = model_.createComplementClass(null, targetRsc); else { if (localProp.getURI().equals(RDFS.subClassOf.getURI()) == false && localProp.getNameSpace().equals(currentNamespace_)) System.err.println("process anonymous targe error"); } } SupportedAssociationQualifier qualifier = getLgQualifier(target); Restriction restriction = null; if (localProp != null && qualifier != null) { restriction = createRestriction(qualifier, localProp, targetRsc); } if (rdfList != null) { if (restriction != null) rdfList.add(restriction); else if (localProp != null && localProp.getURI().equals(OWL.complementOf.getURI())) { targetRsc = model_.createComplementClass(null, targetRsc); } rdfList.add(targetRsc); } else { if (restriction != null) if (classHolder != null && classHolder.equals(ComplementClass.class) == true) { return model_.createComplementClass(null, restriction); } else { return restriction; } else if (classHolder != null && classHolder.equals(ComplementClass.class) == true) { return model_.createComplementClass(null, targetRsc); } else { return targetRsc; } } } } if (rdfList != null && rdfList.size() > 1) { return this.createIntersectionOrUnionClass(classHolder, rdfList); } else return null; } private void createTriple(Resource s, Property p, Resource o) { if (s == null || p == null || o == null) return; try { if (p.getURI().equals(OWL.equivalentClass.getURI())) { ((OntClass) s).addEquivalentClass(o); } else if (p.getURI().equals(OWL.disjointWith.getURI())) { ((OntClass) s).addDisjointWith(o); } else if (p.getURI().equals(OWL.differentFrom.getURI())) { ((OntClass) s).addDifferentFrom(o); } else if (p.getURI().equals(OWL.sameAs.getURI())) { ((OntClass) s).addSameAs(o); } else if (p.getURI().equals(RDFS.isDefinedBy.getURI())) { ((OntClass) s).addIsDefinedBy(o); } else if (p.getURI().equals(RDFS.seeAlso.getURI())) { ((OntClass) s).addSeeAlso(o); } else if (p.getURI().equals(RDFS.subClassOf.getURI())) { ((OntClass) s).addSubClass(o); } else if (p.getURI().equals(RDFS.domain)) { ((OntProperty) s).addDomain(o); } else if (p.getURI().equals(RDFS.range)) { ((OntProperty) s).addRange(o); } else if (p.getURI().equals(OWL.complementOf.getURI())) { if (s.getURI() == null) s = model_.createComplementClass(null, o); else model_.createComplementClass(s.getURI(), o); } else { s.addProperty(p, o); } } catch (Exception e) { messenger_.error(e.toString()); } } private Restriction createRestriction(SupportedAssociationQualifier q, Property p, Resource r) { if (q.getUri().equalsIgnoreCase(OWL.someValuesFrom.getURI())) return model_.createSomeValuesFromRestriction(null, p, r); else if (q.getUri().equalsIgnoreCase(OWL.allValuesFrom.getURI())) return model_.createAllValuesFromRestriction(null, p, r); else if (q.getUri().equalsIgnoreCase(OWL.hasValue.getURI())) return model_.createHasValueRestriction(null, p, r); /** * We cannot create max cardinality and min cardinality restrictions, * since the associatedData does not support the qualifier for now. We * will add this feature in the next release */ // else if (q.getUri().equalsIgnoreCase(OWL.maxCardinality.getURI())) // return model_.createMaxCardinalityRestriction(null, p, n); // else if (q.getUri().equalsIgnoreCase(OWL.minCardinality.getURI())) // return model_.createMinCardinalityRestriction(null, p, n); else return null; } // create intersection class or union class private Resource createIntersectionOrUnionClass(Class<?> cls, List<RDFNode> rdfList) throws LBException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { final String prefix = "create"; Method m = model_.getClass().getMethod(prefix + cls.getSimpleName(), String.class, RDFList.class); m.setAccessible(true); return (Resource) m.invoke(model_, null, model_.createList(rdfList.iterator())); } // Only consider one qualifier private SupportedAssociationQualifier getLgQualifier(AssociatedConcept concept) throws SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { NameAndValueList nameValueList = concept.getAssociationQualifiers(); if (nameValueList != null && nameValueList.getNameAndValueCount() > 0) { for (NameAndValue nameAndValue : nameValueList.getNameAndValue()) { // qualifier is saved in name field if (StringUtils.isEmpty(nameAndValue.getName()) == false) { return DaoUtility.getURIMap(cs_, SupportedAssociationQualifier.class, nameAndValue.getName()); } } } return null; } // private boolean isAssociationSourceProcessed(ResolvedConceptReference // rcr) { // return this.sourceCache.exists(rcr); // } private void addOntProperty(Entity entity) throws LBException, SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { // if it maps to owl/rdf properties, we don't need to add it if (LexRdfMap.isMapped(entity, ontFormat_) == true) return; String namespace = resolveNamespace(entity.getEntityCodeNamespace()); OntProperty ontProperty; /* * If it is owl, create a general property and use lgproperty to define * what type of property it is if is not an owl ontology, create an * object property. */ if (ontFormat_.equals(OntologyFormat.OWLRDF)) ontProperty = model_.createOntProperty(namespace + reformatCode(entity.getEntityCode())); else ontProperty = model_.createObjectProperty(namespace + reformatCode(entity.getEntityCode())); if (entity instanceof AssociationEntity && ((AssociationEntity) entity).isIsTransitive() != null && ((AssociationEntity) entity).isIsTransitive() == true) { ontProperty.addRDFType(OWL.TransitiveProperty); } for (org.LexGrid.commonTypes.Property property : entity.getProperty()) { processLgProperty(ontProperty, property); } } private void processLgProperty(OntProperty ontProperty, org.LexGrid.commonTypes.Property property) throws LBException, SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { // get supported property SupportedProperty supProp = DaoUtility.getURIMap(cs_, SupportedProperty.class, property.getPropertyName()); if (supProp == null) { throw new LBException("no supported property found for " + property.getPropertyName()); } if (supProp.getUri().equalsIgnoreCase(RDFS.domain.getURI())) { String id = resolveNamespace(currentNamespace_) + trimLocalId(property.getValue().getContent()); this.createTriple(ontProperty, model_.getProperty(supProp.getUri()), model_.getResource(id)); } else if (supProp.getUri().equalsIgnoreCase(OWL.inverseOf.getURI())) { StringHelper sh = new StringHelper(property.getValue().getContent(), model_.getNsPrefixMap()); if (sh.getStrFormat().equals(StringHelper.StrFormat.TYPE_VALUE)) { OntProperty localProperty = model_.createOntProperty(trimLocalId(sh.getValue())); localProperty.addRDFType(sh.getType()); ontProperty.addInverseOf(localProperty); } else throw new LBException("invalid property value"); } else if (supProp.getUri().equalsIgnoreCase(RDFS.range.getURI())) { String id = resolveNamespace(currentNamespace_) + this.trimLocalId(property.getValue().getContent()); this.createTriple(ontProperty, model_.getProperty(supProp.getUri()), model_.getResource(id)); } else if (supProp.getUri().equalsIgnoreCase(RDF.type.getURI())) { StringHelper sh = new StringHelper(property.getValue().getContent(), model_.getNsPrefixMap()); if (sh.getStrFormat() != null) ontProperty.addRDFType(sh.getType()); else { Resource ontType = LexRdfMap.get(property.getValue().getContent(), ontFormat_); if (ontType != null) ontProperty.addRDFType(ontType); } } else if (supProp.getUri().equalsIgnoreCase(RDFS.subPropertyOf.getURI())) { StringHelper sh = new StringHelper(property.getValue().getContent(), model_.getNsPrefixMap()); OntProperty localProperty = model_.createOntProperty(sh.getValue()); localProperty.addRDFType(sh.getType()); // ontProperty.addSubProperty(localProperty); localProperty.addSubProperty(ontProperty); } else if (supProp.getUri().equalsIgnoreCase(OWL.equivalentProperty.getURI())) { StringHelper sh = new StringHelper(property.getValue().getContent(), model_.getNsPrefixMap()); if (sh.getStrFormat() == StringHelper.StrFormat.TYPE_VALUE) ontProperty.addEquivalentProperty(model_.getProperty(sh.getValue())); } else if (supProp.getUri().equalsIgnoreCase(RDFS.label.getURI())) { // do nothing. label will be map to presentation } else { System.err.println("attention, not inlucded property, create annotation property for: " + property.getPropertyName() + ": " + property.getValue().getContent()); AnnotationProperty annotationProp = model_.createAnnotationProperty( this.resolveNamespace(currentNamespace_) + property.getPropertyName()); ontProperty.addProperty(annotationProp, property.getValue().getContent()); } } private void processInstance(List<Entity> instanceList) throws LBException { /* * find the if this instance has defined type in the association table, * if it does, create a that type of class, if the instance has no * defined type, map it to owl:thing */ for (Entity entity : instanceList) { CodedNodeGraph localCng = this.restrictToCngAssociation(RDF.type.getLocalName()); ConceptReference sourceConRef = new ConceptReference(); sourceConRef.setCode(entity.getEntityCode()); sourceConRef.setCodeNamespace(entity.getEntityCodeNamespace()); sourceConRef.setCodingSchemeName(cs_.getCodingSchemeName()); sourceConRef.setConceptCode(entity.getEntityCode()); ResolvedConceptReferenceList resolvedConRefList = localCng.resolveAsList(sourceConRef, true, false, 0, 1, null, null, null, -1); // resolvedConRefList size is always one if (resolvedConRefList.getResolvedConceptReferenceCount() == 0 || resolvedConRefList.getResolvedConceptReferenceCount() > 1) { throw new LBException("CNG resolve as list failed"); } AssociationList associationList = resolvedConRefList.getResolvedConceptReference(0).getSourceOf(); if (associationList == null || associationList.getAssociation(0) == null || associationList.getAssociation(0).getAssociatedConcepts().getAssociatedConceptCount() == 0) // no specific type, treat it as owl:thing this.addOwlThing(model_, cs_, entity); else { // specific type for (AssociatedConcept target : associationList.getAssociation(0).getAssociatedConcepts() .getAssociatedConcept()) { String namespace = this.resolveNamespace(entity.getEntityCodeNamespace()); OntResource resource = model_ .createOntResource(namespace + reformatCode(entity.getEntityCode())); OntResource typeResource = model_ .getOntResource(this.resolveNamespace(target.getCodeNamespace()) + target.getCode()); if (typeResource == null) { typeResource = model_.createOntResource( this.resolveNamespace(target.getCodeNamespace()) + target.getCode()); } resource.addRDFType(typeResource); } } } } // if the instance has not defined type, map it to owl:thing private void addOwlThing(OntModel model, CodingScheme cs, Entity entity) throws LBException { String namespace = this.resolveNamespace(entity.getEntityCodeNamespace()); OntResource resource = model.createOntResource(namespace + reformatCode(entity.getEntityCode())); resource.addRDFType(OWL.Thing); } private void addSkosConcept(Entity entity) throws LBException { System.out.println("SKOS!!!!!!"); // for dev String namespace = this.resolveNamespace(entity.getEntityCodeNamespace()); OntResource resource = model_.createOntResource(namespace + reformatCode(entity.getEntityCode())); resource.addRDFType(Skos.Concept); Map<String, ReifiedStatement> statementHash = new HashMap<String, ReifiedStatement>(); // handle entity's comments for (Comment comment : entity.getComment()) { this.addLgCommentOrDefinitionOrPresentation(resource, Skos.note, comment, statementHash); } // handle entity's definition for (Definition def : entity.getDefinition()) { this.addLgCommentOrDefinitionOrPresentation(resource, Skos.definition, def, statementHash); } // handle entity's presentation for (Presentation presentation : entity.getPresentation()) { if (presentation.getIsPreferred() == true) { this.addLgCommentOrDefinitionOrPresentation(resource, Skos.prefLabel, presentation, statementHash); } else { this.addLgCommentOrDefinitionOrPresentation(resource, Skos.altLabel, presentation, statementHash); } } // handle property links for (PropertyLink propLink : entity.getPropertyLink()) { AnnotationProperty ap = model_.createAnnotationProperty(namespace + propLink.getPropertyLink()); String sourceProp = propLink.getSourceProperty(); String targetProp = propLink.getTargetProperty(); statementHash.get(sourceProp).addProperty(ap, statementHash.get(targetProp).getURI()); } } private void addOwlClass(Entity entity) throws LBException, SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { String namespace = this.resolveNamespace(entity.getEntityCodeNamespace()); // add owl class OntClass owlClass = model_.createClass(namespace + reformatCode(entity.getEntityCode())); // set rdf:isDefined if (entity.isIsDefined() != null) owlClass.addProperty(LexRdf.isDefined, entity.isIsDefined().toString()); Map<String, ReifiedStatement> statementHash = new HashMap<String, ReifiedStatement>(); // handle entity's comments for (Comment comment : entity.getComment()) { this.addLgCommentOrDefinitionOrPresentation(owlClass, Skos.note, comment, statementHash); } // handle entity's definition for (Definition def : entity.getDefinition()) { this.addLgCommentOrDefinitionOrPresentation(owlClass, Skos.definition, def, statementHash); } // handle entity's presentation for (Presentation presentation : entity.getPresentation()) { if (presentation.getIsPreferred() != null && presentation.getIsPreferred() == true) { this.addLgCommentOrDefinitionOrPresentation(owlClass, Skos.prefLabel, presentation, statementHash); } else { this.addLgCommentOrDefinitionOrPresentation(owlClass, Skos.altLabel, presentation, statementHash); } } // handle entity's property for (org.LexGrid.commonTypes.Property lgProp : entity.getProperty()) { SupportedProperty supProp = DaoUtility.getURIMap(cs_, SupportedProperty.class, lgProp.getPropertyName()); String uri = supProp.getUri(); if (StringUtils.isBlank(uri) && StringUtils.isNotBlank(lgProp.getPropertyName())) { uri = resolveNamespace(""); uri += lgProp.getPropertyName(); } if (StringUtils.isNotBlank(uri)) { owlClass.addLiteral(model_.getProperty(uri), lgProp.getValue().getContent()); } } // handle property links for (PropertyLink propLink : entity.getPropertyLink()) { AnnotationProperty ap = model_.createAnnotationProperty(namespace + propLink.getPropertyLink()); String sourceProp = propLink.getSourceProperty(); String targetProp = propLink.getTargetProperty(); statementHash.get(sourceProp).addProperty(ap, statementHash.get(targetProp).getURI()); } } // only a regular mapping from lg:property's value to // comment/definition/presentation. not necessary to consider the property // name private void addLgCommentOrDefinitionOrPresentation(OntResource resource, Property prop, org.LexGrid.commonTypes.Property lgProp, Map<String, ReifiedStatement> statementHash) { Statement statement = model_.createStatement(resource, prop, lgProp.getValue().getContent()); ReifiedStatement rs = model_.createReifiedStatement(statement); // general stuff for comment/definition/presentation if (StringUtils.isNotBlank(lgProp.getLanguage())) rs.addProperty(DC.language, lgProp.getLanguage()); for (Source source : lgProp.getSource()) { if (StringUtils.isEmpty(source.getContent()) == false) rs.addProperty(DC.source, source.getContent()); } if (lgProp instanceof Definition) { if (((Definition) lgProp).isIsPreferred() != null && ((Definition) lgProp).isIsPreferred() == true) rs.addProperty(LexRdf.isPreferred, "true"); } else if (lgProp instanceof Presentation) { if (StringUtils.isEmpty(((Presentation) lgProp).getDegreeOfFidelity()) == false) rs.addProperty(LexRdf.degreeOfFidelity, ((Presentation) lgProp).getDegreeOfFidelity()); if (((Presentation) lgProp).getMatchIfNoContext() != null && ((Presentation) lgProp).getMatchIfNoContext() == true) rs.addProperty(LexRdf.matchIfNoContext, ((Presentation) lgProp).getMatchIfNoContext().toString()); if (StringUtils.isEmpty(((Presentation) lgProp).getRepresentationalForm()) == false) rs.addProperty(LexRdf.representationalForm, ((Presentation) lgProp).getRepresentationalForm()); } statementHash.put(lgProp.getPropertyId(), rs); } private String resolveNamespace(String localId) throws LBException { Map<String, String> supportedNamespace = model_.getNsPrefixMap(); String uri; if (StringUtils.isBlank(localId)) { uri = supportedNamespace.get(currentNamespace_); } else { String nmTokenLocalId = convertToNMTokenString(localId); uri = supportedNamespace.get(nmTokenLocalId); } if (uri != null) { if (!uri.endsWith("#") && !uri.endsWith("/") && !uri.endsWith(":")) uri = uri + "#"; } // for dev only if (uri == null) throw new LBException("ns " + localId + " has not been imported to ontology yet!"); return uri; } /** * Remove "/" and ":" from the strings of the code field * @param code * @return */ private String reformatCode(String code) { String formattedCode = code.replace("/", "_").replace(":", "_"); return formattedCode; } private String trimLocalId(String localId) { if (localId.startsWith(this.currentNamespace_ + ":")) return localId.replace(this.currentNamespace_ + ":", ""); return localId; } private void initNamespace() { Map<String, String> nsMap = new HashMap<String, String>(); // skos nsMap.put(LexRdfConstants.SKOS_NS_PREFIX, LexRdfConstants.SKOS_NS_URI); // lexrdf nsMap.put(LexRdfConstants.LEXRDF_NS_PREFIX, LexRdfConstants.LEXRDF_NS_URI); // add codingSchemeURI currentNamespace_ = model_.getOntology(cs_.getCodingSchemeURI()).getLabel(null); nsMap.put("", cs_.getCodingSchemeURI()); nsMap.put(currentNamespace_, cs_.getCodingSchemeURI() + "#"); // check coding scheme mappings if (cs_.getMappings() != null) { // supported namespace SupportedNamespace[] supportedNss = cs_.getMappings().getSupportedNamespace(); for (SupportedNamespace ns : supportedNss) { String nmTokenLocalId = convertToNMTokenString(ns.getLocalId()); if (StringUtils.isNotBlank(nmTokenLocalId) && StringUtils.isNotBlank(ns.getUri())) { nsMap.put(nmTokenLocalId, ns.getUri()); } } // supported associations if (ontFormat_.equals(OntologyFormat.OWLRDF)) { SupportedAssociation[] supportedAssns = cs_.getMappings().getSupportedAssociation(); for (SupportedAssociation assn : supportedAssns) { if (assn.getUri() != null) { model_.createOntProperty(assn.getUri()); } } } } model_.setNsPrefixes(nsMap); } /* * when we need to put restrictions on cng, we need to create a copy of it * and run on it, the queries and restrictions can change the cng itself. */ private CodedNodeGraph restrictToCngAssociation(String restriction) throws LBException { LexBIGService lbsvc = LexBIGServiceImpl.defaultInstance(); CodingSchemeVersionOrTag versionOrTag = new CodingSchemeVersionOrTag(); versionOrTag.setVersion(cs_.getRepresentsVersion()); CodedNodeGraph localCng; localCng = lbsvc.getNodeGraph(cs_.getCodingSchemeURI(), versionOrTag, null); localCng.restrictToAssociations(Constructors.createNameAndValueList(restriction), null); return cng_.intersect(localCng); } private OntologyFormat findOntFormat() { for (org.LexGrid.commonTypes.Property p : cs_.getProperties().getProperty()) { if (p.getPropertyName().equals(OntologyFormat.getMetaName())) { return OntologyFormat.valueOf(p.getValue().getContent()); } } return null; } public void toTripleStore(CodingScheme cs, CodedNodeGraph baseCng, CodedNodeSet cns, Writer writer, LgMessageDirectorIF messenger, OntologyFormat ontFormat) { this.cs_ = cs; this.cns_ = cns; this.cng_ = baseCng; this.messenger_ = messenger; this.writer_ = writer; if (ontFormat != null) this.ontFormat_ = ontFormat; else ontFormat_ = this.findOntFormat(); Model baseModel; try { baseModel = this.getBaseModel(cs.getCodingSchemeURI()); // create or open the default model model_ = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, baseModel); // clean up the triple store to load store_.getTableFormatter().truncate(); // coding schema mapping this.codingSchemeMapping(); // entity mapping this.entityMapping(); // association mapping this.associationMapping(); // model_.write(System.out); // for dev & test/ // now write the model in XML form to a file this.toOwlOntology(cs_.getCodingSchemeURI()); } catch (Exception ex) { this.messenger_.error(ex.toString()); ex.printStackTrace(); } // Close the database connection model_.close(); store_.getConnection().close(); } public void toOwlOntology(String iri) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException { messenger_.info("Converting triple store to ontology ..."); Model baseModel = this.getBaseModel(iri); OntModel localModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, baseModel); RDFWriter rdfw = localModel.getWriter(LexRdfConstants.RDFXML_ABBREV); rdfw.setProperty(LexRdfConstants.SHOW_XML_DECLARATION, true); rdfw.setProperty(LexRdfConstants.XML_BASE, cs_.getCodingSchemeURI()); rdfw.setProperty(LexRdfConstants.RELATIVE_URIS, ""); // FileOutputStream f = new FileOutputStream(outputFile_); rdfw.write(localModel, writer_, cs_.getCodingSchemeURI()); baseModel.close(); } public static void main(String[] args) { ExportStatus status = new ExportStatus(); status.setState(ProcessState.PROCESSING); status.setStartTime(new Date(System.currentTimeMillis())); ExporterMessageDirector md = new ExporterMessageDirector("LexRdfExporter", status); // String codingSchemeUri = // "http://www.xfront.com/owl/ontologies/camera/", // codingSchemeVersion = "UNASSIGNED", // output = "c:/temp/camera.owl"; // String codingSchemeUri = "http://purl.org/net/OCRe/OCRe-Start-Here", // codingSchemeVersion = "UNASSIGNED", // output = "c:/temp/ocre.owl"; // String codingSchemeUri = // "http://www.co-ode.org/ontologies/pizza/2005/05/16/pizza.owl", // codingSchemeVersion = "version 1.2", // output = "C:/temp/pizza.owl"; String codingSchemeUri = "http://www.w3.org/TR/2003/PR-owl-guide-20031209/wine", codingSchemeVersion = "UNASSIGNED", output = "C:/temp/wine.owl"; // String codingSchemeUri = "urn:lsid:bioontology.org:cell", // codingSchemeVersion = "UNASSIGNED", // output = "c:/temp/cell_obo.owl"; // String codingSchemeUri = "urn:lsid:bioontology.org:uberon", // codingSchemeVersion = "UNASSIGNED"; // String codingSchemeUri = "urn:oid:2.16.840.1.113883.6.110", // codingSchemeVersion = "1993.bvt", // output = "c:/temp/umls.owl"; LexGridToOwlRdfConverter converter = new LexGridToOwlRdfConverter(); CodingSchemeVersionOrTag versionOrTag = new CodingSchemeVersionOrTag(); versionOrTag.setVersion(codingSchemeVersion); LexBIGService lbsvc = LexBIGServiceImpl.defaultInstance(); try { CodingScheme codingScheme = lbsvc.resolveCodingScheme(codingSchemeUri, Constructors.createCodingSchemeVersionOrTagFromVersion(codingSchemeVersion)); CodedNodeSet cns = lbsvc.getNodeSet(codingSchemeUri, versionOrTag, null); CodedNodeGraph cng = lbsvc.getNodeGraph(codingSchemeUri, versionOrTag, null); FileOutputStream f = new FileOutputStream(output); Writer w = new OutputStreamWriter(f); converter.toTripleStore(codingScheme, cng, cns, w, md, null); } catch (LBException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } public static String convertToNMTokenString(String str) { if (StringUtils.isBlank(str)) return str; String conv = str.trim().replaceAll("\\s+", "_"); conv = conv.replace('/', '_'); conv = conv.replaceAll("[^a-zA-Z0-9._-]", ""); if (conv.length() > 1 && conv.substring(0, 1).matches("[0-9]")) conv = "_" + conv; return conv; } }