/** * Copyright (C) 2010-2017 Structr GmbH * * This file is part of Structr <http://structr.org>. * * Structr is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * Structr is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Structr. If not, see <http://www.gnu.org/licenses/>. */ package org.structr.rdfs; import java.net.URI; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.apache.commons.lang.StringUtils; import org.structr.common.error.FrameworkException; import org.structr.core.app.App; import org.structr.core.app.StructrApp; import org.structr.core.entity.Localization; import org.structr.core.graph.NodeAttribute; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class OWLProperty<T extends RDFItem> extends RDFItem<T> { private static final Map<String, String> replacementMap = new LinkedHashMap<>(); static { replacementMap.put("<", "less"); replacementMap.put("<;", "less"); replacementMap.put(">", "greater"); replacementMap.put(">", "greater"); replacementMap.put("=", "equal"); replacementMap.put("€", "euro"); replacementMap.put("$", "dollar"); replacementMap.put("%", "percent"); replacementMap.put("/", " per "); replacementMap.put("ä", "ae"); replacementMap.put("Ä", "Ae"); replacementMap.put("ö", "oe"); replacementMap.put("Ö", "Oe"); replacementMap.put("ü", "ue"); replacementMap.put("Ü", "Ue"); replacementMap.put("ß", "ss"); replacementMap.put("?", "unknown"); replacementMap.put("µ", "micro"); replacementMap.put(".", "dot"); replacementMap.put("(", "_"); replacementMap.put(")", "_"); } private final Set<OWLProperty> datatypeProperties = new TreeSet<>(); private final Set<OWLProperty> objectProperties = new TreeSet<>(); private final Set<String> domainIds = new TreeSet<>(); private final Set<String> rangeIds = new TreeSet<>(); private final Set<String> typeIds = new TreeSet<>(); private boolean allowsInstances = false; private boolean multipleOccurrences = false; private boolean isMixedIn = false; private boolean oneWay = false; public OWLProperty(final Element element) { super(element); initialize(); } @Override public String toString() { return getTypeName() + "(" + (typeIds.isEmpty() ? rangeIds : typeIds) + ")"; } public void resolveClassProperties(final Map<URI, OWLClass> classes) { // only the domain can be a class for (final String domainId : getDomainIds()) { final URI uri = URI.create(domainId); final OWLClass cl = classes.get(uri); if (cl != null) { cl.addProperty(this); } else { OWLParserv2.logger.println("No class found for " + domainId); } } } public Set<String> getDomainIds() { if (domainIds.isEmpty() && getSuperclass() != null) { return ((OWLProperty)getSuperclass()).getDomainIds(); } return domainIds; } public Set<String> getRangeIds() { if (rangeIds.isEmpty() && getSuperclass() != null) { return ((OWLProperty)getSuperclass()).getRangeIds(); } return rangeIds; } public Set<String> getTypeIds() { return typeIds; } public boolean allowsInstances() { return allowsInstances; } public boolean multipleOccurrences() { return multipleOccurrences; } public boolean isMixedIn() { return isMixedIn; } public boolean oneWay() { return oneWay; } public void addDatatypeProperty(final OWLProperty prop) { datatypeProperties.add(prop); } public void addObjectProperty(final OWLProperty prop) { objectProperties.add(prop); } public Set<OWLProperty> getDatatypeProperties() { return datatypeProperties; } public Set<OWLProperty> getObjectProperties() { return objectProperties; } // ----- methods from OWLProperty ----- public boolean isPrimitiveType() { return !getTypeIds().isEmpty(); } public String getRawPrimitiveType() { if (!getTypeIds().isEmpty()) { return getTypeIds().iterator().next(); } return null; } public String getStructrType() { final String primitiveType = getRawPrimitiveType(); if (primitiveType != null) { final String mappedXmlType = OWLParserv2.customKTypeMapping.get(primitiveType); if (mappedXmlType != null) { return OWLParserv2.xmlSchemaPropertyMapping.get(mappedXmlType); } else { // no mapping, must be "special" type switch (primitiveType) { case "KBlob": return "File"; case "KChoice": return "Enum"; } } } return null; } public String getAdditionalFormat() { switch (getRawPrimitiveType()) { case "KDate": return "dd.MM.yyyy"; case "KDateAndTime": return "dd.MM.yyyy HH:mm:ss"; case "KFlexTime": return "dd.MM.yyyy"; } return null; } public Set<Choice> getChoices() { final NodeList hasChoiceElements = getElements(getElement(), "krdf:hasChoice"); final Set<Choice> choices = new TreeSet<>(); final int len = hasChoiceElements.getLength(); for (int i=0; i<len; i++) { final Element hasChoice = (Element)hasChoiceElements.item(i); final Element choice = getFirstElement(hasChoice, "krdf:Choice"); if (choice != null) { final Node choiceNameElement = getFirstElement(choice, "krdf:choiceName"); if (choiceNameElement != null) { final String choiceName = getValue(choiceNameElement); if (choiceName != null) { final Choice choiceObject = new Choice(choiceName, convertValue(choiceName).toString()); final String orderString = getValue(getFirstElement(choice, "krdf:order")); // parse and set position (called "order") if (orderString != null && StringUtils.isNumeric(orderString)) { choiceObject.setPosition(Integer.parseInt(orderString)); } choiceObject.setTranslations(getElements(choice, "krdf:choiceTranslation")); choices.add(choiceObject); } } } } return choices; } public Object convertValue(final Object source) { if ("Enum".equals(getStructrType()) && source != null) { String value = source.toString(); for (final Map.Entry<String, String> replacement : replacementMap.entrySet()) { value = value.replace(replacement.getKey(), replacement.getValue()); } return "_" + value.replaceAll("[\\W_]+", "_"); } return source; } public String[] getEnums(final String domain) throws FrameworkException { final App app = StructrApp.getInstance(); final Set<Choice> choices = getChoices(); final String[] names = new String[choices.size()]; int i = 0; for (final Choice choice : choices) { names[i++] = choice.getIdentifier(); for (final Map.Entry<String, String> translation : choice.getTranslations().entrySet()) { // create localization for enum value app.create(Localization.class, new NodeAttribute(Localization.domain, domain), new NodeAttribute(Localization.name, choice.getIdentifier()), new NodeAttribute(Localization.locale, translation.getKey()), new NodeAttribute(Localization.localizedName, translation.getValue()) ); } } return names; } // ----- protected methods ----- @Override protected Set<String> getInheritanceIdentifiers() { final Set<String> identifiers = new HashSet<>(); identifiers.add("rdfs:subPropertyOf"); return identifiers; } // ----- protected methods ----- private void initialize() { domainIds.addAll(getResourceIds("rdfs:domain")); rangeIds.addAll(getResourceIds("rdfs:range")); typeIds.addAll(getResourceIds("krdf:type")); allowsInstances = "true".equals(getValue(getFirstElement(getElement(), "krdf:allowsInstances"))); multipleOccurrences = "true".equals(getValue(getFirstElement(getElement(), "krdf:multipleOccurrences"))); isMixedIn = "true".equals(getValue(getFirstElement(getElement(), "krdf:isMixedIn"))); oneWay = "true".equals(getValue(getFirstElement(getElement(), "krdf:oneWay"))); } }