f73b4d814173e4d189d69ec4f22b61380d059b65
[mir.git] / source / mir / producer / reader / DefaultProducerNodeBuilders.java
1 /*
2  * Copyright (C) 2001, 2002  The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with the com.oreilly.servlet library, any library
22  * licensed under the Apache Software License, The Sun (tm) Java Advanced
23  * Imaging library (JAI), The Sun JIMI library (or with modified versions of
24  * the above that use the same license as the above), and distribute linked
25  * combinations including the two.  You must obey the GNU General Public
26  * License in all respects for all of the code used other than the above
27  * mentioned libraries.  If you modify this file, you may extend this exception
28  * to your version of the file, but you are not obligated to do so.  If you do
29  * not wish to do so, delete this exception statement from your version.
30  */
31
32 package mir.producer.reader;
33
34 import java.util.*;
35 import mir.generator.*;
36 import mir.producer.*;
37 import mir.entity.adapter.*;
38 import mir.util.*;
39
40 public class DefaultProducerNodeBuilders {
41
42   public static void registerBuilders(ProducerNodeBuilderLibrary aBuilderLibrary,
43        EntityAdapterModel aModel, Generator.GeneratorLibrary aGeneratorLibrary,
44        WriterEngine aWriterEngine) {
45
46     aBuilderLibrary.registerBuilder("Set", EvaluatedAssignmentProducerNodeBuilder.class);
47     aBuilderLibrary.registerBuilder("Define", ExpandedAssignmentProducerNodeBuilder.class);
48     aBuilderLibrary.registerBuilder("Log", LoggingProducerNodeBuilder.class);
49     aBuilderLibrary.registerBuilder("Execute", ScriptCallingProducerNodeBuilder.class);
50     aBuilderLibrary.registerBuilder("Resource", ResourceBundleProducerNodeBuilder.class);
51
52     aBuilderLibrary.registerBuilder("DeleteFile", FileDeletingProducerNodeBuilder.class);
53     aBuilderLibrary.registerBuilder("SetFileDate", FileDateSettingProducerNodeBuilder.class);
54     aBuilderLibrary.registerBuilder("If", ConditionalProducerNodeBuilder.class);
55
56
57     aBuilderLibrary.registerFactory("Enumerate", new EnumeratingProducerNodeBuilder.factory(aModel));
58     aBuilderLibrary.registerFactory("List", new ListProducerNodeBuilder.factory(aModel));
59     aBuilderLibrary.registerFactory("Batch", new BatchingProducerNodeBuilder.factory(aModel));
60
61     aBuilderLibrary.registerFactory("Generate",
62         new GeneratingProducerNodeBuilder.factory(aGeneratorLibrary, aWriterEngine));
63   }
64
65   public static abstract class AbstractProducerNodeBuilder implements ProducerNodeBuilder {
66     private Map attributes;
67     private Map subNodes;
68     private Set availableSubnodes;
69
70     public AbstractProducerNodeBuilder(String anAvailableSubNodes[]) {
71       attributes = new HashMap();
72       subNodes = new HashMap();
73       availableSubnodes = new HashSet(Arrays.asList(anAvailableSubNodes));
74     }
75
76     protected ProducerNode getSubNode(String aName) {
77       return (ProducerNode) subNodes.get(aName);
78     }
79
80     public void setSubNode(String aName, ProducerNode aNode) {
81       subNodes.put(aName, aNode);
82     };
83
84     public Set getAvailableSubNodes() {
85       return availableSubnodes;
86     };
87   }
88
89 ////////////////////////////////////////////////////////////////////////////////
90
91   // general attribute names, specifc builders reference these, to keep attribute
92   //    names consistent
93
94   public final static String   SELECTION_ATTRIBUTE = "selection";
95   public final static String   ORDER_ATTRIBUTE = "order";
96   public final static String   DEFINITION_ATTRIBUTE = "table";
97   public final static String   SKIP_ATTRIBUTE = "skip";
98   public final static String   KEY_ATTRIBUTE = "key";
99   public final static String   LIMIT_ATTRIBUTE = "limit";
100
101 ////////////////////////////////////////////////////////////////////////////////
102
103   public static class ExpandedAssignmentProducerNodeBuilder extends AbstractProducerNodeBuilder {
104     private final static String   ASSIGNMENT_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
105     private final static String   ASSIGNMENT_VALUE_ATTRIBUTE = "value";
106     private final static String[] ASSIGNMENT_REQUIRED_ATTRIBUTES = { ASSIGNMENT_KEY_ATTRIBUTE, ASSIGNMENT_VALUE_ATTRIBUTE };
107     private final static String[] ASSIGNMENT_OPTIONAL_ATTRIBUTES = {};
108     private final static String[] ASSIGNMENT_SUBNODES = {};
109
110     private String key;
111     private String value;
112
113     public ExpandedAssignmentProducerNodeBuilder() {
114       super(ASSIGNMENT_SUBNODES);
115     }
116
117     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
118       ReaderTool.checkAttributes(anAttributes, ASSIGNMENT_REQUIRED_ATTRIBUTES, ASSIGNMENT_OPTIONAL_ATTRIBUTES);
119
120       key = (String) anAttributes.get(ASSIGNMENT_KEY_ATTRIBUTE);
121       value = (String) anAttributes.get(ASSIGNMENT_VALUE_ATTRIBUTE);
122     };
123
124     public ProducerNode constructNode() {
125       return new ExpandedAssignmentProducerNode(key, value);
126     };
127   }
128
129 ////////////////////////////////////////////////////////////////////////////////
130
131   public static class EvaluatedAssignmentProducerNodeBuilder extends AbstractProducerNodeBuilder {
132     private final static String   ASSIGNMENT_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
133     private final static String   ASSIGNMENT_VALUE_ATTRIBUTE = "value";
134     private final static String[] ASSIGNMENT_REQUIRED_ATTRIBUTES = { ASSIGNMENT_KEY_ATTRIBUTE, ASSIGNMENT_VALUE_ATTRIBUTE };
135     private final static String[] ASSIGNMENT_OPTIONAL_ATTRIBUTES = {};
136     private final static String[] ASSIGNMENT_SUBNODES = {};
137
138     private String key;
139     private String value;
140
141     public EvaluatedAssignmentProducerNodeBuilder() {
142       super(ASSIGNMENT_SUBNODES);
143     }
144
145     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
146       ReaderTool.checkAttributes(anAttributes, ASSIGNMENT_REQUIRED_ATTRIBUTES, ASSIGNMENT_OPTIONAL_ATTRIBUTES);
147
148       key = (String) anAttributes.get(ASSIGNMENT_KEY_ATTRIBUTE);
149       value = (String) anAttributes.get(ASSIGNMENT_VALUE_ATTRIBUTE);
150     };
151
152     public ProducerNode constructNode() {
153       return new EvaluatedAssignmentProducerNode(key, value);
154     };
155   }
156
157 ////////////////////////////////////////////////////////////////////////////////
158
159   public static class EnumeratingProducerNodeBuilder extends AbstractProducerNodeBuilder {
160     private final static String   ENUMERATION_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
161     private final static String   ENUMERATION_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
162     private final static String   ENUMERATION_SELECTION_ATTRIBUTE = SELECTION_ATTRIBUTE;
163     private final static String   ENUMERATION_ORDER_ATTRIBUTE = ORDER_ATTRIBUTE;
164     private final static String   ENUMERATION_DEFAULT_SUBNODE = "default";
165     private final static String   ENUMERATION_LIMIT_ATTRIBUTE = LIMIT_ATTRIBUTE;
166     private final static String   ENUMERATION_SKIP_ATTRIBUTE = SKIP_ATTRIBUTE;
167     private final static String[] ENUMERATION_REQUIRED_ATTRIBUTES = { ENUMERATION_KEY_ATTRIBUTE, ENUMERATION_DEFINITION_ATTRIBUTE };
168     private final static String[] ENUMERATION_OPTIONAL_ATTRIBUTES = { ENUMERATION_SELECTION_ATTRIBUTE, ENUMERATION_ORDER_ATTRIBUTE, ENUMERATION_LIMIT_ATTRIBUTE, ENUMERATION_SKIP_ATTRIBUTE};
169     private final static String[] ENUMERATION_SUBNODES = {ENUMERATION_DEFAULT_SUBNODE};
170
171     private String key;
172     private String definition;
173     private String selection;
174     private String order;
175     private String limit;
176     private String skip;
177     private EntityAdapterModel model;
178
179     public EnumeratingProducerNodeBuilder(EntityAdapterModel aModel) {
180       super(ENUMERATION_SUBNODES);
181
182       model = aModel;
183     }
184
185     public void setAttributes(Map anAttributes) throws ProducerConfigExc  {
186       ReaderTool.checkAttributes(anAttributes, ENUMERATION_REQUIRED_ATTRIBUTES, ENUMERATION_OPTIONAL_ATTRIBUTES);
187
188       key = (String) anAttributes.get(ENUMERATION_KEY_ATTRIBUTE);
189       definition = (String) anAttributes.get(ENUMERATION_DEFINITION_ATTRIBUTE);
190       selection = (String) ReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_SELECTION_ATTRIBUTE, "");
191       order = (String) ReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_ORDER_ATTRIBUTE, "");
192       limit = (String) anAttributes.get(ENUMERATION_LIMIT_ATTRIBUTE);
193       skip = (String) anAttributes.get(ENUMERATION_SKIP_ATTRIBUTE);
194     };
195
196     public ProducerNode constructNode() {
197       return new EntityEnumeratingProducerNode(key, model, definition, selection, order, limit, skip, getSubNode(ENUMERATION_DEFAULT_SUBNODE ));
198     };
199
200     public static class factory implements ProducerNodeBuilderFactory {
201       private EntityAdapterModel model;
202
203       public factory(EntityAdapterModel aModel) {
204         model = aModel;
205       }
206
207       public ProducerNodeBuilder makeBuilder() {
208         return new EnumeratingProducerNodeBuilder(model);
209       }
210     }
211   }
212
213 ////////////////////////////////////////////////////////////////////////////////
214
215   public static class ListProducerNodeBuilder extends AbstractProducerNodeBuilder {
216     private final static String   LIST_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
217     private final static String   LIST_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
218     private final static String   LIST_SELECTION_ATTRIBUTE = SELECTION_ATTRIBUTE;
219     private final static String   LIST_ORDER_ATTRIBUTE = ORDER_ATTRIBUTE;
220     private final static String   LIST_DEFAULT_SUBNODE = "default";
221     private final static String   LIST_LIMIT_ATTRIBUTE = LIMIT_ATTRIBUTE;
222     private final static String   LIST_SKIP_ATTRIBUTE = SKIP_ATTRIBUTE;
223     private final static String[] LIST_REQUIRED_ATTRIBUTES = { LIST_KEY_ATTRIBUTE, LIST_DEFINITION_ATTRIBUTE };
224     private final static String[] LIST_OPTIONAL_ATTRIBUTES = { LIST_SELECTION_ATTRIBUTE, LIST_ORDER_ATTRIBUTE, LIST_SKIP_ATTRIBUTE, LIST_LIMIT_ATTRIBUTE};
225     private final static String[] LIST_SUBNODES = {};
226
227     private String key;
228     private String definition;
229     private String selection;
230     private String order;
231     private String limit;
232     private String skip;
233     private EntityAdapterModel model;
234
235     public ListProducerNodeBuilder(EntityAdapterModel aModel) {
236       super(LIST_SUBNODES);
237
238       model = aModel;
239     }
240
241     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
242       ReaderTool.checkAttributes(anAttributes, LIST_REQUIRED_ATTRIBUTES, LIST_OPTIONAL_ATTRIBUTES);
243
244       key = (String) anAttributes.get(LIST_KEY_ATTRIBUTE);
245       definition = (String) anAttributes.get(LIST_DEFINITION_ATTRIBUTE);
246       selection = (String) ReaderTool.getStringAttributeWithDefault(anAttributes, LIST_SELECTION_ATTRIBUTE, "");
247       order = (String) ReaderTool.getStringAttributeWithDefault(anAttributes, LIST_ORDER_ATTRIBUTE, "");
248       limit = (String) anAttributes.get(LIST_LIMIT_ATTRIBUTE);
249       skip = (String) anAttributes.get(LIST_SKIP_ATTRIBUTE);
250     };
251
252     public ProducerNode constructNode() {
253       return new EntityListProducerNode(key, model, definition, selection, order, limit, skip, null );
254     };
255
256     public static class factory implements ProducerNodeBuilderFactory {
257       private EntityAdapterModel model;
258
259       public factory(EntityAdapterModel aModel) {
260         model = aModel;
261       }
262
263       public ProducerNodeBuilder makeBuilder() {
264         return new ListProducerNodeBuilder(model);
265       }
266     }
267   }
268
269 ////////////////////////////////////////////////////////////////////////////////
270
271   public static class LoggingProducerNodeBuilder extends AbstractProducerNodeBuilder {
272     private final static String   LOG_MESSAGE_ATTRIBUTE = "message";
273     private final static String[] LOG_REQUIRED_ATTRIBUTES = { LOG_MESSAGE_ATTRIBUTE };
274     private final static String[] LOG_OPTIONAL_ATTRIBUTES = {};
275     private final static String[] LOG_SUBNODES = {};
276
277     private String message;
278
279     public LoggingProducerNodeBuilder() {
280       super(LOG_SUBNODES);
281     }
282
283     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
284       ReaderTool.checkAttributes(anAttributes, LOG_REQUIRED_ATTRIBUTES, LOG_OPTIONAL_ATTRIBUTES);
285
286       message = (String) anAttributes.get(LOG_MESSAGE_ATTRIBUTE);
287     };
288
289     public ProducerNode constructNode() {
290       return new LoggingProducerNode(message);
291     };
292   }
293
294 ////////////////////////////////////////////////////////////////////////////////
295
296   public static class ResourceBundleProducerNodeBuilder extends AbstractProducerNodeBuilder {
297     private final static String   RESOURCEBUNDLE_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
298     private final static String   RESOURCEBUNDLE_BUNDLE_ATTRIBUTE = "bundle";
299     private final static String   RESOURCEBUNDLE_LANGUAGE_ATTRIBUTE = "language";
300     private final static String   RESOURCEBUNDLE_DEFAULT_SUBNODE = "default";
301     private final static String[] RESOURCEBUNDLE_REQUIRED_ATTRIBUTES = { RESOURCEBUNDLE_KEY_ATTRIBUTE, RESOURCEBUNDLE_BUNDLE_ATTRIBUTE };
302     private final static String[] RESOURCEBUNDLE_OPTIONAL_ATTRIBUTES = { RESOURCEBUNDLE_LANGUAGE_ATTRIBUTE};
303     private final static String[] RESOURCEBUNDLE_SUBNODES = {};
304
305     private String key;
306     private String bundle;
307     private String language;
308
309     public ResourceBundleProducerNodeBuilder() {
310       super(RESOURCEBUNDLE_SUBNODES);
311     }
312
313     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
314       ReaderTool.checkAttributes(anAttributes, RESOURCEBUNDLE_REQUIRED_ATTRIBUTES, RESOURCEBUNDLE_OPTIONAL_ATTRIBUTES);
315
316       key = (String) anAttributes.get(RESOURCEBUNDLE_KEY_ATTRIBUTE);
317       bundle = (String) anAttributes.get(RESOURCEBUNDLE_BUNDLE_ATTRIBUTE);
318       language = (String) anAttributes.get(RESOURCEBUNDLE_LANGUAGE_ATTRIBUTE);
319     };
320
321     public ProducerNode constructNode() {
322       return new ResourceBundleProducerNode(key, bundle, language, null );
323     };
324   }
325
326 ////////////////////////////////////////////////////////////////////////////////
327
328   public static class FileDateSettingProducerNodeBuilder extends AbstractProducerNodeBuilder {
329     private final static String   FILEDATESETTING_FILE_ATTRIBUTE = "filename";
330     private final static String   FILEDATESETTING_DATE_ATTRIBUTE = "date";
331     private final static String[] FILEDATESETTING_REQUIRED_ATTRIBUTES = { FILEDATESETTING_FILE_ATTRIBUTE, FILEDATESETTING_DATE_ATTRIBUTE };
332     private final static String[] FILEDATESETTING_OPTIONAL_ATTRIBUTES = { };
333     private final static String[] FILEDATESETTING_SUBNODES = {};
334
335     private String fileNameKey;
336     private String dateKey;
337
338     public FileDateSettingProducerNodeBuilder() {
339       super(FILEDATESETTING_SUBNODES);
340     }
341
342     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
343       ReaderTool.checkAttributes(anAttributes, FILEDATESETTING_REQUIRED_ATTRIBUTES, FILEDATESETTING_OPTIONAL_ATTRIBUTES);
344
345       fileNameKey = (String) anAttributes.get(FILEDATESETTING_FILE_ATTRIBUTE);
346       dateKey = (String) anAttributes.get(FILEDATESETTING_DATE_ATTRIBUTE);
347     };
348
349     public ProducerNode constructNode() {
350       return new FileDateSettingProducerNode(fileNameKey, dateKey);
351     };
352   }
353
354 ////////////////////////////////////////////////////////////////////////////////
355
356   public static class FileDeletingProducerNodeBuilder extends AbstractProducerNodeBuilder {
357     private final static String   FILEDELETING_FILE_ATTRIBUTE = "filename";
358     private final static String[] FILEDELETING_REQUIRED_ATTRIBUTES = { FILEDELETING_FILE_ATTRIBUTE };
359     private final static String[] FILEDELETING_OPTIONAL_ATTRIBUTES = { };
360     private final static String[] FILEDELETING_SUBNODES = { };
361
362     private String fileNameKey;
363
364     public FileDeletingProducerNodeBuilder() {
365       super(FILEDELETING_SUBNODES);
366     }
367
368     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
369       ReaderTool.checkAttributes(anAttributes, FILEDELETING_REQUIRED_ATTRIBUTES, FILEDELETING_OPTIONAL_ATTRIBUTES);
370
371       fileNameKey = (String) anAttributes.get(FILEDELETING_FILE_ATTRIBUTE);
372     };
373
374     public ProducerNode constructNode() {
375       return new FileDeletingProducerNode(fileNameKey);
376     };
377   }
378
379 ////////////////////////////////////////////////////////////////////////////////
380
381   public static class ScriptCallingProducerNodeBuilder extends AbstractProducerNodeBuilder {
382     private final static String   SCRIPT_COMMAND_ATTRIBUTE = "command";
383     private final static String[] SCRIPT_REQUIRED_ATTRIBUTES = { SCRIPT_COMMAND_ATTRIBUTE };
384     private final static String[] SCRIPT_OPTIONAL_ATTRIBUTES = {};
385     private final static String[] SCRIPT_SUBNODES = {};
386
387     private String command;
388
389     public ScriptCallingProducerNodeBuilder() {
390       super(SCRIPT_SUBNODES);
391     }
392
393     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
394       ReaderTool.checkAttributes(anAttributes, SCRIPT_REQUIRED_ATTRIBUTES, SCRIPT_OPTIONAL_ATTRIBUTES);
395
396       command = (String) anAttributes.get(SCRIPT_COMMAND_ATTRIBUTE);
397     };
398
399     public ProducerNode constructNode() {
400       return new ScriptCallingProducerNode(command);
401     };
402   }
403
404 ////////////////////////////////////////////////////////////////////////////////
405
406   public static class GeneratingProducerNodeBuilder extends AbstractProducerNodeBuilder {
407     private final static String   GENERATION_GENERATOR_ATTRIBUTE = "generator";
408     private final static String   GENERATION_DESTINATION_ATTRIBUTE = "destination";
409     private final static String   GENERATION_PARAMETERS_ATTRIBUTE = "parameters";
410     private final static String[] GENERATION_REQUIRED_ATTRIBUTES = { GENERATION_GENERATOR_ATTRIBUTE, GENERATION_DESTINATION_ATTRIBUTE };
411     private final static String[] GENERATION_OPTIONAL_ATTRIBUTES = { GENERATION_PARAMETERS_ATTRIBUTE};
412     private final static String[] GENERATION_SUBNODES = {};
413
414     private String generator;
415     private String destination;
416     private String parameters;
417     private Generator.GeneratorLibrary generatorLibrary;
418     private WriterEngine writerEngine;
419
420     public GeneratingProducerNodeBuilder(Generator.GeneratorLibrary aGeneratorLibrary, WriterEngine aWriterEngine) {
421       super(GENERATION_SUBNODES);
422
423       writerEngine = aWriterEngine;
424       generatorLibrary = aGeneratorLibrary;
425     }
426
427     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
428       ReaderTool.checkAttributes(anAttributes, GENERATION_REQUIRED_ATTRIBUTES, GENERATION_OPTIONAL_ATTRIBUTES);
429
430       generator = (String) anAttributes.get(GENERATION_GENERATOR_ATTRIBUTE);
431       destination = (String) anAttributes.get(GENERATION_DESTINATION_ATTRIBUTE);
432       parameters = ReaderTool.getStringAttributeWithDefault(anAttributes, GENERATION_PARAMETERS_ATTRIBUTE, "" );
433     };
434
435     public ProducerNode constructNode() {
436       return new GeneratingProducerNode(generatorLibrary, writerEngine, generator, destination, parameters);
437     };
438
439     public static class factory implements ProducerNodeBuilderFactory {
440       private Generator.GeneratorLibrary generatorLibrary;
441       private WriterEngine writerEngine;
442
443       public factory(Generator.GeneratorLibrary aGeneratorLibrary, WriterEngine aWriterEngine) {
444         writerEngine = aWriterEngine;
445         generatorLibrary = aGeneratorLibrary;
446       }
447
448       public ProducerNodeBuilder makeBuilder() {
449         return new GeneratingProducerNodeBuilder(generatorLibrary, writerEngine);
450       }
451     }
452   }
453
454 ////////////////////////////////////////////////////////////////////////////////
455
456   public static class BatchingProducerNodeBuilder extends AbstractProducerNodeBuilder {
457
458     private final static String   BATCHER_DATAKEY_ATTRIBUTE = KEY_ATTRIBUTE;
459     private final static String   BATCHER_INFOKEY_ATTRIBUTE = "infokey";
460     private final static String   BATCHER_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
461     private final static String   BATCHER_SELECTION_ATTRIBUTE = SELECTION_ATTRIBUTE;
462     private final static String   BATCHER_ORDER_ATTRIBUTE = ORDER_ATTRIBUTE;
463
464     private final static String   BATCHER_BATCHSIZE_ATTRIBUTE = "batchsize";
465     private final static String   BATCHER_MINBATCHSIZE_ATTRIBUTE = "minbatchsize";
466     private final static String   BATCHER_SKIP_ATTRIBUTE = SKIP_ATTRIBUTE;
467
468     private final static String   BATCHER_PROCESS_ATTRIBUTE = "process";
469
470     private final static String   BATCHER_BATCH_SUBNODE = "batches";
471     private final static String   BATCHER_BATCHLIST_SUBNODE = "batchlist";
472     private final static String[] BATCHER_REQUIRED_ATTRIBUTES = { BATCHER_DATAKEY_ATTRIBUTE, BATCHER_INFOKEY_ATTRIBUTE, BATCHER_DEFINITION_ATTRIBUTE, BATCHER_BATCHSIZE_ATTRIBUTE };
473     private final static String[] BATCHER_OPTIONAL_ATTRIBUTES = { BATCHER_SELECTION_ATTRIBUTE, BATCHER_ORDER_ATTRIBUTE, BATCHER_MINBATCHSIZE_ATTRIBUTE, BATCHER_SKIP_ATTRIBUTE, BATCHER_PROCESS_ATTRIBUTE };
474     private final static String[] BATCHER_SUBNODES = { BATCHER_BATCH_SUBNODE, BATCHER_BATCHLIST_SUBNODE };
475
476     // ML: batchSize, minBatchSize, skip should be expressions!
477
478     private EntityAdapterModel model;
479     private String batchDataKey;
480     private String batchInfoKey;
481     private String definition;
482     private String selection;
483     private String order;
484     private String batchSize;
485     private String minBatchSize;
486     private String skip;
487     private String process;
488
489     public BatchingProducerNodeBuilder(EntityAdapterModel aModel) {
490       super(BATCHER_SUBNODES);
491
492       model = aModel;
493     }
494
495     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
496       ReaderTool.checkAttributes(anAttributes, BATCHER_REQUIRED_ATTRIBUTES, BATCHER_OPTIONAL_ATTRIBUTES);
497
498       batchDataKey = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DATAKEY_ATTRIBUTE, "data" );
499       batchInfoKey = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_INFOKEY_ATTRIBUTE, "info" );
500       definition = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DEFINITION_ATTRIBUTE, "" );
501       selection = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SELECTION_ATTRIBUTE, "" );
502       order = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_ORDER_ATTRIBUTE, "" );
503
504       batchSize = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_BATCHSIZE_ATTRIBUTE, "20" );
505       minBatchSize = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_MINBATCHSIZE_ATTRIBUTE, "0" );
506       skip = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SKIP_ATTRIBUTE, "0" );
507       process = ReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_PROCESS_ATTRIBUTE, "-1" );
508     };
509
510     public ProducerNode constructNode() {
511       return new EntityBatchingProducerNode(
512           batchDataKey,
513           batchInfoKey,
514           model,
515           definition,
516           selection,
517           order,
518           batchSize,
519           minBatchSize,
520           skip,
521           process,
522           getSubNode( BATCHER_BATCH_SUBNODE ),
523           getSubNode( BATCHER_BATCHLIST_SUBNODE )
524       );
525     };
526
527     public static class factory implements ProducerNodeBuilderFactory {
528       private EntityAdapterModel model;
529
530       public factory(EntityAdapterModel aModel) {
531         model = aModel;
532       }
533
534       public ProducerNodeBuilder makeBuilder() {
535         return new BatchingProducerNodeBuilder(model);
536       }
537     }
538   }
539
540 ////////////////////////////////////////////////////////////////////////////////
541
542   public static class ConditionalProducerNodeBuilder extends AbstractProducerNodeBuilder {
543     private final static String   IF_CONDITION_ATTRIBUTE = "condition";
544
545     private final static String   IF_TRUE_SUBNODE = "then";
546     private final static String   IF_FALSE_SUBNODE = "else";
547     private final static String[] IF_REQUIRED_ATTRIBUTES = { IF_CONDITION_ATTRIBUTE };
548     private final static String[] IF_OPTIONAL_ATTRIBUTES = {  };
549     private final static String[] IF_SUBNODES = { IF_TRUE_SUBNODE, IF_FALSE_SUBNODE };
550
551     private String condition;
552
553     public ConditionalProducerNodeBuilder() {
554       super(IF_SUBNODES);
555     }
556
557     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
558       ReaderTool.checkAttributes(anAttributes, IF_REQUIRED_ATTRIBUTES, IF_OPTIONAL_ATTRIBUTES);
559
560       condition = (String) anAttributes.get( IF_CONDITION_ATTRIBUTE );
561     };
562
563     public ProducerNode constructNode() {
564       return new ConditionalProducerNode(
565           condition,
566           getSubNode( IF_TRUE_SUBNODE ),
567           getSubNode( IF_FALSE_SUBNODE )
568       );
569     };
570
571   }
572
573 ////////////////////////////////////////////////////////////////////////////////
574
575   public static class ScriptedProducerParameterNodeBuilder implements ProducerNodeBuilder {
576     private String parameterName;
577     private String scriptedNodeName;
578
579     public ScriptedProducerParameterNodeBuilder(String aScriptedNodeName, String aParameterName) {
580       parameterName = aParameterName;
581       scriptedNodeName = aScriptedNodeName;
582     }
583
584     public void setSubNode(String aName, ProducerNode aNode) {
585     };
586
587     public Set getAvailableSubNodes() {
588       return new HashSet();
589     };
590
591     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
592       if (!anAttributes.isEmpty())
593         throw new ProducerConfigExc("No parameters allowed here");
594     };
595
596     public ProducerNode constructNode() {
597       return new ScriptedProducerNodeDefinition.NodeParameterProducerNode(scriptedNodeName, parameterName);
598     };
599   }
600
601 ////////////////////////////////////////////////////////////////////////////////
602
603   public static class ScriptedProducerNodeBuilder implements ProducerNodeBuilder {
604     private ScriptedProducerNodeDefinition definition;
605     private Map nodeParameterValues;
606     private Map parameterValues;
607
608     public ScriptedProducerNodeBuilder(ScriptedProducerNodeDefinition aDefinition) {
609       definition = aDefinition;
610
611       parameterValues = new HashMap();
612       parameterValues.putAll(definition.getParameters());
613
614       nodeParameterValues = new HashMap();
615     }
616
617     public void setSubNode(String aName, ProducerNode aNode) {
618       nodeParameterValues.put(aName, aNode);
619     };
620
621     public Set getAvailableSubNodes() {
622       return definition.getNodeParameters();
623     };
624
625     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
626       ReaderTool.checkAttributeSet(anAttributes.keySet(), definition.getRequiredAttributes(), definition.getOptionalAttributes());
627     };
628
629     public ProducerNode constructNode() {
630       return new ScriptedProducerNode(definition, parameterValues, nodeParameterValues);
631     };
632
633     public static class factory implements ProducerNodeBuilderFactory {
634       private ScriptedProducerNodeDefinition definition;
635
636       public factory(ScriptedProducerNodeDefinition aDefinition) {
637         definition = aDefinition;
638       }
639
640       public ProducerNodeBuilder makeBuilder() {
641         return new ScriptedProducerNodeBuilder(definition);
642       }
643     }
644   }
645 }