Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Insert code into a method - Java

Is there a way to automatically insert code into a method?

I have the following typical field with a getter and setter and I would like to insert the indicated code into the setter method that records if the field was modified as well to insert the indicated "isFirstNameModified" field to also track if the field was modified or not.

 public class Person {

      Set<String> updatedFields = new LinkedHashSet<String>();

      String firstName;
      public String getFirstName(){
           return firstName;
      }

      boolean isFirstNameChanged = false;           // This code is inserted later
      public void setFirstName(String firstName){       
           if( !isFirstNameChanged ){               // This code is inserted later
                isFirstNameChanged = true;          // This code is inserted later
                updatedFields.add("firstName");     // This code is inserted later
           }                                        // This code is inserted later
           this.firstName = firstName;
      }
 }

I'm also not sure if I can the subset of the method name as a string from inside the method itself as indicated on the line where I add the fieldName as a string into the set of updated fields: updatedFields.add("firstName");. And I'm not sure how to insert fields into a class where I add the boolean field that tracks if the field has been modified or not before (for efficiency to prevent having to manipulate the Set): boolean isFirstNameChanged = false;

It seems to most obvious answer to this would be to use code templates inside eclipse, but I'm concerned about having to go back and change the code later.

Edit:::::::::

I Should have used this simpler code instead of the example above. All it does is add the name of the field as a string to a set.

 public class Person {

  Set<String> updatedFields = new LinkedHashSet<String>();

  String firstName;
  public String getFirstName(){
       return firstName;
  }
  public void setFirstName(String firstName){       
       updatedFields.add("firstName");        // This code is inserted later
       this.firstName = firstName;
  }

}

like image 479
Chris Dutrow Avatar asked Jun 13 '10 05:06

Chris Dutrow


1 Answers

Yes you can, one approach is to use some form of byte code manipulation (e.g. javassist, ASM, BCEL) or a higher level AOP library sit on top of one of these tools, e.g. AspectJ, JBoss AOP.

Note: most JDO libraries do this for handling persistence.

Here is an example using javassist:

public class Person {

    private String firstName;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
}

public static void rewritePersonClass() throws NotFoundException, CannotCompileException {
    ClassPool pool = ClassPool.getDefault();
    CtClass ctPerson = pool.get("Person");
    CtClass ctSet = pool.get("java.util.LinkedHashSet");

    CtField setField = new CtField(ctSet, "updatedFields", ctPerson);
    ctPerson.addField(setField, "new java.util.LinkedHashSet();");

    CtMethod method = ctPerson.getDeclaredMethod("setFirstName");
    method.insertBefore("updatedFields.add(\"firstName\");");

    ctPerson.toClass();
}


public static void main(String[] args) throws Exception {
    rewritePersonClass();

    Person p = new Person();
    p.setFirstName("foo");

    Field field = Person.class.getDeclaredField("updatedFields");
    field.setAccessible(true);
    Set<?> s = (Set<?>) field.get(p);

    System.out.println(s);
}
like image 172
Michael Barker Avatar answered Sep 28 '22 03:09

Michael Barker