ShaclProperties.java

/*******************************************************************************
 * Copyright (c) 2020 Eclipse RDF4J contributors.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Distribution License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *******************************************************************************/
package org.eclipse.rdf4j.sail.shacl.ast;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Stream;

import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.util.Values;
import org.eclipse.rdf4j.model.vocabulary.SHACL;
import org.eclipse.rdf4j.query.algebra.evaluation.util.ValueComparator;
import org.eclipse.rdf4j.sail.shacl.wrapper.shape.ShapeSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ShaclProperties {

	private static final Logger logger = LoggerFactory.getLogger(ShaclProperties.class);

	private Resource id;
	private IRI type;

	private final List<IRI> clazz = new ArrayList<>();
	private final List<Resource> or = new ArrayList<>();
	private final List<Resource> xone = new ArrayList<>();
	private final List<Resource> and = new ArrayList<>();
	private final List<Resource> not = new ArrayList<>();
	private final List<Resource> node = new ArrayList<>();
	private final List<Resource> property = new ArrayList<>();

	private final List<IRI> equals = new ArrayList<>();
	private final List<IRI> disjoint = new ArrayList<>();
	private final List<IRI> lessThan = new ArrayList<>();
	private final List<IRI> lessThanOrEquals = new ArrayList<>();

	private Long minCount;
	private Long maxCount;

	private IRI datatype;
	private Resource in;
	private final List<Value> hasValue = new ArrayList<>();
	private final List<Resource> hasValueIn = new ArrayList<>();

	private Long minLength;
	private Long maxLength;

	private Resource languageIn;
	private Resource nodeKind;

	private Resource path;

	private Literal minExclusive;
	private Literal maxExclusive;
	private Literal minInclusive;
	private Literal maxInclusive;

	private String pattern;
	private String flags;

	private final Set<Resource> targetClass = new HashSet<>();
	private final TreeSet<Value> targetNode = new TreeSet<>(new ValueComparator());
	private final Set<IRI> targetSubjectsOf = new HashSet<>();
	private final Set<IRI> targetObjectsOf = new HashSet<>();
	private final List<Resource> targetShape = new ArrayList<>();

	private Resource qualifiedValueShape;
	private Long qualifiedMinCount;
	private Long qualifiedMaxCount;
	private Boolean qualifiedValueShapesDisjoint;

	private final List<Resource> target = new ArrayList<>();

	private Boolean deactivated = null;

	private Boolean uniqueLang = null;

	private Boolean closed = null;
	private Resource ignoredProperties;

	private final List<Literal> message = new ArrayList<>();
	private IRI severity;

	private final List<Literal> name = new ArrayList<>();
	private final List<Literal> description = new ArrayList<>();

	private Value defaultValue;
	private Value order;
	private Value group;

	private final List<Resource> sparql = new ArrayList<>();

	public ShaclProperties(Resource id, ShapeSource connection) {
		this.id = id;
		try (Stream<Statement> stream = connection.getAllStatements(id)) {
			stream.forEach(statement -> {

				String predicate = statement.getPredicate().toString();
				Value object = statement.getObject();

				switch (predicate) {
				case "http://www.w3.org/1999/02/22-rdf-syntax-ns#type":
					if (object.equals(SHACL.NODE_SHAPE)) {
						if (type != null && !type.equals(SHACL.NODE_SHAPE)) {
							throw new ShaclShapeParsingException(
									"Shape with multiple types: <" + type + ">, <" + SHACL.NODE_SHAPE + ">", id);
						}
						type = SHACL.NODE_SHAPE;
					} else if (object.equals(SHACL.PROPERTY_SHAPE)) {
						if (type != null && !type.equals(SHACL.PROPERTY_SHAPE)) {
							throw new ShaclShapeParsingException(
									"Shape with multiple types: <" + type + ">, <" + SHACL.PROPERTY_SHAPE
											+ ">",
									id);
						}
						type = SHACL.PROPERTY_SHAPE;
					}
					break;
				case "http://www.w3.org/ns/shacl#or":
					try {
						or.add((Resource) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#xone":
					try {
						xone.add((Resource) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#and":
					try {
						and.add((Resource) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#not":
					try {
						not.add((Resource) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#property":
					try {
						property.add((Resource) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#node":
					try {
						node.add((Resource) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#message":
					try {
						message.add((Literal) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#name":
					try {
						name.add((Literal) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#description":
					try {
						description.add((Literal) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					}
					break;

				case "http://www.w3.org/ns/shacl#severity":
					if (severity != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, severity, object);
					}
					try {
						severity = (IRI) object;
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, IRI.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#defaultValue":
					if (defaultValue != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, defaultValue, object);
					}
					defaultValue = object;
					break;
				case "http://www.w3.org/ns/shacl#group":
					if (group != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, group, object);
					}
					group = object;
					break;
				case "http://www.w3.org/ns/shacl#order":
					if (order != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, order, object);
					}
					order = object;
					break;
				case "http://www.w3.org/ns/shacl#languageIn":
					if (languageIn != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, languageIn, object);
					}
					try {
						languageIn = (Resource) object;
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#nodeKind":
					if (nodeKind != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, nodeKind, object);
					}
					try {
						nodeKind = (Resource) object;
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#datatype":
					if (datatype != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, datatype, object);
					}
					try {
						datatype = (IRI) object;
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, IRI.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#minCount":
					if (minCount != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, minCount, object);
					}
					try {
						minCount = ((Literal) object).longValue();
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					} catch (NumberFormatException e) {
						throw getExceptionForLiteralFormatIssue(id, predicate, object, Long.class);
					}
					break;
				case "http://www.w3.org/ns/shacl#maxCount":
					if (maxCount != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, maxCount, object);
					}
					try {
						maxCount = ((Literal) object).longValue();
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					} catch (NumberFormatException e) {
						throw getExceptionForLiteralFormatIssue(id, predicate, object, Long.class);
					}
					break;
				case "http://www.w3.org/ns/shacl#minLength":
					if (minLength != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, minLength, object);
					}
					try {
						minLength = ((Literal) object).longValue();
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					} catch (NumberFormatException e) {
						throw getExceptionForLiteralFormatIssue(id, predicate, object, Long.class);
					}
					break;
				case "http://www.w3.org/ns/shacl#maxLength":
					if (maxLength != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, maxLength, object);
					}
					try {
						maxLength = ((Literal) object).longValue();
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					} catch (NumberFormatException e) {
						throw getExceptionForLiteralFormatIssue(id, predicate, object, Long.class);
					}
					break;
				case "http://www.w3.org/ns/shacl#minExclusive":
					if (minExclusive != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, minExclusive, object);
					}
					try {
						minExclusive = (Literal) object;
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#maxExclusive":
					if (maxExclusive != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, maxExclusive, object);
					}
					try {
						maxExclusive = (Literal) object;
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#minInclusive":
					if (minInclusive != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, minInclusive, object);
					}
					try {
						minInclusive = (Literal) object;
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#maxInclusive":
					if (maxInclusive != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, maxInclusive, object);
					}
					try {
						maxInclusive = (Literal) object;
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#pattern":
					if (pattern != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, pattern, object);
					}
					try {
						pattern = ((Literal) object).getLabel();
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#class":
					try {
						clazz.add((IRI) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, IRI.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#targetNode":
					if (!object.isLiteral() && !object.isIRI()) {
						throw new ShaclShapeParsingException("Expected predicate <" + predicate
								+ "> to have a Literal or an IRI as object, but found "
								+ getClassName(object) + " for " + object, id);
					}
					targetNode.add(object);
					break;
				case "http://www.w3.org/ns/shacl#targetClass":
					try {
						targetClass.add((Resource) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#targetSubjectsOf":
					try {
						targetSubjectsOf.add((IRI) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, IRI.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#targetObjectsOf":
					try {
						targetObjectsOf.add((IRI) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, IRI.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#deactivated":
					if (deactivated != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, deactivated, object);
					}
					try {
						deactivated = ((Literal) object).booleanValue();
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					} catch (IllegalArgumentException e) {
						throw getExceptionForLiteralFormatIssue(id, predicate, object, Boolean.class);
					}
					break;
				case "http://www.w3.org/ns/shacl#uniqueLang":
					if (uniqueLang != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, uniqueLang, object);
					}
					try {
						uniqueLang = ((Literal) object).booleanValue();
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					} catch (IllegalArgumentException e) {
						throw getExceptionForLiteralFormatIssue(id, predicate, object, Boolean.class);
					}
					break;
				case "http://www.w3.org/ns/shacl#closed":
					if (closed != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, closed, object);
					}
					try {
						closed = ((Literal) object).booleanValue();
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					} catch (IllegalArgumentException e) {
						throw getExceptionForLiteralFormatIssue(id, predicate, object, Boolean.class);
					}
					break;
				case "http://www.w3.org/ns/shacl#ignoredProperties":
					if (ignoredProperties != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, ignoredProperties, object);
					}
					try {
						ignoredProperties = ((Resource) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#flags":
					if (flags != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, flags, object);
					}
					try {
						flags = ((Literal) object).getLabel();
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#path":
					if (path != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, path, object);
					}
					if (type == null) {
						type = SHACL.PROPERTY_SHAPE;
					} else if (!type.equals(SHACL.PROPERTY_SHAPE)) {
						throw new IllegalStateException("Shape " + id
								+ " has sh:path and must be of type sh:PropertyShape but is type " + type);
					}
					try {
						path = (Resource) object;
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#in":
					if (in != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, in, object);
					}
					try {
						in = (Resource) object;
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#equals":
					try {
						equals.add((IRI) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, IRI.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#disjoint":
					try {
						disjoint.add((IRI) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, IRI.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#lessThan":
					try {
						lessThan.add((IRI) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, IRI.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#lessThanOrEquals":
					try {
						lessThanOrEquals.add((IRI) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, IRI.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#target":
					try {
						target.add((Resource) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#hasValue":
					hasValue.add(object);
					break;
				case "http://www.w3.org/ns/shacl#qualifiedValueShape":
					if (qualifiedValueShape != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, qualifiedValueShape, object);
					}
					try {
						qualifiedValueShape = ((Resource) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#qualifiedValueShapesDisjoint":
					if (qualifiedValueShapesDisjoint != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, qualifiedValueShapesDisjoint, object);
					}
					try {
						qualifiedValueShapesDisjoint = ((Literal) object).booleanValue();
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					} catch (IllegalArgumentException e) {
						throw getExceptionForLiteralFormatIssue(id, predicate, object, Boolean.class);
					}
					break;
				case "http://www.w3.org/ns/shacl#qualifiedMinCount":
					if (qualifiedMinCount != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, qualifiedMinCount, object);
					}
					try {
						qualifiedMinCount = ((Literal) object).longValue();
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					} catch (NumberFormatException e) {
						throw getExceptionForLiteralFormatIssue(id, predicate, object, Long.class);
					}
					break;
				case "http://www.w3.org/ns/shacl#qualifiedMaxCount":
					if (qualifiedMaxCount != null) {
						throw getExceptionForAlreadyPopulated(id, predicate, qualifiedMaxCount, object);
					}
					try {
						qualifiedMaxCount = ((Literal) object).longValue();
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Literal.class, object);
					} catch (NumberFormatException e) {
						throw getExceptionForLiteralFormatIssue(id, predicate, object, Long.class);
					}
					break;
				case "http://datashapes.org/dash#hasValueIn":
					try {
						hasValueIn.add((Resource) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://rdf4j.org/shacl-extensions#targetShape":
					try {
						targetShape.add((Resource) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;
				case "http://www.w3.org/ns/shacl#sparql":
					try {
						sparql.add((Resource) object);
					} catch (ClassCastException e) {
						throw getExceptionForCastIssue(id, predicate, Resource.class, object);
					}
					break;

				default:
					if (predicate.startsWith(SHACL.NAMESPACE)) {
						logger.warn("Unsupported SHACL feature detected {} in statement {}",
								predicate.replace("http://www.w3.org/ns/shacl#", "sh:"),
								statement);
					}
				}

			});
		}

		// We default to sh:NodeShape if no other type is given.
		if (type == null) {
			type = path == null ? SHACL.NODE_SHAPE : SHACL.PROPERTY_SHAPE;
		}

	}

	private static ShaclShapeParsingException getExceptionForLiteralFormatIssue(Resource id, String predicate,
			Value object, Class<?> clazz) {
		return new ShaclShapeParsingException("Expected predicate <" + predicate + "> to have a "
				+ clazz.getSimpleName() + " as object but found " + object, id);
	}

	private static ShaclShapeParsingException getExceptionForAlreadyPopulated(Resource id, String predicate,
			Object existingObject, Value secondValue) {
		Value existingValue;

		if (existingObject instanceof Value) {
			existingValue = (Value) existingObject;
		} else if (existingObject instanceof String) {
			existingValue = Values.literal(existingObject);
		} else if (existingObject instanceof Boolean) {
			existingValue = Values.literal(existingObject);
		} else {
			return new ShaclShapeParsingException("Expected predicate <" + predicate
					+ "> to have no more than 1 object, found " + existingObject + " and " + secondValue, id);
		}

		return new ShaclShapeParsingException("Expected predicate <" + predicate
				+ "> to have no more than 1 object, found " + existingValue + " and " + secondValue, id);
	}

	private static ShaclShapeParsingException getExceptionForCastIssue(Resource id, String predicate,
			Class<?> expectedClass, Value object) {
		String expectedClassString;
		if (expectedClass == IRI.class) {
			expectedClassString = "an IRI";
		} else {
			expectedClassString = "a " + expectedClass.getSimpleName();
		}

		return new ShaclShapeParsingException("Expected predicate <" + predicate + "> to have " + expectedClassString
				+ " as object, but found " + getClassName(object) + " for " + object, id);
	}

	private static String getClassName(Value object) {
		if (object == null) {
			return "null";
		}
		String actualClassName;
		if (object.isIRI()) {
			actualClassName = "IRI";
		} else if (object.isLiteral()) {
			actualClassName = "Literal";
		} else if (object.isBNode()) {
			actualClassName = "BNode";
		} else if (object.isTriple()) {
			actualClassName = "Triple";
		} else {
			assert false;
			actualClassName = object.getClass().getSimpleName();
		}
		return actualClassName;
	}

	public List<IRI> getClazz() {
		return clazz;
	}

	public List<Resource> getOr() {
		return or;
	}

	public List<Resource> getAnd() {
		return and;
	}

	public List<Resource> getNot() {
		return not;
	}

	public Long getMinCount() {
		return minCount;
	}

	public Long getMaxCount() {
		return maxCount;
	}

	public IRI getDatatype() {
		return datatype;
	}

	public Resource getIn() {
		return in;
	}

	public Long getMinLength() {
		return minLength;
	}

	public Long getMaxLength() {
		return maxLength;
	}

	public Resource getLanguageIn() {
		return languageIn;
	}

	public Resource getNodeKind() {
		return nodeKind;
	}

	public Resource getPath() {
		return path;
	}

	public Literal getMinExclusive() {
		return minExclusive;
	}

	public Literal getMaxExclusive() {
		return maxExclusive;
	}

	public Literal getMinInclusive() {
		return minInclusive;
	}

	public Literal getMaxInclusive() {
		return maxInclusive;
	}

	public String getPattern() {
		return pattern;
	}

	public String getFlags() {
		return flags;
	}

	public Set<Resource> getTargetClass() {
		return targetClass;
	}

	public TreeSet<Value> getTargetNode() {
		return targetNode;
	}

	public Set<IRI> getTargetSubjectsOf() {
		return targetSubjectsOf;
	}

	public Set<IRI> getTargetObjectsOf() {
		return targetObjectsOf;
	}

	public boolean isDeactivated() {
		return deactivated != null && deactivated;
	}

	public boolean isUniqueLang() {
		return uniqueLang != null && uniqueLang;
	}

	public Resource getId() {
		return id;
	}

	public IRI getType() {
		return type;
	}

	public List<Literal> getMessage() {
		return message;
	}

	public IRI getSeverity() {
		return severity;
	}

	public List<Literal> getName() {
		return name;
	}

	public List<Literal> getDescription() {
		return description;
	}

	public Value getDefaultValue() {
		return defaultValue;
	}

	public Value getOrder() {
		return order;
	}

	public Value getGroup() {
		return group;
	}

	public List<Resource> getProperty() {
		return property;
	}

	public List<Resource> getNode() {
		return node;
	}

	public boolean isClosed() {
		return closed != null && closed;
	}

	public Resource getIgnoredProperties() {
		return ignoredProperties;
	}

	public List<Resource> getXone() {
		return xone;
	}

	public List<Value> getHasValue() {
		return hasValue;
	}

	public List<IRI> getEquals() {
		return equals;
	}

	public List<IRI> getDisjoint() {
		return disjoint;
	}

	public List<IRI> getLessThan() {
		return lessThan;
	}

	public List<IRI> getLessThanOrEquals() {
		return lessThanOrEquals;
	}

	public List<Resource> getTarget() {
		return target;
	}

	public List<Resource> getTargetShape() {
		return targetShape;
	}

	public List<Resource> getHasValueIn() {
		return hasValueIn;
	}

	public Resource getQualifiedValueShape() {
		return qualifiedValueShape;
	}

	public Long getQualifiedMinCount() {
		return qualifiedMinCount;
	}

	public Long getQualifiedMaxCount() {
		return qualifiedMaxCount;
	}

	public boolean getQualifiedValueShapesDisjoint() {
		return qualifiedValueShapesDisjoint != null && qualifiedValueShapesDisjoint;
	}

	public List<Resource> getSparql() {
		return sparql;
	}
}