001 package nl.cwi.sen1.modulemanager.model;
002
003 import java.util.HashMap;
004 import java.util.HashSet;
005 import java.util.Iterator;
006 import java.util.LinkedList;
007 import java.util.Map;
008 import java.util.Set;
009
010 import nl.cwi.sen1.moduleapi.types.AttributeStore;
011 import nl.cwi.sen1.moduleapi.types.ModuleId;
012 import aterm.AFun;
013 import aterm.ATerm;
014 import aterm.ATermAppl;
015 import aterm.pure.PureFactory;
016
017 public class ModuleDatabase {
018 private int moduleCount;
019
020 protected Map<ModuleId, Module> modules;
021
022 protected Map<ModuleId, Set<ModuleId>> descendants;
023
024 private Map<ModuleId, Set<ModuleId>> transDescendants;
025
026 private AttributeUpdateRuleMap attributeUpdateRules;
027
028 private Map<ModuleId, Set<ModuleId>> ascendants;
029
030 private AttributeSetListener listener;
031
032 private AFun modalAND, modalOR, modalNOT, modalONE, modalALL, modalSET;
033
034 public ModuleDatabase(AttributeSetListener l, PureFactory factory) {
035 moduleCount = 0;
036 modules = new HashMap<ModuleId, Module>();
037 descendants = new HashMap<ModuleId, Set<ModuleId>>();
038 transDescendants = new HashMap<ModuleId, Set<ModuleId>>();
039 ascendants = new HashMap<ModuleId, Set<ModuleId>>();
040 listener = l;
041 attributeUpdateRules = new AttributeUpdateRuleMap();
042
043 modalAND = factory.makeAFun("and", 2, false);
044 modalOR = factory.makeAFun("or", 2, false);
045 modalNOT = factory.makeAFun("not", 1, false);
046 modalONE = factory.makeAFun("one", 1, false);
047 modalALL = factory.makeAFun("all", 1, false);
048 modalSET = factory.makeAFun("set", 3, false);
049 }
050
051 public int getNextModuleId() {
052 return moduleCount++;
053 }
054
055 public void addModule(Module module, ModuleId moduleId) {
056 modules.put(moduleId, module);
057 descendants.put(moduleId, new HashSet<ModuleId>());
058 ascendants.put(moduleId, new HashSet<ModuleId>());
059 }
060
061 public void removeModule(ModuleId moduleId) {
062 deleteAllDependencies(moduleId);
063 modules.remove(moduleId);
064 descendants.remove(moduleId);
065 ascendants.remove(moduleId);
066 }
067
068 private void triggerAllAttributeUpdateRulesOnAllModules() {
069 for (Iterator<ModuleId> iter = modules.keySet().iterator(); iter
070 .hasNext();) {
071 triggerAllAttributeUpdateRules(iter.next());
072 }
073 }
074
075 private void triggerAllAttributeUpdateRules(ModuleId id) {
076 for (Iterator<AttributeUpdateRule> iter = attributeUpdateRules
077 .iterator(); iter.hasNext();) {
078 propagate(iter.next(), id);
079 }
080 }
081
082 public void setAttribute(ModuleId moduleId, ATerm namespace, ATerm key,
083 ATerm value) {
084 Module module = modules.get(moduleId);
085
086 if (module == null) {
087 System.err.println("MM - addAttribute: module [" + moduleId
088 + "] doesn't exist");
089 return;
090 }
091
092 updateAttribute(moduleId, namespace, key, value);
093 }
094
095 private void updateAttribute(ModuleId moduleId, ATerm namespace, ATerm key,
096 ATerm value) {
097 Module module = modules.get(moduleId);
098 ATerm oldValue = module.getAttribute(namespace, key);
099 ATerm oldPredicate = module.getPredicate(namespace, key);
100
101 module.deletePredicate(namespace, key);
102
103 if (oldValue == null || !oldValue.isEqual(value)) {
104 module.setAttribute(namespace, key, value);
105 if (oldPredicate != null) {
106 fireAttributeSetListener(moduleId, namespace, key,
107 oldPredicate, value);
108 } else {
109 fireAttributeSetListener(moduleId, namespace, key, oldValue,
110 value);
111 }
112 propagateToParents(moduleId);
113 triggerAllAttributeUpdateRules(moduleId);
114 }
115 }
116
117 private void updatePredicate(ModuleId moduleId, ATerm namespace, ATerm key,
118 ATerm predicate) {
119 Module module = modules.get(moduleId);
120 ATerm oldValue = module.getPredicate(namespace, key);
121 // If there was no predicate get the old value. The listener gives the
122 // new value as well as the old value.
123 if (oldValue == null) {
124 oldValue = module.getAttribute(namespace, key);
125 }
126
127 if (oldValue == null || !oldValue.isEqual(predicate)) {
128 module.setPredicate(namespace, key, predicate);
129 fireAttributeSetListener(moduleId, namespace, key, oldValue,
130 predicate);
131 propagateToParents(moduleId);
132 }
133 }
134
135 private void fireAttributeSetListener(ModuleId id, ATerm namespace,
136 ATerm key, ATerm oldValue, ATerm newValue) {
137 listener.attributeSet(id, namespace, key, oldValue, newValue);
138 }
139
140 private void propagateToParents(ModuleId id) {
141 Set<ModuleId> parents = getParents(id);
142 for (Iterator<ModuleId> iter = parents.iterator(); iter.hasNext();) {
143 triggerAllAttributeUpdateRules(iter.next());
144 }
145 }
146
147 private void propagate(AttributeUpdateRule rule, ModuleId id) {
148 Module module = modules.get(id);
149 ATerm namespace = rule.getNamespace();
150 ATerm key = rule.getKey();
151
152 ATerm oldPredicate = module.getPredicate(namespace, key);
153 ATerm newPredicate = rule.getPredicateValue();
154
155 ATerm oldValue = module.getAttribute(namespace, key);
156
157 ATerm formula = rule.getFormula();
158 boolean result = innermostRuleEvaluation(formula, id);
159
160 if (result) {
161 updatePredicate(id, namespace, key, newPredicate);
162 } else {
163 /* Fall back to attribute value by removing predicate */
164 if (oldPredicate != null && newPredicate.equals(oldPredicate)) {
165 module.deletePredicate(namespace, key);
166 fireAttributeSetListener(id, namespace, key, oldPredicate,
167 oldValue);
168 propagateToParents(id);
169 }
170 }
171 }
172
173 public ATerm getModuleAttribute(ModuleId moduleId, ATerm namespace,
174 ATerm key) {
175 Module module = modules.get(moduleId);
176
177 if (module == null) {
178 System.err.println("MM - getModuleAttribute: module [" + moduleId
179 + "] doesn't exist");
180 return null;
181 }
182
183 ATerm value = module.getPredicate(namespace, key);
184 if (value == null) {
185 value = module.getAttribute(namespace, key);
186 }
187
188 return value;
189 }
190
191 public ModuleId getModuleIdByAttribute(ATerm namespace, ATerm key,
192 ATerm value) {
193 for (Iterator<ModuleId> iter = modules.keySet().iterator(); iter
194 .hasNext();) {
195 ModuleId moduleId = iter.next();
196 Module module = modules.get(moduleId);
197
198 if (value.equals(module.getPredicate(namespace, key))) {
199 return moduleId;
200 } else if (value.equals(module.getAttribute(namespace, key))) {
201 return moduleId;
202 }
203 }
204
205 return null;
206 }
207
208 public Set<ModuleId> getAllModules() {
209 Set<ModuleId> allModules = new HashSet<ModuleId>();
210
211 for (Iterator<ModuleId> iter = modules.keySet().iterator(); iter
212 .hasNext();) {
213 allModules.add(iter.next());
214 }
215
216 return allModules;
217 }
218
219 public void deleteModuleAttribute(ModuleId moduleId, ATerm namespace,
220 ATerm key) {
221 Module module = modules.get(moduleId);
222
223 if (module == null) {
224 System.err.println("MM - deleteModuleAttribute: module ["
225 + moduleId + "] doesn't exist");
226 return;
227 }
228
229 module.deleteAttribute(namespace, key);
230 }
231
232 public AttributeStore getAllAttributes(ModuleId moduleId) {
233 Module module = modules.get(moduleId);
234
235 if (module == null) {
236 throw new IllegalArgumentException(
237 "MM - getAllAttributes: module [" + moduleId
238 + "] doesn't exist");
239 }
240
241 return module.getAttributes();
242 }
243
244 public void addDependency(ModuleId moduleFromId, ModuleId moduleToId) {
245 Set<ModuleId> dependencies;
246 Module moduleFrom = modules.get(moduleFromId);
247 Module moduleTo = modules.get(moduleToId);
248
249 if (moduleFrom == null) {
250 System.err.println("MM - addDependency: module [" + moduleFromId
251 + "] doesn't exist");
252 return;
253 }
254
255 if (moduleTo == null) {
256 System.err.println("MM - addDependency: module [" + moduleToId
257 + "] doesn't exist");
258 return;
259 }
260
261 dependencies = descendants.get(moduleFromId);
262 dependencies.add(moduleToId);
263
264 dependencies = ascendants.get(moduleToId);
265 dependencies.add(moduleFromId);
266
267 transDescendants = new HashMap<ModuleId, Set<ModuleId>>();
268 }
269
270 public Set<ModuleId> getChildren(ModuleId moduleId) {
271 return descendants.get(moduleId);
272 }
273
274 public Set<ModuleId> getAllChildren(ModuleId moduleId) {
275 Set<ModuleId> dependencies = transDescendants.get(moduleId);
276
277 if (dependencies == null) {
278 dependencies = new HashSet<ModuleId>();
279 LinkedList<ModuleId> temp = new LinkedList<ModuleId>();
280
281 temp.addAll(getChildren(moduleId));
282
283 while (!temp.isEmpty()) {
284 ModuleId tempId = temp.getFirst();
285 if (!dependencies.contains(tempId)) {
286 dependencies.add(tempId);
287 temp.addAll(getChildren(tempId));
288 }
289 temp.removeFirst();
290 }
291
292 transDescendants.put(moduleId, dependencies);
293 }
294
295 return dependencies;
296 }
297
298 public Set<ModuleId> getParents(ModuleId moduleId) {
299 return ascendants.get(moduleId);
300 }
301
302 public Set<ModuleId> getAllParents(ModuleId moduleId) {
303 Set<ModuleId> dependencies = new HashSet<ModuleId>();
304 LinkedList<ModuleId> temp = new LinkedList<ModuleId>();
305
306 temp.addAll(getParents(moduleId));
307
308 while (!temp.isEmpty()) {
309 ModuleId tempId = temp.getFirst();
310 if (!dependencies.contains(tempId)) {
311 dependencies.add(tempId);
312 temp.addAll(getParents(tempId));
313 }
314 temp.removeFirst();
315 }
316
317 return dependencies;
318 }
319
320 public Set<ModuleId> getClosableModules(ModuleId moduleId) {
321 Set<ModuleId> dependencies = getAllChildren(moduleId);
322 LinkedList<ModuleId> temp = new LinkedList<ModuleId>();
323
324 dependencies.add(moduleId);
325 temp.addAll(dependencies);
326
327 while (!temp.isEmpty()) {
328 ModuleId tempId = temp.getFirst();
329 Set<ModuleId> parents = getParents(tempId);
330
331 if (!dependencies.containsAll(parents)) {
332 Set<ModuleId> children = getAllChildren(tempId);
333 dependencies.removeAll(children);
334 dependencies.remove(tempId);
335 }
336
337 temp.removeFirst();
338 }
339
340 return dependencies;
341 }
342
343 public void deleteDependency(ModuleId moduleFromId, ModuleId moduleToId) {
344 LinkedList<ModuleId> deps;
345 Module moduleFrom = modules.get(moduleFromId);
346
347 if (moduleFrom == null) {
348 System.err.println("MM - deleteDependency: module [" + moduleFromId
349 + "] doesn't exist");
350 return;
351 }
352
353 Module moduleTo = modules.get(moduleToId);
354
355 if (moduleTo == null) {
356 System.err.println("MM - deleteDependency: module [" + moduleToId
357 + "] doesn't exist");
358 return;
359 }
360
361 deps = new LinkedList<ModuleId>(descendants.get(moduleFromId));
362 deps.remove(moduleToId);
363
364 deps = new LinkedList<ModuleId>(ascendants.get(moduleToId));
365 deps.remove(moduleFromId);
366
367 transDescendants = new HashMap<ModuleId, Set<ModuleId>>();
368 }
369
370 public void deleteDependencies(ModuleId moduleId) {
371 Set<ModuleId> dependencies;
372
373 Module module = modules.get(moduleId);
374
375 if (module == null) {
376 System.err.println("MM - deleteDependencies: module [" + moduleId
377 + "] doesn't exist");
378 return;
379 }
380
381 for (Iterator<ModuleId> iter = modules.keySet().iterator(); iter
382 .hasNext();) {
383 ModuleId tempId = iter.next();
384 dependencies = getParents(tempId);
385 if (dependencies.contains(moduleId)) {
386 dependencies.remove(moduleId);
387 }
388 }
389
390 dependencies = descendants.get(moduleId);
391 dependencies.clear();
392 }
393
394 private void deleteAllDependencies(ModuleId moduleId) {
395 deleteDependencies(moduleId);
396
397 for (Iterator<ModuleId> iter = modules.keySet().iterator(); iter
398 .hasNext();) {
399 Set<ModuleId> dependencies = getChildren(iter.next());
400 if (dependencies.contains(moduleId)) {
401 dependencies.remove(moduleId);
402 }
403 }
404 }
405
406 public Map<ModuleId, Set<ModuleId>> getDependencies() {
407 return descendants;
408 }
409
410 public void printStatistics() {
411 int sumDeps = 0;
412 for (Iterator<Set<ModuleId>> iter = descendants.values().iterator(); iter
413 .hasNext();) {
414 sumDeps += iter.next().size();
415 }
416 System.err.println(modules.size() + " modules");
417 System.err.println(sumDeps + " dependencies");
418 }
419
420 public void registerAttributeUpdateRule(ATerm namespace, ATerm key,
421 ATerm rule, ATerm value) {
422 for (Iterator<AttributeUpdateRule> iter = attributeUpdateRules
423 .iterator(); iter.hasNext();) {
424 AttributeUpdateRule check = iter.next();
425 if (checkRuleViolation(check.getNamespace(), check.getKey(), check
426 .getPredicateValue(), rule)) {
427 System.err.println("Rule " + rule + " violates " + check);
428 return;
429 }
430 }
431 attributeUpdateRules.put(namespace, key, rule, value);
432 triggerAllAttributeUpdateRulesOnAllModules();
433 }
434
435 private boolean checkRuleViolation(ATerm namespace, ATerm key,
436 ATerm predicate, ATerm rule) {
437 if (((ATermAppl) rule).getAFun().equals(modalSET)) {
438 return (rule.getChildAt(0).equals(namespace)
439 && rule.getChildAt(1).equals(key) && rule.getChildAt(2)
440 .equals(predicate));
441 }
442
443 boolean violation = false;
444 for (int i = 0; i < rule.getChildCount(); i++) {
445 violation = violation
446 || checkRuleViolation(namespace, key, predicate,
447 (ATerm) rule.getChildAt(i));
448 }
449 return violation;
450 }
451
452 private boolean innermostRuleEvaluation(ATerm rule, ModuleId id) {
453 if (((ATermAppl) rule).getAFun().equals(modalAND)) {
454 return evaluateAnd((ATerm) rule.getChildAt(0), (ATerm) rule
455 .getChildAt(1), id);
456 }
457 if (((ATermAppl) rule).getAFun().equals(modalOR)) {
458 return evaluateOr((ATerm) rule.getChildAt(0), (ATerm) rule
459 .getChildAt(1), id);
460 }
461 if (((ATermAppl) rule).getAFun().equals(modalNOT)) {
462 return evaluateNot((ATerm) rule.getChildAt(0), id);
463 }
464 if (((ATermAppl) rule).getAFun().equals(modalONE)) {
465 return evaluateOne((ATerm) rule.getChildAt(0), id);
466 }
467 if (((ATermAppl) rule).getAFun().equals(modalALL)) {
468 return evaluateAll((ATerm) rule.getChildAt(0), id);
469 }
470 if (((ATermAppl) rule).getAFun().equals(modalSET)) {
471 return evaluateSet((ATerm) rule.getChildAt(2), id, (ATerm) rule
472 .getChildAt(0), (ATerm) rule.getChildAt(1));
473 }
474
475 System.err.println("Error evaluating attribute update rule [" + rule
476 + "]; forgot set?");
477 return false;
478 }
479
480 private boolean evaluateAnd(ATerm op1, ATerm op2, ModuleId id) {
481 return (innermostRuleEvaluation(op1, id) && innermostRuleEvaluation(
482 op2, id));
483 }
484
485 private boolean evaluateOr(ATerm op1, ATerm op2, ModuleId id) {
486 return (innermostRuleEvaluation(op1, id) || innermostRuleEvaluation(
487 op2, id));
488 }
489
490 private boolean evaluateNot(ATerm op, ModuleId id) {
491 return !(innermostRuleEvaluation(op, id));
492 }
493
494 private boolean evaluateOne(ATerm op, ModuleId id) {
495 boolean result = false;
496 Set<ModuleId> children = getAllChildren(id);
497 Iterator<ModuleId> iter = children.iterator();
498
499 while (iter.hasNext() && result == false) {
500 ModuleId childId = iter.next();
501 result = innermostRuleEvaluation(op, childId);
502 }
503
504 return result;
505 }
506
507 private boolean evaluateAll(ATerm op, ModuleId id) {
508 boolean result = true;
509 Set<ModuleId> children = getAllChildren(id);
510 Iterator<ModuleId> iter = children.iterator();
511
512 while (iter.hasNext() && result == true) {
513 ModuleId childId = iter.next();
514 result = innermostRuleEvaluation(op, childId);
515 }
516
517 return result;
518 }
519
520 private boolean evaluateSet(ATerm op, ModuleId id, ATerm namespace,
521 ATerm key) {
522 ATerm value = modules.get(id).getAttribute(namespace, key);
523
524 return op.equals(value);
525 }
526 }