1 package eu.simuline.relana.expressions;
2
3 import eu.simuline.relana.model.Deficiency;
4 import eu.simuline.relana.model.DeficiencyNode;
5
6
7 import java.util.Set;
8 import java.util.HashSet;
9 import java.util.Map;
10 import java.util.HashMap;
11 import java.util.Stack;
12
13
14
15
16
17
18
19
20
21
22
23 public final class Type {
24
25 public static final Type EMPTY = new Type();
26 public static final Type BOOLEAN;
27
28 static {
29 Map<Deficiency, DeficiencyNode> deficiency2ordering =
30 new HashMap<Deficiency, DeficiencyNode>();
31 deficiency2ordering.put(Deficiency.UNDET,
32 new DeficiencyNode(Deficiency.UNDET));
33 BOOLEAN = new Type(deficiency2ordering);
34 }
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 private Map<Deficiency, DeficiencyNode> deficiency2ordering;
50
51 private Set<Deficiency> minDefs;
52
53 private Set<Deficiency> maxDefs;
54
55
56
57
58
59
60 public Type(Map<Deficiency, DeficiencyNode> deficiency2ordering) {
61 this.deficiency2ordering = deficiency2ordering;
62 assert consistency();
63 initMMDefics();
64 }
65
66
67 public Type(Type other) {
68 this(other.copy());
69 }
70
71
72 public Type() {
73 this(new HashMap<Deficiency, DeficiencyNode>());
74 }
75
76
77
78
79
80
81
82
83
84
85 private boolean consistency() {
86 for (DeficiencyNode node : this.deficiency2ordering.values()) {
87 for (DeficiencyNode succ : node.getSuccessors()) {
88 if (this.deficiency2ordering.get(succ.getDeficiency())
89 != succ) {
90
91
92 return false;
93 }
94 }
95 for (DeficiencyNode pred : node.getPredecessors()) {
96 if (this.deficiency2ordering.get(pred.getDeficiency())
97 != pred) {
98
99
100 return false;
101 }
102 }
103 }
104 return true;
105 }
106
107 public Map<Deficiency, DeficiencyNode> getDeficiency2ordering() {
108 return this.deficiency2ordering;
109 }
110
111
112
113 protected void initMMDefics() {
114 this.minDefs = new HashSet<Deficiency>();
115 this.maxDefs = new HashSet<Deficiency>();
116
117 for (DeficiencyNode node : this.deficiency2ordering.values()) {
118 if (node.getSuccessors().isEmpty()) {
119 this.minDefs.add(node.getDeficiency());
120 }
121 if (node.getPredecessors().isEmpty()) {
122 this.maxDefs.add(node.getDeficiency());
123 }
124 }
125 }
126
127 public static Type getEmpty() {
128 return new Type();
129 }
130
131 protected Map<Deficiency, DeficiencyNode> copy() {
132 Map<Deficiency, DeficiencyNode> newDeficiency2ordering =
133 new HashMap<Deficiency, DeficiencyNode>();
134 for (Map.Entry<Deficiency, DeficiencyNode> entry
135 : this.deficiency2ordering.entrySet()) {
136 newDeficiency2ordering.put(entry.getKey(),
137 new DeficiencyNode(entry.getValue()));
138 assert newDeficiency2ordering.get(entry.getKey())
139 .equals(this.deficiency2ordering.get(entry.getKey()));
140 }
141
142 DeficiencyNode node;
143 Set<DeficiencyNode> predSuccs, predSuccsNew;
144 for (Map.Entry<Deficiency, DeficiencyNode> entry
145 : newDeficiency2ordering.entrySet()) {
146 node = entry.getValue();
147
148 predSuccs = node.getPredecessors();
149 predSuccsNew = new HashSet<DeficiencyNode>();
150 for (DeficiencyNode pred : predSuccs) {
151 predSuccsNew
152 .add(newDeficiency2ordering.get(pred.getDeficiency()));
153 }
154 predSuccs.clear();
155 predSuccs.addAll(predSuccsNew);
156
157 predSuccs = node.getSuccessors();
158 predSuccsNew = new HashSet<DeficiencyNode>();
159 for (DeficiencyNode succ : predSuccs) {
160 predSuccsNew
161 .add(newDeficiency2ordering.get(succ.getDeficiency()));
162 }
163 predSuccs.clear();
164 predSuccs.addAll(predSuccsNew);
165 }
166
167
168 return newDeficiency2ordering;
169 }
170
171 protected DeficiencyNode remove(Map<Deficiency, DeficiencyNode> def2ord,
172 Deficiency def) {
173 DeficiencyNode node = def2ord.remove(def);
174 if (node == null) {
175 throw new IllegalArgumentException
176 ("Tried to remove deficiency \"" + def +
177 "\" which is not present in type " + this + ". ");
178 }
179 if (!node.getSuccessors().isEmpty()) {
180 throw new IllegalArgumentException
181 ("Tried to remove deficiency which is not minimal: " +
182 node.getSuccessors() + " are below. ");
183 }
184
185 for (DeficiencyNode pred : node.getPredecessors()) {
186 pred.getSuccessors().remove(node);
187 }
188 return node;
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204 public boolean isValid(Set<Deficiency> set) {
205 DeficiencyNode node;
206
207 for (Deficiency definSet : set) {
208 node = this.deficiency2ordering.get(definSet);
209 if (node == null) {
210 return false;
211 }
212 for (DeficiencyNode succ : node.getSuccessors()) {
213 if (!set.contains(succ.getDeficiency())) {
214 return false;
215 }
216 }
217 }
218 return true;
219 }
220
221
222
223
224
225
226
227
228
229 public Set<Deficiency> asSet() {
230 return this.deficiency2ordering.keySet();
231 }
232
233
234 public Type getInverse() {
235 Map<Deficiency, DeficiencyNode> invDeficiency2ordering =
236 new HashMap<Deficiency, DeficiencyNode>();
237 for (Map.Entry<Deficiency, DeficiencyNode> entry
238 : this.deficiency2ordering.entrySet()) {
239 invDeficiency2ordering.put(entry.getKey(),
240 entry.getValue().getInverse());
241 }
242 return new Type(invDeficiency2ordering);
243 }
244
245 public Set<Deficiency> getMin() {
246 return this.minDefs;
247 }
248
249 public Set<Deficiency> getMax() {
250 return this.maxDefs;
251 }
252
253 public void addAll(Map<Deficiency, DeficiencyNode> deficiency2ordering) {
254 for (Map.Entry<Deficiency, DeficiencyNode> entry
255 : deficiency2ordering.entrySet()) {
256 DeficiencyNode node =
257 this.deficiency2ordering.get(entry.getKey());
258
259 if (node == null) {
260 node = new DeficiencyNode(entry.getKey());
261 } else {
262 node = new DeficiencyNode(node);
263 }
264
265 node.addAll(entry.getValue());
266 this.deficiency2ordering.put(entry.getKey(), node);
267 }
268 initMMDefics();
269 }
270
271 public void replace(Deficiency oldDef,
272 Deficiency newDefMin,
273 Deficiency newDefMax,
274 Type type) {
275 DeficiencyNode nodeMin = type.getDeficiency2ordering().get(newDefMin);
276 DeficiencyNode nodeMax = type.getDeficiency2ordering().get(newDefMax);
277
278 boolean assertn = true;
279 assertn &= nodeMin.getSuccessors ().isEmpty();
280 assertn &= nodeMax.getPredecessors().isEmpty();
281
282 DeficiencyNode node = this.deficiency2ordering.remove(oldDef);
283 for (DeficiencyNode pred : node.getPredecessors()) {
284 assertn &= pred.getSuccessors().remove(node);
285 assertn &= pred.getSuccessors().add(nodeMax);
286 }
287 nodeMax.addPredecessors(node.getPredecessors());
288
289 for (DeficiencyNode pred : node.getSuccessors()) {
290 assertn &= pred.getPredecessors().remove(node);
291 assertn &= pred.getPredecessors().add(nodeMin);
292 }
293 nodeMin.addSuccessors(node.getSuccessors());
294
295 assert assertn;
296 this.deficiency2ordering.putAll(type.getDeficiency2ordering());
297 initMMDefics();
298 }
299
300
301
302
303
304 public Type remove(Deficiency def) {
305 Map<Deficiency, DeficiencyNode> newDef2ord = copy();
306 remove(newDef2ord, def);
307 return new Type(newDef2ord);
308 }
309
310
311
312
313
314
315
316
317
318
319
320
321
322 public Type removeAndAbove(Deficiency def) {
323
324 Map<Deficiency, DeficiencyNode> newDef2ord = copy();
325
326 Stack<Deficiency> defsToBeRemoved = new Stack<Deficiency>();
327 defsToBeRemoved.push(def);
328 while (!defsToBeRemoved.empty()) {
329 def = defsToBeRemoved.pop();
330 DeficiencyNode node = remove(newDef2ord, def);
331 for (DeficiencyNode pred : node.getPredecessors()) {
332 defsToBeRemoved.push(pred.getDeficiency());
333 }
334 }
335
336 return new Type(newDef2ord);
337 }
338
339 public boolean implies(Deficiency def1, Deficiency def2) {
340 DeficiencyNode node = this.deficiency2ordering.get(def1);
341 if (node == null) {
342 throw new IllegalArgumentException
343 ("Deficiency \"" + def1 +
344 "\" does not occur within type " + this + ". ");
345 }
346 Stack<DeficiencyNode> search = new Stack<DeficiencyNode>();
347 search.push(node);
348 while (!search.empty()) {
349 node = search.pop();
350 if (node.getDeficiency().equals(def2)) {
351 return true;
352 }
353 search.addAll(node.getSuccessors());
354 }
355 return false;
356 }
357
358 public Set<Deficiency> getCone(Deficiency def) {
359 Set<Deficiency> result = new HashSet<Deficiency>();
360 Stack<DeficiencyNode> toBeAdded = new Stack<DeficiencyNode>();
361 toBeAdded.push(this.deficiency2ordering.get(def));
362 DeficiencyNode node;
363 while (!toBeAdded.empty()) {
364 node = toBeAdded.pop();
365
366 result.add(node.getDeficiency());
367 toBeAdded.addAll(node.getSuccessors());
368 }
369
370 return result;
371 }
372
373
374 public boolean equals(Object obj) {
375 if (!(obj instanceof Type)) {
376 return false;
377 }
378
379 Type other = (Type) obj;
380 if (!asSet().equals(other.asSet())) {
381 return false;
382 }
383
384
385 for (Map.Entry<Deficiency, DeficiencyNode> entry
386 : this.deficiency2ordering.entrySet()) {
387 if (!other.deficiency2ordering.get(entry.getKey())
388 .equals(entry.getValue())) {
389 return false;
390 }
391 }
392
393 return true;
394 }
395
396 public int hashCode() {
397 return this.deficiency2ordering.hashCode();
398 }
399
400 public String toString() {
401 StringBuffer buf = new StringBuffer();
402 buf.append("\n<Type>");
403 buf.append(this.deficiency2ordering);
404 buf.append("</Type>");
405 return buf.toString();
406 }
407 }