]> source.dussan.org Git - aspectj.git/commitdiff
Addendum to the original contribution from PARC. Three presentations:
authorjhugunin <jhugunin>
Fri, 1 Aug 2003 18:53:07 +0000 (18:53 +0000)
committerjhugunin <jhugunin>
Fri, 1 Aug 2003 18:53:07 +0000 (18:53 +0000)
oneHour talk
three hour tutorial
six hour tutorial including exercises

58 files changed:
docs/teaching/exercises/answers/Answer1a.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer1b.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer1c.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer1d.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer2a.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer2b.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer2c.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer2d.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer2e.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer2f.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer2g.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer2h.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer3a.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer3b.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer3c.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer4a.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer4b.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer4c.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer4d.java [new file with mode: 0644]
docs/teaching/exercises/answers/Answer4e.java [new file with mode: 0644]
docs/teaching/exercises/base.lst [new file with mode: 0644]
docs/teaching/exercises/figures/Box.java [new file with mode: 0644]
docs/teaching/exercises/figures/FigureElement.java [new file with mode: 0644]
docs/teaching/exercises/figures/Group.java [new file with mode: 0644]
docs/teaching/exercises/figures/Line.java [new file with mode: 0644]
docs/teaching/exercises/figures/Point.java [new file with mode: 0644]
docs/teaching/exercises/figures/ShapeFigureElement.java [new file with mode: 0644]
docs/teaching/exercises/figures/SlothfulPoint.java [new file with mode: 0644]
docs/teaching/exercises/figures/gui/FigurePanel.java [new file with mode: 0644]
docs/teaching/exercises/figures/gui/LogAdapter.java [new file with mode: 0644]
docs/teaching/exercises/figures/gui/Main.java [new file with mode: 0644]
docs/teaching/exercises/guibase.lst [new file with mode: 0644]
docs/teaching/exercises/index.html [new file with mode: 0644]
docs/teaching/exercises/pre-letter.txt [new file with mode: 0644]
docs/teaching/exercises/setpaths [new file with mode: 0644]
docs/teaching/exercises/setpaths.bat [new file with mode: 0644]
docs/teaching/exercises/support/Log.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test1a.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test2a.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test2b.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test2c.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test2d.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test2e.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test2f.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test2g.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test2h.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test3a.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test3b.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test3c.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test4a.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test4b.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test4c.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test4d.java [new file with mode: 0644]
docs/teaching/exercises/tests/Test4e.java [new file with mode: 0644]
docs/teaching/oneHour.ppt [new file with mode: 0644]
docs/teaching/readme.txt [new file with mode: 0644]
docs/teaching/tutorial.ppt [new file with mode: 0644]

diff --git a/docs/teaching/exercises/answers/Answer1a.java b/docs/teaching/exercises/answers/Answer1a.java
new file mode 100644 (file)
index 0000000..94d4522
--- /dev/null
@@ -0,0 +1,22 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import figures.*;
+
+aspect Answer1a {
+    declare error
+       : get(java.io.PrintStream System.out)
+          && within(figures..*)
+       : "illegal access to System.out";
+}
diff --git a/docs/teaching/exercises/answers/Answer1b.java b/docs/teaching/exercises/answers/Answer1b.java
new file mode 100644 (file)
index 0000000..ef634a9
--- /dev/null
@@ -0,0 +1,21 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+aspect Answer1b {
+    declare warning
+        : set(private * *)
+          && !withincode(* set*(..))
+          && within(figures.*)
+        : "bad field set";
+}
diff --git a/docs/teaching/exercises/answers/Answer1c.java b/docs/teaching/exercises/answers/Answer1c.java
new file mode 100644 (file)
index 0000000..ff31b63
--- /dev/null
@@ -0,0 +1,21 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+aspect Answer1c {
+    declare error
+        : set(private * *)
+          && !(withincode(* set*(..)) || withincode(new(..)))
+          && within(figures.*)
+        : "bad field set";
+}
diff --git a/docs/teaching/exercises/answers/Answer1d.java b/docs/teaching/exercises/answers/Answer1d.java
new file mode 100644 (file)
index 0000000..9fb3239
--- /dev/null
@@ -0,0 +1,23 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+aspect Answer1c {
+    declare error
+        : set(private * *)
+          && !(withincode(* set*(..))
+               || withincode(new(..))
+               || withincode(void figures.Point.move(int, int)))
+         && within(figures.*)
+        : "bad field set";
+}
diff --git a/docs/teaching/exercises/answers/Answer2a.java b/docs/teaching/exercises/answers/Answer2a.java
new file mode 100644 (file)
index 0000000..b874f06
--- /dev/null
@@ -0,0 +1,26 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import figures.Point;
+import figures.FigureElement;
+
+public aspect Answer2a {
+    before(int newValue): set(int Point.*) && args(newValue) {
+        if (newValue < FigureElement.MIN_VALUE) {
+            throw new IllegalArgumentException("too small");
+        } else if (newValue > FigureElement.MAX_VALUE) {
+            throw new IllegalArgumentException("too large");
+        }
+    }
+}
diff --git a/docs/teaching/exercises/answers/Answer2b.java b/docs/teaching/exercises/answers/Answer2b.java
new file mode 100644 (file)
index 0000000..fc45ad2
--- /dev/null
@@ -0,0 +1,26 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import figures.Group;
+import figures.FigureElement;
+
+public aspect Answer2b {
+    before(FigureElement newValue):
+            call(void Group.add(FigureElement))
+            && args(newValue) {
+       if (newValue == null) {
+            throw new IllegalArgumentException("null not allowed");
+        }
+    }
+}
diff --git a/docs/teaching/exercises/answers/Answer2c.java b/docs/teaching/exercises/answers/Answer2c.java
new file mode 100644 (file)
index 0000000..6dbd7fa
--- /dev/null
@@ -0,0 +1,31 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import figures.Group;
+import figures.FigureElement;
+
+public aspect Answer2c {
+    before(FigureElement newValue, Group g):
+            call(void Group.add(FigureElement))
+            && args(newValue)
+            && target(g) {
+       if (newValue == null) {
+            throw new IllegalArgumentException("null not allowed");
+        }
+       if (newValue == g) {
+            throw new IllegalArgumentException("self not allowed");
+        }
+
+    }
+}
diff --git a/docs/teaching/exercises/answers/Answer2d.java b/docs/teaching/exercises/answers/Answer2d.java
new file mode 100644 (file)
index 0000000..75937ca
--- /dev/null
@@ -0,0 +1,24 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import figures.SlothfulPoint;
+
+aspect Answer2d {
+    after(int newValue, SlothfulPoint p) returning:
+           call(void setX(int)) && args(newValue) && target(p) {
+       if (newValue != p.getX()) {
+           throw new RuntimeException("setter didn't set");
+       }
+    }
+}
diff --git a/docs/teaching/exercises/answers/Answer2e.java b/docs/teaching/exercises/answers/Answer2e.java
new file mode 100644 (file)
index 0000000..a0500bc
--- /dev/null
@@ -0,0 +1,24 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import figures.*;
+
+public aspect Answer2e {
+    pointcut checkpoint(Box box):
+        call(void move(int, int)) && target(box);
+
+    after(Box box) returning: checkpoint(box) {
+        box.checkBoxness();
+    }
+}
diff --git a/docs/teaching/exercises/answers/Answer2f.java b/docs/teaching/exercises/answers/Answer2f.java
new file mode 100644 (file)
index 0000000..aad64f4
--- /dev/null
@@ -0,0 +1,24 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import figures.*;
+
+public aspect Answer2f {
+    pointcut checkpoint(Box box):
+        target(box) && call(public * *(..)) && !within(Answer*);
+
+    after(Box box) returning: checkpoint(box) {
+        box.checkBoxness();
+    }
+}
diff --git a/docs/teaching/exercises/answers/Answer2g.java b/docs/teaching/exercises/answers/Answer2g.java
new file mode 100644 (file)
index 0000000..9bc9a52
--- /dev/null
@@ -0,0 +1,27 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import figures.*;
+
+aspect Answer2g {
+    int around(int val): (set(int Point._x) || set(int Point._y))
+                         && args(val) {
+       return proceed(trim(val));
+    }
+
+    private int trim(int val) {
+        return Math.max(Math.min(val, FigureElement.MAX_VALUE),
+                        FigureElement.MIN_VALUE);
+    }
+}
diff --git a/docs/teaching/exercises/answers/Answer2h.java b/docs/teaching/exercises/answers/Answer2h.java
new file mode 100644 (file)
index 0000000..3dcc47b
--- /dev/null
@@ -0,0 +1,31 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import figures.*;
+
+import java.awt.Rectangle;
+
+aspect Answer2h {
+    void around(FigureElement fe, int dx, int dy):
+            target(fe) && call(void move(int, int)) && args(dx, dy) {
+        Rectangle preBounds = new Rectangle(fe.getBounds());
+        proceed(fe, dx, dy);
+
+        preBounds.translate(dx, dy);
+
+        if (!preBounds.equals(fe.getBounds())) {
+            throw new IllegalStateException("bounds don't match move");
+        }
+    }
+}
diff --git a/docs/teaching/exercises/answers/Answer3a.java b/docs/teaching/exercises/answers/Answer3a.java
new file mode 100644 (file)
index 0000000..7d9c91f
--- /dev/null
@@ -0,0 +1,23 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import support.Log;
+
+import figures.Point;
+
+aspect Answer3a {
+    before(): execution(void Point.move(int, int)) {
+        Log.log("moving");
+    }
+}
diff --git a/docs/teaching/exercises/answers/Answer3b.java b/docs/teaching/exercises/answers/Answer3b.java
new file mode 100644 (file)
index 0000000..b978f1a
--- /dev/null
@@ -0,0 +1,26 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import support.Log;
+
+import figures.Point;
+import figures.Group;
+import figures.FigureElement;
+
+aspect Answer3b {
+    before():
+       execution(void Group.add(FigureElement)) && args(Point) {
+        Log.log("adding Point");
+    }
+}
diff --git a/docs/teaching/exercises/answers/Answer3c.java b/docs/teaching/exercises/answers/Answer3c.java
new file mode 100644 (file)
index 0000000..68797b9
--- /dev/null
@@ -0,0 +1,34 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import support.Log;
+
+import figures.Point;
+import figures.Group;
+import figures.FigureElement;
+
+aspect Answer3c {
+    private Group Point.enclosingGroup = null;
+
+    before(Point p, Group g):
+       execution(void add(FigureElement)) && args(p) && target(g) {
+       p.enclosingGroup = g;
+    }
+
+    before(Point p):
+       call(void move(int, int)) && target(p) {
+       Log.log("moving as a part of " + p.enclosingGroup);
+    }
+
+}
diff --git a/docs/teaching/exercises/answers/Answer4a.java b/docs/teaching/exercises/answers/Answer4a.java
new file mode 100644 (file)
index 0000000..2f3956a
--- /dev/null
@@ -0,0 +1,28 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import figures.FigureElement;
+import figures.Group;
+import java.awt.Rectangle;
+
+aspect Answer4a {
+    private Rectangle wholeCanvas =
+        new Rectangle(FigureElement.MIN_VALUE, FigureElement.MIN_VALUE,
+                      FigureElement.MAX_VALUE - FigureElement.MIN_VALUE,
+                      FigureElement.MAX_VALUE - FigureElement.MIN_VALUE);
+
+    Rectangle around(): execution(Rectangle Group.getBounds()) {
+       return wholeCanvas;
+    }
+}
diff --git a/docs/teaching/exercises/answers/Answer4b.java b/docs/teaching/exercises/answers/Answer4b.java
new file mode 100644 (file)
index 0000000..d0292b1
--- /dev/null
@@ -0,0 +1,29 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import figures.FigureElement;
+import figures.Group;
+import java.awt.Rectangle;
+
+aspect Answer4b {
+    private Rectangle Group.cache = null;
+
+    Rectangle around(Group g):
+            execution(Rectangle Group.getBounds()) && this(g) {
+       if (g.cache == null) {
+           g.cache = proceed(g);
+       }
+       return g.cache;
+    }
+}
diff --git a/docs/teaching/exercises/answers/Answer4c.java b/docs/teaching/exercises/answers/Answer4c.java
new file mode 100644 (file)
index 0000000..54107cf
--- /dev/null
@@ -0,0 +1,33 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import figures.FigureElement;
+import figures.Group;
+import java.awt.Rectangle;
+
+aspect Answer4c {
+    private Rectangle Group.cache = null;
+
+    Rectangle around(Group g):
+            execution(Rectangle Group.getBounds()) && this(g) {
+       if (g.cache == null) {
+           g.cache = proceed(g);
+       }
+       return g.cache;
+    }
+
+    before(Group g): call(void move(int, int)) && target(g) {
+       g.cache = null;
+    }
+}
diff --git a/docs/teaching/exercises/answers/Answer4d.java b/docs/teaching/exercises/answers/Answer4d.java
new file mode 100644 (file)
index 0000000..10d90f6
--- /dev/null
@@ -0,0 +1,42 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import figures.FigureElement;
+import figures.Group;
+import figures.Point;
+import java.awt.Rectangle;
+
+aspect Answer4d {
+    private Rectangle Group.cache = null;
+    private Group Point.enclosingGroup = null;
+
+    before(Point p, Group g):
+       execution(void add(FigureElement)) && args(p) && target(g) {
+       p.enclosingGroup = g;
+    }
+
+    Rectangle around(Group g):
+            execution(Rectangle Group.getBounds()) && this(g) {
+       if (g.cache == null) {
+           g.cache = proceed(g);
+       }
+       return g.cache;
+    }
+
+    before(Point p): set(* Point.*) && target(p) {
+       if (p.enclosingGroup != null) {
+           p.enclosingGroup.cache = null;
+       }
+    }
+}
diff --git a/docs/teaching/exercises/answers/Answer4e.java b/docs/teaching/exercises/answers/Answer4e.java
new file mode 100644 (file)
index 0000000..20f9890
--- /dev/null
@@ -0,0 +1,44 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package answers;
+
+import figures.FigureElement;
+import figures.Group;
+import figures.Point;
+import java.awt.Rectangle;
+
+aspect Answer4e {
+    private Rectangle Group.cache = null;
+    private Group FigureElement.enclosingGroup = null;
+
+    before(FigureElement p, Group g):
+       execution(void add(FigureElement)) && args(p) && target(g) {
+       p.enclosingGroup = g;
+    }
+
+    Rectangle around(Group g):
+            execution(Rectangle Group.getBounds()) && this(g) {
+       if (g.cache == null) {
+           g.cache = proceed(g);
+       }
+       return g.cache;
+    }
+
+    before(Point p): set(* Point.*) && target(p) {
+       FigureElement fe = p;
+       while (fe.enclosingGroup != null) {
+           fe.enclosingGroup.cache = null;
+           fe = fe.enclosingGroup;
+       }
+    }
+}
diff --git a/docs/teaching/exercises/base.lst b/docs/teaching/exercises/base.lst
new file mode 100644 (file)
index 0000000..ae9c8c6
--- /dev/null
@@ -0,0 +1,29 @@
+figures/Box.java
+figures/FigureElement.java
+figures/Group.java
+figures/Line.java
+figures/Point.java
+figures/ShapeFigureElement.java
+figures/SlothfulPoint.java
+
+support/Log.java
+
+answers/Answer.java
+
+tests/Test.java
+tests/Test2a.java
+tests/Test2b.java
+tests/Test2c.java
+tests/Test2d.java
+tests/Test2e.java
+tests/Test2f.java
+tests/Test2g.java
+tests/Test2h.java
+tests/Test3a.java
+tests/Test3b.java
+tests/Test3c.java
+tests/Test4a.java
+tests/Test4b.java
+tests/Test4c.java
+tests/Test4d.java
+tests/Test4e.java
diff --git a/docs/teaching/exercises/figures/Box.java b/docs/teaching/exercises/figures/Box.java
new file mode 100644 (file)
index 0000000..b10faa6
--- /dev/null
@@ -0,0 +1,64 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public class Box extends ShapeFigureElement {
+    private Point _p0;
+    private Point _p1;
+    private Point _p2;
+    private Point _p3;
+
+    public Box(int x0, int y0, int width, int height) {
+        _p0 = new Point(x0, y0);
+        _p1 = new Point(x0+width, y0);
+        _p2 = new Point(x0+width, y0+height);
+        _p3 = new Point(x0, y0+height);
+    }
+
+    public Point getP0() { return _p0; }
+    public Point getP1() { return _p1; }
+    public Point getP2() { return _p2; }
+    public Point getP3() { return _p3; }
+
+    public void move(int dx, int dy) {
+        _p0.move(dx, dy);
+        _p1.move(dx, dy);
+        _p2.move(dx, dy);
+        _p3.move(dx, dy);
+    }
+
+    public void checkBoxness() {
+        if ((_p0.getX() == _p3.getX()) &&
+            (_p1.getX() == _p2.getX()) &&
+            (_p0.getY() == _p1.getY()) &&
+            (_p2.getY() == _p3.getY()))
+          return;
+        throw new IllegalStateException("This is not a square.");
+    }
+
+    public String toString() {
+        return "Box(" + _p0 + ", " + _p1 + ", " + _p2 + ", " + _p3 + ")";
+    }
+
+    public Shape getShape() {
+        return new Rectangle(getP1().getX(),
+                             getP1().getY(),
+                             getP3().getX() - getP1().getX(),
+                             getP3().getY() - getP1().getY());
+    }
+}
+
diff --git a/docs/teaching/exercises/figures/FigureElement.java b/docs/teaching/exercises/figures/FigureElement.java
new file mode 100644 (file)
index 0000000..d6d5c26
--- /dev/null
@@ -0,0 +1,30 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public interface FigureElement {
+    public static final int MIN_VALUE = 0;
+    public static final int MAX_VALUE = 500;
+
+    public abstract void move(int dx, int dy);
+
+    public abstract Rectangle getBounds();
+
+    public abstract boolean contains(Point2D p);
+
+    public abstract void paint(Graphics2D g2);
+}
diff --git a/docs/teaching/exercises/figures/Group.java b/docs/teaching/exercises/figures/Group.java
new file mode 100644 (file)
index 0000000..ad2f224
--- /dev/null
@@ -0,0 +1,97 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package figures;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.geom.*;
+
+public class Group implements FigureElement {
+    private Collection _members;
+    private String _identifier;
+
+    public Group(FigureElement first) {
+        this._members = new ArrayList();
+        add(first);
+    }
+
+    public void add(FigureElement fe) {
+        _members.add(fe);
+    }
+
+    public Iterator members() {
+        return _members.iterator();
+    }
+
+    public void move(int dx, int dy) {
+        for (Iterator i = _members.iterator(); i.hasNext(); ) {
+            FigureElement fe = (FigureElement)i.next();
+            fe.move(dx, dy);
+        }
+    }
+
+    public void setIdentifier(String identifier) {
+        _identifier = identifier;
+    }
+
+    public String toString() {
+        if (_identifier != null) {
+            return _identifier;
+        }
+
+        StringBuffer buf = new StringBuffer("Group(");
+        for (Iterator i = _members.iterator(); i.hasNext(); ) {
+            buf.append(i.next().toString());
+            if (i.hasNext()) {
+                buf.append(", ");
+            }
+        }
+        buf.append(")");
+        return buf.toString();
+    }
+
+    public Rectangle getBounds() {
+        Rectangle previous = null;
+        for (Iterator i = _members.iterator(); i.hasNext(); ) {
+            FigureElement fe = (FigureElement)i.next();
+            Rectangle rect = fe.getBounds();
+            if (previous != null) {
+                previous = previous.union(rect);
+            } else {
+                previous = rect;
+            }
+        }
+        return previous;
+    }
+
+    public boolean contains(Point2D p) {
+        for (Iterator i = _members.iterator(); i.hasNext(); ) {
+            FigureElement fe = (FigureElement)i.next();
+            if (fe.contains(p)) return true;
+        }
+        return false;
+    }
+
+    public void paint(Graphics2D g2) {
+        for (Iterator i = _members.iterator(); i.hasNext(); ) {
+            FigureElement fe = (FigureElement)i.next();
+            fe.paint(g2);
+        }
+    }
+
+    public int size() {
+        return _members.size();
+    }
+}
+
diff --git a/docs/teaching/exercises/figures/Line.java b/docs/teaching/exercises/figures/Line.java
new file mode 100644 (file)
index 0000000..f21c1ef
--- /dev/null
@@ -0,0 +1,64 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public class Line extends ShapeFigureElement {
+    private Point _p1;
+    private Point _p2;
+
+    public Line(Point p1, Point p2) {
+        _p1 = p1;
+        _p2 = p2;
+    }
+
+    public Point getP1() { return _p1; }
+    public Point getP2() { return _p2; }
+
+    public void move(int dx, int dy) {
+        _p1.move(dx, dy);
+        _p2.move(dx, dy);
+    }
+
+    public String toString() {
+        return "Line(" + _p1 + ", " + _p2 + ")";
+    }
+
+    /**
+     * Used to determine if this line {@link contains(Point2D)} a point.
+     */
+    final static int THRESHHOLD = 5;
+
+    /**
+     * Returns <code>true</code> if the point segment distance is less than
+     * {@link THRESHHOLD}.
+     */
+    public boolean contains(Point2D p) {
+        return getLine2D().ptLineDist(p) < THRESHHOLD;
+    }
+
+    private Line2D getLine2D() {
+       return new Line2D.Float((float)getP1().getX(),
+                                (float)getP1().getY(),
+                                (float)getP2().getX(),
+                                (float)getP2().getY());
+    }
+
+    public Shape getShape() {
+        return getLine2D();
+    }
+}
+
diff --git a/docs/teaching/exercises/figures/Point.java b/docs/teaching/exercises/figures/Point.java
new file mode 100644 (file)
index 0000000..63126d9
--- /dev/null
@@ -0,0 +1,58 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public class Point extends ShapeFigureElement {
+    private int _x;
+    private int _y;
+
+    public Point(int x, int y) {
+        _x = x;
+        _y = y;
+    }
+
+    public int getX() { return _x; }
+
+    public int getY() { return _y; }
+
+    public void setX(int x) { _x = x; }
+
+    public void setY(int y) { _y = y; }
+
+    public void move(int dx, int dy) {
+        _x += dx;
+        _y += dy;
+    }
+
+    public String toString() {
+        return "Point(" + _x + ", " + _y + ")";
+    }
+
+    /** The height of displayed {@link Point}s. */
+    private final static int HEIGHT = 10;
+
+    /** The width of displayed {@link Point}s. -- same as {@link HEIGHT}. */
+    private final static int WIDTH  = Point.HEIGHT;
+
+    public Shape getShape() {
+       return new Ellipse2D.Float((float)getX()-Point.WIDTH/2,
+                                   (float)getY()-Point.HEIGHT/2,
+                                   (float)Point.HEIGHT,
+                                   (float)Point.WIDTH);
+    }
+}
+
diff --git a/docs/teaching/exercises/figures/ShapeFigureElement.java b/docs/teaching/exercises/figures/ShapeFigureElement.java
new file mode 100644 (file)
index 0000000..b09bad1
--- /dev/null
@@ -0,0 +1,47 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public abstract class ShapeFigureElement implements FigureElement {
+    public abstract void move(int dx, int dy);
+
+    public abstract Shape getShape();
+
+    public Rectangle getBounds() {
+        return getShape().getBounds();
+    }
+
+    public boolean contains(Point2D p) {
+        return getShape().contains(p);
+    }
+
+    public Color getLineColor() {
+        return Color.black;
+    }
+
+    public Color getFillColor() {
+        return Color.red;
+    }
+
+    public final void paint(Graphics2D g2) {
+        Shape shape = getShape();
+        g2.setPaint(getFillColor());
+        g2.fill(shape);
+        g2.setPaint(getLineColor());
+        g2.draw(shape);
+    }
+}
diff --git a/docs/teaching/exercises/figures/SlothfulPoint.java b/docs/teaching/exercises/figures/SlothfulPoint.java
new file mode 100644 (file)
index 0000000..ede073b
--- /dev/null
@@ -0,0 +1,50 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+/**
+ * This class makes mistakes to be caught by invariant checkers.
+ */
+public class SlothfulPoint extends ShapeFigureElement {
+    private int _x;
+    private int _y;
+
+    public SlothfulPoint(int x, int y) {
+    }
+
+    public int getX() { return _x; }
+
+    public int getY() { return _y; }
+
+    public void setX(int x) { }
+
+    public void setY(int y) { }
+
+    public void move(int dx, int dy) {
+       System.out.println("Slothful moving");
+    }
+
+    public String toString() {
+        return "SlothfulPoint";
+    }
+
+    public Shape getShape() {
+       return new Ellipse2D.Float((float)_x,
+                                   (float)_y, 1.0f, 1.0f);
+    }
+}
+
diff --git a/docs/teaching/exercises/figures/gui/FigurePanel.java b/docs/teaching/exercises/figures/gui/FigurePanel.java
new file mode 100644 (file)
index 0000000..4746bc0
--- /dev/null
@@ -0,0 +1,181 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package figures.gui;
+
+import figures.Point;
+import figures.Line;
+import figures.FigureElement;
+import figures.Group;
+
+
+import java.awt.*;
+import java.awt.geom.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.text.*;
+import javax.swing.border.*;
+
+public class FigurePanel extends JComponent {
+
+    ButtonsPanel bp = new ButtonsPanel();
+    FigureSurface fs = new FigureSurface();
+    ConsolePanel cp = new ConsolePanel();
+
+
+    public FigurePanel() {
+        setLayout(new BorderLayout());
+        JPanel panel = new JPanel();
+        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+        panel.add(fs);
+        panel.add(bp);
+        JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, panel, cp);
+        sp.setPreferredSize(new Dimension(500, 400));
+        sp.setDividerLocation(250);
+        add(BorderLayout.CENTER, sp);
+    }
+
+    class ButtonsPanel extends JPanel {
+        JLabel msgs = new JLabel("click to add a point or line");
+        public ButtonsPanel() {
+            setLayout(new FlowLayout(FlowLayout.LEFT));
+            add(new JButton(new AbstractAction("Main") {
+                    public void actionPerformed(ActionEvent e) {
+                        Main.main(new String[]{});
+                        fs.repaint();
+                    }
+                }));
+            add(msgs);
+        }
+
+        public void log(String msg) {
+            msgs.setText(msg);
+        }
+    }
+
+    static class ConsolePanel extends JPanel {
+
+        JTextArea text = new JTextArea();
+
+        public ConsolePanel() {
+            super(new BorderLayout());
+            text.setFont(StyleContext.getDefaultStyleContext().getFont("SansSerif", Font.PLAIN, 10));
+            JScrollPane scroller = new JScrollPane(text);
+            scroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+            add(BorderLayout.CENTER, scroller);
+        }
+
+        public void println(String msg) {
+            text.append(msg + '\n');
+        }
+    }
+
+    final static Color BACKGROUND = Color.white;
+
+    static class FigureSurface extends JPanel implements MouseListener, MouseMotionListener {
+        Group canvas;
+
+        public FigureSurface() {
+            canvas = new Group(new Point(250, 250));
+            addMouseMotionListener(this);
+            addMouseListener(this);
+            setPreferredSize(new Dimension(500,500));
+        }
+
+        private Point addPoint(int x, int y) {
+            Point p = new Point(x, y);
+            canvas.add(p);
+            repaint();
+            return p;
+        }
+
+        private Line addLine(Point p1, Point p2) {
+            if (Math.abs(p1.getX()-p2.getX()) < 5 ||
+                Math.abs(p1.getY()-p2.getY()) < 5) {
+                return null;
+            }
+
+            Line line = null;
+            if (p1 != null && p2 != null) {
+                line = new Line(p1, p2);
+                canvas.add(line);
+            }
+            repaint();
+            return line;
+        }
+
+        public void paint(Graphics g) {
+            Graphics2D g2 = (Graphics2D) g;
+            g2.setPaint(BACKGROUND);
+            g2.fill(new Rectangle2D.Float(0f, 0f, (float)g2.getClipBounds().width, (float)g2.getClipBounds().height));
+            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+            canvas.paint(g2);
+        }
+
+
+        int lastX, lastY;
+        int pressX, pressY;
+
+        FigureElement first = null;
+        Point point1 = null;
+
+        public void mousePressed(MouseEvent e){
+            int x = e.getX(), y = e.getY();
+            pressX = lastX = x; pressY = lastY = y;
+            first = findFigureElement(x, y);
+            if (first == null) {
+                point1 = addPoint(x, y);
+            }
+        }
+
+        public void mouseDragged(MouseEvent e) {
+            int x = e.getX(), y = e.getY(), dx = lastX-x, dy = lastY-y;
+            lastX = x;
+            lastY = y;
+            if (first == null) {
+                Line line = addLine(point1, new Point(x, y));
+                if (line != null) {
+                    canvas.add(line.getP2());
+                    first = line.getP2();
+                    canvas.add(line);
+                }
+            } else {
+                first.move(-dx, -dy);
+            }
+            repaint();
+        }
+
+        public void mouseReleased(MouseEvent e){
+            mouseDragged(e);
+            first = null;
+            point1 = null;
+        }
+
+
+        public void mouseMoved(MouseEvent e){}
+        public void mouseClicked(MouseEvent e){}
+        public void mouseExited(MouseEvent e){}
+        public void mouseEntered(MouseEvent e){}
+
+        private FigureElement findFigureElement(int x, int y) {
+            Point2D p = new Point2D.Float((float)x, (float)y);
+            for (Iterator i = canvas.members(); i.hasNext(); ) {
+                FigureElement fe = (FigureElement)i.next();
+                if (fe.contains(p)) return fe;
+            }
+            return null;
+        }
+    }
+}
diff --git a/docs/teaching/exercises/figures/gui/LogAdapter.java b/docs/teaching/exercises/figures/gui/LogAdapter.java
new file mode 100644 (file)
index 0000000..9d7d7d9
--- /dev/null
@@ -0,0 +1,25 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package figures.gui;
+
+import support.Log;
+
+aspect LogAdapter {
+
+    before(String s): call(void Log.log(String)) && args(s) {
+        if (Main.panel != null) {
+            Main.panel.cp.println(s);
+        }
+    }
+}
diff --git a/docs/teaching/exercises/figures/gui/Main.java b/docs/teaching/exercises/figures/gui/Main.java
new file mode 100644 (file)
index 0000000..c2d41c3
--- /dev/null
@@ -0,0 +1,31 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package figures.gui;
+
+import javax.swing.*;
+import support.Log;
+
+public class Main {
+    static FigurePanel panel;
+
+    public static void main(String[] args) {
+        JFrame figureFrame = new JFrame("Figure Editor");
+        panel = new FigurePanel();
+        figureFrame.setContentPane(panel);
+        figureFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        figureFrame.pack();
+        figureFrame.setVisible(true);
+    }
+
+}
diff --git a/docs/teaching/exercises/guibase.lst b/docs/teaching/exercises/guibase.lst
new file mode 100644 (file)
index 0000000..0a93714
--- /dev/null
@@ -0,0 +1,5 @@
+-argfile
+base.lst
+figures/gui/FigurePanel.java
+figures/gui/Main.java
+figures/gui/LogAdapter.java
\ No newline at end of file
diff --git a/docs/teaching/exercises/index.html b/docs/teaching/exercises/index.html
new file mode 100644 (file)
index 0000000..4dff3da
--- /dev/null
@@ -0,0 +1,769 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html> <head>
+<title>AspectJ Tutorial Exercises</title>
+</head>
+
+<body bgcolor="white">
+<h1>AspectJ Tutorial Exercises</h1>
+
+<h3>Organization</h3>
+
+<p> The exercises work with a figure editor together with JUnit test
+cases.  They progress, as most users do in their adoption of AspectJ,
+from non-functional, development-only aspects to aspects which augment
+a deployed program with crosscutting features.  </p>
+
+<p> We have made available a package that includes the tests, the base
+code, JUnit, and a distribution of AspectJ.  All it needs is
+information about where Java lives (so set your JAVA_HOME environment
+variable).  It assumes that you unzip it in c:\ (on Windows) or in
+your home directory (on Linux): If you put it somewhere else, edit
+setpaths or setpaths.bat, as appropriate.  Once all this is done, run
+<code>setpaths.bat</code> or <code>source setpaths</code> to export
+some other needed environment variables. </p>
+
+<p> All the files in the program are listed in base.lst, including
+test cases and an empty answer aspect,
+<code>answers/Answer.java</code>.  Therefore, if you write your
+answers there, all you need to do is compile base.lst, either in an
+IDE or with </p>
+
+<blockquote><PRE>
+$ ajc -Xlint -argfile base.lst
+</PRE></blockquote>
+
+<p> Before you move onto another exercise, though, make sure to copy
+your answer into a different file so we can discuss the answers
+together:
+</p>
+
+<blockquote><PRE>
+&gt; copy answers/Answer.java answers/2a.java  (Windows)
+$ cp answers/Answer.java answers/2a.java    (Linux)
+</PRE></blockquote>
+
+<p> If you want to put your answer in a different file, say,
+<code>answers/Answer2a.java</code>, you can compile with </p>
+
+<blockquote><PRE>
+$ ajc -Xlint -argfile base.lst answers/Answer2a.java
+</PRE> </blockquote>
+
+<p> In any case, after building the system, you should invoke Java on
+the compiled test class.  On the command-line, this this would be </p>
+
+<blockquote><PRE>
+$ java tests.Test2a
+</PRE> </blockquote>
+
+<p> (For these exercises, when we give examples of execution we will
+show the command-line use, but of course if you are using JBuilder,
+Forte/NetBeans, Emacs, or Eclipse, use the appropriate compile and
+execute tools.)  </p>
+
+<p> The default test, <code>tests.Test</code>, performs some
+rudimentary tests on figure elements, and so is a useful test to run
+periodically.  Looking at the JUnit tests for each exercise may also
+be helpful. </p>
+
+<p> Again, ae will be looking at some solutions and having discussion,
+which is much more difficult without incremental solutions.  So when
+you go from one exercise to the next, make sure to save your work in a
+file and go on to work in a different file, even if you plan to
+duplicate some code.  </p>
+
+<hr>
+<!-- page break  -->
+<h2>1. Static Invariants</h2>
+
+<h3>a. Catch old tracing</h3>
+
+<p> The way that we are all taught to print "hello world" from Java is
+to use <code>System.out.println()</code>, so that is what we typically
+use for one-off debugging traces.  It's a common mistake to leave
+these in your system longer than is necessary.  Type in the aspect
+below to forces an error at compile time if this mistake is made.
+</p>
+
+<p> When you use this on the given system, you'll find one incorrect
+trace in <code>SlothfulPoint</code>.  
+</p>
+
+<blockquote><PRE>
+$ ajc -argfile base.lst
+./figures/SlothfulPoint.java:29:9: illegal access to System.out
+        System.out.println("Slothful moving");
+               ^
+1 errors
+</PRE></blockquote>
+
+<p> Remove the illegal tracing call. 
+</p>
+
+<p> Make sure your program still passes the JUnit test
+<code>tests.Test</code> (which it should also pass at the beginning of
+all exercises) before continuing.  </p>
+
+<blockquote><PRE>
+$ java tests.Test
+....
+Time: 0.076
+
+OK (4 tests)
+</PRE></blockquote>
+
+<p> <strong>Answer:</strong>
+</p>
+
+<blockquote><PRE>
+package answers;
+
+import figures.*;
+
+aspect Answer1a {
+    declare error
+        : get(java.io.PrintStream System.out) &amp;&amp; within(figures..*)
+        : "illegal access to System.out";
+}
+</PRE></blockquote>
+
+<p> Note that this answer does not say that the <em>call</em> to the
+<code>println()</code> method is incorrect, rather, that the field get
+of the <code>out</code> field is illegal.  This will also catch those
+users who bind System.out to a static field to save typing.  </p>
+
+
+<h3>b. Mandate setters</h3>
+
+<p> One common coding convention is that no private field should be
+set outside of setter methods.  Write an aspect to warn at compile
+time when such an illegal assignment expression exists.  </p>
+
+<p> This is going to look like
+</p>
+
+<pre>
+aspect A {
+    declare warning: <em>&lt;pointcut here&gt;</em> : "bad field set";
+}
+</pre>
+
+<p> where the pointcut picks out join points of private field sets
+outside of setter methods.  "Outside", here, means that the code for
+the assignment is outside the <em>text</em> of the setter (a setter is
+a method that looks like "void set*(..)"), so check out the quick
+reference for <code>set</code> and <code>withincode</code> primitive
+pointcuts.  ) </p>
+
+<p> Make sure your program still passes the JUnit test
+<code>tests.Test</code> before continuing, and that you see all of the
+following warning messages.  You'll notice a LOT of warnings here.
+Wait to fix them until the next exercise...
+</p>
+
+<pre>
+.\figures\Box.java:17:9: bad field set (warning)
+        _p0 = new Point(x0, y0);
+        ^
+.\figures\Box.java:18:9: bad field set (warning)
+        _p1 = new Point(x0+width, y0);
+        ^
+.\figures\Box.java:19:9: bad field set (warning)
+        _p2 = new Point(x0+width, y0+height);
+        ^
+.\figures\Box.java:20:9: bad field set (warning)
+        _p3 = new Point(x0, y0+height);
+        ^
+.\figures\Group.java:16:23: bad field set (warning)
+        this._members = new ArrayList();
+                      ^
+.\figures\Line.java:15:9: bad field set (warning)
+        _p1 = p1;
+        ^
+.\figures\Line.java:16:9: bad field set (warning)
+        _p2 = p2;
+        ^
+.\figures\Point.java:15:9: bad field set (warning)
+        _x = x;
+        ^
+.\figures\Point.java:16:9: bad field set (warning)
+        _y = y;
+        ^
+.\figures\Point.java:28:9: bad field set (warning)
+        _x += dx;
+        ^
+.\figures\Point.java:29:9: bad field set (warning)
+        _y += dy;
+        ^
+</pre>
+
+
+<h3>c. Refine setters mandate</h3>
+
+<p> Look at some of the warnings.  Notice that a lot of them are from
+within constructors.  Actually, the common coding convention is that
+no private field should be set outside of setter methods <b>or
+constructors</b>.  Modify your answer (in a new file) to signal an
+actual error at compile time (rather than just a warning) when such an
+illegal assignment expression exists.  </p>
+
+<p>You'll want to add another <code>withincode</code> primitive
+pointcut to deal with the constructors. 
+</p>
+
+<p>After you specify your pointcut correctly, you'll still find that
+the convention is violated twice in the figures package.  You should see
+the following two errors:</p>
+
+<pre>
+.\figures\Point.java:28:9: bad field set
+        _x += dx;
+        ^
+.\figures\Point.java:29:9: bad field set
+        _y += dy;
+        ^
+2 errors
+</pre>
+
+<p> (If you see more, go back to 1b; you may be capturing sets to
+too many fields.)
+</p>
+
+<p>Rewrite these two occurrences so as not to violate
+the convention.  Make sure your program still passes the JUnit test
+<code>tests.Test</code> before continuing.  </p>
+
+<h3>d. Re-refine setters mandate</h3>
+
+<p> In part (c), you rewrote the code to fit the convention enforced
+by the aspect. It may be that this code doesn't violate the convention
+of your mythical organization.  Try to instead fix the pointcut so it
+doesn't signal an error for these two assignments, and then change
+your code back to making the assignments.  </p>
+
+<p> Make sure your program still passes the JUnit test
+<code>tests.Test</code> before continuing.  </p>
+
+<h3>Help Yourself by Helping Others</h3>
+
+<p> At this point, check the people to your left and right.  If
+they're stuck somewhere, see if you can help them.  </p>
+
+
+<!-- ============================== -->
+
+<hr />
+
+<h2>2. Dynamic invariants</h2>
+
+
+<h3>a. Check a simple precondition</h3>
+
+<p> Write an aspect to throw an <code>IllegalArgumentException</code>
+whenever an attempt is made to set one of <code>Point</code>'s
+<code>int</code> fields to a value that is either too large (greater
+than <code>FigureElement.MAX_VALUE</code>) or too small (less than
+<code>FigureElement.MIN_VALUE</code>).  </p>
+
+<p> This should make the test case of <code>tests.Test2a</code> pass,
+which wouldn't without your aspect.  So before compiling in the
+aspect, 
+</p>
+
+<blockquote><PRE>
+$ ajc -Xlint -argfile base.lst
+
+$ java tests.Test2a
+.F.F.F....
+Time: 0.099
+There were 3 failures:
+1) testTooSmall(tests.Test2a)junit.framework.AssertionFailedError: should have thrown IllegalArgumentException
+2) testTooBig(tests.Test2a)junit.framework.AssertionFailedError: should have thrown IllegalArgumentException
+3) testMove(tests.Test2a)junit.framework.AssertionFailedError: should have thrown IllegalArgumentException
+
+FAILURES!!!
+Tests run: 7,  Failures: 3,  Errors: 0
+</PRE></blockquote>
+
+<p> But after compiling in the aspect...
+</p>
+
+<blockquote><PRE>
+$ ajc -Xlint -argfile base.lst
+
+$ java tests.Test2a
+.......
+Time: 0.097
+
+OK (7 tests)
+</PRE></blockquote>
+
+<p> <strong>Answer:</strong>  
+</p>
+
+<blockquote><PRE>
+package answers;
+
+import figures.*;
+
+aspect Answer2a {
+    before(int newValue): set(int Point.*) &amp;&amp; args(newValue) {
+        if (newValue &lt; FigureElement.MIN_VALUE) {
+            throw new IllegalArgumentException("too small");
+        } else if (newValue &gt; FigureElement.MAX_VALUE) {
+            throw new IllegalArgumentException("too large");
+        }
+    }
+}
+</PRE></blockquote>
+
+<h3>b. Check another precondition</h3>
+
+<p> <code>Group</code> is a <code>FigureElement</code> class that
+encapsulates groups of other figure elements.  As such, only actual
+figure element objects should be added to <code>Group</code> objects.  Write
+an aspect to throw an <code>IllegalArgumentException</code> whenever
+<code>Group.add()</code> is called with a
+<code>null</code> value.  If you look at the source code for
+tests/Test2b.java, you'll see an example of the desired behavior,
+i.e. </p>
+
+<pre>
+    public void testNull() {
+        try {
+           g.add(null);
+            fail("should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException ea) {
+        }
+    }
+</pre>
+
+<p> For each of these exercises, you'll find that the corresponding
+test case provides that most concrete example of the desired behavior
+for your aspect.  Please avail yourself of this resource. </p>
+
+<p> With this aspect in place, your code should pass
+<code>tests.Test2b</code>. 
+</p>
+
+<h3>c. Check yet another precondition</h3>
+
+<p> Another constraint on a well-formed group is that it should not
+contain itself as a member (though it may contain other groups). Write
+an aspect to throw an <code>IllegalArgumentException</code> whenever
+an attempt is made to call <code>Group.add()</code> on a
+<code>null</code> value, or on the group itself. </p>
+
+<p> You will want to use a <code>target</code> pointcut to expose the
+<code>Group</code> object that is the target of the <code>add</code>
+call. 
+</p>
+
+<p> With this aspect in place, your code should pass
+<code>tests.Test2c</code>. 
+</p>
+
+<h3>d. Check a simple postcondition</h3>
+
+<p> One of the simplest postconditions to check is that a setter
+actually sets its value.  Write an aspect that throws a
+<code>java.lang.RuntimeException</code> if, after calling
+<code>setX()</code> on <code>SlothfulPoint</code> objects,
+<code>getX()</code> doesn't return the new value. </p>
+
+<p> You'll want to use an <code>args</code> pointcut to expose the
+argument to <code>setX()</code> and a <code>target</code> pointcut to
+expose the <code>SlothfulPoint</code> object itself (so you can later
+call <code>getX()</code> on it).  
+</p>
+
+<p> An interesting question to think about for discussion is whether
+this postcondition should apply when getX() throws an exception, or
+when it returns normally, or both?  </p>
+
+<p> With this aspect in place, your code should pass
+<code>tests.Test2d</code>. 
+</p>
+
+<h3>e. Check invariant</h3>
+
+<p> There is a method on the <code>Box</code> class, <code>void
+checkBoxness()</code>, that checks whether the four points making up a
+box are correctly positioned relative to each other (i.e., they form a
+rectangle).  Write an aspect that will make sure that after every time
+the <code>void move(int, int)</code> method on <code>Box</code> is
+called, that you also call <code>Box.checkBoxness()</code> to ensure
+that the <code>move</code> didn't break this invariant. </p>
+
+<p> With this aspect in place, your code should pass
+<code>tests.Test2e</code>. 
+</p>
+
+<h3>f. Refine your invariant</h3>
+
+<p> <code>move</code> is not the only interesting method on
+<code>Box</code>.  It may be that a box gets malformed between calls
+to <code>move</code>.  So instead of checking boxness only 
+after the <code>move</code> method of <code>Box</code>, check
+after the call to every one of <code>Box</code>'s public methods.
+</p>
+
+<p> When testing this aspect, you may find yourself facing a
+<code>StackOverflowException</code>.  If so, carefully look at your
+pointcuts.  Needless to say, there should not be an infinite loop in
+your program.  You might want to look at using a <code>within</code>
+pointcut for a filter. </p>
+
+<p> (You might even find that this test case aborts with no message,
+i.e., 
+</p>
+
+<blockquote><pre>
+$ java tests.test2f
+.
+$
+</pre></blockquote>
+
+<p> this is a bug in Sun's JVM where a particular stack overflow
+causes the VM to abort.)
+</p>
+
+<p> Make sure to pass the JUnit test <code>tests.Test2f</code>
+before continuing.  </p>
+
+
+<h3>g. Assure input</h3>
+
+<p> Instead of throwing an exception when one of <code>Point</code>'s
+<code>int</code> fields are set to an out-of-bounds value, write an
+aspect to trim the value into an in-bounds one.  You'll want to use
+<code>around</code> advice that exposes the new value of the field
+assignment with an <code>args</code> pointcut, and
+<code>proceed</code> with the trimmed value. Becuase this is tricky,
+type in the below aspect... the trick for this exercise is not to come
+up with an answer, but to understand the answer. </p>
+
+<p> Make sure to pass the JUnit test <code>tests.Test2g</code>
+before continuing.  </p>
+
+<p> <strong>Answer: </strong>
+</p>
+
+<blockquote><PRE>
+package answers;
+
+import figures.*;
+
+aspect Answer2g {
+    int around(int val):
+            (set(int Point._x) || set(int Point._y))
+            &amp;&amp; args(val) {
+        return proceed(trim(val));
+    }
+
+    private int trim(int val) {
+        return Math.max(Math.min(val, FigureElement.MAX_VALUE),
+                        FigureElement.MIN_VALUE);
+    }
+}
+</PRE></blockquote>
+
+
+<h3>h. Check another invariant</h3>
+
+<p> <code>FigureElement</code> objects have a <code>getBounds()</code>
+method that returns a <code>java.awt.Rectangle</code> representing the
+bounds of the object.  An important postcondition of the
+<code>move</code> operation is that the figure element's bounds
+rectangle should move by the same amount as the figure itself.  Write
+an aspect to check for this postcondition -- throw an
+<code>IllegalStateException</code> if it is violated.  </p>
+
+<p> Note that because we're dealing with how the bounds changes during
+move, we need some way of getting access to the bounds both before
+<em>and</em> after the move, in one piece of advice.  Also, note that
+you can create a copy of a figure element's bounds rectangle with
+<code>new Rectangle(fe.getBounds())</code>, and you can move a bounds
+rectangle <code>rect</code> with <code>rect.translate(dx,
+dy)</code>. </p>
+
+<p> Make sure to pass the JUnit test <code>tests.Test2h</code>
+before continuing.  </p>
+
+
+<h3>Help Yourself by Helping Others</h3>
+
+<p> At this point, check the people to your left and right.  If
+they're stuck somewhere, see if you can help them.  </p>
+
+<!-- ============================== -->
+
+<hr />
+<!-- page break -->
+
+<h2>3.  Tracing</h2>
+
+<p> The crosscutting feature you will be adding in part (4) will be
+support for caching the bound objects of <code>Group</code> figure
+elements, which may be costly to compute.  On the way to that, though,
+it's useful to explore the system with some tracing aspects.  </p>
+
+<h3>a. Simple tracing</h3>
+
+<p> Write an aspect to trace whenever a <code>Point</code> is moved.
+To do this, use the utility class <code>Log</code> (with an import
+from <code>support.Log</code>) and call </p>
+
+<blockquote><PRE>
+Log.log("moving")
+</PRE></blockquote>
+
+<p> This will write the string "moving", followed by a semicolon
+terminator, to the Log. For example, with your aspect enabled,
+</p>
+
+<blockquote><PRE>
+Point p1 = new Point(10, 100);
+p1.move(37, 8);
+System.out.println(Log.getString());
+</PRE></blockquote>
+
+<p> should print out "moving;".  
+</p>
+
+<p> Test this with the JUnit test case <code>tests.Test3a</code>.
+Without adding any aspects, this test should fail: </p>
+
+<blockquote><PRE>
+$ ajc -Xlint -argfile base.lst 
+$ java tests.Test3a
+..F.......
+Time: 0.07
+There was 1 failure:
+1) testMovePointLog(tests.Test3a)junit.framework.AssertionFailedError: expected:&lt;set;&gt; but was:&lt;&gt;
+        at tests.Test3a.testMovePointLog(Test1a.java:30)
+        at tests.Test3a.main(Test1a.java:16)
+
+FAILURES!!!
+Tests run: 9,  Failures: 1,  Errors: 0
+</PRE></blockquote>
+
+<p> But with the proper aspect added to the compilation, (in this
+case, <code>answers/Answer3a.java</code>, but you should feel free to
+use more evocative names), the test should pass </p>
+
+<blockquote><PRE>
+$ ajc -Xlint -argfile base.lst answers/Answer3a.java
+$ java tests.Test3a
+.........
+Time: 0.089
+
+OK (9 tests)
+</PRE></blockquote>
+
+<p> <strong>Answer: </strong>
+</p>
+
+<blockquote><PRE>
+package answers;
+
+import support.Log;
+import figures.*;
+
+aspect Answer3a {
+    before(): execution(void Point.move(int, int)) {
+        Log.log("moving");
+    }
+}
+</PRE></blockquote>
+
+<h3>b. More complex tracing</h3>
+
+<p> Write an aspect to trace whenever a <code>Point</code> is added to
+a group (including initially).  To do this, use the utility class
+<code>Log</code> (with an import from <code>support.Log</code>) and
+call </p>
+
+<blockquote><PRE>
+Log.log("adding Point")
+</PRE></blockquote>
+
+<p> This will write the string "adding Point", followed by a semicolon
+terminator, to the Log. For example, with your aspect enabled, </p>
+
+<blockquote><PRE>
+Point p1 = new Point(10, 100);
+Point p2 = new Point(10, 100);
+Group g = new Group(p1);
+g.add(p2);
+System.out.println(Log.getString());
+</PRE></blockquote>
+
+<p> should print out "adding Point;adding Point;".  
+</p>
+
+<p> <em>Hint: The <code>args</code> pointcut allows you to select join points
+based on the type of a parameter to a method call. </em> </p>
+
+<p> Test this with the JUnit test case <code>tests.Test3b</code>.
+
+
+<h3>c. Keeping track of state</h3>
+
+<p> In this exercise, perform the tracing from part (a), but also log
+the enclosing group, if any, of the moving point.  You can use an
+inter-type declaration inside your aspect to associate a
+<code>Group</code> field with <code>Point</code> objects, and then
+work with that field, setting it appropriately when the
+<code>Point</code> is added to a <code>Group</code> (at the same join
+points you were tracing in part b).  So </p>
+
+<blockquote><PRE>
+Point p1 = new Point(10, 100);
+p1.move(0, 0);
+System.out.println(Log.getString());
+</PRE></blockquote>
+
+<p> should print out "moving as a part of null;", but   
+</p>
+
+<blockquote><PRE>
+Point p1 = new Point(10, 100);
+Group g = new Group(p1);
+p1.move(0, 0);
+System.out.println(Log.getString());
+</PRE></blockquote>
+
+<p> should print out "moving as a part of Group(Point(10, 100));",
+which you can do by using the toString() method already defined on
+Group.  </p>
+
+<p> <em> Hint: This exercise combines the tracing from parts a and b.
+If you start with an aspect that includes the solutions to those
+previous exercises, you'll be most of the way there. </em> </p>
+
+<p> Test this with the JUnit test case <code>tests.Test3c</code>.
+
+
+<h3>Help Yourself by Helping Others</h3>
+
+<p> At this point, check the people to your left and right.  If
+they're stuck somewhere, see if you can help them.  </p>
+
+
+<!-- ============================== -->
+
+<hr />
+
+<!-- page break -->
+<h3>4.  Caching</h3>
+
+<p> Computation of the bounding box of <code>Group</code> objects
+needs to deal with all aggregate parts of the group, and this
+computation can be expensive.  In this section, we will explore
+various ways of reducing this expense. </p>
+
+<p> <strong>Optional</strong>: In all of these exercises, you should
+only deal with points that are added directly to Groups, rather than
+those that are added "indirectly" through Lines and Boxes.  You should
+handle those points contained in Lines and Boxes only if time permits.
+</p>
+
+<h3>a. Make a constant override</h3>
+
+<p> <code>Group</code>'s <code>getBounds()</code> method could be
+understood to be a conservative approximation of the bounding box of a
+group.  If that is true, then it would be a legal (and much faster)
+implementation of <code>getBounds()</code> to simply always return a
+rectangle consisting of the entire canvas, that is
+</p>
+
+<blockquote><PRE>
+new Rectangle(FigureElement.MIN_VALUE, FigureElement.MIN_VALUE, 
+              FigureElement.MAX_VALUE - FigureElement.MIN_VALUE,
+              FigureElement.MAX_VALUE - FigureElement.MIN_VALUE)
+</PRE></blockquote>
+
+<p> Write an aspect to implement this change.  You can override
+<code>Group</code>'s <code>getBounds()</code> method entirely with
+around advice intercepting the method.  
+</p>
+
+<p> Your code should pass the JUnit test case
+<code>tests.Test4a</code> with this change.
+</p>
+
+<p> <strong>Answer: </strong>
+</p>
+
+<blockquote><PRE>
+package answers;
+
+import figures.*;
+import java.awt.Rectangle;
+
+aspect Answer4a {
+    private Rectangle wholeCanvas =
+        new Rectangle(FigureElement.MIN_VALUE, FigureElement.MIN_VALUE, 
+                      FigureElement.MAX_VALUE - FigureElement.MIN_VALUE,
+                      FigureElement.MAX_VALUE - FigureElement.MIN_VALUE);
+
+    Rectangle around(): execution(Rectangle Group.getBounds()) {
+        return wholeCanvas;
+    }
+}
+</PRE></blockquote>
+
+<h3>b. Make a constant cache</h3>
+
+<p> Instead of making the (very) conservative approximation of
+<code>getBounds()</code> from part (a), write an aspect instead that
+remembers the return value from the first time
+<code>getBounds()</code> has been called on a <code>Group</code>, and
+returns that first <code>Rectangle</code> for every subsequent
+call. </p>
+
+<p> <em>Hint: You can use an inter-type declaration to keep some
+state for every <code>Group</code> object.</em> </p>
+
+<p> Your code should pass the JUnit test case
+<code>tests.Test4b</code> with this change.
+</p>
+
+
+<h3>c. Invalidate, part 1</h3>
+
+<p> While caching in this way does save computation, it will lead to
+incorrect bounding boxes if a <code>Group</code> is ever moved.
+Change your aspect so that it invalidates the cache whenever the
+<code>move()</code> method of <code>Group</code> is called. 
+</p>
+
+<p> Your code should pass the JUnit test case
+<code>tests.Test4c</code> with this change.
+</p>
+
+<h3>d. Invalidate, part 2</h3>
+
+<p> Of course, part (c) didn't really solve the problem.  What if a
+<code>Point</code> that is part of a <code>Group</code> moves?
+Whenever either of a Point's fields are set it should invalidate the
+caches of all enclosing groups.  Use your solution to problem 3c to
+modify your invalidation criteria in this way, but note that this is
+slightly different than the problem in 3c: Here you care about fields,
+where there you cared about method calls. </p>
+
+<p> Your code should pass the JUnit test case
+<code>tests.Test4d</code> with this change.
+</p>
+
+<h3>e. Invalidate, part 3</h3>
+
+<p> Did you really do part (d) correctly?  Run the JUnit test
+<code>tests.Test4e</code> to see.  If you pass, congratulations, now
+go help other people.  Otherwise, you have fallen prey to our cruel
+trap: Remember that whenever a point moves it should invalidate the
+caches of <em>all</em> enclosing groups.  </p>
+
+<hr>
+</body> </html>
diff --git a/docs/teaching/exercises/pre-letter.txt b/docs/teaching/exercises/pre-letter.txt
new file mode 100644 (file)
index 0000000..4833bee
--- /dev/null
@@ -0,0 +1,130 @@
+Dear OOPSLA 2002 attendee;
+
+We have you listed as being registered for tutorial T40,
+Aspect-oriented programming with AspectJ.  We are excited about giving
+this tutorial, and hope you will enjoy the presentation, exercises and
+discussion we have prepared.
+
+As with our past tutorials of this form, in the afternoon we would
+like to break the attendees into groups of two or three and work
+through a number of AspectJ exercises together.
+
+We will be bringing media and making ourselves available during breaks
+for help with setup, but in order to jump straight in and give you the
+most we can from this tutorial, it would really help us if many of you
+had an AspectJ environment installed early.
+
+This message contains basic instructions on where to get some needed
+tools.  These instructions will not take much time. 
+
+If you are planning to bring a laptop to the tutorial, would you
+please take the time to do the steps outlined in this message?  
+
+If you're not planning to, you might want to install an AspectJ
+environment on your desktop anyway and try the instructions below, so
+you will be comfortable when we meet on Wednesday.
+
+[If you already have a working AspectJ environment and are familliar
+with it, we still recommend that you upgrade to 1.0.6 and follow the
+steps below]
+
+Thank you, and please don't hesitate to contact us (at
+support@aspectj.org) if you have any questions.  See you on
+Wednesday...
+
+-Erik Hilsdale, 
+ Jim Hugunin, 
+ and the whole AspectJ Team
+
+
+Getting Ready for T40, Aspect-oriented programming with AspectJ
+--------------------------------------
+
+Overview:
+
+  0. Install AspectJ
+  1. Download JUnit and put it on your classpath
+  2. Test your setup
+  
+------------------------------
+0. AspectJ
+
+Download the AspectJ 1.0.6 from
+
+  http://aspectj.org/dl
+
+You should definitly download and intstall the tools package and the
+docs package.  If you plan to use JBuilder, Forte/NetBeans, Emacs, or
+Eclipse for your development, you should download the appropriate
+plugin.
+
+
+------------------------------
+1. JUnit
+
+We use the JUnit framework for testing our exercises.  Download JUnit
+from 
+
+   http://www.junit.org
+
+and place junit.jar on your CLASSPATH.  
+
+
+------------------------------
+2. Test your setup
+
+a. Create a file "Hello.java" with this class:
+
+    class Hello {
+        public static void main(String[] args) {
+            System.err.println(getHelloString());
+        }
+        public static String getHelloString() { 
+            return "Hello, WORLD"; 
+        }
+    }
+
+b. Compile the class with ajc and run it...
+
+    > ajc Hello.java
+    > java Hello
+    Hello, WORLD
+
+c. Create a file "TestHello.java" with this class:
+    
+    public class TestHello extends junit.framework.TestCase {
+        public TestHello(String name) {
+            super(name);
+        }
+        public static void main(String[] args) {
+            junit.textui.TestRunner.run(TestHello.class);
+        }
+        public void testHello() {
+             assertEquals("Hello, OOPSLA", Hello.getHelloString());
+        }
+    }
+
+d. Compile the class with ajc and run it...
+
+    > ajc TestHello.java
+    > java TestHello
+    .F
+    Time: 0.01
+    There was 1 failure:
+    1) testHello(TestHello)junit.framework.ComparisonFailure: 
+    expected:<...OOPSLA> but was:<...WORLD>
+            at TestHello.testHello(TestHello.java:9)
+            at TestHello.main(TestHello.java:6)
+
+    FAILURES!!!
+    Tests run: 1,  Failures: 1,  Errors: 0
+
+e. Oops... the test case seems to want a different string than the
+   tested class.  Fix that, compile whichever file you changed with
+   ajc, run the tester again, and you're done.  Thanks!
+
+    > java TestHello
+    .
+    Time: 0
+
+    OK (1 test)
diff --git a/docs/teaching/exercises/setpaths b/docs/teaching/exercises/setpaths
new file mode 100644 (file)
index 0000000..1e9a858
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh\r
+\r
+# Change this to be the full path for this directory\r
+EXTRACTION=$HOME/aj-oopsla\r
+\r
+if [ "$JAVA_HOME" = "" ] \r
+then\r
+    echo Please remember to manually set $JAVA_HOME to \r
+    echo the location of your java installation\r
+fi\r
+\r
+export ASPECTJ_HOME=$EXTRACTION/aspectj\r
+export PATH=$ASPECTJ_HOME/bin:$PATH\r
+export CLASSPATH=.:$ASPECTJ_HOME/lib/aspectjrt.jar:$EXTRACTION/junit.jar\r
diff --git a/docs/teaching/exercises/setpaths.bat b/docs/teaching/exercises/setpaths.bat
new file mode 100644 (file)
index 0000000..bfb9a80
--- /dev/null
@@ -0,0 +1,15 @@
+@echo off\r
+\r
+rem Change this to be the full path for this directory\r
+set EXTRACTION=c:\aj-oopsla\r
+\r
+if exist "%JAVA_HOME%\bin\java.exe" goto haveJava\r
+if exist "%JAVA_HOME%\bin\java.bat" goto haveJava\r
+if exist "%JAVA_HOME%\bin\java" goto haveJava\r
+echo java does not exist as %JAVA_HOME%\bin\java\r
+echo please fix the JAVA_HOME environment variable\r
+\r
+:haveJava\r
+set ASPECTJ_HOME=%EXTRACTION%\aspectj\r
+set PATH=%ASPECTJ_HOME%\bin;%PATH%\r
+set CLASSPATH=.;%ASPECTJ_HOME%\lib\aspectjrt.jar;%EXTRACTION%\junit.jar\r
diff --git a/docs/teaching/exercises/support/Log.java b/docs/teaching/exercises/support/Log.java
new file mode 100644 (file)
index 0000000..37d4d7a
--- /dev/null
@@ -0,0 +1,45 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package support;
+
+public class Log {
+    static StringBuffer data = new StringBuffer();
+
+    public static void traceObject(Object o) {
+        throw new UnsupportedOperationException();
+    }
+
+    public static void log(String s) {
+        data.append(s);
+        data.append(';');
+    }
+
+    public static void logClassName(Class _class) {
+        String name = _class.getName();
+        int dot = name.lastIndexOf('.');
+        if (dot == -1) {
+            log(name);
+        } else {
+            log(name.substring(dot+1, name.length()));
+        }
+    }
+
+    public static String getString() {
+        return data.toString();
+    }
+
+    public static void clear() {
+        data.setLength(0);
+    }
+}
diff --git a/docs/teaching/exercises/tests/Test.java b/docs/teaching/exercises/tests/Test.java
new file mode 100644 (file)
index 0000000..e4f5b60
--- /dev/null
@@ -0,0 +1,80 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class Test extends TestCase {
+    public Test(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test.class);
+    }
+
+    Box bb;
+    Point p1;
+    Point p2;
+    Line l1;
+    SlothfulPoint sloth1;
+    Group g;
+
+    public void setUp() {
+       p1 = new Point(10, 100);
+       p2 = new Point(20, 200);
+       l1 = new Line(p1, p2);
+        bb = new Box(5, 5, 10, 10);
+        sloth1 = new SlothfulPoint(0, 0);
+       g = new Group(p1);
+    }
+
+    public final void testCreate() {
+        assertEquals(p1.getX(), 10);
+        assertEquals(p1.getY(), 100);
+
+        assertEquals(l1.getP1(), p1);
+        assertEquals(l1.getP2(), p2);
+    }
+
+    public final void testSetPoint() {
+       p1.setX(20);
+        assertEquals(p1.getX(), 20);
+        assertEquals(p1.getY(), 100);
+
+       p1.setY(10);
+        assertEquals(p1.getX(), 20);
+        assertEquals(p1.getY(), 10);
+    }
+
+    public final void testMoveLine1() {
+       l1.move(40, 40);
+        assertEquals(l1.getP1(), p1);
+        assertEquals(l1.getP2(), p2);
+
+        assertEquals(p1.getX(), 50);
+        assertEquals(p1.getY(), 140);
+
+        assertEquals(p2.getX(), 60);
+        assertEquals(p2.getY(), 240);
+    }
+
+    public final void testMoveLine2() {
+       l1.move(-10, -10);
+        assertEquals(p1.getX(), 0);
+        assertEquals(p1.getY(), 90);
+
+        assertEquals(p2.getX(), 10);
+        assertEquals(p2.getY(), 190);
+    }
+}
diff --git a/docs/teaching/exercises/tests/Test1a.java b/docs/teaching/exercises/tests/Test1a.java
new file mode 100644 (file)
index 0000000..b8bb2e1
--- /dev/null
@@ -0,0 +1,55 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import support.Log;
+
+import junit.framework.*;
+
+public class Test1a extends Test {
+    public Test1a(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test1a.class);
+    }
+
+    public void setUp() {
+        Log.clear();
+        super.setUp();
+    }
+
+    public void testCreateLog() {
+        assertEquals("", Log.getString());
+    }
+
+    public void testSetXPointLog() {
+       p1.setX(20);
+        assertEquals("set;", Log.getString());
+    }
+
+    public void testSetYPointLog() {
+       p1.setY(10);
+        assertEquals("", Log.getString());
+    }
+
+    public void testGetYPointLog() {
+       p1.getY();
+        assertEquals("", Log.getString());
+    }
+
+    public void testMoveLineLog() {
+       l1.move(40, 40);
+        assertEquals("", Log.getString());
+    }
+}
diff --git a/docs/teaching/exercises/tests/Test2a.java b/docs/teaching/exercises/tests/Test2a.java
new file mode 100644 (file)
index 0000000..21ce08a
--- /dev/null
@@ -0,0 +1,55 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class Test2a extends Test {
+    public Test2a(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test2a.class);
+    }
+
+    public void setUp() {
+        super.setUp();
+    }
+
+    public void testTooSmall() {
+        try {
+            p1.setX(-10);
+            fail("should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException ea) {
+        }
+    }
+
+
+    public void testTooBig() {
+        try {
+            p1.setY(1000);
+            fail("should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException ea) {
+        }
+    }
+
+
+    public void testMove() {
+        try {
+            l1.move(-500, -500);
+            fail("should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException ea) {
+        }
+    }
+}
diff --git a/docs/teaching/exercises/tests/Test2b.java b/docs/teaching/exercises/tests/Test2b.java
new file mode 100644 (file)
index 0000000..63a10b7
--- /dev/null
@@ -0,0 +1,37 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class Test2b extends Test {
+    public Test2b(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test2b.class);
+    }
+
+    public void setUp() {
+        super.setUp();
+    }
+
+    public void testNull() {
+        try {
+           g.add(null);
+            fail("should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException ea) {
+        }
+    }
+}
diff --git a/docs/teaching/exercises/tests/Test2c.java b/docs/teaching/exercises/tests/Test2c.java
new file mode 100644 (file)
index 0000000..cfcb0d1
--- /dev/null
@@ -0,0 +1,45 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class Test2c extends Test {
+    public Test2c(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test2c.class);
+    }
+
+    public void setUp() {
+        super.setUp();
+    }
+
+    public void testNull() {
+        try {
+           g.add(null);
+            fail("should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException ea) {
+        }
+    }
+
+    public void testSelf() {
+        try {
+           g.add(g);
+            fail("should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException ea) {
+        }
+    }
+}
diff --git a/docs/teaching/exercises/tests/Test2d.java b/docs/teaching/exercises/tests/Test2d.java
new file mode 100644 (file)
index 0000000..89e47c0
--- /dev/null
@@ -0,0 +1,37 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class Test2d extends Test {
+    public Test2d(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test2d.class);
+    }
+
+    public void setUp() {
+        super.setUp();
+    }
+
+    public void testSetting() {
+        try {
+           sloth1.setX(10);
+            fail("should have thrown RuntimeException");
+        } catch (RuntimeException ea) {
+        }
+    }
+}
diff --git a/docs/teaching/exercises/tests/Test2e.java b/docs/teaching/exercises/tests/Test2e.java
new file mode 100644 (file)
index 0000000..57af085
--- /dev/null
@@ -0,0 +1,42 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class Test2e extends Test {
+    public Test2e(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test2e.class);
+    }
+
+    public void setUp() {
+        super.setUp();
+    }
+
+    public void testEasy() {
+        Box sq = new Box(0, 0, 10, 10);
+        sq.move(5,5);
+        assertEquals(sq.getP0().getX(), 5);
+        assertEquals(sq.getP0().getY(), 5);
+
+        try {
+            sq.getP0().setX(100);
+           sq.move(37, 1);
+            fail("should have thrown IllegalStateException");
+        } catch (IllegalStateException e) { }
+    }
+}
diff --git a/docs/teaching/exercises/tests/Test2f.java b/docs/teaching/exercises/tests/Test2f.java
new file mode 100644 (file)
index 0000000..da63b12
--- /dev/null
@@ -0,0 +1,42 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class Test2f extends Test {
+    public Test2f(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test2f.class);
+    }
+
+    public void setUp() {
+        super.setUp();
+    }
+
+    public void testEasy() {
+        Box sq = new Box(0, 0, 10, 10);
+        sq.move(5,5);
+        assertEquals(sq.getP0().getX(), 5);
+        assertEquals(sq.getP0().getY(), 5);
+
+        try {
+            sq.getP0().setX(100);
+            sq.getP1();
+            fail("should have thrown IllegalStateException");
+        } catch (IllegalStateException e) { }
+    }
+}
diff --git a/docs/teaching/exercises/tests/Test2g.java b/docs/teaching/exercises/tests/Test2g.java
new file mode 100644 (file)
index 0000000..7ed9ba3
--- /dev/null
@@ -0,0 +1,42 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class Test2g extends Test {
+    public Test2g(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test2g.class);
+    }
+
+    public void setUp() {
+        super.setUp();
+    }
+
+    public void testBounds() {
+        p1.setX(FigureElement.MAX_VALUE + 1);
+        assertEquals(FigureElement.MAX_VALUE, p1.getX());
+        p1.setY(FigureElement.MIN_VALUE - 1);
+        assertEquals(FigureElement.MIN_VALUE, p1.getY());
+    }
+
+    public void testBox() {
+        Box s = new Box(50, 50, 20000, 20000);
+        assertEquals(FigureElement.MAX_VALUE, s.getP2().getX());
+        assertEquals(FigureElement.MAX_VALUE, s.getP2().getY());
+    }
+}
diff --git a/docs/teaching/exercises/tests/Test2h.java b/docs/teaching/exercises/tests/Test2h.java
new file mode 100644 (file)
index 0000000..9ed695d
--- /dev/null
@@ -0,0 +1,42 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class Test2h extends Test {
+    public Test2h(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test2h.class);
+    }
+
+    public void setUp() {
+        super.setUp();
+    }
+
+    public void testSloth() {
+        FigureElement fe = new SlothfulPoint(10, 10);
+        try {
+            fe.move(10, 10);
+            fail("should have thrown IllegalStateException");
+        } catch (IllegalStateException e) { }
+    }
+
+    public void movePoints() {
+        p1.move(30, 45);
+        p2.move(10, 33);
+    }
+}
diff --git a/docs/teaching/exercises/tests/Test3a.java b/docs/teaching/exercises/tests/Test3a.java
new file mode 100644 (file)
index 0000000..3cb0632
--- /dev/null
@@ -0,0 +1,49 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import support.Log;
+
+import junit.framework.*;
+
+public class Test3a extends Test {
+    public Test3a(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test3a.class);
+    }
+
+    public void setUp() {
+        Log.clear();
+        super.setUp();
+    }
+
+    public void testCreateLog() {
+        assertEquals("", Log.getString());
+    }
+
+    public void testMovePointLog() {
+       p1.move(20, 30);
+        assertEquals("moving;", Log.getString());
+    }
+
+    public void testSetYPointLog() {
+        assertEquals("", Log.getString());
+    }
+
+    public void testGetYPointLog() {
+       p1.getY();
+        assertEquals("", Log.getString());
+    }
+}
diff --git a/docs/teaching/exercises/tests/Test3b.java b/docs/teaching/exercises/tests/Test3b.java
new file mode 100644 (file)
index 0000000..6ec933c
--- /dev/null
@@ -0,0 +1,54 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import support.Log;
+
+import junit.framework.*;
+
+public class Test3b extends Test {
+    public Test3b(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test3b.class);
+    }
+
+    public void setUp() {
+        super.setUp();
+        Log.clear();
+    }
+
+    public void testCreateLog() {
+        assertEquals("", Log.getString());
+    }
+
+    public void testCreateWithPointLog() {
+       g = new Group(p1);
+        assertEquals("adding Point;", Log.getString());
+    }
+
+    public void testCreateWithoutPointLog() {
+       g = new Group(l1);
+        assertEquals("", Log.getString());
+    }
+
+    public void testAddPointLog() {
+       g.add(p1);
+        assertEquals("adding Point;", Log.getString());
+    }
+    public void testAddNonPointLog() {
+       g.add(l1);
+        assertEquals("", Log.getString());
+    }
+}
diff --git a/docs/teaching/exercises/tests/Test3c.java b/docs/teaching/exercises/tests/Test3c.java
new file mode 100644 (file)
index 0000000..6c135e9
--- /dev/null
@@ -0,0 +1,47 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import support.Log;
+
+import junit.framework.*;
+
+public class Test3c extends Test {
+    public Test3c(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test3c.class);
+    }
+
+    public void setUp() {
+        Log.clear();
+        super.setUp();
+    }
+
+    public void testCreateLog() {
+        assertEquals("", Log.getString());
+    }
+
+    public void testMoveLonePoint() {
+       p1 = new Point(0, 0);
+       p1.move(37, 88);
+        assertEquals("moving as a part of null;", Log.getString());
+    }
+
+    public void testMoveGroupedPoint() {
+       g = new Group(p1);
+       p1.move(0, 0);
+        assertEquals("moving as a part of " + g + ";", Log.getString());
+    }
+}
diff --git a/docs/teaching/exercises/tests/Test4a.java b/docs/teaching/exercises/tests/Test4a.java
new file mode 100644 (file)
index 0000000..ddb1841
--- /dev/null
@@ -0,0 +1,38 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import java.awt.Rectangle;
+
+import junit.framework.*;
+
+public class Test4a extends Test {
+    Rectangle wholeCanvas =
+       new Rectangle(FigureElement.MIN_VALUE, FigureElement.MIN_VALUE,
+                     FigureElement.MAX_VALUE, FigureElement.MAX_VALUE);
+
+    public Test4a(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test4a.class);
+    }
+
+    public void setUp() {
+        super.setUp();
+    }
+
+    public void testGroupBounds() {
+        assertEquals(g.getBounds(), wholeCanvas);
+    }
+}
diff --git a/docs/teaching/exercises/tests/Test4b.java b/docs/teaching/exercises/tests/Test4b.java
new file mode 100644 (file)
index 0000000..6092895
--- /dev/null
@@ -0,0 +1,70 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import java.awt.Rectangle;
+
+import junit.framework.*;
+
+public class Test4b extends Test {
+
+    public Test4b(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test4b.class);
+    }
+
+    public void setUp() {
+        super.setUp();
+    }
+
+    public void testBasicEquality() {
+       assertTrue(g.getBounds() == g.getBounds());
+    }
+
+    public void testEqualityAfterAddition() {
+       Point p0 = new Point(1, 2);
+       Point p1 = new Point(2, 3);
+
+       Group g0 = new Group(p0);
+       Group g1 = new Group(p1);
+
+       Rectangle r0 = g0.getBounds();
+       Rectangle r1 = g1.getBounds();
+       assertTrue(r0 != r1);
+       g0.add(new Point(37, 90));
+       assertTrue(g0.getBounds() == r0);
+       assertTrue(g1.getBounds() != r0);
+       assertTrue(g0.getBounds() != r1);
+       assertTrue(g1.getBounds() == r1);
+
+       g1.add(new Point(4, 8));
+       assertTrue(g0.getBounds() == r0);
+       assertTrue(g1.getBounds() != r0);
+       assertTrue(g0.getBounds() != r1);
+       assertTrue(g1.getBounds() == r1);
+    }
+
+    public void testNotWholeCanvas() {
+        assertTrue("bounds for this group should not be the whole canvas",
+                   g.getBounds().getWidth() <
+                   (FigureElement.MAX_VALUE - FigureElement.MIN_VALUE));
+        assertTrue("bounds for this group should not be the whole canvas",
+                   g.getBounds().getHeight() <
+                   (FigureElement.MAX_VALUE - FigureElement.MIN_VALUE));
+
+    }
+}
+
+
diff --git a/docs/teaching/exercises/tests/Test4c.java b/docs/teaching/exercises/tests/Test4c.java
new file mode 100644 (file)
index 0000000..b5bf8f7
--- /dev/null
@@ -0,0 +1,84 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import java.awt.Rectangle;
+
+import junit.framework.*;
+
+public class Test4c extends Test {
+
+    public Test4c(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test4c.class);
+    }
+
+    public void setUp() {
+        super.setUp();
+    }
+
+    public void testBasicEquality() {
+       assertTrue(g.getBounds() == g.getBounds());
+    }
+
+    public void testEqualityAfterAddition() {
+       Point p0 = new Point(1, 2);
+       Point p1 = new Point(2, 3);
+
+       Group g0 = new Group(p0);
+       Group g1 = new Group(p1);
+
+       Rectangle r0 = g0.getBounds();
+       Rectangle r1 = g1.getBounds();
+       assertTrue(r0 != r1);
+       g0.add(new Point(37, 90));
+       assertTrue(g0.getBounds() == r0);
+       assertTrue(g1.getBounds() != r0);
+       assertTrue(g0.getBounds() != r1);
+       assertTrue(g1.getBounds() == r1);
+
+       g1.add(new Point(4, 8));
+       assertTrue(g0.getBounds() == r0);
+       assertTrue(g1.getBounds() != r0);
+       assertTrue(g0.getBounds() != r1);
+       assertTrue(g1.getBounds() == r1);
+    }
+
+    public void testEqualityAfterMove() {
+       Point p0 = new Point(1, 2);
+       Point p1 = new Point(2, 3);
+
+       Group g0 = new Group(p0);
+       Group g1 = new Group(p1);
+
+       Rectangle r0 = g0.getBounds();
+       Rectangle r1 = g1.getBounds();
+       assertTrue(r0 != r1);
+       assertTrue(g0.getBounds() == r0);
+       assertTrue(g1.getBounds() != r0);
+       assertTrue(g0.getBounds() != r1);
+       assertTrue(g1.getBounds() == r1);
+
+       g0.move(3, 1);
+       Rectangle r00 = g0.getBounds();
+       Rectangle r10 = g1.getBounds();
+
+       assertTrue(r10 != r00);
+       assertTrue(r0 != r00);
+       assertTrue(g0.getBounds() == r00);
+    }
+}
+
+
diff --git a/docs/teaching/exercises/tests/Test4d.java b/docs/teaching/exercises/tests/Test4d.java
new file mode 100644 (file)
index 0000000..e4458c6
--- /dev/null
@@ -0,0 +1,81 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import java.awt.Rectangle;
+
+import junit.framework.*;
+
+public class Test4d extends Test {
+
+    public Test4d(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test4d.class);
+    }
+
+    public void setUp() {
+        super.setUp();
+    }
+
+    public void testBasicEquality() {
+       assertTrue(g.getBounds() == g.getBounds());
+    }
+
+    public void testNonGroupMove() {
+       p1.move(3, 27);
+    }
+
+    public void testEqualityAfterAddition() {
+       Rectangle r = g.getBounds();
+       g.add(new Point(37, 90));
+       assertTrue(g.getBounds() == r);
+    }
+
+    public void testEqualityAfterMove() {
+       Point p0 = new Point(1, 2);
+       Point p1 = new Point(2, 3);
+
+       Group g0 = new Group(p0);
+       Group g1 = new Group(p1);
+
+       Rectangle r0 = g0.getBounds();
+       Rectangle r1 = g1.getBounds();
+       assertTrue(r0 != r1);
+       assertTrue(g0.getBounds() == r0);
+       assertTrue(g1.getBounds() != r0);
+       assertTrue(g0.getBounds() != r1);
+       assertTrue(g1.getBounds() == r1);
+
+       p0.move(3, 1);
+       Rectangle r00 = g0.getBounds();
+       Rectangle r10 = g1.getBounds();
+
+       assertTrue(r10 != r00);
+       assertTrue(r0 != r00);
+       assertTrue(g0.getBounds() == r00);
+    }
+
+    public void testEqualityAfterMove0() {
+       g = new Group(p1);
+       Rectangle r0 = g.getBounds();
+       assertTrue(g.getBounds() == r0);
+       p1.move(3, 1);
+       Rectangle r1 = g.getBounds();
+       assertTrue(r0 != r1);
+       assertTrue(r1 == g.getBounds());
+    }
+}
+
+
diff --git a/docs/teaching/exercises/tests/Test4e.java b/docs/teaching/exercises/tests/Test4e.java
new file mode 100644 (file)
index 0000000..f6a3635
--- /dev/null
@@ -0,0 +1,68 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import java.awt.Rectangle;
+
+import junit.framework.*;
+
+public class Test4e extends Test {
+
+    public Test4e(String name) { super(name); }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(Test4e.class);
+    }
+
+    public void setUp() {
+        super.setUp();
+    }
+
+    public void testBasicEquality() {
+       assertTrue(g.getBounds() == g.getBounds());
+    }
+
+    public void testNonGroupMove() {
+       p1.move(3, 27);
+    }
+
+    public void testEqualityAfterAddition() {
+       Rectangle r = g.getBounds();
+       g.add(new Point(37, 90));
+       assertTrue(g.getBounds() == r);
+    }
+
+    public void testEqualityAfterMove() {
+       g = new Group(p1);
+       Rectangle r0 = g.getBounds();
+       assertTrue(g.getBounds() == r0);
+       p1.move(3, 1);
+       Rectangle r1 = g.getBounds();
+       assertTrue(r0 != r1);
+       assertTrue(r1 == g.getBounds());
+    }
+
+    public void testSecondEnclosingGroup() {
+       g = new Group(p1);
+       Group h = new Group(g);
+       Rectangle r0 = h.getBounds();
+       assertTrue(h.getBounds() == r0);
+       p1.move(3, 1);
+       Rectangle r1 = h.getBounds();
+       assertTrue(r0 != r1);
+       assertTrue(r1 == h.getBounds());
+    }
+}
+
+
diff --git a/docs/teaching/oneHour.ppt b/docs/teaching/oneHour.ppt
new file mode 100644 (file)
index 0000000..c6a00c4
Binary files /dev/null and b/docs/teaching/oneHour.ppt differ
diff --git a/docs/teaching/readme.txt b/docs/teaching/readme.txt
new file mode 100644 (file)
index 0000000..f346cd4
--- /dev/null
@@ -0,0 +1,11 @@
+These presentations (oneHour.ppt, tutorial.ppt, and the teaching materials in exercises) are
+Copyright (c) 1998-2002 Palo Alto Research Center, Incorporated (PARC).
+All rights reserved. 
+
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
\ No newline at end of file
diff --git a/docs/teaching/tutorial.ppt b/docs/teaching/tutorial.ppt
new file mode 100644 (file)
index 0000000..0ba0c5b
Binary files /dev/null and b/docs/teaching/tutorial.ppt differ