f0295f8da246126424c46ef900703a3d633982b8
[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  any library licensed under the Apache Software License,
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23  * (or with modified versions of the above that use the same license as the above),
24  * and distribute linked combinations including the two.  You must obey the
25  * GNU General Public License in all respects for all of the code used other than
26  * the above mentioned libraries.  If you modify this file, you may extend this
27  * exception to your version of the file, but you are not obligated to do so.
28  * If you do not wish to do so, delete this exception statement from your version.
29  */
30 package mir.producer.reader;
31
32 import java.util.Arrays;
33 import java.util.HashMap;
34 import java.util.HashSet;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Set;
39 import java.io.File;
40
41 import mir.entity.adapter.EntityAdapterModel;
42 import mir.generator.Generator;
43 import mir.generator.WriterEngine;
44 import mir.log.LoggerWrapper;
45 import mir.producer.ConditionalProducerNode;
46 import mir.producer.DirCopyingProducerNode;
47 import mir.producer.EntityBatchingProducerNode;
48 import mir.producer.EntityDeletingProducerNode;
49 import mir.producer.EntityEnumeratingProducerNode;
50 import mir.producer.EntityListProducerNode;
51 import mir.producer.EntityModifyingProducerNode;
52 import mir.producer.EvaluatedAssignmentProducerNode;
53 import mir.producer.ExpandedAssignmentProducerNode;
54 import mir.producer.ExternalDbProducerNode;
55 import mir.producer.FileDateSettingProducerNode;
56 import mir.producer.FileDeletingProducerNode;
57 import mir.producer.FreeQueryProducerNode;
58 import mir.producer.GeneratingProducerNode;
59 import mir.producer.ListEnumeratingProducerNode;
60 import mir.producer.LoggingProducerNode;
61 import mir.producer.LoopProducerNode;
62 import mir.producer.ProducerNode;
63 import mir.producer.RDFAggregatorProducerNode;
64 import mir.producer.RSSProducerNode;
65 import mir.producer.BundleProducerNode;
66 import mir.producer.ExecuteProgramProducerNode;
67 import mir.util.StringRoutines;
68 import mir.util.xml.XMLParserExc;
69 import mir.util.xml.XMLReaderTool;
70
71 public class DefaultProducerNodeBuilders {
72
73   public static void registerBuilders(ProducerNodeBuilderLibrary aBuilderLibrary,
74        EntityAdapterModel aModel, Generator.Library aGeneratorLibrary,
75        WriterEngine aWriterEngine, File aSourceBasePath, File aDestinationBasePath) throws ProducerConfigExc {
76
77     aBuilderLibrary.registerBuilder("Set", EvaluatedAssignmentProducerNodeBuilder.class);
78     aBuilderLibrary.registerBuilder("Define", ExpandedAssignmentProducerNodeBuilder.class);
79     aBuilderLibrary.registerBuilder("Log", LoggingProducerNodeBuilder.class);
80     aBuilderLibrary.registerBuilder("Execute", ExecuteProgramProducerNodeBuilder.class);
81     aBuilderLibrary.registerBuilder("Resource", BundleProducerNodeBuilder.class);
82     aBuilderLibrary.registerBuilder("Bundle", BundleProducerNodeBuilder.class);
83     aBuilderLibrary.registerFactory("CopyDir", new DirCopyProducerNodeBuilder.factory(aSourceBasePath, aDestinationBasePath));
84
85     aBuilderLibrary.registerBuilder("DeleteFile", FileDeletingProducerNodeBuilder.class);
86     aBuilderLibrary.registerBuilder("SetFileDate", FileDateSettingProducerNodeBuilder.class);
87     aBuilderLibrary.registerBuilder("If", ConditionalProducerNodeBuilder.class);
88     aBuilderLibrary.registerBuilder("While", LoopProducerNodeBuilder.class);
89
90     aBuilderLibrary.registerBuilder("RSS", RSSProducerNodeBuilder.class);
91     aBuilderLibrary.registerBuilder("RDFAggregate", RDFAggregatorProducerNodeBuilder.class);
92
93     aBuilderLibrary.registerBuilder("FreeQuery", FreeQueryProducerNodeBuilder.class);
94     aBuilderLibrary.registerBuilder("ExternalDbQuery", ExternalDbProducerNodeBuilder.class);
95
96     aBuilderLibrary.registerFactory("Enumerate", new EnumeratingProducerNodeBuilder.factory(aModel));
97     aBuilderLibrary.registerFactory("List", new ListProducerNodeBuilder.factory(aModel));
98     aBuilderLibrary.registerFactory("Batch", new BatchingProducerNodeBuilder.factory(aModel));
99
100     aBuilderLibrary.registerFactory("UpdateEntity", new UpdateEntityProducerNodeBuilder.factory(aModel));
101     aBuilderLibrary.registerFactory("CreateEntity", new CreateEntityProducerNodeBuilder.factory(aModel));
102     aBuilderLibrary.registerFactory("DeleteEntity", new DeleteEntityProducerNodeBuilder.factory(aModel));
103
104     aBuilderLibrary.registerFactory("Generate", new GeneratingProducerNodeBuilder.factory(aGeneratorLibrary, aWriterEngine));
105   }
106
107   public static abstract class AbstractProducerNodeBuilder implements ProducerNodeBuilder {
108     private Map subNodes;
109     private Set availableSubnodes;
110
111     public AbstractProducerNodeBuilder(String anAvailableSubNodes[]) {
112       subNodes = new HashMap();
113       availableSubnodes = new HashSet(Arrays.asList(anAvailableSubNodes));
114     }
115
116     protected ProducerNode getSubNode(String aName) {
117       return (ProducerNode) subNodes.get(aName);
118     }
119
120     public void setSubNode(String aName, ProducerNode aNode) {
121       subNodes.put(aName, aNode);
122     };
123
124     public Set getAvailableSubNodes() {
125       return availableSubnodes;
126     };
127   }
128
129 ////////////////////////////////////////////////////////////////////////////////
130
131   // general attribute names, specifc builders reference these, to keep attribute
132   //    names consistent
133
134   public final static String   EXTRA_TABLES_ATTRIBUTE = "extratables";
135   public final static String   SELECTION_ATTRIBUTE = "selection";
136   public final static String   ORDER_ATTRIBUTE = "order";
137   public final static String   DEFINITION_ATTRIBUTE = "table";
138   public final static String   SKIP_ATTRIBUTE = "skip";
139   public final static String   KEY_ATTRIBUTE = "key";
140   public final static String   LIMIT_ATTRIBUTE = "limit";
141   public final static String   URL_ATTRIBUTE = "url";
142
143 ////////////////////////////////////////////////////////////////////////////////
144
145   private final static String   ASSIGNMENT_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
146   private final static String   ASSIGNMENT_VALUE_ATTRIBUTE = "value";
147   private final static String[] ASSIGNMENT_REQUIRED_ATTRIBUTES = { ASSIGNMENT_KEY_ATTRIBUTE, ASSIGNMENT_VALUE_ATTRIBUTE };
148   private final static String[] ASSIGNMENT_OPTIONAL_ATTRIBUTES = {};
149   private final static String[] ASSIGNMENT_SUBNODES = {};
150
151   public static class ExpandedAssignmentProducerNodeBuilder extends AbstractProducerNodeBuilder {
152
153     private String key;
154     private String value;
155
156     public ExpandedAssignmentProducerNodeBuilder() {
157       super(ASSIGNMENT_SUBNODES);
158     }
159
160     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
161       XMLReaderTool.checkAttributes(anAttributes, ASSIGNMENT_REQUIRED_ATTRIBUTES, ASSIGNMENT_OPTIONAL_ATTRIBUTES);
162
163       key = (String) anAttributes.get(ASSIGNMENT_KEY_ATTRIBUTE);
164       value = (String) anAttributes.get(ASSIGNMENT_VALUE_ATTRIBUTE);
165     };
166
167     public ProducerNode constructNode() {
168       return new ExpandedAssignmentProducerNode(key, value);
169     };
170   }
171
172 ////////////////////////////////////////////////////////////////////////////////
173
174   public static class EvaluatedAssignmentProducerNodeBuilder extends AbstractProducerNodeBuilder {
175
176     private String key;
177     private String value;
178
179     public EvaluatedAssignmentProducerNodeBuilder() {
180       super(ASSIGNMENT_SUBNODES);
181     }
182
183     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
184       XMLReaderTool.checkAttributes(anAttributes, ASSIGNMENT_REQUIRED_ATTRIBUTES, ASSIGNMENT_OPTIONAL_ATTRIBUTES);
185
186       key = (String) anAttributes.get(ASSIGNMENT_KEY_ATTRIBUTE);
187       value = (String) anAttributes.get(ASSIGNMENT_VALUE_ATTRIBUTE);
188     };
189
190     public ProducerNode constructNode() {
191       return new EvaluatedAssignmentProducerNode(key, value);
192     };
193   }
194
195 ////////////////////////////////////////////////////////////////////////////////
196
197   public static class EnumeratingProducerNodeBuilder extends AbstractProducerNodeBuilder {
198     private final static String   ENUMERATION_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
199     private final static String   ENUMERATION_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
200     private final static String   ENUMERATION_LIST_ATTRIBUTE = "list";
201     private final static String   ENUMERATION_SELECTION_ATTRIBUTE = SELECTION_ATTRIBUTE;
202     private final static String   ENUMERATION_ORDER_ATTRIBUTE = ORDER_ATTRIBUTE;
203     private final static String   ENUMERATION_DEFAULT_SUBNODE = "default";
204     private final static String   ENUMERATION_LIMIT_ATTRIBUTE = LIMIT_ATTRIBUTE;
205     private final static String   ENUMERATION_SKIP_ATTRIBUTE = SKIP_ATTRIBUTE;
206     private final static String   ENUMERATION_EXTRATABLES_ATTRIBUTE = EXTRA_TABLES_ATTRIBUTE;
207     private final static String[] ENUMERATION_LIST_REQUIRED_ATTRIBUTES = { ENUMERATION_LIST_ATTRIBUTE, ENUMERATION_KEY_ATTRIBUTE };
208     private final static String[] ENUMERATION_LIST_OPTIONAL_ATTRIBUTES = { };
209     private final static String[] ENUMERATION_QUERY_REQUIRED_ATTRIBUTES = { ENUMERATION_DEFINITION_ATTRIBUTE, ENUMERATION_KEY_ATTRIBUTE };
210     private final static String[] ENUMERATION_QUERY_OPTIONAL_ATTRIBUTES = { ENUMERATION_SELECTION_ATTRIBUTE, ENUMERATION_ORDER_ATTRIBUTE, ENUMERATION_LIMIT_ATTRIBUTE, ENUMERATION_SKIP_ATTRIBUTE,ENUMERATION_EXTRATABLES_ATTRIBUTE};
211     private final static String[] ENUMERATION_SUBNODES = {ENUMERATION_DEFAULT_SUBNODE};
212
213     private String key;
214     private String definition;
215     private String mainTablePrefix;
216     private String extraTables;
217     private String list;
218     private String selection;
219     private String order;
220     private String limit;
221     private String skip;
222     private EntityAdapterModel model;
223
224     public EnumeratingProducerNodeBuilder(EntityAdapterModel aModel) {
225       super(ENUMERATION_SUBNODES);
226
227       model = aModel;
228     }
229
230     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc  {
231       definition = (String) anAttributes.get(ENUMERATION_DEFINITION_ATTRIBUTE);
232       list = (String) anAttributes.get(ENUMERATION_LIST_ATTRIBUTE);
233
234       if ((list==null && definition==null) || (list!=null && definition!=null))
235         throw new ProducerConfigExc("Exactly one of "+ENUMERATION_DEFINITION_ATTRIBUTE+" and "+ENUMERATION_LIST_ATTRIBUTE+" must be set");
236
237
238       if (list!=null)
239         XMLReaderTool.checkAttributes(anAttributes, ENUMERATION_LIST_REQUIRED_ATTRIBUTES, ENUMERATION_LIST_OPTIONAL_ATTRIBUTES);
240       if (definition!=null)
241         XMLReaderTool.checkAttributes(anAttributes, ENUMERATION_QUERY_REQUIRED_ATTRIBUTES, ENUMERATION_QUERY_OPTIONAL_ATTRIBUTES);
242
243
244       key = (String) anAttributes.get(ENUMERATION_KEY_ATTRIBUTE);
245       selection = XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_SELECTION_ATTRIBUTE, "");
246       order = XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_ORDER_ATTRIBUTE, "");
247       limit = (String) anAttributes.get(ENUMERATION_LIMIT_ATTRIBUTE);
248       skip = (String) anAttributes.get(ENUMERATION_SKIP_ATTRIBUTE);
249       extraTables = XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_EXTRATABLES_ATTRIBUTE,"");
250       if (definition!=null) {
251         List parts = StringRoutines.splitString(definition.trim(), " ");
252         if (parts.size() > 0)
253           definition = (String) parts.get(0);
254         if (parts.size() > 1)
255           mainTablePrefix = (String) parts.get(1);
256       }
257     };
258
259     public ProducerNode constructNode() {
260       if (definition!=null)
261         return new EntityEnumeratingProducerNode(key, model, mainTablePrefix, extraTables, definition, selection, order, limit, skip, getSubNode(ENUMERATION_DEFAULT_SUBNODE ));
262       else
263         return new ListEnumeratingProducerNode(key, list, getSubNode(ENUMERATION_DEFAULT_SUBNODE ));
264     };
265
266     public static class factory implements ProducerNodeBuilderFactory {
267       private EntityAdapterModel model;
268
269       public factory(EntityAdapterModel aModel) {
270         model = aModel;
271       }
272
273       public ProducerNodeBuilder makeBuilder() {
274         return new EnumeratingProducerNodeBuilder(model);
275       }
276     }
277   }
278
279 ////////////////////////////////////////////////////////////////////////////////
280
281   public static class UpdateEntityProducerNodeBuilder extends AbstractProducerNodeBuilder {
282     private final static String   UPDATE_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
283     private final static String   UPDATE_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
284     private final static String[] UPDATE_SUBNODES = {};
285
286     private String key;
287     private String definition;
288     private Map fieldValues;
289
290     private EntityAdapterModel model;
291
292     public UpdateEntityProducerNodeBuilder(EntityAdapterModel aModel) {
293       super(UPDATE_SUBNODES);
294
295       model = aModel;
296       fieldValues = new HashMap();
297     }
298
299     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc  {
300       key = (String) anAttributes.get(UPDATE_KEY_ATTRIBUTE);
301
302       if (key == null)
303         throw new XMLParserExc("missing required attribute '" + UPDATE_KEY_ATTRIBUTE + "'" );
304       definition = (String) anAttributes.get(UPDATE_DEFINITION_ATTRIBUTE);
305
306       fieldValues.putAll(anAttributes);
307       fieldValues.remove(UPDATE_KEY_ATTRIBUTE);
308       fieldValues.remove(UPDATE_DEFINITION_ATTRIBUTE);
309     };
310
311     public ProducerNode constructNode() {
312       return new EntityModifyingProducerNode(model, false, definition, key, fieldValues);
313     };
314
315     public static class factory implements ProducerNodeBuilderFactory {
316       private EntityAdapterModel model;
317
318       public factory(EntityAdapterModel aModel) {
319         model = aModel;
320       }
321
322       public ProducerNodeBuilder makeBuilder() {
323         return new UpdateEntityProducerNodeBuilder(model);
324       }
325     }
326   }
327
328 ////////////////////////////////////////////////////////////////////////////////
329
330   public static class CreateEntityProducerNodeBuilder extends AbstractProducerNodeBuilder {
331     private final static String   CREATEENTITY_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
332     private final static String   CREATEENTITY_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
333     private final static String[] CREATEENTITY_SUBNODES = {};
334
335     private String key;
336     private String definition;
337     private Map fieldValues;
338
339     private EntityAdapterModel model;
340
341     public CreateEntityProducerNodeBuilder(EntityAdapterModel aModel) {
342       super(CREATEENTITY_SUBNODES);
343
344       model = aModel;
345       fieldValues = new HashMap();
346     }
347
348     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc  {
349       key = (String) anAttributes.get(CREATEENTITY_KEY_ATTRIBUTE);
350       definition = (String) anAttributes.get(CREATEENTITY_DEFINITION_ATTRIBUTE);
351
352       if (key == null)
353         throw new XMLParserExc("missing required attribute '" + CREATEENTITY_KEY_ATTRIBUTE + "'" );
354       if (definition == null)
355         throw new XMLParserExc("missing required attribute '" + CREATEENTITY_DEFINITION_ATTRIBUTE + "'" );
356
357       fieldValues.putAll(anAttributes);
358       fieldValues.remove(CREATEENTITY_KEY_ATTRIBUTE);
359       fieldValues.remove(CREATEENTITY_DEFINITION_ATTRIBUTE);
360     };
361
362     public ProducerNode constructNode() {
363       return new EntityModifyingProducerNode(model, true, definition, key, fieldValues);
364     };
365
366     public static class factory implements ProducerNodeBuilderFactory {
367       private EntityAdapterModel model;
368
369       public factory(EntityAdapterModel aModel) {
370         model = aModel;
371       }
372
373       public ProducerNodeBuilder makeBuilder() {
374         return new CreateEntityProducerNodeBuilder(model);
375       }
376     }
377   }
378
379 ////////////////////////////////////////////////////////////////////////////////
380
381   public static class LoopProducerNodeBuilder extends AbstractProducerNodeBuilder {
382     private final static String   LOOP_CONDITION_ATTRIBUTE = "condition";
383     private final static String   LOOP_LIMIT_ATTRIBUTE = LIMIT_ATTRIBUTE;
384     private final static String   LOOP_DEFAULT_SUBNODE = "default";
385     private final static String[] LOOP_REQUIRED_ATTRIBUTES = { LOOP_CONDITION_ATTRIBUTE };
386     private final static String[] LOOP_OPTIONAL_ATTRIBUTES = { LOOP_LIMIT_ATTRIBUTE };
387     private final static String[] LOOP_SUBNODES = {LOOP_DEFAULT_SUBNODE};
388
389     private String condition;
390     private String limit;
391
392     public LoopProducerNodeBuilder() {
393       super(LOOP_SUBNODES);
394     }
395
396     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc  {
397       XMLReaderTool.checkAttributes(anAttributes, LOOP_REQUIRED_ATTRIBUTES, LOOP_OPTIONAL_ATTRIBUTES);
398
399       condition = (String) anAttributes.get(LOOP_CONDITION_ATTRIBUTE);
400       limit = XMLReaderTool.getStringAttributeWithDefault(anAttributes, LOOP_LIMIT_ATTRIBUTE, "");
401     };
402
403     public ProducerNode constructNode() {
404       return new LoopProducerNode(condition, limit, getSubNode( LOOP_DEFAULT_SUBNODE ));
405     };
406   }
407
408 ////////////////////////////////////////////////////////////////////////////////
409
410   public static class ListProducerNodeBuilder extends AbstractProducerNodeBuilder {
411     private final static String   LIST_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
412     private final static String   LIST_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
413     private final static String   LIST_SELECTION_ATTRIBUTE = SELECTION_ATTRIBUTE;
414     private final static String   LIST_EXTRATABLES_ATTRIBUTE = EXTRA_TABLES_ATTRIBUTE;
415     private final static String   LIST_ORDER_ATTRIBUTE = ORDER_ATTRIBUTE;
416     private final static String   LIST_LIMIT_ATTRIBUTE = LIMIT_ATTRIBUTE;
417     private final static String   LIST_SKIP_ATTRIBUTE = SKIP_ATTRIBUTE;
418     private final static String[] LIST_REQUIRED_ATTRIBUTES = { LIST_KEY_ATTRIBUTE, LIST_DEFINITION_ATTRIBUTE };
419     private final static String[] LIST_OPTIONAL_ATTRIBUTES = { LIST_SELECTION_ATTRIBUTE, LIST_ORDER_ATTRIBUTE, LIST_SKIP_ATTRIBUTE, LIST_LIMIT_ATTRIBUTE,LIST_EXTRATABLES_ATTRIBUTE};
420     private final static String[] LIST_SUBNODES = {};
421
422     private String key;
423     private String definition;
424     private String mainTablePrefix;
425     private String extraTables;
426     private String selection;
427     private String order;
428     private String limit;
429     private String skip;
430     private EntityAdapterModel model;
431
432     public ListProducerNodeBuilder(EntityAdapterModel aModel) {
433       super(LIST_SUBNODES);
434
435       model = aModel;
436     }
437
438     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
439       XMLReaderTool.checkAttributes(anAttributes, LIST_REQUIRED_ATTRIBUTES, LIST_OPTIONAL_ATTRIBUTES);
440
441       key = (String) anAttributes.get(LIST_KEY_ATTRIBUTE);
442       definition = (String) anAttributes.get(LIST_DEFINITION_ATTRIBUTE);
443       selection = XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_SELECTION_ATTRIBUTE, "");
444       order = XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_ORDER_ATTRIBUTE, "");
445       limit = (String) anAttributes.get(LIST_LIMIT_ATTRIBUTE);
446       skip = (String) anAttributes.get(LIST_SKIP_ATTRIBUTE);
447       extraTables = XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_EXTRATABLES_ATTRIBUTE,"");
448       List parts = StringRoutines.splitString(definition.trim()," ");
449       if (parts.size()>0) definition=(String)parts.get(0);
450       if (parts.size()>1) mainTablePrefix=(String)parts.get(1);
451
452     };
453
454     public ProducerNode constructNode() {
455       return new EntityListProducerNode(key, model, mainTablePrefix, extraTables, definition, selection, order, limit, skip, null );
456     };
457
458     public static class factory implements ProducerNodeBuilderFactory {
459       private EntityAdapterModel model;
460
461       public factory(EntityAdapterModel aModel) {
462         model = aModel;
463       }
464
465       public ProducerNodeBuilder makeBuilder() {
466         return new ListProducerNodeBuilder(model);
467       }
468     }
469   }
470
471 ////////////////////////////////////////////////////////////////////////////////
472
473   public static class DeleteEntityProducerNodeBuilder extends AbstractProducerNodeBuilder {
474     private final static String   DELETEENTITY_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
475     private final static String   DELETEENTITY_SELECTION_ATTRIBUTE = SELECTION_ATTRIBUTE;
476     private final static String[] DELETEENTITY_REQUIRED_ATTRIBUTES = { DELETEENTITY_SELECTION_ATTRIBUTE, DELETEENTITY_DEFINITION_ATTRIBUTE };
477     private final static String[] DELETEENTITY_OPTIONAL_ATTRIBUTES = { };
478     private final static String[] DELETEENTITY_SUBNODES = {};
479
480     private String definition;
481     private String selection;
482
483     private EntityAdapterModel model;
484
485     public DeleteEntityProducerNodeBuilder(EntityAdapterModel aModel) {
486       super(DELETEENTITY_SUBNODES);
487
488       model = aModel;
489     }
490
491     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
492       XMLReaderTool.checkAttributes(anAttributes, DELETEENTITY_REQUIRED_ATTRIBUTES, DELETEENTITY_OPTIONAL_ATTRIBUTES);
493
494       definition = (String) anAttributes.get(DELETEENTITY_DEFINITION_ATTRIBUTE);
495       selection = XMLReaderTool.getStringAttributeWithDefault(anAttributes, DELETEENTITY_SELECTION_ATTRIBUTE, "");
496     };
497
498     public ProducerNode constructNode() {
499       return new EntityDeletingProducerNode(model, definition, selection);
500     };
501
502     public static class factory implements ProducerNodeBuilderFactory {
503       private EntityAdapterModel model;
504
505       public factory(EntityAdapterModel aModel) {
506         model = aModel;
507       }
508
509       public ProducerNodeBuilder makeBuilder() {
510         return new DeleteEntityProducerNodeBuilder(model);
511       }
512     }
513   }
514
515 ////////////////////////////////////////////////////////////////////////////////
516
517   public static class LoggingProducerNodeBuilder extends AbstractProducerNodeBuilder {
518     private final static String   LOG_MESSAGE_ATTRIBUTE = "message";
519     private final static String   LOG_TYPE_ATTRIBUTE = "type";
520     private final static String[] LOG_REQUIRED_ATTRIBUTES = { LOG_MESSAGE_ATTRIBUTE };
521     private final static String[] LOG_OPTIONAL_ATTRIBUTES = { LOG_TYPE_ATTRIBUTE };
522     private final static String[] LOG_SUBNODES = {};
523
524     private String message;
525     private int type = LoggerWrapper.INFO_MESSAGE;
526
527     public LoggingProducerNodeBuilder() {
528       super(LOG_SUBNODES);
529     }
530
531     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
532       String typeString;
533
534       XMLReaderTool.checkAttributes(anAttributes, LOG_REQUIRED_ATTRIBUTES, LOG_OPTIONAL_ATTRIBUTES);
535
536       message = (String) anAttributes.get(LOG_MESSAGE_ATTRIBUTE);
537       if (anAttributes.containsKey(LOG_TYPE_ATTRIBUTE)) {
538         typeString = ((String) anAttributes.get( LOG_TYPE_ATTRIBUTE ));
539
540         if (typeString.toLowerCase().equals("debug"))
541           type = LoggerWrapper.DEBUG_MESSAGE;
542         else if (typeString.toLowerCase().equals("info"))
543           type = LoggerWrapper.INFO_MESSAGE;
544         else if (typeString.toLowerCase().equals("error"))
545           type = LoggerWrapper.ERROR_MESSAGE;
546         else if (typeString.toLowerCase().equals("warning"))
547           type = LoggerWrapper.WARN_MESSAGE;
548         else if (typeString.toLowerCase().equals("fatal"))
549           type = LoggerWrapper.FATAL_MESSAGE;
550         else
551           throw new ProducerConfigExc("unknown log type: " + typeString + " (allowed are debug, info, warning, error, fatal)");
552       }
553       else
554         type = LoggerWrapper.INFO_MESSAGE;
555     };
556
557     public ProducerNode constructNode() {
558       return new LoggingProducerNode(message, type);
559     };
560   }
561
562 ////////////////////////////////////////////////////////////////////////////////
563
564   public static class FreeQueryProducerNodeBuilder extends AbstractProducerNodeBuilder {
565     private final static String   FREEQUERY_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
566     private final static String   FREEQUERY_LIMIT_ATTRIBUTE = LIMIT_ATTRIBUTE;
567     private final static String   FREEQUERY_QUERY_ATTRIBUTE = "query";
568     private final static String   FREEQUERY_TYPE_ATTRIBUTE = "type";
569     private final static String[] FREEQUERY_REQUIRED_ATTRIBUTES = { KEY_ATTRIBUTE, FREEQUERY_QUERY_ATTRIBUTE };
570     private final static String[] FREEQUERY_OPTIONAL_ATTRIBUTES = { LIMIT_ATTRIBUTE, FREEQUERY_TYPE_ATTRIBUTE };
571     private final static String[] FREEQUERY_SUBNODES = {};
572
573     private String key;
574     private String query;
575     private String limit;
576     private int type;
577
578     public FreeQueryProducerNodeBuilder() {
579       super(FREEQUERY_SUBNODES);
580     }
581
582     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
583       String typeString;
584
585       XMLReaderTool.checkAttributes(anAttributes, FREEQUERY_REQUIRED_ATTRIBUTES, FREEQUERY_OPTIONAL_ATTRIBUTES);
586
587       key = (String) anAttributes.get(FREEQUERY_KEY_ATTRIBUTE);
588       query = (String) anAttributes.get(FREEQUERY_QUERY_ATTRIBUTE);
589       limit = (String) anAttributes.get(FREEQUERY_LIMIT_ATTRIBUTE);
590
591       if (anAttributes.containsKey(FREEQUERY_TYPE_ATTRIBUTE)) {
592         typeString = ((String) anAttributes.get( FREEQUERY_TYPE_ATTRIBUTE ));
593
594         if (typeString.toLowerCase().equals("set"))
595           type = FreeQueryProducerNode.QUERY_TYPE_SET;
596         else if (typeString.toLowerCase().equals("row"))
597           type = FreeQueryProducerNode.QUERY_TYPE_ROW;
598         else if (typeString.toLowerCase().equals("value"))
599           type = FreeQueryProducerNode.QUERY_TYPE_VALUE;
600         else if (typeString.toLowerCase().equals("update"))
601           type = FreeQueryProducerNode.QUERY_TYPE_UPDATE;
602         else
603           throw new ProducerConfigExc("unknown query type: " + typeString + " (allowed are set, row and value)");
604       }
605       else
606         type = FreeQueryProducerNode.QUERY_TYPE_SET;
607     };
608
609     public ProducerNode constructNode() {
610       return new FreeQueryProducerNode(key, query, limit, type);
611     };
612   }
613 ////////////////////////////////////////////////////////////////////////////////
614
615   public static class ExternalDbProducerNodeBuilder extends AbstractProducerNodeBuilder {
616     private final static String   EXTDB_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
617     private final static String   EXTDB_DRIVER_ATTRIBUTE = "driver";
618     private final static String   EXTDB_HOST_ATTRIBUTE = "host";
619     private final static String   EXTDB_PORT_ATTRIBUTE = "port";
620     private final static String   EXTDB_DATABASE_ATTRIBUTE = "database";
621     private final static String   EXTDB_USERNAME_ATTRIBUTE = "username";
622     private final static String   EXTDB_PASSWORD_ATTRIBUTE = "password";
623     private final static String   EXTDB_QUERY_ATTRIBUTE = "query";
624     private final static String   EXTDB_DEFAULT_SUBNODE = "default";
625     private final static String[] EXTDB_REQUIRED_ATTRIBUTES = { KEY_ATTRIBUTE, EXTDB_DRIVER_ATTRIBUTE, EXTDB_HOST_ATTRIBUTE, EXTDB_PORT_ATTRIBUTE, EXTDB_DATABASE_ATTRIBUTE, EXTDB_USERNAME_ATTRIBUTE, EXTDB_PASSWORD_ATTRIBUTE, EXTDB_QUERY_ATTRIBUTE };
626     private final static String[] EXTDB_OPTIONAL_ATTRIBUTES = { };
627     private final static String[] EXTDB_SUBNODES = {EXTDB_DEFAULT_SUBNODE};
628
629     private String key;
630     private String driver;
631     private String host;
632     private String port;
633     private String database;
634     private String username;
635     private String password;
636     private String query;   
637
638
639     public ExternalDbProducerNodeBuilder() {
640       super(EXTDB_SUBNODES);
641     }
642
643     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
644       String typeString;
645
646       XMLReaderTool.checkAttributes(anAttributes, EXTDB_REQUIRED_ATTRIBUTES, EXTDB_OPTIONAL_ATTRIBUTES);
647
648       key = (String) anAttributes.get(EXTDB_KEY_ATTRIBUTE);
649       driver = (String) anAttributes.get(EXTDB_DRIVER_ATTRIBUTE);
650       host = (String) anAttributes.get(EXTDB_HOST_ATTRIBUTE);
651       port = (String) anAttributes.get(EXTDB_PORT_ATTRIBUTE);
652       database = (String) anAttributes.get(EXTDB_DATABASE_ATTRIBUTE);
653       username = (String) anAttributes.get(EXTDB_USERNAME_ATTRIBUTE);
654       password = (String) anAttributes.get(EXTDB_PASSWORD_ATTRIBUTE);
655       query = (String) anAttributes.get(EXTDB_QUERY_ATTRIBUTE);
656
657     };
658
659     public ProducerNode constructNode() {
660       return new ExternalDbProducerNode(key, driver, host, port, database, username, password, query,  getSubNode(EXTDB_DEFAULT_SUBNODE));
661     };
662   }
663
664 ////////////////////////////////////////////////////////////////////////////////
665
666   public static class BundleProducerNodeBuilder extends AbstractProducerNodeBuilder {
667     private final static String   RESOURCEBUNDLE_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
668     private final static String   RESOURCEBUNDLE_BUNDLE_ATTRIBUTE = "bundle";
669     private final static String   RESOURCEBUNDLE_LANGUAGE_ATTRIBUTE = "language";
670     private final static String[] RESOURCEBUNDLE_REQUIRED_ATTRIBUTES = { RESOURCEBUNDLE_KEY_ATTRIBUTE, RESOURCEBUNDLE_BUNDLE_ATTRIBUTE };
671     private final static String[] RESOURCEBUNDLE_OPTIONAL_ATTRIBUTES = { RESOURCEBUNDLE_LANGUAGE_ATTRIBUTE};
672     private final static String[] RESOURCEBUNDLE_SUBNODES = {};
673
674     private String key;
675     private String bundle;
676     private String language;
677
678     public BundleProducerNodeBuilder() {
679       super(RESOURCEBUNDLE_SUBNODES);
680     }
681
682     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
683       XMLReaderTool.checkAttributes(anAttributes, RESOURCEBUNDLE_REQUIRED_ATTRIBUTES, RESOURCEBUNDLE_OPTIONAL_ATTRIBUTES);
684
685       key = (String) anAttributes.get(RESOURCEBUNDLE_KEY_ATTRIBUTE);
686       bundle = (String) anAttributes.get(RESOURCEBUNDLE_BUNDLE_ATTRIBUTE);
687       language = (String) anAttributes.get(RESOURCEBUNDLE_LANGUAGE_ATTRIBUTE);
688     };
689
690     public ProducerNode constructNode() {
691       return new BundleProducerNode(key, bundle, language);
692     };
693   }
694
695 ////////////////////////////////////////////////////////////////////////////////
696
697   public static class FileDateSettingProducerNodeBuilder extends AbstractProducerNodeBuilder {
698     private final static String   FILEDATESETTING_FILE_ATTRIBUTE = "filename";
699     private final static String   FILEDATESETTING_DATE_ATTRIBUTE = "date";
700     private final static String[] FILEDATESETTING_REQUIRED_ATTRIBUTES = { FILEDATESETTING_FILE_ATTRIBUTE, FILEDATESETTING_DATE_ATTRIBUTE };
701     private final static String[] FILEDATESETTING_OPTIONAL_ATTRIBUTES = { };
702     private final static String[] FILEDATESETTING_SUBNODES = {};
703
704     private String fileNameKey;
705     private String dateKey;
706
707     public FileDateSettingProducerNodeBuilder() {
708       super(FILEDATESETTING_SUBNODES);
709     }
710
711     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
712       XMLReaderTool.checkAttributes(anAttributes, FILEDATESETTING_REQUIRED_ATTRIBUTES, FILEDATESETTING_OPTIONAL_ATTRIBUTES);
713
714       fileNameKey = (String) anAttributes.get(FILEDATESETTING_FILE_ATTRIBUTE);
715       dateKey = (String) anAttributes.get(FILEDATESETTING_DATE_ATTRIBUTE);
716     };
717
718     public ProducerNode constructNode() {
719       return new FileDateSettingProducerNode(fileNameKey, dateKey);
720     };
721   }
722
723 ////////////////////////////////////////////////////////////////////////////////
724
725   public static class FileDeletingProducerNodeBuilder extends AbstractProducerNodeBuilder {
726     private final static String   FILEDELETING_FILE_ATTRIBUTE = "filename";
727     private final static String[] FILEDELETING_REQUIRED_ATTRIBUTES = { FILEDELETING_FILE_ATTRIBUTE };
728     private final static String[] FILEDELETING_OPTIONAL_ATTRIBUTES = { };
729     private final static String[] FILEDELETING_SUBNODES = { };
730
731     private String fileNameKey;
732
733     public FileDeletingProducerNodeBuilder() {
734       super(FILEDELETING_SUBNODES);
735     }
736
737     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
738       XMLReaderTool.checkAttributes(anAttributes, FILEDELETING_REQUIRED_ATTRIBUTES, FILEDELETING_OPTIONAL_ATTRIBUTES);
739
740       fileNameKey = (String) anAttributes.get(FILEDELETING_FILE_ATTRIBUTE);
741     };
742
743     public ProducerNode constructNode() {
744       return new FileDeletingProducerNode(fileNameKey);
745     };
746   }
747
748 ////////////////////////////////////////////////////////////////////////////////
749
750   public static class ExecuteProgramProducerNodeBuilder extends AbstractProducerNodeBuilder {
751     private final static String   EXECUTEPROGRAM_COMMAND_ATTRIBUTE = "command";
752     private final static String   EXECUTEPROGRAM_MAXTIME_ATTRIBUTE = "maxduration";
753     private final static String   EXECUTEPROGRAM_RESULTVAR_ATTRIBUTE = "resultvar";
754     private final static String   EXECUTEPROGRAM_RETURNVALUE_ATTRIBUTE = "returnvaluevar";
755     private final static String[] EXECUTEPROGRAM_REQUIRED_ATTRIBUTES = { EXECUTEPROGRAM_COMMAND_ATTRIBUTE };
756     private final static String[] EXECUTEPROGRAM_OPTIONAL_ATTRIBUTES = { EXECUTEPROGRAM_MAXTIME_ATTRIBUTE, EXECUTEPROGRAM_RESULTVAR_ATTRIBUTE };
757     private final static String[] EXECUTEPROGRAM_SUBNODES = {};
758
759     private String command;
760     private String time;
761     private String resultvar;
762     private String returnValueVar;
763
764     public ExecuteProgramProducerNodeBuilder() {
765       super(EXECUTEPROGRAM_SUBNODES);
766     }
767
768     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
769       XMLReaderTool.checkAttributes(anAttributes, EXECUTEPROGRAM_REQUIRED_ATTRIBUTES, EXECUTEPROGRAM_OPTIONAL_ATTRIBUTES);
770
771       command = (String) anAttributes.get(EXECUTEPROGRAM_COMMAND_ATTRIBUTE);
772       time = XMLReaderTool.getStringAttributeWithDefault(anAttributes, EXECUTEPROGRAM_MAXTIME_ATTRIBUTE, null);
773       resultvar = XMLReaderTool.getStringAttributeWithDefault(anAttributes, EXECUTEPROGRAM_RESULTVAR_ATTRIBUTE, null);
774       returnValueVar = XMLReaderTool.getStringAttributeWithDefault(anAttributes, EXECUTEPROGRAM_RETURNVALUE_ATTRIBUTE, null);
775     };
776
777     public ProducerNode constructNode() {
778       return new
779           ExecuteProgramProducerNode(command, time, resultvar, returnValueVar);
780     };
781   }
782
783 ////////////////////////////////////////////////////////////////////////////////
784
785   private final static String   DIRCOPY_SOURCE_ATTRIBUTE = "source";
786   private final static String   DIRCOPY_DESTINATION_ATTRIBUTE = "destination";
787   private final static String[] DIRCOPY_REQUIRED_ATTRIBUTES = { DIRCOPY_SOURCE_ATTRIBUTE, DIRCOPY_DESTINATION_ATTRIBUTE };
788   private final static String[] DIRCOPY_OPTIONAL_ATTRIBUTES = {};
789   private final static String[] DIRCOPY_SUBNODES = {};
790
791   public static class DirCopyProducerNodeBuilder extends AbstractProducerNodeBuilder {
792     private String source;
793     private String destination;
794     private File sourceBasePath;
795     private File destinationBasePath;
796
797     public DirCopyProducerNodeBuilder(File aSourceBasePath, File aDestinationBasePath) {
798       super(DIRCOPY_SUBNODES);
799
800       sourceBasePath = aSourceBasePath;
801       destinationBasePath = aDestinationBasePath;
802     }
803
804     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
805       XMLReaderTool.checkAttributes(anAttributes, DIRCOPY_REQUIRED_ATTRIBUTES, DIRCOPY_OPTIONAL_ATTRIBUTES);
806
807       source = (String) anAttributes.get(DIRCOPY_SOURCE_ATTRIBUTE);
808       destination = (String) anAttributes.get(DIRCOPY_DESTINATION_ATTRIBUTE);
809     };
810
811     public ProducerNode constructNode() {
812       return new DirCopyingProducerNode(sourceBasePath, destinationBasePath, source, destination);
813     };
814
815     public static class factory implements ProducerNodeBuilderFactory {
816       private File sourceBasePath;
817       private File destinationBasePath;
818
819       public factory(File aSourceBasePath, File aDestinationBasePath) {
820         sourceBasePath = aSourceBasePath;
821         destinationBasePath = aDestinationBasePath;
822       }
823
824       public ProducerNodeBuilder makeBuilder() {
825         return new DirCopyProducerNodeBuilder(sourceBasePath, destinationBasePath);
826       }
827     }
828   }
829
830 ////////////////////////////////////////////////////////////////////////////////
831
832   public static class GeneratingProducerNodeBuilder extends AbstractProducerNodeBuilder {
833     private final static String   GENERATION_GENERATOR_ATTRIBUTE = "generator";
834     private final static String   GENERATION_DESTINATION_ATTRIBUTE = "destination";
835     private final static String   GENERATION_PARAMETERS_ATTRIBUTE = "parameters";
836     private final static String[] GENERATION_REQUIRED_ATTRIBUTES = { GENERATION_GENERATOR_ATTRIBUTE, GENERATION_DESTINATION_ATTRIBUTE };
837     private final static String[] GENERATION_OPTIONAL_ATTRIBUTES = { GENERATION_PARAMETERS_ATTRIBUTE};
838     private final static String[] GENERATION_SUBNODES = {};
839
840     private String generator;
841     private String destination;
842     private String parameters;
843     private Generator.Library generatorLibrary;
844     private WriterEngine writerEngine;
845
846     public GeneratingProducerNodeBuilder(Generator.Library aGeneratorLibrary, WriterEngine aWriterEngine) {
847       super(GENERATION_SUBNODES);
848
849       writerEngine = aWriterEngine;
850       generatorLibrary = aGeneratorLibrary;
851     }
852
853     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
854       XMLReaderTool.checkAttributes(anAttributes, GENERATION_REQUIRED_ATTRIBUTES, GENERATION_OPTIONAL_ATTRIBUTES);
855
856       generator = (String) anAttributes.get(GENERATION_GENERATOR_ATTRIBUTE);
857       destination = (String) anAttributes.get(GENERATION_DESTINATION_ATTRIBUTE);
858       parameters = XMLReaderTool.getStringAttributeWithDefault(anAttributes, GENERATION_PARAMETERS_ATTRIBUTE, "" );
859     };
860
861     public ProducerNode constructNode() {
862       return new GeneratingProducerNode(generatorLibrary, writerEngine, generator, destination, parameters);
863     };
864
865     public static class factory implements ProducerNodeBuilderFactory {
866       private Generator.Library generatorLibrary;
867       private WriterEngine writerEngine;
868
869       public factory(Generator.Library aGeneratorLibrary, WriterEngine aWriterEngine) {
870         writerEngine = aWriterEngine;
871         generatorLibrary = aGeneratorLibrary;
872       }
873
874       public ProducerNodeBuilder makeBuilder() {
875         return new GeneratingProducerNodeBuilder(generatorLibrary, writerEngine);
876       }
877     }
878   }
879
880 ////////////////////////////////////////////////////////////////////////////////
881
882   public static class BatchingProducerNodeBuilder extends AbstractProducerNodeBuilder {
883
884     private final static String   BATCHER_DATAKEY_ATTRIBUTE = KEY_ATTRIBUTE;
885     private final static String   BATCHER_INFOKEY_ATTRIBUTE = "infokey";
886     private final static String   BATCHER_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
887     private final static String   BATCHER_SELECTION_ATTRIBUTE = SELECTION_ATTRIBUTE;
888     private final static String   BATCHER_ORDER_ATTRIBUTE = ORDER_ATTRIBUTE;
889
890     private final static String   BATCHER_BATCHSIZE_ATTRIBUTE = "batchsize";
891     private final static String   BATCHER_MINBATCHSIZE_ATTRIBUTE = "minbatchsize";
892     private final static String   BATCHER_SKIP_ATTRIBUTE = SKIP_ATTRIBUTE;
893
894     private final static String   BATCHER_PROCESS_ATTRIBUTE = "process";
895     private final static String   BATCHER_EXTRATABLES_ATTRIBUTE = EXTRA_TABLES_ATTRIBUTE;
896
897     private final static String   BATCHER_BATCH_SUBNODE = "batches";
898     private final static String   BATCHER_BATCHLIST_SUBNODE = "batchlist";
899     private final static String[] BATCHER_REQUIRED_ATTRIBUTES = { BATCHER_DATAKEY_ATTRIBUTE, BATCHER_INFOKEY_ATTRIBUTE, BATCHER_DEFINITION_ATTRIBUTE, BATCHER_BATCHSIZE_ATTRIBUTE };
900     private final static String[] BATCHER_OPTIONAL_ATTRIBUTES = { BATCHER_SELECTION_ATTRIBUTE, BATCHER_ORDER_ATTRIBUTE, BATCHER_MINBATCHSIZE_ATTRIBUTE, BATCHER_SKIP_ATTRIBUTE, BATCHER_PROCESS_ATTRIBUTE, BATCHER_EXTRATABLES_ATTRIBUTE };
901     private final static String[] BATCHER_SUBNODES = { BATCHER_BATCH_SUBNODE, BATCHER_BATCHLIST_SUBNODE };
902
903     private EntityAdapterModel model;
904     private String batchDataKey;
905     private String batchInfoKey;
906     private String mainTablePrefix;
907     private String extraTables;
908     private String definition;
909     private String selection;
910     private String order;
911     private String batchSize;
912     private String minBatchSize;
913     private String skip;
914     private String process;
915
916     public BatchingProducerNodeBuilder(EntityAdapterModel aModel) {
917       super(BATCHER_SUBNODES);
918
919       model = aModel;
920     }
921
922     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
923       XMLReaderTool.checkAttributes(anAttributes, BATCHER_REQUIRED_ATTRIBUTES, BATCHER_OPTIONAL_ATTRIBUTES);
924
925       batchDataKey = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DATAKEY_ATTRIBUTE, "data" );
926       batchInfoKey = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_INFOKEY_ATTRIBUTE, "info" );
927       definition = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DEFINITION_ATTRIBUTE, "" );
928       selection = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SELECTION_ATTRIBUTE, "" );
929       order = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_ORDER_ATTRIBUTE, "" );
930
931       batchSize = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_BATCHSIZE_ATTRIBUTE, "20" );
932       minBatchSize = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_MINBATCHSIZE_ATTRIBUTE, "0" );
933       skip = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SKIP_ATTRIBUTE, "0" );
934       process = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_PROCESS_ATTRIBUTE, "-1" );
935
936       extraTables = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_EXTRATABLES_ATTRIBUTE,"");
937
938       List parts = StringRoutines.splitString(definition.trim()," ");
939       if (parts.size()>0) definition=(String)parts.get(0);
940       if (parts.size()>1) mainTablePrefix=(String)parts.get(1);
941     };
942
943     public ProducerNode constructNode() {
944       return new EntityBatchingProducerNode(
945           batchDataKey,
946           batchInfoKey,
947           model,
948           mainTablePrefix,
949           extraTables,
950           definition,
951           selection,
952           order,
953           batchSize,
954           minBatchSize,
955           skip,
956           process,
957           getSubNode( BATCHER_BATCH_SUBNODE ),
958           getSubNode( BATCHER_BATCHLIST_SUBNODE )
959       );
960     };
961
962     public static class factory implements ProducerNodeBuilderFactory {
963       private EntityAdapterModel model;
964
965       public factory(EntityAdapterModel aModel) {
966         model = aModel;
967       }
968
969       public ProducerNodeBuilder makeBuilder() {
970         return new BatchingProducerNodeBuilder(model);
971       }
972     }
973   }
974
975 ////////////////////////////////////////////////////////////////////////////////
976
977   public static class ConditionalProducerNodeBuilder extends AbstractProducerNodeBuilder {
978     private final static String   IF_CONDITION_ATTRIBUTE = "condition";
979
980     private final static String   IF_TRUE_SUBNODE = "then";
981     private final static String   IF_FALSE_SUBNODE = "else";
982     private final static String[] IF_REQUIRED_ATTRIBUTES = { IF_CONDITION_ATTRIBUTE };
983     private final static String[] IF_OPTIONAL_ATTRIBUTES = {  };
984     private final static String[] IF_SUBNODES = { IF_TRUE_SUBNODE, IF_FALSE_SUBNODE };
985
986     private String condition;
987
988     public ConditionalProducerNodeBuilder() {
989       super(IF_SUBNODES);
990     }
991
992     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
993       XMLReaderTool.checkAttributes(anAttributes, IF_REQUIRED_ATTRIBUTES, IF_OPTIONAL_ATTRIBUTES);
994
995       condition = (String) anAttributes.get( IF_CONDITION_ATTRIBUTE );
996     };
997
998     public ProducerNode constructNode() {
999       return new ConditionalProducerNode(
1000           condition,
1001           getSubNode( IF_TRUE_SUBNODE ),
1002           getSubNode( IF_FALSE_SUBNODE )
1003       );
1004     };
1005
1006   }
1007
1008 ////////////////////////////////////////////////////////////////////////////////
1009
1010   public static class RSSProducerNodeBuilder extends AbstractProducerNodeBuilder {
1011     private final static String   RSS_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
1012     private final static String   RSS_URL_ATTRIBUTE = URL_ATTRIBUTE;
1013     private final static String   RSS_ENCODING_ATTRIBUTE = "encoding";
1014     private final static String   RSS_VERSION_ATTRIBUTE = "version";
1015
1016     private final static String[] RSS_REQUIRED_ATTRIBUTES = { RSS_KEY_ATTRIBUTE, RSS_URL_ATTRIBUTE };
1017     private final static String[] RSS_OPTIONAL_ATTRIBUTES = { RSS_VERSION_ATTRIBUTE, RSS_ENCODING_ATTRIBUTE };
1018     private final static String[] RSS_SUBNODES = {  };
1019
1020     private String key;
1021     private String url;
1022     private String version;
1023     private String encoding;
1024
1025     public RSSProducerNodeBuilder() {
1026       super(RSS_SUBNODES);
1027     }
1028
1029     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
1030       XMLReaderTool.checkAttributes(anAttributes, RSS_REQUIRED_ATTRIBUTES, RSS_OPTIONAL_ATTRIBUTES);
1031
1032       key = (String) anAttributes.get( RSS_KEY_ATTRIBUTE );
1033       url = (String) anAttributes.get( RSS_URL_ATTRIBUTE );
1034       version = XMLReaderTool.getStringAttributeWithDefault(anAttributes, RSS_VERSION_ATTRIBUTE, "1.0");
1035       encoding = XMLReaderTool.getStringAttributeWithDefault(anAttributes, RSS_ENCODING_ATTRIBUTE, null);
1036     };
1037
1038     public ProducerNode constructNode() {
1039       return new RSSProducerNode(key, url, version, encoding);
1040     };
1041   }
1042
1043 ////////////////////////////////////////////////////////////////////////////////
1044
1045   public static class RDFAggregatorProducerNodeBuilder extends AbstractProducerNodeBuilder {
1046     private final static String   RDF_AGGREGATOR_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
1047     private final static String   RDF_AGGREGATOR_SOURCE_ATTRIBUTE = "source";
1048     private final static String   RDF_AGGREGATOR_ORDER_ATTRIBUTE = ORDER_ATTRIBUTE;
1049     private final static String   RDF_AGGREGATOR_FILTER_ATTRIBUTE = "filter";
1050
1051     private final static String[] RDF_AGGREGATOR_REQUIRED_ATTRIBUTES = { RDF_AGGREGATOR_KEY_ATTRIBUTE, RDF_AGGREGATOR_SOURCE_ATTRIBUTE };
1052     private final static String[] RDF_AGGREGATOR_OPTIONAL_ATTRIBUTES = { RDF_AGGREGATOR_ORDER_ATTRIBUTE, RDF_AGGREGATOR_FILTER_ATTRIBUTE };
1053     private final static String[] RDF_AGGREGATOR_SUBNODES = {  };
1054
1055     private String key;
1056     private String source;
1057     private String order;
1058     private String filter;
1059
1060     public RDFAggregatorProducerNodeBuilder() {
1061       super(RDF_AGGREGATOR_SUBNODES);
1062     }
1063
1064     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
1065       XMLReaderTool.checkAttributes(anAttributes, RDF_AGGREGATOR_REQUIRED_ATTRIBUTES, RDF_AGGREGATOR_OPTIONAL_ATTRIBUTES);
1066
1067       key = (String) anAttributes.get( RDF_AGGREGATOR_KEY_ATTRIBUTE );
1068       source = (String) anAttributes.get( RDF_AGGREGATOR_SOURCE_ATTRIBUTE );
1069       order = XMLReaderTool.getStringAttributeWithDefault(anAttributes, RDF_AGGREGATOR_SOURCE_ATTRIBUTE, "");
1070       filter = XMLReaderTool.getStringAttributeWithDefault(anAttributes, RDF_AGGREGATOR_FILTER_ATTRIBUTE, "");
1071     };
1072
1073     public ProducerNode constructNode() {
1074       return new RDFAggregatorProducerNode(key, source, order, filter);
1075     };
1076   }
1077
1078 ////////////////////////////////////////////////////////////////////////////////
1079
1080   public static class ScriptedProducerParameterNodeBuilder implements ProducerNodeBuilder {
1081     private String parameterName;
1082     private String scriptedNodeName;
1083
1084     public ScriptedProducerParameterNodeBuilder(String aScriptedNodeName, String aParameterName) {
1085       parameterName = aParameterName;
1086       scriptedNodeName = aScriptedNodeName;
1087     }
1088
1089     public void setSubNode(String aName, ProducerNode aNode) {
1090     };
1091
1092     public Set getAvailableSubNodes() {
1093       return new HashSet();
1094     };
1095
1096     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
1097       if (!anAttributes.isEmpty())
1098         throw new ProducerConfigExc("No parameters allowed here");
1099     };
1100
1101     public ProducerNode constructNode() {
1102       return new ScriptedProducerNodeDefinition.NodeParameterProducerNode(scriptedNodeName, parameterName);
1103     };
1104   }
1105
1106 ////////////////////////////////////////////////////////////////////////////////
1107
1108   public static class ScriptedProducerNodeBuilder implements ProducerNodeBuilder {
1109     private ScriptedProducerNodeDefinition definition;
1110     private Map nodeParameterValues;
1111     private Map integerParameterValues;
1112     private Map stringParameterValues;
1113
1114     public ScriptedProducerNodeBuilder(ScriptedProducerNodeDefinition aDefinition) {
1115       definition = aDefinition;
1116
1117       stringParameterValues = new HashMap();
1118       stringParameterValues.putAll(definition.getStringParameters());
1119
1120       integerParameterValues = new HashMap();
1121       integerParameterValues.putAll(definition.getIntegerParameters());
1122
1123       nodeParameterValues = new HashMap();
1124     }
1125
1126     public void setSubNode(String aName, ProducerNode aNode) {
1127       nodeParameterValues.put(aName, aNode);
1128     };
1129
1130     public Set getAvailableSubNodes() {
1131       return definition.getNodeParameters();
1132     };
1133
1134     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
1135       XMLReaderTool.checkAttributeSet(anAttributes.keySet(), definition.getRequiredAttributes(), definition.getOptionalAttributes());
1136
1137       Iterator i = anAttributes.entrySet().iterator();
1138       while (i.hasNext()) {
1139         Map.Entry entry = (Map.Entry) i.next();
1140
1141         if (definition.getIntegerParameters().keySet().contains(entry.getKey()))
1142           integerParameterValues.put(entry.getKey(), entry.getValue());
1143         else
1144           stringParameterValues.put(entry.getKey(), entry.getValue());
1145       }
1146     };
1147
1148     public ProducerNode constructNode() {
1149       return new ScriptedProducerNode(definition, stringParameterValues, integerParameterValues, nodeParameterValues);
1150     };
1151
1152     public static class factory implements ProducerNodeBuilderFactory {
1153       private ScriptedProducerNodeDefinition definition;
1154
1155       public factory(ScriptedProducerNodeDefinition aDefinition) {
1156         definition = aDefinition;
1157       }
1158
1159       public ProducerNodeBuilder makeBuilder() {
1160         return new ScriptedProducerNodeBuilder(definition);
1161       }
1162     }
1163   }
1164 }