View Javadoc
1   package eu.simuline.relana.expressions;
2   
3   import eu.simuline.relana.model.Deficiency;
4   import eu.simuline.relana.model.DeficiencyMap;
5   
6   import java.util.List;
7   import java.util.ArrayList;
8   import java.util.Map;
9   import java.util.HashMap;
10  import java.util.Set;
11  import java.util.HashSet;
12  import java.util.Iterator;
13  
14  /**
15   * Represents the operations as intersection, union, complement, 
16   * covariant and contravariant functors and maps. 
17   *
18   *
19   * Created: Fri Apr 29 01:57:48 2005
20   *
21   * @author <a href="mailto:ernst.reissner@simuline.eu">Ernst Reissner</a>
22   * @version 1.0
23   */
24  public abstract class Operation {
25  
26      /**
27       * Comprises the basic set theoretic operations 
28       * union, intersection and complement. 
29       */
30      public enum BaseOps {
31  
32  	/* ---------------------------------------------------------------- *
33  	 * constructor constants.                                           *
34  	 * ---------------------------------------------------------------- */
35  
36  	Intersection(new IntsOp()) {
37  	    public String toString() {
38  		return "&";
39  	    }
40  	},
41  	Union(new UnionOp()) {
42  	    public String toString() {
43  		return "|";
44  	    }
45  	},
46  	Complement(new CompOp()) {
47  	    public String toString() {
48  		return "~";
49  	    }
50  	};
51  
52  	/* ---------------------------------------------------------------- *
53  	 * constructors.                                                    *
54  	 * ---------------------------------------------------------------- */
55  
56  	BaseOps(Operation oper) {
57  	    this.oper = oper;
58  	}
59  
60  	/* ---------------------------------------------------------------- *
61  	 * class constants and initializer.                                 *
62  	 * ---------------------------------------------------------------- */
63  
64  	private static final Map<String, BaseOps> KEY2OP;
65  
66  	static {
67  	    KEY2OP = new HashMap<String, BaseOps>();
68  	    KEY2OP.put(Intersection.toString(), Intersection);
69  	    KEY2OP.put(Union       .toString(), Union       );
70  	    KEY2OP.put(Complement  .toString(), Complement  );
71  	}
72  
73  	/* ---------------------------------------------------------------- *
74  	 * fields.                                                          *
75  	 * ---------------------------------------------------------------- */
76  
77  	private Operation oper;
78  
79  	/* ---------------------------------------------------------------- *
80  	 * methods.                                                          *
81  	 * ---------------------------------------------------------------- */
82  
83  	Operation getOperation() {
84  	    return this.oper;
85  	}
86  
87  	public static Operation getOperation(String str) {
88  	    BaseOps oper = KEY2OP.get(str);
89  	    if (oper == null) {
90  		throw new IllegalStateException
91  		    ("Unknown operation \"" + str + "\". ");
92  	    }
93  	    return oper.getOperation();
94  	}
95      } // enum BaseOps 
96  
97      /**
98       * Defines the basic set theoretic intersection. 
99       */
100     static final class IntsOp extends Operation implements Eval {
101 	//private Type type;
102 	IntsOp() {
103 	    //this.type = type;
104 	}
105 
106 	/* ---------------------------------------------------------------- *
107 	 * methods.                                                          *
108 	 * ---------------------------------------------------------------- */
109 
110 	boolean arity1() {
111 	    return false;
112 	}
113 
114 	public Type retType(Set<FormulaDecl> args) {
115 	    Iterator<FormulaDecl> iter = args.iterator();
116 	    if (!iter.hasNext()) {
117 		throw new IllegalArgumentException
118 		    ("Expected at least one argument. ");
119 	    }
120 	    Type proto = iter.next().retType();
121 	    //Type cand;
122 	    while (iter.hasNext()) {
123 		if (!proto.equals(iter.next().retType())) {
124 		    // prepare types 
125 		    List<Type> argTypes = new ArrayList<Type>();
126 		    for (FormulaDecl form : args) {
127 			argTypes.add(form.retType());
128 		    }
129 		    throw new IllegalArgumentException
130 			("Expected all the same types; found " + args + 
131 			 " with types " + argTypes + ". ");
132 		}
133 	    }
134 	    return proto;
135 	}
136 
137 	public Set<Deficiency> eval(Set<Set<Deficiency>> param) {
138 	    Iterator<Set<Deficiency>> iter = param.iterator();
139 	    assert iter.hasNext();
140 	    Set<Deficiency> result = new HashSet<Deficiency>(iter.next());
141 	    while (iter.hasNext()) {
142 		result.retainAll(iter.next());
143 	    }
144 	    return result;
145 	}
146 
147 	public Eval getEval(Type type) {
148 	    return this;
149 	}
150 
151 	public Operation getOperation() {
152 	    return this;
153 	}
154 
155 	boolean isIsoAntitone() {
156 	    return true;
157 	}
158 
159 	public String toString() {
160 	    return "&";
161 	}
162     } // class IntsOp 
163 
164     /**
165      * Defines the basic set theoretic union complement. 
166      */
167     static final class UnionOp extends Operation implements Eval {
168 
169 	boolean arity1() {
170 	    return false;
171 	}
172 
173 	public Type retType(Set<FormulaDecl> args) {
174 	    Iterator<FormulaDecl> iter = args.iterator();
175 	    if (!iter.hasNext()) {
176 		throw new IllegalArgumentException
177 		    ("Expected at least one argument. ");
178 	    }
179 	    Type proto = iter.next().retType();
180 //	    Type cand;
181 	    while (iter.hasNext()) {
182 		if (!proto.equals(iter.next().retType())) {
183 		    // prepare types 
184 		    List<Type> argTypes = new ArrayList<Type>();
185 		    for (FormulaDecl form : args) {
186 			argTypes.add(form.retType());
187 		    }
188 		    throw new IllegalArgumentException
189 			("Expected all the same types; found " + args + 
190 			 " with types " + argTypes + ". ");
191 		}
192 	    }
193 	    return proto;
194 	}
195 
196 	public Set<Deficiency> eval(Set<Set<Deficiency>> param) {
197 	    Set<Deficiency> result = new HashSet<Deficiency>();
198 	    for (Set<Deficiency> set : param) {
199 		result.addAll(set);
200 	    }
201 	    return result;
202 	}
203 
204 	public Eval getEval(Type type) {
205 	    return this;
206 	}
207 
208 	public Operation getOperation() {
209 	    return this;
210 	}
211 
212 	boolean isIsoAntitone() {
213 	    return true;
214 	}
215 	public String toString() {
216 	    return "|";
217 	}
218     } // class UnionOp 
219 
220     /**
221      * Defines the basic set theoretic complement. 
222      */
223     static final class CompOp extends Operation {
224 	boolean arity1() {
225 	    return true;
226 	}
227 	public Type retType(Set<FormulaDecl> args) {
228 	    Iterator<FormulaDecl> iter = args.iterator();
229 	    if (!iter.hasNext()) {
230 		throw new IllegalArgumentException
231 		    ("Expected at least one argument. ");
232 	    }
233 	    Type proto = iter.next().retType();
234 	    if (iter.hasNext()) {
235 		throw new IllegalArgumentException
236 		    ("Expected no more than one argument. ");
237 	    }
238 	    return proto.getInverse();
239 
240 	}
241 
242 	public Eval getEval(final Type type) {
243 	    return new Eval() {
244 		    public Set<Deficiency> eval(Set<Set<Deficiency>> param) {
245 			Set<Deficiency> result = type.asSet();
246 			Iterator<Set<Deficiency>> iter = param.iterator();
247 			result.removeAll(iter.next());
248 			assert !iter.hasNext();
249 			return result;
250 		    }
251 		    public Operation getOperation() {
252 			return CompOp.this;
253 		    }
254 
255 		};
256 	}
257 
258 	boolean isIsoAntitone() {
259 	    return false;
260 	}
261 	public String toString() {
262 	    return "~";
263 	}
264     } // class CompOp 
265 
266     /**
267      * Enumerates the kinds of functors covariant and contravariant ones. 
268      * **** 
269      */
270     public enum Functor {
271 
272 	/* ---------------------------------------------------------------- *
273 	 * constructor constants.                                           *
274 	 * ---------------------------------------------------------------- */
275 
276 	Covariant() {
277 	    public boolean isAllowed(DeficiencyMap map) {
278 		return map.isTwistIsotone();
279 	    }
280 	    public String twistIsotone() {
281 		return "twist-isotone";
282 	    }
283 	    Set<Deficiency> eval(DeficiencyMap map, Set<Deficiency> defs) {
284 		return map.cov(defs);
285 	    }
286 	    Type source(DeficiencyMap map) {
287 		return map.getSource().getType();
288 	    }
289 	    Type target(DeficiencyMap map) {
290 		return map.getTarget().getType();
291 	    }
292 	    String getSymbol() {
293 		return ",";
294 	    }
295 	},
296 	Contravariant() {
297 	    public boolean isAllowed(DeficiencyMap map) {
298 		return map.isIsotone();
299 	    }
300 	    public String twistIsotone() {
301 		return "isotone";
302 	    }
303 	    Set<Deficiency> eval(DeficiencyMap map, Set<Deficiency> defs) {
304 		return map.cont(defs);
305 	    }
306 	    Type source(DeficiencyMap map) {
307 		return map.getTarget().getType();
308 	    }
309 	    Type target(DeficiencyMap map) {
310 		return map.getSource().getType();
311 	    }
312 	    String getSymbol() {
313 		return "'";
314 	    }
315 	};
316 
317 	/* ---------------------------------------------------------------- *
318 	 * methods.                                                         *
319 	 * ---------------------------------------------------------------- */
320 
321 	public abstract boolean isAllowed(DeficiencyMap map);
322 	public abstract String twistIsotone();
323 	abstract Type source(DeficiencyMap map);
324 	abstract Type target(DeficiencyMap map);
325 
326 	Set<Deficiency> eval(Set<Set<Deficiency>> param,
327 			     DeficiencyMap map) {
328 	    assert param.size() == 1;
329 	    return eval(map, param.iterator().next());
330 	}
331 	abstract Set<Deficiency> eval(DeficiencyMap map,
332 				      Set<Deficiency> defs);
333 
334 	Type retType(Set<FormulaDecl> args, Maps mapOper) {
335 	    Type retType = args.iterator().next().retType();
336 	    if (!source(mapOper.getMap()).equals(retType)) {
337 		throw new IllegalArgumentException
338 		    ("Cannot apply \"" + mapOper + 
339 		     "\" to formula \"" + args.iterator().next() + 
340 		     "\" with return type " + retType + ". ");
341 	    }
342 	    return target(mapOper.getMap());
343 	}
344 	//abstract Operation getOperation(DeficiencyMap map);
345 	abstract String getSymbol();
346 
347 	private static final Map<String, Operation.Functor> ACC2FUNCT;
348 
349 	static { 
350 	    ACC2FUNCT = new HashMap<String, Operation.Functor>();
351 	    ACC2FUNCT.put(Operation.Functor.Covariant    .getSymbol(),
352 			  Operation.Functor.Covariant);
353 	    ACC2FUNCT.put(Operation.Functor.Contravariant.getSymbol(),
354 			  Operation.Functor.Contravariant);
355 	}
356 
357 	public static Functor covCont(String acc) {
358 	    return ACC2FUNCT.get(acc);
359 	}
360     } // enum Functor 
361 
362     /**
363      * Represents an operation defined by a covariant/contravariant functor. 
364      * **** 
365      */
366     public static final class Maps extends Operation implements Operation.Eval {
367 
368 	/* ---------------------------------------------------------------- *
369 	 * fields.                                                          *
370 	 * ---------------------------------------------------------------- */
371 
372 	private final String funName;
373 	private final boolean isInverted;
374 	private final DeficiencyMap map;
375 	private final Functor funct;
376 
377 	/* ---------------------------------------------------------------- *
378 	 * constructors.                                                    *
379 	 * ---------------------------------------------------------------- */
380 
381 	public Maps(String funName,
382 		    boolean isInverted,
383 		    DeficiencyMap map, 
384 		    Functor funct) {
385 	    this.funName = funName;
386 	    this.isInverted = isInverted;
387 	    this.map = map;
388 	    this.funct = funct;
389 	    if (!funct.isAllowed(map)) {
390 		throw new IllegalArgumentException
391 		    ("Map \"" + this.funName + 
392 		     "\" is not " + funct.twistIsotone() + 
393 		     " and so corresponding functor \"" + this + 
394 		     "\" is not defined. ");
395 	    }
396 	}
397 
398 	/* ---------------------------------------------------------------- *
399 	 * methods.                                                         *
400 	 * ---------------------------------------------------------------- */
401 
402 	private DeficiencyMap getMap() {
403 	    return this.map;
404 	}
405 
406 	boolean arity1() {
407 	    return true;
408 	}
409 	public Type retType(Set<FormulaDecl> args) {
410 	    return this.funct.retType(args, this);
411 	}
412 	public Set<Deficiency> eval(Set<Set<Deficiency>> param) {
413 	    return this.funct.eval(param, this.map);
414 	}
415 
416 	public Operation.Eval getEval(Type type) {
417 	    return this;
418 	}
419 
420 	public Operation getOperation() {
421 	    return this;
422 	}
423 
424 	// **** caution: if false: 
425 	// then the operation is assumed to be antitone
426 	public boolean isIsoAntitone() {
427 	    return true;
428 	}
429 	public String toString() {
430 	    StringBuffer res = new StringBuffer();
431 	    res.append(this.funName);
432 	    if (this.isInverted) {
433 		res.append('!');
434 	    }
435 	    res.append(this.funct.getSymbol());
436 	    return res.toString();
437 	}
438     } // class Maps
439 
440     /**
441      *
442      */
443     public interface Eval {
444 	// length == 1 if arity1() 
445 	Set<Deficiency> eval(Set<Set<Deficiency>> param);
446 	Operation getOperation();
447     } // interface Eval 
448 
449     /* -------------------------------------------------------------------- *
450      * constructors.                                                        *
451      * -------------------------------------------------------------------- */
452 
453     public Operation() {
454 		    // is empty. 
455     } // Operation constructor
456 
457     /* -------------------------------------------------------------------- *
458      * methods.                                                             *
459      * -------------------------------------------------------------------- */
460 
461     // whether arity of parameter list must be one; 
462     // otherwise it is an arbitrary but POSITIVE number. 
463     abstract boolean arity1();
464     // **** caution: if false: then the operation is assumed to be antitone
465     abstract boolean isIsoAntitone();
466 
467     public abstract Type retType(Set<FormulaDecl> args);
468     public abstract Eval getEval(Type type);
469 
470 
471 
472     public static Operation getOperation(BaseOps baseOps) {
473 	return baseOps.getOperation();
474     }
475 
476     public static Operation getOperation(String funName,
477 					 boolean isInverted,
478 					 DeficiencyMap map, 
479 					 Functor funct) {
480 	return new Maps(funName, isInverted, map, funct);
481     }
482 
483 } // Operation