Posted by & filed under openSUSE, Uncategorized.

The steam linux beta is now open to everyone. I just installed it on my openSUSE PC. Here’s how.

Update Andrew Wafaa pointed out that there’s an rpm package providing a much easier installation option that I could have found myself ¬_¬

It wasn’t entirely straightforward as there is only an Ubuntu package. These steps are unlikely to work on all setups, but they may help someone. I’m using 64bit openSUSE 12.2

Steam on Linux

1. Add tools repository

$ zypper ar http://download.opensuse.org/repositories/utilities/openSUSE_12.2/ alien

2. Install alien and steam’s dependencies

Alien is a tool that can convert debian packages to RPMs.

$ zypper in alien libpango-1_0-0-32bit libgtk-2_0-0-32bit  mozilla-nss-32bit  libgcrypt11-32bit  libopenal1-soft-32bit libpulse0-32bit libpng12-0-32bit

3. Download the steam deb package

$ wget http://media.steampowered.com/client/installer/steam.deb

4. Convert steam deb to an rpm

$ alien --to-rpm ./steam.deb

5. Install rpm

$ rpm -Uvh ./steam*.rpm

6. Run steam

$ SDL_AUDIODRIVER=alsa steam

The SDL_AUDIODRIVER=alsa was needed for me because I uninstalled pulseaudio because I like being able to play multiple audio streams at the same time.

Posted by & filed under openSUSE, webpin.

I have added support for searching by package names only. This was one of the most requested features.

I would like to make the normal search “just work” as much as possible and rank relevant search results highly. However, there do seem to be some good use cases for only searching package names.

You can do so by prefixing a search term with either name: to restrict your search to package names or exact: to find only packages that exactly match the specified name.

Compare name:amarok vs exact:amarok vs amarok

I’ve added a tips page to document these hidden features.

This week I’ve also

  • Added google chrome repository for openSUSE 12.2
  • Indexed more OBS repositories

Please do keep your suggestions and bug reports coming via email.

Posted by & filed under c#, Java.

Someone on IRC was asking whether it was possible to do catch multiple types of exceptions at the same time in c#.

In Java 7 there’s a feature from project coin called multi catch that enables the following syntax:

public class MultiCatch {
	public static void main(String... args) {
		try {
			throw new ExceptionA();	
		} catch (final ExceptionA | ExceptionB ex) {
			System.out.println("Got " + ex.getClass().getSimpleName());
		}
	}
}
 
class ExceptionA extends RuntimeException {}
class ExceptionB extends RuntimeException {}

Here the catch block catches either an ExceptionA or an ExceptionB. This can be useful if you want to handle several exceptions in the same way.

I don’t believe c# has a similar language feature, however since it has lambdas you can replicate something similar yourself like so:

using System;
 
public class MultiCatch {
  public static void Main() {
    Trier.Try(() => {
      throw new ExceptionA(" Hello A");
    }).Catch<ExceptionA, ExceptionB>(ex => {
      Console.WriteLine(ex.GetType() + ex.Message);
    });
 
    Trier.Try(() => {
      throw new ExceptionC(" Hello C");
    }).Catch<ExceptionA, ExceptionB, ExceptionC>(ex => {
      Console.WriteLine(ex.GetType() + ex.Message);
    });
  }
}

We create a method called Try and pass it an Action. We then chain a call to a Catch method which we pass the Exceptions we want to catch as Type arguments. As you can see we can vary the number of type arguments. This is something you can’t do in Java partly due to type erasure.

The Try method simply passes the action through to a Catcher

  public static Catcher Try(Action action) {
    return new Catcher(action);
  }

and the Catch method has overloads for any number of exceptions you want to support. We can restrict the type arguments to only Exception types by using the where clause.

  public void Catch<T,U>(Action<Exception> catchAction) where T : Exception where U : Exception {
    try {
      action();
    } catch (T t) {
      catchAction(t);
    } catch (U u) {
      catchAction(u);
    }
  }

Here’s the full code listing:

using System;
 
public class MultiCatch {
  public static void Main() {
    Trier.Try(() => {
      throw new ExceptionA(" Hello A");
    }).Catch<ExceptionA, ExceptionB>(ex => {
      Console.WriteLine(ex.GetType() + ex.Message);
    });
 
    Trier.Try(() => {
      throw new ExceptionC(" Hello C");
    }).Catch<ExceptionA, ExceptionB, ExceptionC>(ex => {
      Console.WriteLine(ex.GetType() + ex.Message);
    });
  }
}
 
class Trier {
  public static Catcher Try(Action action) {
    return new Catcher(action);
  }
}
 
class Catcher {
  private Action action;
  public Catcher(Action action) {
    this.action = action;
  }
 
  public void Catch<T,U>(Action<Exception> catchAction) where T : Exception where U : Exception {
    try {
      action();
    } catch (T t) {
      catchAction(t);
    } catch (U u) {
      catchAction(u);
    }
  }
 
   public void Catch<T,U,V>(Action<Exception> catchAction) where T : Exception where U : Exception where V : Exception {
    try {
      action();
    } catch (T t) {
      catchAction(t);
    } catch (U u) {
      catchAction(u);
    } catch (V v) {
      catchAction(v);
    }
  }
}
 
class ExceptionA : Exception {
  public ExceptionA(string message) : base(message) {}
}
 
class ExceptionB : Exception {
  public ExceptionB(string message) : base(message) {}
}
 
class ExceptionC : Exception {
  public ExceptionC(string message) : base(message) {}
}

This is why Java needs lambdas. Because they fix everything ¬_¬

For reference, the closest I could do in Java prior to 7 was something like this:

public class MultiCatchWithoutCoin {
	public static void main(String... args) {
		new TrierII<ExceptionA, ExceptionB>() {
			public void Try() {
				throw new ExceptionA();
			}
			public void Catch(Exception ex) {
				System.out.println("Got " + ex.getClass().getSimpleName());
			}
		};
	}
}

I had to use an abstract class instead of lambdas as Java has no lambdas. I also had to create a new class for each number of type arguments I wanted because you can’t overload with variable numbers of type arguments.

I also had to use Gafter’s gadget to access the types of the Exceptions to catch.

Here’s the full code listing.

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
 
public class MultiCatchWithoutCoin {
	public static void main(String... args) {
		new TrierII<ExceptionA, ExceptionB>() {
			public void Try() {
				throw new ExceptionA();
			}
			public void Catch(Exception ex) {
				System.out.println("Got " + ex.getClass().getSimpleName());
			}
		};
	}
}
 
abstract class TrierII<T extends Exception, U extends Exception> {
	public abstract void Try();
	public abstract void Catch(Exception ex);
	public TrierII() throws T, U {
		try {
			Try();	
		} catch (Exception e) {
			if (getTypeArgument(1).isAssignableFrom(e.getClass()) || getTypeArgument(2).isAssignableFrom(e.getClass())) { 
				Catch(e);
			}
			throw e;
		} 
	}
 
	Class<? extends Exception> getTypeArgument(int num) {
		Type superclass = getClass().getGenericSuperclass();
		if (superclass instanceof Class) {
			throw new RuntimeException("Missing type parameter.");
        	}
        	Type type = ((ParameterizedType) superclass).getActualTypeArguments()[num - 1];
		if (type instanceof Class<?>) {
               		return (Class<? extends Exception>) type;
		} else {
			return (Class<? extends Exception>) ((ParameterizedType) type).getRawType();
		}
	}
 
}
 
class ExceptionA extends RuntimeException {}
class ExceptionB extends RuntimeException {}

Posted by & filed under openSUSE, webpin.

Thanks to everyone who has been sending me bug reports and suggestions for webpinstant

This evening I

Now that it has had some testing I’ll be making sure that all the remaining OBS repositories are indexed. I’ll also perform a complete re-index of all repositories to benefit from the indexing bugfixes.

Posted by & filed under openSUSE, webpin.

A few years ago I wrote a tool called webpin that allowed people to search for openSUSE packages across all openSUSE repositories, both by package names and their contents.

This was useful for finding where a package for a particular file was located. openSUSE had an awful lot of separate package repositories (There are now over 3,000 for 12.2).

 

It’s now back, and better, at http://webpinstant.com/

 

Webpinstant

I have now re-written this tool. It’s now much faster at both searching and indexing, meaning it can index a lot more and hopefully provide better results.

Sample Searches:

kde irc client

(Brings back konversation and quassel).

bzcat

(brings back bzip2 on debian)

Multiple Distributions

I have also added support for other distributions including Fedora, Debian, and Ubuntu. In fact any distribution that uses repo-md or debian style repositories can be easily added to the index.

Select Distribution

So far it has an index of repositories for:

  • openSUSE 12.1
  • openSUSE 12.2
  • Fedora 17
  • Ubuntu Quantal
  • Debian Squeeze

Let me know suggestions of more distributions you’d like to see indexed. RHEL, CENTOS, and SLES seem like obvious candidates.

Ubuntu Limitations

openSUSE build service repositories are detected automatically. I’d like to do the same for Ubuntu PPAs but haven’t yet worked out how to obtain a list of PPAs programmatically. If you have a suggestion please let me know. In the meantime please do suggest any important PPAs that it would be useful to index.

I also can’t find the Contents.gz files in Ubuntu PPAs that are available in other Debian repositories. These provide a lot more metadata for searching. Am I just failing to look well enough or are they missing from PPAs?

Search/Ranking

Some of the things indexed include:

  • Package Names
  • Summaries
  • Descriptions
  • RPM provides
  • Files within packages

Basically anything found in Primary.xml/FileLists.xml in repo-md repositories and anything found in the Packages and Contents lists in Debian repositories.

I have also put a lot of work into improving the search ranking based on cases that the original webpin performed poorly on. I suspect there will still be lots of things that are not found or not ranked highly. If you can’t find what you’re looking for with webpin then please let me know what your search terms were and if possible what you expected to appear as a result.

API and Command line app

I have added support for the old API that the command line webpin app by Pascal Bleser wrote.

You can try it out if you like. To update the tool to use the new webpin on openSUSE 12.2 you need to edit a couple of files. First add the following to distVersionMap in /usr/lib/python2.7/site-packages/webpin/const.py

'12.2': 'openSUSE_122',

Then change the server line in the same file as follows

server = 'webpinstant.com'

Future Features

Things I’d like to add other than more distros / repositories include:

* One Click Install support. Adding install links to the search results. This is something that the old webpin had.
* A better API desktop/command line clients

Feedback

Please do let me know bug reports / feature requests. In particular I’m interested in

  • What distributions should I index
  • What repositories should I index?
  • What searches result in badly ranked results
  • What future features should I prioritise?

Please let me know using email webpin at benjiweber.co.uk or find me on freenode (benjiman). or @benjiweber on twitter.

Posted by & filed under Uncategorized.

I thought I’d start posting some of my notes on tips for testing. Starting with some tips and tricks for Mockito.

Mocking/Stubbing frameworks like Mockito help to test units of code in isolation with minimal boilerplate.

A couple of guidelines I like to aim to follow when writing tests are:

  • Each test should assert/verify just one thing (or as few things as possible)
  • Minimise stubbing noise per test

Sometimes it can be hard to write consise tests for consise, readable code. It’s often tempting to compromise the simplicity of the code under test in order to make the tests easier. However, Mockito is flexible enough that this can usually be avoided.

Obviously we have to be careful. Often (perhaps even usually) code being hard to test is a smell, and it’s better to re-think how the code is written to make it more naturally testable.

Here are three things that can make tests more difficult:

  • Use of the Builder Pattern
  • Use of Real Objects (not everything is stubbed)
  • Methods that return arguments (e.g. put on caches)

Use of the Builder Pattern

Here’s the first example. We’d like to write some code like the following.

public class Example1 {
	FoxBuilder foxBuilder;
	Dog dog;
 
	public void someMethod() {
		Fox fox = foxBuilder
			.speed(QUICK)
			.colour(BROWN)
			.legs(4)
			.longTail()
			.gender(MALE)
			.build();
 
		fox.jumpOver(dog);
	}
}

If you have a basic familiarity with Mockito you might be tempted to write a test like the following. Unfortunately here

  • The stubbing is very verbose (and could be worse in a less trivial example)
  • We are testing several things in a single test, so lots of different things could break it
@RunWith(MockitoJUnitRunner.class)
public class Example1NaiveTest {
	@Mock FoxBuilder foxBuilder;
	@Mock Fox fox;
	@Mock Dog dog;
 
	@InjectMocks
	Example1 example = new Example1();
 
	@Test public void naiveTest() {
		when(foxBuilder.speed(QUICK)).thenReturn(foxBuilder);	
		when(foxBuilder.colour(BROWN)).thenReturn(foxBuilder);
		when(foxBuilder.legs(4)).thenReturn(foxBuilder);
		when(foxBuilder.longTail()).thenReturn(foxBuilder);
		when(foxBuilder.gender(MALE)).thenReturn(foxBuilder);
		when(foxBuilder.build()).thenReturn(fox);
 
		example.someMethod();
 
		verify(fox).jumpOver(dog);
	}
}

Omitting one of the when() stubbings from the above test will result in a NullPointerException.

Fortunately Mockito has a solution. When a method invocation on a mock has not been stubbed in the test, Mockito will fall back to the “default answer”. We can also specify what the default answer will be. So let’s create a default answer suitable for builders.

Here we create an Answer to make Mocks return themselves from any method invocation on them that has a compatible return type.

public class Return {
	public static Answer<?> Self = new Answer<Object>() {
		public Object answer(InvocationOnMock invocation) throws Throwable {
			if (invocation.getMethod().getReturnType().isAssignableFrom(invocation.getMock().getClass())) {
				return invocation.getMock();
			}
 
			return null;
		}
	};
}

Now our test can look like this. We only have to stub out the build invocation. Notice the instantiations of the Mocks now tell Mockito to use our new default Answer.

@RunWith(MockitoJUnitRunner.class)
public class Example1Test {
	FoxBuilder foxBuilder = mock(FoxBuilder.class, Return.Self);
	FoxBuilder quickFoxBuilder = mock(FoxBuilder.class, Return.Self);
 
	@Mock Fox fox;
	@Mock Dog dog;
 
	@InjectMocks
	Example1 example = new Example1();
 
	@Test public void whenSomeMethodCalled_aFox_shouldJumpOverTheLazyDog() {
		when(foxBuilder.build()).thenReturn(fox);
		example.someMethod();
		verify(fox).jumpOver(dog);
	}
}

“Ah”, you might say. “Now we’re no longer checking we build a fox of the right type”. Well, if that’s important to us we can put it in another test. That way we stick to one test per item of behaviour we want to assert.

We can assert that the speed method on the builder is called

@Test public void whenSomeMethodCalled_shouldCreateQuickFox() {
	when(foxBuilder.build()).thenReturn(fox);
	example.someMethod();
	verify(foxBuilder).speed(QUICK);
}

Or, to more properly check that the dog is jumped over by a fox-that-is-quick we could utilise two builders to represent a state transition:

@Test public void whenSomeMethodCalled_shouldJumpOverAFoxThatIsQuick() {
	when(foxBuilder.speed(QUICK)).thenReturn(quickFoxBuilder);
	when(quickFoxBuilder.build()).thenReturn(fox);
	example.someMethod();
	verify(fox).jumpOver(dog);
}

 

Real Objects

Now, suppose we decided that the dog should be instantiated within the method instead of a field on Example. Making it hard to test.

Here is the code we want to write

public class Example2 {
	FoxBuilder foxBuilder;
 
	public void someMethod() {
		Fox fox = foxBuilder
			.speed(QUICK)
			.colour(BROWN)
			.legs(4)
			.longTail()
			.gender(MALE)
			.build();
 
		Dog dog = new Dog();
 
		dog.setLazy();
 
		fox.jumpOver(dog);
	}
}

We could create a dogFactory and stub out the creation of the dog. However, this adds complexity and changes the implementation for the test.
We could use powermock to mock the Dog’s constructor.
However, there can be valid reasons not to mock objects like this. For example it’s good to avoid mocking Value Objects.

So, how can we test it with a real object? Use a Mockito utility called an ArgumentCaptor

Here we capture the real Dog object passed to the Fox mock, and can perform assertions on it afterwards.

@Test public void whenSomeMethodCalled_aRealFox_shouldJumpOverTheLazyDog() {
	when(foxBuilder.build()).thenReturn(fox);
	example.someMethod();
 
	ArgumentCaptor dogCaptor = ArgumentCaptor.forClass(Dog.class);
	verify(fox).jumpOver(dogCaptor.capture());
	assertTrue(dogCaptor.getValue().isLazy());		
}

Methods that Return Arguments

 

Now let’s make it harder again. Suppose the real dog passes through another object such as a cache that we’d like to stub.

public class Example3 {
	FoxBuilder foxBuilder;
	Cache cache;
 
	public void someMethod() {
		Fox fox = foxBuilder
			.speed(QUICK)
			.colour(BROWN)
			.legs(4)
			.longTail()
			.gender(MALE)
			.build();
 
		Dog dog = new Dog();
		dog.setLazy();
 
		dog = cache.put(dog);
 
		fox.jumpOver(dog);
	}
}

These presents some challenges to test if we have stubbed the cache. One approach would be to test both the dog being lazy and the cache-addition in the same test, re-using the ArgumentCaptor used above.

This is undesirable because there are two things being asserted in a single test.

@RunWith(MockitoJUnitRunner.class)
public class Example3Test {
	FoxBuilder foxBuilder = mock(FoxBuilder.class, Return.Self);
	FoxBuilder quickFoxBuilder = mock(FoxBuilder.class, Return.Self);
 
	@Mock
	Cache mockCache;
	@Mock
	Fox fox;
	@Mock 
	Dog dog;
 
	@InjectMocks
	Example3 example = new Example3();
 
	@Test public void bad_whenSomeMethodCalled_aRealFox_shouldJumpOverTheLazyDog() {
		when(foxBuilder.build()).thenReturn(fox);
		when(mockCache.put(any(Dog.class))).thenReturn(dog);
 
		example.someMethod();
 
		ArgumentCaptor dogCaptor = ArgumentCaptor.forClass(Dog.class);
		verify(mockCache).put(dogCaptor.capture());
		assertTrue(dogCaptor.getValue().isLazy());
 
		verify(fox).jumpOver(dog);
	}
}

The trick is to use a Mockito Answer again to create a custom stubbing rule. Here we define an Answer that will return an argument passed to the mock method invocation.

public static <T> Answer<T> argument(final int num) {
	return new Answer<T>() {
		@SuppressWarnings("unchecked")
		public T answer(InvocationOnMock invocation) throws Throwable {
			return (T) invocation.getArguments()[num - 1];
		}
	};
}

Using this, the test is only one line longer than it was before adding the cache. We could even move the cache stubbing (2nd line of test) to an @Before section to further declutter the test (as it’s generic cache behaviour)

@Test public void whenSomeMethodCalled_aRealFox_shouldJumpOverTheLazyDog() {
	when(foxBuilder.build()).thenReturn(fox);
	when(mockCache.put(any())).thenAnswer(argument(1));
 
	example.someMethod();
	ArgumentCaptor dogCaptor = ArgumentCaptor.forClass(Dog.class);
 
	verify(fox).jumpOver(dogCaptor.capture());
	assertTrue(dogCaptor.getValue().isLazy());
}

If we actually want to assert the caching happens we can write another test. This test is consise and if it fails we will know why.

If we cared about the specific properties of the dog being cached we could add the ArgumentCaptor back in.

@Test public void whenSomeMethodCalled_aFoxShouldBeCached() {
	when(foxBuilder.build()).thenReturn(fox);
	example.someMethod();
	verify(mockCache).put(any(Dog.class));
}

The examples used in this post are on github

There are lots of other things you can use Mockito Answers for. Take a look at the Answers enum for some of the default answers provided. RETURN_DEEP_STUBS can be useful, particularly for testing legacy code.

Posted by & filed under Java.

Jammer is a quick 1hr project that clones IRC discussion on Yammer.

Yammer is a social network for internal use by organisations. It’s a great way to broadcast information and have asynchronous discussion, and simple enough for anyone to use.

Developers already have a great forum for asynchronous discussion – IRC. IRC is great for developers to use, but most irc client software is not particularly user friendly. Unless you idle in the channel all the time you will miss scrollback.

I haven’t used Yammer for some time so I thought I’d remind myself how to use the API by building a bridge between IRC and Yammer. Here’s the result of just over an hour’s work:

Jammer is a quick proof of concept IRC bot that will sit in an IRC channel and clone messages from authorised users to a specified group in Yammer. It lets you keep a record and publish discussion for others in the organisation to see.

The code is on github at https://github.com/benjiman/jammer

It might be useful to someone else as a tutorial for getting started with the Yammer API and how to authenticate with oauth. There are only 3 short Java files.

Jammer

Here’s how you run Jammer:

 $ git clone https://github.com/benjiman/jammer.github
 $ cd jammer
 $ mvn compile
 $ mvn assembly:single
 $ java -jar ./target/jammer-0.0.1-SNAPSHOT-jar-with-dependencies.jar <irc server (in quotes)> <channel> <yammer group id> <yammer client id> <yammer client secret>

Then in your IRC client:

 /msg jammer auth

Click the link provided, approve the app, and copy the authentication token back with

 /msg jammer auth <token>

Now simply join the channel the bot is in and start talking and all messages will be cross-posted to Yammer.

You can get a client id and client secret in Yammer by registering a new application.

You can get a group id by visiting the group on Yammer.com and copying the id at the end of the URL

For more information read

The Yammer API documentation
There’s a tutorial for PircBot (Easily write IRC bots in Java)

Posted by & filed under Java.

Hibernate is great, but often one has to specify queries as HQL in Strings, or as criteria which allow building of invalid queries.

It would be great to use the java type system to help enforce correct queries. I am aware of some tools to do this, but all the ones I have seen require either a code generation step, or preclude the use of standard getters/setters.

Here is a proof of concept of one approach that I think could work. It allows things like:

    public List<Person> getPeopleByName(final String firstName, final String lastName) {
        return new Query<Person>() {
            public CompletedQuery spec(Person person) { // <- Only Person can be passed to here.
                return where(person.getFirstname())
                    .equalTo(firstName) // <- Only comparisons are valid at this step, a .and(... would be a compilefailure.
                    .and(person.getLastname())
                    .equalTo(lastName)
                    .select(); // <- Omitting this would be a compile failure due to return type.
            }
        }.list(HibernateUtil.getSessionFactory().getCurrentSession()); // <- Method returns a List<Person>
    }

A toString on the above Query<Person> when passed firstname benji and lastname weber would yield:

FROM Person WHERE firstname = 'benji' AND lastname = 'weber'

If we were to try to supply a non-string value for first name we would get a compile failure.

    public List<Person> getPeopleByName(final String firstName, final String lastName) {
        return new Query<Person>() {
            public CompletedQuery spec(Person person) {
                return where(person.getFirstname())
                    .equalTo(firstName)
                    .and(person.getLastname())
                    .equalTo(5) // <- Compile failure
                    .select();
            }
        }.list(HibernateUtil.getSessionFactory().getCurrentSession());
    }

This approach can even work querying through relationships

    public List<Person> getPeopleByAddress(final Address address) {
        return new Query<Person>() {
            public CompletedQuery spec(Person person) {
                return where(person.getAddress().getId())
                    .equalTo(address.getId()) // < - Only Integers are allowed here.
                    .select();
            }
        }.list(HibernateUtil.getSessionFactory().getCurrentSession());
    }

A toString on the above Query<Person> when passed an Address with id 2 would yield:

FROM Person WHERE address.id = 2

To implement this I used a few tricks:

  • Query<T> is an abstract class that uses Gafter’s Gadget to obtain a Class<T> this is used to get the entity name that we are querying, and later to create an instance.
  • A Dynamic Proxy class is created for this Class and passed to the spec(T value) method.
  • This dynamic proxy records all calls made to it. If the call is to a method that returns another mockable object (e.g. getAddress() in the above example) then another recording-proxy is returned.
  • The query builder then uses the recorded method calls to determine which properties are being queried
  • The need to return a CompletedQuery interface forces the implementor to type a complete query or they will get a compile failure.
  • Interfaces represent the valid progressions at each step of the query building. e.g. after a where() you need to supply a comparison equalTo(), or like() etc. After a comparison you can complete the query or add another restriction with and();

Here is the example implementation of Query that enables this. Full demo code here

package uk.co.benjiweber.typesafehibernate.typesafe;
 
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.hibernate.Session;
import org.springframework.util.StringUtils;
 
public abstract class Query<T> {
 
    private final Type type;
    private final Recorder<T> recorder;
    private final StringBuilder queryBuilder = new StringBuilder();
 
    public Query() {
        Type superclass = getClass().getGenericSuperclass();
        this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0];
        this.queryBuilder.append("FROM " + getParamClass().getSimpleName());
        recorder = createMockInstance();
        spec(recorder.getObject());
    }
 
    public abstract CompletedQuery spec(T entity);
 
    public interface CompletedQuery {
    }
 
    public <U> Comparison<U> where(U ignore) {
        queryBuilder.append(" WHERE ");
        return comparison(ignore);
    }
 
    private <U> Comparison<U> comparison(U ignore) {
        return new Comparison<U>()  {
 
            public QueryOptions equalTo(U value) {
                return comparison(value, "=");
            }
 
            public QueryOptions notEqualTo(U value) {
                return comparison(value, "!=");
            }
 
            public QueryOptions like(U value) {
                return comparison(value, "LIKE");
            }
 
            private QueryOptions comparison(U value, String operator) {
                boolean quote = value != null && String.class.equals(value.getClass());
 
                queryBuilder.append(recorder.getCurrentPropertyName()).append(" ").append(operator).append(" ").append(quote ? "'" : "").append(value).append(quote ? "'" : "");
                return new AbstractQueryOptions()  {
 
                    public <V> Comparison<V> and(V o) {
                        return Query.this.and(o);
                    }
                };
            }
        };
    }
 
    private <U> Comparison<U> and(U ignore) {
        queryBuilder.append(" AND ");
        return comparison(ignore);
    }
 
    public interface Comparison<U> {
 
        QueryOptions equalTo(U value);
 
        QueryOptions notEqualTo(U value);
 
        QueryOptions like(U value);
    }
 
    abstract static class AbstractQueryOptions implements QueryOptions {
 
        public CompletedQuery select() {
            return new CompletedQuery()  {
            };
        }
    }
 
    public interface QueryOptions {
 
        <V> Comparison<V> and(V o);
 
        CompletedQuery select();
    }
 
    private Recorder<T> createMockInstance() {
        Class<T> cls = getParamClass();
 
        return RecordingObject.create(cls);
    }
 
    private Class<T> getParamClass() {
        return type instanceof Class<?>
                ? (Class<T>) type
                : (Class<T>) ((ParameterizedType) type).getRawType();
 
    }
 
    @Override
    public String toString() {
        return queryBuilder.toString();
    }
 
    public List<T> list(Session session) {
        return session.createQuery(toString()).list();
    }
}
 
class Recorder<T> {
 
    private T t;
    private RecordingObject recorder;
 
    public Recorder(T t, RecordingObject recorder) {
        this.t = t;
        this.recorder = recorder;
    }
 
    public String getCurrentPropertyName() {
        return recorder.getCurrentPropertyName();
    }
 
    public T getObject() {
        return t;
    }
}
 
class RecordingObject implements MethodInterceptor {
 
    private String currentPropertyName = "";
    private Recorder<?> currentMock = null;
 
    @SuppressWarnings("unchecked")
    public static <T> Recorder<T> create(Class<T> cls) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(cls);
        final RecordingObject recordingObject = new RecordingObject();
 
        enhancer.setCallback(recordingObject);
        return new Recorder((T) enhancer.create(), recordingObject);
    }
 
    public Object intercept(Object o, Method method, Object[] os, MethodProxy mp) throws Throwable {
        if (method.getName().equals("getCurrentPropertyName")) {
            return getCurrentPropertyName();
        }
        currentPropertyName = StringUtils.uncapitalize(method.getName().replaceAll("^get", ""));
        try {
            currentMock = create(method.getReturnType()); //method.invoke(o, os);
            return currentMock.getObject();
        } catch (IllegalArgumentException e) {
            //non-mockable
            return null;
        }
    }
 
    public String getCurrentPropertyName() {
        return currentPropertyName + (currentMock == null ? "" : ("." + currentMock.getCurrentPropertyName()));
    }
}

Posted by & filed under Java, Uncategorized.

One annoyance in Java is having to do instanceof checks on multiple lines. e.g.

if (object instanceof Foo) {
    Foo foo = (Foo)object;
    foo.foo();
}

While this is often a sign of a design failure, there are times when instanceof checks are required often due to framework constraints etc. The above is quite ugly and involves using 3 lines instead of 1 for a single method call. If foo() is a void method we can’t even use the ternary ? : operator to make it more concise.

In c# with Lambdas and Extension methods one can create something like :

    object.When<Foo>(foo => foo.Foo());

Where “When” is an extension method added to all objects which takes a type parameter and a lambda to execute if the type parameter matches. (Implementation available if anyone cares).

Since Java doesn’t have Extension methods or Lambdas yet (Oracle minus minus) we can’t do this. We can however always use reflection and get something like:

package scratchpad;
 
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
 
import static scratchpad.When.when;
 
public class Let {
	public static void main(String... args) {
		Object a = new Foo();
		Object b = "hello world";
 
		when(Foo.class).isTypeOf(a).foo(); // Prints "foo"
		when(Foo.class).isTypeOf(b).foo(); // Does nothing at all
	}
}
 
class Foo {
	public void foo() {
		System.out.println("foo");
	}
}
 
class When {
	public static <T> Is<T> when(final Class<T> cls) {
		return new Is<T>() {
			@SuppressWarnings("unchecked")
			public T isTypeOf(Object o) {
				return o != null && cls.isAssignableFrom(o.getClass()) 
					? (T)o
					: NullObject.create(cls);
			}
 
		};
	}
 
	public interface Is<T> {
		public T isTypeOf(Object o);
	}
}
 
class NullObject implements MethodInterceptor  {
 
	@SuppressWarnings("unchecked")
	public static <T> T create(Class<T> cls){
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(cls);
		enhancer.setCallback(new NullObject());
		return (T)enhancer.create();
	}
 
	public Object intercept(Object o, Method method, Object[] os, MethodProxy mp) throws Throwable {
		return null;
	}
}

Posted by & filed under Uncategorized.

I meant to post some time ago about how great the n900 is for java development. Not only can one install OpenJDK, but Netbeans is even usable. It’s pretty easy to get running. Just install openjdk6 in the application manager. Then download and run the netbeans installer.

installation

running

It even runs at quite a reasonable speed if you’re not running much else.