b3024f196fad17002d2b0da46a9437eb7a45f3e1
[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.xml.*;
67 import mir.util.xml.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 subNodes;
106     private Set availableSubnodes;
107
108     public AbstractProducerNodeBuilder(String anAvailableSubNodes[]) {
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, XMLParserExc {
157       mir.util.xml.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, XMLParserExc {
180       mir.util.xml.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_EXTRATABLES_ATTRIBUTE = "extratables";
203     private final static String[] ENUMERATION_LIST_REQUIRED_ATTRIBUTES = { ENUMERATION_LIST_ATTRIBUTE, ENUMERATION_KEY_ATTRIBUTE };
204     private final static String[] ENUMERATION_LIST_OPTIONAL_ATTRIBUTES = { };
205     private final static String[] ENUMERATION_QUERY_REQUIRED_ATTRIBUTES = { ENUMERATION_DEFINITION_ATTRIBUTE, ENUMERATION_KEY_ATTRIBUTE };
206     private final static String[] ENUMERATION_QUERY_OPTIONAL_ATTRIBUTES = { ENUMERATION_SELECTION_ATTRIBUTE, ENUMERATION_ORDER_ATTRIBUTE, ENUMERATION_LIMIT_ATTRIBUTE, ENUMERATION_SKIP_ATTRIBUTE,ENUMERATION_EXTRATABLES_ATTRIBUTE};
207     private final static String[] ENUMERATION_SUBNODES = {ENUMERATION_DEFAULT_SUBNODE};
208
209     private String key;
210     private String definition;
211     private String mainTablePrefix;
212     private List   extraTables;
213     private String list;
214     private String selection;
215     private String order;
216     private String limit;
217     private String skip;
218     private EntityAdapterModel model;
219
220     public EnumeratingProducerNodeBuilder(EntityAdapterModel aModel) {
221       super(ENUMERATION_SUBNODES);
222
223       model = aModel;
224     }
225
226     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc  {
227       definition = (String) anAttributes.get(ENUMERATION_DEFINITION_ATTRIBUTE);
228       list = (String) anAttributes.get(ENUMERATION_LIST_ATTRIBUTE);
229
230       if ((list==null && definition==null) || (list!=null && definition!=null))
231         throw new ProducerConfigExc("Exactly one of "+ENUMERATION_DEFINITION_ATTRIBUTE+" and "+ENUMERATION_LIST_ATTRIBUTE+" must be set");
232
233
234       if (list!=null)
235         mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, ENUMERATION_LIST_REQUIRED_ATTRIBUTES, ENUMERATION_LIST_OPTIONAL_ATTRIBUTES);
236       if (definition!=null)
237         mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, ENUMERATION_QUERY_REQUIRED_ATTRIBUTES, ENUMERATION_QUERY_OPTIONAL_ATTRIBUTES);
238
239
240       key = (String) anAttributes.get(ENUMERATION_KEY_ATTRIBUTE);
241       selection = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_SELECTION_ATTRIBUTE, "");
242       order = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_ORDER_ATTRIBUTE, "");
243       limit = (String) anAttributes.get(ENUMERATION_LIMIT_ATTRIBUTE);
244       skip = (String) anAttributes.get(ENUMERATION_SKIP_ATTRIBUTE);
245       extraTables = StringRoutines.splitString(mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_EXTRATABLES_ATTRIBUTE,"").trim(), ",");
246       if (definition!=null) {
247         List parts = StringRoutines.splitString(definition.trim(), " ");
248         if (parts.size() > 0)
249           definition = (String) parts.get(0);
250         if (parts.size() > 1)
251           mainTablePrefix = (String) parts.get(1);
252       }
253     };
254
255     public ProducerNode constructNode() {
256       if (definition!=null)
257         return new EntityEnumeratingProducerNode(key, model, mainTablePrefix, extraTables, definition, selection, order, limit, skip, getSubNode(ENUMERATION_DEFAULT_SUBNODE ));
258       else
259         return new ListEnumeratingProducerNode(key, list, getSubNode(ENUMERATION_DEFAULT_SUBNODE ));
260     };
261
262     public static class factory implements ProducerNodeBuilderFactory {
263       private EntityAdapterModel model;
264
265       public factory(EntityAdapterModel aModel) {
266         model = aModel;
267       }
268
269       public ProducerNodeBuilder makeBuilder() {
270         return new EnumeratingProducerNodeBuilder(model);
271       }
272     }
273   }
274
275 ////////////////////////////////////////////////////////////////////////////////
276
277   public static class UpdateEntityProducerNodeBuilder extends AbstractProducerNodeBuilder {
278     private final static String   UPDATE_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
279     private final static String   UPDATE_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
280     private final static String[] UPDATE_SUBNODES = {};
281
282     private String key;
283     private String definition;
284     private Map fieldValues;
285
286     private EntityAdapterModel model;
287
288     public UpdateEntityProducerNodeBuilder(EntityAdapterModel aModel) {
289       super(UPDATE_SUBNODES);
290
291       model = aModel;
292       fieldValues = new HashMap();
293     }
294
295     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc  {
296       key = (String) anAttributes.get(UPDATE_KEY_ATTRIBUTE);
297
298       if (key == null)
299         throw new XMLParserExc("missing required attribute '" + UPDATE_KEY_ATTRIBUTE + "'" );
300       definition = (String) anAttributes.get(UPDATE_DEFINITION_ATTRIBUTE);
301
302       fieldValues.putAll(anAttributes);
303       fieldValues.remove(UPDATE_KEY_ATTRIBUTE);
304       fieldValues.remove(UPDATE_DEFINITION_ATTRIBUTE);
305     };
306
307     public ProducerNode constructNode() {
308       return new EntityModifyingProducerNode(model, false, definition, key, fieldValues);
309     };
310
311     public static class factory implements ProducerNodeBuilderFactory {
312       private EntityAdapterModel model;
313
314       public factory(EntityAdapterModel aModel) {
315         model = aModel;
316       }
317
318       public ProducerNodeBuilder makeBuilder() {
319         return new UpdateEntityProducerNodeBuilder(model);
320       }
321     }
322   }
323
324 ////////////////////////////////////////////////////////////////////////////////
325
326   public static class CreateEntityProducerNodeBuilder extends AbstractProducerNodeBuilder {
327     private final static String   CREATEENTITY_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
328     private final static String   CREATEENTITY_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
329     private final static String[] CREATEENTITY_SUBNODES = {};
330
331     private String key;
332     private String definition;
333     private Map fieldValues;
334
335     private EntityAdapterModel model;
336
337     public CreateEntityProducerNodeBuilder(EntityAdapterModel aModel) {
338       super(CREATEENTITY_SUBNODES);
339
340       model = aModel;
341       fieldValues = new HashMap();
342     }
343
344     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc  {
345       key = (String) anAttributes.get(CREATEENTITY_KEY_ATTRIBUTE);
346       definition = (String) anAttributes.get(CREATEENTITY_DEFINITION_ATTRIBUTE);
347
348       if (key == null)
349         throw new XMLParserExc("missing required attribute '" + CREATEENTITY_KEY_ATTRIBUTE + "'" );
350       if (definition == null)
351         throw new XMLParserExc("missing required attribute '" + CREATEENTITY_DEFINITION_ATTRIBUTE + "'" );
352
353       fieldValues.putAll(anAttributes);
354       fieldValues.remove(CREATEENTITY_KEY_ATTRIBUTE);
355       fieldValues.remove(CREATEENTITY_DEFINITION_ATTRIBUTE);
356     };
357
358     public ProducerNode constructNode() {
359       return new EntityModifyingProducerNode(model, true, definition, key, fieldValues);
360     };
361
362     public static class factory implements ProducerNodeBuilderFactory {
363       private EntityAdapterModel model;
364
365       public factory(EntityAdapterModel aModel) {
366         model = aModel;
367       }
368
369       public ProducerNodeBuilder makeBuilder() {
370         return new CreateEntityProducerNodeBuilder(model);
371       }
372     }
373   }
374
375 ////////////////////////////////////////////////////////////////////////////////
376
377   public static class LoopProducerNodeBuilder extends AbstractProducerNodeBuilder {
378     private final static String   LOOP_CONDITION_ATTRIBUTE = "condition";
379     private final static String   LOOP_LIMIT_ATTRIBUTE = LIMIT_ATTRIBUTE;
380     private final static String   LOOP_DEFAULT_SUBNODE = "default";
381     private final static String[] LOOP_REQUIRED_ATTRIBUTES = { LOOP_CONDITION_ATTRIBUTE };
382     private final static String[] LOOP_OPTIONAL_ATTRIBUTES = { LOOP_LIMIT_ATTRIBUTE };
383     private final static String[] LOOP_SUBNODES = {LOOP_DEFAULT_SUBNODE};
384
385     private String condition;
386     private String limit;
387
388     public LoopProducerNodeBuilder() {
389       super(LOOP_SUBNODES);
390     }
391
392     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc  {
393       mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, LOOP_REQUIRED_ATTRIBUTES, LOOP_OPTIONAL_ATTRIBUTES);
394
395       condition = (String) anAttributes.get(LOOP_CONDITION_ATTRIBUTE);
396       limit = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, LOOP_LIMIT_ATTRIBUTE, "");
397     };
398
399     public ProducerNode constructNode() {
400       return new LoopProducerNode(condition, limit, getSubNode( LOOP_DEFAULT_SUBNODE ));
401     };
402   }
403
404 ////////////////////////////////////////////////////////////////////////////////
405
406   public static class ListProducerNodeBuilder extends AbstractProducerNodeBuilder {
407     private final static String   LIST_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
408     private final static String   LIST_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
409     private final static String   LIST_SELECTION_ATTRIBUTE = SELECTION_ATTRIBUTE;
410     private final static String   LIST_EXTRATABLES_ATTRIBUTE = "extratables";
411     private final static String   LIST_ORDER_ATTRIBUTE = ORDER_ATTRIBUTE;
412     private final static String   LIST_LIMIT_ATTRIBUTE = LIMIT_ATTRIBUTE;
413     private final static String   LIST_SKIP_ATTRIBUTE = SKIP_ATTRIBUTE;
414     private final static String[] LIST_REQUIRED_ATTRIBUTES = { LIST_KEY_ATTRIBUTE, LIST_DEFINITION_ATTRIBUTE };
415     private final static String[] LIST_OPTIONAL_ATTRIBUTES = { LIST_SELECTION_ATTRIBUTE, LIST_ORDER_ATTRIBUTE, LIST_SKIP_ATTRIBUTE, LIST_LIMIT_ATTRIBUTE,LIST_EXTRATABLES_ATTRIBUTE};
416     private final static String[] LIST_SUBNODES = {};
417
418     private String key;
419     private String definition;
420     private String mainTablePrefix;
421     private List   extraTables;
422     private String selection;
423     private String order;
424     private String limit;
425     private String skip;
426     private EntityAdapterModel model;
427
428     public ListProducerNodeBuilder(EntityAdapterModel aModel) {
429       super(LIST_SUBNODES);
430
431       model = aModel;
432     }
433
434     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
435       mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, LIST_REQUIRED_ATTRIBUTES, LIST_OPTIONAL_ATTRIBUTES);
436
437       key = (String) anAttributes.get(LIST_KEY_ATTRIBUTE);
438       definition = (String) anAttributes.get(LIST_DEFINITION_ATTRIBUTE);
439       selection = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_SELECTION_ATTRIBUTE, "");
440       order = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_ORDER_ATTRIBUTE, "");
441       limit = (String) anAttributes.get(LIST_LIMIT_ATTRIBUTE);
442       skip = (String) anAttributes.get(LIST_SKIP_ATTRIBUTE);
443       extraTables = StringRoutines.splitString(mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_EXTRATABLES_ATTRIBUTE,"").trim(), ",");
444       List parts = StringRoutines.splitString(definition.trim()," ");
445       if (parts.size()>0) definition=(String)parts.get(0);
446       if (parts.size()>1) mainTablePrefix=(String)parts.get(1);
447
448     };
449
450     public ProducerNode constructNode() {
451       return new EntityListProducerNode(key, model, mainTablePrefix, extraTables, definition, selection, order, limit, skip, null );
452     };
453
454     public static class factory implements ProducerNodeBuilderFactory {
455       private EntityAdapterModel model;
456
457       public factory(EntityAdapterModel aModel) {
458         model = aModel;
459       }
460
461       public ProducerNodeBuilder makeBuilder() {
462         return new ListProducerNodeBuilder(model);
463       }
464     }
465   }
466
467 ////////////////////////////////////////////////////////////////////////////////
468
469   public static class DeleteEntityProducerNodeBuilder extends AbstractProducerNodeBuilder {
470     private final static String   DELETEENTITY_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
471     private final static String   DELETEENTITY_SELECTION_ATTRIBUTE = SELECTION_ATTRIBUTE;
472     private final static String[] DELETEENTITY_REQUIRED_ATTRIBUTES = { DELETEENTITY_SELECTION_ATTRIBUTE, DELETEENTITY_DEFINITION_ATTRIBUTE };
473     private final static String[] DELETEENTITY_OPTIONAL_ATTRIBUTES = { };
474     private final static String[] DELETEENTITY_SUBNODES = {};
475
476     private String definition;
477     private String selection;
478
479     private EntityAdapterModel model;
480
481     public DeleteEntityProducerNodeBuilder(EntityAdapterModel aModel) {
482       super(DELETEENTITY_SUBNODES);
483
484       model = aModel;
485     }
486
487     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
488       mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, DELETEENTITY_REQUIRED_ATTRIBUTES, DELETEENTITY_OPTIONAL_ATTRIBUTES);
489
490       definition = (String) anAttributes.get(DELETEENTITY_DEFINITION_ATTRIBUTE);
491       selection = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, DELETEENTITY_SELECTION_ATTRIBUTE, "");
492     };
493
494     public ProducerNode constructNode() {
495       return new EntityDeletingProducerNode(model, definition, selection);
496     };
497
498     public static class factory implements ProducerNodeBuilderFactory {
499       private EntityAdapterModel model;
500
501       public factory(EntityAdapterModel aModel) {
502         model = aModel;
503       }
504
505       public ProducerNodeBuilder makeBuilder() {
506         return new DeleteEntityProducerNodeBuilder(model);
507       }
508     }
509   }
510
511 ////////////////////////////////////////////////////////////////////////////////
512
513   public static class LoggingProducerNodeBuilder extends AbstractProducerNodeBuilder {
514     private final static String   LOG_MESSAGE_ATTRIBUTE = "message";
515     private final static String   LOG_TYPE_ATTRIBUTE = "type";
516     private final static String[] LOG_REQUIRED_ATTRIBUTES = { LOG_MESSAGE_ATTRIBUTE };
517     private final static String[] LOG_OPTIONAL_ATTRIBUTES = { LOG_TYPE_ATTRIBUTE };
518     private final static String[] LOG_SUBNODES = {};
519
520     private String message;
521     private int type = LoggerWrapper.INFO_MESSAGE;
522
523     public LoggingProducerNodeBuilder() {
524       super(LOG_SUBNODES);
525     }
526
527     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
528       String typeString;
529
530       mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, LOG_REQUIRED_ATTRIBUTES, LOG_OPTIONAL_ATTRIBUTES);
531
532       message = (String) anAttributes.get(LOG_MESSAGE_ATTRIBUTE);
533       if (anAttributes.containsKey(LOG_TYPE_ATTRIBUTE)) {
534         typeString = ((String) anAttributes.get( LOG_TYPE_ATTRIBUTE ));
535
536         if (typeString.toLowerCase().equals("debug"))
537           type = LoggerWrapper.DEBUG_MESSAGE;
538         else if (typeString.toLowerCase().equals("info"))
539           type = LoggerWrapper.INFO_MESSAGE;
540         else if (typeString.toLowerCase().equals("error"))
541           type = LoggerWrapper.ERROR_MESSAGE;
542         else if (typeString.toLowerCase().equals("warning"))
543           type = LoggerWrapper.WARN_MESSAGE;
544         else if (typeString.toLowerCase().equals("fatal"))
545           type = LoggerWrapper.FATAL_MESSAGE;
546         else
547           throw new ProducerConfigExc("unknown log type: " + typeString + " (allowed are debug, info, warning, error, fatal)");
548       }
549       else
550         type = LoggerWrapper.INFO_MESSAGE;
551     };
552
553     public ProducerNode constructNode() {
554       return new LoggingProducerNode(message, type);
555     };
556   }
557
558 ////////////////////////////////////////////////////////////////////////////////
559
560   public static class FreeQueryProducerNodeBuilder extends AbstractProducerNodeBuilder {
561     private final static String   FREEQUERY_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
562     private final static String   FREEQUERY_LIMIT_ATTRIBUTE = LIMIT_ATTRIBUTE;
563     private final static String   FREEQUERY_QUERY_ATTRIBUTE = "query";
564     private final static String   FREEQUERY_TYPE_ATTRIBUTE = "type";
565     private final static String[] FREEQUERY_REQUIRED_ATTRIBUTES = { KEY_ATTRIBUTE, FREEQUERY_QUERY_ATTRIBUTE };
566     private final static String[] FREEQUERY_OPTIONAL_ATTRIBUTES = { LIMIT_ATTRIBUTE, FREEQUERY_TYPE_ATTRIBUTE };
567     private final static String[] FREEQUERY_SUBNODES = {};
568
569     private String key;
570     private String query;
571     private String limit;
572     private int type;
573
574     public FreeQueryProducerNodeBuilder() {
575       super(FREEQUERY_SUBNODES);
576     }
577
578     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
579       String typeString;
580
581       mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, FREEQUERY_REQUIRED_ATTRIBUTES, FREEQUERY_OPTIONAL_ATTRIBUTES);
582
583       key = (String) anAttributes.get(FREEQUERY_KEY_ATTRIBUTE);
584       query = (String) anAttributes.get(FREEQUERY_QUERY_ATTRIBUTE);
585       limit = (String) anAttributes.get(FREEQUERY_LIMIT_ATTRIBUTE);
586
587       if (anAttributes.containsKey(FREEQUERY_TYPE_ATTRIBUTE)) {
588         typeString = ((String) anAttributes.get( FREEQUERY_TYPE_ATTRIBUTE ));
589
590         if (typeString.toLowerCase().equals("set"))
591           type = FreeQueryProducerNode.QUERY_TYPE_SET;
592         else if (typeString.toLowerCase().equals("row"))
593           type = FreeQueryProducerNode.QUERY_TYPE_ROW;
594         else if (typeString.toLowerCase().equals("value"))
595           type = FreeQueryProducerNode.QUERY_TYPE_VALUE;
596         else if (typeString.toLowerCase().equals("update"))
597           type = FreeQueryProducerNode.QUERY_TYPE_UPDATE;
598         else
599           throw new ProducerConfigExc("unknown query type: " + typeString + " (allowed are set, row and value)");
600       }
601       else
602         type = FreeQueryProducerNode.QUERY_TYPE_SET;
603     };
604
605     public ProducerNode constructNode() {
606       return new FreeQueryProducerNode(key, query, limit, type);
607     };
608   }
609
610 ////////////////////////////////////////////////////////////////////////////////
611
612   public static class ResourceBundleProducerNodeBuilder extends AbstractProducerNodeBuilder {
613     private final static String   RESOURCEBUNDLE_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
614     private final static String   RESOURCEBUNDLE_BUNDLE_ATTRIBUTE = "bundle";
615     private final static String   RESOURCEBUNDLE_LANGUAGE_ATTRIBUTE = "language";
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, XMLParserExc {
629       mir.util.xml.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, XMLParserExc {
658       mir.util.xml.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, XMLParserExc {
684       mir.util.xml.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_TIME_ATTRIBUTE = "time";
699     private final static String[] SCRIPT_REQUIRED_ATTRIBUTES = { SCRIPT_COMMAND_ATTRIBUTE };
700     private final static String[] SCRIPT_OPTIONAL_ATTRIBUTES = {};
701     private final static String[] SCRIPT_SUBNODES = {};
702
703     private String command;
704     private String time;
705
706     public ScriptCallingProducerNodeBuilder() {
707       super(SCRIPT_SUBNODES);
708     }
709
710     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
711       mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, SCRIPT_REQUIRED_ATTRIBUTES, SCRIPT_OPTIONAL_ATTRIBUTES);
712
713       command = (String) anAttributes.get(SCRIPT_COMMAND_ATTRIBUTE);
714       time = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, SCRIPT_TIME_ATTRIBUTE, "0");
715     };
716
717     public ProducerNode constructNode() {
718       return new
719           ScriptCallingProducerNode(command, time);
720     };
721   }
722
723 ////////////////////////////////////////////////////////////////////////////////
724
725   private final static String   DIRCOPY_SOURCE_ATTRIBUTE = "source";
726   private final static String   DIRCOPY_DESTINATION_ATTRIBUTE = "destination";
727   private final static String[] DIRCOPY_REQUIRED_ATTRIBUTES = { DIRCOPY_SOURCE_ATTRIBUTE, DIRCOPY_DESTINATION_ATTRIBUTE };
728   private final static String[] DIRCOPY_OPTIONAL_ATTRIBUTES = {};
729   private final static String[] DIRCOPY_SUBNODES = {};
730
731   public static class DirCopyProducerNodeBuilder extends AbstractProducerNodeBuilder {
732     private String source;
733     private String destination;
734     private String sourceBasePath;
735     private String destinationBasePath;
736
737     public DirCopyProducerNodeBuilder(String aSourceBasePath, String aDestinationBasePath) {
738       super(DIRCOPY_SUBNODES);
739
740       sourceBasePath = aSourceBasePath;
741       destinationBasePath = aDestinationBasePath;
742     }
743
744     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
745       mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, DIRCOPY_REQUIRED_ATTRIBUTES, DIRCOPY_OPTIONAL_ATTRIBUTES);
746
747       source = (String) anAttributes.get(DIRCOPY_SOURCE_ATTRIBUTE);
748       destination = (String) anAttributes.get(DIRCOPY_DESTINATION_ATTRIBUTE);
749     };
750
751     public ProducerNode constructNode() {
752       return new DirCopyingProducerNode(sourceBasePath, destinationBasePath, source, destination);
753     };
754
755     public static class factory implements ProducerNodeBuilderFactory {
756       private String sourceBasePath;
757       private String destinationBasePath;
758
759       public factory(String aSourceBasePath, String aDestinationBasePath) {
760         sourceBasePath = aSourceBasePath;
761         destinationBasePath = aDestinationBasePath;
762       }
763
764       public ProducerNodeBuilder makeBuilder() {
765         return new DirCopyProducerNodeBuilder(sourceBasePath, destinationBasePath);
766       }
767     }
768   }
769
770 ////////////////////////////////////////////////////////////////////////////////
771
772   public static class GeneratingProducerNodeBuilder extends AbstractProducerNodeBuilder {
773     private final static String   GENERATION_GENERATOR_ATTRIBUTE = "generator";
774     private final static String   GENERATION_DESTINATION_ATTRIBUTE = "destination";
775     private final static String   GENERATION_PARAMETERS_ATTRIBUTE = "parameters";
776     private final static String[] GENERATION_REQUIRED_ATTRIBUTES = { GENERATION_GENERATOR_ATTRIBUTE, GENERATION_DESTINATION_ATTRIBUTE };
777     private final static String[] GENERATION_OPTIONAL_ATTRIBUTES = { GENERATION_PARAMETERS_ATTRIBUTE};
778     private final static String[] GENERATION_SUBNODES = {};
779
780     private String generator;
781     private String destination;
782     private String parameters;
783     private Generator.GeneratorLibrary generatorLibrary;
784     private WriterEngine writerEngine;
785
786     public GeneratingProducerNodeBuilder(Generator.GeneratorLibrary aGeneratorLibrary, WriterEngine aWriterEngine) {
787       super(GENERATION_SUBNODES);
788
789       writerEngine = aWriterEngine;
790       generatorLibrary = aGeneratorLibrary;
791     }
792
793     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
794       mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, GENERATION_REQUIRED_ATTRIBUTES, GENERATION_OPTIONAL_ATTRIBUTES);
795
796       generator = (String) anAttributes.get(GENERATION_GENERATOR_ATTRIBUTE);
797       destination = (String) anAttributes.get(GENERATION_DESTINATION_ATTRIBUTE);
798       parameters = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, GENERATION_PARAMETERS_ATTRIBUTE, "" );
799     };
800
801     public ProducerNode constructNode() {
802       return new GeneratingProducerNode(generatorLibrary, writerEngine, generator, destination, parameters);
803     };
804
805     public static class factory implements ProducerNodeBuilderFactory {
806       private Generator.GeneratorLibrary generatorLibrary;
807       private WriterEngine writerEngine;
808
809       public factory(Generator.GeneratorLibrary aGeneratorLibrary, WriterEngine aWriterEngine) {
810         writerEngine = aWriterEngine;
811         generatorLibrary = aGeneratorLibrary;
812       }
813
814       public ProducerNodeBuilder makeBuilder() {
815         return new GeneratingProducerNodeBuilder(generatorLibrary, writerEngine);
816       }
817     }
818   }
819
820 ////////////////////////////////////////////////////////////////////////////////
821
822   public static class BatchingProducerNodeBuilder extends AbstractProducerNodeBuilder {
823
824     private final static String   BATCHER_DATAKEY_ATTRIBUTE = KEY_ATTRIBUTE;
825     private final static String   BATCHER_INFOKEY_ATTRIBUTE = "infokey";
826     private final static String   BATCHER_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
827     private final static String   BATCHER_SELECTION_ATTRIBUTE = SELECTION_ATTRIBUTE;
828     private final static String   BATCHER_ORDER_ATTRIBUTE = ORDER_ATTRIBUTE;
829
830     private final static String   BATCHER_BATCHSIZE_ATTRIBUTE = "batchsize";
831     private final static String   BATCHER_MINBATCHSIZE_ATTRIBUTE = "minbatchsize";
832     private final static String   BATCHER_SKIP_ATTRIBUTE = SKIP_ATTRIBUTE;
833
834     private final static String   BATCHER_PROCESS_ATTRIBUTE = "process";
835     private final static String   BATCHER_EXTRATABLES_ATTRIBUTE = "extratables";
836
837     private final static String   BATCHER_BATCH_SUBNODE = "batches";
838     private final static String   BATCHER_BATCHLIST_SUBNODE = "batchlist";
839     private final static String[] BATCHER_REQUIRED_ATTRIBUTES = { BATCHER_DATAKEY_ATTRIBUTE, BATCHER_INFOKEY_ATTRIBUTE, BATCHER_DEFINITION_ATTRIBUTE, BATCHER_BATCHSIZE_ATTRIBUTE };
840     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 };
841     private final static String[] BATCHER_SUBNODES = { BATCHER_BATCH_SUBNODE, BATCHER_BATCHLIST_SUBNODE };
842
843     private EntityAdapterModel model;
844     private String batchDataKey;
845     private String batchInfoKey;
846     private String mainTablePrefix;
847     private List extraTables;
848     private String definition;
849     private String selection;
850     private String order;
851     private String batchSize;
852     private String minBatchSize;
853     private String skip;
854     private String process;
855
856     public BatchingProducerNodeBuilder(EntityAdapterModel aModel) {
857       super(BATCHER_SUBNODES);
858
859       model = aModel;
860     }
861
862     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
863       mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, BATCHER_REQUIRED_ATTRIBUTES, BATCHER_OPTIONAL_ATTRIBUTES);
864
865       batchDataKey = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DATAKEY_ATTRIBUTE, "data" );
866       batchInfoKey = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_INFOKEY_ATTRIBUTE, "info" );
867       definition = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DEFINITION_ATTRIBUTE, "" );
868       selection = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SELECTION_ATTRIBUTE, "" );
869       order = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_ORDER_ATTRIBUTE, "" );
870
871       batchSize = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_BATCHSIZE_ATTRIBUTE, "20" );
872       minBatchSize = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_MINBATCHSIZE_ATTRIBUTE, "0" );
873       skip = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SKIP_ATTRIBUTE, "0" );
874       process = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_PROCESS_ATTRIBUTE, "-1" );
875       extraTables = StringRoutines.splitString(mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_EXTRATABLES_ATTRIBUTE,"").trim(), ",");
876       List parts = StringRoutines.splitString(definition.trim()," ");
877       if (parts.size()>0) definition=(String)parts.get(0);
878       if (parts.size()>1) mainTablePrefix=(String)parts.get(1);
879     };
880
881     public ProducerNode constructNode() {
882       return new EntityBatchingProducerNode(
883           batchDataKey,
884           batchInfoKey,
885           model,
886           mainTablePrefix,
887           extraTables,
888           definition,
889           selection,
890           order,
891           batchSize,
892           minBatchSize,
893           skip,
894           process,
895           getSubNode( BATCHER_BATCH_SUBNODE ),
896           getSubNode( BATCHER_BATCHLIST_SUBNODE )
897       );
898     };
899
900     public static class factory implements ProducerNodeBuilderFactory {
901       private EntityAdapterModel model;
902
903       public factory(EntityAdapterModel aModel) {
904         model = aModel;
905       }
906
907       public ProducerNodeBuilder makeBuilder() {
908         return new BatchingProducerNodeBuilder(model);
909       }
910     }
911   }
912
913 ////////////////////////////////////////////////////////////////////////////////
914
915   public static class ConditionalProducerNodeBuilder extends AbstractProducerNodeBuilder {
916     private final static String   IF_CONDITION_ATTRIBUTE = "condition";
917
918     private final static String   IF_TRUE_SUBNODE = "then";
919     private final static String   IF_FALSE_SUBNODE = "else";
920     private final static String[] IF_REQUIRED_ATTRIBUTES = { IF_CONDITION_ATTRIBUTE };
921     private final static String[] IF_OPTIONAL_ATTRIBUTES = {  };
922     private final static String[] IF_SUBNODES = { IF_TRUE_SUBNODE, IF_FALSE_SUBNODE };
923
924     private String condition;
925
926     public ConditionalProducerNodeBuilder() {
927       super(IF_SUBNODES);
928     }
929
930     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
931       mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, IF_REQUIRED_ATTRIBUTES, IF_OPTIONAL_ATTRIBUTES);
932
933       condition = (String) anAttributes.get( IF_CONDITION_ATTRIBUTE );
934     };
935
936     public ProducerNode constructNode() {
937       return new ConditionalProducerNode(
938           condition,
939           getSubNode( IF_TRUE_SUBNODE ),
940           getSubNode( IF_FALSE_SUBNODE )
941       );
942     };
943
944   }
945
946 ////////////////////////////////////////////////////////////////////////////////
947
948   public static class RSSProducerNodeBuilder extends AbstractProducerNodeBuilder {
949     private final static String   RSS_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
950     private final static String   RSS_URL_ATTRIBUTE = URL_ATTRIBUTE;
951     private final static String   RSS_VERSION_ATTRIBUTE = "version";
952
953     private final static String[] RSS_REQUIRED_ATTRIBUTES = { RSS_KEY_ATTRIBUTE, RSS_URL_ATTRIBUTE };
954     private final static String[] RSS_OPTIONAL_ATTRIBUTES = { RSS_VERSION_ATTRIBUTE };
955     private final static String[] RSS_SUBNODES = {  };
956
957     private String key;
958     private String url;
959     private String version;
960
961     public RSSProducerNodeBuilder() {
962       super(RSS_SUBNODES);
963     }
964
965     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
966       mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, RSS_REQUIRED_ATTRIBUTES, RSS_OPTIONAL_ATTRIBUTES);
967
968       key = (String) anAttributes.get( RSS_KEY_ATTRIBUTE );
969       url = (String) anAttributes.get( RSS_URL_ATTRIBUTE );
970       version = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, RSS_VERSION_ATTRIBUTE, "1.0");
971     };
972
973     public ProducerNode constructNode() {
974       return new RSSProducerNode(key, url, version);
975     };
976   }
977
978 ////////////////////////////////////////////////////////////////////////////////
979
980   public static class RDFAggregatorProducerNodeBuilder extends AbstractProducerNodeBuilder {
981     private final static String   RDF_AGGREGATOR_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
982     private final static String   RDF_AGGREGATOR_SOURCE_ATTRIBUTE = "source";
983     private final static String   RDF_AGGREGATOR_ORDER_ATTRIBUTE = ORDER_ATTRIBUTE;
984     private final static String   RDF_AGGREGATOR_FILTER_ATTRIBUTE = "filter";
985
986     private final static String[] RDF_AGGREGATOR_REQUIRED_ATTRIBUTES = { RDF_AGGREGATOR_KEY_ATTRIBUTE, RDF_AGGREGATOR_SOURCE_ATTRIBUTE };
987     private final static String[] RDF_AGGREGATOR_OPTIONAL_ATTRIBUTES = { RDF_AGGREGATOR_ORDER_ATTRIBUTE, RDF_AGGREGATOR_FILTER_ATTRIBUTE };
988     private final static String[] RDF_AGGREGATOR_SUBNODES = {  };
989
990     private String key;
991     private String source;
992     private String order;
993     private String filter;
994
995     public RDFAggregatorProducerNodeBuilder() {
996       super(RDF_AGGREGATOR_SUBNODES);
997     }
998
999     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
1000       mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, RDF_AGGREGATOR_REQUIRED_ATTRIBUTES, RDF_AGGREGATOR_OPTIONAL_ATTRIBUTES);
1001
1002       key = (String) anAttributes.get( RDF_AGGREGATOR_KEY_ATTRIBUTE );
1003       source = (String) anAttributes.get( RDF_AGGREGATOR_SOURCE_ATTRIBUTE );
1004       order = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, RDF_AGGREGATOR_SOURCE_ATTRIBUTE, "");
1005       filter = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, RDF_AGGREGATOR_FILTER_ATTRIBUTE, "");
1006     };
1007
1008     public ProducerNode constructNode() {
1009       return new RDFAggregatorProducerNode(key, source, order, filter);
1010     };
1011   }
1012
1013 ////////////////////////////////////////////////////////////////////////////////
1014
1015   public static class ScriptedProducerParameterNodeBuilder implements ProducerNodeBuilder {
1016     private String parameterName;
1017     private String scriptedNodeName;
1018
1019     public ScriptedProducerParameterNodeBuilder(String aScriptedNodeName, String aParameterName) {
1020       parameterName = aParameterName;
1021       scriptedNodeName = aScriptedNodeName;
1022     }
1023
1024     public void setSubNode(String aName, ProducerNode aNode) {
1025     };
1026
1027     public Set getAvailableSubNodes() {
1028       return new HashSet();
1029     };
1030
1031     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
1032       if (!anAttributes.isEmpty())
1033         throw new ProducerConfigExc("No parameters allowed here");
1034     };
1035
1036     public ProducerNode constructNode() {
1037       return new ScriptedProducerNodeDefinition.NodeParameterProducerNode(scriptedNodeName, parameterName);
1038     };
1039   }
1040
1041 ////////////////////////////////////////////////////////////////////////////////
1042
1043   public static class ScriptedProducerNodeBuilder implements ProducerNodeBuilder {
1044     private ScriptedProducerNodeDefinition definition;
1045     private Map nodeParameterValues;
1046     private Map integerParameterValues;
1047     private Map stringParameterValues;
1048
1049     public ScriptedProducerNodeBuilder(ScriptedProducerNodeDefinition aDefinition) {
1050       definition = aDefinition;
1051
1052       stringParameterValues = new HashMap();
1053       stringParameterValues.putAll(definition.getStringParameters());
1054
1055       integerParameterValues = new HashMap();
1056       integerParameterValues.putAll(definition.getIntegerParameters());
1057
1058       nodeParameterValues = new HashMap();
1059     }
1060
1061     public void setSubNode(String aName, ProducerNode aNode) {
1062       nodeParameterValues.put(aName, aNode);
1063     };
1064
1065     public Set getAvailableSubNodes() {
1066       return definition.getNodeParameters();
1067     };
1068
1069     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc {
1070       mir.util.xml.XMLReaderTool.checkAttributeSet(anAttributes.keySet(), definition.getRequiredAttributes(), definition.getOptionalAttributes());
1071
1072       Iterator i = anAttributes.entrySet().iterator();
1073       while (i.hasNext()) {
1074         Map.Entry entry = (Map.Entry) i.next();
1075
1076         if (definition.getIntegerParameters().keySet().contains(entry.getKey()))
1077           integerParameterValues.put(entry.getKey(), entry.getValue());
1078         else
1079           stringParameterValues.put(entry.getKey(), entry.getValue());
1080       }
1081     };
1082
1083     public ProducerNode constructNode() {
1084       return new ScriptedProducerNode(definition, stringParameterValues, integerParameterValues, nodeParameterValues);
1085     };
1086
1087     public static class factory implements ProducerNodeBuilderFactory {
1088       private ScriptedProducerNodeDefinition definition;
1089
1090       public factory(ScriptedProducerNodeDefinition aDefinition) {
1091         definition = aDefinition;
1092       }
1093
1094       public ProducerNodeBuilder makeBuilder() {
1095         return new ScriptedProducerNodeBuilder(definition);
1096       }
1097     }
1098   }
1099 }