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