oneHour talk three hour tutorial six hour tutorial including exercisestags/V1_1_1
/* ******************************************************************* | |||||
* 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"; | |||||
} |
/* ******************************************************************* | |||||
* 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"; | |||||
} |
/* ******************************************************************* | |||||
* 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"; | |||||
} |
/* ******************************************************************* | |||||
* 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"; | |||||
} |
/* ******************************************************************* | |||||
* 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"); | |||||
} | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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"); | |||||
} | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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"); | |||||
} | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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"); | |||||
} | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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(); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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(); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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"); | |||||
} | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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"); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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"); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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; | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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; | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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; | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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; | |||||
} | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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; | |||||
} | |||||
} | |||||
} |
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 |
/* ******************************************************************* | |||||
* 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()); | |||||
} | |||||
} | |||||
/* ******************************************************************* | |||||
* 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); | |||||
} |
/* ******************************************************************* | |||||
* 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(); | |||||
} | |||||
} | |||||
/* ******************************************************************* | |||||
* 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(); | |||||
} | |||||
} | |||||
/* ******************************************************************* | |||||
* 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); | |||||
} | |||||
} | |||||
/* ******************************************************************* | |||||
* 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); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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); | |||||
} | |||||
} | |||||
/* ******************************************************************* | |||||
* 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; | |||||
} | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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); | |||||
} | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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); | |||||
} | |||||
} |
-argfile | |||||
base.lst | |||||
figures/gui/FigurePanel.java | |||||
figures/gui/Main.java | |||||
figures/gui/LogAdapter.java |
<!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> |
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) |
#!/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 |
@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 |
/* ******************************************************************* | |||||
* 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); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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()); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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) { | |||||
} | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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) { | |||||
} | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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) { | |||||
} | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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) { | |||||
} | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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) { } | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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) { } | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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()); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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()); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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()); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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()); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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); | |||||
} | |||||
} |
/* ******************************************************************* | |||||
* 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)); | |||||
} | |||||
} | |||||
/* ******************************************************************* | |||||
* 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); | |||||
} | |||||
} | |||||
/* ******************************************************************* | |||||
* 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()); | |||||
} | |||||
} | |||||
/* ******************************************************************* | |||||
* 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()); | |||||
} | |||||
} | |||||
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 |