use eclipse to autowrap an object

Tuesday, April 07, 2009

I'm sure there's a better design methodology to do this, but I have an issue in Java where the PostgreSQL JDBC driver can't execute createBlob() (in JDBC3 spec), so I want to overwrite its Connection. I can't subclass it, as it's returned from the call DriverManager.getConnection(...). So what I need to do is use the Wrapper design pattern, aka Decorator, aka Delegator. Oh wouldn't it be great to use via? But alas, until my cry is heard, or someone corrects me, the solution is to:

  1. Create a new class that also implements Connection.
  2. Use this class to wrap the obtained PostgreSQLConnection
  3. Painstakingly implement each and every method in Connection to pass through to the wrapped connection, except for the methods I want to meddle with.
  4. Pass out of my Connection-obtainer class, not the raw Connection, but my new wrapper.
  5. Accept resignedly that when the Connection interface changes, my Connection wrapper will now not fulfil the new interface and will break. Really good reason for via.
So enough whinging. In Eclipse, it is just a matter of creating a new class, and implementing Connection. If the methods didn't appear then the class name will have an error; Ctrl+1 on this gives the option 'Add unimplemented methods'. And there they will be, all 50 of them (rough count), ready to type this.connection.blah() in each. But hey, Eclipse can do multiline regex finds, and we can use regular expressions in the find and replace, so....

To fix all wrapped method calls that return a value:
In the new class, Ctrl-F to bring up the find/replace dialog. Make sure 'Wrap search' and 'Regular expression' are ticked, and 'Scope' is 'All', then copy and paste into Find:
(?s)[^\n]*(public (?!class)[^\n]* (\S*\([^\)]*\))[^\{]*\{)[^\}]*return[^\}]*}

This searches for any lines having the word public, not followed by class, and having a return statement.
Hit Find a few times to validate it's matching correctly.

Now, in Replace:
\1\nreturn this.myWrappedFieldName.\2;\n}

Takes the first match (\1) and appends the method call (\2) to the field name.

Click 'Replace All' to see it happen.

To fix the remaining method calls with no return value (ie void)
In Find:
(?m).*(public void (\S*\([^\n]*\)).*\{)[^\}]*}

Now, in Replace:
\1\nthis.myWrappedFieldName.\2;\n}

And 'Replace All' again.

As yet the above regex statements don't remove parameter types from the calling statements, so you will have to go through and remove them, but that should be relatively little work.

0 comments:

Post a Comment