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