org.odpi.openmetadata.archiveutilities.designmodels.owlcanonicalglossarymodel.CanonicalGlossaryOwlParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of glossary-canonical-model Show documentation
Show all versions of glossary-canonical-model Show documentation
The Glossary Canonical Model allows for loading common/standard glossary models from third parties.
The newest version!
/* SPDX-License-Identifier: Apache-2.0 */
/* Copyright Contributors to the ODPi Egeria project. */
package org.odpi.openmetadata.archiveutilities.designmodels.owlcanonicalglossarymodel;
import org.apache.jena.rdf.model.*;
import org.odpi.openmetadata.archiveutilities.designmodels.owlcanonicalglossarymodel.properties.GlossaryModel;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.*;
/**
* CanonicalGlossaryOwlParser reads the CanonicalGlossaryOwlParserModel and parses it into a set of Java Beans
* ready for the archive builder. It hides the format of the model from the builder.
*/
class CanonicalGlossaryOwlParser {
// JSON-LD keyword
private static String JSONLD = "JSON-LD";
// maps of json ld content
Set containerURIs = new HashSet<>();
Set classURIs = new HashSet<>();
Set ontologyURIs = new HashSet<>();
Set objectPropertyURIs = new HashSet<>();
Set dataPropertyURIs = new HashSet<>();
// label map
Map labelMap = new HashMap<>();
// comment map
Map commentMap = new HashMap<>();
//license Map
Map licenseMap = new HashMap<>();
Map> memberMap = new HashMap<>();
private final List errorReport = new ArrayList<>();
private final GlossaryModel glossaryModel = new GlossaryModel();
/**
* Create a parser passing the location of the model. This may be a single JSON-LD file or the GitHub file structure beginning
* at either the src directory or the one with the top-level context.jsonld in it.
*
* @param modelLocation location of the model content
*/
CanonicalGlossaryOwlParser(String modelLocation) throws IOException {
System.out.println("\nModel file Name: " + modelLocation);
File modelContent = new File(modelLocation);
if (modelContent.isDirectory()) {
System.out.println("\nDo not support directories");
System.exit(-1);
} else {
parseSingleFile(modelLocation);
validate();
populateModel();
displaySummary();
}
/*
* Errors found during the processing are added to the error report.
*/
if (!errorReport.isEmpty()) {
System.out.println("Error Report");
System.out.println(errorReport);
}
}
private void validate() {
if (ontologyURIs != null && ontologyURIs.size() != 1) {
System.err.println("Please supply a file that contains 1 and only 1 owl:Ontology. Found " + ontologyURIs.size());
System.exit(-1);
}
Map isDefinedByMap = glossaryModel.getIsDefinedByMap();
if (isDefinedByMap != null) {
int glossaryContentCount = 0;
if (classURIs != null) {
glossaryContentCount = classURIs.size();
}
if (objectPropertyURIs != null) {
glossaryContentCount += objectPropertyURIs.size();
}
if (dataPropertyURIs != null) {
glossaryContentCount += dataPropertyURIs.size();
}
if (containerURIs != null) {
glossaryContentCount += containerURIs.size();
}
if (glossaryContentCount != isDefinedByMap.keySet().size()) {
System.err.println("Expecting the number of relationships (" + isDefinedByMap.keySet().size() + ") and glossary elements (" +
glossaryContentCount + ") to be equal.");
System.exit(-1);
}
}
}
/**
* Parse the supplied file using apache Jena into maps containing json-ld content.
*
* @param fileName location of the model content
*/
@SuppressWarnings("unchecked")
private void parseSingleFile(String fileName) throws IOException {
System.out.println("\nRetrieving model contents from: " + fileName);
org.apache.jena.rdf.model.Model m = ModelFactory.createDefaultModel();
Reader fileReader = new FileReader(fileName);
org.apache.jena.rdf.model.Model model = m.read(fileReader, null, JSONLD);
StmtIterator it = model.listStatements();
while (it.hasNext()) {
Statement statement = it.next();
Resource s = statement.getSubject();
org.apache.jena.rdf.model.Property p = statement.getPredicate();
RDFNode o = statement.getObject();
String subjectURI = s.getURI();
String predicate = p.getLocalName();
switch (predicate) {
case "type":
if (o.isURIResource()) {
String object = o.toString();
switch (object) {
case "http://www.w3.org/2002/07/owl#Ontology":
ontologyURIs.add(subjectURI);
break;
case "http://www.w3.org/2002/07/owl#Class":
classURIs.add(subjectURI);
break;
case "http://www.w3.org/2000/01/rdf-schema#Container":
containerURIs.add(subjectURI);
break;
case "http://www.w3.org/2002/07/owl#ObjectProperty":
objectPropertyURIs.add(subjectURI);
break;
case "http://www.w3.org/2002/07/owl#DatatypeProperty":
dataPropertyURIs.add(subjectURI);
break;
}
} else if (o.isResource()) {
// should not happen
System.out.println("Not expecting a non uri resource subject:" + subjectURI + ",object: " + o.asResource());
} else if (o.isLiteral()) {
// does not happen
System.out.println("Not expecting type literal");
}
break;
case "member":
Set containerURIs = glossaryModel.getConceptTermMemberMap().get(subjectURI);
if (containerURIs == null) {
containerURIs = new HashSet<>();
}
containerURIs.add(o.asResource().getURI());
memberMap.put(subjectURI, containerURIs);
break;
case "example":
Map> examplesMap = glossaryModel.getExampleMap();
Set examples = examplesMap.get(subjectURI);
if (examples == null) {
examples = new HashSet<>();
}
examples.add((String) o.asLiteral().getValue());
examplesMap.put(subjectURI, examples);
glossaryModel.setExampleMap(examplesMap);
break;
case "subClassOf":
if (o.isResource()) {
glossaryModel.getResourceSubClassMap().put(subjectURI, o.asResource().getURI());
} else if (o.isLiteral()) {
glossaryModel.getLiteralSubClassMap().put(subjectURI, o.asLiteral().getValue().toString());
}
break;
case "domain":
Map> domainsMap = glossaryModel.getDomainsMap();
Set domains = domainsMap.get(subjectURI);
boolean createDomainsMap = false;
if (domains == null) {
domains = new HashSet<>();
createDomainsMap = true;
}
if (o.isResource()) {
domains.add(o.asResource().getURI());
domainsMap.put(subjectURI, domains);
if (createDomainsMap) {
glossaryModel.setDomainsMap(domainsMap);
}
}
break;
case "range":
Map> rangesMap = glossaryModel.getRangesMap();
Set ranges = rangesMap.get(subjectURI);
boolean createRangesMap = false;
if (ranges == null) {
ranges = new HashSet<>();
createRangesMap = true;
}
if (o.isResource()) {
ranges.add(o.asResource().getURI());
rangesMap.put(subjectURI, ranges);
if (createRangesMap) {
glossaryModel.setRangesMap(rangesMap);
}
}
break;
case "label":
labelMap.put(subjectURI, o.asLiteral());
break;
case "comment":
commentMap.put(subjectURI, o.asLiteral());
break;
case "isDefinedBy":
glossaryModel.getIsDefinedByMap().put(subjectURI, o.asResource().getURI());
break;
case "license":
licenseMap.put(subjectURI, o.asLiteral());
break;
// the following are recognised but are not supported at this time
case "versionInfo":
case "minCardinality":
case "maxCardinality":
break;
}
}
}
/**
* Summarize what we have found in the model. Write this content to standard out.
*/
private void displaySummary() {
System.out.println("Found " + glossaryModel.getGlossaryLiteralMap().keySet().size() + " glossaries");
System.out.println("Found " + glossaryModel.getCategoryLiteralMap().keySet().size() + " categories");
System.out.println("Found " + glossaryModel.getConceptTermLiteralMap().keySet().size() + " concept terms");
System.out.println("Found " + glossaryModel.getObjectPropertyTermLiteralMap().keySet().size() + "object property terms");
Map> memberMap = glossaryModel.getConceptTermMemberMap();
Map resourceSubClassMap = glossaryModel.getResourceSubClassMap();
Map literalSubClassMap = glossaryModel.getLiteralSubClassMap();
Map> rangesMap = glossaryModel.getRangesMap();
Map> domainsMap = glossaryModel.getDomainsMap();
Map isDefinedByMap = glossaryModel.getIsDefinedByMap();
if (resourceSubClassMap != null) {
System.out.println("No resourceSubClassMap");
} else {
System.out.println("Found " + resourceSubClassMap.keySet().size() + " resourceSubclasses");
}
if (literalSubClassMap == null) {
System.out.println("No literalSubClassMap");
} else {
System.out.println("Found " + literalSubClassMap.keySet().size() + " literalSubClassMap");
}
if (rangesMap == null) {
System.out.println("No ranges");
} else {
System.out.println("Found " + rangesMap.keySet().size() + " rangesMap");
}
if (domainsMap == null) {
System.out.println("No domains");
} else {
System.out.println("Found " + domainsMap.keySet().size() + " domainsMap");
}
if (isDefinedByMap == null) {
System.out.println("No is defined by");
} else {
System.out.println("Found " + isDefinedByMap.keySet().size() + " is defined by Map");
}
if (memberMap == null) {
System.out.println("No members");
} else {
System.out.println("Found " + memberMap.keySet().size() + " members Map");
}
}
/**
* populate the model, this is picked up ny the archive builder to build the archive content
*/
private void populateModel() {
String ontologyURI = ontologyURIs.iterator().next();
glossaryModel.setModelTechnicalName(ontologyURI);
glossaryModel.setModelLanguage("us_en");
glossaryModel.setModelScope("Owl Canonical Vocabulary");
processLabels();
processComments();
processLicense();
processMembers();
// TODO get from tags
glossaryModel.setModelLanguage("us_en");
Literal glossaryDisplayNameLiteral = glossaryModel.getGlossaryLiteralMap().get(ontologyURI).get("displayName");
glossaryModel.setModelName((String) glossaryDisplayNameLiteral.getValue());
Literal glossaryDescriptionLiteral = glossaryModel.getGlossaryLiteralMap().get(ontologyURI).get("description");
glossaryModel.setModelDescription((String) glossaryDescriptionLiteral.getValue());
Literal glossaryLicenseLiteral = glossaryModel.getGlossaryLiteralMap().get(ontologyURI).get("license");
glossaryModel.setLicense((String) glossaryLicenseLiteral.getValue());
}
/**
* Process members. Members have membership of a container. A container will be mapped to a Glossary Category.
* Member can be container (a glossary Category), a class (a Spine object) or an objectProperty a (Spine attribute).
*/
private void processMembers() {
// split out the members
for (String member : memberMap.keySet()) {
if (containerURIs.contains(member)) {
glossaryModel.getContainmentMemberMap().put(member, memberMap.get(member));
}
if (classURIs.contains((member))) {
glossaryModel.getConceptTermMemberMap().put(member, memberMap.get(member));
}
if (objectPropertyURIs.contains(member)) {
glossaryModel.getPropertyTermMemberMap().put(member, memberMap.get(member));
}
}
}
/**
* Process the license
*/
private void processLicense() {
for (String subject : licenseMap.keySet()) {
if (ontologyURIs.contains(subject)) {
// found an ontology = Egeria glossary
Map> glossaryLiteralMap = glossaryModel.getGlossaryLiteralMap();
Map literalMap = glossaryLiteralMap.get(subject);
literalMap = setLicense(subject, literalMap);
glossaryLiteralMap.put(subject, literalMap);
}
}
}
/**
* Process comments - these will end up as descriptions in Egeria Entities.
*/
private void processComments() {
for (String subject : commentMap.keySet()) {
if (ontologyURIs.contains(subject)) {
// found an ontology = Egeria glossary
Map> glossaryLiteralMap = glossaryModel.getGlossaryLiteralMap();
Map literalMap = glossaryLiteralMap.get(subject);
literalMap = setDescription(subject, literalMap);
glossaryLiteralMap.put(subject, literalMap);
}
if (containerURIs.contains(subject)) {
// found a container = Egeria Category
Map> categoryLiteralMap = glossaryModel.getCategoryLiteralMap();
Map literalMap = categoryLiteralMap.get(subject);
literalMap = setDescription(subject, literalMap);
categoryLiteralMap.put(subject, literalMap);
}
if (classURIs.contains(subject)) {
// found a class = Egeria Spine object
Map> termLiteralMap = glossaryModel.getConceptTermLiteralMap();
Map literalMap = termLiteralMap.get(subject);
literalMap = setDescription(subject, literalMap);
termLiteralMap.put(subject, literalMap);
}
if (objectPropertyURIs.contains(subject)) {
// found a property = Egeria spine Attribute
Map> termLiteralMap = glossaryModel.getObjectPropertyTermLiteralMap();
Map literalMap = termLiteralMap.get(subject);
literalMap = setDescription(subject, literalMap);
termLiteralMap.put(subject, literalMap);
}
if (dataPropertyURIs.contains(subject)) {
// found a datatype property
Map> termLiteralMap = glossaryModel.getDatatypePropertyTermLiteralMap();
Map literalMap = termLiteralMap.get(subject);
literalMap = setDescription(subject, literalMap);
termLiteralMap.put(subject, literalMap);
}
}
}
/**
* Process lables - these will end up as display names in Egeria Entities
*/
private void processLabels() {
// spin down each label and look at it literal and subject. Subject should match property, container or class
for (String subject : labelMap.keySet()) {
if (ontologyURIs.contains(subject)) {
// found an ontology = Egeria glossary
Map> glossaryLiteralMap = glossaryModel.getGlossaryLiteralMap();
Map literalMap = glossaryLiteralMap.get(subject);
literalMap = setDisplayName(subject, literalMap);
glossaryLiteralMap.put(subject, literalMap);
}
if (containerURIs.contains(subject)) {
// found a container = Egeria Category
Map> categoryLiteralMap = glossaryModel.getCategoryLiteralMap();
Map literalMap = categoryLiteralMap.get(subject);
literalMap = setDisplayName(subject, literalMap);
categoryLiteralMap.put(subject, literalMap);
}
if (classURIs.contains(subject)) {
// found a class = Egeria Spine object
Map> termLiteralMap = glossaryModel.getConceptTermLiteralMap();
Map literalMap = termLiteralMap.get(subject);
literalMap = setDisplayName(subject, literalMap);
termLiteralMap.put(subject, literalMap);
}
if (objectPropertyURIs.contains(subject)) {
// found a object property
Map> termLiteralMap = glossaryModel.getObjectPropertyTermLiteralMap();
Map literalMap = termLiteralMap.get(subject);
literalMap = setDisplayName(subject, literalMap);
termLiteralMap.put(subject, literalMap);
}
if (dataPropertyURIs.contains(subject)) {
// found a datatype property
Map> termLiteralMap = glossaryModel.getDatatypePropertyTermLiteralMap();
Map literalMap = termLiteralMap.get(subject);
literalMap = setDisplayName(subject, literalMap);
termLiteralMap.put(subject, literalMap);
}
}
}
private Map setDisplayName(String subject, Map literalMap) {
if (literalMap == null) {
literalMap = new HashMap<>();
}
Literal literal = labelMap.get(subject);
literalMap.put("displayName", literal);
return literalMap;
}
private Map setDescription(String subject, Map literalMap) {
if (literalMap == null) {
literalMap = new HashMap<>();
}
Literal literal = commentMap.get(subject);
literalMap.put("description", literal);
return literalMap;
}
private Map setLicense(String subject, Map literalMap) {
if (literalMap == null) {
literalMap = new HashMap<>();
}
Literal literal = licenseMap.get(subject);
literalMap.put("license", literal);
return literalMap;
}
/**
* Return the discovered content to the caller.
*
* @return model object with the model content contained in nested beans.
*/
public GlossaryModel getModel() {
glossaryModel.setErrorReport(errorReport);
return glossaryModel;
}
}