1 package org.simantics.db.layer0.validation;
\r
3 import java.util.Collection;
\r
4 import java.util.HashSet;
\r
5 import java.util.List;
\r
6 import java.util.Set;
\r
8 import org.simantics.db.ChangeSet;
\r
9 import org.simantics.db.ChangeSet.StatementChange;
\r
10 import org.simantics.db.Issue;
\r
11 import org.simantics.db.ReadGraph;
\r
12 import org.simantics.db.Resource;
\r
13 import org.simantics.db.common.utils.Functions;
\r
14 import org.simantics.db.common.utils.Logger;
\r
15 import org.simantics.db.common.utils.NameUtils;
\r
16 import org.simantics.db.event.ChangeEvent;
\r
17 import org.simantics.db.event.ChangeListener;
\r
18 import org.simantics.db.exception.DatabaseException;
\r
19 import org.simantics.layer0.Layer0;
\r
21 public class ChangeSetValidator implements ChangeListener {
\r
23 void reportInconsistency(ReadGraph graph, Resource subject, String description) throws DatabaseException {
\r
24 System.err.println("Change set validation reports the following issue: " + NameUtils.getSafeName(graph, subject, true) + ": " + description);
\r
28 public void graphChanged(ChangeEvent e) throws DatabaseException {
\r
29 ChangeSet changeSet = e.getChanges();
\r
30 ReadGraph g = e.getGraph();
\r
31 // Layer0 l0 = Layer0.getInstance(g);
\r
33 HashSet<Resource> allResources = new HashSet<Resource>();
\r
35 for(StatementChange change : changeSet.changedStatements()) {
\r
36 allResources.add(change.getSubject());
\r
37 allResources.add(change.getObject());
\r
38 // if(change.isClaim()) {
\r
39 // Resource subject = change.getSubject();
\r
40 // Resource predicate = change.getPredicate();
\r
41 // Resource object = change.getObject();
\r
42 // if(predicate == l0.InstanceOf) {
\r
43 // if(!isType(g, l0, object)) {
\r
44 // reportInconsistency(g, subject, "The range of InstanceOf relation is Type.");
\r
50 // else if(predicate == l0.SubrelationOf) {
\r
51 // if(!isRelation(g, l0, object)) {
\r
52 // reportInconsistency(g, subject, "The range of SubrelationOf relation is Relation.");
\r
55 // else if(predicate == l0.Inherits) {
\r
56 // if(!isType(g, l0, object)) {
\r
57 // reportInconsistency(g, subject, "The range of Inherits relation is Type.");
\r
61 // if(!isRelation(g, l0, predicate)) {
\r
62 // reportInconsistency(g, subject, "The predicate of a statement must be a relation.");
\r
65 // if(g.isInstanceOf(predicate, l0.FunctionalRelation)) {
\r
66 // if(g.getObjects(subject, predicate).size() > 1)
\r
67 // reportInconsistency(g, subject,
\r
69 // NameUtils.getSafeName(g, predicate)
\r
70 // + " is functional.");
\r
72 // if(g.isSubrelationOf(predicate, l0.HasProperty)) {
\r
73 // String error = L0Validations.checkValueType(g, subject, predicate);
\r
74 // if(error != null) reportInconsistency(g, subject, error);
\r
77 // Collection<Resource> domain = g.getObjects(predicate, l0.HasDomain);
\r
78 // if (!isInstanceOfAny(g, subject, domain, true)) {
\r
79 // StringBuilder sb = new StringBuilder()
\r
80 // .append("The domain of ")
\r
81 // .append(NameUtils.getSafeName(g, predicate))
\r
82 // .append(" relation is ");
\r
83 // orString(g, sb, domain).append(".");
\r
84 // reportInconsistency(g, subject, sb.toString());
\r
88 // Collection<Resource> range = g.getObjects(predicate, l0.HasRange);
\r
89 // if (!isInstanceOfAny(g, object, range, true)) {
\r
90 // StringBuilder sb = new StringBuilder()
\r
91 // .append("The range of ")
\r
92 // .append(NameUtils.getSafeName(g, predicate))
\r
93 // .append(" relation is ");
\r
94 // orString(g, sb, range).append(".");
\r
95 // reportInconsistency(g, object, sb.toString());
\r
106 for(Resource resource : changeSet.changedValues()) {
\r
107 allResources.add(resource);
\r
108 // if(g.hasValue(resource)) {
\r
109 // if(!g.isInstanceOf(resource, l0.Literal)) {
\r
110 // reportInconsistency(g, resource,
\r
111 // "Resource has a value but it is not a literal.");
\r
114 // // TODO check that the value is valid for the data type
\r
118 // if(g.isInstanceOf(resource, l0.Literal)) {
\r
119 // reportInconsistency(g, resource,
\r
120 // "Resource is a literal but it does not have a value.");
\r
125 Layer0 L0 = Layer0.getInstance(g);
\r
127 for(Resource r : allResources) {
\r
131 for(Resource constraint : g.sync(new GetConstraints(r))) {
\r
135 Resource function = g.getSingleObject(constraint, L0.Constraint_Validator);
\r
136 @SuppressWarnings("unchecked")
\r
137 Set<Issue> contexts = new HashSet<Issue>((List<Issue>)Functions.exec(g, function, g, r));
\r
138 for(Issue i : contexts) {
\r
139 reportInconsistency(g, r, g.getURI(i.getType()));
\r
142 } catch (Throwable t) {
\r
143 Logger.defaultLogError(t);
\r
148 } catch (Throwable t) {
\r
149 Logger.defaultLogError(t);
\r
156 private boolean isInstanceOfAny(ReadGraph graph, Resource r, Collection<Resource> types, boolean ifEmpty) throws DatabaseException {
\r
157 if (types.isEmpty())
\r
159 for (Resource type : types) {
\r
160 if (graph.isInstanceOf(r, type)) {
\r
167 private StringBuilder orString(ReadGraph graph, StringBuilder sb, Collection<Resource> rs) throws DatabaseException {
\r
169 boolean first = true;
\r
170 for (Resource r : rs) {
\r
174 sb.append(NameUtils.getSafeName(graph, r));
\r
180 public static boolean isRelation(ReadGraph g, Layer0 l0, Resource relation) throws DatabaseException {
\r
181 return g.hasStatement(relation, l0.SubrelationOf) || relation == l0.IsWeaklyRelatedTo;
\r
184 public static boolean isType(ReadGraph g, Layer0 l0, Resource type) throws DatabaseException {
\r
185 return g.hasStatement(type, l0.Inherits) || type == l0.Entity;
\r