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 }