1 17 18 package SOFA.SOFAnode.Util.DFSRChecker.node; 19 20 import java.util.HashMap ; 21 import java.util.LinkedList ; 22 import java.util.TreeSet ; 23 import java.util.ArrayList ; 24 import java.util.TreeMap ; 25 import java.util.Iterator ; 26 27 28 import SOFA.SOFAnode.Util.DFSRChecker.DFSR.BadActivityException; 29 import SOFA.SOFAnode.Util.DFSRChecker.DFSR.CheckingException; 30 import SOFA.SOFAnode.Util.DFSRChecker.DFSR.NoActivityException; 31 import SOFA.SOFAnode.Util.DFSRChecker.DFSR.Options; 32 import SOFA.SOFAnode.Util.DFSRChecker.state.CompositeState; 33 import SOFA.SOFAnode.Util.DFSRChecker.state.State; 34 import SOFA.SOFAnode.Util.DFSRChecker.state.TransitionPair; 35 import SOFA.SOFAnode.Util.DFSRChecker.state.TransitionPairs; 36 import SOFA.SOFAnode.Util.DFSRChecker.state.TransitionPairs.IntPair; 37 import SOFA.SOFAnode.Util.DFSRChecker.utils.AnotatedProtocol; 38 39 42 public class ConsentNode extends TreeNode { 43 44 62 public ConsentNode(TreeNode node1, TreeNode node2, TreeSet events, 63 TreeSet unboundEvents, ActionRepository repository, boolean test) { 64 super("(" + node1.protocol + ")%(" + node2.protocol + ")"); 65 66 this.events = events; 67 this.unboundEvents = unboundEvents; 68 this.repository = repository; 69 this.topmost = true; 70 this.test = test; 71 72 this.nodes = new TreeNode[2]; 73 this.nodes[0] = node1; 74 this.nodes[1] = node2; 75 76 if (node1 instanceof ConsentNode) 78 ((ConsentNode) node1).topmost = false; 79 80 if (node2 instanceof ConsentNode) 81 ((ConsentNode) node2).topmost = false; 82 83 this.boundEvents = new TreeSet (); 84 this.boundAtomicActions = new boolean[2][]; 85 this.dependecies = new LinkedList [2]; 86 this.delayed = new HashMap (); 87 } 88 89 92 public long getWeight() { 93 if (weight != -1) 94 return weight; 95 else { 96 long w1 = nodes[0].getWeight(), w2 = nodes[1].getWeight(); 98 return weight = (long) (0.5f * w1 * w2 + 0.25f * ((w1 + w2) / 2)); 99 } 100 } 101 102 105 public State getInitial() { 106 State[] states = new State[2]; 107 states[0] = nodes[0].getInitial(); 108 states[1] = nodes[1].getInitial(); 109 110 return new CompositeState(states); 111 } 112 113 116 public boolean isAccepting(State state) { 117 CompositeState cstate = (CompositeState) state; 118 119 return (nodes[0].isAccepting(cstate.states[0])) && (nodes[1].isAccepting(cstate.states[1])); 120 } 121 122 125 public TransitionPairs getTransitions(State state) throws InvalidParameterException, CheckingException { 126 CompositeState cstate = (CompositeState) state; 127 delayed.clear(); 128 129 TransitionPairs transp1 = nodes[0].getTransitions(cstate.states[0]); 130 TransitionPairs transp2 = nodes[1].getTransitions(cstate.states[1]); 131 132 TransitionPair[] trans1 = transp1.transitions; 133 TransitionPair[] trans2 = transp2.transitions; 134 135 currentdeps = new LinkedList (); 136 dependecies[0] = transp1.deps; 137 dependecies[1] = transp2.deps; 138 139 ArrayList result = new ArrayList (); 140 TreeMap sync = new TreeMap (); 141 this.boundAtomicActions[0] = new boolean[trans1.length]; 142 this.boundAtomicActions[1] = new boolean[trans2.length]; 143 144 for (int i = 0; i < trans1.length; ++i) { 147 Integer key = new Integer (trans1[i].eventIndex); 148 149 if (key.intValue() < 0) { 150 if (makeAtomicTransition(i, trans1, trans2, cstate, result, 0)) 152 boundAtomicActions[0][i] = true; 153 } 154 155 else if (events.contains(new Integer (ActionRepository.getPure(trans1[i].eventIndex)))) { 156 164 165 sync.put(new Integer (trans1[i].eventIndex), trans1[i]); 166 167 168 for (Iterator it = currentdeps.iterator(); it.hasNext(); ) { 169 IntPair item = (IntPair)it.next(); 170 171 if (item.second == trans1[i].eventIndex) 172 it.remove(); 173 } 174 175 delayed.put(key, null); 176 } 177 178 else if (topmost && unboundEvents.contains(new Integer (ActionRepository.getPure(trans1[i].eventIndex)))) { 180 boolean isResponse = repository.isResponse(trans1[i].eventIndex); 181 if ((Options.badactivity) && (test) && (!isResponse)) 182 throw new BadActivityException("missing binding for request '" + repository.getItemString(trans2[i].eventIndex) + "':"); 183 } 184 185 else { 187 State[] states = new State[2]; 188 states[0] = trans1[i].state; 189 states[1] = cstate.states[1]; 190 191 result.add(new TransitionPair(trans1[i].eventIndex, new CompositeState(states))); 192 } 193 } 194 195 boundEvents.clear(); 196 boundEvents.addAll(sync.keySet()); 197 198 for (int i = 0; i < trans2.length; ++i) { 200 Integer key = new Integer (trans2[i].eventIndex); 201 if (key.intValue() < 0) { 202 if (!boundAtomicActions[1][i]) 204 makeAtomicTransition(i, trans2, trans1, cstate, result, 1); 205 } 206 207 else if (events.contains(new Integer (ActionRepository.getPure(trans2[i].eventIndex)))) { 208 Integer invkey = new Integer (repository.getInverseAction(trans2[i].eventIndex)); 209 if (sync.containsKey(invkey)) { 210 223 224 State[] states = new State[2]; 225 states[0] = ((TransitionPair) sync.get(invkey)).state; 226 states[1] = trans2[i].state; 227 228 result.add(new TransitionPair(repository.getTauAction(trans2[i].eventIndex), new CompositeState(states))); 229 230 231 for (Iterator it = currentdeps.iterator(); it.hasNext(); ) { 232 IntPair item = (IntPair)it.next(); 233 234 if (item.second == trans2[i].eventIndex) 235 it.remove(); 236 } 237 238 239 boundEvents.remove(invkey); 240 delayed.put(key, null); 241 } 242 243 else { boolean isResponse = repository.isResponse(trans2[i].eventIndex); 245 if ((Options.badactivity) && (test) && (!isResponse) && !boundAtomicActions[1][i] && (!unboundEvents.contains(new Integer (ActionRepository.getPure(trans2[i].eventIndex))))) 246 throw new BadActivityException("bad activity(" + repository.getItemString(trans2[i].eventIndex) + "):"); 247 else { 248 249 } 250 } 251 252 if (topmost && test && unboundEvents.contains(new Integer (ActionRepository.getPure(trans2[i].eventIndex))) && (!repository.isResponse(trans2[i].eventIndex))) { 254 throw new BadActivityException("missing binding for request '" + repository.getItemString(trans2[i].eventIndex) + "':"); 255 } 256 } 258 else if (topmost && unboundEvents.contains(new Integer (ActionRepository.getPure(trans2[i].eventIndex)))) { 260 boolean isResponse = repository.isResponse(trans2[i].eventIndex); 261 if ((Options.badactivity) && (test) && (!isResponse)) 262 throw new BadActivityException("missing binding for request '" + repository.getItemString(trans2[i].eventIndex) + "':"); 263 } 264 265 else { 267 State[] states = new State[2]; 268 states[0] = cstate.states[0]; 269 states[1] = trans2[i].state; 270 271 result.add(new TransitionPair(trans2[i].eventIndex, new CompositeState(states))); 272 } 273 } 274 275 Iterator it = boundEvents.iterator(); 276 277 while (it.hasNext()) { 278 int action = ((Integer ) it.next()).intValue(); 279 if ((Options.badactivity) && (test) && (!repository.isResponse(action))) 280 throw new BadActivityException("bad activity (" + repository.getItemString(action) + "):"); 281 } 282 283 for (Iterator it2 = delayed.keySet().iterator(); it2.hasNext() ;) { 285 IntPair data = (IntPair)delayed.get(it2.next()); 286 if (data != null) 287 throw new BadActivityException("Bad activity (atomic action " + repository.getItemString(data.first) + " cannot accept " + repository.getItemString(repository.getInverseAction(data.second)) + "). Trace: "); 288 } 289 290 if (topmost) { 292 for (Iterator it3 = result.iterator(); it3.hasNext(); ) { 293 if (unboundEvents.contains(new Integer (ActionRepository.getPure(((TransitionPair)it3.next()).eventIndex)))) 294 it3.remove(); 295 } 296 } 297 298 TransitionPair[] result1 = new TransitionPair[result.size()]; 299 Iterator it2 = result.iterator(); 300 int i = 0; 301 302 while (it2.hasNext()) 303 result1[i++] = (TransitionPair) it2.next(); 304 305 if (result1.length == 0) { 307 if ((Options.noactivity) && (test) && (!this.isAccepting(state))) { 308 throw new NoActivityException("no activity:"); 309 } 310 } 311 312 if (topmost) { 313 for (int j = 0; j < result1.length; ++j) { 314 if (result1[j].eventIndex < 0) { for (Iterator itt = currentdeps.iterator(); itt.hasNext(); ) { 316 TransitionPairs.IntPair item = (IntPair) itt.next(); 317 if (item.first == result1[j].eventIndex) throw new BadActivityException("Atomic action " + repository.getItemString(item.first) + " raised a bad activity exception. Trace:"); 319 } 320 321 } 322 323 } 324 } 325 326 return new TransitionPairs(result1, currentdeps); 327 } 328 329 343 private boolean makeAtomicTransition(int index, TransitionPair[] first, 344 TransitionPair[] second, CompositeState starting, ArrayList result, 345 int tooglebit) throws BadActivityException { 346 347 LinkedList trans = makeTransition(index, first, second, starting, tooglebit); 348 349 if (trans.size() > 0) { 350 result.addAll(trans); 351 return true; 352 } else 353 return false; 354 } 355 356 369 private LinkedList makeTransition(int index, final TransitionPair[] first, final TransitionPair[] second, CompositeState starting, int tooglebit) throws BadActivityException { 370 int atomicactionindex = first[index].eventIndex; 371 final AtomicAction aaction = repository.getAtomicEvents(atomicactionindex); 372 AtomicAction synchroaction = new AtomicAction(); 373 LinkedList result = new LinkedList (); 374 LinkedList nosynchro = new LinkedList (); 375 boolean bound = false; 376 boolean boundsimple = false; 377 AtomicAction newaa = null; 378 379 Iterator it = aaction.iterator(); 380 381 while (it.hasNext()) { 382 Integer event = (Integer ) it.next(); 383 384 if (events.contains(new Integer (ActionRepository.getPure(event.intValue())))) 385 synchroaction.add(event); 386 else 387 nosynchro.add(event); 388 } 389 390 if (synchroaction.size() > 1) 393 throw new BadActivityException("Atomic action not well-formed (" + repository.getItemString(first[index].eventIndex) + ") - contains more than 1 simple action on a binding. Trace: "); 395 396 if (synchroaction.size() == 0) { 398 State[] states = new State[2]; 399 states[tooglebit] = first[index].state; 400 states[1 - tooglebit] = starting.states[1 - tooglebit]; 401 result.add(new TransitionPair(first[index].eventIndex, new CompositeState(states))); 402 403 for (Iterator it2 = dependecies[tooglebit].iterator(); it2.hasNext(); ) { 405 TransitionPairs.IntPair item = (TransitionPairs.IntPair)it2.next(); 406 if (item.first == first[index].eventIndex) 407 currentdeps.add(item); 408 } 409 return result; 410 } 411 412 else { 413 414 int synchroactionidx = ((Integer ) synchroaction.first()).intValue(); 415 416 for (int i = 0; i < second.length; ++i) { 417 if ((tooglebit == 1) && boundAtomicActions[0][i]) 418 continue; 419 420 if (second[i].eventIndex >= 0) { if (synchroactionidx == repository.getInverseAction(second[i].eventIndex)) { 423 newaa = new AtomicAction(aaction); 425 newaa.remove(new Integer (synchroactionidx)); 426 newaa.add(new Integer (repository.getTauAction(synchroactionidx))); 427 State[] states = new State[2]; 428 states[tooglebit] = first[index].state; 429 states[1 - tooglebit] = second[i].state; 430 result.add(new TransitionPair(repository.getItemIndex(newaa), new CompositeState(states))); 431 432 444 445 boundAtomicActions[1 - tooglebit][i] = true; 446 bound = true; 447 boundsimple = true; 448 } 449 450 else if (repository.isResponse(synchroactionidx)) { 451 currentdeps.add(new TransitionPairs.IntPair(first[index].eventIndex, second[i].eventIndex)); 454 } 455 456 } else { newaa = new AtomicAction(repository.getAtomicEvents(second[i].eventIndex)); 458 459 Iterator it2 = repository.getAtomicEvents(second[i].eventIndex).iterator(); 460 461 while (it2.hasNext()) { 462 Integer event = (Integer ) it2.next(); 463 AtomicAction bounding = new AtomicAction(repository.getAtomicEvents(event.intValue())); 464 boolean was = bounding.remove(new Integer (repository.getInverseAction(synchroactionidx))); 465 466 if (was) { 467 newaa.remove(new Integer (synchroactionidx)); 468 newaa.add(new Integer (repository.getTauAction(synchroactionidx))); 469 newaa.addAll(bounding); 470 State[] states = new State[2]; 471 states[tooglebit] = first[index].state; 472 states[1 - tooglebit] = second[i].state; 473 result.add(new TransitionPair(repository.getItemIndex(newaa), new CompositeState(states))); 474 bound = true; 475 boundAtomicActions[1 - tooglebit][i] = true; 476 477 494 495 break; } 497 } 498 } 499 } 500 501 if (!bound) { 502 if (repository.isResponse(synchroactionidx)) { 503 for (Iterator iterator = currentdeps.iterator(); iterator.hasNext() ;) { 504 TransitionPairs.IntPair item = (TransitionPairs.IntPair)iterator.next(); 505 506 if (item.first == first[index].eventIndex) { 507 if (repository.isResponse(item.second)) { 508 if (!delayed.containsKey(new Integer (item.second))) 509 delayed.put(new Integer (item.second), item); 510 511 } else { 513 iterator.remove(); 514 delayed.put(new Integer (item.second), null); 515 } 516 } 517 } 518 519 return result; 520 } 521 else { 523 for (Iterator it2 = dependecies[tooglebit].iterator(); it2.hasNext(); ) { 524 TransitionPairs.IntPair item = (TransitionPairs.IntPair)it2.next(); 525 if (item.first == first[index].eventIndex) { 526 item.first = repository.getItemIndex(newaa); currentdeps.add(item); 528 } 529 } 530 531 result.add(new TransitionPair(first[index].eventIndex, null)); 532 currentdeps.add(new TransitionPairs.IntPair(first[index].eventIndex, synchroactionidx)); 533 return result; 534 } 535 } 536 else 537 return result; 538 } 539 } 540 541 544 public String [] getTypeName() { 545 String [] result = { "Consent", "%" }; 546 return result; 547 } 548 549 553 public TreeNode forwardCut(TreeSet livingevents) { 554 TreeSet exlivev = new TreeSet (livingevents); 555 556 exlivev.addAll(events); 557 TreeSet exlivev2 = new TreeSet (exlivev); 558 559 nodes[0] = nodes[0].forwardCut(exlivev); 560 nodes[1] = nodes[1].forwardCut(exlivev2); 561 562 if (nodes[0] == null) 563 nodes[0] = new NullNode(); 564 565 if (nodes[1] == null) 566 nodes[1] = new NullNode(); 567 568 return this; 569 } 570 571 574 public AnotatedProtocol getAnotatedProtocol(State state) { 575 CompositeState cstate = (CompositeState) state; 576 int nodecnt = nodes.length; 577 String result = new String (); 578 ArrayList indicesresult = new ArrayList (); 579 580 for (int i = 0; i < nodecnt; ++i) { 581 AnotatedProtocol subresult = nodes[i].getAnotatedProtocol((cstate != null) ? cstate.states[i] : null); 582 583 for (int j = 0; j < subresult.indices.size(); ++j) 584 indicesresult.add(new Integer (((Integer ) subresult.indices.get(j)).intValue() + result.length())); 585 586 result += subresult.protocol; 587 588 if (i < nodecnt - 1) 589 result += " % "; 590 } 591 592 return new AnotatedProtocol(result, indicesresult); 593 } 594 595 597 600 final private TreeSet events; 601 602 605 final private TreeSet unboundEvents; 606 607 610 private ActionRepository repository; 611 612 616 private boolean topmost; 617 618 621 private boolean test; 622 623 626 private TreeSet boundEvents; 627 628 631 private boolean[][] boundAtomicActions; 632 633 636 private LinkedList [] dependecies; 637 638 641 private LinkedList currentdeps; 642 643 646 private HashMap delayed; 647 } | Popular Tags |