1 package eu.simuline.relana.model;
2
3 import java.util.Map;
4 import java.util.HashMap;
5 import java.util.Set;
6 import java.util.HashSet;
7 import java.util.Iterator;
8
9
10
11
12
13
14
15
16
17
18 public final class DeficiencyMap {
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 private final Map<Set<Deficiency>, Deficiency> setOfNew2old;
37
38
39
40
41
42 private final SClass source;
43
44
45
46
47
48 private final SClass target;
49
50
51
52
53
54
55 private final Set<Deficiency> domain;
56
57
58
59
60
61
62 private final Set<Deficiency> range;
63
64
65
66
67
68
69
70 private Set<Deficiency> idDom;
71
72
73
74
75
76 public static
77 DeficiencyMap getSubclassMap(Map<Set<Deficiency>, Deficiency> setOfNew2old,
78 SClass source,
79 SClass target) {
80
81 DeficiencyMap result =
82 new DeficiencyMap(setOfNew2old,
83 source,
84 target,
85 new HashSet<Deficiency>());
86
87 Set<Deficiency> sourceId =
88 new HashSet<Deficiency>(source.getType().asSet());
89 sourceId.removeAll(result.getDomain());
90 Set<Deficiency> rangeId =
91 new HashSet<Deficiency>(target.getType().asSet());
92 rangeId.removeAll(result.getRange());
93 if (!sourceId.equals(rangeId)) {
94 throw new IllegalArgumentException
95 ("No subclass map extending " + result + ". ");
96 }
97 result.idDom = rangeId;
98
99 return result;
100 }
101
102 public DeficiencyMap(Map<Set<Deficiency>, Deficiency> setOfNew2old,
103 SClass source,
104 SClass target,
105 Set<Deficiency> idDom) {
106 this.setOfNew2old = setOfNew2old;
107 this.source = source;
108 this.target = target;
109 this.idDom = idDom;
110
111
112 this.domain = new HashSet<Deficiency>(this.idDom);
113 for (Set<Deficiency> setDef : this.setOfNew2old.keySet()) {
114 this.domain.addAll(setDef);
115 }
116 this.range = new HashSet<Deficiency>(this.idDom);
117 this.range.addAll(this.setOfNew2old.values());
118
119 checkInvImg01();
120
121
122 Set<Deficiency> domain = getDomain();
123 if (!this.source.getType().asSet().containsAll(domain)) {
124 throw new IllegalArgumentException
125 ("Domain " + domain + " not inside type range " +
126 this.source.getType().asSet() + ". ");
127 }
128
129
130
131 int num = this.idDom.size();
132 for (Set<Deficiency> setDef : this.setOfNew2old.keySet()) {
133 num += setDef.size();
134 }
135 if (num != domain.size()) {
136 throw new IllegalArgumentException
137 ("Inverse images " + this.setOfNew2old.keySet() +
138 " and identity domain " + this.idDom +
139 " are not pairwise disjoint. ");
140 }
141
142
143 Set<Deficiency> range = getRange();
144 if (!this.target.getType().asSet().containsAll(range)) {
145 throw new IllegalArgumentException
146 ("Range " + range + " not inside type range " +
147 this.target.getType().asSet() + ". ");
148 }
149
150
151
152 if (this.setOfNew2old.size() + this.idDom.size() != range.size()) {
153 throw new IllegalArgumentException
154 ("Images " + this.setOfNew2old.values() +
155 " and identity domain " + this.idDom +
156 " are not pairwise disjoint. ");
157 }
158 }
159
160
161 void checkInvImg01() {
162
163
164
165 Iterator<Map.Entry<Set<Deficiency>, Deficiency>> iter =
166 this.setOfNew2old.entrySet()
167 .iterator();
168 Set<Deficiency> setDef;
169 Map.Entry<Set<Deficiency>, Deficiency> mapEntry;
170 Deficiency def;
171 while (iter.hasNext()) {
172 mapEntry = iter.next();
173
174 setDef = mapEntry.getKey();
175 switch (setDef.size()) {
176 case 0:
177
178 throw new IllegalArgumentException
179 ("Found empty inverse image for " +
180
181 mapEntry.getValue() + ". ");
182 case 1:
183
184 def = this.setOfNew2old.get(setDef);
185 if (setDef.contains(def)) {
186
187 iter.remove();
188 this.idDom.add(def);
189 }
190 continue;
191 default:
192
193 continue;
194 }
195 }
196 }
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227 public static DeficiencyMap identity(SClass sourceTarget) {
228 System.out.println("sourceTarget: " + sourceTarget);
229 DeficiencyMap map = sourceTarget.getDeficiencyMap();
230 Set<Deficiency> idDom = (map == null)
231 ? new HashSet<Deficiency>
232 (sourceTarget.getDeclaredDeficiency2ordering().keySet())
233 : map.getDomain();
234
235 return new DeficiencyMap(new HashMap<Set<Deficiency>, Deficiency>(),
236 sourceTarget,
237 sourceTarget,
238 idDom);
239 }
240
241
242
243
244
245
246
247
248
249 public DeficiencyMap getInverse() {
250
251 if (getDomain().size() != getRange().size()) {
252 throw new UnsupportedOperationException
253 ("This map is not invertible: " + this + ". ");
254 }
255
256 Map<Set<Deficiency>, Deficiency> invSetOfNew2old =
257 new HashMap<Set<Deficiency>, Deficiency>();
258 Set<Deficiency> oneDefSet;
259 Deficiency def;
260 for (Map.Entry<Set<Deficiency>, Deficiency> entry
261 : this.setOfNew2old.entrySet()) {
262 assert entry.getKey().size() == 1;
263 oneDefSet = new HashSet<Deficiency>();
264 oneDefSet.add(entry.getValue());
265 def = entry.getKey().iterator().next();
266 invSetOfNew2old.put(oneDefSet, def);
267 }
268
269 return new DeficiencyMap(invSetOfNew2old,
270 this.target,
271 this.source,
272 this.idDom);
273 }
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288 public DeficiencyMap compose(DeficiencyMap second) {
289 if (this.target != second.source) {
290 throw new IllegalArgumentException
291 ("Composition of maps is allowed only " +
292 "if source and target coincide but found " +
293 second.source.getName() + " and " +
294 this.target .getName() + ". ");
295 }
296
297 Map<Set<Deficiency>, Deficiency> setOfNew2old =
298 new HashMap<Set<Deficiency>, Deficiency>();
299
300 Set<Deficiency> invImg;
301 for (Map.Entry<Set<Deficiency>, Deficiency> entry
302 : second.setOfNew2old.entrySet()) {
303
304 invImg = this.cont(entry.getKey());
305 setOfNew2old.put(invImg, entry.getValue());
306 }
307
308
309 for (Map.Entry<Set<Deficiency>, Deficiency> entry
310 : this.setOfNew2old.entrySet()) {
311 if (!second.idDom.contains(entry.getValue())) {
312 continue;
313 }
314
315 setOfNew2old.put(entry.getKey(), entry.getValue());
316 }
317
318 Set<Deficiency> idDom = new HashSet<Deficiency>(this.idDom);
319 idDom.retainAll(second.idDom);
320
321
322 Deficiency cand;
323 Iterator<Map.Entry<Set<Deficiency>, Deficiency>> iter =
324 setOfNew2old.entrySet().iterator();
325 Map.Entry<Set<Deficiency>, Deficiency> entry;
326 while (iter.hasNext()) {
327 entry = iter.next();
328 if (entry.getKey().size() != 1) {
329 continue;
330 }
331 assert entry.getKey().size() == 1;
332 cand = entry.getKey().iterator().next();
333 if (!cand.equals(entry.getValue())) {
334 continue;
335 }
336
337 idDom.add(cand);
338 iter.remove();
339 }
340
341 return new DeficiencyMap(setOfNew2old,
342 this.source,
343 second.target,
344 idDom);
345 }
346
347
348
349
350
351
352
353
354
355
356
357
358 public Deficiency map(Deficiency def) {
359 if (this.idDom.contains(def)) {
360 return def;
361 }
362
363 for (Map.Entry<Set<Deficiency>, Deficiency> entry
364 : this.setOfNew2old.entrySet()) {
365 if (entry.getKey().contains(def)) {
366 return entry.getValue();
367 }
368 }
369
370 return null;
371 }
372
373
374
375
376
377
378
379
380
381
382
383
384
385 Set<Deficiency> getInverseImage(Deficiency def) {
386 Set<Deficiency> result = new HashSet<Deficiency>();
387 if (this.idDom.contains(def)) {
388 result.add(def);
389 return result;
390 }
391
392 for (Map.Entry<Set<Deficiency>, Deficiency> entry
393 : this.setOfNew2old.entrySet()) {
394 if (entry.getValue().equals(def)) {
395 return entry.getKey();
396 }
397 }
398
399 return result;
400 }
401
402
403
404
405
406
407
408 Set<Deficiency> getDomain() {
409 return this.domain;
410 }
411
412
413
414
415
416
417
418 Set<Deficiency> getRange() {
419 return this.range;
420 }
421
422
423
424
425
426 public SClass getSource() {
427 return this.source;
428 }
429
430
431
432
433
434 public SClass getTarget() {
435 return this.target;
436 }
437
438
439
440
441
442
443
444 public boolean isIsotone() {
445 Set<Deficiency> cone;
446 for (Deficiency def1 : getDomain()) {
447 cone = this.source.getType().getCone(def1);
448 if (!getDomain().containsAll(cone)) {
449 return false;
450 }
451 for (Deficiency def2 : cone) {
452 if (!this.target.getType().implies(map(def1), map(def2))) {
453 return false;
454 }
455 }
456 }
457 return true;
458 }
459
460
461
462
463
464
465
466 public boolean isTwistIsotone() {
467 Set<Deficiency> cone, coneT;
468 for (Deficiency def1 : getDomain()) {
469 cone = this.source.getType().getCone( def1);
470 coneT = this.target.getType().getCone(map(def1));
471 for (Deficiency defT2 : coneT) {
472 Set<Deficiency> inter =
473 new HashSet<Deficiency>(getInverseImage(defT2));
474 inter.retainAll(cone);
475 if (inter.isEmpty()) {
476 return false;
477 }
478 }
479 }
480 return true;
481 }
482
483
484
485
486
487
488
489
490
491 public Set<Deficiency> cov(Set<Deficiency> defs) {
492 assert this.source.getType().isValid(defs);
493 Set<Deficiency> defsToMap = new HashSet<Deficiency>(defs);
494 defsToMap.retainAll(this.domain);
495 Set<Deficiency> result = new HashSet<Deficiency>();
496
497 Set<Deficiency> inter;
498 for (Map.Entry<Set<Deficiency>, Deficiency> entry
499 : this.setOfNew2old.entrySet()) {
500 inter = new HashSet<Deficiency>(entry.getKey());
501 inter.retainAll(defsToMap);
502 if (!inter.isEmpty()) {
503 result.add(entry.getValue());
504 }
505 }
506
507 defsToMap.retainAll(this.target.getType().asSet());
508 result.addAll(defsToMap);
509 assert this.target.getType().isValid(result);
510 return result;
511 }
512
513
514
515
516
517
518
519
520
521 public Set<Deficiency> cont(Set<Deficiency> defs) {
522 assert this.target.getType().isValid(defs);
523 Set<Deficiency> result = new HashSet<Deficiency>();
524 for (Map.Entry<Set<Deficiency>, Deficiency> entry
525 : this.setOfNew2old.entrySet()) {
526 if (defs.contains(entry.getValue())) {
527 result.addAll(entry.getKey());
528 }
529 }
530
531 Set<Deficiency> defsToMap =
532 new HashSet<Deficiency>(this.source.getType().asSet());
533 defsToMap.retainAll(defs);
534 result.addAll(defsToMap);
535 assert this.source.getType().isValid(result);
536 return result;
537 }
538
539
540 public String toString() {
541 StringBuffer res = new StringBuffer();
542 res.append("<DeficiencyMap source=\"");
543 res.append(source.getPathName());
544 res.append("\" target=\"");
545 res.append(target.getPathName());
546 res.append("\">\n");
547 res.append(this.setOfNew2old);
548 res.append('\n');
549 res.append(this.idDom);
550 res.append("\n</DeficiencyMap>");
551 return res.toString();
552 }
553
554 }