aboutsummaryrefslogtreecommitdiffstats
path: root/docs/modules/ROOT/pages/teaching/exercises
diff options
context:
space:
mode:
authorAlexander Kriegisch <Alexander@Kriegisch.name>2024-01-30 10:00:56 +0700
committerAlexander Kriegisch <Alexander@Kriegisch.name>2024-01-30 12:39:24 +0700
commit5665de78868050d9964a315fb5e3628bd6696c62 (patch)
tree08449691b6329e02c2e86def4246f31bb4cb3823 /docs/modules/ROOT/pages/teaching/exercises
parente91e8f96fd620672d2fdf182a0a8708116d3464b (diff)
downloadaspectj-5665de78868050d9964a315fb5e3628bd6696c62.tar.gz
aspectj-5665de78868050d9964a315fb5e3628bd6696c62.zip
Change directory layout to suit Antora
Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
Diffstat (limited to 'docs/modules/ROOT/pages/teaching/exercises')
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/README.txt124
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer.java7
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer1a.java22
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer1b.java21
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer1c.java21
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer2a.java24
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer2b.java26
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer2c.java31
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer2d.java24
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer2e.java34
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer2f.java32
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer3a.java21
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer3b.java31
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer3c.java25
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer3d.java32
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer3e.java33
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer4a.java23
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer4b.java30
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer4c.java36
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer4d.java47
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/answers/Answer4e.java49
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/base.lst29
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/build.xml120
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/figures.zargobin0 -> 21599 bytes
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/figures/Box.java64
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/figures/FigureElement.java30
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/figures/Group.java97
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/figures/Line.java64
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/figures/Point.java58
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/figures/ShapeFigureElement.java47
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/figures/SlothfulPoint.java50
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/figures/gui/FigurePanel.java181
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/figures/gui/LogAdapter.java25
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/figures/gui/Main.java31
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/figures_classes.pngbin0 -> 15036 bytes
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/figures_classes.svg298
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/guibase.lst5
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/index.html689
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/install.txt63
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/junit.jarbin0 -> 121070 bytes
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/plugins/index.adoc19
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/plugins/index.html31
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.1.12.zipbin0 -> 80474 bytes
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0M2.zipbin0 -> 241708 bytes
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0_301_Dev.zipbin0 -> 241780 bytes
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0_31M5_Dev.zipbin0 -> 82816 bytes
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/pre-letter.txt130
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/scripts/ajbrowser3
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/scripts/ajbrowser.bat9
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/scripts/ajc3
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/scripts/ajc.bat9
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/scripts/setpaths.bat15
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/scripts/setpaths.csh11
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/scripts/setpaths.sh18
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/setpaths14
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/setpaths.bat15
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/support/Log.java33
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/CoreTest.java79
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test2a.java47
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test2b.java44
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test2c.java43
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test2d.java44
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test2e.java37
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test2f.java40
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test3a.java59
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test3b.java59
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test3c.java52
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test3d.java38
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test3e.java39
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test4a.java29
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test4b.java61
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test4c.java78
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test4d.java75
-rw-r--r--docs/modules/ROOT/pages/teaching/exercises/tests/Test4e.java62
74 files changed, 3740 insertions, 0 deletions
diff --git a/docs/modules/ROOT/pages/teaching/exercises/README.txt b/docs/modules/ROOT/pages/teaching/exercises/README.txt
new file mode 100644
index 000000000..91c8c3e52
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/README.txt
@@ -0,0 +1,124 @@
+AspectJ Figures Exercises
+------------------------------
+
+This file is really out-of-date. We're in the middle of recovery
+from OOPSLA 2004, and we need to move stuff around in this
+package. In particular, we need to build in a new structure.
+
+One idea is that we should have _four_ projects within the
+workspace, one for each problem set. There's still a bit of work
+necessary to avoid duplicating code here (in CVS) even though we
+want to duplicate code in the generated workspaces.
+
+------------------------------
+Generated Structure
+
+We want a particular _generated_ structure for users. We're
+eventually going to dump to a zip file or a CD.
+
+Folder: aj-<event>:
+ /eclipse (arch)
+ /workspace (noarch)
+ /packages (noarch)
+ j2sdk for win, linux
+ aspectj for everybody
+
+------------------------------
+Requirements for users:
+
+* We learned at OOPSLA 2004 that the system doesn't work well at
+ all under linux using the blackdown JDK. Use Sun's jdk!
+
+
+------------------------------
+------------------------------
+
+THIS FILE IS OUT-OF-DATE !!! (2003-3-17)
+
+These exercises are designed to be used with AspectJ 1.0.6.
+
+THEY MUST NOT BE DISTRIBUTED ELECTRONICALLY WITHOUT THINKING FIRST!!!
+There may be licence issues with just sticking the junit jar in there
+that I don't understand.
+
+To build distribution zips, use ant -f build.xml. This will create
+
+ EV-exercises.zip -- the contents of these exercises, minus AspectJ
+ EV-answers.zip -- some answers to these exercises.
+ EV-setup.zip -- the exercises bundled with AspectJ
+ EV-allcontent.zip -- the exercises bundled with the answers
+
+
+If you don't want to be bothered with specifying where AspectJ is,
+feel free to just do ant -f build.xml answers.zip. By default it will
+build both exercises and answers.
+
+------------------------------
+Required environment
+
+In order to actually do the exercises, the three very important files
+to have are:
+
+ EV-exercises.zip
+ aspectj-tools-1.0.6.jar
+ <some installer of java>
+
+It is almost certainly a good idea to hope that Java is already
+installed on the students' systems, but to provide two installers
+(windows and linux) anyway.
+
+ http://java.sun.com
+
+You may want to also include the rest of the AspectJ installers as
+well, but that might be a bit of a distraction
+
+ http://aspectj.org/dl
+
+These require junit.jar. I've included a copy in with the two zip
+files, but they might want to be refreshed every now and again.
+
+ http://junit.org
+
+
+------------------------------
+Printing
+
+It would be really nice to have an automated solution to generate the
+documents, but no such luck.
+
+* index.html should print out with useful page breaks. It should be
+ separated into four chunks if possible.
+
+* answers in four chunks.
+
+* quick reference sheets.
+
+Remember to have a one-sided copy of everything as a separate
+clean-copy.
+
+
+------------------------------
+Distribution
+
+ /j2sdk-1_4_1_01-linux-i586.bin
+ /j2sdk-1_4_1_01-windows-i586.exe
+ /exercises.zip containing:
+ aj-EV/src/figures.zip
+ aj-EV/src/aspectj-tools-1.0.6.jar
+ aj-EV/src/aspectj-docs-1.0.6.jar
+ aj-EV/<exploded version of figures.zip>
+ aj-EV/aspectj/<exploded version of aspectj-tools>
+ aj-EV/aspectj/<exploded version of aspectj-docs>
+ aj-EV/setpaths
+ aj-EV/setpaths.bat
+
+/bin/ajc, are edited to make sure that JAVA_HOME is used, as the
+defaults will almost certainly be wrong. setpaths scripts do what
+they look like they do. All six of these scripts are stored in
+scripts under CVS.
+
+---- Instructors
+
+Since the only difference is the answers, just overwrite the
+extraction directory with answers.zip.
+
diff --git a/docs/modules/ROOT/pages/teaching/exercises/answers/Answer.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer.java
new file mode 100644
index 000000000..d2030d398
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer.java
@@ -0,0 +1,7 @@
+package answers;
+
+import figures.*;
+
+aspect Answer {
+
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/answers/Answer1a.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer1a.java
new file mode 100644
index 000000000..09c41a28d
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer1a.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/answers/Answer1b.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer1b.java
new file mode 100644
index 000000000..95c6e130d
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer1b.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package answers;
+
+aspect Answer1b {
+ declare warning
+ : set(private * *)
+ && !withincode(* set*(..))
+ && within(figures.*)
+ : "bad field set";
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/answers/Answer1c.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer1c.java
new file mode 100644
index 000000000..f90dc8bcc
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer1c.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/answers/Answer2a.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer2a.java
new file mode 100644
index 000000000..46519a83e
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer2a.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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 < 0) {
+ throw new IllegalArgumentException("too small");
+ }
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/answers/Answer2b.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer2b.java
new file mode 100644
index 000000000..c9ba82bee
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer2b.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/answers/Answer2c.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer2c.java
new file mode 100644
index 000000000..2364aaeb0
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer2c.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/answers/Answer2d.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer2d.java
new file mode 100644
index 000000000..0d99f537f
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer2d.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package answers;
+
+import figures.*;
+
+aspect Answer2d {
+ void around(int val): (set(int Point._x) || set(int Point._y))
+ && args(val) {
+ if (val < 0)
+ val = 0;
+ proceed(val);
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/answers/Answer2e.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer2e.java
new file mode 100644
index 000000000..7da69c313
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer2e.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package answers;
+
+import figures.*;
+
+import java.awt.Rectangle;
+
+aspect Answer2e {
+ void around(Point p, int dx, int dy):
+ target(p) && call(void move(int, int)) && args(dx, dy) {
+ int preX = p.getX();
+ int preY = p.getY();
+
+ proceed(p, dx, dy);
+
+ int postX = p.getX();
+ int postY = p.getY();
+
+ if ((postX != preX + dx) || (postY != preY + dy)) {
+ throw new IllegalStateException("point didn't move properly");
+ }
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/answers/Answer2f.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer2f.java
new file mode 100644
index 000000000..f8992ccf9
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer2f.java
@@ -0,0 +1,32 @@
+/* *******************************************************************
+ * 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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package answers;
+
+import figures.*;
+
+import java.awt.Rectangle;
+
+aspect Answer2f {
+ 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/modules/ROOT/pages/teaching/exercises/answers/Answer3a.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer3a.java
new file mode 100644
index 000000000..d48924ee8
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer3a.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package answers;
+
+import support.Log;
+
+aspect Answer3a {
+ before(): execution(public * *(..)) && within(figures.*) {
+ Log.write(thisJoinPoint);
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/answers/Answer3b.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer3b.java
new file mode 100644
index 000000000..4fe3072fa
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer3b.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package answers;
+
+import support.Log;
+
+import figures.Point;
+import figures.Group;
+import figures.FigureElement;
+
+aspect Answer3b {
+ before(Object o):
+ execution(public * *(..))
+ && !execution(public String toString(..))
+ // or perhaps !cflow(adviceexecution())
+ && within(figures.*)
+ && target(o)
+ {
+ Log.write(thisJoinPoint + " at " + o);
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/answers/Answer3c.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer3c.java
new file mode 100644
index 000000000..198558d06
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer3c.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package answers;
+
+import support.Log;
+
+import figures.*;
+
+aspect Answer3c {
+ before():
+ execution(void Group.add(FigureElement))
+ && args(Point) {
+ Log.write("adding Point");
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/answers/Answer3d.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer3d.java
new file mode 100644
index 000000000..b2e74218c
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer3d.java
@@ -0,0 +1,32 @@
+/* *******************************************************************
+ * 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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package answers;
+
+import support.Log;
+
+import figures.*;
+
+aspect Answer3d {
+
+ private boolean Point.inGroup = false;
+
+ before(Point p):
+ execution(void Group.add(FigureElement))
+ && args(p) {
+ if (p.inGroup) {
+ throw new IllegalStateException();
+ } else {
+ p.inGroup = true;
+ }
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/answers/Answer3e.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer3e.java
new file mode 100644
index 000000000..505aa22c6
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer3e.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package answers;
+
+import support.Log;
+
+import figures.*;
+
+aspect Answer3e {
+
+ private Group Point.containingGroup = null;
+
+ before(Group g, Point p):
+ execution(void Group.add(FigureElement))
+ && this(g)
+ && args(p) {
+ if (p.containingGroup != null) {
+ throw new IllegalStateException(p.containingGroup.toString());
+ } else {
+ p.containingGroup = g;
+ }
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/answers/Answer4a.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer4a.java
new file mode 100644
index 000000000..99fa96cc1
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer4a.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package answers;
+
+import figures.FigureElement;
+import figures.Group;
+import java.awt.Rectangle;
+
+aspect Answer4a {
+ Rectangle around(): execution(Rectangle Group.getBounds()) {
+ return FigureElement.MAX_BOUNDS;
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/answers/Answer4b.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer4b.java
new file mode 100644
index 000000000..2e77fd862
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer4b.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/answers/Answer4c.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer4c.java
new file mode 100644
index 000000000..c9d0e8415
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer4c.java
@@ -0,0 +1,36 @@
+/* *******************************************************************
+ * 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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/answers/Answer4d.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer4d.java
new file mode 100644
index 000000000..2f019c249
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer4d.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/answers/Answer4e.java b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer4e.java
new file mode 100644
index 000000000..e3d6fa3d4
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/answers/Answer4e.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/base.lst b/docs/modules/ROOT/pages/teaching/exercises/base.lst
new file mode 100644
index 000000000..cb6914637
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/base.lst
@@ -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/Test3a.java
+tests/Test3b.java
+tests/Test3c.java
+tests/Test3d.java
+tests/Test3e.java
+tests/Test4a.java
+tests/Test4b.java
+tests/Test4c.java
+tests/Test4d.java
+tests/Test4e.java
diff --git a/docs/modules/ROOT/pages/teaching/exercises/build.xml b/docs/modules/ROOT/pages/teaching/exercises/build.xml
new file mode 100644
index 000000000..d35fd5e2a
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/build.xml
@@ -0,0 +1,120 @@
+<!--
+
+This build script will create a directory called burn that is
+_almost_ suitable for burning onto a CD. However, there
+are a number of things that should be done to this directory
+before actually burning:
+
+The PDFs in the print directory need to be manually generated.
+Use the content of foo.pdf.contents to generate foo.pdf, and
+and then delete the foo.pdf.contents directory.
+
+The powerpoint and packages directory should be populated
+with whatever you want to populate it with. The
+packages directory is typically filled with Linux installers
+and a clean AspectJ installer.
+-->
+
+<project name="build" default="burn" basedir=".">
+ <description>
+ Build a CD image containing AspectJ exercises.
+ </description>
+
+ <!-- CUSTOMIZE THESE PROPERTIES -->
+
+ <!-- this directory should hold a clean unpacked AspectJ release -->
+ <property name="aj.home" value="c:/apps/aspectj" />
+
+ <!-- this is the name of the event -->
+ <property name="aj.event" value="oopsla2004" />
+
+ <!-- NO CUSTOMIZABLE PROPERTIES BELOW HERE -->
+
+ <property name="burndir" value="burn" />
+ <property name="eventdir" value="${burndir}/aj-${aj.event}" />
+ <property name="packagedir" value="${burndir}/packages" />
+ <property name="printdir" value="${burndir}/print" />
+ <property name="powerpointdir" value="${burndir}/powerpoint" />
+
+ <!-- now real targets -->
+ <target name="burn" depends="clean,skeleton,event,answers,printables" />
+
+ <target name="printables" depends="skeleton">
+ <delete dir="${printdir}/answers.pdf.contents" />
+ <mkdir dir="${printdir}/answers.pdf.contents" />
+ <copy toDir="${printdir}/answers.pdf.contents">
+ <fileset dir="answers" includes="*.java" excludes="Answer.java"/>
+ </copy>
+
+ <delete dir="${printdir}/exercises.pdf.contents" />
+ <mkdir dir="${printdir}/exercises.pdf.contents" />
+ <copy toDir="${printdir}/exercises.pdf.contents" file="index.html" />
+ <copy toDir="${printdir}/exercises.pdf.contents" file="figures_classes.pdf" />
+ <copy toDir="${printdir}/exercises.pdf.contents" file="${aj.home}/doc/quick.pdf" />
+
+ <delete dir="${printdir}/install.pdf.contents" />
+ <mkdir dir="${printdir}/install.pdf.contents" />
+ <copy toDir="${printdir}/install.pdf.contents" file="install.txt" />
+ </target>
+
+ <target name="answers" depends="skeleton">
+ <zip destfile="${packagedir}/${aj.event}-answers.zip">
+ <zipfileset dir="answers"
+ prefix="aj-${aj.event}/answers"
+ includes="*.java"
+ excludes="Answer.java"
+ />
+ </zip>
+ </target>
+
+ <target name="event" depends="tools,exercises">
+ <filter token="aj.event" value="${aj.event}" />
+ <copy file="install.txt" toDir="${eventdir}" filtering="yes" />
+ </target>
+
+ <target name="exercises" depends="skeleton">
+ <copy toDir="${eventdir}">
+ <fileset dir="."
+ includes="junit.jar,base.lst,guibase.lst,*.html,support/**/*.java,figures/**/*.java,tests/**/*.java,answers/Answer.java"
+ />
+ </copy>
+ </target>
+
+ <target name="tools" depends="skeleton">
+ <mkdir dir="${eventdir}/aspectj" />
+ <filter token="aj.event" value="${aj.event}" />
+
+ <copy toDir="${eventdir}/aspectj">
+ <fileset dir="${aj.home}" excludes="bin/**" />
+ </copy>
+ <copy toDir="${eventdir}/aspectj/bin" filtering="yes">
+ <fileset dir="scripts" excludes="setpaths*" />
+ </copy>
+ <copy toDir="${eventdir}" filtering="yes">
+ <fileset dir="scripts" includes="setpaths*" />
+ </copy>
+ <fixcrlf srcDir="${eventdir}"
+ includes="setpaths.bat,aspectj/bin/ajbrowser.bat,aspectj/bin/ajc.bat"
+ eol="crlf" />
+ <fixcrlf srcDir="${eventdir}"
+ includes="setpaths.sh,setpaths.csh,aspectj/bin/ajbrowser,aspectj/bin/ajc"
+ eol="lf" />
+ </target>
+
+ <target name="skeleton">
+ <mkdir dir="${burndir}" />
+ <mkdir dir="${eventdir}" />
+ <mkdir dir="${packagedir}" />
+ <mkdir dir="${printdir}" />
+ <mkdir dir="${powerpointdir}" />
+ </target>
+
+ <target name="clean">
+ <delete dir="burn" />
+ </target>
+
+ <target name="javaclean">
+ <delete dir="burn" />
+ </target>
+
+</project>
diff --git a/docs/modules/ROOT/pages/teaching/exercises/figures.zargo b/docs/modules/ROOT/pages/teaching/exercises/figures.zargo
new file mode 100644
index 000000000..c042c5969
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/figures.zargo
Binary files differ
diff --git a/docs/modules/ROOT/pages/teaching/exercises/figures/Box.java b/docs/modules/ROOT/pages/teaching/exercises/figures/Box.java
new file mode 100644
index 000000000..2db991a21
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/figures/Box.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/figures/FigureElement.java b/docs/modules/ROOT/pages/teaching/exercises/figures/FigureElement.java
new file mode 100644
index 000000000..ac588f94d
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/figures/FigureElement.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public interface FigureElement {
+ public static final Rectangle MAX_BOUNDS =
+ new Rectangle(0, 0, 500, 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/modules/ROOT/pages/teaching/exercises/figures/Group.java b/docs/modules/ROOT/pages/teaching/exercises/figures/Group.java
new file mode 100644
index 000000000..f8ec65556
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/figures/Group.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/figures/Line.java b/docs/modules/ROOT/pages/teaching/exercises/figures/Line.java
new file mode 100644
index 000000000..fb3b86b65
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/figures/Line.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/figures/Point.java b/docs/modules/ROOT/pages/teaching/exercises/figures/Point.java
new file mode 100644
index 000000000..95bd63994
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/figures/Point.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/figures/ShapeFigureElement.java b/docs/modules/ROOT/pages/teaching/exercises/figures/ShapeFigureElement.java
new file mode 100644
index 000000000..8e7bd34c2
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/figures/ShapeFigureElement.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/figures/SlothfulPoint.java b/docs/modules/ROOT/pages/teaching/exercises/figures/SlothfulPoint.java
new file mode 100644
index 000000000..89f80d700
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/figures/SlothfulPoint.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/figures/gui/FigurePanel.java b/docs/modules/ROOT/pages/teaching/exercises/figures/gui/FigurePanel.java
new file mode 100644
index 000000000..6b264f42a
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/figures/gui/FigurePanel.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/figures/gui/LogAdapter.java b/docs/modules/ROOT/pages/teaching/exercises/figures/gui/LogAdapter.java
new file mode 100644
index 000000000..dbacd37ca
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/figures/gui/LogAdapter.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/figures/gui/Main.java b/docs/modules/ROOT/pages/teaching/exercises/figures/gui/Main.java
new file mode 100644
index 000000000..23330ca8a
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/figures/gui/Main.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * 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/modules/ROOT/pages/teaching/exercises/figures_classes.png b/docs/modules/ROOT/pages/teaching/exercises/figures_classes.png
new file mode 100644
index 000000000..0e3c65065
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/figures_classes.png
Binary files differ
diff --git a/docs/modules/ROOT/pages/teaching/exercises/figures_classes.svg b/docs/modules/ROOT/pages/teaching/exercises/figures_classes.svg
new file mode 100644
index 000000000..1e2587a82
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/figures_classes.svg
@@ -0,0 +1,298 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 20001102//EN' 'http://www.w3.org/TR/2000/CR-SVG-20001102/DTD/svg-20001102.dtd'>
+<svg xmlns="http://www.w3.org/2000/svg" width="1007" height="675">
+<rect x="148" y="14" width="148" height="108" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="148" y="14" width="147" height="107" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<line x1="149" y1="122" x2="296" y2="122" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<line x1="296" y1="15" x2="296" y2="121" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<rect x="148" y="14" width="148" height="19" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="148" y="14" width="147" height="18" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="189" y="29" style="font-family:Dialog; font-size:10;">
+&lt;&lt;Interface&gt;&gt;</text>
+<rect x="148" y="32" width="148" height="21" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="148" y="32" width="147" height="20" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="187" y="47" style="font-family:Dialog; font-size:10;">
+FigureElement</text>
+<rect x="149" y="32" width="146" height="2" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="149" y="32" width="145" height="1" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="148" y="52" width="148" height="70" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="148" y="52" width="147" height="69" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="150" y="68" style="font-family:Dialog; font-size:10; font-style:italic;">
+move(dx: int,dy: int) : void</text>
+<text x="150" y="85" style="font-family:Dialog; font-size:10; font-style:italic;">
+getBounds() : Rectangle</text>
+<text x="150" y="102" style="font-family:Dialog; font-size:10; font-style:italic;">
+contains(p: Point2D) : boolean</text>
+<text x="150" y="119" style="font-family:Dialog; font-size:10; font-style:italic;">
+paint(g2: Graphics2D) : void</text>
+<rect x="14" y="202" width="148" height="159" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="14" y="202" width="147" height="158" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<line x1="15" y1="361" x2="162" y2="361" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<line x1="162" y1="203" x2="162" y2="360" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<rect x="14" y="202" width="148" height="21" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="14" y="202" width="147" height="20" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="38" y="217" style="font-family:Dialog; font-size:10; font-style:italic;">
+ShapeFigureElement</text>
+<rect x="14" y="222" width="148" height="18" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="14" y="222" width="147" height="17" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<rect x="14" y="239" width="148" height="122" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="14" y="239" width="147" height="121" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="16" y="255" style="font-family:Dialog; font-size:10; font-style:italic;">
+move(dx: int,dy: int) : void</text>
+<text x="16" y="272" style="font-family:Dialog; font-size:10; font-style:italic;">
+getShape() : Shape</text>
+<text x="16" y="289" style="font-family:Dialog; font-size:10;">
+getBounds() : Rectangle</text>
+<text x="16" y="306" style="font-family:Dialog; font-size:10;">
+contains(p: Point2D) : boolean</text>
+<text x="16" y="323" style="font-family:Dialog; font-size:10;">
+getLineColor() : Color</text>
+<text x="16" y="340" style="font-family:Dialog; font-size:10;">
+getFillColor() : Color</text>
+<text x="16" y="357" style="font-family:Dialog; font-size:10;">
+paint(g2: Graphics2D) : void</text>
+<rect x="242" y="202" width="188" height="192" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="242" y="202" width="187" height="191" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<line x1="243" y1="394" x2="430" y2="394" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<line x1="430" y1="203" x2="430" y2="393" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<rect x="242" y="202" width="188" height="21" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="242" y="202" width="187" height="20" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="321" y="217" style="font-family:Dialog; font-size:10;">
+Group</text>
+<rect x="242" y="222" width="188" height="172" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="242" y="222" width="187" height="171" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="244" y="238" style="font-family:Dialog; font-size:10;">
+&lt;&lt;create&gt;&gt; Group(first: FigureElement)</text>
+<text x="244" y="255" style="font-family:Dialog; font-size:10;">
+add(fe: FigureElement) : void</text>
+<text x="244" y="272" style="font-family:Dialog; font-size:10;">
+members() : Iterator</text>
+<text x="244" y="289" style="font-family:Dialog; font-size:10;">
+move(dx: int,dy: int) : void</text>
+<text x="244" y="306" style="font-family:Dialog; font-size:10;">
+setIdentifier(identifier: String) : void</text>
+<text x="244" y="323" style="font-family:Dialog; font-size:10;">
+toString() : String</text>
+<text x="244" y="340" style="font-family:Dialog; font-size:10;">
+getBounds() : Rectangle</text>
+<text x="244" y="357" style="font-family:Dialog; font-size:10;">
+contains(p: Point2D) : boolean</text>
+<text x="244" y="374" style="font-family:Dialog; font-size:10;">
+paint(g2: Graphics2D) : void</text>
+<text x="244" y="391" style="font-family:Dialog; font-size:10;">
+size() : int</text>
+<rect x="14" y="490" width="141" height="158" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="14" y="490" width="140" height="157" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<line x1="15" y1="648" x2="155" y2="648" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<line x1="155" y1="491" x2="155" y2="647" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<rect x="14" y="490" width="141" height="21" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="14" y="490" width="140" height="20" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="72" y="505" style="font-family:Dialog; font-size:10;">
+Point</text>
+<rect x="14" y="510" width="141" height="138" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="14" y="510" width="140" height="137" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="16" y="526" style="font-family:Dialog; font-size:10;">
+&lt;&lt;create&gt;&gt; Point(x: int,y: int)</text>
+<text x="16" y="543" style="font-family:Dialog; font-size:10;">
+getX() : int</text>
+<text x="16" y="560" style="font-family:Dialog; font-size:10;">
+getY() : int</text>
+<text x="16" y="577" style="font-family:Dialog; font-size:10;">
+setX(x: int) : void</text>
+<text x="16" y="594" style="font-family:Dialog; font-size:10;">
+setY(y: int) : void</text>
+<text x="16" y="611" style="font-family:Dialog; font-size:10;">
+move(dx: int,dy: int) : void</text>
+<text x="16" y="628" style="font-family:Dialog; font-size:10;">
+toString() : String</text>
+<text x="16" y="645" style="font-family:Dialog; font-size:10;">
+getShape() : Shape</text>
+<rect x="259" y="474" width="177" height="158" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="259" y="474" width="176" height="157" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<line x1="260" y1="632" x2="436" y2="632" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<line x1="436" y1="475" x2="436" y2="631" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<rect x="259" y="474" width="177" height="21" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="259" y="474" width="176" height="20" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="337" y="489" style="font-family:Dialog; font-size:10;">
+Line</text>
+<rect x="259" y="494" width="177" height="138" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="259" y="494" width="176" height="137" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="261" y="510" style="font-family:Dialog; font-size:10;">
+&lt;&lt;create&gt;&gt; Line(p1: Point,p2: Point)</text>
+<text x="261" y="527" style="font-family:Dialog; font-size:10;">
+getP1() : Point</text>
+<text x="261" y="544" style="font-family:Dialog; font-size:10;">
+getP2() : Point</text>
+<text x="261" y="561" style="font-family:Dialog; font-size:10;">
+move(dx: int,dy: int) : void</text>
+<text x="261" y="578" style="font-family:Dialog; font-size:10;">
+toString() : String</text>
+<text x="261" y="595" style="font-family:Dialog; font-size:10;">
+contains(p: Point2D) : boolean</text>
+<text x="261" y="612" style="font-family:Dialog; font-size:10;">
+getLine2D() : Line2D</text>
+<text x="261" y="629" style="font-family:Dialog; font-size:10;">
+getShape() : Shape</text>
+<rect x="492" y="474" width="243" height="175" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="492" y="474" width="242" height="174" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<line x1="493" y1="649" x2="735" y2="649" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<line x1="735" y1="475" x2="735" y2="648" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<rect x="492" y="474" width="243" height="21" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="492" y="474" width="242" height="20" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="604" y="489" style="font-family:Dialog; font-size:10;">
+Box</text>
+<rect x="492" y="494" width="243" height="155" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="492" y="494" width="242" height="154" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="494" y="510" style="font-family:Dialog; font-size:10;">
+&lt;&lt;create&gt;&gt; Box(x0: int,y0: int,width: int,height: int)</text>
+<text x="494" y="527" style="font-family:Dialog; font-size:10;">
+getP0() : Point</text>
+<text x="494" y="544" style="font-family:Dialog; font-size:10;">
+getP1() : Point</text>
+<text x="494" y="561" style="font-family:Dialog; font-size:10;">
+getP2() : Point</text>
+<text x="494" y="578" style="font-family:Dialog; font-size:10;">
+getP3() : Point</text>
+<text x="494" y="595" style="font-family:Dialog; font-size:10;">
+move(dx: int,dy: int) : void</text>
+<text x="494" y="612" style="font-family:Dialog; font-size:10;">
+checkBoxness() : void</text>
+<text x="494" y="629" style="font-family:Dialog; font-size:10;">
+toString() : String</text>
+<text x="494" y="646" style="font-family:Dialog; font-size:10;">
+getShape() : Shape</text>
+<rect x="815" y="474" width="178" height="158" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="815" y="474" width="177" height="157" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<line x1="816" y1="632" x2="993" y2="632" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<line x1="993" y1="475" x2="993" y2="631" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<rect x="815" y="474" width="178" height="21" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="815" y="474" width="177" height="20" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="873" y="489" style="font-family:Dialog; font-size:10;">
+SlothfulPoint</text>
+<rect x="815" y="494" width="178" height="138" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="815" y="494" width="177" height="137" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="817" y="510" style="font-family:Dialog; font-size:10;">
+&lt;&lt;create&gt;&gt; SlothfulPoint(x: int,y: int)</text>
+<text x="817" y="527" style="font-family:Dialog; font-size:10;">
+getX() : int</text>
+<text x="817" y="544" style="font-family:Dialog; font-size:10;">
+getY() : int</text>
+<text x="817" y="561" style="font-family:Dialog; font-size:10;">
+setX(x: int) : void</text>
+<text x="817" y="578" style="font-family:Dialog; font-size:10;">
+setY(y: int) : void</text>
+<text x="817" y="595" style="font-family:Dialog; font-size:10;">
+move(dx: int,dy: int) : void</text>
+<text x="817" y="612" style="font-family:Dialog; font-size:10;">
+toString() : String</text>
+<text x="817" y="629" style="font-family:Dialog; font-size:10;">
+getShape() : Shape</text>
+<rect x="630" y="86" width="139" height="108" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="630" y="86" width="138" height="107" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<line x1="631" y1="194" x2="769" y2="194" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<line x1="769" y1="87" x2="769" y2="193" style="fill:#1a1a1a; stroke:#1a1a1a; stroke-width:1"/>
+<rect x="630" y="86" width="139" height="21" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="630" y="86" width="138" height="20" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<text x="690" y="101" style="font-family:Dialog; font-size:10;">
+Log</text>
+<rect x="630" y="106" width="139" height="18" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="630" y="106" width="138" height="17" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<line x1="632" y1="123" x2="678" y2="123" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<text x="632" y="122" style="font-family:Dialog; font-size:10;">
+data : List</text>
+<rect x="630" y="123" width="139" height="71" style="fill:#ffffff; stroke:#ffffff; stroke-width:1"/>
+<rect x="630" y="123" width="138" height="70" style="fill:#ffffff; stroke:#000000; stroke-width:1"/>
+<line x1="632" y1="140" x2="767" y2="140" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<text x="632" y="139" style="font-family:Dialog; font-size:10;">
+traceObject(o: Object) : void</text>
+<line x1="632" y1="157" x2="720" y2="157" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<text x="632" y="156" style="font-family:Dialog; font-size:10;">
+log(s: String) : void</text>
+<line x1="632" y1="174" x2="700" y2="174" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<text x="632" y="173" style="font-family:Dialog; font-size:10;">
+getData() : List</text>
+<line x1="632" y1="191" x2="691" y2="191" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<text x="632" y="190" style="font-family:Dialog; font-size:10;">
+clear() : void</text>
+<line x1="98" y1="202" x2="98" y2="197" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="98" y1="192" x2="98" y2="187" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="98" y1="182" x2="98" y2="177" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="98" y1="172" x2="98" y2="167" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="98" y1="162" x2="98" y2="157" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="98" y1="154" x2="103" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="108" y1="154" x2="113" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="118" y1="154" x2="123" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="128" y1="154" x2="133" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="138" y1="154" x2="143" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="148" y1="154" x2="153" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="158" y1="154" x2="163" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="168" y1="154" x2="173" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="178" y1="154" x2="183" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="188" y1="154" x2="193" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="198" y1="154" x2="203" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="208" y1="154" x2="213" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="218" y1="154" x2="223" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="228" y1="154" x2="232" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="232" y1="154" x2="232" y2="149" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="232" y1="144" x2="232" y2="139" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="232" y1="134" x2="232" y2="129" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="232" y1="124" x2="232" y2="122" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<polygon style="fill:#ffffff; stroke:#ffffff; stroke-width:1" points="232,123 239,135 225,135"/>
+<polygon style="fill:#ffffff; stroke:#000000; stroke-width:1" points="232,123 239,135 225,135"/>
+<line x1="346" y1="202" x2="346" y2="197" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="346" y1="192" x2="346" y2="187" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="346" y1="182" x2="346" y2="177" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="346" y1="172" x2="346" y2="167" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="346" y1="162" x2="346" y2="157" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="346" y1="154" x2="341" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="336" y1="154" x2="331" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="326" y1="154" x2="321" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="316" y1="154" x2="311" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="306" y1="154" x2="301" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="296" y1="154" x2="291" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="286" y1="154" x2="281" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="276" y1="154" x2="271" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="266" y1="154" x2="261" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="256" y1="154" x2="251" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="246" y1="154" x2="241" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="236" y1="154" x2="232" y2="154" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="232" y1="154" x2="232" y2="149" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="232" y1="144" x2="232" y2="139" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="232" y1="134" x2="232" y2="129" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="232" y1="124" x2="232" y2="122" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<polygon style="fill:#ffffff; stroke:#ffffff; stroke-width:1" points="232,123 239,135 225,135"/>
+<polygon style="fill:#ffffff; stroke:#000000; stroke-width:1" points="232,123 239,135 225,135"/>
+<polyline style="fill:none; stroke:#000000; stroke-width:1" points="84,490 84,442 88,442 88,361"/>
+<polygon style="fill:#ffffff; stroke:#ffffff; stroke-width:1" points="88,362 95,374 81,374"/>
+<polygon style="fill:#ffffff; stroke:#000000; stroke-width:1" points="88,362 95,374 81,374"/>
+<polyline style="fill:none; stroke:#000000; stroke-width:1" points="323,474 323,442 88,442 88,361"/>
+<polygon style="fill:#ffffff; stroke:#ffffff; stroke-width:1" points="88,362 95,374 81,374"/>
+<polygon style="fill:#ffffff; stroke:#000000; stroke-width:1" points="88,362 95,374 81,374"/>
+<polyline style="fill:none; stroke:#000000; stroke-width:1" points="613,474 613,442 88,442 88,361"/>
+<polygon style="fill:#ffffff; stroke:#ffffff; stroke-width:1" points="88,362 95,374 81,374"/>
+<polygon style="fill:#ffffff; stroke:#000000; stroke-width:1" points="88,362 95,374 81,374"/>
+<polyline style="fill:none; stroke:#000000; stroke-width:1" points="904,474 904,442 88,442 88,361"/>
+<polygon style="fill:#ffffff; stroke:#ffffff; stroke-width:1" points="88,362 95,374 81,374"/>
+<polygon style="fill:#ffffff; stroke:#000000; stroke-width:1" points="88,362 95,374 81,374"/>
+<polyline style="fill:none; stroke:#000000; stroke-width:1" points="296,202 296,122"/>
+<polygon style="fill:#ffffff; stroke:#ffffff; stroke-width:1" points="296,202 291,192 296,182 301,192"/>
+<polygon style="fill:#ffffff; stroke:#000000; stroke-width:1" points="296,202 291,192 296,182 301,192"/>
+<line x1="303" y1="135" x2="296" y2="123" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="289" y1="135" x2="296" y2="123" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<text x="279" y="193" style="font-family:Dialog; font-size:10;">
+*</text>
+<polyline style="fill:none; stroke:#000000; stroke-width:1" points="155,566 259,566"/>
+<line x1="167" y1="559" x2="155" y2="566" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="167" y1="573" x2="155" y2="566" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<polygon style="fill:#ffffff; stroke:#ffffff; stroke-width:1" points="258,566 248,571 238,566 248,561"/>
+<polygon style="fill:#ffffff; stroke:#000000; stroke-width:1" points="258,566 248,571 238,566 248,561"/>
+<text x="241" y="557" style="font-family:Dialog; font-size:10;">
+2</text>
+<polyline style="fill:none; stroke:#000000; stroke-width:1" points="155,646 492,646"/>
+<line x1="167" y1="639" x2="155" y2="646" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<line x1="167" y1="653" x2="155" y2="646" style="fill:#000000; stroke:#000000; stroke-width:1"/>
+<polygon style="fill:#ffffff; stroke:#ffffff; stroke-width:1" points="491,646 481,651 471,646 481,641"/>
+<polygon style="fill:#ffffff; stroke:#000000; stroke-width:1" points="491,646 481,651 471,646 481,641"/>
+<text x="474" y="637" style="font-family:Dialog; font-size:10;">
+4</text>
+</svg>
diff --git a/docs/modules/ROOT/pages/teaching/exercises/guibase.lst b/docs/modules/ROOT/pages/teaching/exercises/guibase.lst
new file mode 100644
index 000000000..0a9371462
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/guibase.lst
@@ -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/modules/ROOT/pages/teaching/exercises/index.html b/docs/modules/ROOT/pages/teaching/exercises/index.html
new file mode 100644
index 000000000..5212f6e42
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/index.html
@@ -0,0 +1,689 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+
+<!-- This file represents the Exercises for the hands-on AspectJ
+ tutorial. It is commonly checked into CVS with identifying
+ information for the latest conference (such as presenters
+ and publication information).
+
+ When you use it for your own purposes, don't forget to
+ modify at the very least anything that says
+ id="copyright" or class="presenter". If you're in an A4
+ country, don't forget to modify the paper size.
+
+ The gif included at the end is somewhat fragile,
+ so be careful with different paper sizes.
+
+ TODO: There is currently something weird about PDF generation
+ from this: If generated from a windows machine, it will
+ generate mac-unfriendly PDF because of the requested windows
+ font. If the PDF is only used for immediate printing,
+ that's fine, but if it's used for distribution, bad.
+-->
+
+<head>
+ <title>Hands-on Programming with AspectJ&reg; &mdash; Exercises</title>
+ <style type="text/css">
+div.instruction { padding: 0.5em; border-width: 1px; border-style: solid }
+body { background-color: #FFF; margin: 2em }
+body { font-family: "Gill Sans MT", "Gill sans", "Trebuchet ms", Verdana, sans-serif; }
+.newpage { page-break-before: always }
+pre { margin-left: 1em; border-left-style: solid; border-width: 1px; padding-left: 1em;}
+h2 { margin-top: 4ex; }
+h3 { margin-top: 4ex; border-bottom-style: solid; border-width: 1px }
+.presenter { text-align: right }
+@page {
+ size: 8.5in 11in;
+ margin: 3in;
+ marks: cross
+}
+@media print {
+ body { font-size: 10pt }
+ #copyright {
+ font-family: "Times New Roman", "Times Roman", fixed;
+ font-size: 8pt;
+ display: normal;
+ position: absolute;
+ bottom: 1in;
+ border-style: none
+ }
+}
+@media screen {
+ #copyright { display: none }
+}
+ </style>
+</head>
+
+<body>
+
+<h1>Hands-on Programming with AspectJ<sup>&reg;</sup></h1>
+
+<div class="presenter">Erik Hilsdale</div>
+<div class="presenter">Mik Kersten</div>
+<div class="presenter">http://www.eclipse.com/aspectj</div>
+
+<h2>Overview</h2>
+
+<p> In this tutorial you will solve some canonical programming
+tasks using AspectJ. The tasks progress from writing
+non-functional, development-only aspects to writing aspects that
+augment a deployed program with crosscutting features. This
+follows the same progression most users see in their own adoption
+of AspectJ. </p>
+
+<p> Since this is a hands-on tutorial, you will be working with a
+live AspectJ distribution. The example code we will be working
+with is a simple figure editor, along with JUnit tests for each
+exercise. We will break up into groups of two to three people
+per computer to foster discussion within the group as well as
+with the presenters. </p>
+
+<p> If you have a laptop running a recent version of Windows,
+MacOS or Linux, feel free to bring it along. We will provide CDs
+and other installation media for a standalone AspectJ system,
+including the figure editor code these exercises are based on and
+unit tests for the exercises. If you don't have a laptop with
+you, don't worry about it. </p>
+
+<p> These notes consist of four sections of exercises, a quick
+reference to AspectJ syntax, and a UML diagram of a figure editor
+program. </p>
+
+<div class="instruction"> If you receive these tutorial notes
+early, feel free to have a quick look, especially at the UML
+diagram and quick reference. But you'll be cheating yourself if
+you try to do the exercises early; you'll learn a lot more by
+working through it in groups during the tutorial proper. </div>
+
+<!--
+This space is used for a copyright that appears on the
+bottom of the _printed_ page. It's suppressed when viewed on
+a computer screen by the stylesheet.
+
+<div id="copyright">
+Copyright is held by the author/owner(s). <br />
+OOPSLA’04, October 24-28, 2004, Vancouver, British Columbia, Canada <br />
+2004 ACM 04/0010
+</div>
+-->
+
+<h3 class="newpage">Command-line usage</h3>
+
+<p> While the AspectJ system is well integrated with a number of
+IDEs, it can also be used as a command-line compiler. The
+standalone package we provide (containing the tests, the base
+code, JUnit, and a distribution of AspectJ) needs 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 <code>setpaths</code> or <code>setpaths.bat</code>, as
+appropriate.
+</p>
+
+<p> Each time you open a new shell window run
+<code>setpaths.bat</code> or <code>source setpaths</code> to
+export some other needed environment variables. </p>
+
+<p> In general, all the files in the program are listed in
+<code>base.lst</code>, 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
+<code>base.lst</code>, either in an IDE or with </p>
+
+<pre>
+$ ajc -argfile base.lst
+</pre>
+
+<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>
+
+<pre>
+&gt; copy answers/Answer.java answers/2a.java (Windows)
+$ cp answers/Answer.java answers/2a.java (Unix)
+</pre>
+
+<p> After building the system, you should invoke Java on the compiled
+test class. On the command-line, this this would be </p>
+
+<pre>
+$ java tests.Test2a
+</pre>
+
+<p> The default test, <code>tests.CoreTest</code>, performs some
+rudimentary tests on figure elements, and so is a useful test to run
+periodically. You should also look at the JUnit tests for each
+exercise as you do it. </p>
+
+<p> Again, we will be looking at solutions and having discussion,
+which is much more difficult without incremental solutions. So
+when you go from one exercise to the next, <strong>save your
+work</strong> in a file before going on to the next exercise
+even if you plan to duplicate some code. </p>
+
+<div class="instruction"> When we give examples of execution in
+these exercises we will show the command-line use, but of course
+you should use the appropriate compile and execute tools if you
+are using the AspectJ browser, Emacs, or Eclipse. </div>
+
+<!-- ============================== -->
+
+<h2 class="newpage">1. Static Invariants</h2>
+
+<p> The easiest way to get started with AspectJ is to use it to
+enforce static invariants.
+</p>
+
+<h3>1.a. Find old tracing</h3>
+
+<div class="instruction"> <strong>Sample Exercise</strong>: The
+main point of this exercise is to make sure your configuration
+works. Type in the answer below into your answer file, make sure
+you get the desired compile-time error, remove the offending
+line, and make sure you pass the JUnit test. </div>
+
+<p> <strong>Task:</strong> Signal an error for calls to
+<code>System.out.println</code>.
+</p>
+
+<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 far longer than is necessary. Type in the aspect
+below to signal an error at compile time if this mistake is made.
+</p>
+
+<p> <strong>Answer:</strong>
+</p>
+
+<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>
+
+<p> When you use this on the given system, you'll find one incorrect
+trace in <code>SlothfulPoint</code>.
+</p>
+
+<pre>
+$ ajc -argfile base.lst
+./figures/SlothfulPoint.java:38 illegal access to System.out
+
+1 error
+</pre>
+
+<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>
+
+<p> After you have successfully used this aspect, edit your
+program to remove the illegal tracing call. </p>
+
+<p> Make sure your program still passes the JUnit test
+<code>tests.CoreTest</code> (which it should also pass at the beginning of
+all exercises) before continuing. </p>
+
+<pre>
+$ java tests.CoreTest
+....
+Time: 0.03
+
+OK (4 tests)
+</pre>
+
+<h3 class="newpage">1.b. Mandate setters</h3>
+
+<p> <strong>Task:</strong> Signal a warning for assignments outside
+of setter methods. </p>
+
+<p> <strong>Tools:</strong> <code>set</code>, <code>withincode</code>,
+the <code>void set*(..)</code> pattern
+</p>
+
+<p> One common coding convention is that no private field should
+be assigned to outside of setter methods. Write an aspect to
+signal a warning at compile time for these illegal assignment
+expressions. </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.
+
+<p> Make sure your program still passes the JUnit test
+<code>tests.CoreTest</code> before continuing. Make sure you get eleven
+warnings from this. Wait to fix them until the next exercise. </p>
+
+<h3>1.c. Refine setters mandate</h3>
+
+<p> <strong>Task:</strong> Allow assignmnents inside of constructors.
+</p>
+
+<p> <strong>Tools:</strong> the <code>new(..)</code> pattern</p>
+
+<p> Look at some of the warnings from the previous exercise. Notice
+that a lot of them are from within constructors. Actually, the common
+coding convention is that no private field should be assigned to outside of
+setter methods <em>or constructors</em>. Modify your answer 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:37 bad field set
+.\figures\Point.java:38 bad field set
+
+2 errors
+</pre>
+
+<p>Rewrite these two occurrences so as not to violate
+the convention. Make sure your program still passes the JUnit test
+<code>tests.CoreTest</code> before continuing. </p>
+
+<div class="instruction"> Congratulations, you've taken your
+first steps. At this point, check the people to your left and
+right. If they're stuck somewhere, see if you can help them.
+Try to resist moving on to the next section until we discuss
+solutions as a group. </div>
+
+<!-- ============================== -->
+
+<h2 class="newpage">2. Dynamic invariants</h2>
+
+<p> The next step in AspectJ adoption is often to augment a test suite
+by including additional dynamic tests.
+</p>
+
+<div class="instruction"> Tutorial attendees typically progress
+at different speeds through these exercises. Throughout this
+tutorial, if you finish early, see what the people around you are
+doing and if they need help. Don't help them out of charity,
+help them out of naked self-interest&mdash;we promise you'll learn a
+lot about using AspectJ by explaining it. </div>
+
+<h3>2.a. Check a simple precondition</h3>
+
+<div class="instruction"> <strong>Sample Exercise</strong>: We've
+provided the answer to this exercise to get you started. Feel
+free to think a bit, but don't get stuck on this one. </div>
+
+<p> <strong>Task:</strong> Pass <code>tests.Test2a</code>.
+</p>
+
+<p> <strong>Tools:</strong> <code>args</code>, <code>before</code>
+</p>
+
+<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 less than zero. </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>
+
+<pre>
+$ java tests.Test2a
+.F..F....
+Time: 0.04
+There were 2 failures:
+1) testTooSmall(tests.Test2a)junit.framework.AssertionFailedError: should have thrown IllegalArgumentException
+2) testMove(tests.Test2a)junit.framework.AssertionFailedError: should have thrown IllegalArgumentException
+
+FAILURES!!!
+Tests run: 7, Failures: 2, Errors: 0
+</pre>
+
+<p> But after compiling in the aspect...
+</p>
+
+<pre>
+$ ajc -argfile base.lst answers/Answer.java
+
+$ java tests.Test2a
+.......
+Time: 0.04
+
+OK (7 tests)
+</pre>
+
+<p> <strong>Answer:</strong>
+</p>
+
+<pre>
+package answers;
+
+import figures.*;
+
+aspect Answer2a {
+ before(int newValue): set(int Point.*) &amp;&amp; args(newValue) {
+ if (newValue &lt; 0) {
+ throw new IllegalArgumentException("too small");
+ }
+ }
+}
+</pre>
+
+<h3>2.b. Check another precondition</h3>
+
+<p> <strong>Task:</strong> Pass <code>tests.Test2b</code>. </p>
+
+<p> <strong>Tools: </strong> <code>call</code>.
+</p>
+
+<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. </p>
+
+<p> Look at <code>tests/Test2b.java</code> to see exactly what we're
+testing for. </p>
+
+<h3>2.c. Check yet another precondition</h3>
+
+<p> <strong>Task:</strong> Pass <code>tests.Test2c</code>. </p>
+
+<p> <strong>Tools:</strong> <code>target</code>
+</p>
+
+<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>
+
+<h3>2.d. Assure input</h3>
+
+<p> <strong>Task: </strong> Pass <code>tests.Test2d</code>.
+</p>
+
+<p> <strong>Tools: </strong> around advice
+</p>
+
+<p> Instead of throwing an exception when one of <code>Point</code>'s
+<code>int</code> fields is set to a negative value, write an aspect
+to trim the value to zero. 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. </p>
+
+<p> This is going to look something like
+</p>
+
+<pre>
+aspect A {
+ void around(int val): <var>&lt;Pointcut&gt;</var> {
+ <var>&lt;Do something with val&gt;</var>
+ proceed(val);
+ }
+}
+</pre>
+
+<h3 class="newpage">2.e. Check a postcondition</h3>
+
+<p> <strong>Task: </strong> Pass <code>tests.Test2e</code>
+</p>
+
+<p> <strong>Tools: </strong> around advice
+</p>
+
+<p> A postcondition of a <code>Point</code>'s <code>move</code>
+operation is that the <code>Point</code>'s coordinates should change.
+If a call to move didn't actually move a point by the desired
+offset, then the point is in an illegal state and so an
+<code>IllegalStateException</code> should be thrown.
+</p>
+
+<p> Note that because we're dealing with how the coordinates change
+during move, we need some way of getting access to the coordinates
+both before <em>and</em> after the move, in one piece of advice. </p>
+
+<h3>2.f. Check another postcondition</h3>
+
+<p> <strong>Task: </strong> Pass <code>tests.Test2f</code>
+</p>
+
+<p> <strong>Tools:</strong> the <code> Rectangle(Rectangle)</code>
+constructor, the <code>Rectangle.translate(int, int)</code> method.
+</p>
+
+<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 general
+<code>move</code> operation on a figure element 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>
+
+<!-- ============================== -->
+
+<h2 class="newpage">3. Tracing</h2>
+
+<p> Tracing is one of the classic AspectJ applications, and is often
+the first where AspectJ is used on deployed code.
+</p>
+
+<h3>3.a. Simple tracing</h3>
+
+<p> <strong>Task:</strong> Pass <code>tests.Test3a</code>.</p>
+
+<p> <strong>Tools:</strong>
+ <code>Log.write(String)</code>,
+ <code>thisJoinPoint.toString()</code>,
+ <code>execution</code>,
+ <code>within</code>
+</p>
+
+<p> Write an aspect to log the execution of all public methods
+in the figures package. To do this, use the utility class
+<code>Log</code> (this is in the <code>support</code> package, so
+remember to import it into your answer aspect). Write a message
+into the log with the static <code>write(String)</code> method.</p>
+
+<h3>3.b. Exposing a value</h3>
+
+<p> <strong>Task:</strong> Pass <code>tests.Test3b</code>.</p>
+
+<p> <strong>Tools:</strong> <code>target</code>
+</p>
+
+<p> AspectJ can expose the target object at a join point for tracing.
+In this exercise, you will print not only the join point information,
+but also the target object, with the form
+</p>
+
+<pre>
+<em>thisJoinPointInfo</em> at <em>targetObject</em>
+</pre>
+
+
+<h3>3.c. More specialized logging</h3>
+
+<p> <strong>Task:</strong> Pass <code>tests.Test3c</code>.</p>
+
+<p> <strong>Tools:</strong> <code>args</code>.
+</p>
+
+<p> Write an aspect to log whenever a <code>Point</code> is added to a
+group. The <code>args</code> pointcut allows you to select join points
+based on the type of a parameter to a method call. </p>
+
+<p> Look at the test case to see the trace message we expect you
+to write in the log.
+</p>
+
+<h3 class="newpage">3.d. Logging extended to checking an invariant</h3>
+
+<p> <strong>Task:</strong> Pass <code>tests.Test3d</code>.</p>
+
+<p> <strong>Tools:</strong> <code>inter-type field declaration</code>
+</p>
+
+<p> Make sure that a <code>Point</code> is never added to more
+than one <code>Group</code>. To do so, associate a boolean flag
+with each <code>Point</code> using an inter-type declaration,
+such as </p>
+
+<pre>
+boolean Point.hasBeenAdded = false;
+</pre>
+
+<p> Check and set this flag with the same kind of advice from your
+answer to problem (c). Throw an <code>IllegalStateException</code> if
+the point has already been added.
+</p>
+
+<h3>3.e. Better error messages for 3.d.</h3>
+
+<p> <strong>Task:</strong> Pass <code>tests.Test3e</code>.</p>
+
+<p> Extend your solution to problem (d) by using the string
+representation of the Point's containing group as the <code>msg</code>
+part of the <code>IllegalStateException</code>. </p>
+
+<!-- ============================== -->
+
+<h2 class="newpage">4. Caching</h2>
+
+<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>
+
+<div class="instruction"> <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. </div>
+
+<h3>4.a. Make a constant override</h3>
+
+<p> <strong>Task:</strong> Pass <code>tests.Test4a</code>.</p>
+
+<p> <strong>Tools:</strong> <code>around</code>,
+ <code>FigureElement.MAX_BOUNDS</code>
+</p>
+
+<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. The entire canvas is returned
+by the static method <code>FigureElement.MAX_BOUNDS</code>.
+</p>
+
+<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>
+
+<h3>4.b. Make a constant cache</h3>
+
+<p> <strong>Task:</strong> Pass <code>tests.Test4b</code>.
+</p>
+
+<p> <strong>Tools:</strong> inter-type field.
+</p>
+
+<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>
+
+
+<h3>4.c. Invalidate, part 1</h3>
+
+<p> <strong>Task:</strong> Pass <code>tests.Test4c</code>.
+</p>
+
+<p> <strong>Tools:</strong> <code>before</code>
+</p>
+
+<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>
+
+<h3 class="newpage">4.d. Invalidate, part 2</h3>
+
+<p> <strong>Task:</strong> Pass <code>tests.Test4d</code>.</p>
+
+<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>
+
+<h3>4.e. Invalidate, part 3</h3>
+
+<p> <strong>Task:</strong> Pass <code>tests.Test4e</code>.</p>
+
+<p> <strong>Tools:</strong> <em>You're on you're own</em></p>
+
+<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>
+
+<div class="instruction">
+
+<p> Congratulations! Not only have you learned about how to
+program in AspectJ, you have worked through exercises paralleling
+a common AspectJ adoption strategy. You should be able to
+pick up AspectJ and use it to improve your own software's
+crosscutting modularity. </p>
+
+<p> You can find the current binaries, source, documentation and
+an active user community for AspectJ at</p>
+
+ <blockquote>
+ https://www.eclipse.org/aspectj
+ </blockquote>
+
+</div>
+
+<img style="newpage" src="figures_classes.png" height="900" alt="" />
+
+</body> </html>
diff --git a/docs/modules/ROOT/pages/teaching/exercises/install.txt b/docs/modules/ROOT/pages/teaching/exercises/install.txt
new file mode 100644
index 000000000..ccb2b9e71
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/install.txt
@@ -0,0 +1,63 @@
+0. Install
+
+ Now get the directory "aj-@aj.event@/". Just copy the
+ "aj-@aj.event@/" directory from the provided CD.
+
+ If you're running a Windows machine, we recommend you copy into
+ "c:\". If you're running your favorite Unix (we've had success under
+ Linux and MacOS X), we recommend you install into "~\".
+
+1. Configure
+
+ Our installation is fairly well self-contained, but it does need to know
+ where Java lives. To do this you must set the environment variable named
+ JAVA_HOME. This variable should point to something like
+
+ c:\apps\jdk1.3.1_04
+ /usr/java
+ /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
+
+ depending on your system. You may either do this globally, or you may
+ edit the appropriate setpaths script:
+
+ setpaths.bat (under Windows)
+ setpaths.sh (if you run bash/sh/ksh, like most Linux setups)
+ setpaths.csh (if you run csh, like most MacOS X setups)
+
+ Also, if you installed into a directory other than "c:\" or "~/", then you
+ need to change the EXTRACTION environment variable in the setpaths script.
+
+2. Test
+
+ Open a new command shell and change to the "aj-@aj.event@/" directory.
+
+ We have provided a "setpaths" script to set permissions and various paths
+ variables, so run this script:
+
+ > setpaths.bat (under Windows)
+ > source setpaths.sh (if you run bash/sh/ksh, like most Linux setups)
+ > source setpaths.csh (if you run csh, like most MacOS X setups)
+
+ You must remember to run this script every time you open a new command
+ shell.
+
+ Now, compile the core system with ajc:
+
+ > ajc -argfile guibase.lst
+
+ This should compile the figures application (source code in the figures
+ directory) as well as a single unit test (source code in the tests
+ directory).
+
+ See if the compile was successful by running the gui figures app you just
+ compiled:
+
+ > java figures.gui.Main
+
+ And, after quitting out of the gui figures app, run the unit test:
+
+ > java tests.Test
+ ....
+ Time: 0.076
+
+ OK (4 tests)
diff --git a/docs/modules/ROOT/pages/teaching/exercises/junit.jar b/docs/modules/ROOT/pages/teaching/exercises/junit.jar
new file mode 100644
index 000000000..674d71e89
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/junit.jar
Binary files differ
diff --git a/docs/modules/ROOT/pages/teaching/exercises/plugins/index.adoc b/docs/modules/ROOT/pages/teaching/exercises/plugins/index.adoc
new file mode 100644
index 000000000..1cdf0fbc1
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/plugins/index.adoc
@@ -0,0 +1,19 @@
+== Exercises plugin for the tutorial
+
+Download the appropriate version and unzip it in your eclipse\plugins
+directory:
+
+[cols=",",]
+|===
+|For Eclipse 3.0 with AJDT 1.1.12
+|https://dev.eclipse.org/viewcvs/index.cgi/~checkout~/org.aspectj/modules/docs/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.1.12.zip?rev=1.1&cvsroot=Technology_Project[org.aspectj.tutorial.exercises_1.1.12.zip]
+
+|For Eclipse 3.0 with AJDT 1.2.0M2
+|https://dev.eclipse.org/viewcvs/index.cgi/~checkout~/org.aspectj/modules/docs/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0M2.zip?rev=1.1&cvsroot=Technology_Project[org.aspectj.tutorial.exercises_1.2.0M2.zip]
+
+|For Eclipse 3.0 with AJDT 1.2.0 latest dev build
+|https://dev.eclipse.org/viewcvs/index.cgi/~checkout~/org.aspectj/modules/docs/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0_301_Dev.zip?rev=1.1&cvsroot=Technology_Project[org.aspectj.tutorial.exercises_1.2.0_301_Dev.zip]
+
+|For Eclipse 3.1M5 with AJDT 1.2.0 latest dev build
+|https://dev.eclipse.org/viewcvs/index.cgi/~checkout~/org.aspectj/modules/docs/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0_31M5_Dev.zip?rev=1.1&cvsroot=Technology_Project[org.aspectj.tutorial.exercises_1.2.0_31M5_Dev.zip]
+|===
diff --git a/docs/modules/ROOT/pages/teaching/exercises/plugins/index.html b/docs/modules/ROOT/pages/teaching/exercises/plugins/index.html
new file mode 100644
index 000000000..ef87c84c8
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/plugins/index.html
@@ -0,0 +1,31 @@
+<html>
+<head>
+</head>
+<body>
+<h1>Exercises plugin for the tutorial</h1>
+
+<p>Download the appropriate version and unzip it in your eclipse\plugins directory:</p>
+<table>
+<tr>
+<td>For Eclipse 3.0 with AJDT 1.1.12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
+<td><a href="https://dev.eclipse.org/viewcvs/index.cgi/~checkout~/org.aspectj/modules/docs/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.1.12.zip?rev=1.1&cvsroot=Technology_Project">
+org.aspectj.tutorial.exercises_1.1.12.zip</a></td>
+</tr>
+<tr>
+<td>For Eclipse 3.0 with AJDT 1.2.0M2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
+<td><a href="https://dev.eclipse.org/viewcvs/index.cgi/~checkout~/org.aspectj/modules/docs/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0M2.zip?rev=1.1&cvsroot=Technology_Project">
+org.aspectj.tutorial.exercises_1.2.0M2.zip</a></td>
+</tr>
+<tr>
+<td>For Eclipse 3.0 with AJDT 1.2.0 latest dev build&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
+<td><a href="https://dev.eclipse.org/viewcvs/index.cgi/~checkout~/org.aspectj/modules/docs/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0_301_Dev.zip?rev=1.1&cvsroot=Technology_Project">
+org.aspectj.tutorial.exercises_1.2.0_301_Dev.zip</a></td>
+</tr>
+<tr>
+<td>For Eclipse 3.1M5 with AJDT 1.2.0 latest dev build&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
+<td><a href="https://dev.eclipse.org/viewcvs/index.cgi/~checkout~/org.aspectj/modules/docs/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0_31M5_Dev.zip?rev=1.1&cvsroot=Technology_Project">
+org.aspectj.tutorial.exercises_1.2.0_31M5_Dev.zip</a></td>
+</tr>
+</table>
+</body>
+</html>
diff --git a/docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.1.12.zip b/docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.1.12.zip
new file mode 100644
index 000000000..674af9cd7
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.1.12.zip
Binary files differ
diff --git a/docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0M2.zip b/docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0M2.zip
new file mode 100644
index 000000000..90a4acc86
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0M2.zip
Binary files differ
diff --git a/docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0_301_Dev.zip b/docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0_301_Dev.zip
new file mode 100644
index 000000000..6c192738c
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0_301_Dev.zip
Binary files differ
diff --git a/docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0_31M5_Dev.zip b/docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0_31M5_Dev.zip
new file mode 100644
index 000000000..3c817b274
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/plugins/org.aspectj.tutorial.exercises_1.2.0_31M5_Dev.zip
Binary files differ
diff --git a/docs/modules/ROOT/pages/teaching/exercises/pre-letter.txt b/docs/modules/ROOT/pages/teaching/exercises/pre-letter.txt
new file mode 100644
index 000000000..4833beeb5
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/pre-letter.txt
@@ -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/modules/ROOT/pages/teaching/exercises/scripts/ajbrowser b/docs/modules/ROOT/pages/teaching/exercises/scripts/ajbrowser
new file mode 100644
index 000000000..2f804efda
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/scripts/ajbrowser
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+"$JAVA_HOME/bin/java" -classpath "$ASPECTJ_HOME/lib/aspectjtools.jar:$JAVA_HOME/lib/tools.jar:$CLASSPATH" -Xmx64M org.aspectj.tools.ajbrowser.Main "$@"
diff --git a/docs/modules/ROOT/pages/teaching/exercises/scripts/ajbrowser.bat b/docs/modules/ROOT/pages/teaching/exercises/scripts/ajbrowser.bat
new file mode 100644
index 000000000..dd717ccae
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/scripts/ajbrowser.bat
@@ -0,0 +1,9 @@
+@echo off
+if exist "%JAVA_HOME%\bin\java.exe" goto haveJava
+if exist "%JAVA_HOME%\bin\java.bat" goto haveJava
+if exist "%JAVA_HOME%\bin\java" goto haveJava
+echo java does not exist as %JAVA_HOME%\bin\java
+echo please fix the JAVA_HOME environment variable
+
+:haveJava
+"%JAVA_HOME%\bin\java" -classpath "%ASPECTJ_HOME%\lib\aspectjtools.jar;%JAVA_HOME%\lib\tools.jar;%CLASSPATH%" -Xmx64M org.aspectj.tools.ajbrowser.Main %1 %2 %3 %4 %5 %6 %7 %8 %9
diff --git a/docs/modules/ROOT/pages/teaching/exercises/scripts/ajc b/docs/modules/ROOT/pages/teaching/exercises/scripts/ajc
new file mode 100644
index 000000000..f8f45ee35
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/scripts/ajc
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+"$JAVA_HOME/bin/java" -classpath "$ASPECTJ_HOME/lib/aspectjtools.jar:$JAVA_HOME/lib/tools.jar:$CLASSPATH" -Xmx64M org.aspectj.tools.ajc.Main "$@"
diff --git a/docs/modules/ROOT/pages/teaching/exercises/scripts/ajc.bat b/docs/modules/ROOT/pages/teaching/exercises/scripts/ajc.bat
new file mode 100644
index 000000000..ca51b07be
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/scripts/ajc.bat
@@ -0,0 +1,9 @@
+@echo off
+if exist "%JAVA_HOME%\bin\java.exe" goto haveJava
+if exist "%JAVA_HOME%\bin\java.bat" goto haveJava
+if exist "%JAVA_HOME%\bin\java" goto haveJava
+echo java does not exist as %JAVA_HOME%\bin\java
+echo please fix the JAVA_HOME environment variable
+
+:haveJava
+"%JAVA_HOME%\bin\java" -classpath "%ASPECTJ_HOME%\lib\aspectjtools.jar;%JAVA_HOME%\lib\tools.jar;%CLASSPATH%" -Xmx64M org.aspectj.tools.ajc.Main %1 %2 %3 %4 %5 %6 %7 %8 %9
diff --git a/docs/modules/ROOT/pages/teaching/exercises/scripts/setpaths.bat b/docs/modules/ROOT/pages/teaching/exercises/scripts/setpaths.bat
new file mode 100644
index 000000000..390eec58a
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/scripts/setpaths.bat
@@ -0,0 +1,15 @@
+@echo off
+
+rem Change this to be the full path for this directory
+set EXTRACTION=c:\aj-@aj.event@
+
+if exist "%JAVA_HOME%\bin\java.exe" goto haveJava
+if exist "%JAVA_HOME%\bin\java.bat" goto haveJava
+if exist "%JAVA_HOME%\bin\java" goto haveJava
+echo java does not exist as %JAVA_HOME%\bin\java
+echo please fix the JAVA_HOME environment variable
+
+:haveJava
+set ASPECTJ_HOME=%EXTRACTION%\aspectj
+set PATH=%ASPECTJ_HOME%\bin;%PATH%
+set CLASSPATH=.;%ASPECTJ_HOME%\lib\aspectjrt.jar;%EXTRACTION%\junit.jar;%JAVA_HOME%\jre\lib\rt.jar
diff --git a/docs/modules/ROOT/pages/teaching/exercises/scripts/setpaths.csh b/docs/modules/ROOT/pages/teaching/exercises/scripts/setpaths.csh
new file mode 100644
index 000000000..276bbf4d1
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/scripts/setpaths.csh
@@ -0,0 +1,11 @@
+# this file should be sourced, NOT executed
+
+# Change this to be the full path for this directory
+set EXTRACTION=$HOME/aj-@aj.event@
+
+set ASPECTJ_HOME=$EXTRACTION/aspectj
+set PATH=$ASPECTJ_HOME/bin:$PATH
+set CLASSPATH=.:$ASPECTJ_HOME/lib/aspectjrt.jar:$EXTRACTION/junit.jar:$JAVA_HOME/jre/lib/rt.jar
+
+chmod a+x $ASPECTJ_HOME/bin/ajc
+chmod a+x $ASPECTJ_HOME/bin/ajbrowser
diff --git a/docs/modules/ROOT/pages/teaching/exercises/scripts/setpaths.sh b/docs/modules/ROOT/pages/teaching/exercises/scripts/setpaths.sh
new file mode 100644
index 000000000..e944776ed
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/scripts/setpaths.sh
@@ -0,0 +1,18 @@
+# this file should be sourced, NOT executed
+
+# Change this to be the full path for this directory
+EXTRACTION=$HOME/aj-@aj.event@
+
+if [ "$JAVA_HOME" = "" ]
+then
+ echo Please remember to manually set $JAVA_HOME to
+ echo the location of your java installation
+fi
+
+export ASPECTJ_HOME=$EXTRACTION/aspectj
+export PATH=$ASPECTJ_HOME/bin:$PATH
+export CLASSPATH=.:$ASPECTJ_HOME/lib/aspectjrt.jar:$EXTRACTION/junit.jar:$JAVA_HOME/jre/lib/rt.jar
+
+chmod a+x $ASPECTJ_HOME/bin/ajc
+chmod a+x $ASPECTJ_HOME/bin/ajbrowser
+
diff --git a/docs/modules/ROOT/pages/teaching/exercises/setpaths b/docs/modules/ROOT/pages/teaching/exercises/setpaths
new file mode 100644
index 000000000..2933d3a89
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/setpaths
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# Change this to be the full path for this directory
+EXTRACTION=$HOME/aj-oopsla
+
+if [ "$JAVA_HOME" = "" ]
+then
+ echo Please remember to manually set $JAVA_HOME to
+ echo the location of your java installation
+fi
+
+export ASPECTJ_HOME=$EXTRACTION/aspectj
+export PATH=$ASPECTJ_HOME/bin:$PATH
+export CLASSPATH=.:$ASPECTJ_HOME/lib/aspectjrt.jar:$EXTRACTION/junit.jar
diff --git a/docs/modules/ROOT/pages/teaching/exercises/setpaths.bat b/docs/modules/ROOT/pages/teaching/exercises/setpaths.bat
new file mode 100644
index 000000000..6722060ea
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/setpaths.bat
@@ -0,0 +1,15 @@
+@echo off
+
+rem Change this to be the full path for this directory
+set EXTRACTION=c:\aj-oopsla
+
+if exist "%JAVA_HOME%\bin\java.exe" goto haveJava
+if exist "%JAVA_HOME%\bin\java.bat" goto haveJava
+if exist "%JAVA_HOME%\bin\java" goto haveJava
+echo java does not exist as %JAVA_HOME%\bin\java
+echo please fix the JAVA_HOME environment variable
+
+:haveJava
+set ASPECTJ_HOME=%EXTRACTION%\aspectj
+set PATH=%ASPECTJ_HOME%\bin;%PATH%
+set CLASSPATH=.;%ASPECTJ_HOME%\lib\aspectjrt.jar;%EXTRACTION%\junit.jar
diff --git a/docs/modules/ROOT/pages/teaching/exercises/support/Log.java b/docs/modules/ROOT/pages/teaching/exercises/support/Log.java
new file mode 100644
index 000000000..7c615836e
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/support/Log.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+
+package support;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class Log {
+ static List data = new ArrayList();
+
+ public static void write(String s) {
+ data.add(s);
+ }
+
+ public static List getData() {
+ return data;
+ }
+
+ public static void clear() {
+ data.clear();
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/tests/CoreTest.java b/docs/modules/ROOT/pages/teaching/exercises/tests/CoreTest.java
new file mode 100644
index 000000000..e069e67b5
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/CoreTest.java
@@ -0,0 +1,79 @@
+/* *******************************************************************
+ * 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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class CoreTest extends TestCase {
+
+ 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/modules/ROOT/pages/teaching/exercises/tests/Test2a.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test2a.java
new file mode 100644
index 000000000..8035a0543
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test2a.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class Test2a extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test2a.class);
+ }
+
+ public void testTooSmall() {
+ Point p1 = new Point(10, 100);
+ try {
+ p1.setX(-10);
+ fail("should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException ea) {
+ }
+ }
+
+ public void testNotTooSmall() {
+ Point p1 = new Point(10, 100);
+ p1.setX(0);
+ }
+
+ public void testMove() {
+ Line l1 = new Line(new Point(10, 100), new Point(20, 200));
+ try {
+ l1.move(-500, -500);
+ fail("should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException ea) {
+ }
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/tests/Test2b.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test2b.java
new file mode 100644
index 000000000..2e2fecf73
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test2b.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class Test2b extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test2b.class);
+ }
+
+ public void testNull() {
+ Point p1 = new Point(10, 100);
+ Group g = new Group(p1);
+
+ try {
+ g.add(null);
+ fail("should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException ea) {
+ }
+ }
+
+ public void testNonNull() {
+ Point p1 = new Point(10, 100);
+ Group g = new Group(p1);
+ Point p2 = new Point(20, 200);
+
+ g.add(p2);
+ }
+
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/tests/Test2c.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test2c.java
new file mode 100644
index 000000000..2bb7093ee
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test2c.java
@@ -0,0 +1,43 @@
+/* *******************************************************************
+ * 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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class Test2c extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test2c.class);
+ }
+
+ public void testSelf() {
+ Point p1 = new Point(10, 100);
+ Group g = new Group(p1);
+
+ try {
+ g.add(g);
+ fail("should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException ea) {
+ }
+ }
+
+ public void testNotSelf() {
+ Point p1 = new Point(10, 100);
+ Group g1 = new Group(p1);
+ Group g2 = new Group(p1);
+
+ g1.add(g2);
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/tests/Test2d.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test2d.java
new file mode 100644
index 000000000..baabd9aea
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test2d.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class Test2d extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test2d.class);
+ }
+
+ public void testOutOfBounds() {
+ Point p1 = new Point(10, 100);
+
+ p1.setX(-10);
+ p1.setY(-100);
+
+ assertEquals(0, p1.getX());
+ assertEquals(0, p1.getY());
+ }
+
+ public void testInBounds() {
+ Point p1 = new Point(10, 100);
+
+ p1.setX(30);
+ p1.setY(300);
+
+ assertEquals(30, p1.getX());
+ assertEquals(300, p1.getY());
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/tests/Test2e.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test2e.java
new file mode 100644
index 000000000..bf388cbb6
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test2e.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class Test2e extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test2e.class);
+ }
+
+ public void testNonMoving() {
+ Point sp = new Point(10, 10) { public void move(int x, int y) {} };
+ try {
+ sp.move(10, 10);
+ fail("should have thrown IllegalStateException");
+ } catch (IllegalStateException e) { }
+ }
+
+ public void testMoving() {
+ Point p1 = new Point(10, 100);
+ p1.move(3, 30);
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/tests/Test2f.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test2f.java
new file mode 100644
index 000000000..adcf58923
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test2f.java
@@ -0,0 +1,40 @@
+/* *******************************************************************
+ * 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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+
+import junit.framework.*;
+
+public class Test2f extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test2f.class);
+ }
+
+ public void testSloth() {
+ FigureElement fe = new SlothfulPoint(10, 10);
+ try {
+ fe.move(10, 10);
+ fail("should have thrown IllegalStateException");
+ } catch (IllegalStateException e) { }
+ }
+
+ public void testNonSloth() {
+ Point p1 = new Point(10, 100);
+ Point p2 = new Point(20, 200);
+ Line l1 = new Line(p1, p2);
+
+ l1.move(3, 30);
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/tests/Test3a.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test3a.java
new file mode 100644
index 000000000..8baf39096
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test3a.java
@@ -0,0 +1,59 @@
+/* *******************************************************************
+ * 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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import support.Log;
+import junit.framework.*;
+import java.util.List;
+import java.util.Arrays;
+
+public class Test3a extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test3a.class);
+ }
+
+ public void testMovePointLog() {
+ Point p1 = new Point(10, 100);
+
+ Log.clear();
+ p1.move(20, 30);
+ List foundLog = Log.getData();
+
+ List desiredLog =
+ Arrays.asList(new String[] {
+ "execution(void figures.Point.move(int, int))"
+ });
+
+ assertEquals(desiredLog, foundLog);
+ }
+
+ public void testMoveLineLog() {
+ Point p1 = new Point(10, 100);
+ Point p2 = new Point(20, 200);
+ Line l = new Line(p1, p2);
+
+ Log.clear();
+ l.move(20, 30);
+ List foundLog = Log.getData();
+
+ List desiredLog =
+ Arrays.asList(new String[] {
+ "execution(void figures.Line.move(int, int))",
+ "execution(void figures.Point.move(int, int))",
+ "execution(void figures.Point.move(int, int))"
+ });
+ assertEquals(desiredLog, foundLog);
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/tests/Test3b.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test3b.java
new file mode 100644
index 000000000..294951824
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test3b.java
@@ -0,0 +1,59 @@
+/* *******************************************************************
+ * 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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import support.Log;
+import junit.framework.*;
+import java.util.List;
+import java.util.Arrays;
+
+public class Test3b extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test3b.class);
+ }
+
+ public void testMovePointLog() {
+ Point p1 = new Point(10, 100);
+
+ Log.clear();
+ p1.move(20, 30);
+ List foundLog = Log.getData();
+
+ List desiredLog =
+ Arrays.asList(new String[] {
+ "execution(void figures.Point.move(int, int)) at Point(10, 100)"
+ });
+
+ assertEquals(desiredLog, foundLog);
+ }
+
+ public void testMoveLineLog() {
+ Point p1 = new Point(10, 100);
+ Point p2 = new Point(20, 200);
+ Line l = new Line(p1, p2);
+
+ Log.clear();
+ l.move(20, 30);
+ List foundLog = Log.getData();
+
+ List desiredLog =
+ Arrays.asList(new String[] {
+ "execution(void figures.Line.move(int, int)) at Line(Point(10, 100), Point(20, 200))",
+ "execution(void figures.Point.move(int, int)) at Point(10, 100)",
+ "execution(void figures.Point.move(int, int)) at Point(20, 200)"
+ });
+ assertEquals(desiredLog, foundLog);
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/tests/Test3c.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test3c.java
new file mode 100644
index 000000000..d563d8056
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test3c.java
@@ -0,0 +1,52 @@
+/* *******************************************************************
+ * 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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import support.Log;
+import junit.framework.*;
+import java.util.List;
+import java.util.Arrays;
+
+public class Test3c extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test3c.class);
+ }
+
+ public void testCreateWithPointLog() {
+ Log.clear();
+ Point p1 = new Point(10, 100);
+ Group g = new Group(p1);
+ List foundLog = Log.getData();
+
+ List desiredLog =
+ Arrays.asList(new String[] {
+ "adding Point"
+ });
+ assertEquals(desiredLog, foundLog);
+ }
+
+ public void testCreateWithoutPointLog() {
+ Log.clear();
+ Point p1 = new Point(10, 100);
+ Point p2 = new Point(20, 200);
+ Line l = new Line(p1, p2);
+ Group g = new Group(l);
+ List foundLog = Log.getData();
+
+ List desiredLog = Arrays.asList(new String[] {});
+ assertEquals(desiredLog, foundLog);
+ }
+}
+
diff --git a/docs/modules/ROOT/pages/teaching/exercises/tests/Test3d.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test3d.java
new file mode 100644
index 000000000..0dc4c0ad4
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test3d.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import support.Log;
+import junit.framework.*;
+import java.util.List;
+import java.util.Arrays;
+
+public class Test3d extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test3d.class);
+ }
+
+ public void testDuplicateAdd() {
+ Log.clear();
+ Point p1 = new Point(10, 100);
+ Group g1 = new Group(p1);
+ try {
+ Group g2 = new Group(p1);
+ fail("should have thrown IllegalStateException");
+ } catch (IllegalStateException ea) {
+ }
+ }
+}
+
diff --git a/docs/modules/ROOT/pages/teaching/exercises/tests/Test3e.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test3e.java
new file mode 100644
index 000000000..c223a83cd
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test3e.java
@@ -0,0 +1,39 @@
+/* *******************************************************************
+ * 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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import support.Log;
+import junit.framework.*;
+import java.util.List;
+import java.util.Arrays;
+
+public class Test3e extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test3e.class);
+ }
+
+ public void testDuplicateAdd() {
+ Log.clear();
+ Point p1 = new Point(10, 100);
+ Group g1 = new Group(p1);
+ try {
+ Group g2 = new Group(p1);
+ fail("should have thrown IllegalStateException");
+ } catch (IllegalStateException ea) {
+ assertEquals(g1.toString(), ea.getMessage());
+ }
+ }
+}
+
diff --git a/docs/modules/ROOT/pages/teaching/exercises/tests/Test4a.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test4a.java
new file mode 100644
index 000000000..4087f39a6
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test4a.java
@@ -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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import java.awt.Rectangle;
+
+import junit.framework.*;
+
+public class Test4a extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test4a.class);
+ }
+
+ public void testGroupBounds() {
+ assertEquals(g.getBounds(), FigureElement.MAX_BOUNDS);
+ }
+}
diff --git a/docs/modules/ROOT/pages/teaching/exercises/tests/Test4b.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test4b.java
new file mode 100644
index 000000000..3429b3d24
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test4b.java
@@ -0,0 +1,61 @@
+/* *******************************************************************
+ * 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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import java.awt.Rectangle;
+
+import junit.framework.*;
+
+public class Test4b extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test4b.class);
+ }
+
+ 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_BOUNDS.getWidth());
+ assertTrue("bounds for this group should not be the whole canvas",
+ g.getBounds().getHeight() < FigureElement.MAX_BOUNDS.getHeight());
+ }
+}
+
+
diff --git a/docs/modules/ROOT/pages/teaching/exercises/tests/Test4c.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test4c.java
new file mode 100644
index 000000000..544409db1
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test4c.java
@@ -0,0 +1,78 @@
+/* *******************************************************************
+ * 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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import java.awt.Rectangle;
+
+import junit.framework.*;
+
+public class Test4c extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test4c.class);
+ }
+
+ 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/modules/ROOT/pages/teaching/exercises/tests/Test4d.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test4d.java
new file mode 100644
index 000000000..dc7770f34
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test4d.java
@@ -0,0 +1,75 @@
+/* *******************************************************************
+ * 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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import java.awt.Rectangle;
+
+import junit.framework.*;
+
+public class Test4d extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test4d.class);
+ }
+
+ 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/modules/ROOT/pages/teaching/exercises/tests/Test4e.java b/docs/modules/ROOT/pages/teaching/exercises/tests/Test4e.java
new file mode 100644
index 000000000..4d8b18466
--- /dev/null
+++ b/docs/modules/ROOT/pages/teaching/exercises/tests/Test4e.java
@@ -0,0 +1,62 @@
+/* *******************************************************************
+ * 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 Eclipse Public License v 2.0
+ * which accompanies this distribution and is available at
+ * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package tests;
+
+import figures.*;
+import java.awt.Rectangle;
+
+import junit.framework.*;
+
+public class Test4e extends CoreTest {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(Test4e.class);
+ }
+
+ 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());
+ }
+}
+
+