package io.lumify.core.model.ontology;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Files;
import io.lumify.core.config.Configuration;
import io.lumify.core.exception.LumifyException;
import io.lumify.core.exception.LumifyResourceNotFoundException;
import io.lumify.core.model.longRunningProcess.LongRunningProcessRepository;
import io.lumify.core.model.properties.LumifyProperties;
import io.lumify.core.model.termMention.TermMentionRepository;
import io.lumify.core.model.user.UserRepository;
import io.lumify.core.model.workspace.WorkspaceRepository;
import io.lumify.core.util.ExecutorServiceUtil;
import io.lumify.core.util.JSONUtil;
import io.lumify.core.util.LumifyLogger;
import io.lumify.core.util.LumifyLoggerFactory;
import io.lumify.web.clientapi.model.ClientApiOntology;
import io.lumify.web.clientapi.model.PropertyType;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.coode.owlapi.rdf.rdfxml.RDFXMLRenderer;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.securegraph.Authorizations;
import org.securegraph.DefinePropertyBuilder;
import org.securegraph.Graph;
import org.securegraph.TextIndexHint;
import org.securegraph.property.StreamingPropertyValue;
import org.securegraph.util.CloseableUtils;
import org.securegraph.util.ConvertingIterable;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.io.OWLOntologyDocumentSource;
import org.semanticweb.owlapi.io.ReaderDocumentSource;
import org.semanticweb.owlapi.model.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.google.common.base.Preconditions.checkNotNull;
public abstract class OntologyRepositoryBase implements OntologyRepository {
private static final LumifyLogger LOGGER = LumifyLoggerFactory.getLogger(OntologyRepositoryBase.class);
public static final String BASE_OWL_IRI = "http://lumify.io";
public static final String COMMENT_OWL_IRI = "http://lumify.io/comment";
private final Configuration configuration;
protected OntologyRepositoryBase(Configuration configuration) {
this.configuration = configuration;
}
public void loadOntologies(Configuration config, Authorizations authorizations) throws Exception {
Concept rootConcept = getOrCreateConcept(null, OntologyRepository.ROOT_CONCEPT_IRI, "root", null);
Concept entityConcept = getOrCreateConcept(rootConcept, OntologyRepository.ENTITY_CONCEPT_IRI, "thing", null);
clearCache();
addEntityGlyphIcon(entityConcept);
importResourceOwl("base.owl", BASE_OWL_IRI, authorizations);
importResourceOwl("user.owl", UserRepository.OWL_IRI, authorizations);
importResourceOwl("termMention.owl", TermMentionRepository.OWL_IRI, authorizations);
importResourceOwl("workspace.owl", WorkspaceRepository.OWL_IRI, authorizations);
importResourceOwl("comment.owl", COMMENT_OWL_IRI, authorizations);
importResourceOwl("longRunningProcess.owl", LongRunningProcessRepository.OWL_IRI, authorizations);
for (Map.Entry<String, Map<String, String>> owlGroup : config.getMultiValue(Configuration.ONTOLOGY_REPOSITORY_OWL).entrySet()) {
String iri = owlGroup.getValue().get("iri");
String dir = owlGroup.getValue().get("dir");
String file = owlGroup.getValue().get("file");
if (iri == null) {
throw new LumifyException("iri is required for group " + Configuration.ONTOLOGY_REPOSITORY_OWL + "." + owlGroup.getKey());
}
if (dir == null && file == null) {
throw new LumifyException("dir or file is required for " + Configuration.ONTOLOGY_REPOSITORY_OWL + "." + owlGroup.getKey());
}
if (dir != null && file != null) {
throw new LumifyException("you cannot specify both dir and file for " + Configuration.ONTOLOGY_REPOSITORY_OWL + "." + owlGroup.getKey());
}
if (isOntologyDefined(iri)) {
LOGGER.debug("Ontology %s (iri: %s) is already defined", dir != null ? dir : file, iri);
continue;
}
if (dir != null) {
File owlFile = findOwlFile(new File(dir));
if (owlFile == null) {
throw new LumifyResourceNotFoundException("could not find owl file in directory " + new File(dir).getAbsolutePath());
}
importFile(owlFile, IRI.create(iri), authorizations);
} else {
writePackage(new File(file), IRI.create(iri), authorizations);
}
}
}
private void importResourceOwl(String fileName, String iri, Authorizations authorizations) {
if (isOntologyDefined(iri)) {
LOGGER.debug("Ontology %s (iri: %s) is already defined", fileName, iri);
return;
}
LOGGER.debug("importResourceOwl %s (iri: %s)", fileName, iri);
InputStream baseOwlFile = OntologyRepositoryBase.class.getResourceAsStream(fileName);
checkNotNull(baseOwlFile, "Could not load resource " + OntologyRepositoryBase.class.getResource(fileName));
try {
IRI documentIRI = IRI.create(iri);
byte[] inFileData = IOUtils.toByteArray(baseOwlFile);
try {
importFile(inFileData, documentIRI, null, authorizations);
} catch (OWLOntologyAlreadyExistsException ex) {
LOGGER.warn("Ontology was already defined but not stored: " + fileName + " (iri: " + iri + ")", ex);
storeOntologyFile(new ByteArrayInputStream(inFileData), documentIRI);
}
} catch (Exception ex) {
throw new LumifyException("Could not import ontology file: " + fileName + " (iri: " + iri + ")", ex);
} finally {
CloseableUtils.closeQuietly(baseOwlFile);
}
}
protected abstract boolean isOntologyDefined(String iri);
private void addEntityGlyphIcon(Concept entityConcept) {
InputStream entityGlyphIconInputStream = OntologyRepositoryBase.class.getResourceAsStream("entity.png");
checkNotNull(entityGlyphIconInputStream, "Could not load resource " + OntologyRepositoryBase.class.getResource("entity.png"));
try {
ByteArrayOutputStream imgOut = new ByteArrayOutputStream();
IOUtils.copy(entityGlyphIconInputStream, imgOut);
byte[] rawImg = imgOut.toByteArray();
addEntityGlyphIconToEntityConcept(entityConcept, rawImg);
} catch (IOException e) {
throw new LumifyException("invalid stream for glyph icon");
}
}
protected abstract void addEntityGlyphIconToEntityConcept(Concept entityConcept, byte[] rawImg);
@Override
public String guessDocumentIRIFromPackage(File file) throws IOException, ZipException {
ZipFile zipped = new ZipFile(file);
if (zipped.isValidZipFile()) {
File tempDir = Files.createTempDir();
try {
LOGGER.info("Extracting: %s to %s", file.getAbsoluteFile(), tempDir.getAbsolutePath());
zipped.extractAll(tempDir.getAbsolutePath());
File owlFile = findOwlFile(tempDir);
return guessDocumentIRIFromFile(owlFile);
} finally {
FileUtils.deleteDirectory(tempDir);
}
} else {
if (file.isDirectory()) {
file = findOwlFile(file);
}
return guessDocumentIRIFromFile(file);
}
}
public String guessDocumentIRIFromFile(File owlFile) throws IOException {
try (FileInputStream owlFileIn = new FileInputStream(owlFile)) {
String owlContents = IOUtils.toString(owlFileIn);
Pattern iriRegex = Pattern.compile("<owl:Ontology rdf:about=\"(.*?)\">");
Matcher m = iriRegex.matcher(owlContents);
if (m.find()) {
return m.group(1);
}
return null;
}
}
@Override
public void importFile(File inFile, IRI documentIRI, Authorizations authorizations) throws Exception {
checkNotNull(inFile, "inFile cannot be null");
if (!inFile.exists()) {
throw new LumifyException("File " + inFile + " does not exist");
}
File inDir = inFile.getParentFile();
try (FileInputStream inFileIn = new FileInputStream(inFile)) {
LOGGER.debug("importing %s", inFile.getAbsolutePath());
byte[] inFileData = IOUtils.toByteArray(inFileIn);
importFile(inFileData, documentIRI, inDir, authorizations);
}
}
private void importFile(byte[] inFileData, IRI documentIRI, File inDir, Authorizations authorizations) throws Exception {
Reader inFileReader = new InputStreamReader(new ByteArrayInputStream(inFileData));
OWLOntologyLoaderConfiguration config = new OWLOntologyLoaderConfiguration();
OWLOntologyManager m = createOwlOntologyManager(config, documentIRI);
OWLOntologyDocumentSource documentSource = new ReaderDocumentSource(inFileReader, documentIRI);
OWLOntology o = m.loadOntologyFromOntologyDocument(documentSource, config);
long totalStartTime = System.currentTimeMillis();
long startTime = System.currentTimeMillis();
importOntologyAnnotationProperties(o, inDir, authorizations);
clearCache(); // this is required to cause a new lookup of classes for data and object properties.
long endTime = System.currentTimeMillis();
long importAnnotationPropertiesTime = endTime - startTime;
startTime = System.currentTimeMillis();
importOntologyClasses(o, inDir, authorizations);
clearCache(); // this is required to cause a new lookup of classes for data and object properties.
endTime = System.currentTimeMillis();
long importConceptsTime = endTime - startTime;
startTime = System.currentTimeMillis();
importDataProperties(o);
endTime = System.currentTimeMillis();
long importDataPropertiesTime = endTime - startTime;
startTime = System.currentTimeMillis();
importObjectProperties(o);
clearCache(); // needed to find the relationship for inverse of
endTime = System.currentTimeMillis();
long importObjectPropertiesTime = endTime - startTime;
startTime = System.currentTimeMillis();
importInverseOfObjectProperties(o);
endTime = System.currentTimeMillis();
long importInverseOfObjectPropertiesTime = endTime - startTime;
long totalEndTime = System.currentTimeMillis();
LOGGER.debug("import annotation properties time: %dms", importAnnotationPropertiesTime);
LOGGER.debug("import concepts time: %dms", importConceptsTime);
LOGGER.debug("import data properties time: %dms", importDataPropertiesTime);
LOGGER.debug("import object properties time: %dms", importObjectPropertiesTime);
LOGGER.debug("import inverse of object properties time: %dms", importInverseOfObjectPropertiesTime);
LOGGER.debug("import total time: %dms", totalEndTime - totalStartTime);
// do this last after everything was successful so that isOntologyDefined can be used
storeOntologyFile(new ByteArrayInputStream(inFileData), documentIRI);
clearCache();
}
private void importInverseOfObjectProperties(OWLOntology o) {
for (OWLObjectProperty objectProperty : o.getObjectPropertiesInSignature()) {
if (!o.isDeclared(objectProperty, false)) {
continue;
}
importInverseOf(o, objectProperty);
}
}
private void importObjectProperties(OWLOntology o) {
for (OWLObjectProperty objectProperty : o.getObjectPropertiesInSignature()) {
if (!o.isDeclared(objectProperty, false)) {
continue;
}
importObjectProperty(o, objectProperty);
}
}
private void importDataProperties(OWLOntology o) {
for (OWLDataProperty dataTypeProperty : o.getDataPropertiesInSignature()) {
if (!o.isDeclared(dataTypeProperty, false)) {
continue;
}
importDataProperty(o, dataTypeProperty);
}
}
protected void importOntologyAnnotationProperties(OWLOntology o, File inDir, Authorizations authorizations) {
for (OWLAnnotationProperty annotation : o.getAnnotationPropertiesInSignature()) {
importOntologyAnnotationProperty(o, annotation, inDir, authorizations);
}
}
protected void importOntologyAnnotationProperty(OWLOntology o, OWLAnnotationProperty annotationProperty, File inDir, Authorizations authorizations) {
}
private void importOntologyClasses(OWLOntology o, File inDir, Authorizations authorizations) throws IOException {
for (OWLClass ontologyClass : o.getClassesInSignature()) {
if (!o.isDeclared(ontologyClass, false)) {
continue;
}
importOntologyClass(o, ontologyClass, inDir, authorizations);
}
}
public OWLOntologyManager createOwlOntologyManager(OWLOntologyLoaderConfiguration config, IRI excludeDocumentIRI) throws Exception {
OWLOntologyManager m = OWLManager.createOWLOntologyManager();
config.setMissingImportHandlingStrategy(MissingImportHandlingStrategy.SILENT);
loadOntologyFiles(m, config, excludeDocumentIRI);
return m;
}
protected abstract void storeOntologyFile(InputStream inputStream, IRI documentIRI);
public void exportOntology(OutputStream out, IRI documentIRI) throws Exception {
OWLOntologyManager m = OWLManager.createOWLOntologyManager();
OWLOntologyLoaderConfiguration config = new OWLOntologyLoaderConfiguration();
config.setMissingImportHandlingStrategy(MissingImportHandlingStrategy.SILENT);
List<OWLOntology> loadedOntologies = loadOntologyFiles(m, config, null);
OWLOntology o = findOntology(loadedOntologies, documentIRI);
if (o == null) {
throw new LumifyException("Could not find ontology with iri " + documentIRI);
}
Writer fileWriter = new OutputStreamWriter(out);
new RDFXMLRenderer(o, fileWriter).render();
}
protected abstract List<OWLOntology> loadOntologyFiles(OWLOntologyManager m, OWLOntologyLoaderConfiguration config, IRI excludedIRI) throws Exception;
private OWLOntology findOntology(List<OWLOntology> loadedOntologies, IRI documentIRI) {
for (OWLOntology o : loadedOntologies) {
if (documentIRI.equals(o.getOntologyID().getOntologyIRI())) {
return o;
}
}
return null;
}
protected Concept importOntologyClass(OWLOntology o, OWLClass ontologyClass, File inDir, Authorizations authorizations) throws IOException {
String uri = ontologyClass.getIRI().toString();
if ("http://www.w3.org/2002/07/owl#Thing".equals(uri)) {
return getEntityConcept();
}
String label = getLabel(o, ontologyClass);
checkNotNull(label, "label cannot be null or empty: " + uri);
LOGGER.info("Importing ontology class " + uri + " (label: " + label + ")");
Concept parent = getParentConcept(o, ontologyClass, inDir, authorizations);
Concept result = getOrCreateConcept(parent, uri, label, inDir);
for (OWLAnnotation annotation : ontologyClass.getAnnotations(o)) {
String annotationIri = annotation.getProperty().getIRI().toString();
OWLLiteral valueLiteral = (OWLLiteral) annotation.getValue();
String valueString = valueLiteral.getLiteral();
if (annotationIri.equals(LumifyProperties.INTENT.getPropertyName())) {
result.addIntent(valueString, authorizations);
continue;
}
if (annotationIri.equals(LumifyProperties.SEARCHABLE.getPropertyName())) {
boolean searchable = valueString == null || Boolean.parseBoolean(valueString);
result.setProperty(LumifyProperties.SEARCHABLE.getPropertyName(), searchable, authorizations);
continue;
}
if (annotationIri.equals(LumifyProperties.ADDABLE.getPropertyName())) {
boolean searchable = valueString == null || Boolean.parseBoolean(valueString);
result.setProperty(LumifyProperties.ADDABLE.getPropertyName(), searchable, authorizations);
continue;
}
if (annotationIri.equals(LumifyProperties.USER_VISIBLE.getPropertyName())) {
boolean userVisible = valueString == null || Boolean.parseBoolean(valueString);
result.setProperty(LumifyProperties.USER_VISIBLE.getPropertyName(), userVisible, authorizations);
continue;
}
if (annotationIri.equals(LumifyProperties.GLYPH_ICON_FILE_NAME.getPropertyName())) {
setIconProperty(result, inDir, valueString, LumifyProperties.GLYPH_ICON.getPropertyName(), authorizations);
continue;
}
if (annotationIri.equals(LumifyProperties.MAP_GLYPH_ICON_FILE_NAME.getPropertyName())) {
setIconProperty(result, inDir, valueString, LumifyProperties.MAP_GLYPH_ICON.getPropertyName(), authorizations);
continue;
}
if (annotationIri.equals(LumifyProperties.ADD_RELATED_CONCEPT_WHITE_LIST.getPropertyName())) {
if (valueString == null || valueString.trim().length() == 0) {
continue;
}
result.setProperty(LumifyProperties.ADD_RELATED_CONCEPT_WHITE_LIST.getPropertyName(), valueString.trim(), authorizations);
continue;
}
if (annotationIri.equals("http://www.w3.org/2000/01/rdf-schema#label")) {
continue;
}
result.setProperty(annotationIri, valueString, authorizations);
}
return result;
}
protected void setIconProperty(Concept concept, File inDir, String glyphIconFileName, String propertyKey, Authorizations authorizations) throws IOException {
if (glyphIconFileName != null) {
File iconFile = new File(inDir, glyphIconFileName);
if (!iconFile.exists()) {
throw new RuntimeException("Could not find icon file: " + iconFile.toString());
}
try (InputStream iconFileIn = new FileInputStream(iconFile)) {
StreamingPropertyValue value = new StreamingPropertyValue(iconFileIn, byte[].class);
value.searchIndex(false);
value.store(true);
concept.setProperty(propertyKey, value, authorizations);
}
}
}
protected Concept getParentConcept(OWLOntology o, OWLClass ontologyClass, File inDir, Authorizations authorizations) throws IOException {
Set<OWLClassExpression> superClasses = ontologyClass.getSuperClasses(o);
if (superClasses.size() == 0) {
return getEntityConcept();
} else if (superClasses.size() == 1) {
OWLClassExpression superClassExpr = superClasses.iterator().next();
OWLClass superClass = superClassExpr.asOWLClass();
String superClassUri = superClass.getIRI().toString();
Concept parent = getConceptByIRI(superClassUri);
if (parent != null) {
return parent;
}
parent = importOntologyClass(o, superClass, inDir, authorizations);
if (parent == null) {
throw new LumifyException("Could not find or create parent: " + superClass);
}
return parent;
} else {
throw new LumifyException("Unhandled multiple super classes. Found " + superClasses.size() + ", expected 0 or 1.");
}
}
protected void importDataProperty(OWLOntology o, OWLDataProperty dataTypeProperty) {
String propertyIRI = dataTypeProperty.getIRI().toString();
String propertyDisplayName = getLabel(o, dataTypeProperty);
PropertyType propertyType = getPropertyType(o, dataTypeProperty);
boolean userVisible = getUserVisible(o, dataTypeProperty);
boolean searchable = getSearchable(o, dataTypeProperty);
boolean addable = getAddable(o, dataTypeProperty);
String displayType = getDisplayType(o, dataTypeProperty);
String propertyGroup = getPropertyGroup(o, dataTypeProperty);
String validationFormula = getValidationFormula(o, dataTypeProperty);
String displayFormula = getDisplayFormula(o, dataTypeProperty);
ImmutableList<String> dependentPropertyIris = getDependentPropertyIri(o, dataTypeProperty);
Double boost = getBoost(o, dataTypeProperty);
String[] intents = getIntents(o, dataTypeProperty);
if (propertyType == null) {
throw new LumifyException("Could not get property type on data property " + propertyIRI);
}
List<Concept> domainConcepts = new ArrayList<>();
for (OWLClassExpression domainClassExpr : dataTypeProperty.getDomains(o)) {
OWLClass domainClass = domainClassExpr.asOWLClass();
String domainClassUri = domainClass.getIRI().toString();
Concept domainConcept = getConceptByIRI(domainClassUri);
if (domainConcept == null) {
LOGGER.error("Could not find class with uri: %s", domainClassUri);
} else {
LOGGER.info("Adding data property " + propertyIRI + " to class " + domainConcept.getIRI());
domainConcepts.add(domainConcept);
}
}
Map<String, String> possibleValues = getPossibleValues(o, dataTypeProperty);
Collection<TextIndexHint> textIndexHints = getTextIndexHints(o, dataTypeProperty);
addPropertyTo(
domainConcepts,
propertyIRI,
propertyDisplayName,
propertyType,
possibleValues,
textIndexHints,
userVisible,
searchable,
addable,
displayType,
propertyGroup,
boost,
validationFormula,
displayFormula,
dependentPropertyIris,
intents
);
}
protected abstract OntologyProperty addPropertyTo(
List<Concept> concepts,
String propertyIri,
String displayName,
PropertyType dataType,
Map<String, String> possibleValues,
Collection<TextIndexHint> textIndexHints,
boolean userVisible,
boolean searchable,
boolean addable,
String displayType,
String propertyGroup,
Double boost,
String validationFormula,
String displayFormula,
ImmutableList<String> dependentPropertyIris,
String[] intents);
protected void importObjectProperty(OWLOntology o, OWLObjectProperty objectProperty) {
String iri = objectProperty.getIRI().toString();
String label = getLabel(o, objectProperty);
String[] intents = getIntents(o, objectProperty);
boolean userVisible = getUserVisible(o, objectProperty);
checkNotNull(label, "label cannot be null or empty for " + iri);
LOGGER.info("Importing ontology object property " + iri + " (label: " + label + ")");
getOrCreateRelationshipType(getDomainsConcepts(o, objectProperty), getRangesConcepts(o, objectProperty), iri, label, intents, userVisible);
}
protected void importInverseOf(OWLOntology o, OWLObjectProperty objectProperty) {
String iri = objectProperty.getIRI().toString();
Relationship fromRelationship = null;
for (OWLObjectPropertyExpression inverseOf : objectProperty.getInverses(o)) {
if (inverseOf instanceof OWLObjectProperty) {
if (fromRelationship == null) {
fromRelationship = getRelationshipByIRI(iri);
checkNotNull(fromRelationship, "could not find from relationship: " + iri);
}
OWLObjectProperty inverseOfOWLObjectProperty = (OWLObjectProperty) inverseOf;
String inverseOfIri = inverseOfOWLObjectProperty.getIRI().toString();
Relationship inverseOfRelationship = getRelationshipByIRI(inverseOfIri);
getOrCreateInverseOfRelationship(fromRelationship, inverseOfRelationship);
}
}
}
protected abstract void getOrCreateInverseOfRelationship(Relationship fromRelationship, Relationship inverseOfRelationship);
private Iterable<Concept> getRangesConcepts(OWLOntology o, OWLObjectProperty objectProperty) {
List<Concept> ranges = new ArrayList<>();
for (OWLClassExpression rangeClassExpr : objectProperty.getRanges(o)) {
OWLClass rangeClass = rangeClassExpr.asOWLClass();
String rangeClassUri = rangeClass.getIRI().toString();
Concept ontologyClass = getConceptByIRI(rangeClassUri);
if (ontologyClass == null) {
LOGGER.error("Could not find class with uri: %s", rangeClassUri);
} else {
ranges.add(ontologyClass);
}
}
return ranges;
}
private Iterable<Concept> getDomainsConcepts(OWLOntology o, OWLObjectProperty objectProperty) {
List<Concept> domains = new ArrayList<>();
for (OWLClassExpression domainClassExpr : objectProperty.getDomains(o)) {
OWLClass rangeClass = domainClassExpr.asOWLClass();
String rangeClassUri = rangeClass.getIRI().toString();
Concept ontologyClass = getConceptByIRI(rangeClassUri);
if (ontologyClass == null) {
LOGGER.error("Could not find class with uri: %s", rangeClassUri);
} else {
domains.add(ontologyClass);
}
}
return domains;
}
protected PropertyType getPropertyType(OWLOntology o, OWLDataProperty dataTypeProperty) {
Set<OWLDataRange> ranges = dataTypeProperty.getRanges(o);
if (ranges.size() == 0) {
return null;
}
if (ranges.size() > 1) {
throw new LumifyException("Unexpected number of ranges on data property " + dataTypeProperty.getIRI().toString());
}
for (OWLDataRange range : ranges) {
if (range instanceof OWLDatatype) {
OWLDatatype datatype = (OWLDatatype) range;
return getPropertyType(datatype.getIRI().toString());
}
}
throw new LumifyException("Could not find range on data property " + dataTypeProperty.getIRI().toString());
}
private PropertyType getPropertyType(String iri) {
if ("http://www.w3.org/2001/XMLSchema#string".equals(iri)) {
return PropertyType.STRING;
}
if ("http://www.w3.org/2001/XMLSchema#dateTime".equals(iri)) {
return PropertyType.DATE;
}
if ("http://www.w3.org/2001/XMLSchema#date".equals(iri)) {
return PropertyType.DATE;
}
if ("http://www.w3.org/2001/XMLSchema#gYear".equals(iri)) {
return PropertyType.DATE;
}
if ("http://www.w3.org/2001/XMLSchema#gYearMonth".equals(iri)) {
return PropertyType.DATE;
}
if ("http://www.w3.org/2001/XMLSchema#int".equals(iri)) {
return PropertyType.DOUBLE;
}
if ("http://www.w3.org/2001/XMLSchema#double".equals(iri)) {
return PropertyType.DOUBLE;
}
if ("http://www.w3.org/2001/XMLSchema#float".equals(iri)) {
return PropertyType.DOUBLE;
}
if ("http://lumify.io#geolocation".equals(iri)) {
return PropertyType.GEO_LOCATION;
}
if ("http://lumify.io#currency".equals(iri)) {
return PropertyType.CURRENCY;
}
if ("http://lumify.io#image".equals(iri)) {
return PropertyType.IMAGE;
}
if ("http://www.w3.org/2001/XMLSchema#hexBinary".equals(iri)) {
return PropertyType.BINARY;
}
if ("http://www.w3.org/2001/XMLSchema#boolean".equals(iri)) {
return PropertyType.BOOLEAN;
}
if ("http://www.w3.org/2001/XMLSchema#integer".equals(iri)) {
return PropertyType.INTEGER;
}
if ("http://www.w3.org/2001/XMLSchema#nonNegativeInteger".equals(iri)) {
return PropertyType.INTEGER;
}
if ("http://www.w3.org/2001/XMLSchema#positiveInteger".equals(iri)) {
return PropertyType.INTEGER;
}
throw new LumifyException("Unhandled property type " + iri);
}
public static String getLabel(OWLOntology o, OWLEntity owlEntity) {
String bestLabel = owlEntity.getIRI().toString();
for (OWLAnnotation annotation : owlEntity.getAnnotations(o)) {
if (annotation.getProperty().isLabel()) {
OWLLiteral value = (OWLLiteral) annotation.getValue();
bestLabel = value.getLiteral();
if (value.getLang() != null && value.getLang().equals("en")) {
return bestLabel;
}
}
}
return bestLabel;
}
protected String getDisplayType(OWLOntology o, OWLEntity owlEntity) {
return getAnnotationValueByUri(o, owlEntity, LumifyProperties.DISPLAY_TYPE.getPropertyName());
}
protected String getPropertyGroup(OWLOntology o, OWLEntity owlEntity) {
return getAnnotationValueByUri(o, owlEntity, LumifyProperties.PROPERTY_GROUP.getPropertyName());
}
protected String getValidationFormula(OWLOntology o, OWLEntity owlEntity) {
return getAnnotationValueByUri(o, owlEntity, LumifyProperties.VALIDATION_FORMULA.getPropertyName());
}
protected String getDisplayFormula(OWLOntology o, OWLEntity owlEntity) {
return getAnnotationValueByUri(o, owlEntity, LumifyProperties.DISPLAY_FORMULA.getPropertyName());
}
protected ImmutableList<String> getDependentPropertyIri(OWLOntology o, OWLEntity owlEntity) {
return getAnnotationValuesByUriOrNull(o, owlEntity, LumifyProperties.DEPENDENT_PROPERTY_IRI.getPropertyName());
}
protected Double getBoost(OWLOntology o, OWLEntity owlEntity) {
String val = getAnnotationValueByUri(o, owlEntity, LumifyProperties.BOOST.getPropertyName());
if (val == null) {
return null;
}
return Double.parseDouble(val);
}
protected String[] getIntents(OWLOntology o, OWLEntity owlEntity) {
return getAnnotationValuesByUri(o, owlEntity, LumifyProperties.INTENT.getPropertyName());
}
protected boolean getUserVisible(OWLOntology o, OWLEntity owlEntity) {
String val = getAnnotationValueByUri(o, owlEntity, LumifyProperties.USER_VISIBLE.getPropertyName());
return val == null || Boolean.parseBoolean(val);
}
protected boolean getSearchable(OWLOntology o, OWLEntity owlEntity) {
String val = getAnnotationValueByUri(o, owlEntity, "http://lumify.io#searchable");
return val == null || Boolean.parseBoolean(val);
}
protected boolean getAddable(OWLOntology o, OWLEntity owlEntity) {
String val = getAnnotationValueByUri(o, owlEntity, "http://lumify.io#addable");
return val == null || Boolean.parseBoolean(val);
}
protected Map<String, String> getPossibleValues(OWLOntology o, OWLEntity owlEntity) {
String val = getAnnotationValueByUri(o, owlEntity, LumifyProperties.POSSIBLE_VALUES.getPropertyName());
if (val == null || val.trim().length() == 0) {
return null;
}
return JSONUtil.toMap(new JSONObject(val));
}
protected Collection<TextIndexHint> getTextIndexHints(OWLOntology o, OWLDataProperty owlEntity) {
return TextIndexHint.parse(getAnnotationValueByUri(o, owlEntity, LumifyProperties.TEXT_INDEX_HINTS.getPropertyName()));
}
protected String getAnnotationValueByUri(OWLOntology o, OWLEntity owlEntity, String uri) {
for (OWLAnnotation annotation : owlEntity.getAnnotations(o)) {
if (annotation.getProperty().getIRI().toString().equals(uri)) {
OWLLiteral value = (OWLLiteral) annotation.getValue();
return value.getLiteral();
}
}
return null;
}
protected ImmutableList<String> getAnnotationValuesByUriOrNull(OWLOntology o, OWLEntity owlEntity, String uri) {
List<String> values = new ArrayList<>();
for (OWLAnnotation annotation : owlEntity.getAnnotations(o)) {
if (annotation.getProperty().getIRI().toString().equals(uri)) {
OWLLiteral value = (OWLLiteral) annotation.getValue();
values.add(value.getLiteral());
}
}
if (values.size() == 0) {
return null;
}
return ImmutableList.copyOf(values);
}
protected String[] getAnnotationValuesByUri(OWLOntology o, OWLEntity owlEntity, String uri) {
List<String> results = new ArrayList<>();
for (OWLAnnotation annotation : owlEntity.getAnnotations(o)) {
if (annotation.getProperty().getIRI().toString().equals(uri)) {
OWLLiteral value = (OWLLiteral) annotation.getValue();
results.add(value.getLiteral());
}
}
return results.toArray(new String[results.size()]);
}
@Override
public void writePackage(File file, IRI documentIRI, Authorizations authorizations) throws Exception {
ZipFile zipped = new ZipFile(file);
if (zipped.isValidZipFile()) {
File tempDir = Files.createTempDir();
try {
LOGGER.info("Extracting: %s to %s", file.getAbsoluteFile(), tempDir.getAbsolutePath());
zipped.extractAll(tempDir.getAbsolutePath());
File owlFile = findOwlFile(tempDir);
importFile(owlFile, documentIRI, authorizations);
} finally {
FileUtils.deleteDirectory(tempDir);
}
} else {
importFile(file, documentIRI, authorizations);
}
}
protected File findOwlFile(File fileOrDir) {
if (fileOrDir.isFile()) {
return fileOrDir;
}
File[] files = fileOrDir.listFiles();
if (files == null) {
return null;
}
for (File child : files) {
if (child.isDirectory()) {
File found = findOwlFile(child);
if (found != null) {
return found;
}
} else if (child.getName().toLowerCase().endsWith(".owl")) {
return child;
}
}
return null;
}
@Override
public void resolvePropertyIds(JSONArray filterJson) throws JSONException {
for (int i = 0; i < filterJson.length(); i++) {
JSONObject filter = filterJson.getJSONObject(i);
if (filter.has("propertyId") && !filter.has("propertyName")) {
String propertyVertexId = filter.getString("propertyId");
OntologyProperty property = getPropertyByIRI(propertyVertexId);
if (property == null) {
throw new RuntimeException("Could not find property with id: " + propertyVertexId);
}
filter.put("propertyName", property.getTitle());
filter.put("propertyDataType", property.getDataType());
}
}
}
@Override
public Concept getConceptByIRI(String conceptIRI) {
for (Concept concept : getConceptsWithProperties()) {
if (concept.getIRI().equals(conceptIRI)) {
return concept;
}
}
return null;
}
@Override
public OntologyProperty getPropertyByIRI(String propertyIRI) {
for (OntologyProperty prop : getProperties()) {
if (prop.getTitle().equals(propertyIRI)) {
return prop;
}
}
return null;
}
public Relationship getRelationshipByIRI(String relationshipIRI) {
for (Relationship rel : getRelationships()) {
if (rel.getIRI().equals(relationshipIRI)) {
return rel;
}
}
return null;
}
public Concept getConceptByIntent(String intent) {
String configurationKey = CONFIG_INTENT_CONCEPT_PREFIX + intent;
String conceptIri = getConfiguration().get(configurationKey, null);
if (conceptIri != null) {
Concept concept = getConceptByIRI(conceptIri);
if (concept == null) {
throw new LumifyException("Could not find concept by configuration key: " + configurationKey);
}
return concept;
}
List<Concept> concepts = findLoadedConceptsByIntent(intent);
if (concepts.size() == 0) {
return null;
}
if (concepts.size() == 1) {
return concepts.get(0);
}
String iris = Joiner.on(',').join(new ConvertingIterable<Concept, String>(concepts) {
@Override
protected String convert(Concept o) {
return o.getIRI();
}
});
throw new LumifyException("Found multiple concepts for intent: " + intent + " (" + iris + ")");
}
public String getConceptIRIByIntent(String intent) {
Concept concept = getConceptByIntent(intent);
if (concept != null) {
return concept.getIRI();
}
return null;
}
@Override
public Concept getRequiredConceptByIntent(String intent) {
Concept concept = getConceptByIntent(intent);
if (concept == null) {
throw new LumifyException("Could not find concept by intent: " + intent);
}
return concept;
}
@Override
public String getRequiredConceptIRIByIntent(String intent) {
return getRequiredConceptByIntent(intent).getIRI();
}
private List<Concept> findLoadedConceptsByIntent(String intent) {
List<Concept> results = new ArrayList<>();
for (Concept concept : getConceptsWithProperties()) {
String[] conceptIntents = concept.getIntents();
if (Arrays.asList(conceptIntents).contains(intent)) {
results.add(concept);
}
}
return results;
}
public Relationship getRelationshipByIntent(String intent) {
String configurationKey = CONFIG_INTENT_RELATIONSHIP_PREFIX + intent;
String relationshipIri = getConfiguration().get(configurationKey, null);
if (relationshipIri != null) {
Relationship relationship = getRelationshipByIRI(relationshipIri);
if (relationship == null) {
throw new LumifyException("Could not find relationship by configuration key: " + configurationKey);
}
return relationship;
}
List<Relationship> relationships = findLoadedRelationshipsByIntent(intent);
if (relationships.size() == 0) {
return null;
}
if (relationships.size() == 1) {
return relationships.get(0);
}
String iris = Joiner.on(',').join(new ConvertingIterable<Relationship, String>(relationships) {
@Override
protected String convert(Relationship o) {
return o.getIRI();
}
});
throw new LumifyException("Found multiple relationships for intent: " + intent + " (" + iris + ")");
}
public String getRelationshipIRIByIntent(String intent) {
Relationship relationship = getRelationshipByIntent(intent);
if (relationship != null) {
return relationship.getIRI();
}
return null;
}
@Override
public Relationship getRequiredRelationshipByIntent(String intent) {
Relationship relationship = getRelationshipByIntent(intent);
if (relationship == null) {
throw new LumifyException("Could not find relationship by intent: " + intent);
}
return relationship;
}
@Override
public String getRequiredRelationshipIRIByIntent(String intent) {
return getRequiredRelationshipByIntent(intent).getIRI();
}
private List<Relationship> findLoadedRelationshipsByIntent(String intent) {
List<Relationship> results = new ArrayList<>();
for (Relationship relationship : getRelationships()) {
String[] relationshipIntents = relationship.getIntents();
if (Arrays.asList(relationshipIntents).contains(intent)) {
results.add(relationship);
}
}
return results;
}
public OntologyProperty getPropertyByIntent(String intent) {
String configurationKey = CONFIG_INTENT_PROPERTY_PREFIX + intent;
String propertyIri = getConfiguration().get(configurationKey, null);
if (propertyIri != null) {
OntologyProperty property = getPropertyByIRI(propertyIri);
if (property == null) {
throw new LumifyException("Could not find property by configuration key: " + configurationKey);
}
return property;
}
List<OntologyProperty> properties = findLoadedPropertiesByIntent(intent);
if (properties.size() == 0) {
return null;
}
if (properties.size() == 1) {
return properties.get(0);
}
String iris = Joiner.on(',').join(new ConvertingIterable<OntologyProperty, String>(properties) {
@Override
protected String convert(OntologyProperty o) {
return o.getTitle();
}
});
throw new LumifyException("Found multiple properties for intent: " + intent + " (" + iris + ")");
}
public String getPropertyIRIByIntent(String intent) {
OntologyProperty prop = getPropertyByIntent(intent);
if (prop != null) {
return prop.getTitle();
}
return null;
}
@Override
public OntologyProperty getRequiredPropertyByIntent(String intent) {
OntologyProperty property = getPropertyByIntent(intent);
if (property == null) {
throw new LumifyException("Could not find property by intent: " + intent);
}
return property;
}
@Override
public String getRequiredPropertyIRIByIntent(String intent) {
return getRequiredPropertyByIntent(intent).getTitle();
}
private List<OntologyProperty> findLoadedPropertiesByIntent(String intent) {
List<OntologyProperty> results = new ArrayList<>();
for (OntologyProperty property : getProperties()) {
String[] propertyIntents = property.getIntents();
if (Arrays.asList(propertyIntents).contains(intent)) {
results.add(property);
}
}
return results;
}
@Override
@SuppressWarnings("unchecked")
public ClientApiOntology getClientApiObject() {
Object[] results = ExecutorServiceUtil.runAllAndWait(
new Callable<Object>() {
@Override
public Object call() {
Iterable<Concept> concepts = getConceptsWithProperties();
return Concept.toClientApiConcepts(concepts);
}
},
new Callable<Object>() {
@Override
public Object call() {
Iterable<OntologyProperty> properties = getProperties();
return OntologyProperty.toClientApiProperties(properties);
}
},
new Callable<Object>() {
@Override
public Object call() {
Iterable<Relationship> relationships = getRelationships();
return Relationship.toClientApiRelationships(relationships);
}
}
);
ClientApiOntology ontology = new ClientApiOntology();
ontology.addAllConcepts((Collection<ClientApiOntology.Concept>) results[0]);
ontology.addAllProperties((Collection<ClientApiOntology.Property>) results[1]);
ontology.addAllRelationships((Collection<ClientApiOntology.Relationship>) results[2]);
return ontology;
}
public final Configuration getConfiguration() {
return configuration;
}
protected void definePropertyOnGraph(Graph graph, String propertyIri, PropertyType dataType, Collection<TextIndexHint> textIndexHints, Double boost) {
DefinePropertyBuilder definePropertyBuilder = graph.defineProperty(propertyIri);
definePropertyBuilder.dataType(PropertyType.getTypeClass(dataType));
if (dataType == PropertyType.STRING) {
definePropertyBuilder.textIndexHint(textIndexHints);
}
if (boost != null) {
if (graph.isFieldBoostSupported()) {
definePropertyBuilder.boost(boost);
} else {
LOGGER.warn("Field boosting is not support by the graph");
}
}
definePropertyBuilder.define();
}
}