001 package sysModel.env; 002 003 import controller.IScrollAdapter; 004 import controller.IDisplayAdapter; 005 import junit.framework.TestCase; 006 import lrs.IAlgo; 007 import lrs.LRStruct; 008 import lrs.visitor.GetLength; 009 import lrs.visitor.Remove; 010 import model.ILambda; 011 import model.fish.GenericFish; 012 import sysModel.ICmdFactory; 013 import sysModel.ISecurityAdapter; 014 import sysModel.NoOpLambda; 015 import sysModel.fish.IFishFactory; 016 import sysModel.fish.AFish; 017 import sysModel.parser.Lexer; 018 019 import java.awt.*; 020 import java.awt.event.MouseEvent; 021 import java.util.LinkedList; 022 import java.io.PrintWriter; 023 024 /** 025 * Implementation of a square unbounded environment. 026 * 027 * @author Mathias G. Ricken 028 */ 029 public class UnboundedEnv extends ASquareEnv { 030 031 /** 032 * Concrete local environment for the square unbounded environment. 033 */ 034 protected class LocalEnvironment extends ASquareLocalEnvironment { 035 /** 036 * Location. 037 */ 038 protected Location _loc; 039 040 /** 041 * Direction. 042 */ 043 protected Direction _dir; 044 045 /** 046 * Lambda to execute a move. 047 */ 048 protected class MoveLambda implements ILambda { 049 /// target direction 050 protected Direction _newDir; 051 /// target location 052 protected Location _newLoc; 053 054 /** 055 * Constructor. 056 * 057 * @param le target local environment 058 */ 059 public MoveLambda(LocalEnvironment le) { 060 _newLoc = makeLocation(le._loc.getX(), le._loc.getY()); 061 _newDir = makeDirection(le._dir); 062 } 063 064 /** 065 * Execute the move. 066 * 067 * @param param not used 068 * @return null 069 */ 070 public Object apply(Object param) { 071 // execute the movement 072 _loc = _newLoc; 073 _dir = _newDir; 074 075 // deactivate all lambdas 076 deactivateMoveLambdas(); 077 return null; 078 } 079 } 080 081 /** 082 * Construct a new local environment. 083 * 084 * @param loc location 085 * @param dir direction 086 */ 087 public LocalEnvironment(Location loc, Direction dir) { 088 _loc = loc; 089 _dir = dir; 090 } 091 092 /** 093 * Accessor for the location. 094 * 095 * @return location 096 */ 097 public Location location() { 098 return _loc; 099 } 100 101 /** 102 * Accessor for the direction. 103 * 104 * @return direction 105 */ 106 public Direction direction() { 107 return _dir; 108 } 109 110 /** 111 * Make local environment in forward direction. Do not block yourself. 112 * 113 * @return new local environment in forward direction 114 */ 115 protected ALocalEnv makeMoveFwdLocalEnv() { 116 // remove this local environment to prevent collision with itself 117 _localEnvList.execute(Remove.Singleton, this); 118 ALocalEnv le = makeLocalEnv(_loc.getNeighbor(_dir), _dir); 119 // add this local environment back in 120 _localEnvList.insertFront(this); 121 return le; 122 } 123 124 /** 125 * Factory method for a move lambda. 126 * 127 * @param le local environment for the target 128 * @return move lambda to execute the move to the target 129 */ 130 protected ILambda makeMoveLambda(ALocalEnv le) { 131 return new MoveLambda((LocalEnvironment) le); 132 } 133 } 134 135 /** 136 * Size of the pan area. 137 */ 138 protected final int PAN_SIZE = 2000; 139 140 /** 141 * Center of the pan area. 142 */ 143 protected final Point.Double PAN_CENTER = new Point.Double(PAN_SIZE / 2, PAN_SIZE / 2); 144 145 /** 146 * List of local environments in this global environment. 147 */ 148 private LRStruct _localEnvList; 149 150 /** 151 * Construct a new square unbounded environment. 152 * 153 * @param cmdFactory command factory to use 154 * @param sm security manager to control fish actions 155 */ 156 public UnboundedEnv(ICmdFactory cmdFactory, ISecurityAdapter sm) { 157 super(cmdFactory, sm); 158 _localEnvList = new LRStruct(); 159 } 160 161 /** 162 * Add the fish to the global environment. 163 * 164 * @param localEnv local environment 165 * @param fish fish to add 166 */ 167 protected void addFishToInternalData(ALocalEnv localEnv, AFish fish) { 168 _localEnvList.insertFront(localEnv); 169 } 170 171 /** 172 * Remove the fish from the global environment. 173 * 174 * @param localEnv local environment 175 */ 176 protected void removeFishFromInternalData(ALocalEnv localEnv) { 177 _localEnvList.execute(Remove.Singleton, localEnv); 178 } 179 180 /** 181 * Create a local environment for the position. 182 * 183 * @param loc location 184 * @param dir direction 185 * @return local environment 186 */ 187 protected ASquareLocalEnvironment makeLocalEnv(final Location loc, final Direction dir) { 188 return (ASquareLocalEnvironment) _localEnvList.execute(new IAlgo() { 189 /** 190 * Operates on a non-empty LRStruct host, given an input object. 191 * 192 * @param host a non-empty LRStruct. 193 * @param inp input object needed by this IAlgo. 194 * @return an appropriate output object. 195 */ 196 public Object nonEmptyCase(LRStruct host, Object inp) { 197 LocalEnvironment localEnv = (LocalEnvironment) host.getFirst(); 198 if (localEnv.location().inField(loc)) { 199 return localEnv; 200 } 201 else { 202 return host.getRest().execute(this, inp); 203 } 204 } 205 206 /** 207 * Operates on an empty LRStruct host, given an input object. 208 * 209 * @param host an empty LRStruct. 210 * @param inp input object needed by this IAlgo. 211 * @return an appropriate output object. 212 */ 213 public Object emptyCase(LRStruct host, Object inp) { 214 return new LocalEnvironment(loc, dir); 215 } 216 }, null); 217 } 218 219 /** 220 * Factory method for parsing a stream of tokens and creating a global environment from it. 221 * 222 * @param l lexer to use 223 * @return new global environment 224 */ 225 protected AGlobalEnv parseEnvironment(Lexer l) { 226 UnboundedEnv env = new UnboundedEnv(_cmdFactory, _securityAdapter); 227 env.parseFish(l); 228 return env; 229 } 230 231 /** 232 * Get the environment settings class. 233 * 234 * @return environment settings class 235 */ 236 public AEnvFactory makeEnvFactory() { 237 return new AEnvFactory() { 238 public AGlobalEnv create() { 239 return new UnboundedEnv(_cmdFactory, _securityAdapter); 240 } 241 242 public String toString() { 243 return UnboundedEnv.class.getName(); 244 } 245 }; 246 } 247 248 /** 249 * Print file header. 250 * 251 * @param pw PrintWriter to use 252 */ 253 protected void printHeader(PrintWriter pw) { 254 pw.println(getClass().getName()); 255 } 256 257 /** 258 * Get size of the display. 259 * 260 * @return size of the display in model coordinate units. 261 */ 262 public Dimension getDisplaySize() { 263 return new Dimension(PAN_SIZE, PAN_SIZE); 264 } 265 266 /** 267 * The action to be executed if the display should return home. 268 * 269 * @param sa scroll adapter 270 */ 271 public void returnHome(IScrollAdapter sa) { 272 sa.setCorner((int) PAN_CENTER.x, (int) PAN_CENTER.y); 273 sa.resetScrolling(); 274 } 275 276 /** 277 * Ask the model where to scroll, given where the user has scrolled. If the environment just acts like a normal 278 * panal, it should return pos without modification. If the environment recenters, it should return a position in 279 * the middle of the pan area. All coordinates are in model coordinate units. 280 * 281 * @param pos position where the user scrolled to 282 * @return position where the environment wants the view to be 283 * @see IDisplayAdapter#getPanDelta 284 */ 285 public Point.Double getViewPosition(Point.Double pos) { 286 // the panel always gets recentered after moving it, so return the center position 287 return PAN_CENTER; 288 } 289 290 /** 291 * Ask the model how much to pan, given where the user scrolled. If the environment just acts like a normal panal, 292 * it should return (0,0). If the environment recenters, it should return delta without modification. All 293 * coordinates are in model coordinate units. 294 * 295 * @param delta how far the user scrolled 296 * @return how far the panel should scroll 297 * @see IDisplayAdapter#getViewPosition 298 */ 299 public Point.Double getPanDelta(Point.Double delta) { 300 // we want the panel to keep track of the position, so return the delta as pan value 301 return delta; 302 } 303 304 /***************************************************************************************************************** 305 * Tests follow 306 *****************************************************************************************************************/ 307 308 /** 309 * Test cases for UnboundedEnv. 310 * 311 * @author Mathias Ricken 312 */ 313 public static class Test_UnboundedEnv extends TestCase { 314 private ICmdFactory _cmdFactory; 315 private ISecurityAdapter _sm; 316 private UnboundedEnv _env; 317 private IFishFactory _fishFactory; 318 319 private static final ILambda _notify = new ILambda() { 320 public Object apply(Object param) { 321 return "notifyCmd"; 322 } 323 }; 324 private static final ILambda _delete = new ILambda() { 325 public Object apply(Object param) { 326 return "deleteCmd"; 327 } 328 }; 329 private static final ILambda _add = new ILambda() { 330 public Object apply(Object param) { 331 return "addCmd"; 332 } 333 }; 334 335 public void setUp() throws Exception { 336 super.setUp(); 337 _cmdFactory = new ICmdFactory() { 338 public ILambda makeNotifyCmd(ILambda lambda) { 339 return _notify; 340 } 341 342 public ILambda makeDeleteCmd(ALocalEnv env) { 343 return _delete; 344 } 345 346 public ILambda makeAddCmd(AFish fish) { 347 return _add; 348 } 349 }; 350 _sm = new ISecurityAdapter() { 351 public void setProtected(boolean _protected) { 352 } 353 public ThreadGroup getFishThreadGroup() { 354 return null; 355 } 356 public ClassLoader getClassLoader() { 357 return null; 358 } 359 public void handleException(Throwable t) { 360 } 361 }; 362 363 _env = new UnboundedEnv(_cmdFactory, _sm); 364 365 _fishFactory = new IFishFactory() { 366 /** 367 * Create a new fish. 368 * 369 * @return new fish 370 */ 371 public AFish createFish() { 372 return new GenericFish(Color.RED); 373 } 374 }; 375 } 376 377 /** 378 * Test addFishToInternalData. 379 */ 380 public void testAddFish() { 381 LRStruct lrs = _env._localEnvList; 382 383 assertEquals(0, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 384 385 ALocalEnv lTop = _env.makeLocalEnv(new Point.Double(1.0, 1.0)); 386 GenericFish fTop = new GenericFish(Color.RED); 387 fTop.setLocalEnvironment(lTop); 388 _env.addFishToInternalData(lTop, fTop); 389 390 assertEquals(1, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 391 392 ALocalEnv lBottom = _env.makeLocalEnv(new Point.Double(1.0, 2.0)); 393 GenericFish fBottom = new GenericFish(Color.RED); 394 fBottom.setLocalEnvironment(lBottom); 395 _env.addFishToInternalData(lBottom, fBottom); 396 397 assertEquals(2, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 398 } 399 400 /** 401 * Test editFish. 402 */ 403 public void testEditFish() { 404 LRStruct lrs = _env._localEnvList; 405 406 assertEquals(0, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 407 408 ASquareLocalEnvironment l = (ASquareLocalEnvironment) _env.makeLocalEnv(new Point.Double(1.0, 1.0)); 409 GenericFish f = new GenericFish(Color.RED); 410 f.setLocalEnvironment(l); 411 _env.addFishToInternalData(l, f); 412 Direction d = l.direction(); 413 414 assertEquals(1, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 415 assertEquals(0.0, d.getAngle(), 0.01); 416 417 ILambda lambda = _env.editFish(l, _fishFactory, MouseEvent.BUTTON1); 418 assertEquals(1, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 419 assertEquals(Math.PI / 2.0, d.getAngle(), 0.01); 420 assertEquals(NoOpLambda.instance(), lambda); 421 422 lambda = _env.editFish(l, _fishFactory, MouseEvent.BUTTON1); 423 assertEquals(1, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 424 assertEquals(Math.PI, d.getAngle(), 0.01); 425 assertEquals(NoOpLambda.instance(), lambda); 426 427 lambda = _env.editFish(l, _fishFactory, MouseEvent.BUTTON1); 428 assertEquals(1, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 429 assertEquals(3 * Math.PI / 2.0, d.getAngle(), 0.01); 430 assertEquals(NoOpLambda.instance(), lambda); 431 432 lambda = _env.editFish(l, _fishFactory, MouseEvent.BUTTON1); 433 assertEquals(0, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 434 assertEquals(0, d.getAngle(), 0.01); 435 assertEquals(_delete, lambda); 436 } 437 438 /** 439 * Test getViewPosition. 440 */ 441 public void testGetViewPosition() { 442 Point.Double panCenter = _env.PAN_CENTER; 443 444 assertTrue(_env.getViewPosition(new Point.Double(0, 0)).equals(panCenter)); 445 assertTrue(_env.getViewPosition(new Point.Double(1.0, 0)).equals(panCenter)); 446 assertTrue(_env.getViewPosition(new Point.Double(1.2, 0)).equals(panCenter)); 447 assertTrue(_env.getViewPosition(new Point.Double(0, 1.0)).equals(panCenter)); 448 assertTrue(_env.getViewPosition(new Point.Double(0, 1.3)).equals(panCenter)); 449 assertTrue(_env.getViewPosition(new Point.Double(-2.5, 0)).equals(panCenter)); 450 assertTrue(_env.getViewPosition(new Point.Double(-3.0, 0)).equals(panCenter)); 451 assertTrue(_env.getViewPosition(new Point.Double(0, -2.5)).equals(panCenter)); 452 assertTrue(_env.getViewPosition(new Point.Double(0, -3.0)).equals(panCenter)); 453 assertTrue(_env.getViewPosition(new Point.Double(2.0, 1.0)).equals(panCenter)); 454 assertTrue(_env.getViewPosition(new Point.Double(-4.0, -2.3)).equals(panCenter)); 455 } 456 457 /** 458 * Test getPanDelta. 459 */ 460 public void testGetPanDelta() { 461 assertTrue(_env.getPanDelta(new Point.Double(0, 0)).equals(new Point.Double(0, 0))); 462 assertTrue(_env.getPanDelta(new Point.Double(1.0, 0)).equals(new Point.Double(1.0, 0))); 463 assertTrue(_env.getPanDelta(new Point.Double(1.2, 0)).equals(new Point.Double(1.2, 0))); 464 assertTrue(_env.getPanDelta(new Point.Double(0, 1.0)).equals(new Point.Double(0, 1.0))); 465 assertTrue(_env.getPanDelta(new Point.Double(0, 1.3)).equals(new Point.Double(0, 1.3))); 466 assertTrue(_env.getPanDelta(new Point.Double(-2.5, 0)).equals(new Point.Double(-2.5, 0))); 467 assertTrue(_env.getPanDelta(new Point.Double(-3.0, 0)).equals(new Point.Double(-3.0, 0))); 468 assertTrue(_env.getPanDelta(new Point.Double(0, -2.5)).equals(new Point.Double(0, -2.5))); 469 assertTrue(_env.getPanDelta(new Point.Double(0, -3.0)).equals(new Point.Double(0, -3.0))); 470 assertTrue(_env.getPanDelta(new Point.Double(2.0, 1.0)).equals(new Point.Double(2.0, 1.0))); 471 assertTrue(_env.getPanDelta(new Point.Double(-4.0, -2.3)).equals(new Point.Double(-4.0, -2.3))); 472 } 473 } 474 475 /** 476 * Test cases for UnboundedEnv.LocalEnv. 477 * 478 * @author Mathias Ricken 479 */ 480 public static class Test_UnboundedEnv_LocalEnv extends TestCase { 481 private ICmdFactory _cmdFactory; 482 private ISecurityAdapter _sm; 483 private UnboundedEnv _env; 484 485 private static class SuccessException extends RuntimeException { 486 public SuccessException() { 487 super(); 488 } 489 } 490 491 private static final ILambda _notify = new ILambda() { 492 public Object apply(Object param) { 493 return "notifyCmd"; 494 } 495 }; 496 private static final ILambda _delete = new ILambda() { 497 public Object apply(Object param) { 498 return "deleteCmd"; 499 } 500 }; 501 private static final ILambda _add = new ILambda() { 502 public Object apply(Object param) { 503 return "addCmd"; 504 } 505 }; 506 507 public void setUp() throws Exception { 508 super.setUp(); 509 _cmdFactory = new ICmdFactory() { 510 public ILambda makeNotifyCmd(ILambda lambda) { 511 return _notify; 512 } 513 514 public ILambda makeDeleteCmd(ALocalEnv env) { 515 return _delete; 516 } 517 518 public ILambda makeAddCmd(AFish fish) { 519 return _add; 520 } 521 }; 522 _sm = new ISecurityAdapter() { 523 public void setProtected(boolean _protected) { 524 } 525 public ThreadGroup getFishThreadGroup() { 526 return null; 527 } 528 public ClassLoader getClassLoader() { 529 return null; 530 } 531 public void handleException(Throwable t) { 532 } 533 }; 534 535 _env = new UnboundedEnv(_cmdFactory, _sm); 536 } 537 538 /** 539 * Test local environment's execute. 540 */ 541 public void testExecute() { 542 ALocalEnv l = _env.makeLocalEnv(new Point.Double(1, 1)); 543 544 try { 545 l.execute(new AGlobalEnv.ILocalEnvVisitor() { 546 public Object emptyCase(ALocalEnv host, Object param) { 547 // ok 548 throw new SuccessException(); 549 } 550 551 public Object nonEmptyCase(ALocalEnv host, Object param) { 552 throw new RuntimeException("Should be empty --"); 553 } 554 }, null); 555 fail("emptyCase should have been called --"); 556 } 557 catch (SuccessException e) { 558 } 559 560 GenericFish f = new GenericFish(Color.RED); 561 f.setLocalEnvironment(l); 562 _env.addFish(l, f); 563 564 ALocalEnv l2 = _env.makeLocalEnv(new Point.Double(1, 1)); 565 try { 566 l2.execute(new AGlobalEnv.ILocalEnvVisitor() { 567 public Object emptyCase(ALocalEnv host, Object param) { 568 throw new RuntimeException("Should be non-empty --"); 569 } 570 571 public Object nonEmptyCase(ALocalEnv host, Object param) { 572 // ok 573 throw new SuccessException(); 574 } 575 }, null); 576 fail("nonEmptyCase should have been falled --"); 577 } 578 catch (SuccessException e) { 579 } 580 581 ALocalEnv l3 = _env.makeLocalEnv(new Point.Double(1.4, 1.6)); 582 try { 583 l3.execute(new AGlobalEnv.ILocalEnvVisitor() { 584 public Object emptyCase(ALocalEnv host, Object param) { 585 throw new RuntimeException("Should be non-empty --"); 586 } 587 588 public Object nonEmptyCase(ALocalEnv host, Object param) { 589 // ok 590 throw new SuccessException(); 591 } 592 }, null); 593 fail("nonEmptyCase should have been falled --"); 594 } 595 catch (SuccessException e) { 596 } 597 598 ALocalEnv l4 = _env.makeLocalEnv(new Point.Double(1.0, 2.0)); 599 try { 600 l4.execute(new AGlobalEnv.ILocalEnvVisitor() { 601 public Object emptyCase(ALocalEnv host, Object param) { 602 // ok 603 throw new SuccessException(); 604 } 605 606 public Object nonEmptyCase(ALocalEnv host, Object param) { 607 throw new RuntimeException("Should be empty --"); 608 } 609 }, null); 610 fail("emptyCase should have been falled --"); 611 } 612 catch (SuccessException e) { 613 } 614 615 GenericFish f4 = new GenericFish(Color.RED); 616 f4.setLocalEnvironment(l4); 617 _env.addFish(l4, f4); 618 try { 619 l4.execute(new AGlobalEnv.ILocalEnvVisitor() { 620 public Object emptyCase(ALocalEnv host, Object param) { 621 throw new RuntimeException("Should be non-empty --"); 622 } 623 624 public Object nonEmptyCase(ALocalEnv host, Object param) { 625 // ok 626 throw new SuccessException(); 627 } 628 }, null); 629 fail("nonEmptyCase should have been falled --"); 630 } 631 catch (SuccessException e) { 632 } 633 634 } 635 636 /** 637 * Test local environment's tryMoveFwd. 638 */ 639 public void testTryMoveFwd() { 640 ALocalEnv lTop = _env.makeLocalEnv(new Point.Double(1.0, 1.0)); 641 GenericFish fTop = new GenericFish(Color.RED); 642 fTop.setLocalEnvironment(lTop); 643 _env.addFish(lTop, fTop); 644 645 ALocalEnv lBottom = _env.makeLocalEnv(new Point.Double(1.0, 2.0)); 646 GenericFish fBottom = new GenericFish(Color.RED); 647 fBottom.setLocalEnvironment(lBottom); 648 _env.addFish(lBottom, fBottom); 649 650 // move lBottom into lTop --> blocked 651 Integer i = (Integer) lBottom.tryMoveFwd(fBottom, new IBlockedCommand() { 652 public Object apply(Object param) { 653 // ok 654 return new Integer(456); 655 } 656 }, new IOpenCommand() { 657 public Object apply(Object param) { 658 throw new RuntimeException("Should be blocked --"); 659 } 660 }); 661 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(456), i); 662 663 // move lTop --> open, don't move 664 i = ((Integer) lTop.tryMoveFwd(fTop, new IBlockedCommand() { 665 public Object apply(Object param) { 666 throw new RuntimeException("Should be open --"); 667 } 668 }, new IOpenCommand() { 669 public Object apply(Object param) { 670 assertNotNull("Error, deactivatable move lambda needs to be passed to openCmd --", param); 671 assertEquals("Error, deactivatable move lambda needs to be passed to openCmd --", 672 DeactivatableLambda.class, 673 param.getClass()); 674 // ok 675 return new Integer(123); 676 } 677 })); 678 assertEquals("Error in delegation, blockedCmd not called, or incorrect return value --", 679 new Integer(123), 680 i); 681 682 // move lBottom into lTop --> blocked 683 i = (Integer) lBottom.tryMoveFwd(fBottom, new IBlockedCommand() { 684 public Object apply(Object param) { 685 // ok 686 return new Integer(789); 687 } 688 }, new IOpenCommand() { 689 public Object apply(Object param) { 690 throw new RuntimeException("Should be blocked --"); 691 } 692 }); 693 assertEquals("Error in delegation, blockedCmd not called, or incorrect return value --", 694 new Integer(789), 695 i); 696 697 // move lTop --> open, move 698 i = (Integer) lTop.tryMoveFwd(fTop, new IBlockedCommand() { 699 public Object apply(Object param) { 700 throw new RuntimeException("Should be open --"); 701 } 702 }, new IOpenCommand() { 703 public Object apply(Object param) { 704 assertNotNull("Error, deactivatable move lambda needs to be passed to openCmd --", param); 705 assertEquals("Error, deactivatable move lambda needs to be passed to openCmd --", 706 DeactivatableLambda.class, 707 param.getClass()); 708 // ok, make move 709 ((ILambda) param).apply(null); 710 return new Integer(111); 711 } 712 }); 713 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(111), i); 714 715 // move lBottom --> open 716 i = (Integer) lBottom.tryMoveFwd(fBottom, new IBlockedCommand() { 717 public Object apply(Object param) { 718 throw new RuntimeException("Should be open --"); 719 } 720 }, new IOpenCommand() { 721 public Object apply(Object param) { 722 assertNotNull("Error, deactivatable move lambda needs to be passed to openCmd --", param); 723 assertEquals("Error, deactivatable move lambda needs to be passed to openCmd --", 724 DeactivatableLambda.class, 725 param.getClass()); 726 // ok 727 return new Integer(222); 728 } 729 }); 730 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(222), i); 731 732 // move lTop --> open, don't move 733 i = (Integer) lTop.tryMoveFwd(fTop, new IBlockedCommand() { 734 public Object apply(Object param) { 735 throw new RuntimeException("Should be open --"); 736 } 737 }, new IOpenCommand() { 738 public Object apply(Object param) { 739 assertNotNull("Error, deactivatable move lambda needs to be passed to openCmd --", param); 740 assertEquals("Error, deactivatable move lambda needs to be passed to openCmd --", 741 DeactivatableLambda.class, 742 param.getClass()); 743 // ok 744 return new Integer(333); 745 } 746 }); 747 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(333), i); 748 749 // turn and move lTop --> open, don't move 750 lTop.turnRight(fTop, Math.PI / 2.0); 751 i = (Integer) lTop.tryMoveFwd(fTop, new IBlockedCommand() { 752 public Object apply(Object param) { 753 throw new RuntimeException("Should be open --"); 754 } 755 }, new IOpenCommand() { 756 public Object apply(Object param) { 757 assertNotNull("Error, deactivatable move lambda needs to be passed to openCmd --", param); 758 assertEquals("Error, deactivatable move lambda needs to be passed to openCmd --", 759 DeactivatableLambda.class, 760 param.getClass()); 761 // ok 762 return new Integer(444); 763 } 764 }); 765 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(444), i); 766 } 767 768 /** 769 * Test local environment's tryBreedFwd. 770 */ 771 public void testTryBreedFwd() { 772 LRStruct lrs = _env._localEnvList; 773 774 assertEquals(0, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 775 776 ALocalEnv lTop = _env.makeLocalEnv(new Point.Double(1.0, 1.0)); 777 GenericFish fTop = new GenericFish(Color.RED); 778 fTop.setLocalEnvironment(lTop); 779 _env.addFish(lTop, fTop); 780 781 assertEquals(1, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 782 783 ALocalEnv lBottom = _env.makeLocalEnv(new Point.Double(1.0, 2.0)); 784 GenericFish fBottom = new GenericFish(Color.RED); 785 fBottom.setLocalEnvironment(lBottom); 786 _env.addFish(lBottom, fBottom); 787 788 assertEquals(2, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 789 790 // breed lBottom into lTop --> blocked 791 Integer i = (Integer) lBottom.tryBreedFwd(fBottom, new IBlockedCommand() { 792 public Object apply(Object param) { 793 // ok 794 return new Integer(456); 795 } 796 }, new IOpenCommand() { 797 public Object apply(Object param) { 798 throw new RuntimeException("Should be blocked --"); 799 } 800 }); 801 assertEquals("Error in delegation, blockedCmd not called, or incorrect return value --", 802 new Integer(456), 803 i); 804 805 // breed lTop --> open, don't breed 806 i = (Integer) lTop.tryBreedFwd(fTop, new IBlockedCommand() { 807 public Object apply(Object param) { 808 throw new RuntimeException("Should be open --"); 809 } 810 }, new IOpenCommand() { 811 public Object apply(Object param) { 812 assertNotNull("Error, deactivatable breed lambda needs to be passed to openCmd --", param); 813 assertEquals("Error, deactivatable breed lambda needs to be passed to openCmd --", 814 DeactivatableLambda.class, 815 param.getClass()); 816 // ok 817 return new Integer(123); 818 } 819 }); 820 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(123), i); 821 822 assertEquals(2, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 823 824 // breed lBottom into lTop --> blocked 825 i = (Integer) lBottom.tryBreedFwd(fBottom, new IBlockedCommand() { 826 public Object apply(Object param) { 827 // ok 828 return new Integer(456); 829 } 830 }, new IOpenCommand() { 831 public Object apply(Object param) { 832 throw new RuntimeException("Should be blocked --"); 833 } 834 }); 835 assertEquals("Error in delegation, blockedCmd not called, or incorrect return value --", 836 new Integer(456), 837 i); 838 839 // breed lTop --> open, breed 840 i = (Integer) lTop.tryBreedFwd(fTop, new IBlockedCommand() { 841 public Object apply(Object param) { 842 throw new RuntimeException("Should be open --"); 843 } 844 }, new IOpenCommand() { 845 public Object apply(Object param) { 846 assertNotNull("Error, deactivatable breed lambda needs to be passed to openCmd --", param); 847 assertEquals("Error, deactivatable breed lambda needs to be passed to openCmd --", 848 DeactivatableLambda.class, 849 param.getClass()); 850 // ok, breed 851 ((ILambda) param).apply(null); 852 return new Integer(123); 853 } 854 }); 855 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(123), i); 856 857 assertEquals(3, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 858 859 // breed lBottom into lTop --> blocked 860 i = (Integer) lBottom.tryBreedFwd(fBottom, new IBlockedCommand() { 861 public Object apply(Object param) { 862 // ok 863 return new Integer(456); 864 } 865 }, new IOpenCommand() { 866 public Object apply(Object param) { 867 throw new RuntimeException("Should be blocked --"); 868 } 869 }); 870 assertEquals("Error in delegation, blockedCmd not called, or incorrect return value --", 871 new Integer(456), 872 i); 873 874 // breed lTop --> blocked 875 i = (Integer) lTop.tryBreedFwd(fTop, new IBlockedCommand() { 876 public Object apply(Object param) { 877 // ok 878 return new Integer(456); 879 } 880 }, new IOpenCommand() { 881 public Object apply(Object param) { 882 throw new RuntimeException("Should be blocked --"); 883 } 884 }); 885 assertEquals("Error in delegation, blockedCmd not called, or incorrect return value --", 886 new Integer(456), 887 i); 888 889 // turn and breed lTop --> open, don't breed 890 lTop.turnRight(fTop, Math.PI / 2.0); 891 i = (Integer) lTop.tryBreedFwd(fTop, new IBlockedCommand() { 892 public Object apply(Object param) { 893 throw new RuntimeException("Should be open --"); 894 } 895 }, new IOpenCommand() { 896 public Object apply(Object param) { 897 assertNotNull("Error, deactivatable breed lambda needs to be passed to openCmd --", param); 898 assertEquals("Error, deactivatable breed lambda needs to be passed to openCmd --", 899 DeactivatableLambda.class, 900 param.getClass()); 901 // ok 902 return new Integer(789); 903 } 904 }); 905 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(789), i); 906 907 assertEquals(3, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 908 909 // turn and breed lTop --> open, breed 910 i = (Integer) lTop.tryBreedFwd(fTop, new IBlockedCommand() { 911 public Object apply(Object param) { 912 throw new RuntimeException("Should be open --"); 913 } 914 }, new IOpenCommand() { 915 public Object apply(Object param) { 916 assertNotNull("Error, deactivatable breed lambda needs to be passed to openCmd --", param); 917 assertEquals("Error, deactivatable breed lambda needs to be passed to openCmd --", 918 DeactivatableLambda.class, 919 param.getClass()); 920 // ok, breed 921 ((ILambda) param).apply(null); 922 return new Integer(789); 923 } 924 }); 925 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(789), i); 926 927 assertEquals(4, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 928 929 // turn and breed lTop --> blocked 930 i = (Integer) lTop.tryBreedFwd(fTop, new IBlockedCommand() { 931 public Object apply(Object param) { 932 // ok 933 return new Integer(789); 934 } 935 }, new IOpenCommand() { 936 public Object apply(Object param) { 937 throw new RuntimeException("Should be blocked --"); 938 } 939 }); 940 assertEquals("Error in delegation, blockedCmd not called, or incorrect return value --", 941 new Integer(789), 942 i); 943 944 assertEquals(4, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 945 } 946 947 /** 948 * Test local environment's turnRight. 949 */ 950 public void testTurnRight() { 951 ASquareLocalEnvironment l = (ASquareLocalEnvironment) _env.makeLocalEnv(new Point.Double(1.0, 1.0)); 952 GenericFish f = new GenericFish(Color.RED); 953 f.setLocalEnvironment(l); 954 _env.addFish(l, f); 955 Direction d = l.direction(); 956 957 assertEquals(0.0, d.getAngle(), 0.01); 958 l.turnRight(f, Math.PI / 2); 959 assertEquals(Math.PI / 2.0, d.getAngle(), 0.01); 960 l.turnRight(f, Math.PI / 2); 961 assertEquals(Math.PI, d.getAngle(), 0.01); 962 l.turnRight(f, Math.PI / 2); 963 assertEquals(3 * Math.PI / 2.0, d.getAngle(), 0.01); 964 l.turnRight(f, Math.PI / 2); 965 assertEquals(0, d.getAngle(), 0.01); 966 } 967 968 /** 969 * Test local environment's removeFish. 970 */ 971 public void testRemoveFish() { 972 LRStruct lrs = _env._localEnvList; 973 974 assertEquals(0, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 975 976 ALocalEnv lTop = _env.makeLocalEnv(new Point.Double(1.0, 1.0)); 977 GenericFish fTop = new GenericFish(Color.RED); 978 fTop.setLocalEnvironment(lTop); 979 _env.addFish(lTop, fTop); 980 981 assertEquals(1, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 982 983 ALocalEnv lBottom = _env.makeLocalEnv(new Point.Double(1.0, 2.0)); 984 GenericFish fBottom = new GenericFish(Color.RED); 985 fBottom.setLocalEnvironment(lBottom); 986 _env.addFish(lBottom, fBottom); 987 988 assertEquals(2, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 989 990 lTop.removeFish(fTop); 991 992 assertEquals(1, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 993 994 lBottom.removeFish(fBottom); 995 996 assertEquals(0, ((Integer) lrs.execute(GetLength.Singleton, null)).intValue()); 997 } 998 999 1000 /** 1001 * Test to make sure only one move lambda can be executed. 1002 */ 1003 public void testOnlyOneMove() { 1004 ASquareLocalEnvironment l = (ASquareLocalEnvironment) _env.makeLocalEnv(new Point.Double(5.0, 5.0)); 1005 GenericFish f = new GenericFish(Color.RED); 1006 f.setLocalEnvironment(l); 1007 _env.addFish(l, f); 1008 1009 final LinkedList<ILambda> lambdas = new LinkedList<ILambda>(); 1010 l.tryMoveFwd(f, new IBlockedCommand() { 1011 public Object apply(Object param) { 1012 throw new RuntimeException("Should be open --"); 1013 } 1014 }, new IOpenCommand() { 1015 public Object apply(Object param) { 1016 assertNotNull("Error, deactivatable move lambda needs to be passed to openCmd --", param); 1017 assertEquals("Error, deactivatable move lambda needs to be passed to openCmd --", 1018 DeactivatableLambda.class, 1019 param.getClass()); 1020 lambdas.add((ILambda)param); 1021 return null; 1022 } 1023 }); 1024 f.turnRight(); 1025 l.tryMoveFwd(f, new IBlockedCommand() { 1026 public Object apply(Object param) { 1027 throw new RuntimeException("Should be open --"); 1028 } 1029 }, new IOpenCommand() { 1030 public Object apply(Object param) { 1031 assertNotNull("Error, deactivatable move lambda needs to be passed to openCmd --", param); 1032 assertEquals("Error, deactivatable move lambda needs to be passed to openCmd --", 1033 DeactivatableLambda.class, 1034 param.getClass()); 1035 lambdas.add((ILambda)param); 1036 return null; 1037 } 1038 }); 1039 1040 assertEquals(2, lambdas.size()); 1041 1042 lambdas.get(0).apply(null); 1043 Location loc = l.location(); 1044 assertTrue("Should have moved -- ", loc.same(_env.makeLocation(5.0, 4.0))); 1045 1046 lambdas.get(1).apply(null); 1047 loc = l.location(); 1048 assertTrue("Should not have moved, move lambda was not deactivated -- ", 1049 loc.same(_env.makeLocation(5.0, 4.0))); 1050 1051 lambdas.clear(); 1052 l.tryMoveFwd(f, new IBlockedCommand() { 1053 public Object apply(Object param) { 1054 throw new RuntimeException("Should be open --"); 1055 } 1056 }, new IOpenCommand() { 1057 public Object apply(Object param) { 1058 assertNotNull("Error, deactivatable move lambda needs to be passed to openCmd --", param); 1059 assertEquals("Error, deactivatable move lambda needs to be passed to openCmd --", 1060 DeactivatableLambda.class, 1061 param.getClass()); 1062 lambdas.add((ILambda)param); 1063 return null; 1064 } 1065 }); 1066 f.turnRight(); 1067 l.tryMoveFwd(f, new IBlockedCommand() { 1068 public Object apply(Object param) { 1069 throw new RuntimeException("Should be open --"); 1070 } 1071 }, new IOpenCommand() { 1072 public Object apply(Object param) { 1073 assertNotNull("Error, deactivatable move lambda needs to be passed to openCmd --", param); 1074 assertEquals("Error, deactivatable move lambda needs to be passed to openCmd --", 1075 DeactivatableLambda.class, 1076 param.getClass()); 1077 lambdas.add((ILambda)param); 1078 return null; 1079 } 1080 }); 1081 1082 assertEquals(2, lambdas.size()); 1083 1084 lambdas.get(1).apply(null); 1085 loc = l.location(); 1086 assertTrue("Should have moved -- ", loc.same(_env.makeLocation(6.0, 4.0))); 1087 1088 lambdas.get(0).apply(null); 1089 loc = l.location(); 1090 assertTrue("Should not have moved, move lambda was not deactivated -- ", 1091 loc.same(_env.makeLocation(6.0, 4.0))); 1092 } 1093 } 1094 }