use of org.apache.jena.shacl.parser.PropertyShape in project webofneeds by researchstudio-sat.
the class MainTypesPostprocessor method configureTypeWithNodeShapes.
private void configureTypeWithNodeShapes(TypeSpec.Builder typeBuilder, String name, Set<Shape> relevantShapes, Shapes shapes, Shacl2JavaConfig config) {
// first,prepare a methodbuilder for the toRdf method
// we will add statements to it while processing the relevant shapes
MethodSpec.Builder toRdfBuilderDelegating = MethodSpec.methodBuilder("toRdf").addModifiers(PUBLIC).addAnnotation(Override.class).addParameter(ParameterizedTypeName.get(Consumer.class, Triple.class), "tripleConsumer").addStatement("toRdf(tripleConsumer, true)");
typeBuilder.addMethod(toRdfBuilderDelegating.build());
MethodSpec.Builder toRdfBuilder = MethodSpec.methodBuilder("toRdf").addModifiers(PUBLIC).addParameter(ParameterizedTypeName.get(Consumer.class, Triple.class), "tripleConsumer").addParameter(ClassName.BOOLEAN, "includeIndividuals").addStatement("$T obj = null", Node.class).addStatement("$T entityNode = getNodeCreateIfNecessary()", Node.class).beginControlFlow("if (getGraph() == null)").addStatement("additionalTriplesToRdf(tripleConsumer)");
generateRequiredRdfTypeStatements(toRdfBuilder, relevantShapes);
// we want each type to have a .builder() method returning a builder for the
// type
TypeName typeName = ClassName.get(config.getPackageName(), name);
ClassName builderTypeName = ClassName.get(config.getPackageName(), name + ".Builder");
TypeSpec.Builder builderBuilder = generateBuilderBuilder(typeBuilder, typeName, builderTypeName);
// for the clone() method, we prepare another builder
// we will add statements to it while processing the relevant shapes
MethodSpec.Builder cloneBuilder = MethodSpec.methodBuilder("clone").addModifiers(PUBLIC).returns(ClassName.OBJECT).addAnnotation(Override.class).addStatement("$T clone = ($T) super.clone()", typeName, typeName);
for (Shape relevantShape : relevantShapes) {
Set<PropertyShape> propertyShapes = new HashSet();
propertyShapes.addAll(relevantShape.getPropertyShapes());
propertyShapes.addAll(ShapeUtils.getShPropertyShapes(relevantShape));
// remember all fields we generate for the same path for this type, so we can
// add a common interface
// and a getter for the union of all these fields:
Map<Path, Set<FieldSpec>> fieldsPerPath = new HashMap<>();
Map<Path, Set<PropertySpec>> propSpecsPerPath = propertyShapes.stream().collect(Collectors.toMap(s -> s.getPath(), s -> (Set<PropertySpec>) ShapeUtils.getPropertySpecs(s), (left, right) -> {
Set union = new HashSet(left);
union.addAll(right);
return union;
}));
for (Path path : propSpecsPerPath.keySet()) {
Optional<String> propertyName = NameUtils.propertyNameForPath(path);
if (!propertyName.isPresent()) {
continue;
}
logger.debug("generating property '{}' of {}", propertyName.get(), NameUtils.nameForShape(relevantShape));
Set<PropertySpec> propertySpecs = propSpecsPerPath.get(path);
if (logger.isDebugEnabled()) {
for (PropertySpec propertySpec : propertySpecs) {
logger.debug("\tfound property spec: {}", propertySpec);
}
}
boolean addTypeSuffix = propertySpecs.size() > 1;
for (PropertySpec propertySpec : propertySpecs) {
addFieldWithPropertySpec(shapes, propertyName.get(), path, propertySpec, typeBuilder, builderBuilder, builderTypeName, toRdfBuilder, cloneBuilder, fieldsPerPath, config, addTypeSuffix);
}
}
// add union getter
fieldsPerPath.entrySet().stream().forEach(pathToFields -> {
Set<FieldSpec> fieldSpecs = pathToFields.getValue();
if (fieldSpecs.size() < 2) {
return;
}
Path path = pathToFields.getKey();
Optional<String> fieldName = propertyNameForPath(path);
if (fieldName.isPresent()) {
addUnionGetter(fieldName.get(), path, typeBuilder, fieldSpecs, config);
}
});
}
//
relevantShapes.stream().flatMap(s -> checkShapeForIndividuals(s).stream()).collect(Collectors.toMap(s -> new Object[] { s.getPredicate(), s.getClassName() }, s -> s, (left, right) -> IndividualPropertySpec.merge(left, right))).values().stream().forEach(spec -> addFieldWithIndividualPropertySpec(spec, typeBuilder, toRdfBuilder, cloneBuilder, config));
// finish toRdf method
toRdfBuilder.nextControlFlow("else").addStatement("super.toRdf(tripleConsumer)").endControlFlow();
// finish clone method
cloneBuilder.addStatement("return clone");
typeBuilder.addType(builderBuilder.build());
typeBuilder.addMethod(toRdfBuilder.build());
typeBuilder.addMethod(cloneBuilder.build());
}
use of org.apache.jena.shacl.parser.PropertyShape in project jena by apache.
the class VLib method validateShape.
public static void validateShape(ValidationContext vCxt, Graph data, Shape shape, Node focusNode) {
if (shape.deactivated())
return;
if (vCxt.isVerbose())
out.println("S: " + shape);
Path path;
Set<Node> vNodes;
if (shape instanceof NodeShape) {
path = null;
vNodes = null;
} else if (shape instanceof PropertyShape) {
PropertyShape propertyShape = (PropertyShape) shape;
path = propertyShape.getPath();
vNodes = ShaclPaths.valueNodes(data, focusNode, propertyShape.getPath());
} else {
if (vCxt.isVerbose())
out.println("Z: " + shape);
return;
}
// Constraints of this shape.
for (Constraint c : shape.getConstraints()) {
if (vCxt.isVerbose())
out.println("C: " + c);
evalConstraint(vCxt, data, shape, focusNode, path, vNodes, c);
}
// Reachable shapes.
// Follow sh:property (sh:node behaves as a constraint).
validationPropertyShapes(vCxt, data, shape.getPropertyShapes(), focusNode);
if (vCxt.isVerbose())
out.println();
}
use of org.apache.jena.shacl.parser.PropertyShape in project webofneeds by researchstudio-sat.
the class Shacl2JavaInstanceFactory method instantiate.
/**
* Creates all instances for the given node / shape combination.
*
* @param node may be null, in which case all target nodes of the shape are
* chosen.
* @param shape
* @return the set of nodes reached during instantiation that have not been
* instantiated yet
*/
private Set<DataNodeAndShapes> instantiate(Node node, Shape shape, boolean forceApplyShape, InstantiationContext ctx) {
if (shape.getShapeNode().isBlank()) {
if (node == null) {
if (logger.isDebugEnabled()) {
logger.debug("Not instantiating entity for shape {}", shape.getShapeNode().getBlankNodeLabel());
}
} else {
throw new IllegalArgumentException(String.format("Cannot instantiate entity for node %s: shape %s is a blank node", node.getLocalName(), shape.getShapeNode().getBlankNodeLabel()));
}
}
Collection<Node> focusNodes;
if (node != null) {
if (!forceApplyShape) {
if (!isFocusNode(shape, node, ctx.getData())) {
return Collections.emptySet();
}
}
if (ctx.hasInstanceForFocusNode(node) && !ctx.isNewShapeForFocusNode(node, shape)) {
return Collections.emptySet();
}
if (logger.isDebugEnabled()) {
logger.debug("processing node {} with shape {}", node, shape);
}
focusNodes = Collections.singleton(node);
} else {
focusNodes = focusNodes(ctx.getData(), shape);
}
if (focusNodes.isEmpty()) {
return Collections.emptySet();
}
final Set<Node> finalFocusNodes = removeNodesInstantiatedInBaseContext(focusNodes).stream().filter(fnode -> {
// check if focusnode conforms to shape
ValidationContext vCtx = ctx.newValidationContext();
VLib.validateShape(vCtx, ctx.getData(), shape, fnode);
if (vCtx.hasViolation()) {
if (logger.isDebugEnabled()) {
logger.debug("skipping node {} as it does not conform to shape {}", fnode, shape.getShapeNode());
}
return false;
} else {
if (logger.isDebugEnabled()) {
logger.debug("accepting node {} as it conforms to shape {}", fnode, shape.getShapeNode());
}
}
return true;
}).collect(Collectors.toSet());
String shapeURI = shape.getShapeNode().getURI();
Set<Class<?>> classesForShape = ctx.getClassesForShape(shapeURI);
if (classesForShape == null) {
if (logger.isDebugEnabled()) {
logger.debug("No class found to instantiate for shape {}.", shape.getShapeNode().getLocalName());
logger.debug("Instantiation context:");
logger.debug(ctx.getFormattedState());
}
throw new IllegalArgumentException(String.format("No class found to instantiate for shape %s, more information is logged on loglevel debug", shape.getShapeNode().getLocalName()));
}
Set ret = classesForShape.stream().map(classForShape -> {
// our shape might reference other shapes via sh:node (maybe through other
// operators such as sh:or)
// * we remember them for wiring
// * we return them as dependencies to instantiate
Set<Shape> allRelevantShapes = ShapeUtils.getNodeShapes((NodeShape) shape, shapes);
Map<Path, Set<PropertyShape>> propertyShapesPerPath = getPropertyShapesByPath(allRelevantShapes);
allRelevantShapes.add(shape);
return finalFocusNodes.parallelStream().map(focusNode -> {
try {
Object instance = null;
if (logger.isDebugEnabled()) {
logger.debug("attempting to instantiate focus node {} with shape {}", focusNode, shape.getShapeNode());
}
instance = instantiate(shape, shapeURI, focusNode, classForShape, ctx);
if (instance == null) {
// maybe another shape works better
return Collections.emptySet();
}
ctx.addInstanceForFocusNode(focusNode, instance);
ctx.setFocusNodeForInstance(instance, focusNode);
ctx.setClassForInstance(instance, classForShape);
ctx.addShapesForFocusNode(focusNode, allRelevantShapes);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(String.format("Cannot instantiate %s for shape %s", classForShape.getName(), shape.getShapeNode().getLocalName()) + ": no parameterless constructor found", e);
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
throw new IllegalArgumentException(String.format("Cannot instantiate %s for shape %s - %s: %s", classForShape.getName(), shape.getShapeNode().getLocalName(), e.getClass().getSimpleName(), e.getMessage()), e);
}
if (logger.isDebugEnabled()) {
logger.debug("Collecting dependencies of focus node {}", focusNode);
}
return propertyShapesPerPath.entrySet().parallelStream().map(pathToShapes -> {
Path path = pathToShapes.getKey();
Set<PropertyShape> propertyShapes = pathToShapes.getValue();
if (logger.isDebugEnabled()) {
logger.debug("\tcollecting new focus nodes via path {} ", path);
}
Set<Node> valueNodes = ShaclPaths.valueNodes(ctx.getData(), focusNode, path);
if (valueNodes.isEmpty()) {
return Collections.emptySet();
}
return valueNodes.stream().map(valueNode -> propertyShapes.stream().map(ctx::getNodeShapesForPropertyShape).map(nodeShapeNodes -> new DataNodeAndShapes(valueNode, nodeShapeNodes)).collect(Collectors.toSet())).reduce(CollectionUtils::union).orElse(Collections.emptySet());
}).reduce(CollectionUtils::union).orElse(Collections.emptySet());
}).reduce(CollectionUtils::union).orElse(Collections.emptySet());
}).reduce(CollectionUtils::union).orElse(Collections.emptySet());
return ret;
}
use of org.apache.jena.shacl.parser.PropertyShape in project webofneeds by researchstudio-sat.
the class Shacl2JavaInstanceFactory method wireDependencies.
private void wireDependencies(Object instance, InstantiationContext ctx) {
Map<Path, Set<Field>> fieldsByPath = new HashMap<>();
Class<?> type = instance.getClass();
Field[] instanceFields = type.getDeclaredFields();
for (Field field : instanceFields) {
extractPath(fieldsByPath, field);
wireIndividuals(instance, field, ctx);
}
Node focusNode = ctx.getFocusNodeForInstance(instance);
if (focusNode == null) {
if (logger.isDebugEnabled()) {
logger.debug("No focus node found for instance {}", instance);
}
return;
}
Set<Shape> shapesForFocusNode = ctx.getShapesForFocusNode(focusNode);
if (shapesForFocusNode == null) {
if (logger.isDebugEnabled()) {
logger.debug("No shapes found for focus node {}", focusNode);
}
return;
}
Set<Path> pathsFromPropertyShapes = ctx.getShapesForFocusNode(focusNode).stream().flatMap(s -> s.getPropertyShapes().stream()).map(PropertyShape::getPath).collect(Collectors.toSet());
pathsFromPropertyShapes.parallelStream().forEach(path -> {
Set<Node> valueNodes = ShaclPaths.valueNodes(ctx.getData(), focusNode, path);
Set<Field> fieldsForPath = fieldsByPath.get(path);
if (fieldsForPath != null && !fieldsForPath.isEmpty()) {
if (valueNodes.size() > 0) {
for (Node valueNode : valueNodes) {
Set<Object> dependencyCandidates = ctx.getInstancesForFocusNode(valueNode);
if (dependencyCandidates == null) {
dependencyCandidates = new HashSet<>();
}
// covered by a shape
if (valueNode.isLiteral()) {
dependencyCandidates.add(valueNode.getLiteralDatatype().parse(valueNode.getLiteralLexicalForm()));
} else if (valueNode.isURI()) {
dependencyCandidates.add(URI.create(valueNode.getURI()));
}
Field field = null;
try {
SatisfiedFieldDependency fieldDependency = selectFieldByType(fieldsForPath, instance, dependencyCandidates);
if (fieldDependency == null) {
throw new IllegalArgumentException(makeWiringErrorMessage(instance, focusNode, dependencyCandidates, null, null) + ": unable to identify appropriate field to set");
}
field = fieldDependency.getField();
Object dependency = fieldDependency.getDependency();
setDependency(instance, field.getName(), dependency);
if (logger.isDebugEnabled()) {
logger.debug("wired {} ", makeWiringMessage(instance, focusNode, dependency, field));
}
} catch (Throwable e) {
throw new IllegalArgumentException(makeWiringErrorMessage(instance, focusNode, dependencyCandidates, field, e), e);
}
}
}
}
});
}
Aggregations