1 /*******************************************************************************
2 * Copyright (c) 2007, 2018 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.ui.workbench.editor.input;
14 import java.util.Arrays;
16 import org.simantics.db.ReadGraph;
17 import org.simantics.db.Resource;
18 import org.simantics.db.common.request.ParametrizedRead;
19 import org.simantics.db.common.request.Queries;
20 import org.simantics.db.common.request.UnaryRead;
21 import org.simantics.db.exception.DatabaseException;
22 import org.simantics.db.layer0.request.combinations.Combinators;
23 import org.simantics.db.request.Read;
24 import org.simantics.ui.workbench.IResourceEditorInput;
27 * Composable database read operations designed to be used for defining
28 * validation strategies for resource editor inputs through composition.
31 * For example one validation criterion might be that the editor input or one of
32 * its neighboring resources must have a proper URI.
34 * @author Tuukka Lehtonen
36 public final class InputValidationCombinators {
41 * = subject -> exists(URI(subject))
45 public static ParametrizedRead<Resource, Boolean> hasURI() {
52 * = input -> resource(input)
56 public static ParametrizedRead<IResourceEditorInput, Resource> extractInputResource() {
57 return EXTRACT_INPUT_RESOURCE;
63 * = subject -> singleObject(subject, resource(relationURI))
67 public static ParametrizedRead<Resource,Resource> completeFunction(String relationURI) {
68 return new CompleteFunctionURI(relationURI);
74 * = subject -> possibleObject(subject, resource(relationURI))
78 public static ParametrizedRead<Resource,Resource> partialFunction(String relationURI) {
79 return new PartialFunctionURI(relationURI);
85 * = subject -> true if any of conditions is true for subject, false otherwise
89 @SuppressWarnings("unchecked")
90 public static ParametrizedRead<Resource, Boolean> or(ParametrizedRead<Resource, Boolean> c1,
91 ParametrizedRead<Resource, Boolean> c2) {
92 return new FunctionOr(new ParametrizedRead[] { c1, c2 });
95 // ------------------------------------------------------------------------
97 private static class Or extends UnaryRead<Resource, Boolean> {
98 ParametrizedRead<Resource, Boolean>[] reads;
99 public Or(Resource resource, ParametrizedRead<Resource, Boolean>... reads) {
104 public Boolean perform(ReadGraph graph) throws DatabaseException {
105 for (ParametrizedRead<Resource, Boolean> r : reads) {
106 Read<Boolean> read = r.get(parameter);
107 Boolean value = graph.syncRequest( read );
111 return Boolean.FALSE;
114 public int hashCode() {
115 return super.hashCode() * 31 + Arrays.hashCode(reads);
118 public boolean equals(Object object) {
119 if (this == object) return true;
120 else if (object == null || getClass() != object.getClass()) return false;
121 Or other = (Or) object;
122 return super.equals(object) && Arrays.equals(reads, other.reads);
126 // ------------------------------------------------------------------------
128 private static class FunctionOr implements ParametrizedRead<Resource, Boolean> {
129 ParametrizedRead<Resource, Boolean>[] reads;
130 public FunctionOr(ParametrizedRead<Resource, Boolean>... reads) {
134 public Read<Boolean> get(Resource subject) {
135 if (subject == null || reads.length == 0)
136 return Combinators.constant(Boolean.TRUE);
137 return new Or(subject, reads);
140 public int hashCode() {
141 return getClass().hashCode() + 31 * Arrays.hashCode(reads);
144 public boolean equals(Object obj) {
145 if(obj == this) return true;
146 if(obj == null || obj.getClass() != getClass()) return false;
147 FunctionOr other = (FunctionOr)obj;
148 return Arrays.equals(reads, other.reads);
152 // ------------------------------------------------------------------------
154 private static class HasURI extends UnaryRead<Resource, Boolean> {
155 public HasURI(Resource resource) {
159 public Boolean perform(ReadGraph graph) throws DatabaseException {
160 if (parameter == null)
161 return Boolean.FALSE;
163 String uri = graph.syncRequest(Queries.possibleUri(parameter));
164 //System.out.println("uri(" + parameter + "): " + uri);
166 return Boolean.FALSE;
168 // FIXME: URI request will return invalid URIs, like
169 // null/Configuration/MyComposite after deleting the parenting model
170 // For this reason we try to reverse lookup the URI back into a
171 // resource which must be equal to the original parameter resource.
173 Resource reverseLookup = graph.getPossibleResource(uri);
174 //System.out.println("resource(" + uri + "): " + reverseLookup);
175 return parameter.equals(reverseLookup);
179 public static Read<Boolean> hasURI(Resource resource) {
180 return new HasURI(resource);
183 // ------------------------------------------------------------------------
185 private static class ExtractResource extends UnaryRead<IResourceEditorInput, Resource> {
186 public ExtractResource(IResourceEditorInput input) {
190 public Resource perform(ReadGraph graph) throws DatabaseException {
191 return parameter != null ? parameter.getResource() : null;
195 public static Read<Resource> extractResource(IResourceEditorInput input) {
196 return new ExtractResource(input);
199 // ------------------------------------------------------------------------
201 private static class PossibleObjectURI implements Read<Resource> {
204 public PossibleObjectURI(Resource subject, String relationURI) {
205 this.subject = subject;
206 this.relationURI = relationURI;
209 public Resource perform(ReadGraph graph) throws DatabaseException {
210 Resource relation = graph.getResource(relationURI);
211 return graph.getPossibleObject(subject, relation);
214 public int hashCode() {
215 return subject.hashCode() + 31 * relationURI.hashCode();
218 public boolean equals(Object object) {
219 if (this == object) return true;
220 else if (object == null || getClass() != object.getClass()) return false;
221 PossibleObjectURI other = (PossibleObjectURI)object;
222 return subject.equals(other.subject) && relationURI.equals(other.relationURI);
227 * Returns a read request that reads an object possibly connected to the subject by the relation.
229 public static Read<Resource> possibleObject(Resource subject, String relationURI) {
230 return new PossibleObjectURI(subject, relationURI);
233 // ------------------------------------------------------------------------
235 private static class PartialFunctionURI implements ParametrizedRead<Resource, Resource> {
237 public PartialFunctionURI(String relationURI) {
238 this.relationURI = relationURI;
241 public Read<Resource> get(Resource subject) {
243 return Combinators.constant(null);
244 return possibleObject(subject, relationURI);
247 public int hashCode() {
248 return getClass().hashCode() + 31 * relationURI.hashCode();
251 public boolean equals(Object obj) {
252 if(obj == this) return true;
253 if(obj == null || obj.getClass() != getClass()) return false;
254 PartialFunctionURI other = (PartialFunctionURI)obj;
255 return relationURI.equals(other.relationURI);
259 // ------------------------------------------------------------------------
261 private static class SingleObjectURI implements Read<Resource> {
264 public SingleObjectURI(Resource subject, String relationURI) {
265 this.subject = subject;
266 this.relationURI = relationURI;
269 public Resource perform(ReadGraph graph) throws DatabaseException {
270 Resource relation = graph.getResource(relationURI);
271 return graph.getSingleObject(subject, relation);
274 public int hashCode() {
275 return subject.hashCode() + 31 * relationURI.hashCode();
278 public boolean equals(Object object) {
279 if (this == object) return true;
280 else if (object == null || getClass() != object.getClass()) return false;
281 SingleObjectURI other = (SingleObjectURI) object;
282 return subject.equals(other.subject) && relationURI.equals(other.relationURI);
287 * Returns a read request that reads a single object connected to the
288 * subject by the relation.
290 public static Read<Resource> singleObject(Resource subject, String relationURI) {
291 return new SingleObjectURI(subject, relationURI);
294 // ------------------------------------------------------------------------
296 private static class CompleteFunctionURI implements ParametrizedRead<Resource, Resource> {
298 public CompleteFunctionURI(String relationURI) {
299 this.relationURI = relationURI;
302 public Read<Resource> get(Resource subject) {
304 return Combinators.constant(null);
305 return singleObject(subject, relationURI);
308 public int hashCode() {
309 return getClass().hashCode() + 31 * relationURI.hashCode();
312 public boolean equals(Object obj) {
313 if(obj == this) return true;
314 if(obj == null || obj.getClass() != getClass()) return false;
315 CompleteFunctionURI other = (CompleteFunctionURI)obj;
316 return relationURI.equals(other.relationURI);
320 // ------------------------------------------------------------------------
322 private static final ParametrizedRead<IResourceEditorInput, Resource> EXTRACT_INPUT_RESOURCE = new ParametrizedRead<IResourceEditorInput, Resource>() {
324 public Read<Resource> get(IResourceEditorInput input) {
325 return extractResource(input);
329 // ------------------------------------------------------------------------
331 private static final ParametrizedRead<Resource, Boolean> HAS_URI = new ParametrizedRead<Resource, Boolean>() {
333 public Read<Boolean> get(Resource resource) {
334 return hasURI(resource);