/**
* 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.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.lang.StringUtils;
import org.structr.common.CaseHelper;
import org.structr.common.SecurityContext;
import org.structr.common.error.FrameworkException;
import org.structr.core.GraphObject;
import org.structr.core.app.StructrApp;
import org.structr.core.converter.PropertyConverter;
import org.structr.core.property.PropertyKey;
import org.structr.schema.ConfigurationProvider;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public abstract class RDFItem<T extends RDFItem> implements Comparable<RDFItem> {
protected final List<Name> names = new LinkedList<>();
private final Set<T> subclasses = new TreeSet<>();
protected String createdAt = null;
protected String modifiedAt = null;
protected String rdfReferenceId = null;
private Element element = null;
private T superclass = null;
private URI superclassId = null;
private URI id = null;
private String internalName = null;
private String type = null;
protected abstract Set<String> getInheritanceIdentifiers();
public RDFItem(final Element element) {
if (element != null) {
this.type = element.getTagName();
this.element = element;
initialize(element);
}
}
@Override
public String toString() {
return getTypeName() + ", " + id + " extends " + superclassId;
}
public List<Name> getNames() {
return names;
}
public final String getTypeName() {
return CaseHelper.toUpperCamelCase(cleanName(type));
}
public final String getStructrName(final boolean upperCase) {
return getFragmentName(upperCase);
}
public String getRawFragmentName() {
if (id != null) {
return id.getFragment();
}
return null;
}
public String getFragmentName(final boolean upperCase) {
if (id != null) {
final String fragment = id.getFragment();
if (StringUtils.isNotBlank(fragment)) {
if (upperCase) {
return CaseHelper.toUpperCamelCase(cleanName(fragment));
} else {
return CaseHelper.toLowerCamelCase(cleanName(fragment));
}
}
}
return internalName;
}
public final URI getSuperclassId() {
return superclassId;
}
public final URI getId() {
return id;
}
public final void setId(final String id) {
if (id != null) {
try {
setId(URI.create(id));
} catch (Throwable ignore) {}
}
}
public final void setId(final URI id) {
this.id = id;
}
public void resolveSuperclasses(final Map<URI, T> classes) {
final URI _superclassId = getSuperclassId();
if (_superclassId != null) {
final T _superclass = classes.get(_superclassId);
if (_superclass != null) {
this.addSuperclass(_superclass);
}
}
}
public void addSuperclass(final T superclass) {
superclass.getSubclasses().add(this);
this.superclass = superclass;
}
public T getSuperclass() {
return superclass;
}
public Set<T> getSubclasses() {
return subclasses;
}
public T getRoot() {
if (superclass != null) {
return (T)superclass.getRoot();
}
return (T)this;
}
public Set<T> getTypeAndSuperclasses() {
final Set<T> superclasses = new LinkedHashSet<>();
superclasses.add((T)this);
if (getSuperclass() != null) {
superclasses.addAll(superclass.getTypeAndSuperclasses());
}
return superclasses;
}
// ----- interface Comparable<RDFItem> -----
@Override
public int compareTo(final RDFItem o) {
if (id != null && o != null && o.id != null) {
return id.compareTo(o.id);
}
return -1;
}
// ----- protected methods -----
protected final Element getElement() {
return element;
}
protected final String getResourceId(final Node node) {
return getAttribute(node, "rdf:resource");
}
protected final String getAttribute(final Node node, final String key) {
final NamedNodeMap map = node.getAttributes();
final Node attrNode = map.getNamedItem(key);
if (attrNode != null) {
return attrNode.getNodeValue();
}
return null;
}
protected final String getValue(final Node element) {
if (element != null) {
final Node firstChild = element.getFirstChild();
if (firstChild != null) {
return firstChild.getNodeValue();
}
}
return null;
}
protected Element getFirstElement(final Element element, final String key) {
return (Element)element.getElementsByTagName(key).item(0);
}
protected NodeList getElements(final Element element, final String key) {
return element.getElementsByTagName(key);
}
protected Set<String> getResourceIds(final String key) {
final NodeList ranges = element.getElementsByTagName(key);
final Set<String> ids = new TreeSet<>();
if (ranges != null) {
final int len = ranges.getLength();
for (int i=0; i<len; i++) {
final Node item = ranges.item(i);
final String itemId = getResourceId(item);
if (itemId != null) {
ids.add(itemId);
}
}
}
return ids;
}
protected Object setProperty(final Class nodeType, final GraphObject instance, final String propertyName, final Object value) throws FrameworkException {
final ConfigurationProvider config = StructrApp.getConfiguration();
Object convertedValue = value;
if (convertedValue != null) {
final PropertyKey key = config.getPropertyKeyForJSONName(nodeType, propertyName, false);
if (key != null) {
final PropertyConverter inputConverter = key.inputConverter(SecurityContext.getSuperUserInstance());
if (inputConverter != null) {
convertedValue = inputConverter.convert(convertedValue);
}
if (convertedValue == null) {
OWLParserv2.logger.println("Invalid converted value " + convertedValue + ", source was " + value);
}
return instance.setProperty(key, convertedValue);
} else {
System.out.println("Key " + propertyName + " not found on " + nodeType.getSimpleName());
}
}
return null;
}
// ----- private methods -----
private void initialize(final Element element) {
String _id = getAttribute(element, "rdf:about");
if (_id != null) {
setId(_id);
}
initializeRDFSLabels(element.getElementsByTagName("rdfs:label"));
internalName = getValue(getFirstElement(getElement(), "krdf:internalName"));
// detect inheritance
for (final String inheritanceIdentifier : getInheritanceIdentifiers()) {
initializeSuperclass(element.getElementsByTagName(inheritanceIdentifier));
if (superclassId != null) {
break;
}
}
// extract and parse creation and modification dates
createdAt = getValue(getFirstElement(getElement(), "createdAt"));
modifiedAt = getValue(getFirstElement(getElement(), "modifiedAt"));
rdfReferenceId = getAttribute(getElement(), "rdf:ID");
}
private void initializeSuperclass(final NodeList nodeList) {
if (nodeList != null) {
final int len = nodeList.getLength();
for (int i=0; i<len; i++) {
final String superclass = getResourceId(nodeList.item(i));
if (superclass != null) {
this.superclassId = URI.create(superclass);
}
}
}
}
private void initializeRDFSLabels(final NodeList elements) {
if (elements != null) {
final int len = elements.getLength();
for (int i=0; i<len; i++) {
final Node node = elements.item(i);
final String value = getValue(node);
String lang = getAttribute(node, "xml:lang");
if (lang == null) {
lang = "de";
}
if (lang != null && value != null) {
names.add(new Name(lang, value));
}
}
}
}
public static String cleanName(final String source) {
final StringBuilder buf = new StringBuilder();
final String[] parts = source.split("[ ,\\.\\-\\+\\?\\*\\\"\\'\\=\\(\\)\\[\\]<>]+");
final int len = parts.length;
for (int i=0; i<len; i++) {
String part = parts[i].trim();
if (StringUtils.isNotBlank(part)) {
part = part.replace("ä", "ae");
part = part.replace("ö", "oe");
part = part.replace("ü", "ue");
part = part.replace("Ä", "Ae");
part = part.replace("Ö", "Oe");
part = part.replace("Ü", "Ue");
part = part.replace("ß", "ss");
buf.append(StringUtils.capitalize(part));
}
}
return buf.toString().replaceAll("[\\W]+", "");
}
}