/**
* 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.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
public class OWLClass extends RDFItem<OWLClass> {
private final Set<OWLProperty> properties = new TreeSet<>();
private final Set<OWLClass> sourceClasses = new TreeSet<>();
private final Set<OWLClass> targetClasses = new TreeSet<>();
private final Set<String> domainIds = new TreeSet<>();
private final Set<String> rangeIds = new TreeSet<>();
private boolean isRelationship = false;
private boolean allowsInstances = false;
private boolean multipleOccurrences = false;
private boolean isMixedIn = false;
private boolean oneWay = false;
private boolean primary = false;
private OWLClass actualSourceType = null;
private OWLClass actualTargetType = null;
private OWLClass inverse = null;
private URI inverseId = null;
protected String icon = null;
public OWLClass(final Element element) {
super(element);
initialize();
}
@Override
public String toString() {
return getStructrName(true); // + (getSuperclass() != null ? " extends " + getSuperclass().toString() : "");
}
public String getIcon() {
return icon;
}
public void addProperty(final OWLProperty property) {
properties.add(property);
}
public Set<OWLProperty> getProperties() {
return properties;
}
public Set<OWLProperty> getAllProperties() {
final Set<OWLClass> typeAndSuperclasses = getTypeAndSuperclasses();
final Set<OWLProperty> allProperties = new TreeSet<>();
for (final OWLClass type : typeAndSuperclasses) {
allProperties.addAll(type.getProperties());
}
return allProperties;
}
public boolean hasSuperclass(final OWLClass type) {
final OWLClass superclass = getSuperclass();
if (superclass != null) {
if (superclass.getId().equals(type.getId())) {
return true;
}
return superclass.hasSuperclass(type);
}
return false;
}
public Set<String> getDomainIds() {
if (domainIds.isEmpty() && getSuperclass() != null) {
return getSuperclass().getDomainIds();
}
return domainIds;
}
public Set<String> getRangeIds() {
if (rangeIds.isEmpty() && getSuperclass() != null) {
return getSuperclass().getRangeIds();
}
return rangeIds;
}
public void resolveRelatedTypes(final Map<URI, OWLClass> classes) {
for (final String domainId : getDomainIds()) {
final URI uri = URI.create(domainId);
final OWLClass cl = classes.get(uri);
if (cl != null) {
sourceClasses.add(cl);
} else {
OWLParserv2.logger.println("No class found for " + domainId);
}
}
for (final String rangeId : getRangeIds()) {
final URI uri = URI.create(rangeId);
final OWLClass cl = classes.get(uri);
if (cl != null) {
targetClasses.add(cl);
} else {
OWLParserv2.logger.println("No class found for " + rangeId);
}
}
}
public void setIsRelationship(final boolean isRelationship) {
this.isRelationship = isRelationship;
}
public boolean isRelationship() {
return isRelationship;
}
// ----- methods from OWLProperty -----
public void setSourceClass(final OWLClass sourceClass) {
this.sourceClasses.add(sourceClass);
}
public void setTargetClass(final OWLClass targetClass) {
this.targetClasses.add(targetClass);
}
public void resolveRelationshipTypes(final Map<URI, OWLClass> owlClasses) {
if (inverseId != null) {
inverse = owlClasses.get(inverseId);
}
this.actualSourceType = findCommonBaseType(sourceClasses);
this.actualTargetType = findCommonBaseType(targetClasses);
}
public Set<OWLClass> getSourceClasses() {
return sourceClasses;
}
public Set<OWLClass> getTargetClasses() {
return targetClasses;
}
public OWLClass getInverse() {
return inverse;
}
public URI getInverseOfId() {
return inverseId;
}
public boolean multipleOccurrences() {
return multipleOccurrences;
}
public List<OWLClass> getActualSourceTypes() {
final List<OWLClass> actualSourceTypes = new LinkedList<>();
if (actualSourceType != null) {
actualSourceTypes.add(actualSourceType);
} else {
actualSourceTypes.addAll(findCommonBaseTypes(sourceClasses));
}
return actualSourceTypes;
}
public List<OWLClass> getActualTargetTypes() {
final List<OWLClass> actualTargetTypes = new LinkedList<>();
if (actualTargetType != null) {
actualTargetTypes.add(actualTargetType);
} else {
actualTargetTypes.addAll(findCommonBaseTypes(targetClasses));
}
return actualTargetTypes;
}
public boolean hasInverse() {
return inverse != null;
}
public boolean isPrimary() {
return primary;
}
private OWLClass findCommonBaseType(final Set<OWLClass> source) {
if (!source.isEmpty()) {
if (source.size() > 1) {
Set<OWLClass> commonSuperclasses = null;
for (final OWLClass sourceClass : source) {
final Set<OWLClass> superclasses = sourceClass.getTypeAndSuperclasses();
if (commonSuperclasses == null) {
// create initial set
commonSuperclasses = new LinkedHashSet<>();
commonSuperclasses.addAll(superclasses);
} else {
// intersect with existing set
commonSuperclasses.retainAll(superclasses);
}
}
// commonSuperclasses are sorted so the last
// class is the lowest common supertype
if (!commonSuperclasses.isEmpty()) {
return commonSuperclasses.iterator().next();
}
} else {
return source.iterator().next();
}
}
return null;
}
private List<OWLClass> findCommonBaseTypes(final Set<OWLClass> source) {
final List<OWLClass> commonBaseTypes = new LinkedList<>();
if (!source.isEmpty()) {
// first test: add all types
commonBaseTypes.addAll(source);
}
return commonBaseTypes;
}
// ----- protected methods -----
@Override
protected Set<String> getInheritanceIdentifiers() {
final Set<String> identifiers = new HashSet<>();
identifiers.add("rdfs:subClassOf");
identifiers.add("rdfs:subPropertyOf");
return identifiers;
}
// ----- private methods -----
private void initialize() {
domainIds.addAll(getResourceIds("rdfs:domain"));
rangeIds.addAll(getResourceIds("rdfs:range"));
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")));
icon = getValue(getFirstElement(getElement(), "krdf:icon"));
final Object isPrimaryValue = getValue(getFirstElement(getElement(), "krdf:primary"));
if (isPrimaryValue == null || "true".equals(isPrimaryValue)) {
primary = true;
}
final Node node = getFirstElement(getElement(), "owl:inverseOf");
if (node != null) {
final String inverse = getResourceId(node);
if (inverse != null) {
this.inverseId = URI.create(inverse);
}
}
}
}