Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.konig.core.pojo.SimplePojoEmitter Maven / Gradle / Ivy
package io.konig.core.pojo;
/*
* #%L
* Konig Core
* %%
* Copyright (C) 2015 - 2016 Gregory McFall
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.openrdf.model.Namespace;
import org.openrdf.model.Resource;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.ValueFactory;
import org.openrdf.model.impl.ValueFactoryImpl;
import org.openrdf.model.vocabulary.RDF;
import io.konig.annotation.RdfList;
import io.konig.annotation.RdfProperty;
import io.konig.core.Graph;
import io.konig.core.KonigException;
import io.konig.core.NamespaceManager;
import io.konig.core.Vertex;
import io.konig.shacl.PropertyConstraint;
import io.konig.shacl.Shape;
public class SimplePojoEmitter implements PojoEmitter {
private static SimplePojoEmitter INSTANCE = new SimplePojoEmitter();
private ValueFactory valueFactory = ValueFactoryImpl.getInstance();
public static SimplePojoEmitter getInstance() {
return INSTANCE;
}
@Override
public void emit(EmitContext context, Object pojo, Graph sink) {
Worker worker = new Worker(context, sink);
worker.emit(pojo);
}
public void emit(Object pojo, Graph sink) {
emit(new EmitContext(sink), pojo, sink);
}
@Override
public void emit(NamespaceManager nsManager, Shape shape, Object pojo, Graph sink) {
Worker worker = new Worker(nsManager, sink);
worker.emit(shape, pojo);
}
private class Worker {
private EmitContext context;
private Map pojoIdMap = new HashMap<>();
private Set memory = new HashSet<>();
private Graph sink;
private NamespaceManager sinkNamespaces;
private NamespaceManager sourceNamespaces;
public Worker(EmitContext context, Graph sink) {
this.context = context;
this.sink = sink;
sinkNamespaces = sink.getNamespaceManager();
sourceNamespaces = context.getNamespaceManager();
}
public Worker(NamespaceManager sourceNamespaces, Graph sink) {
this.sink = sink;
this.sourceNamespaces = sourceNamespaces;
this.sinkNamespaces = sink.getNamespaceManager();
}
public void emit(Shape shape, Object pojo) {
if (!memory.contains(pojo)) {
memory.add(pojo);
Resource subject = getId(pojo);
emitProperties(subject, shape, pojo);
}
}
private void emitProperties(Resource subject, Shape shape, Object pojo) {
List propertyList = shape.getProperty();
for (PropertyConstraint p : propertyList) {
URI predicate = p.getPredicate();
if (predicate != null) {
Method getter = getter(p, pojo);
if (getter != null) {
try {
Object value = getter.invoke(pojo);
if (value instanceof Collection) {
emitCollection(p, subject, predicate, (Collection>)value);
} else if (value != null) {
Value object = toValue(value);
sink.edge(subject, predicate, object);
Shape valueShape = p.getShape();
if (valueShape != null) {
emit(valueShape, value);
}
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new KonigException(e);
}
} else {
String predicateName = predicate.getLocalName();
String message = "On class" + pojo.getClass().getSimpleName() +
", getter not found for predicate: " + predicateName;
throw new KonigException(message);
}
}
}
}
private void emitCollection(PropertyConstraint p, Resource subject, URI predicate, Collection> collection) {
for (Object value : collection) {
Value object = toValue(value);
sink.edge(subject, predicate, object);
Shape valueShape = p.getShape();
if (valueShape != null) {
emit(valueShape, value);
}
}
}
private Method getter(PropertyConstraint p, Object pojo) {
URI predicate = p.getPredicate();
if (predicate != null) {
Class> javaClass = pojo.getClass();
String getterName = BeanUtil.getterName(predicate);
Method[] methodList = javaClass.getMethods();
for (Method m : methodList) {
RdfProperty annotation = m.getAnnotation(RdfProperty.class);
if (annotation != null) {
String rdfProperty = annotation.value();
if (rdfProperty.equals(predicate.stringValue())) {
return m;
}
}
String methodName = m.getName();
if (methodName.equals(getterName)) {
return m;
}
}
}
return null;
}
void emit(Object pojo) {
doEmit(null, pojo);
}
void doEmit(Resource id, Object pojo) {
if (!memory.contains(pojo)) {
context.register(pojo.getClass());
if (id == null) {
id = getId(pojo);
}
if (id != null) {
memory.add(pojo);
emitProperties(id, pojo);
}
}
}
private void emitProperties(Resource subject, Object pojo) {
Class> javaClass = pojo.getClass();
Method[] methodList = javaClass.getMethods();
for (Method m : methodList) {
URI predicate = context.getterPredicate(m);
if (predicate != null) {
Object javaObject;
try {
javaObject = m.invoke(pojo);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new KonigException(e);
}
if (javaObject == null) {
continue;
}
if (javaObject.getClass().getAnnotation(RdfList.class) != null) {
emitRdfListProxy(subject, predicate, javaObject);
} else if (javaObject instanceof Collection) {
emitCollection(subject, predicate, (Collection>) javaObject);
} else {
Value object = toValue(javaObject);
if (object != null) {
registerNamespace(predicate);
sink.edge(subject, predicate, object);
}
if (canEmbed(object, predicate, javaObject)) {
doEmit((Resource)object, javaObject);
}
}
}
}
}
private void emitRdfListProxy(Resource subject, URI predicate, Object javaObject) {
Collection> collection = null;
if (javaObject instanceof Collection>) {
collection = (Collection>) javaObject;
} else {
Class> type = javaObject.getClass();
Method m = context.listGetterMethod(type);
if (m == null) {
for (Method method : type.getMethods()) {
if (
method.getParameterCount()==0 &&
method.getName().startsWith("get") &&
Collection.class.isAssignableFrom(method.getReturnType())
) {
context.putListGetterMethod(type, method);
try {
collection = (Collection>) method.invoke(javaObject);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new KonigException("Failed to invoke getter for @RdfList class: " + type.getName());
}
}
}
}
if (collection == null) {
throw new KonigException("Getter not found for @RdfList class: " + type.getName());
}
}
emitRdfList(subject, predicate, collection);
}
private void emitCollection(Resource subject, URI predicate, Collection> javaObject) {
boolean registered = false;
for (Object value : javaObject) {
Value object = toValue(value);
if (object != null) {
if (!registered) {
registerNamespace(predicate);
registered = true;
}
sink.edge(subject, predicate, object);
if (canEmbed(object, predicate, value)) {
doEmit((Resource)object, value);
}
}
}
}
private boolean canEmbed(Value object, URI predicate, Object javaObject) {
boolean ok = object instanceof Resource && !context.isIriReference(predicate);
if (ok && javaObject instanceof ConditionalEmbeddable) {
ConditionalEmbeddable e = (ConditionalEmbeddable) javaObject;
ok = e.isEmbeddabled();
}
return ok;
}
private void emitRdfList(Resource subject, URI predicate, Collection> javaCollection) {
if (!javaCollection.isEmpty()) {
Vertex priorList = null;
for (Object value : javaCollection) {
Vertex list = sink.vertex();
Value object = toValue(value);
sink.edge(list.getId(), RDF.FIRST, object);
if (priorList == null) {
registerNamespace(predicate);
sink.edge(subject, predicate, list.getId());
} else {
sink.edge(priorList.getId(), RDF.REST, list.getId());
}
priorList = list;
}
sink.edge(priorList.getId(), RDF.REST, RDF.NIL);
}
}
private Value toValue(Object object) {
Value value = BeanUtil.toValue(object);
if (value != null) {
if (value instanceof URI) {
registerNamespace((URI)value);
}
return value;
}
return getId(object);
}
private Resource getId(Object pojo) {
if (pojo == null) {
return null;
}
Resource result = pojoIdMap.get(pojo);
if (result == null) {
Class> javaClass = pojo.getClass();
try {
Method idMethod = javaClass.getMethod("getId");
Class> returnType = idMethod.getReturnType();
if (Resource.class.isAssignableFrom(returnType)) {
result = (Resource) idMethod.invoke(pojo);
if (result != null) {
if (result instanceof URI) {
URI uri = (URI) result;
registerNamespace(uri);
}
}
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException e) {
throw new KonigException(e);
} catch (NoSuchMethodException e) {
// Ignore
}
}
if (result == null) {
result = valueFactory.createBNode();
}
pojoIdMap.put(pojo, result);
return result;
}
private void registerNamespace(URI uri) {
if (sinkNamespaces != null && sourceNamespaces!=null) {
String namespace = uri.getNamespace();
Namespace ns = sourceNamespaces.findByName(namespace);
if (ns != null) {
sinkNamespaces.add(ns);
}
}
}
}
}