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 }