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