[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: [ice-dev] [triquetrum-dev] ice-triquetrum fork
|
Hi Jay, ICE team,
I'm trying to implement a "2-step"-form on an ICE Item, as explained
below. I.e. :
1. the user should get a list of available workflows (the list is
now mocked with 2 painfully simple in-memory constructed model
instances)
2. the user picks one model and then
3. the Item form should be replaced/extended with a form that shows
dynamically generated workflow configuration entries
(based on the parameters that the workflow has defined in its model)
4. the user can optionally change parameter values and then launch
the workflow
So I'm trying to add a datacomponent with on-the-fly generation of a
variable set of form entries after giving the user the opportunity
to pick a workflow.
But I can not get this working, although I think I'm close...
It seems the form and the included datacomponents of an item must be
created in setupForm() that is already invoked during the base-class
constructor invocation?
And that it should be possible to add entries to one of those
datacomponents dynamically later on?
I've tried that, cfr attached source. Is someone able to review
that?
I also hit an NPE, e.g. when trying to save the form after selecting
a workflow or when clicking Go! for an incomplete form and then
returning a FormStatus.NeedsInfo from inside process().
It seems the Item base class has an action property that is null. Do
I need to set that one at some point? I could not see that being
done in those examples though...
E.g. when saving :

!ENTRY org.eclipse.ui 2 0 2016-02-25 22:13:38.071
!MESSAGE Save Failed
!STACK 0
java.lang.NullPointerException
at org.eclipse.ice.item.Item.getForm(Item.java:795)
at
org.eclipse.ice.core.internal.itemmanager.ItemManager.retrieveItem(ItemManager.java:315)
at org.eclipse.ice.core.internal.Core.getItem(Core.java:448)
at
org.eclipse.ice.client.internal.Client.formUpdated(Client.java:607)
at
org.eclipse.ice.client.widgets.ICEFormEditor.notifyUpdateListeners(ICEFormEditor.java:1069)
at
org.eclipse.ice.client.widgets.ICEFormEditor.doSave(ICEFormEditor.java:710)
at
org.eclipse.ui.internal.SaveableHelper$2.run(SaveableHelper.java:156)
at
org.eclipse.ui.internal.SaveableHelper$5.run(SaveableHelper.java:285)
at
org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:463)
at
org.eclipse.jface.operation.ModalContext.run(ModalContext.java:371)
at
org.eclipse.ui.internal.WorkbenchWindow$14.run(WorkbenchWindow.java:2156)
at
org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
at
org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow.java:2152)
at
org.eclipse.ui.internal.SaveableHelper.runProgressMonitorOperation(SaveableHelper.java:293)
at
org.eclipse.ui.internal.SaveableHelper.runProgressMonitorOperation(SaveableHelper.java:271)
at
org.eclipse.ui.internal.SaveableHelper.savePart(SaveableHelper.java:161)
at
org.eclipse.ui.internal.WorkbenchPage.saveSaveable(WorkbenchPage.java:3874)
at
org.eclipse.ui.internal.WorkbenchPage.saveEditor(WorkbenchPage.java:3888)
And when trying to Go! :
Exception in thread "Thread-73" java.lang.NullPointerException
at org.eclipse.ice.item.Item.getForm(Item.java:795)
at
org.eclipse.ice.core.internal.itemmanager.ItemManager.retrieveItem(ItemManager.java:315)
at org.eclipse.ice.core.internal.Core.getItem(Core.java:448)
at
org.eclipse.ice.client.internal.ItemProcessor.run(ItemProcessor.java:473)
at java.lang.Thread.run(Thread.java:745)
regards
erwin
Op 25/02/2016 om 18:26 schreef Jay Jay
Billings:
Ah. I see. There are several ways you could do
that. One way is to use our MasterDetailsComponent, but that can
be pretty complicated to get working. It would give you a really
nice Master-Details pair view of the list of workflows and the
parameters.
Personally, I would just keep it simple. You can create a
second DataComponent in setupForm() that shows the parameters
for the workflow. Leave it empty or fill it with common,
default values to start. Then, override reviewEntries() and
once they pick the workflow and hit 'Save' you can just
add/overwrite entries in the second DataComponent. This is
what we do most of the time for problems like this and it is
very scalable.
Nek5000 is a good example of this, which you can see if you
check out org.eclipse.ice.nek5000.Nek5000Model.java:250. In
this case, users pick which example problem they want to run
in a data component on the left, and the remaining data
components (of which there are 5-10) are repopulated based on
that choice.
Jay
_______________________________________________
triquetrum-dev mailing list
triquetrum-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/triquetrum-dev
|
package org.eclipse.ice.triquetrum.model;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.core.resources.IProject;
import org.eclipse.ice.datastructures.entry.DiscreteEntry;
import org.eclipse.ice.datastructures.entry.IEntry;
import org.eclipse.ice.datastructures.entry.StringEntry;
import org.eclipse.ice.datastructures.form.DataComponent;
import org.eclipse.ice.datastructures.form.Form;
import org.eclipse.ice.datastructures.form.FormStatus;
import org.eclipse.ice.item.model.Model;
import org.eclipse.ice.triquetrum.WorkflowServiceTracker;
import org.eclipse.triquetrum.workflow.ModelHandle;
import org.eclipse.triquetrum.workflow.WorkflowExecutionService;
import org.eclipse.triquetrum.workflow.WorkflowExecutionService.StartMode;
import ptolemy.actor.CompositeActor;
import ptolemy.actor.TypedCompositeActor;
import ptolemy.actor.lib.Const;
import ptolemy.actor.lib.gui.Display;
import ptolemy.data.expr.Parameter;
import ptolemy.data.expr.StringParameter;
import ptolemy.domains.sdf.kernel.SDFDirector;
@XmlRootElement(name = "TriquetrumWorkflowItemModel")
public class TriquetrumWorkflowItemModel extends Model {
private static final String AVAILABLE_WORKFLOWS = "Available workflows";
private Map<String, CompositeActor> models;
private DiscreteEntry workflowSelectionEntry;
private DataComponent workflowCfgComp;
private boolean workflowSelected = false;
public TriquetrumWorkflowItemModel() {
this(null);
}
public TriquetrumWorkflowItemModel(IProject project) {
// Setup the form and everything
super(project);
}
@Override
public void setupForm() {
if (form == null) {
allowedActions = new ArrayList<String>();
allowedActions.add("Launch the Workflow");
form = new Form();
form.setActionList(allowedActions);
models = new HashMap<>();
try {
models.put("hello", buildTrivialCompositeActor("hello"));
models.put("goodbye", buildTrivialCompositeActor("goodbye"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// Create a data component for the workflow selection
DataComponent workflowSelectionComp = new DataComponent();
// not sure what this ID is for? I can not seem to find getters by ID on
// the form or other ways in which the ID is used?
workflowSelectionComp.setId(1);
workflowSelectionComp.setName("Triquetrum Info");
workflowSelectionComp.setDescription("Select a Triquetrum workflow from the list");
workflowSelectionEntry = new DiscreteEntry();
workflowSelectionEntry.setName(AVAILABLE_WORKFLOWS);
workflowSelectionEntry.setAllowedValues(new ArrayList<String>(models.keySet()));
workflowSelectionComp.addEntry(workflowSelectionEntry);
form.addComponent(workflowSelectionComp);
// Create a data component for configuring a selected workflow
workflowCfgComp = new DataComponent();
workflowCfgComp.setId(2);
workflowCfgComp.setDescription("Configure the selected workflow");
form.addComponent(workflowCfgComp);
return;
}
@Override
public void setupFormWithServices() {
// TODO use workflow repository service here?
super.setupFormWithServices();
}
@Override
protected void setupItemInfo() {
setName("Triquetrum workflow Model");
setDescription("An item to launch a Triquetrum workflow");
}
@Override
protected FormStatus reviewEntries(Form preparedForm) {
String selectedWorkflowName = workflowSelectionEntry.getValue();
if (selectedWorkflowName == null) {
return FormStatus.NeedsInfo;
} else if (!workflowSelected) {
CompositeActor selectedWorkflow = models.get(selectedWorkflowName);
// Create a data component for configuring a selected workflow
// workflowCfgComp = new DataComponent();
// workflowCfgComp.setId(2);
// workflowCfgComp.setDescription("Configure the selected workflow");
// form.addComponent(workflowCfgComp);
for (Parameter p : selectedWorkflow.attributeList(Parameter.class)) {
StringEntry newEntry = new StringEntry();
newEntry.setName(p.getName());
newEntry.setDefaultValue(p.getExpression());
workflowCfgComp.addEntry(newEntry);
}
workflowSelected = true;
return FormStatus.NeedsInfo;
} else {
// the workflow parameterization is optional, so we just check that the cfg panel was shown at least.
// and if so, we're ready to process!
return FormStatus.ReadyToProcess;
}
}
@Override
public FormStatus process(String actionName) {
// Not sure if this might break something in ICE,
// but I'd like to make sure that review is always done,
// also when the user did not save the form.
// Using getForm generates an NPE here, so let's try with using form directly.
FormStatus processStatus = reviewEntries(form);
if (FormStatus.ReadyToProcess.equals(processStatus)) {
String selectedWorkflowName = workflowSelectionEntry.getValue();
CompositeActor selectedWorkflow = models.get(selectedWorkflowName);
try {
WorkflowExecutionService workflowExecutionService = WorkflowServiceTracker.getWorkflowExecutionService();
if (workflowExecutionService != null) {
workflowExecutionService.start(StartMode.RUN, selectedWorkflow, null, getParameterOverrides(), null);
} else {
// figure out how to return error msgs to ICE
// seems there's no FormStatus.ProcessError or so...
System.err.println("No active WorkflowExecutionService found...");
}
status = FormStatus.Processed;
} catch (Exception e) {
e.printStackTrace();
status = FormStatus.Processed;
}
} else {
status = processStatus;
}
return status;
}
@Override
public void loadInput(String name) {
// Implement this if you want to enable imports for this Item
// TODO: Add User Code Here
}
private Map<String, String> getParameterOverrides() {
Map<String,String> parameterOverrides = new HashMap<>();
for(IEntry entry : workflowCfgComp.retrieveAllEntries()) {
if(entry.isModified()) {
parameterOverrides.put(entry.getName(), entry.getValue());
}
}
return parameterOverrides;
}
private CompositeActor buildTrivialCompositeActor(String wfName) throws Exception {
CompositeActor compositeActor = new TypedCompositeActor();
compositeActor.setName(wfName);
compositeActor.setDirector(new SDFDirector(compositeActor, "director"));
new StringParameter(compositeActor, "msg").setExpression(wfName);
;
Const source = new Const(compositeActor, "const");
Display sink = new Display(compositeActor, "sink");
compositeActor.connect(source.output, sink.input);
return compositeActor;
}
}