View Javadoc
1 package org.drools.reteoo.impl; 2 3 /* 4 $Id: JoinMemoryImpl.java,v 1.4 2002/08/27 23:31:08 bob Exp $ 5 6 Copyright 2002 (C) The Werken Company. All Rights Reserved. 7 8 Redistribution and use of this software and associated documentation 9 ("Software"), with or without modification, are permitted provided 10 that the following conditions are met: 11 12 1. Redistributions of source code must retain copyright 13 statements and notices. Redistributions must also contain a 14 copy of this document. 15 16 2. Redistributions in binary form must reproduce the 17 above copyright notice, this list of conditions and the 18 following disclaimer in the documentation and/or other 19 materials provided with the distribution. 20 21 3. The name "drools" must not be used to endorse or promote 22 products derived from this Software without prior written 23 permission of The Werken Company. For written permission, 24 please contact bob@werken.com. 25 26 4. Products derived from this Software may not be called "drools" 27 nor may "drools" appear in their names without prior written 28 permission of The Werken Company. "drools" is a registered 29 trademark of The Werken Company. 30 31 5. Due credit should be given to The Werken Company. 32 (http://drools.werken.com/). 33 34 THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS 35 ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT 36 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 37 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 38 THE WERKEN COMPANY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 39 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 40 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 41 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 42 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 43 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 44 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 45 OF THE POSSIBILITY OF SUCH DAMAGE. 46 47 */ 48 49 import org.drools.WorkingMemory; 50 import org.drools.FactException; 51 import org.drools.reteoo.JoinMemory; 52 import org.drools.rule.Declaration; 53 54 import java.util.Set; 55 import java.util.HashSet; 56 import java.util.Iterator; 57 import java.util.Collections; 58 59 /*** Memory for left and right inputs of a <code>JoinNode</code>. 60 * 61 * @see JoinMemory 62 * @see JoinNodeImpl 63 * @see ReteTuple 64 * 65 * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a> 66 */ 67 public class JoinMemoryImpl implements JoinMemory 68 { 69 // ------------------------------------------------------------ 70 // Instance members 71 // ------------------------------------------------------------ 72 73 /*** Left-side tuples. */ 74 private TupleSet leftTuples; 75 76 /*** Right-side tuples. */ 77 private TupleSet rightTuples; 78 79 /*** Join column declarations. */ 80 private Set joinDeclarations; 81 82 // ------------------------------------------------------------ 83 // Constructors 84 // ------------------------------------------------------------ 85 86 /*** Construct. 87 * 88 * @param node The <code>JoinNode</code> this memory 89 * is for. 90 */ 91 public JoinMemoryImpl(JoinNodeImpl node) 92 { 93 this.leftTuples = new TupleSet(); 94 this.rightTuples = new TupleSet(); 95 96 this.joinDeclarations = node.getCommonDeclarations(); 97 } 98 99 // ------------------------------------------------------------ 100 // Instance methods 101 // ------------------------------------------------------------ 102 103 /*** Retract an object from this memory. 104 * 105 * @param object The object to retract. 106 */ 107 protected void retractObject(Object object) 108 { 109 try 110 { 111 ReteTuple eachTuple = null; 112 113 Iterator tupleIter = leftTuples.iterator(); 114 115 while ( tupleIter.hasNext() ) 116 { 117 eachTuple = (ReteTuple) tupleIter.next(); 118 119 if ( eachTuple.dependsOn( object ) ) 120 { 121 tupleIter.remove(); 122 } 123 } 124 125 tupleIter = rightTuples.iterator(); 126 127 while ( tupleIter.hasNext() ) 128 { 129 eachTuple = (ReteTuple) tupleIter.next(); 130 131 if ( eachTuple.dependsOn( object ) ) 132 { 133 tupleIter.remove(); 134 } 135 } 136 } 137 catch (Exception e) 138 { 139 e.printStackTrace(); 140 } 141 } 142 143 /*** Retract tuples from this memory. 144 * 145 * @param keys The keys for the tuples to be removed. 146 */ 147 protected void retractTuples(Set keys) 148 { 149 Iterator keyIter = keys.iterator(); 150 TupleKey eachKey = null; 151 152 while ( keyIter.hasNext() ) 153 { 154 eachKey = (TupleKey) keyIter.next(); 155 156 retractTuples( eachKey ); 157 } 158 } 159 160 /*** Retract tuples from this memory. 161 * 162 * @param key The key for the tuples to be removed. 163 */ 164 protected void retractTuples(TupleKey key) 165 { 166 retractTuples( key, 167 getLeftTuples().iterator() ); 168 169 retractTuples( key, 170 getRightTuples().iterator() ); 171 } 172 173 /*** Retract tuples from this memory. 174 * 175 * @param key The key for the tuples to be removed. 176 * @param tupleIter Iterator of tuples to be removed. 177 */ 178 private void retractTuples(TupleKey key, 179 Iterator tupleIter) 180 { 181 ReteTuple eachTuple = null; 182 183 while ( tupleIter.hasNext() ) 184 { 185 eachTuple = (ReteTuple) tupleIter.next(); 186 187 if ( eachTuple.getKey().containsAll( key ) ) 188 { 189 tupleIter.remove(); 190 } 191 } 192 } 193 194 /*** Modify tuples on the left-side. 195 * 196 * @param trigger Triggering object. 197 * @param newTuples Modification replacement tuples. 198 * @param joinNode This memory's join node. 199 * @param workingMemory The working memory session. 200 * 201 * @throws FactException if an error occurs during modification. 202 */ 203 protected void modifyLeftTuples(Object trigger, 204 TupleSet newTuples, 205 JoinNodeImpl joinNode, 206 WorkingMemory workingMemory) throws FactException 207 { 208 modifyTuples( trigger, 209 newTuples, 210 getLeftTuples(), 211 getRightTuples(), 212 joinNode, 213 workingMemory ); 214 } 215 216 /*** Modify tuples on the right-side. 217 * 218 * @param trigger Triggering object. 219 * @param newTuples Modification replacement tuples. 220 * @param joinNode This memory's join node. 221 * @param workingMemory The working memory session. 222 * 223 * @throws FactException if an error occurs during modification. 224 */ 225 protected void modifyRightTuples(Object trigger, 226 TupleSet newTuples, 227 JoinNodeImpl joinNode, 228 WorkingMemory workingMemory) throws FactException 229 { 230 modifyTuples( trigger, 231 newTuples, 232 getRightTuples(), 233 getLeftTuples(), 234 joinNode, 235 workingMemory ); 236 } 237 238 /*** Modify tuples 239 * 240 * @param trigger Triggering object. 241 * @param newTuples Modification replacement tuples. 242 * @param thisSideTuples The tuples on the side that's receiving 243 * the modifications. 244 * @param thatSideTuples The tuples on the side that's <b>not</b> 245 * receiving the modifications. 246 * @param joinNode This memory's join node. 247 * @param workingMemory The working memory session. 248 * 249 * @throws FactException if an error occurs during modification. 250 */ 251 protected void modifyTuples(Object trigger, 252 TupleSet newTuples, 253 TupleSet thisSideTuples, 254 TupleSet thatSideTuples, 255 JoinNodeImpl joinNode, 256 WorkingMemory workingMemory) throws FactException 257 { 258 Set retractedKeys = new HashSet(); 259 260 Set origModified = new HashSet(); 261 Set newModified = new HashSet(); 262 263 ReteTuple origTuple = null; 264 ReteTuple newTuple = null; 265 266 Iterator tupleIter = thisSideTuples.iterator(); 267 268 while ( tupleIter.hasNext() ) 269 { 270 origTuple = (ReteTuple) tupleIter.next(); 271 272 if ( origTuple.dependsOn( trigger ) ) 273 { 274 newTuple = newTuples.getTuple( origTuple.getKey() ); 275 276 if ( newTuple == null ) 277 { 278 retractedKeys.add( origTuple.getKey() ); 279 } 280 else 281 { 282 newModified.add( newTuple ); 283 origModified.add( origTuple ); 284 } 285 } 286 } 287 288 newModified.addAll( newTuples.getTuples() ); 289 290 ReteTuple eachTuple = null; 291 292 TupleSet origJoined = new TupleSet(); 293 294 tupleIter = origModified.iterator(); 295 296 while ( tupleIter.hasNext() ) 297 { 298 eachTuple = (ReteTuple) tupleIter.next(); 299 300 origJoined.addAllTuples( attemptJoin( eachTuple, 301 thatSideTuples.iterator() ) ); 302 } 303 304 TupleSet newJoined = new TupleSet(); 305 306 tupleIter = newModified.iterator(); 307 308 while ( tupleIter.hasNext() ) 309 { 310 eachTuple = (ReteTuple) tupleIter.next(); 311 312 newJoined.addAllTuples( attemptJoin( eachTuple, 313 thatSideTuples.iterator() ) ); 314 } 315 316 tupleIter = origJoined.iterator(); 317 318 while ( tupleIter.hasNext() ) 319 { 320 eachTuple = (ReteTuple) tupleIter.next(); 321 322 if ( ! newJoined.containsTuple( eachTuple.getKey() ) ) 323 { 324 retractedKeys.add( eachTuple.getKey() ); 325 } 326 } 327 328 thisSideTuples.addAllTuples( newTuples ); 329 330 propagateRetractTuples( trigger, 331 retractedKeys, 332 joinNode, 333 workingMemory ); 334 335 joinNode.propagateModifyTuples( trigger, 336 newJoined, 337 workingMemory ); 338 } 339 340 /*** Propagate retractions. 341 * 342 * @param trigger The retracted trigger object. 343 * @param retractedKeys Keys to the retracted tuples. 344 * @param joinNode This memory's join node. 345 * @param workingMemory The working memory session. 346 * 347 * @throws FactException if an error occurs during modification. 348 */ 349 private void propagateRetractTuples(Object trigger, 350 Set retractedKeys, 351 JoinNodeImpl joinNode, 352 WorkingMemory workingMemory) throws FactException 353 { 354 Iterator keyIter = retractedKeys.iterator(); 355 TupleKey eachKey = null; 356 357 while ( keyIter.hasNext() ) 358 { 359 eachKey = (TupleKey) keyIter.next(); 360 361 joinNode.propagateRetractTuples( eachKey, 362 workingMemory ); 363 } 364 365 } 366 367 /*** Add a <code>ReteTuple</code> received from the <code>JoinNode's</code> 368 * left input to the left side of this memory, and attempt 369 * to join to existing <code>Tuples</code> in the right 370 * side. 371 * 372 * @see JoinNodeImpl 373 * @see ReteTuple 374 * 375 * @param tuple The <code>Tuple</code> to add to the left 376 * side memory. 377 * 378 * @return A <code>List</code> of <code>Tuples</code> successfully 379 * created by joining the incoming <code>tuple</code> 380 * against existing <code>Tuples</code> on the right 381 * side memory. 382 */ 383 protected Set addLeftTuple(ReteTuple tuple) 384 { 385 this.leftTuples.addTuple( tuple ); 386 387 388 Set joined = attemptJoin( tuple, 389 getRightTupleIterator() ); 390 391 return joined; 392 } 393 394 /*** Retrieve the <code>List</code> of <code>Tuples</code> 395 * held in the left side memory. 396 * 397 * @return The <code>List</code> of <code>Tuples</code> 398 * help in the left side memory. 399 */ 400 protected TupleSet getLeftTuples() 401 { 402 return this.leftTuples; 403 } 404 405 /*** Retrieve an <code>Iterator</code> over the <code>Tuples</code> 406 * held in the left side memory. 407 * 408 * @return An <code>Iterator</code> over the <code>Tuples</code> 409 * help in the left side memory. 410 */ 411 protected Iterator getLeftTupleIterator() 412 { 413 return this.leftTuples.iterator(); 414 } 415 416 /*** Add a <code>ReteTuple</code> received from the <code>JoinNode's</code> 417 * right input to the right side of this memory, and attempt 418 * to join to existing <code>Tuples</code> in the left 419 * side. 420 * 421 * @see JoinNodeImpl 422 * @see ReteTuple 423 * 424 * @param tuple The <code>Tuple</code> to add to the right 425 * side memory. 426 * 427 * @return A <code>List</code> of <code>Tuples</code> successfully 428 * created by joining the incoming <code>tuple</code> 429 * against existing <code>Tuples</code> on the left 430 * side memory. 431 */ 432 protected Set addRightTuple(ReteTuple tuple) 433 { 434 this.rightTuples.addTuple( tuple ); 435 436 return attemptJoin( tuple, 437 getLeftTupleIterator() ); 438 } 439 440 /*** Retrieve the <code>List</code> of <code>Tuples</code> 441 * held in the right side memory. 442 * 443 * @return The <code>List</code> of <code>Tuples</code> 444 * help in the right side memory. 445 */ 446 protected TupleSet getRightTuples() 447 { 448 return this.rightTuples; 449 } 450 451 /*** Retrieve an <code>Iterator</code> over the <code>Tuples</code> 452 * held in the right side memory. 453 * 454 * @return An <code>Iterator</code> over the <code>Tuples</code> 455 * help in the right side memory. 456 */ 457 protected Iterator getRightTupleIterator() 458 { 459 return this.rightTuples.iterator(); 460 } 461 462 /*** Retrieve an <code>Iterator</code> over the common 463 * <code>Declarations</code> used to join <code>Tuples</code> 464 * from the left and right side memories. 465 * 466 * @return An <code>Iterator</code> of common join 467 * <code>Declarations</code>. 468 */ 469 protected Iterator getJoinDeclarationIterator() 470 { 471 return this.joinDeclarations.iterator(); 472 } 473 474 /*** Attempt to join the <code>tuple</code> against the 475 * tuples available through the <code>tupleIterator</code>. 476 * 477 * @param tuple The <code>Tuple</code> to attempt joining. 478 * @param tupleIter The <code>Iterator</code> over 479 * <code>Tuples</code> to attempt joining to the 480 * <code>tuple</code> parameter. 481 * 482 * @return A possibly empty <code>List</code> of joined 483 * <code>Tuples</code>. 484 */ 485 protected Set attemptJoin(ReteTuple tuple, 486 Iterator tupleIter) 487 { 488 Set joinedTuples = Collections.EMPTY_SET; 489 490 ReteTuple eachTuple = null; 491 ReteTuple joinedTuple = null; 492 493 while ( tupleIter.hasNext() ) 494 { 495 eachTuple = (ReteTuple) tupleIter.next(); 496 497 joinedTuple = attemptJoin( tuple, 498 eachTuple ); 499 500 if ( joinedTuple != null ) 501 { 502 if ( joinedTuples == Collections.EMPTY_SET ) 503 { 504 joinedTuples = new HashSet(); 505 } 506 507 joinedTuples.add( joinedTuple ); 508 } 509 } 510 511 return joinedTuples; 512 } 513 514 /*** Attempt to join two <code>Tuples</code>. 515 * 516 * @param left The left-side <code>Tuple</code>. 517 * @param right The right-side <code>Tuple</code>. 518 * 519 * @return A newly joined <code>Tuple</code> if a join 520 * is possible, else <code>null</code>. 521 */ 522 protected ReteTuple attemptJoin(ReteTuple left, 523 ReteTuple right) 524 { 525 526 Iterator declIter = getJoinDeclarationIterator(); 527 Declaration eachDecl = null; 528 529 Object leftValue = null; 530 Object rightValue = null; 531 532 while ( declIter.hasNext() ) 533 { 534 535 eachDecl = (Declaration) declIter.next(); 536 537 leftValue = left.get( eachDecl ); 538 rightValue = right.get( eachDecl ); 539 540 if ( leftValue == null 541 && 542 rightValue == null ) 543 { 544 continue; 545 } 546 547 if ( leftValue == null 548 || 549 rightValue == null ) 550 { 551 return null; 552 } 553 554 if ( leftValue.equals( rightValue ) ) 555 { 556 continue; 557 } 558 else 559 { 560 return null; 561 } 562 } 563 564 ReteTuple joinedTuple = new JoinTuple( left, 565 right ); 566 567 return joinedTuple; 568 569 } 570 571 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 572 // java.lang.Object 573 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 574 575 /*** Produce debug string. 576 * 577 * @return The debug string. 578 */ 579 public String toString() 580 { 581 return "[JoinMemory \n\tleft=" + this.leftTuples + "\n\tright=" + this.rightTuples + "]"; 582 } 583 584 }

This page was automatically generated by Maven