When using the Visitor Pattern, can the visit(object) method update or modify the object it visits or is it simply supposed to only use the object in performing some computation and returning the computation result?
Thanks
All examples of the visitor pattern I've seen don't change the objects visited.
But as far as I understand the definition given on Wikipedia, it's just not defined what the visitor can do with the visited objects.
Even the definition from Gang of Four (also in the wiki article) doesn't touch that subject:
Represent an operation to be performed on elements of an object
structure. Visitor lets you define a new operation without changing
the classes of the elements on which it operates.
Therefore I'd say that a visitor may call any accessible method on an object it visits as this is not part of the visitor pattern - the visitor pattern just describes how this objects are made accessible.
In the following example the mailer is the "element" and the "visitor" is the lambda expression which is passed to send().
As you can see here (and in many other examples) the visitor can modify the element's internal state. That said, changing the element's internal state is not a requirement: it could be that the visitor will call some of the element's methods in order to do all sorts of actions: pass a message to another object, run a computation and print to screen the result and etc.
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
Mailer.send(mailer ->
mailer.from("me#hotmail.com")
.to("you#hotmail.com")
.body("what's up bud?")
);
}
}
class Mailer {
String fromStr;
String toStr;
String bodyStr;
public Mailer from(String from) {
this.fromStr = from;
return this;
}
public Mailer to(String to) {
this.toStr = to;
return this;
}
public Mailer body(String body) {
this.bodyStr = body;
return this;
}
public static void send(Consumer<Mailer> loader) {
Mailer mailer = new Mailer();
loader.accept(mailer);
System.out.println(mailer);
// ... send the email
}
#Override
public String toString() {
return "From: " + fromStr + "\n" +
"To: " + toStr + "\n" +
"Body: " + bodyStr;
}
}
The visitor pattern is not meant to modify the object's state. Instead, its purpose is to implement specific functionality.
A paradigm would be adding the functionality of counting the elements of a tree, an example I explain in this Case Study: Applied Design Patterns and Software Architecture.
The CharacterVisitor which holds the count value of the total visited CustomCharacter class has the following structure:
/**
* Implements the Visitor pattern
*/
class CharacterVisitor
{
private int count = 0;
void visitCharacter(CustomCharacter customCharacter)
{
count++;
}
public int getResult()
{
return count;
}
}
The countCharacters() function, which implements the logic of the Visitor pattern:
/**
* Counts the words in the text by using the Iterator and Visitor patterns.
*/
int countCharacters()
{
CharacterVisitor characterVisitor = new CharacterVisitor();
CharacterIterator characterIterator =
new CharacterIterator(editorController.getCompositeBuilder());
characterIterator.first();
while(!characterIterator.isDone())
{
CustomCharacter customCharacter = characterIterator.getCurrent();
customCharacter.accept(characterVisitor);
characterIterator.next();
}
return characterVisitor.getResult();
}
Note that in this example I also implement the Iterator pattern as well. I go in to more details in the case study.
You can find the complete code in this github repository, where I explain all of the design patterns mentioned in the legendary GOF book.
The visit(object) method is able to update or modify the object it visits. That said it is only able to update or modify fields or properties that are both public and not readonly on that class. Alternatively the visit method could use public methods that object exposes to update or modify the object.
Related
I am sorry for the vague question. I am not sure what I'm looking for here.
I have a Java class, let's call it Bar. In that class is an instance variable, let's call it foo. foo is a String.
foo cannot just have any value. There is a long list of strings, and foo must be one of them.
Then, for each of those strings in the list I would like the possibility to set some extra conditions as to whether that specific foo can belong in that specific type of Bar (depending on other instance variables in that same Bar).
What approach should I take here? Obviously, I could put the list of strings in a static class somewhere and upon calling setFoo(String s) check whether s is in that list. But that would not allow me to check for extra conditions - or I would need to put all that logic for every value of foo in the same method, which would get ugly quickly.
Is the solution to make several hundred classes for every possible value of foo and insert in each the respective (often trivial) logic to determine what types of Bar it fits? That doesn't sound right either.
What approach should I take here?
Here's a more concrete example, to make it more clear what I am looking for. Say there is a Furniture class, with a variable material, which can be lots of things, anything from mahogany to plywood. But there is another variable, upholstery, and you can make furniture containing cotton of plywood but not oak; satin furniture of oak but not walnut; other types of fabric go well with any material; et cetera.
I wouldn't suggest creating multiple classes/templates for such a big use case. This is very opinion based but I'll take a shot at answering as best as I can.
In such a case where your options can be numerous and you want to keep a maintainable code base, the best solution is to separate the values and the logic. I recommend that you store your foo values in a database. At the same time, keep your client code as clean and small as possible. So that it doesn't need to filter through the data to figure out which data is valid. You want to minimize dependency to data in your code. Think of it this way: tomorrow you might need to add a new material to your material list. Do you want to modify all your code for that? Or do you want to just add it to your database and everything magically works? Obviously the latter is a better option. Here is an example on how to design such a system. Of course, this can vary based on your use case or variables but it is a good guideline. The basic rule of thumb is: your code should have as little dependency to data as possible.
Let's say you want to create a Bar which has to have a certain foo. In this case, I would create a database for BARS which contains all the possible Bars. Example:
ID NAME FOO
1 Door 1,4,10
I will also create a database FOOS which contains the details of each foo. For example:
ID NAME PROPERTY1 PROPERTY2 ...
1 Oak Brown Soft
When you create a Bar:
Bar door = new Bar(Bar.DOOR);
in the constructor you would go to the BARS table and query the foos. Then you would query the FOOS table and load all the material and assign them to the field inside your new object.
This way whenever you create a Bar the material can be changed and loaded from DB without changing any code. You can add as many types of Bar as you can and change material properties as you goo. Your client code however doesn't change much.
You might ask why do we create a database for FOOS and refer to it's ids in the BARS table? This way, you can modify the properties of each foo as much as you want. Also you can share foos between Bars and vice versa but you only need to change the db once. cross referencing becomes a breeze. I hope this example explains the idea clearly.
You say:
Is the solution to make several hundred classes for every possible
value of foo and insert in each the respective (often trivial) logic
to determine what types of Bar it fits? That doesn't sound right
either.
Why not have separate classes for each type of Foo? Unless you need to define new types of Foo without changing the code you can model them as plain Java classes. You can go with enums as well but it does not really give you any advantage since you still need to update the enum when adding a new type of Foo.
In any case here is type safe approach that guarantees compile time checking of your rules:
public static interface Material{}
public static interface Upholstery{}
public static class Oak implements Material{}
public static class Plywood implements Material{}
public static class Cotton implements Upholstery{}
public static class Satin implements Upholstery{}
public static class Furniture<M extends Material, U extends Upholstery>{
private M matrerial = null;
private U upholstery = null;
public Furniture(M matrerial, U upholstery){
this.matrerial = matrerial;
this.upholstery = upholstery;
}
public M getMatrerial() {
return matrerial;
}
public U getUpholstery() {
return upholstery;
}
}
public static Furniture<Plywood, Cotton> cottonFurnitureWithPlywood(Plywood plywood, Cotton cotton){
return new Furniture<>(plywood, cotton);
}
public static Furniture<Oak, Satin> satinFurnitureWithOak(Oak oak, Satin satin){
return new Furniture<>(oak, satin);
}
It depends on what you really want to achieve. Creating objects and passing them around will not magically solve your domain-specific problems.
If you cannot think of any real behavior to add to your objects (except the validation), then it might make more sense to just store your data and read them into memory whenever you want. Even treat rules as data.
Here is an example:
public class Furniture {
String name;
Material material;
Upholstery upholstery;
//getters, setters, other behavior
public Furniture(String name, Material m, Upholstery u) {
//Read rule files from memory or disk and do all the checks
//Do not instantiate if validation does not pass
this.name = name;
material = m;
upholstery = u;
}
}
To specify rules, you will then create three plain text files (e.g. using csv format). File 1 will contain valid values for material, file 2 will contain valid values for upholstery, and file 3 will have a matrix format like the following:
upholstery\material plywood mahogany oak
cotton 1 0 1
satin 0 1 0
to check if a material goes with an upholstery or not, just check the corresponding row and column.
Alternatively, if you have lots of data, you can opt for a database system along with an ORM. Rule tables then can be join tables and come with extra nice features a DBMS may provide (like easy checking for duplicate values). The validation table could look something like:
MaterialID UpholsteryID Compatability_Score
plywood cotton 1
oak satin 0
The advantage of using this approach is that you quickly get a working application and you can decide what to do as you add new behavior to your application. And even if it gets way more complex in the future (new rules, new data types, etc) you can use something like the repository pattern to keep your data and business logic decoupled.
Notes about Enums:
Although the solution suggested by #Igwe Kalu solves the specific case described in the question, it is not scalable. What if you want to find what material goes with a given upholstery (the reverse case)? You will need to create another enum which does not add anything meaningful to the program, or add complex logic to your application.
This is a more detailed description of the idea I threw out there in the comment:
Keep Furniture a POJO, i.e., just hold the data, no behavior or rules implemented in it.
Implement the rules in separate classes, something along the lines of:
interface FurnitureRule {
void validate(Furniture furniture) throws FurnitureRuleException;
}
class ValidMaterialRule implements FurnitureRule {
// this you can load in whatever way suitable in your architecture -
// from enums, DB, an XML file, a JSON file, or inject via Spring, etc.
private Set<String> validMaterialNames;
#Overload
void validate(Furniture furniture) throws FurnitureRuleException {
if (!validMaterialNames.contains(furniture.getMaterial()))
throws new FurnitureRuleException("Invalid material " + furniture.getMaterial());
}
}
class UpholsteryRule implements FurnitureRule {
// Again however suitable to implement/config this
private Map<String, Set<String>> validMaterialsPerUpholstery;
#Overload
void validate(Furniture furniture) throws FurnitureRuleException {
Set<String> validMaterialNames = validMaterialsPerUpholstery.get(furniture.getUpholstery();
if (validMaterialNames != null && !validMaterialNames.contains(furniture.getMaterial()))
throws new FurnitureRuleException("Invalid material " + furniture.getMaterial() + " for upholstery " + furniture.getUpholstery());
}
}
// and more complex rules if you need to
Then have some service along the lines of FurnitureManager. It's the "gatekeeper" for all Furniture creation/updates:
class FurnitureManager {
// configure these via e.g. Spring.
private List<FurnitureRule> rules;
public void updateFurniture(Furniture furniture) throws FurnitureRuleException {
rules.forEach(rule -> rule.validate(furniture))
// proceed to persist `furniture` in the database or whatever else you do with a valid piece of furniture.
}
}
material should be of type Enum.
public enum Material {
MAHOGANY,
TEAK,
OAK,
...
}
Furthermore you can have a validator for Furniture that contains the logic which types of Furniture make sense, and then call that validator in every method that can change the material or upholstery variable (typically only your setters).
public class Furniture {
private Material material;
private Upholstery upholstery; //Could also be String depending on your needs of course
public void setMaterial(Material material) {
if (FurnitureValidator.isValidCombination(material, this.upholstery)) {
this.material = material;
}
}
...
private static class FurnitureValidator {
private static boolean isValidCombination(Material material, Upholstery upholstery) {
switch(material) {
case MAHOGANY: return upholstery != Upholstery.COTTON;
break;
//and so on
}
}
}
}
We often are oblivious of the power inherent in enum types. The Java™ Tutorials clearly states "you should use enum types any time you need to represent a fixed set of constants."
How do you simply make the best of enum in resolving the challenge you presented? - Here goes:
public enum Material {
MAHOGANY( "satin", "velvet" ),
PLYWOOD( "leather" ),
// possibly many other materials and their matching fabrics...
OAK( "some other fabric - 0" ),
WALNUT( "some other fabric - 0", "some other fabric - 1" );
private final String[] listOfSuitingFabrics;
Material( String... fabrics ) {
this.listOfSuitingFabrics = fabrics;
}
String[] getListOfSuitingFabrics() {
return Arrays.copyOf( listOfSuitingFabrics );
}
public String toString() {
return name().substring( 0, 1 ) + name().substring( 1 );
}
}
Let's test it:
public class TestMaterial {
for ( Material material : Material.values() ) {
System.out.println( material.toString() + " go well with " + material.getListOfSuitingFabrics() );
}
}
Probably the approach I'd use (because it involves the least amount of code and it's reasonably fast) is to "flatten" the hierarchical logic into a one-dimensional Set of allowed value combinations. Then when setting one of the fields, validate that the proposed new combination is valid. I'd probably just use a Set of concatenated Strings for simplicity. For the example you give above, something like this:
class Furniture {
private String wood;
private String upholstery;
/**
* Set of all acceptable values, with each combination as a String.
* Example value: "plywood:cotton"
*/
private static final Set<String> allowed = new HashSet<>();
/**
* Load allowed values in initializer.
*
* TODO: load allowed values from DB or config file
* instead of hard-wiring.
*/
static {
allowed.add("plywood:cotton");
...
}
public void setWood(String wood) {
if (!allowed.contains(wood + ":" + this.upholstery)) {
throw new IllegalArgumentException("bad combination of materials!");
}
this.wood = wood;
}
public void setUpholstery(String upholstery) {
if (!allowed.contains(this.wood + ":" + upholstery)) {
throw new IllegalArgumentException("bad combination of materials!");
}
this.upholstery = upholstery;
}
public void setMaterials(String wood, String upholstery) {
if (!allowed.contains(wood + ":" + upholstery)) {
throw new IllegalArgumentException("bad combination of materials!");
}
this.wood = wood;
this.upholstery = upholstery;
}
// getters
...
}
The disadvantage of this approach compared to other answers is that there is no compile-time type checking. For example, if you try to set the wood to plywoo instead of plywood you won’t know about your error until runtime. In practice this disadvantage is negligible since presumably the options will be chosen by a user through a UI (or through some other means), so you won’t know what they are until runtime anyway. Plus the big advantage is that the code will never have to be changed so long as you’re willing to maintain a list of allowed combinations externally. As someone with 30 years of development experience, take my word for it that this approach is far more maintainable.
With the above code, you'll need to use setMaterials before using setWood or setUpholstery, since the other field will still be null and therefore not an allowed combination. You can initialize the class's fields with default materials to avoid this if you want.
I am using a composite pattern with multiple leaf node classes which have specialist operations and a visitor pattern to allow those operations to be performed. In this example I've left out all the obvious accept methods for clarity.
interface Command {
public int getCost();
}
class SimpleCommand implements Command {
private int cost;
public int getCost() {
return cost;
}
}
class MultiCommand implements Command {
private Command subcommand;
private int repeated;
public int getCost() {
return repeated * subcommand.getCost();
}
public void decrement() {
if (repeated > 0)
repeated--;
}
}
class CommandList implements Command {
private List<Command> commands;
public int getCost() {
return commands.stream().mapToInt(Command::getCost).sum();
}
public void add(Command command) {
commands.add(command);
}
}
interface CommandVisitor {
default void visitSimpleCommand(SimpleCommandCommand command) { }
default void visitMultiCommand(MultiCommand multiCommand) { }
default void visitCommandList(CommandList commandList) { }
}
It's now possible to build visitors to perform operations such as decrement. However I find it easier to create a general purpose visitor that streams objects of a certain class so that any operation can be performed on them:
class MultiCommandCollector implements CommandVisitor {
private final Stream.Builder<MultiCommand> streamBuilder = Stream.builder();
public static Stream<MultiCommand> streamFor(Command command) {
MultiCommandVisitor visitor = new MultiCommandVisitor();
command.accept(visitor);
return visitor.streamBuilder.build();
}
public void visitMultiCommand(MultiCommand multiCommand) {
builder.accept(multiCommand);
}
}
This is used as you would expect. For example:
MultiCommandCollector.streamFor(command).forEach(MultiCommand::decrement);
This has one significant limitation: it can't be used to alter the hierarchy as the stream is processed. For example, the following fails:
CommandListCollector.streamFor(commandList).forEach(cl -> cl.add(command));
I can't think of an alternative elegant design that would allow this.
My question is: is there a natural extension to this design to allow a general purpose visitor that can also alter the hierarchy? In other words, is there a way that the visitor can visit one member then refresh the hierarchy before visiting the next? Is this compatible with the use of streams?
In my prior experience, Visitor pattern is useful to either query or to recreate the hierarchy. The querying part is obvious - you would simply listen for specific types of sub-objects and then build the query result as it fits. The other question, changing the hierarchy, is more difficult.
It may really get hard to change the hierarchy while iterating through it. Therefore, I know of two useful techniques that work fine in practice.
While visiting the hierarchy, build the list of objects to change.
Do not change them until the visiting is completed. Concrete visitor
can build the list of objects of interest as its private member. Once it
completes the visit, it would expose the list of objects as its result.
Only then start iterating through the resulting list and make changes to
the objects.
While visiting the hierarchy, as you visit an element, create a copy of
the element. If the element needs to be changed, then construct the changed
version. Otherwise, if the elements needs not change, just return it as the
new element. After entire visit is done, you will have the new hierarchy
with all modifications made as intended. The old hierarchy could be
dereferenced then, and garbage collector will collect those elements which
have been replaced with new ones.
The first algorithm is applicable when elements are mutable. The second algorithm is applicable when elements are immutable.
Hope this helps.
How can I get the names of the methods invoked in each method declaration of a program using AST (Abstract Syntax Tree) parser? So far, I have managed to get all the names of the methods' declaration and all the names of the methods being invoked, but I want to know which method call which methods. For example, I want to see that method m1 calls methods mA and mB, while method m2 calls methods mC and mD, etc.
[EDIT 11/9/2011 IDB, transcribing newbie's extended comment back in the body of the original question. I hope I have transcribed it correctly. I hope the author comes back and revises as necessary]:
My problem seems to be that (Eclipse's) MethodDeclaration api doesn't have a GetInvokedMethodName function to call. Here is my code:
public class MethodVisitor extends ASTVisitor {
List<MethodDeclaration> methods = new ArrayList<MethodDeclaration>();
#Override public boolean visit(MethodDeclaration node) {
methods.add(node);
return super.visit(node); }
public List<MethodDeclaration> getMethods()
{ return methods; }
List<MethodInvocation> methods1 = new ArrayList<MethodInvocation>();
#Override public boolean visit(MethodInvocation node)
{ methods1.add(node);
return super.visit(node); }
public List<MethodInvocation> getMethods1()
{ return methods1; }
}
...
for (MethodDeclaration method : visitor .getMethods())
{ System.out.println("Method name: " + method.getName()
+ " Return type: " + method.getReturnType2()
+ " Is constructor: " + method.isConstructor()
+ " Method invoked: " + ASTNode.METHOD_INVOCATION );
); }
for (MethodInvocation method1 : visitor .getMethods1())
{ System.out.println("Method name invoked: " + method1.getName() ); }
I had the same problem. This was my solution to it:
final HashMap<MethodDeclaration, ArrayList<MethodInvocation>> invocationsForMethods =
new HashMap<MethodDeclaration, ArrayList<MethodInvocation>>();
CompilationUnit cu = (CompilationUnit) ap.createAST(null);
cu.accept(new ASTVisitor() {
private MethodDeclaration activeMethod;
#Override
public boolean visit(MethodDeclaration node) {
activeMethod = node;
return super.visit(node);
}
#Override
public boolean visit(MethodInvocation node) {
if (invocationsForMethods.get(activeMethod) == null) {
invocationsForMethods.put(activeMethod, new ArrayList<MethodInvocation>());
}
invocationsForMethods.get(activeMethod).add(node);
return super.visit(node);
}
});
Now, one can ask the invocationsForMethods.keySet() to get all the method declarations for the used AST and invocationsForMethods.get(key) returns all method invocations for the declaration given as a key.
If you want to know which specific method mB (of all the ones named "mB" throughout your vast array of classes) is invoked by m1, you need more than just the AST. You need a full symbol table, that binds each symbol use to the possible definitions that match it.
The process of computing such a symbol table is difficult for many languages and very hard for Java (but not nearly as bad as it is for C++). Somebody has to encode the rules of how an identifier is looked up in the face of (local) scopes, inheritance, overloads, implied casts, etc, and the Java reference manual devotes a significant portion of its content trying to explain that. You don't want to have to do this yourself.
What you really need is a full Java front end, that has both ASTs and the corresponding symbol tables, for each method you want to inspect. You can get this, I think, from interfaces to the (Sun?) Java compiler (I don't personally know how to do this), from the Jikes compiler, from the Eclipse Java AST (?) module, and from tools such as our Java Front End. Another approach is to process class files, which contain the method calls in JVM form, with the advavntage that the JVM instructions all have built with the benefit of a symbol table.
If you want to compute m1 calls mA calls mQ calls .... mZ, you need a tool that is willing to read in the entire source code base at once. The compilers won't do that for you, but you can use Eclipse or our front end to do that.
I'm trying to write a unit test (using JMockit) that verifies that methods are called according to a partial order. The specific use case is ensuring that certain operations are called inside a transaction, but more generally I want to verify something like this:
Method beginTransaction is called.
Methods operation1 through to operationN are called in any order.
Method endTransaction is called.
Method someOtherOperation is called some time before, during or after the transaction.
The Expectations and Verifications APIs don't seem to be able to handle this requirement.
If I have a #Mocked BusinessObject bo I can verify that the right methods are called (in any order) with this:
new Verifications() {{
bo.beginTransaction();
bo.endTransaction();
bo.operation1();
bo.operation2();
bo.someOtherOperation();
}};
optionally making it a FullVerifications to check that there are no other side-effects.
To check the ordering constraints I can do something like this:
new VerificationsInOrder() {{
bo.beginTransaction();
unverifiedInvocations();
bo.endTransaction();
}};
but this does not handle the someOtherOperation case. I can't replace the unverifiedInvocations with bo.operation1(); bo.operation2() because that puts a total ordering on the invocations. A correct implementation of the business method could call bo.operation2(); bo.operation1().
If I make it:
new VerificationsInOrder() {{
unverifiedInvocations();
bo.beginTransaction();
unverifiedInvocations();
bo.endTransaction();
unverifiedInvocations();
}};
then I get a "No unverified invocations left" failure when someOtherOperation is called before the transaction. Trying bo.someOtherOperation(); minTimes = 0 also doesn't work.
So: Is there a clean way to specify partial ordering requirements on method calls using the Expectations/Verifications API in JMockIt? Or do I have to use a MockClass and manually keep track of invocations, a la:
#MockClass(realClass = BusinessObject.class)
public class MockBO {
private boolean op1Called = false;
private boolean op2Called = false;
private boolean beginCalled = false;
#Mock(invocations = 1)
public void operation1() {
op1Called = true;
}
#Mock(invocations = 1)
public void operation2() {
op2Called = true;
}
#Mock(invocations = 1)
public void someOtherOperation() {}
#Mock(invocations = 1)
public void beginTransaction() {
assertFalse(op1Called);
assertFalse(op2Called);
beginCalled = true;
}
#Mock(invocations = 1)
public void endTransaction() {
assertTrue(beginCalled);
assertTrue(op1Called);
assertTrue(op2Called);
}
}
if you really need such test then: don't use mocking library but create your own mock with state inside that can simply check the correct order of methods.
but testing order of invocations is usually a bad sign. my advice would be: don't test it, refactor. you should test your logic and results rather than a sequence of invocations. check if side effects are correct (database content, services interaction etc). if you test the sequence then your test is basically exact copy of your production code. so what's the added value of such test? and such test is also very fragile (as any duplication).
maybe you should make your code looks like that:
beginTransaction()
doTransactionalStuff()
endTransaction()
doNonTransactionalStuff()
From my usage of jmockit, I believe the answer is no even in the latest version 1.49.
You can implement this type of advanced verification using a MockUp extension with some internal fields to keep track of which functions get called, when, and in what order.
For example, I implemented a simple MockUp to track method call counts. The purpose of this example is real, for where the Verifications and Expectations times fields did not work when mocking a ThreadGroup (useful for other sensitive types as well):
public class CalledCheckMockUp<T> extends MockUp<T>
{
private Map<String, Boolean> calledMap = Maps.newHashMap();
private Map<String, AtomicInteger> calledCountMap = Maps.newHashMap();
public void markAsCalled(String methodCalled)
{
if (methodCalled == null)
{
Log.logWarning("Caller attempted to mark a method string" +
" that is null as called, this is surely" +
" either a logic error or an unhandled edge" +
" case.");
}
else
{
calledMap.put(methodCalled, Boolean.TRUE);
calledCountMap.putIfAbsent(methodCalled, new AtomicInteger()).
incrementAndGet();
}
}
public int methodCallCount(String method)
{
return calledCountMap.putIfAbsent(method, new AtomicInteger()).get();
}
public boolean wasMethodCalled(String method)
{
if (method == null)
{
Log.logWarning("Caller attempted to mark a method string" +
" that is null as called, this is surely" +
" either a logic error or an unhandled edge" +
" case.");
return false;
}
return calledMap.containsKey(method) ? calledMap.get(method) :
Boolean.FALSE;
}
}
With usage like the following, where cut1 is a dynamic proxy type that wraps an actual ThreadGroup:
String methodId = "activeCount";
CalledCheckMockUp<ThreadGroup> calledChecker = new CalledCheckMockUp<ThreadGroup>()
{
#Mock
public int activeCount()
{
markAsCalled(methodId);
return active;
}
};
. . .
int callCount = 0;
int activeCount = cut1.activeCount();
callCount += 1;
Assertions.assertTrue(calledChecker.wasMethodCalled(methodId));
Assertions.assertEquals(callCount, calledChecker.methodCallCount(methodId));
I know question is old and this example doesn't fit OP's use case exactly, but hoping it may help guide others to a potential solution that come looking (or the OP, god-forbid this is still unsolved for an important use case, which is unlikely).
Given the complexity of what OP is trying to do, it may help to override the $advice method in your custom MockUp to ease differentiating and recording method calls. Docs here: Applying AOP-style advice.
I'm working on a small UML editor project, in Java, that I started a couple of months ago. After a few weeks, I got a working copy for a UML class diagram editor.
But now, I'm redesigning it completely to support other types of diagrams, such a sequence, state, class, etc. This is done by implementing a graph construction framework (I'm greatly inspired by Cay Horstmann work on the subject with the Violet UML editor).
Redesign was going smoothly until one of my friends told me that I forgot to add a Do/Undo functionnality to the project, which, in my opinion, is vital.
Remembering object oriented design courses, I immediately thought of Memento and Command pattern.
Here's the deal. I have a abstract class, AbstractDiagram, that contains two ArrayLists : one for storing nodes (called Elements in my project) and the other for storing Edges (called Links in my projects). The diagram will probably keep a stack of commands that can be Undoed/Redoed. Pretty standard.
How can I execute these commands in a efficient way? Say, for example, that I want to move a node (the node will be an interface type named INode, and there will be concrete nodes derived from it (ClassNode, InterfaceNode, NoteNode, etc.)).
The position information is held as an attribute in the node, so by modying that attribute in the node itself, the state is changed. When the display will be refreshed, the node will have moved. This is the Memento part of the pattern (I think), with the difference that the object is the state itself.
Moreover, if I keep a clone of the original node (before it moved), I can get back to its old version. The same technique applies for the information contained in the node (the class or interface name, the text for a note node, the attributes name, and so on).
The thing is, how do I replace, in the diagram, the node with its clone upon undo/redo operation? If I clone the original object that is referenced by the diagram (being in the node list), the clone isn't reference in the diagram, and the only thing that points to is the Command itself! Shoud I include mechanisms in the diagram for finding a node according to an ID (for example) so I can replace, in the diagram, the node by its clone (and vice-versa) ? Is it up to the Memento and Command patterns to do that ? What about links? They should be movable too but I don't want to create a command just for links (and one just for nodes), and I should be able to modify the right list (nodes or links) according to the type of the object the command is referring to.
How would you proceed? In short, I am having trouble representing the state of an object in a command/memento pattern so that it can be efficiently recovered and the original object restored in the diagram list, and depending on the object type (node or link).
Thanks a lot!
Guillaume.
P.S.: if I'm not clear, tell me and I will clarify my message (as always!).
Edit
Here's my actual solution, that I started implementing before posting this question.
First, I have an AbstractCommand class defined as follow :
public abstract class AbstractCommand {
public boolean blnComplete;
public void setComplete(boolean complete) {
this.blnComplete = complete;
}
public boolean isComplete() {
return this.blnComplete;
}
public abstract void execute();
public abstract void unexecute();
}
Then, each type of command is implemented using a concrete derivation of AbstractCommand.
So I have a command to move an object :
public class MoveCommand extends AbstractCommand {
Moveable movingObject;
Point2D startPos;
Point2D endPos;
public MoveCommand(Point2D start) {
this.startPos = start;
}
public void execute() {
if(this.movingObject != null && this.endPos != null)
this.movingObject.moveTo(this.endPos);
}
public void unexecute() {
if(this.movingObject != null && this.startPos != null)
this.movingObject.moveTo(this.startPos);
}
public void setStart(Point2D start) {
this.startPos = start;
}
public void setEnd(Point2D end) {
this.endPos = end;
}
}
I also have a MoveRemoveCommand (to... move or remove an object/node). If I use the ID of instanceof method, I don't have to pass the diagram to the actual node or link so that it can remove itself from the diagram (which is a bad idea I think).
AbstractDiagram diagram;
Addable obj;
AddRemoveType type;
#SuppressWarnings("unused")
private AddRemoveCommand() {}
public AddRemoveCommand(AbstractDiagram diagram, Addable obj, AddRemoveType type) {
this.diagram = diagram;
this.obj = obj;
this.type = type;
}
public void execute() {
if(obj != null && diagram != null) {
switch(type) {
case ADD:
this.obj.addToDiagram(diagram);
break;
case REMOVE:
this.obj.removeFromDiagram(diagram);
break;
}
}
}
public void unexecute() {
if(obj != null && diagram != null) {
switch(type) {
case ADD:
this.obj.removeFromDiagram(diagram);
break;
case REMOVE:
this.obj.addToDiagram(diagram);
break;
}
}
}
Finally, I have a ModificationCommand which is used to modify the info of a node or link (class name, etc.). This may be merged in the future with the MoveCommand. This class is empty for now. I will probably do the ID thing with a mechanism to determine if the modified object is a node or an edge (via instanceof or a special denotion in the ID).
Is this is a good solution?
I think you just need to decompose your problem into smaller ones.
First problem:
Q: How to represent the steps in your app with the memento/command pattern?
First off, I have no idea exactly how your app works but hopefully you will see where I am going with this. Say I want to place a ClassNode on the diagram that with the following properties
{ width:100, height:50, position:(10,25), content:"Am I certain?", edge-connections:null}
That would be wrapped up as a command object. Say that goes to a DiagramController. Then the diagram controller's responsibility can be to record that command (push onto a stack would be my bet) and pass the command to a DiagramBuilder for example. The DiagramBuilder would actually be responsible for updating the display.
DiagramController
{
public DiagramController(diagramBuilder:DiagramBuilder)
{
this._diagramBuilder = diagramBuilder;
this._commandStack = new Stack();
}
public void Add(node:ConditionalNode)
{
this._commandStack.push(node);
this._diagramBuilder.Draw(node);
}
public void Undo()
{
var node = this._commandStack.pop();
this._diagramBuilderUndraw(node);
}
}
Some thing like that should do it and of course there will be plenty of details to sort out. By the way, the more properties your nodes have the more detailed Undraw is going to have to be.
Using an id to link the command in your stack to the element drawn might be a good idea. That might look like this:
DiagramController
{
public DiagramController(diagramBuilder:DiagramBuilder)
{
this._diagramBuilder = diagramBuilder;
this._commandStack = new Stack();
}
public void Add(node:ConditionalNode)
{
string graphicalRefId = this._diagramBuilder.Draw(node);
var nodePair = new KeyValuePair<string, ConditionalNode> (graphicalRefId, node);
this._commandStack.push(nodePair);
}
public void Undo()
{
var nodePair = this._commandStack.pop();
this._diagramBuilderUndraw(nodePair.Key);
}
}
At this point you don't absolutely have to have the object since you have the ID but it will be helpful should you decide to also implement redo functionality. A good way to generate the id for your nodes would be to implement a hashcode method for them except for the fact that you wouldn't be guaranteed not to duplicate your nodes in such a way that would cause the hash code to be identical.
The next part of the problem is within your DiagramBuilder because you're trying to figure out how the heck to deal with these commands. For that all I can say is to really just ensure you can create an inverse action for each type of component you can add. To handle the delinking you can look at the edge-connection property (links in your code I think) and notify each of the edge-connections that they are to disconnect from the specific node. I would assume that on disconnection they could redraw themselves appropriately.
To kinda summarize, I would recommend not keeping a reference to your nodes in the stack but instead just a kind of token that represents a given node's state at that point. This will allow you to represent the same node in your undo stack at multiple places without it referring to the same object.
Post if you've got Q's. This is a complex issue.
In my humble opinion, you're thinking it in a more complicated way than it really is. In order to revert to previous state, clone of whole node is not required at all. Rather each **Command class will have -
reference to the node it is acting upon,
memento object (having state variables just enough for the node to revert to)
execute() method
undo() method.
Since command classes have reference to the node, we do not need ID mechanism to refer to objects in the diagram.
In the example from your question, we want to move a node to a new position. For that, we have a NodePositionChangeCommand class.
public class NodePositionChangeCommand {
// This command will act upon this node
private Node node;
// Old state is stored here
private NodePositionMemento previousNodePosition;
NodePositionChangeCommand(Node node) {
this.node = node;
}
public void execute(NodePositionMemento newPosition) {
// Save current state in memento object previousNodePosition
// Act upon this.node
}
public void undo() {
// Update this.node object with values from this.previousNodePosition
}
}
What about links? They should be movable too but I don't want to create a command just for links (and one just for nodes).
I read in GoF book (in memento pattern discussion) that move of link with change in position of nodes are handled by some kind of constraint solver.