At the moment, generic factories are far too generic - for most of the problems, an optimization can be found so that the amount of reasonable moves is significantly reduced. The intention is to allow customization of the generic move factories, while still using all their power. Generic move factory simply produces every possible move and the user defines, in a MoveFilter, which of them shouldn't be passed to the planner. The feature could work like this:
1. An interface is introduced, called eg. MoveFilter<T extends Move>. This interface declares one method - boolean filter(Solution solution, T move). This method accepts the solution of the MoveFactory, as well as the Move object that's been created by the MoveFactory. It returns true if the GenericMove should be included in the createMoveList() method of the MoveFactory, false otherwise.
(Please make sure that the MoveFilter type is generic, so that filter() always knows the correct type of the move without the user doing any magic or assumptions. This would most probably require making MoveFactory generic as well, but that could be useful.)
2. Implementations of the MoveFilter interface are annotated with @MoveFilter(factory = [SomeMoveFactory.class, SomeOtherMoveFactory.class]). This annotation would specify to which move factory this filter should be related. Some checks should be put in place that the annotation will only work when the MoveFilter and MoveFactory share the same Move type.
3. The same as in (2) can be achieved by specifying filters in the XML configuration of the solver, altough I personally don't like the XML configs much.
4. MoveFactory's createMoveList() method is enhanced so that it runs user-specified MoveFilters and excludes the filtered moves from the resulting MoveList.