/**
* 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.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.structr.common.error.FrameworkException;
import org.structr.core.app.App;
import org.structr.core.app.StructrApp;
import org.structr.core.entity.AbstractNode;
import org.structr.core.graph.NodeAttribute;
import org.structr.core.graph.NodeInterface;
import org.structr.core.property.ISO8601DateProperty;
import org.structr.core.property.PropertyKey;
import org.structr.schema.ConfigurationProvider;
import org.structr.schema.json.JsonSchema;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class OWLInstance extends RDFItem<OWLInstance> {
private static final Map<URI, NodeInterface> instances = new LinkedHashMap<>();
private final SimpleDateFormat isoFormat = new SimpleDateFormat(ISO8601DateProperty.getDefaultFormat());
private final SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
protected OWLClass type = null;
protected Class nodeType = null;
protected PropertyKey originIdKey = null;
protected NodeInterface instance = null;
public OWLInstance(final Element element) {
super(element);
}
public void setType(final OWLClass type) {
this.type = type;
}
public OWLClass getType() {
return type;
}
public void createDatabaseNode(final App app) throws FrameworkException {
final ConfigurationProvider config = StructrApp.getConfiguration();
final String className = type.getStructrName(true);
nodeType = config.getNodeEntityClass(className);
if (nodeType != null) {
originIdKey = config.getPropertyKeyForJSONName(nodeType, "originId", false);
if (originIdKey != null) {
instance = app.create(nodeType, new NodeAttribute(originIdKey, getId().toString()));
if (instance != null) {
instances.put(getId(), instance);
}
} else {
OWLParserv2.logger.println("NOT creating instance for " + getId() + ", no originId property key found.");
}
} else {
OWLParserv2.logger.println("NOT creating instance for " + getId() + ", no node type found.");
}
}
public void resolveExtensions(final App app, final Map<String, OWLClass> owlClassesByFragment, final Map<URI, OWLInstance> owlInstances, final List<OWLInstance> newInstances) throws FrameworkException {
final NodeList extensions = getElements(getElement(), "krdf:KExtendedByRelation");
final ConfigurationProvider config = StructrApp.getConfiguration();
final Class baseType = config.getNodeEntityClass("BaseNode");
final PropertyKey extensionsKey = config.getPropertyKeyForJSONName(baseType, "extendedBy", false);
if (extensions != null && extensionsKey != null) {
int len = extensions.getLength();
for (int i=0; i<len; i++) {
final Element ext = (Element)extensions.item(i);
final NodeList contents = ext.getChildNodes();
if (contents != null) {
int contentLen = contents.getLength();
for (int j=0; j<contentLen; j++) {
final Node node = contents.item(j);
if (node instanceof Element) {
final Element content = (Element)node;
final OWLInstance inst = new OWLInstance(content);
final URI id = inst.getId();
if (id != null) {
final String type = inst.getTypeName();
if (type != null) {
final OWLClass owlType = owlClassesByFragment.get(type);
if (owlType != null) {
inst.setType(owlType);
newInstances.add(inst);
inst.createDatabaseNode(app);
if (instance != null) {
// create extension entity and link
final Set extendedBySet = new HashSet<>((List)instance.getProperty(extensionsKey));
extendedBySet.add(inst.instance);
instance.setProperty(extensionsKey, new LinkedList<>(extendedBySet));
}
}
}
}
}
}
}
}
}
}
public void resolveProperties() throws FrameworkException {
if (instance != null && type != null) {
OWLParserv2.logger.println("#################################################################################################");
OWLParserv2.logger.println("Resolving properties of " + type.getStructrName(true) + ": " + getId());
final App app = StructrApp.getInstance();
final ConfigurationProvider config = StructrApp.getConfiguration();
final Class baseNodeType = config.getNodeEntityClass("BaseNode");
final Class localizedNameType = config.getNodeEntityClass("LocalizedName");
final PropertyKey namesKey = config.getPropertyKeyForJSONName(baseNodeType, "names");
final PropertyKey langKey = config.getPropertyKeyForJSONName(localizedNameType, "locale");
if (localizedNameType != null && namesKey != null) {
// set name(s)
final List<NodeInterface> localizedNames = new LinkedList<>();
for (final Name name : names) {
localizedNames.add(app.create(localizedNameType, new NodeAttribute<>(AbstractNode.name, name.name), new NodeAttribute<>(langKey, name.lang)));
}
instance.setProperty(namesKey, localizedNames);
}
// extract creation and modification dates
try { setProperty(nodeType, instance, "createdAt", isoFormat.format(dateFormat.parse(createdAt))); } catch (Throwable ignore) { }
try { setProperty(nodeType, instance, "modifiedAt", isoFormat.format(dateFormat.parse(modifiedAt))); } catch (Throwable ignore) { }
for (final OWLProperty property : type.getAllProperties()) {
final String rawPropertyName = property.getId().getFragment();
final String cleanPropertyName = property.getFragmentName(false);
if (property.multipleOccurrences()) {
final NodeList values = getElements(getElement(), rawPropertyName);
final int len = values.getLength();
final ArrayList<String> array = new ArrayList<>();
for (int i=0; i<len; i++) {
final Object value = getValue(values.item(i));
if (value != null) {
array.add(value.toString());
}
}
final String[] value = array.toArray(new String[0]);
OWLParserv2.logger.println(cleanPropertyName + " = " + value);
setProperty(nodeType, instance, cleanPropertyName, value);
} else {
Object value = getValue(getFirstElement(getElement(), rawPropertyName));
OWLParserv2.logger.println(cleanPropertyName + " = " + value);
setProperty(nodeType, instance, cleanPropertyName, property.convertValue(value));
}
}
}
}
public void resolveRelationships(final JsonSchema schema, final Map<String, OWLClass> owlClassesByFragment, final Map<URI, OWLInstance> instances, final Map<String, RDFDescription> descriptions, final Map<String, OWLProperty> properties) throws FrameworkException {
if (instance != null && type != null) {
OWLParserv2.logger.println("#################################################################################################");
OWLParserv2.logger.println("Resolving relationships of " + type.getStructrName(true) + ": " + getId());
final ConfigurationProvider config = StructrApp.getConfiguration();
final NodeList propertyElements = getElement().getChildNodes();
if (propertyElements != null) {
final int len = propertyElements.getLength();
for (int i=0; i<len; i++) {
final Node propertyElement = propertyElements.item(i);
if (propertyElement instanceof Element) {
final Element element = (Element)propertyElement;
final String tagName = RDFItem.cleanName(element.getTagName());
final String reference = getAttribute(element, "rdf:resource");
if (reference != null) {
final OWLInstance relatedInstance = instances.get(URI.create(reference));
if (relatedInstance != null) {
final OWLClass relationshipType = owlClassesByFragment.get(tagName);
if (relationshipType != null) {
final List<OWLClass> sourceTypes = relationshipType.getActualSourceTypes();
final List<OWLClass> targetTypes = relationshipType.getActualTargetTypes();
final Class hyperRelationshipType = config.getNodeEntityClass(tagName);
if (hyperRelationshipType != null) {
if (sourceTypes.size() == 1 && targetTypes.size() == 1) {
final OWLClass sourceType = sourceTypes.get(0);
final OWLClass targetType = targetTypes.get(0);
final String sourcePropertyName = sourceType.getStructrName(false);
final String targetPropertyName = targetType.getStructrName(false);
final PropertyKey sourceKey = config.getPropertyKeyForJSONName(hyperRelationshipType, sourcePropertyName, false);
final PropertyKey targetKey = config.getPropertyKeyForJSONName(hyperRelationshipType, targetPropertyName, false);
if (sourceKey != null && targetKey != null) {
if (this.instance != null && relatedInstance.instance != null) {
final NodeInterface hyperNode = StructrApp.getInstance().create(hyperRelationshipType,
new NodeAttribute(sourceKey, this.instance),
new NodeAttribute(targetKey, relatedInstance.instance)
);
// resolve properties that come via rdf:Description
final String referenceId = getAttribute(element, "rdf:ID");
if (referenceId != null && hyperNode != null) {
final RDFDescription description = descriptions.get(referenceId);
if (description != null) {
description.resolveProperties(hyperNode, owlClassesByFragment, properties);
}
}
} else {
System.out.println("!!!!!!!! No instance found to set on " + getId());
}
} else {
System.out.println(" No property keys found for " + sourcePropertyName + ", " + targetPropertyName);
}
} else {
System.out.println(" Ambiguous source or target types: " + sourceTypes + ", " + targetTypes);
}
} else {
System.out.println(" Relationship type " + tagName + " not found for " + getId());
}
} else {
System.out.println("No type found for " + tagName);
}
} else {
System.out.println(" No instance found for " + reference);
}
}
}
}
}
}
}
// ----- protected methods -----
@Override
protected Set<String> getInheritanceIdentifiers() {
return Collections.emptySet();
}
}