1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 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.layer0.request.combinations.Combinators.SynchronizationProcedure;
24 import org.simantics.db.request.Read;
25 import org.simantics.ui.workbench.IResourceEditorInput;
28 * Composable database read operations designed to be used for defining
29 * validation strategies for resource editor inputs through composition.
32 * For example one validation criterion might be that the editor input or one of
33 * its neighboring resources must have a proper URI.
35 * @author Tuukka Lehtonen
37 public final class InputValidationCombinators {
42 * = subject -> exists(URI(subject))
46 public static ParametrizedRead<Resource, Boolean> hasURI() {
53 * = input -> resource(input)
57 public static ParametrizedRead<IResourceEditorInput, Resource> extractInputResource() {
58 return EXTRACT_INPUT_RESOURCE;
64 * = subject -> singleObject(subject, resource(relationURI))
68 public static ParametrizedRead<Resource,Resource> completeFunction(String relationURI) {
69 return new CompleteFunctionURI(relationURI);
75 * = subject -> possibleObject(subject, resource(relationURI))
79 public static ParametrizedRead<Resource,Resource> partialFunction(String relationURI) {
80 return new PartialFunctionURI(relationURI);
86 * = subject -> true if any of conditions is true for subject, false otherwise
90 @SuppressWarnings("unchecked")
91 public static ParametrizedRead<Resource, Boolean> or(ParametrizedRead<Resource, Boolean> c1,
92 ParametrizedRead<Resource, Boolean> c2) {
93 return new FunctionOr(new ParametrizedRead[] { c1, c2 });
96 // ------------------------------------------------------------------------
98 private static class Or extends UnaryRead<Resource, Boolean> {
99 ParametrizedRead<Resource, Boolean>[] reads;
100 public Or(Resource resource, ParametrizedRead<Resource, Boolean>... reads) {
105 public Boolean perform(ReadGraph graph) throws DatabaseException {
106 for (ParametrizedRead<Resource, Boolean> r : reads) {
107 Read<Boolean> read = r.get(parameter);
108 Boolean value = graph.syncRequest( read );
112 return Boolean.FALSE;
115 public int hashCode() {
116 return super.hashCode() * 31 + Arrays.hashCode(reads);
119 public boolean equals(Object object) {
120 if (this == object) return true;
121 else if (object == null || getClass() != object.getClass()) return false;
122 Or other = (Or) object;
123 return super.equals(object) && Arrays.equals(reads, other.reads);
127 // ------------------------------------------------------------------------
129 private static class FunctionOr implements ParametrizedRead<Resource, Boolean> {
130 ParametrizedRead<Resource, Boolean>[] reads;
131 public FunctionOr(ParametrizedRead<Resource, Boolean>... reads) {
135 public Read<Boolean> get(Resource subject) {
136 if (subject == null || reads.length == 0)
137 return Combinators.constant(Boolean.TRUE);
138 return new Or(subject, reads);
141 public int hashCode() {
142 return getClass().hashCode() + 31 * Arrays.hashCode(reads);
145 public boolean equals(Object obj) {
146 if(obj == this) return true;
147 if(obj == null || obj.getClass() != getClass()) return false;
148 FunctionOr other = (FunctionOr)obj;
149 return Arrays.equals(reads, other.reads);
153 // ------------------------------------------------------------------------
155 private static class HasURI extends UnaryRead<Resource, Boolean> {
156 public HasURI(Resource resource) {
160 public Boolean perform(ReadGraph graph) throws DatabaseException {
161 if (parameter == null)
162 return Boolean.FALSE;
164 String uri = graph.syncRequest(Queries.possibleUri(parameter));
165 //System.out.println("uri(" + parameter + "): " + uri);
167 return Boolean.FALSE;
169 // FIXME: URI request will return invalid URIs, like
170 // null/Configuration/MyComposite after deleting the parenting model
171 // For this reason we try to reverse lookup the URI back into a
172 // resource which must be equal to the original parameter resource.
174 Resource reverseLookup = graph.getPossibleResource(uri);
175 //System.out.println("resource(" + uri + "): " + reverseLookup);
176 return parameter.equals(reverseLookup);
180 public static Read<Boolean> hasURI(Resource resource) {
181 return new HasURI(resource);
184 // ------------------------------------------------------------------------
186 private static class ExtractResource extends UnaryRead<IResourceEditorInput, Resource> {
187 public ExtractResource(IResourceEditorInput input) {
191 public Resource perform(ReadGraph graph) throws DatabaseException {
192 return parameter != null ? parameter.getResource() : null;
196 public static Read<Resource> extractResource(IResourceEditorInput input) {
197 return new ExtractResource(input);
200 // ------------------------------------------------------------------------
202 private static class PossibleObjectURI implements Read<Resource> {
205 public PossibleObjectURI(Resource subject, String relationURI) {
206 this.subject = subject;
207 this.relationURI = relationURI;
210 public Resource perform(ReadGraph graph) throws DatabaseException {
211 SynchronizationProcedure<Resource> procedure = new SynchronizationProcedure<Resource>();
212 Resource relation = graph.getResource(relationURI);
213 graph.forPossibleObject(subject, relation, procedure);
214 return procedure.getResult();
217 public int hashCode() {
218 return subject.hashCode() + 31 * relationURI.hashCode();
221 public boolean equals(Object object) {
222 if (this == object) return true;
223 else if (object == null || getClass() != object.getClass()) return false;
224 PossibleObjectURI other = (PossibleObjectURI)object;
225 return subject.equals(other.subject) && relationURI.equals(other.relationURI);
230 * Returns a read request that reads an object possibly connected to the subject by the relation.
232 public static Read<Resource> possibleObject(Resource subject, String relationURI) {
233 return new PossibleObjectURI(subject, relationURI);
236 // ------------------------------------------------------------------------
238 private static class PartialFunctionURI implements ParametrizedRead<Resource, Resource> {
240 public PartialFunctionURI(String relationURI) {
241 this.relationURI = relationURI;
244 public Read<Resource> get(Resource subject) {
246 return Combinators.constant(null);
247 return possibleObject(subject, relationURI);
250 public int hashCode() {
251 return getClass().hashCode() + 31 * relationURI.hashCode();
254 public boolean equals(Object obj) {
255 if(obj == this) return true;
256 if(obj == null || obj.getClass() != getClass()) return false;
257 PartialFunctionURI other = (PartialFunctionURI)obj;
258 return relationURI.equals(other.relationURI);
262 // ------------------------------------------------------------------------
264 private static class SingleObjectURI implements Read<Resource> {
267 public SingleObjectURI(Resource subject, String relationURI) {
268 this.subject = subject;
269 this.relationURI = relationURI;
272 public Resource perform(ReadGraph graph) throws DatabaseException {
273 SynchronizationProcedure<Resource> procedure = new SynchronizationProcedure<Resource>();
274 Resource relation = graph.getResource(relationURI);
275 graph.forSingleObject(subject, relation, procedure);
276 return procedure.getResult();
279 public int hashCode() {
280 return subject.hashCode() + 31 * relationURI.hashCode();
283 public boolean equals(Object object) {
284 if (this == object) return true;
285 else if (object == null || getClass() != object.getClass()) return false;
286 SingleObjectURI other = (SingleObjectURI) object;
287 return subject.equals(other.subject) && relationURI.equals(other.relationURI);
292 * Returns a read request that reads a single object connected to the
293 * subject by the relation.
295 public static Read<Resource> singleObject(Resource subject, String relationURI) {
296 return new SingleObjectURI(subject, relationURI);
299 // ------------------------------------------------------------------------
301 private static class CompleteFunctionURI implements ParametrizedRead<Resource, Resource> {
303 public CompleteFunctionURI(String relationURI) {
304 this.relationURI = relationURI;
307 public Read<Resource> get(Resource subject) {
309 return Combinators.constant(null);
310 return singleObject(subject, relationURI);
313 public int hashCode() {
314 return getClass().hashCode() + 31 * relationURI.hashCode();
317 public boolean equals(Object obj) {
318 if(obj == this) return true;
319 if(obj == null || obj.getClass() != getClass()) return false;
320 CompleteFunctionURI other = (CompleteFunctionURI)obj;
321 return relationURI.equals(other.relationURI);
325 // ------------------------------------------------------------------------
327 private static final ParametrizedRead<IResourceEditorInput, Resource> EXTRACT_INPUT_RESOURCE = new ParametrizedRead<IResourceEditorInput, Resource>() {
329 public Read<Resource> get(IResourceEditorInput input) {
330 return extractResource(input);
334 // ------------------------------------------------------------------------
336 private static final ParametrizedRead<Resource, Boolean> HAS_URI = new ParametrizedRead<Resource, Boolean>() {
338 public Read<Boolean> get(Resource resource) {
339 return hasURI(resource);