0

I am currently doing a small workflow engine for a personal project with generic parameter.

This is not elaborate, the aim is to do something with generics.

The WorkflowExecutor is the class which will execute all step of my workflow

public class WorkflowExecutor<U extends WorkflowCommand<T>, T extends WorkflowArgumentWrapper> {
    List<U> commands = new ArrayList<U>();

    public WorkflowExecutor<U, T> addCommand(U command) {
        commands.add(command);
        return this;
    }

    public void execute(T arg) {
        for(int i = 0; i < commands.size(); i++) {
            arg = commands.get(i).perform(arg);
        }
    }
}

The WorkflowCommand class is a step of my workflow :

public abstract class WorkflowCommand<T extends WorkflowArgumentWrapper> {
    public abstract T perform(T arg);
}

The WorkflowArgumentWrapper is the class which is pass to all step of a workflow. So basically this object will be modified by a workflow step and pass to the following step.

public class WorkflowArgumentWrappable {
}

And finally a container of workflow (supposed to be a singleton in the future). It contains all my workflow and I can execute them from there :

public class WorkflowContainer {

    private Map<WorkflowType , WorkflowExecutor<? extends WorkflowCommand<? extends WorkflowArgumentWrapper>,? extends WorkflowArgumentWrapper>> executors =
            new HashMap<WorkflowType , WorkflowExecutor<? extends WorkflowCommand<? extends WorkflowArgumentWrapper>, ? extends WorkflowArgumentWrapper>>();

    public static enum WorkflowType {
        TEST
    }

    public void init() {
        executors.put(WorkflowType.TEST, new WorkflowExecutor<WorkflowHelloWorldCmd, WorkflowHelloWorldArgument>())
            .addCommand(new WorkflowHelloWorldCmd())  // PROBLEM HERE
            .addCommand(new WorkflowHelloWorldCmd()); // PROBLEM HERE
    }

    public void execute(WorkflowType type, WorkflowArgumentWrapper arg) {
        executors.get(type).execute(arg); // PROBLEM HERE
    }
}

With :

public class WorkflowHelloWorldCmd extends WorkflowCommand<WorkflowHelloWorldArgument> {
    @Override
    public WorkflowHelloWorldArgument perform(WorkflowHelloWorldArgument arg) {
        System.out.println(arg.getCount() + " : " + arg.getSentence());
        arg.setCount(arg.getCount() + 1);
        return arg;
    }
}

public class WorkflowHelloWorldArgument implements WorkflowArgumentWrapper {
    private String sentence;
    private int count;

    public WorkflowHelloWorldArgument()  {
        this.sentence = "Hello world";
        this.count = 0;
    }

    public String getSentence() {
        return sentence;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public int getCount() {
        return count;
    }
}

I have a problem when I add my command to my executor : 'addCommand(capture<? extends tbetous.workflow.WorkflowCommand<? extends tbetous.workflow.WorkflowArgumentWrapper>>)' in 'tbetous.workflow.WorkflowExecutor' cannot be applied to '(tbetous.test.WorkflowHelloWorldCmd)'

And I have a problem with executors.get(type).execute(arg); because 'execute(capture<? extends workflow.WorkflowArgumentWrapper>)' in 'workflow.WorkflowExecutor' cannot be applied to '(workflow.WorkflowArgumentWrapper)'

I completely stuck with this. Is there a way to do what I want ? Thank you for your help in advance.

Thomas Betous
  • 4,633
  • 2
  • 24
  • 45
  • This is the usual problem with wildcards (hence the duplicate). It probably means that you don't actually want/need wildcards in this situation. – Oliver Charlesworth Mar 13 '16 at 18:12
  • @OliverCharlesworth, thanks for your help, but the post with the possible duplication does not help me. If I let just WorkflowExecutor with no wildcare, then I have warnings. I am not sure it's good not to type my executor. Do you have an advice for me ? – Thomas Betous Mar 13 '16 at 19:10
  • There is too much code here for me to reason about it (especially because I don't know what the intended behaviour is). But basically, you cannot invoke a method `Foo.bar(U stuff)` if `U == ?`. The fact that you want to do that means that your class should *probably* be parameterised as `WorkflowArgumentWrapper`, not `? extends WorkflowArgumentWrapper`. – Oliver Charlesworth Mar 13 '16 at 19:15

0 Answers0