package io.lumify.palantir.ontologyToOwl; import io.lumify.core.exception.LumifyException; import io.lumify.core.model.properties.LumifyProperties; import io.lumify.core.util.LumifyLogger; import io.lumify.core.util.LumifyLoggerFactory; import io.lumify.palantir.DataToSequenceFile; import io.lumify.palantir.model.PtPropertyType; import io.lumify.palantir.service.Exporter; import io.lumify.palantir.util.XmlUtil; import org.apache.commons.codec.binary.Base64; import org.apache.hadoop.fs.*; import org.json.JSONObject; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.SAXException; import javax.xml.namespace.NamespaceContext; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class OntologyToOwl implements Exporter { private static final LumifyLogger LOGGER = LumifyLoggerFactory.getLogger(OntologyToOwl.class); public static final String INVERSE_SUFFIX = "_inverse"; private final String baseIri; private Element exportRootElement; private Document exportDoc; private Document linkRelationsXml; private Document imageInfoXml; private DocumentBuilder docBuilder; private TitleFormulaMaker titleFormulaMaker; private Map<String, ObjectProperty> objectProperties = new HashMap<>(); private Map<String, DataTypeProperty> dataTypeProperties = new HashMap<>(); private Map<String, List<OwlElement>> iconMapping = new HashMap<>(); private Map<String, String> typeGroupUriToDisplayNames = new HashMap<>(); private NamespaceContext ns; public OntologyToOwl(String baseIri) { if (baseIri.endsWith("#")) { baseIri = baseIri.substring(0, baseIri.length() - 1); } this.baseIri = baseIri; this.titleFormulaMaker = new TitleFormulaMaker(); } @Override public void run(ExporterSource exporterSource) throws Exception { run(exporterSource.getFileSystem(), exporterSource.getDestinationPath()); } @Override public Class getObjectClass() { return OntologyToOwl.class; } public void run(FileSystem fs, Path destinationPath) throws Exception { Path outPath = new Path(destinationPath, "owl"); ns = XmlUtil.getNamespaceContext(); DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); docFactory.setNamespaceAware(true); docBuilder = docFactory.newDocumentBuilder(); exportDoc = docBuilder.newDocument(); exportRootElement = exportDoc.createElementNS(ns.getNamespaceURI("rdf"), "rdf:RDF"); exportRootElement.setAttribute("xmlns:rdf", ns.getNamespaceURI("rdf")); exportRootElement.setAttribute("xmlns:owl", ns.getNamespaceURI("owl")); exportRootElement.setAttribute("xmlns:rdfs", ns.getNamespaceURI("rdfs")); exportRootElement.setAttribute("xmlns:lumify", ns.getNamespaceURI("lumify")); exportDoc.appendChild(exportRootElement); Element ontologyElement = exportDoc.createElementNS(ns.getNamespaceURI("owl"), "owl:Ontology"); ontologyElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:about", baseIri); exportRootElement.appendChild(ontologyElement); Element importsElement = exportDoc.createElementNS(ns.getNamespaceURI("owl"), "owl:imports"); importsElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:resource", "http://lumify.io"); ontologyElement.appendChild(importsElement); runOnDir(fs, outPath, new Path(destinationPath, DataToSequenceFile.ONTOLOGY_XML_DIR_NAME)); if (linkRelationsXml == null) { LOGGER.warn("Could not find link relations xml."); } else { runOnLinkRelationsXml(linkRelationsXml); writeLinkRelations(); } if (imageInfoXml == null) { LOGGER.warn("Could not find image info xml."); } else { runOnImageInfoXml(fs, outPath, imageInfoXml); } TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); DOMSource source = new DOMSource(exportDoc); try (OutputStream out = fs.create(new Path(outPath, "palantir.owl"), true)) { StreamResult result = new StreamResult(out); transformer.transform(source, result); } } private void runOnImageInfoXml(FileSystem fs, Path destinationPath, Document imageInfoXml) { List<Element> imageInfoConfigs = XmlUtil.getXmlElements(imageInfoXml, "/image_infos/image_info_config"); for (Element imageInfoConfig : imageInfoConfigs) { try { runOnImageInfoConfig(fs, destinationPath, imageInfoConfig); } catch (Exception ex) { LOGGER.error("Could not process: %s", imageInfoConfig.toString(), ex); } } } private void runOnImageInfoConfig(FileSystem fs, Path destinationPath, Element imageInfoConfig) throws IOException { String uri = XmlUtil.getXmlString(imageInfoConfig, "uri"); String path = XmlUtil.getXmlString(imageInfoConfig, "path"); if (path.startsWith("/")) { path = path.substring(1); } Path expectedFilePath = new Path(destinationPath, path); if (!fs.exists(expectedFilePath)) { throw new LumifyException("Could not find file for uri " + uri + " with path " + expectedFilePath.toString()); } List<OwlElement> owlElements = iconMapping.get(uri); if (owlElements == null) { LOGGER.warn("Could not find owl elements for icon mapping with uri: %s", uri); return; } for (OwlElement owlElement : owlElements) { Element glyphIconFileNameElement = exportDoc.createElementNS(ns.getNamespaceURI("lumify"), "lumify:glyphIconFileName"); glyphIconFileNameElement.appendChild(exportDoc.createTextNode(path)); owlElement.getElement().appendChild(glyphIconFileNameElement); } } private void writeLinkRelations() { writeObjectPropertyLinkRelations(); writeDataTypePropertyLinkRelations(); } private void writeDataTypePropertyLinkRelations() { for (DataTypeProperty dataTypeProperty : dataTypeProperties.values()) { if (dataTypeProperty.getTypeGroupUri() != null) { String propertyGroupName = this.typeGroupUriToDisplayNames.get(dataTypeProperty.getTypeGroupUri()); if (propertyGroupName != null) { Element propertyGroupElement = exportDoc.createElementNS(ns.getNamespaceURI("lumify"), "lumify:propertyGroup"); propertyGroupElement.appendChild(exportDoc.createTextNode(propertyGroupName)); dataTypeProperty.getElement().appendChild(propertyGroupElement); } } for (String domainUri : dataTypeProperty.getDomainUris()) { Element domainElement = exportDoc.createElementNS(ns.getNamespaceURI("rdfs"), "rdfs:domain"); domainElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:resource", domainUri); dataTypeProperty.getElement().appendChild(domainElement); for (Element relatedPropertyElement : dataTypeProperty.getRelatedPropertyElements()) { domainElement = exportDoc.createElementNS(ns.getNamespaceURI("rdfs"), "rdfs:domain"); domainElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:resource", domainUri); relatedPropertyElement.appendChild(domainElement); } } } } private void writeObjectPropertyLinkRelations() { for (ObjectProperty objectProperty : objectProperties.values()) { for (String domainUri : objectProperty.getDomainUris()) { Element domainElement = exportDoc.createElementNS(ns.getNamespaceURI("rdfs"), "rdfs:domain"); domainElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:resource", domainUri); objectProperty.getElement().appendChild(domainElement); } for (String rangeUri : objectProperty.getRangeUris()) { Element rangeElement = exportDoc.createElementNS(ns.getNamespaceURI("rdfs"), "rdfs:range"); rangeElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:resource", rangeUri); objectProperty.getElement().appendChild(rangeElement); } } } private void runOnDir(FileSystem fs, Path outPath, Path inDir) throws IOException { LOGGER.debug("Processing dir: " + inDir.toString()); FileStatus[] files = fs.listStatus(inDir); if (files == null) { return; } for (FileStatus f : files) { if (f.isDirectory()) { runOnDir(fs, outPath, f.getPath()); continue; } if (f.isFile()) { try { runOnFile(fs, outPath, f); } catch (Throwable e) { LOGGER.error("Could not process: %s", f.getPath().toString(), e); } } } } @SuppressWarnings("StatementWithEmptyBody") private void runOnFile(FileSystem fs, Path outPath, FileStatus inFile) throws IOException, SAXException { LOGGER.debug("processing file: %s", inFile.getPath().toString()); if (!inFile.getPath().getName().toLowerCase().endsWith(".xml")) { LOGGER.warn("skipping file: %s", inFile.toString()); return; } Document inXml; try (FSDataInputStream in = fs.open(inFile.getPath())) { inXml = docBuilder.parse(in); } LOGGER.info("processing %s xml: %s", inXml.getDocumentElement().getNodeName(), inFile.toString()); if (inXml.getDocumentElement().getNodeName().equals("pt_object_type_config")) { runOnObjectTypeConfig(inXml); } else if (inXml.getDocumentElement().getNodeName().equals("ontology_resource_config")) { runOnOntologyResourceConfig(fs, outPath, inXml); } else if (inXml.getDocumentElement().getNodeName().equals("ontologyExportInfo")) { // skip } else if (inXml.getDocumentElement().getNodeName().equals("link_type_config")) { runOnLinkTypeConfig(inXml); } else if (inXml.getDocumentElement().getNodeName().equals("property_type_config")) { runOnPropertyTypeConfig(inXml); } else if (inXml.getDocumentElement().getNodeName().equals("node_display_type_config")) { // skip } else if (inXml.getDocumentElement().getNodeName().equals("type_group_config")) { runOnTypeGroupConfig(inXml); } else if (inXml.getDocumentElement().getNodeName().equals("link_relations")) { linkRelationsXml = inXml; } else if (inXml.getDocumentElement().getNodeName().equals("image_infos")) { imageInfoXml = inXml; } else { throw new LumifyException("Invalid xml root node name: " + inXml.getDocumentElement().getNodeName()); } } private void runOnTypeGroupConfig(Document inXml) { String uri = XmlUtil.getXmlString(inXml, "/type_group_config/uri"); if (uri == null || uri.trim().length() == 0) { throw new LumifyException("Invalid type group config, null or empty uri"); } String displayName = XmlUtil.getXmlString(inXml, "/type_group_config/displayName"); if (displayName == null || displayName.trim().length() == 0) { throw new LumifyException("Invalid type group config, null or empty displayName"); } typeGroupUriToDisplayNames.put(uri, displayName); } private void runOnOntologyResourceConfig(FileSystem fs, Path outPath, Document inXml) throws IOException { String path = XmlUtil.getXmlString(inXml, "/ontology_resource_config/path"); String contents = XmlUtil.getXmlString(inXml, "/ontology_resource_config/contents"); if (path.startsWith("/")) { path = path.substring(1); } byte[] data = Base64.decodeBase64(contents); try (FSDataOutputStream out = fs.create(new Path(outPath, path))) { out.write(data); } } private void runOnLinkRelationsXml(Document linkRelationsXml) { List<Element> linkRelationConfigs = XmlUtil.getXmlElements(linkRelationsXml, "/link_relations/link_relation_config"); for (Element linkRelationConfig : linkRelationConfigs) { try { runOnLinkRelationConfig(linkRelationConfig); } catch (Exception ex) { LOGGER.error("Could not process: %s", linkRelationConfig.toString(), ex); } } } private void runOnLinkRelationConfig(Element linkRelationConfig) { String uri1 = XmlUtil.getXmlString(linkRelationConfig, "uri1"); String uri2 = XmlUtil.getXmlString(linkRelationConfig, "uri2"); String linkUri = XmlUtil.getXmlString(linkRelationConfig, "linkUri"); LOGGER.info("processing %s, %s, %s", uri1, uri2, linkUri); // TODO linkStatus ??? // TODO hidden ??? // TODO tableType1 or tableType2 ??? if ("com.palantir.link.Simple".equals(linkUri)) { DataTypeProperty dataTypeProperty = dataTypeProperties.get(uri2); if (dataTypeProperty != null) { dataTypeProperty.addDomain(uriToIri(uri1)); return; } } ObjectProperty objectProperty = objectProperties.get(linkUri); if (objectProperty != null) { objectProperty.addDomain(uriToIri(uri2)); objectProperty.addRange(uriToIri(uri1)); ObjectProperty objectPropertyInverse = objectProperties.get(linkUri + INVERSE_SUFFIX); if (objectPropertyInverse != null) { objectPropertyInverse.addDomain(uriToIri(uri2)); objectPropertyInverse.addRange(uriToIri(uri1)); } return; } throw new LumifyException("Could not find a object property or data type property matching '" + linkUri + "' or '" + uri2 + "'"); } private void runOnPropertyTypeConfig(Document inXml) { String uri = XmlUtil.getXmlString(inXml, "/property_type_config/uri"); String label = XmlUtil.getXmlString(inXml, "/property_type_config/type/displayName"); String comment = XmlUtil.getXmlString(inXml, "/property_type_config/description"); String gisEligibleString = XmlUtil.getXmlString(inXml, "/property_type_config/type/gisEligible"); String typeGroupUri = XmlUtil.getXmlString(inXml, "/property_type_config/typeGroups/typeGroup/uri"); List<Element> entryElements = XmlUtil.getXmlElements(inXml, "/property_type_config/type/enumeration/entry"); List<Element> componentElements = XmlUtil.getXmlElements(inXml, "/property_type_config/type/components/component"); String propertyIri = uriToIri(uri); String propertyRange = getPropertyRange(inXml.getDocumentElement()); boolean gisEligible; if (gisEligibleString == null) { gisEligible = false; } else { gisEligible = Boolean.parseBoolean(gisEligibleString); } boolean hasGisButNoComponents = gisEligible && (componentElements == null || componentElements.size() == 0); Element datatypePropertyElement = createDatatypePropertyElement(propertyIri); DataTypeProperty dataTypeProperty = new DataTypeProperty(propertyIri, datatypePropertyElement, typeGroupUri); addLabel(datatypePropertyElement, label); dataTypeProperty.addRelatedPropertyElement(createErrorPropertyElement(propertyIri, label)); if (hasGisButNoComponents) { addRange(datatypePropertyElement, "http://www.w3.org/2001/XMLSchema#string"); String valuePropertyIri = propertyIri + '/' + PtPropertyType.VALUE_SUFFIX; Element datatypePropertyValueElement = createDatatypePropertyElement(valuePropertyIri); addLabel(datatypePropertyValueElement, "Value"); addTextIndexHints(datatypePropertyValueElement); addRange(datatypePropertyValueElement, propertyRange); if (comment != null && comment.length() > 0) { addComments(datatypePropertyValueElement, comment); } if (entryElements.size() > 0) { addPossibleValues(datatypePropertyValueElement, entryElements); } addDependentPropertyIri(dataTypeProperty, valuePropertyIri); dataTypeProperty.addRelatedPropertyElement(datatypePropertyValueElement); dataTypeProperty.addRelatedPropertyElement(createErrorPropertyElement(valuePropertyIri, label)); } else { addTextIndexHints(datatypePropertyElement); addRange(datatypePropertyElement, propertyRange); if (comment != null && comment.length() > 0) { addComments(datatypePropertyElement, comment); } if (entryElements.size() > 0) { addPossibleValues(datatypePropertyElement, entryElements); } } // dependent properties if ((componentElements != null && componentElements.size() > 0) || gisEligible) { List<Element> argsElements = XmlUtil.getXmlElements(inXml, "/property_type_config/display/args/arg"); if (argsElements.size() > 0) { String titleFormula = titleFormulaMaker.create(new TitleFormulaMaker.Options(propertyIri + '/'), argsElements); if (titleFormula.trim().length() > 0) { Element displayFormulaElement = exportDoc.createElementNS(ns.getNamespaceURI("lumify"), "lumify:displayFormula"); displayFormulaElement.appendChild(exportDoc.createCDATASection("\n" + indent(titleFormula, " ") + "\n ")); dataTypeProperty.getElement().appendChild(displayFormulaElement); } } if (componentElements != null) { for (Element componentElement : componentElements) { String componentUri = XmlUtil.getXmlString(componentElement, "uri"); String dependentPropertyIri = propertyIri + '/' + componentUri; addDependentPropertyIri(dataTypeProperty, dependentPropertyIri); runOnPropertyTypeConfigComponent(dataTypeProperty, dependentPropertyIri, componentElement); } } if (gisEligible) { String dependentPropertyIri = propertyIri + PtPropertyType.GIS_SUFFIX; addDependentPropertyIri(dataTypeProperty, dependentPropertyIri); createGisProperty(dataTypeProperty, dependentPropertyIri); } } dataTypeProperties.put(uri, dataTypeProperty); } private void addDependentPropertyIri(DataTypeProperty dataTypeProperty, String dependentPropertyIri) { Element dependentPropertyIriElement = exportDoc.createElementNS(ns.getNamespaceURI("lumify"), "lumify:dependentPropertyIri"); dependentPropertyIriElement.appendChild(exportDoc.createTextNode(dependentPropertyIri)); dataTypeProperty.getElement().appendChild(dependentPropertyIriElement); } private Element createDatatypePropertyElement(String propertyIri) { Element datatypePropertyElement = exportDoc.createElementNS(ns.getNamespaceURI("owl"), "owl:DatatypeProperty"); datatypePropertyElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:about", propertyIri); exportRootElement.appendChild(datatypePropertyElement); return datatypePropertyElement; } private void addPossibleValues(Element datatypePropertyElement, List<Element> entryElements) { JSONObject possibleValues = new JSONObject(); for (Element entryElement : entryElements) { String key = XmlUtil.getXmlString(entryElement, "key"); String value = XmlUtil.getXmlString(entryElement, "value"); possibleValues.put(key, value); } Element possibleValuesElement = exportDoc.createElementNS(ns.getNamespaceURI("lumify"), "lumify:possibleValues"); possibleValuesElement.appendChild(exportDoc.createTextNode("\n" + indent(possibleValues.toString(2), " ") + "\n ")); datatypePropertyElement.appendChild(possibleValuesElement); } private void addComments(Element datatypePropertyElement, String comment) { Element commentElement = exportDoc.createElementNS(ns.getNamespaceURI("rdfs"), "rdfs:comment"); commentElement.appendChild(exportDoc.createTextNode(comment)); datatypePropertyElement.appendChild(commentElement); } private void addRange(Element datatypePropertyElement, String propertyRange) { Element rangeElement = exportDoc.createElementNS(ns.getNamespaceURI("rdfs"), "rdfs:range"); rangeElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:resource", propertyRange); datatypePropertyElement.appendChild(rangeElement); } private void addTextIndexHints(Element datatypePropertyElement) { Element textIndexHintsElement = exportDoc.createElementNS(ns.getNamespaceURI("lumify"), "lumify:textIndexHints"); textIndexHintsElement.appendChild(exportDoc.createTextNode("FULL_TEXT")); datatypePropertyElement.appendChild(textIndexHintsElement); } private void addLabel(Element element, String label) { Element labelElement = exportDoc.createElementNS(ns.getNamespaceURI("rdfs"), "rdfs:label"); labelElement.setAttributeNS(ns.getNamespaceURI("xml"), "xml:lang", "en"); labelElement.appendChild(exportDoc.createTextNode(label)); element.appendChild(labelElement); } private String getPropertyRange(Element element) { String typeString = XmlUtil.getXmlString(element, "type/base"); if (typeString == null) { typeString = XmlUtil.getXmlString(element, "type"); } if ("com.palantir.type.Number".equals(typeString)) { return "http://www.w3.org/2001/XMLSchema#double"; } if ("com.palantir.type.Date".equals(typeString)) { return "http://www.w3.org/2001/XMLSchema#dateTime"; } return "http://www.w3.org/2001/XMLSchema#string"; } private void runOnPropertyTypeConfigComponent(DataTypeProperty dataTypeProperty, String dependentPropertyIri, Element componentElement) { String displayName = XmlUtil.getXmlString(componentElement, "displayName"); Element datatypePropertyElement = createDatatypePropertyElement(dependentPropertyIri); addLabel(datatypePropertyElement, displayName); addTextIndexHints(datatypePropertyElement); Element rangeElement = exportDoc.createElementNS(ns.getNamespaceURI("rdfs"), "rdfs:range"); rangeElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:resource", getPropertyRange(componentElement)); datatypePropertyElement.appendChild(rangeElement); dataTypeProperty.addRelatedPropertyElement(datatypePropertyElement); dataTypeProperty.addRelatedPropertyElement(createErrorPropertyElement(dependentPropertyIri, displayName)); } private void createGisProperty(DataTypeProperty dataTypeProperty, String dependentPropertyIri) { String displayName = "GIS"; Element datatypePropertyElement = createDatatypePropertyElement(dependentPropertyIri); addLabel(datatypePropertyElement, displayName); addTextIndexHints(datatypePropertyElement); Element rangeElement = exportDoc.createElementNS(ns.getNamespaceURI("rdfs"), "rdfs:range"); rangeElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:resource", LumifyProperties.GEO_LOCATION_RANGE); datatypePropertyElement.appendChild(rangeElement); dataTypeProperty.addRelatedPropertyElement(datatypePropertyElement); dataTypeProperty.addRelatedPropertyElement(createErrorPropertyElement(dependentPropertyIri, displayName)); } private Element createErrorPropertyElement(String propertyIri, String displayName) { Element datatypePropertyElement = createDatatypePropertyElement(propertyIri + PtPropertyType.ERROR_SUFFIX); addLabel(datatypePropertyElement, displayName + " Error"); Element searchableElement = exportDoc.createElementNS(ns.getNamespaceURI("lumify"), "lumify:searchable"); searchableElement.appendChild(exportDoc.createTextNode("false")); datatypePropertyElement.appendChild(searchableElement); Element addableElement = exportDoc.createElementNS(ns.getNamespaceURI("lumify"), "lumify:addable"); addableElement.appendChild(exportDoc.createTextNode("false")); datatypePropertyElement.appendChild(addableElement); Element textIndexHintsElement = exportDoc.createElementNS(ns.getNamespaceURI("lumify"), "lumify:textIndexHints"); textIndexHintsElement.appendChild(exportDoc.createTextNode("NONE")); datatypePropertyElement.appendChild(textIndexHintsElement); Element rangeElement = exportDoc.createElementNS(ns.getNamespaceURI("rdfs"), "rdfs:range"); rangeElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:resource", "http://www.w3.org/2001/XMLSchema#string"); datatypePropertyElement.appendChild(rangeElement); return datatypePropertyElement; } private String indent(String stringToIndent, String indentChars) { return indentChars + stringToIndent.replaceAll("\n", "\n" + indentChars); } private void runOnLinkTypeConfig(Document inXml) { String uri = XmlUtil.getXmlString(inXml, "/link_type_config/uri"); String label = XmlUtil.getXmlString(inXml, "/link_type_config/displayName"); List<Element> asymmetricElements = XmlUtil.getXmlElements(inXml, "/link_type_config/asymmetric"); // TODO edgeIconUri ??? // TODO infoIconUri ??? // TODO objectToObject ??? // TODO objectToProperty ??? // TODO systemProperty ??? // TODO typeGroups ??? Element objectPropertyElement = exportDoc.createElementNS(ns.getNamespaceURI("owl"), "owl:ObjectProperty"); objectPropertyElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:about", uriToIri(uri)); exportRootElement.appendChild(objectPropertyElement); if (asymmetricElements != null && asymmetricElements.size() > 0) { if (asymmetricElements.size() > 1) { throw new LumifyException("To many 'asymmetric' elements found. Expected 0 or 1, found " + asymmetricElements.size()); } String parentToChildLabel = XmlUtil.getXmlString(asymmetricElements.get(0), "parentToChild/displayName"); String childToParentLabel = XmlUtil.getXmlString(asymmetricElements.get(0), "childToParent/displayName"); if (parentToChildLabel != null && parentToChildLabel.length() > 0) { label = parentToChildLabel; } String inverseLabel = label; if (childToParentLabel != null && childToParentLabel.length() > 0) { inverseLabel = childToParentLabel; } Element inverseObjectPropertyElement = exportDoc.createElementNS(ns.getNamespaceURI("owl"), "owl:ObjectProperty"); inverseObjectPropertyElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:about", uriToIri(uri + INVERSE_SUFFIX)); exportRootElement.appendChild(inverseObjectPropertyElement); addLabel(inverseObjectPropertyElement, inverseLabel); Element inverseOfElement = exportDoc.createElementNS(ns.getNamespaceURI("owl"), "owl:inverseOf"); inverseOfElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:resource", uriToIri(uri + INVERSE_SUFFIX)); objectPropertyElement.appendChild(inverseOfElement); inverseOfElement = exportDoc.createElementNS(ns.getNamespaceURI("owl"), "owl:inverseOf"); inverseOfElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:resource", uriToIri(uri)); inverseObjectPropertyElement.appendChild(inverseOfElement); objectProperties.put(uri + INVERSE_SUFFIX, new ObjectProperty(inverseObjectPropertyElement)); } addLabel(objectPropertyElement, label); objectProperties.put(uri, new ObjectProperty(objectPropertyElement)); } private void addIconMapping(String iconUri, OwlElement owlElement) { List<OwlElement> list = iconMapping.get(iconUri); if (list == null) { list = new ArrayList<>(); iconMapping.put(iconUri, list); } list.add(owlElement); } private void runOnObjectTypeConfig(Document inXml) { String uri = XmlUtil.getXmlString(inXml, "/pt_object_type_config/uri"); String label = XmlUtil.getXmlString(inXml, "/pt_object_type_config/displayName"); String parentTypeUri = XmlUtil.getXmlString(inXml, "/pt_object_type_config/parentType"); String infoIconUri = XmlUtil.getXmlString(inXml, "/pt_object_type_config/display/infoIconUri"); String comment = XmlUtil.getXmlString(inXml, "/pt_object_type_config/description"); List<Element> titleArgs = XmlUtil.getXmlElements(inXml, "/pt_object_type_config/title/args/arg"); // TODO baseType ??? // TODO commit-able ??? // TODO intrinsic ??? // TODO guessers ??? // TODO typeGroups ??? // TODO display/defaultNodeDisplayTypeUri ??? // TODO display/edgeIconUri ??? // TODO labelPropertyUri ??? Element classElement = exportDoc.createElementNS(ns.getNamespaceURI("owl"), "owl:Class"); classElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:about", uriToIri(uri)); exportRootElement.appendChild(classElement); addLabel(classElement, label); if (parentTypeUri != null && parentTypeUri.length() > 0 && !parentTypeUri.equals(uri)) { Element subClassOfElement = exportDoc.createElementNS(ns.getNamespaceURI("rdfs"), "rdfs:subClassOf"); subClassOfElement.setAttributeNS(ns.getNamespaceURI("rdf"), "rdf:resource", uriToIri(parentTypeUri)); classElement.appendChild(subClassOfElement); } if (comment != null && comment.length() > 0) { addComments(classElement, comment); } if (titleArgs != null && titleArgs.size() > 0) { addTitleFormula(classElement, titleArgs); } OwlClass owlClass = new OwlClass(classElement); if (infoIconUri != null && infoIconUri.length() > 0) { addIconMapping(infoIconUri, owlClass); } } private void addTitleFormula(Element classElement, List<Element> titleArgs) { String titleFormula = titleFormulaMaker.create(new TitleFormulaMaker.Options(baseIri + '#'), titleArgs); if (titleFormula.trim().length() > 0) { Element titleFormulaElement = exportDoc.createElementNS(ns.getNamespaceURI("lumify"), "lumify:titleFormula"); titleFormulaElement.appendChild(exportDoc.createCDATASection("\n" + indent(titleFormula, " ") + "\n ")); classElement.appendChild(titleFormulaElement); } } private String uriToIri(String uri) { return uriToIri(baseIri, uri); } public static String uriToIri(String baseIri, String uri) { return baseIri + '#' + uri; } }