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