88import org .knime .core .data .DataCell ;
99import org .knime .core .data .DataRow ;
1010import org .knime .core .data .DataType ;
11+ import org .knime .core .data .filestore .FileStore ;
1112import org .knime .core .node .ExecutionContext ;
1213import org .knime .core .node .NodeLogger ;
1314import org .knime .scijava .commands .CellOutput ;
3031 *
3132 * @author Christian Dietz, University of Konstanz
3233 */
33- class DefaultNodeModule implements NodeModule {
34+ abstract class AbstractNodeModule implements NodeModule {
3435
3536 @ Parameter
3637 private PluginService ps ;
3738
3839 @ Parameter
39- private KNIMEConverterService cs ;
40+ private KNIMEConverterService convertService ;
4041
4142 @ Parameter
4243 private ModuleService ms ;
4344
44- // Internally used variables
45- private final Module module ;
46-
4745 private final Map <Integer , ModuleItem <?>> inputMapping ;
48-
4946 private final Map <ModuleItem <?>, DataType > outputMapping ;
5047
48+ private final ModuleInfo moduleInfo ;
49+ private final Module module ;
50+
5151 private NodeModuleOutputChangedListener outputListener ;
5252
5353 private final LogService logService ;
@@ -68,7 +68,7 @@ class DefaultNodeModule implements NodeModule {
6868 * @param logger
6969 * NodeLogger to delegate output to.
7070 */
71- public DefaultNodeModule (final Context context , final ModuleInfo info ,
71+ public AbstractNodeModule (final Context context , final ModuleInfo info ,
7272 final Map <String , Object > params ,
7373 final Map <Integer , ModuleItem <?>> inputMapping ,
7474 final Map <ModuleItem <?>, DataType > outputMapping ,
@@ -77,8 +77,9 @@ public DefaultNodeModule(final Context context, final ModuleInfo info,
7777
7878 this .inputMapping = inputMapping ;
7979 this .outputMapping = outputMapping ;
80+ this .moduleInfo = info ;
8081 this .module = ms .createModule (info );
81- this .outputListener = new NodeModuleOutputChangedListener (false );
82+ this .outputListener = new NodeModuleOutputChangedListener (true );
8283 this .logService = new KNIMELogService (logger );
8384
8485 preProcess (params );
@@ -96,7 +97,6 @@ private void preProcess(final Map<String, Object> params) {
9697 module .resolveInput (entry .getKey ());
9798 }
9899
99- // FIXME: do we need them all?
100100 final List <PreprocessorPlugin > pre = ps
101101 .createInstancesOfType (PreprocessorPlugin .class );
102102
@@ -109,7 +109,7 @@ private void preProcess(final Map<String, Object> params) {
109109 /* MultiOutputListener */
110110 final String name = item .getName ();
111111
112- outputListener = new NodeModuleOutputChangedListener (true );
112+ outputListener = new NodeModuleOutputChangedListener (false );
113113 module .setInput (name , outputListener );
114114 module .resolveInput (name );
115115 } else if (LogService .class .equals (item .getType ())) {
@@ -125,12 +125,12 @@ private void preProcess(final Map<String, Object> params) {
125125 /*
126126 * Set module input values from the input row.
127127 */
128- private void setModuleInput (final DataRow input ) throws Exception {
128+ protected void setModuleInput (final DataRow input ) throws Exception {
129129 // input can be null if source node
130130 if (input != null ) {
131131 for (final Entry <Integer , ModuleItem <?>> entry : inputMapping
132132 .entrySet ()) {
133- final Object obj = cs .convertToJava (
133+ final Object obj = convertService .convertToJava (
134134 input .getCell (entry .getKey ()),
135135 entry .getValue ().getType ());
136136 module .setInput (entry .getValue ().getName (), obj );
@@ -151,42 +151,76 @@ public void run(final DataRow input, final CellOutput output,
151151 outputListener .flush ();
152152 }
153153
154+ /**
155+ * Create cells for the currently set output {@link ModuleItem}s of the
156+ * module.
157+ *
158+ * @param context
159+ * Execution Context to use when creating {@link FileStore}s
160+ * @return array of cells with the values of the module output
161+ * @throws Exception
162+ */
163+ protected DataCell [] getModuleOutput (final ExecutionContext context )
164+ throws Exception {
165+ final List <DataCell > cells = new ArrayList <DataCell >();
166+ for (final ModuleItem <?> entry : getInfo ().outputs ()) {
167+ cells .add (convertService .convertToKnime (
168+ getModule ().getOutput (entry .getName ()), entry .getType (),
169+ getOutputMapping ().get (entry ), context ));
170+ }
171+
172+ return cells .toArray (new DataCell [cells .size ()]);
173+ }
174+
175+ @ Override
176+ public Map <Integer , ModuleItem <?>> getIntputMapping () {
177+ return inputMapping ;
178+ }
179+
180+ @ Override
181+ public Map <ModuleItem <?>, DataType > getOutputMapping () {
182+ return outputMapping ;
183+ }
184+
185+ @ Override
186+ public ModuleInfo getInfo () {
187+ return moduleInfo ;
188+ }
189+
190+ @ Override
191+ public Module getModule () {
192+ return module ;
193+ }
194+
195+ protected final KNIMEConverterService getConvertService () {
196+ return convertService ;
197+ }
198+
154199 private class NodeModuleOutputChangedListener
155200 implements MultiOutputListener {
156201 private ExecutionContext ctx ;
157202
158203 private CellOutput output ;
159204
160205 /* true if the modules handles pushes itself, false otherwise */
161- private final boolean manualPush ;
206+ private final boolean pushOnFlush ;
162207
163208 /**
164209 * Constructor.
165210 *
166- * @param manualPush
167- * if <code>true</code>, signals that the module handles
168- * pushing rows .
211+ * @param pushOnFlush
212+ * if <code>true</code>, will push a final row when flush is
213+ * called .
169214 */
170- public NodeModuleOutputChangedListener (final boolean manualPush ) {
171- this .manualPush = manualPush ;
215+ public NodeModuleOutputChangedListener (final boolean pushOnFlush ) {
216+ this .pushOnFlush = pushOnFlush ;
172217 }
173218
174219 @ Override
175220 public void notifyListener () throws Exception {
176221 // output can be null if sink node
177222 if (output != null ) {
178- final List <DataCell > cells = new ArrayList <DataCell >();
179- for (final ModuleItem <?> entry : module .getInfo ().outputs ()) {
180- // FIXME hack because e.g. python script contains
181- // result log
182- if (!entry .getName ().equals ("result" )) {
183- cells .add (cs .convertToKnime (
184- module .getOutput (entry .getName ()),
185- entry .getType (), outputMapping .get (entry ),
186- ctx ));
187- }
188- }
189- output .push (cells .toArray (new DataCell [cells .size ()]));
223+ output .push (getModuleOutput (ctx ));
190224 }
191225 }
192226
@@ -213,10 +247,11 @@ public void setCellOutput(final CellOutput output) {
213247 /**
214248 * Final flush. Will push a row in case module does not handle pushing
215249 * output rows.
250+ *
216251 * @throws Exception
217252 */
218253 public void flush () throws Exception {
219- if (!manualPush ) {
254+ if (!pushOnFlush ) {
220255 notifyListener ();
221256 }
222257 }
0 commit comments