split the XML parser from the producer-config reader and improved XML parser error...
[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 the com.oreilly.servlet library, any library
22  * licensed under the Apache Software License, The Sun (tm) Java Advanced
23  * Imaging library (JAI), The Sun JIMI library (or with modified versions of
24  * the above that use the same license as the above), and distribute linked
25  * combinations including the two.  You must obey the GNU General Public
26  * License in all respects for all of the code used other than the above
27  * mentioned libraries.  If you modify this file, you may extend this exception
28  * to your version of the file, but you are not obligated to do so.  If you do
29  * not wish to do so, delete this exception statement from your version.
30  */
31
32 package mir.producer.reader;
33
34 import java.util.Arrays;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.Iterator;
38 import java.util.Map;
39 import java.util.Set;
40
41 import mir.entity.adapter.EntityAdapterModel;
42 import mir.generator.Generator;
43 import mir.generator.WriterEngine;
44 import mir.log.LoggerWrapper;
45 import mir.producer.ConditionalProducerNode;
46 import mir.producer.DirCopyingProducerNode;
47 import mir.producer.EntityBatchingProducerNode;
48 import mir.producer.EntityEnumeratingProducerNode;
49 import mir.producer.EntityListProducerNode;
50 import mir.producer.EvaluatedAssignmentProducerNode;
51 import mir.producer.ExpandedAssignmentProducerNode;
52 import mir.producer.FileDateSettingProducerNode;
53 import mir.producer.FileDeletingProducerNode;
54 import mir.producer.GeneratingProducerNode;
55 import mir.producer.LoggingProducerNode;
56 import mir.producer.LoopProducerNode;
57 import mir.producer.ProducerNode;
58 import mir.producer.ResourceBundleProducerNode;
59 import mir.producer.ScriptCallingProducerNode;
60 import mir.util.*;
61
62 public class DefaultProducerNodeBuilders {
63
64   public static void registerBuilders(ProducerNodeBuilderLibrary aBuilderLibrary,
65        EntityAdapterModel aModel, Generator.GeneratorLibrary aGeneratorLibrary,
66        WriterEngine aWriterEngine, String aSourceBasePath, String aDestinationBasePath) throws ProducerConfigExc {
67
68     aBuilderLibrary.registerBuilder("Set", EvaluatedAssignmentProducerNodeBuilder.class);
69     aBuilderLibrary.registerBuilder("Define", ExpandedAssignmentProducerNodeBuilder.class);
70     aBuilderLibrary.registerBuilder("Log", LoggingProducerNodeBuilder.class);
71     aBuilderLibrary.registerBuilder("Execute", ScriptCallingProducerNodeBuilder.class);
72     aBuilderLibrary.registerBuilder("Resource", ResourceBundleProducerNodeBuilder.class);
73     aBuilderLibrary.registerFactory("CopyDir", new DirCopyProducerNodeBuilder.factory( aSourceBasePath, aDestinationBasePath));
74
75     aBuilderLibrary.registerBuilder("DeleteFile", FileDeletingProducerNodeBuilder.class);
76     aBuilderLibrary.registerBuilder("SetFileDate", FileDateSettingProducerNodeBuilder.class);
77     aBuilderLibrary.registerBuilder("If", ConditionalProducerNodeBuilder.class);
78     aBuilderLibrary.registerBuilder("While", LoopProducerNodeBuilder.class);
79
80     aBuilderLibrary.registerFactory("Enumerate", new EnumeratingProducerNodeBuilder.factory(aModel));
81     aBuilderLibrary.registerFactory("List", new ListProducerNodeBuilder.factory(aModel));
82     aBuilderLibrary.registerFactory("Batch", new BatchingProducerNodeBuilder.factory(aModel));
83
84     aBuilderLibrary.registerFactory("Generate",
85         new GeneratingProducerNodeBuilder.factory(aGeneratorLibrary, aWriterEngine));
86   }
87
88   public static abstract class AbstractProducerNodeBuilder implements ProducerNodeBuilder {
89     private Map attributes;
90     private Map subNodes;
91     private Set availableSubnodes;
92
93     public AbstractProducerNodeBuilder(String anAvailableSubNodes[]) {
94       attributes = new HashMap();
95       subNodes = new HashMap();
96       availableSubnodes = new HashSet(Arrays.asList(anAvailableSubNodes));
97     }
98
99     protected ProducerNode getSubNode(String aName) {
100       return (ProducerNode) subNodes.get(aName);
101     }
102
103     public void setSubNode(String aName, ProducerNode aNode) {
104       subNodes.put(aName, aNode);
105     };
106
107     public Set getAvailableSubNodes() {
108       return availableSubnodes;
109     };
110   }
111
112 ////////////////////////////////////////////////////////////////////////////////
113
114   // general attribute names, specifc builders reference these, to keep attribute
115   //    names consistent
116
117   public final static String   SELECTION_ATTRIBUTE = "selection";
118   public final static String   ORDER_ATTRIBUTE = "order";
119   public final static String   DEFINITION_ATTRIBUTE = "table";
120   public final static String   SKIP_ATTRIBUTE = "skip";
121   public final static String   KEY_ATTRIBUTE = "key";
122   public final static String   LIMIT_ATTRIBUTE = "limit";
123
124 ////////////////////////////////////////////////////////////////////////////////
125
126   private final static String   ASSIGNMENT_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
127   private final static String   ASSIGNMENT_VALUE_ATTRIBUTE = "value";
128   private final static String[] ASSIGNMENT_REQUIRED_ATTRIBUTES = { ASSIGNMENT_KEY_ATTRIBUTE, ASSIGNMENT_VALUE_ATTRIBUTE };
129   private final static String[] ASSIGNMENT_OPTIONAL_ATTRIBUTES = {};
130   private final static String[] ASSIGNMENT_SUBNODES = {};
131
132   public static class ExpandedAssignmentProducerNodeBuilder extends AbstractProducerNodeBuilder {
133
134     private String key;
135     private String value;
136
137     public ExpandedAssignmentProducerNodeBuilder() {
138       super(ASSIGNMENT_SUBNODES);
139     }
140
141     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
142       XMLReaderTool.checkAttributes(anAttributes, ASSIGNMENT_REQUIRED_ATTRIBUTES, ASSIGNMENT_OPTIONAL_ATTRIBUTES);
143
144       key = (String) anAttributes.get(ASSIGNMENT_KEY_ATTRIBUTE);
145       value = (String) anAttributes.get(ASSIGNMENT_VALUE_ATTRIBUTE);
146     };
147
148     public ProducerNode constructNode() {
149       return new ExpandedAssignmentProducerNode(key, value);
150     };
151   }
152
153 ////////////////////////////////////////////////////////////////////////////////
154
155   public static class EvaluatedAssignmentProducerNodeBuilder extends AbstractProducerNodeBuilder {
156
157     private String key;
158     private String value;
159
160     public EvaluatedAssignmentProducerNodeBuilder() {
161       super(ASSIGNMENT_SUBNODES);
162     }
163
164     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
165       XMLReaderTool.checkAttributes(anAttributes, ASSIGNMENT_REQUIRED_ATTRIBUTES, ASSIGNMENT_OPTIONAL_ATTRIBUTES);
166
167       key = (String) anAttributes.get(ASSIGNMENT_KEY_ATTRIBUTE);
168       value = (String) anAttributes.get(ASSIGNMENT_VALUE_ATTRIBUTE);
169     };
170
171     public ProducerNode constructNode() {
172       return new EvaluatedAssignmentProducerNode(key, value);
173     };
174   }
175
176 ////////////////////////////////////////////////////////////////////////////////
177
178   public static class EnumeratingProducerNodeBuilder extends AbstractProducerNodeBuilder {
179     private final static String   ENUMERATION_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
180     private final static String   ENUMERATION_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
181     private final static String   ENUMERATION_SELECTION_ATTRIBUTE = SELECTION_ATTRIBUTE;
182     private final static String   ENUMERATION_ORDER_ATTRIBUTE = ORDER_ATTRIBUTE;
183     private final static String   ENUMERATION_DEFAULT_SUBNODE = "default";
184     private final static String   ENUMERATION_LIMIT_ATTRIBUTE = LIMIT_ATTRIBUTE;
185     private final static String   ENUMERATION_SKIP_ATTRIBUTE = SKIP_ATTRIBUTE;
186     private final static String[] ENUMERATION_REQUIRED_ATTRIBUTES = { ENUMERATION_KEY_ATTRIBUTE, ENUMERATION_DEFINITION_ATTRIBUTE };
187     private final static String[] ENUMERATION_OPTIONAL_ATTRIBUTES = { ENUMERATION_SELECTION_ATTRIBUTE, ENUMERATION_ORDER_ATTRIBUTE, ENUMERATION_LIMIT_ATTRIBUTE, ENUMERATION_SKIP_ATTRIBUTE};
188     private final static String[] ENUMERATION_SUBNODES = {ENUMERATION_DEFAULT_SUBNODE};
189
190     private String key;
191     private String definition;
192     private String selection;
193     private String order;
194     private String limit;
195     private String skip;
196     private EntityAdapterModel model;
197
198     public EnumeratingProducerNodeBuilder(EntityAdapterModel aModel) {
199       super(ENUMERATION_SUBNODES);
200
201       model = aModel;
202     }
203
204     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc  {
205       XMLReaderTool.checkAttributes(anAttributes, ENUMERATION_REQUIRED_ATTRIBUTES, ENUMERATION_OPTIONAL_ATTRIBUTES);
206
207       key = (String) anAttributes.get(ENUMERATION_KEY_ATTRIBUTE);
208       definition = (String) anAttributes.get(ENUMERATION_DEFINITION_ATTRIBUTE);
209       selection = (String) XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_SELECTION_ATTRIBUTE, "");
210       order = (String) XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_ORDER_ATTRIBUTE, "");
211       limit = (String) anAttributes.get(ENUMERATION_LIMIT_ATTRIBUTE);
212       skip = (String) anAttributes.get(ENUMERATION_SKIP_ATTRIBUTE);
213     };
214
215     public ProducerNode constructNode() {
216       return new EntityEnumeratingProducerNode(key, model, definition, selection, order, limit, skip, getSubNode(ENUMERATION_DEFAULT_SUBNODE ));
217     };
218
219     public static class factory implements ProducerNodeBuilderFactory {
220       private EntityAdapterModel model;
221
222       public factory(EntityAdapterModel aModel) {
223         model = aModel;
224       }
225
226       public ProducerNodeBuilder makeBuilder() {
227         return new EnumeratingProducerNodeBuilder(model);
228       }
229     }
230   }
231
232 ////////////////////////////////////////////////////////////////////////////////
233
234   public static class LoopProducerNodeBuilder extends AbstractProducerNodeBuilder {
235     private final static String   LOOP_CONDITION_ATTRIBUTE = "condition";
236     private final static String   LOOP_LIMIT_ATTRIBUTE = LIMIT_ATTRIBUTE;
237     private final static String   LOOP_DEFAULT_SUBNODE = "default";
238     private final static String[] LOOP_REQUIRED_ATTRIBUTES = { LOOP_CONDITION_ATTRIBUTE };
239     private final static String[] LOOP_OPTIONAL_ATTRIBUTES = { LOOP_LIMIT_ATTRIBUTE };
240     private final static String[] LOOP_SUBNODES = {LOOP_DEFAULT_SUBNODE};
241
242     private String condition;
243     private String limit;
244
245     public LoopProducerNodeBuilder() {
246       super(LOOP_SUBNODES);
247     }
248
249     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc  {
250       XMLReaderTool.checkAttributes(anAttributes, LOOP_REQUIRED_ATTRIBUTES, LOOP_OPTIONAL_ATTRIBUTES);
251
252       condition = (String) anAttributes.get(LOOP_CONDITION_ATTRIBUTE);
253       limit = (String) XMLReaderTool.getStringAttributeWithDefault(anAttributes, LOOP_LIMIT_ATTRIBUTE, "");
254     };
255
256     public ProducerNode constructNode() {
257       return new LoopProducerNode(condition, limit, getSubNode( LOOP_DEFAULT_SUBNODE ));
258     };
259   }
260
261 ////////////////////////////////////////////////////////////////////////////////
262
263   public static class ListProducerNodeBuilder extends AbstractProducerNodeBuilder {
264     private final static String   LIST_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
265     private final static String   LIST_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
266     private final static String   LIST_SELECTION_ATTRIBUTE = SELECTION_ATTRIBUTE;
267     private final static String   LIST_ORDER_ATTRIBUTE = ORDER_ATTRIBUTE;
268     private final static String   LIST_DEFAULT_SUBNODE = "default";
269     private final static String   LIST_LIMIT_ATTRIBUTE = LIMIT_ATTRIBUTE;
270     private final static String   LIST_SKIP_ATTRIBUTE = SKIP_ATTRIBUTE;
271     private final static String[] LIST_REQUIRED_ATTRIBUTES = { LIST_KEY_ATTRIBUTE, LIST_DEFINITION_ATTRIBUTE };
272     private final static String[] LIST_OPTIONAL_ATTRIBUTES = { LIST_SELECTION_ATTRIBUTE, LIST_ORDER_ATTRIBUTE, LIST_SKIP_ATTRIBUTE, LIST_LIMIT_ATTRIBUTE};
273     private final static String[] LIST_SUBNODES = {};
274
275     private String key;
276     private String definition;
277     private String selection;
278     private String order;
279     private String limit;
280     private String skip;
281     private EntityAdapterModel model;
282
283     public ListProducerNodeBuilder(EntityAdapterModel aModel) {
284       super(LIST_SUBNODES);
285
286       model = aModel;
287     }
288
289     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
290       XMLReaderTool.checkAttributes(anAttributes, LIST_REQUIRED_ATTRIBUTES, LIST_OPTIONAL_ATTRIBUTES);
291
292       key = (String) anAttributes.get(LIST_KEY_ATTRIBUTE);
293       definition = (String) anAttributes.get(LIST_DEFINITION_ATTRIBUTE);
294       selection = (String) XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_SELECTION_ATTRIBUTE, "");
295       order = (String) XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_ORDER_ATTRIBUTE, "");
296       limit = (String) anAttributes.get(LIST_LIMIT_ATTRIBUTE);
297       skip = (String) anAttributes.get(LIST_SKIP_ATTRIBUTE);
298     };
299
300     public ProducerNode constructNode() {
301       return new EntityListProducerNode(key, model, definition, selection, order, limit, skip, null );
302     };
303
304     public static class factory implements ProducerNodeBuilderFactory {
305       private EntityAdapterModel model;
306
307       public factory(EntityAdapterModel aModel) {
308         model = aModel;
309       }
310
311       public ProducerNodeBuilder makeBuilder() {
312         return new ListProducerNodeBuilder(model);
313       }
314     }
315   }
316
317 ////////////////////////////////////////////////////////////////////////////////
318
319   public static class LoggingProducerNodeBuilder extends AbstractProducerNodeBuilder {
320     private final static String   LOG_MESSAGE_ATTRIBUTE = "message";
321     private final static String   LOG_TYPE_ATTRIBUTE = "type";
322     private final static String[] LOG_REQUIRED_ATTRIBUTES = { LOG_MESSAGE_ATTRIBUTE };
323     private final static String[] LOG_OPTIONAL_ATTRIBUTES = { LOG_TYPE_ATTRIBUTE };
324     private final static String[] LOG_SUBNODES = {};
325
326     private String message;
327     private int type = LoggerWrapper.INFO_MESSAGE;
328
329     public LoggingProducerNodeBuilder() {
330       super(LOG_SUBNODES);
331     }
332
333     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
334       String typeString;
335
336       XMLReaderTool.checkAttributes(anAttributes, LOG_REQUIRED_ATTRIBUTES, LOG_OPTIONAL_ATTRIBUTES);
337
338       message = (String) anAttributes.get(LOG_MESSAGE_ATTRIBUTE);
339       if (anAttributes.containsKey(LOG_TYPE_ATTRIBUTE)) {
340         typeString = ((String) anAttributes.get( LOG_TYPE_ATTRIBUTE ));
341
342         if (typeString.toLowerCase().equals("debug"))
343           type = LoggerWrapper.DEBUG_MESSAGE;
344         else if (typeString.toLowerCase().equals("info"))
345           type = LoggerWrapper.INFO_MESSAGE;
346         else if (typeString.toLowerCase().equals("error"))
347           type = LoggerWrapper.ERROR_MESSAGE;
348         else if (typeString.toLowerCase().equals("warning"))
349           type = LoggerWrapper.WARN_MESSAGE;
350         else if (typeString.toLowerCase().equals("fatal"))
351           type = LoggerWrapper.FATAL_MESSAGE;
352         else
353           throw new ProducerConfigExc("unknown log type: " + typeString + " (allowed are debug, info, warning, error, fatal)");
354       }
355       else
356         type = LoggerWrapper.INFO_MESSAGE;
357     };
358
359     public ProducerNode constructNode() {
360       return new LoggingProducerNode(message, type);
361     };
362   }
363
364 ////////////////////////////////////////////////////////////////////////////////
365
366   public static class ResourceBundleProducerNodeBuilder extends AbstractProducerNodeBuilder {
367     private final static String   RESOURCEBUNDLE_KEY_ATTRIBUTE = KEY_ATTRIBUTE;
368     private final static String   RESOURCEBUNDLE_BUNDLE_ATTRIBUTE = "bundle";
369     private final static String   RESOURCEBUNDLE_LANGUAGE_ATTRIBUTE = "language";
370     private final static String   RESOURCEBUNDLE_DEFAULT_SUBNODE = "default";
371     private final static String[] RESOURCEBUNDLE_REQUIRED_ATTRIBUTES = { RESOURCEBUNDLE_KEY_ATTRIBUTE, RESOURCEBUNDLE_BUNDLE_ATTRIBUTE };
372     private final static String[] RESOURCEBUNDLE_OPTIONAL_ATTRIBUTES = { RESOURCEBUNDLE_LANGUAGE_ATTRIBUTE};
373     private final static String[] RESOURCEBUNDLE_SUBNODES = {};
374
375     private String key;
376     private String bundle;
377     private String language;
378
379     public ResourceBundleProducerNodeBuilder() {
380       super(RESOURCEBUNDLE_SUBNODES);
381     }
382
383     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
384       XMLReaderTool.checkAttributes(anAttributes, RESOURCEBUNDLE_REQUIRED_ATTRIBUTES, RESOURCEBUNDLE_OPTIONAL_ATTRIBUTES);
385
386       key = (String) anAttributes.get(RESOURCEBUNDLE_KEY_ATTRIBUTE);
387       bundle = (String) anAttributes.get(RESOURCEBUNDLE_BUNDLE_ATTRIBUTE);
388       language = (String) anAttributes.get(RESOURCEBUNDLE_LANGUAGE_ATTRIBUTE);
389     };
390
391     public ProducerNode constructNode() {
392       return new ResourceBundleProducerNode(key, bundle, language);
393     };
394   }
395
396 ////////////////////////////////////////////////////////////////////////////////
397
398   public static class FileDateSettingProducerNodeBuilder extends AbstractProducerNodeBuilder {
399     private final static String   FILEDATESETTING_FILE_ATTRIBUTE = "filename";
400     private final static String   FILEDATESETTING_DATE_ATTRIBUTE = "date";
401     private final static String[] FILEDATESETTING_REQUIRED_ATTRIBUTES = { FILEDATESETTING_FILE_ATTRIBUTE, FILEDATESETTING_DATE_ATTRIBUTE };
402     private final static String[] FILEDATESETTING_OPTIONAL_ATTRIBUTES = { };
403     private final static String[] FILEDATESETTING_SUBNODES = {};
404
405     private String fileNameKey;
406     private String dateKey;
407
408     public FileDateSettingProducerNodeBuilder() {
409       super(FILEDATESETTING_SUBNODES);
410     }
411
412     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
413       XMLReaderTool.checkAttributes(anAttributes, FILEDATESETTING_REQUIRED_ATTRIBUTES, FILEDATESETTING_OPTIONAL_ATTRIBUTES);
414
415       fileNameKey = (String) anAttributes.get(FILEDATESETTING_FILE_ATTRIBUTE);
416       dateKey = (String) anAttributes.get(FILEDATESETTING_DATE_ATTRIBUTE);
417     };
418
419     public ProducerNode constructNode() {
420       return new FileDateSettingProducerNode(fileNameKey, dateKey);
421     };
422   }
423
424 ////////////////////////////////////////////////////////////////////////////////
425
426   public static class FileDeletingProducerNodeBuilder extends AbstractProducerNodeBuilder {
427     private final static String   FILEDELETING_FILE_ATTRIBUTE = "filename";
428     private final static String[] FILEDELETING_REQUIRED_ATTRIBUTES = { FILEDELETING_FILE_ATTRIBUTE };
429     private final static String[] FILEDELETING_OPTIONAL_ATTRIBUTES = { };
430     private final static String[] FILEDELETING_SUBNODES = { };
431
432     private String fileNameKey;
433
434     public FileDeletingProducerNodeBuilder() {
435       super(FILEDELETING_SUBNODES);
436     }
437
438     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
439       XMLReaderTool.checkAttributes(anAttributes, FILEDELETING_REQUIRED_ATTRIBUTES, FILEDELETING_OPTIONAL_ATTRIBUTES);
440
441       fileNameKey = (String) anAttributes.get(FILEDELETING_FILE_ATTRIBUTE);
442     };
443
444     public ProducerNode constructNode() {
445       return new FileDeletingProducerNode(fileNameKey);
446     };
447   }
448
449 ////////////////////////////////////////////////////////////////////////////////
450
451   public static class ScriptCallingProducerNodeBuilder extends AbstractProducerNodeBuilder {
452     private final static String   SCRIPT_COMMAND_ATTRIBUTE = "command";
453     private final static String[] SCRIPT_REQUIRED_ATTRIBUTES = { SCRIPT_COMMAND_ATTRIBUTE };
454     private final static String[] SCRIPT_OPTIONAL_ATTRIBUTES = {};
455     private final static String[] SCRIPT_SUBNODES = {};
456
457     private String command;
458
459     public ScriptCallingProducerNodeBuilder() {
460       super(SCRIPT_SUBNODES);
461     }
462
463     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
464       XMLReaderTool.checkAttributes(anAttributes, SCRIPT_REQUIRED_ATTRIBUTES, SCRIPT_OPTIONAL_ATTRIBUTES);
465
466       command = (String) anAttributes.get(SCRIPT_COMMAND_ATTRIBUTE);
467     };
468
469     public ProducerNode constructNode() {
470       return new ScriptCallingProducerNode(command);
471     };
472   }
473
474 ////////////////////////////////////////////////////////////////////////////////
475
476   private final static String   DIRCOPY_SOURCE_ATTRIBUTE = "source";
477   private final static String   DIRCOPY_DESTINATION_ATTRIBUTE = "destination";
478   private final static String[] DIRCOPY_REQUIRED_ATTRIBUTES = { DIRCOPY_SOURCE_ATTRIBUTE, DIRCOPY_DESTINATION_ATTRIBUTE };
479   private final static String[] DIRCOPY_OPTIONAL_ATTRIBUTES = {};
480   private final static String[] DIRCOPY_SUBNODES = {};
481
482   public static class DirCopyProducerNodeBuilder extends AbstractProducerNodeBuilder {
483     private String source;
484     private String destination;
485     private String sourceBasePath;
486     private String destinationBasePath;
487
488     public DirCopyProducerNodeBuilder(String aSourceBasePath, String aDestinationBasePath) {
489       super(DIRCOPY_SUBNODES);
490
491       sourceBasePath = aSourceBasePath;
492       destinationBasePath = aDestinationBasePath;
493     }
494
495     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
496       XMLReaderTool.checkAttributes(anAttributes, DIRCOPY_REQUIRED_ATTRIBUTES, DIRCOPY_OPTIONAL_ATTRIBUTES);
497
498       source = (String) anAttributes.get(DIRCOPY_SOURCE_ATTRIBUTE);
499       destination = (String) anAttributes.get(DIRCOPY_DESTINATION_ATTRIBUTE);
500     };
501
502     public ProducerNode constructNode() {
503       return new DirCopyingProducerNode(sourceBasePath, destinationBasePath, source, destination);
504     };
505
506     public static class factory implements ProducerNodeBuilderFactory {
507       private String sourceBasePath;
508       private String destinationBasePath;
509
510       public factory(String aSourceBasePath, String aDestinationBasePath) {
511         sourceBasePath = aSourceBasePath;
512         destinationBasePath = aDestinationBasePath;
513       }
514
515       public ProducerNodeBuilder makeBuilder() {
516         return new DirCopyProducerNodeBuilder(sourceBasePath, destinationBasePath);
517       }
518     }
519   }
520
521 ////////////////////////////////////////////////////////////////////////////////
522
523   public static class GeneratingProducerNodeBuilder extends AbstractProducerNodeBuilder {
524     private final static String   GENERATION_GENERATOR_ATTRIBUTE = "generator";
525     private final static String   GENERATION_DESTINATION_ATTRIBUTE = "destination";
526     private final static String   GENERATION_PARAMETERS_ATTRIBUTE = "parameters";
527     private final static String[] GENERATION_REQUIRED_ATTRIBUTES = { GENERATION_GENERATOR_ATTRIBUTE, GENERATION_DESTINATION_ATTRIBUTE };
528     private final static String[] GENERATION_OPTIONAL_ATTRIBUTES = { GENERATION_PARAMETERS_ATTRIBUTE};
529     private final static String[] GENERATION_SUBNODES = {};
530
531     private String generator;
532     private String destination;
533     private String parameters;
534     private Generator.GeneratorLibrary generatorLibrary;
535     private WriterEngine writerEngine;
536
537     public GeneratingProducerNodeBuilder(Generator.GeneratorLibrary aGeneratorLibrary, WriterEngine aWriterEngine) {
538       super(GENERATION_SUBNODES);
539
540       writerEngine = aWriterEngine;
541       generatorLibrary = aGeneratorLibrary;
542     }
543
544     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
545       XMLReaderTool.checkAttributes(anAttributes, GENERATION_REQUIRED_ATTRIBUTES, GENERATION_OPTIONAL_ATTRIBUTES);
546
547       generator = (String) anAttributes.get(GENERATION_GENERATOR_ATTRIBUTE);
548       destination = (String) anAttributes.get(GENERATION_DESTINATION_ATTRIBUTE);
549       parameters = XMLReaderTool.getStringAttributeWithDefault(anAttributes, GENERATION_PARAMETERS_ATTRIBUTE, "" );
550     };
551
552     public ProducerNode constructNode() {
553       return new GeneratingProducerNode(generatorLibrary, writerEngine, generator, destination, parameters);
554     };
555
556     public static class factory implements ProducerNodeBuilderFactory {
557       private Generator.GeneratorLibrary generatorLibrary;
558       private WriterEngine writerEngine;
559
560       public factory(Generator.GeneratorLibrary aGeneratorLibrary, WriterEngine aWriterEngine) {
561         writerEngine = aWriterEngine;
562         generatorLibrary = aGeneratorLibrary;
563       }
564
565       public ProducerNodeBuilder makeBuilder() {
566         return new GeneratingProducerNodeBuilder(generatorLibrary, writerEngine);
567       }
568     }
569   }
570
571 ////////////////////////////////////////////////////////////////////////////////
572
573   public static class BatchingProducerNodeBuilder extends AbstractProducerNodeBuilder {
574
575     private final static String   BATCHER_DATAKEY_ATTRIBUTE = KEY_ATTRIBUTE;
576     private final static String   BATCHER_INFOKEY_ATTRIBUTE = "infokey";
577     private final static String   BATCHER_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE;
578     private final static String   BATCHER_SELECTION_ATTRIBUTE = SELECTION_ATTRIBUTE;
579     private final static String   BATCHER_ORDER_ATTRIBUTE = ORDER_ATTRIBUTE;
580
581     private final static String   BATCHER_BATCHSIZE_ATTRIBUTE = "batchsize";
582     private final static String   BATCHER_MINBATCHSIZE_ATTRIBUTE = "minbatchsize";
583     private final static String   BATCHER_SKIP_ATTRIBUTE = SKIP_ATTRIBUTE;
584
585     private final static String   BATCHER_PROCESS_ATTRIBUTE = "process";
586
587     private final static String   BATCHER_BATCH_SUBNODE = "batches";
588     private final static String   BATCHER_BATCHLIST_SUBNODE = "batchlist";
589     private final static String[] BATCHER_REQUIRED_ATTRIBUTES = { BATCHER_DATAKEY_ATTRIBUTE, BATCHER_INFOKEY_ATTRIBUTE, BATCHER_DEFINITION_ATTRIBUTE, BATCHER_BATCHSIZE_ATTRIBUTE };
590     private final static String[] BATCHER_OPTIONAL_ATTRIBUTES = { BATCHER_SELECTION_ATTRIBUTE, BATCHER_ORDER_ATTRIBUTE, BATCHER_MINBATCHSIZE_ATTRIBUTE, BATCHER_SKIP_ATTRIBUTE, BATCHER_PROCESS_ATTRIBUTE };
591     private final static String[] BATCHER_SUBNODES = { BATCHER_BATCH_SUBNODE, BATCHER_BATCHLIST_SUBNODE };
592
593     // ML: batchSize, minBatchSize, skip should be expressions!
594
595     private EntityAdapterModel model;
596     private String batchDataKey;
597     private String batchInfoKey;
598     private String definition;
599     private String selection;
600     private String order;
601     private String batchSize;
602     private String minBatchSize;
603     private String skip;
604     private String process;
605
606     public BatchingProducerNodeBuilder(EntityAdapterModel aModel) {
607       super(BATCHER_SUBNODES);
608
609       model = aModel;
610     }
611
612     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
613       XMLReaderTool.checkAttributes(anAttributes, BATCHER_REQUIRED_ATTRIBUTES, BATCHER_OPTIONAL_ATTRIBUTES);
614
615       batchDataKey = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DATAKEY_ATTRIBUTE, "data" );
616       batchInfoKey = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_INFOKEY_ATTRIBUTE, "info" );
617       definition = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DEFINITION_ATTRIBUTE, "" );
618       selection = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SELECTION_ATTRIBUTE, "" );
619       order = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_ORDER_ATTRIBUTE, "" );
620
621       batchSize = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_BATCHSIZE_ATTRIBUTE, "20" );
622       minBatchSize = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_MINBATCHSIZE_ATTRIBUTE, "0" );
623       skip = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SKIP_ATTRIBUTE, "0" );
624       process = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_PROCESS_ATTRIBUTE, "-1" );
625     };
626
627     public ProducerNode constructNode() {
628       return new EntityBatchingProducerNode(
629           batchDataKey,
630           batchInfoKey,
631           model,
632           definition,
633           selection,
634           order,
635           batchSize,
636           minBatchSize,
637           skip,
638           process,
639           getSubNode( BATCHER_BATCH_SUBNODE ),
640           getSubNode( BATCHER_BATCHLIST_SUBNODE )
641       );
642     };
643
644     public static class factory implements ProducerNodeBuilderFactory {
645       private EntityAdapterModel model;
646
647       public factory(EntityAdapterModel aModel) {
648         model = aModel;
649       }
650
651       public ProducerNodeBuilder makeBuilder() {
652         return new BatchingProducerNodeBuilder(model);
653       }
654     }
655   }
656
657 ////////////////////////////////////////////////////////////////////////////////
658
659   public static class ConditionalProducerNodeBuilder extends AbstractProducerNodeBuilder {
660     private final static String   IF_CONDITION_ATTRIBUTE = "condition";
661
662     private final static String   IF_TRUE_SUBNODE = "then";
663     private final static String   IF_FALSE_SUBNODE = "else";
664     private final static String[] IF_REQUIRED_ATTRIBUTES = { IF_CONDITION_ATTRIBUTE };
665     private final static String[] IF_OPTIONAL_ATTRIBUTES = {  };
666     private final static String[] IF_SUBNODES = { IF_TRUE_SUBNODE, IF_FALSE_SUBNODE };
667
668     private String condition;
669
670     public ConditionalProducerNodeBuilder() {
671       super(IF_SUBNODES);
672     }
673
674     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
675       XMLReaderTool.checkAttributes(anAttributes, IF_REQUIRED_ATTRIBUTES, IF_OPTIONAL_ATTRIBUTES);
676
677       condition = (String) anAttributes.get( IF_CONDITION_ATTRIBUTE );
678     };
679
680     public ProducerNode constructNode() {
681       return new ConditionalProducerNode(
682           condition,
683           getSubNode( IF_TRUE_SUBNODE ),
684           getSubNode( IF_FALSE_SUBNODE )
685       );
686     };
687
688   }
689
690 ////////////////////////////////////////////////////////////////////////////////
691
692   public static class ScriptedProducerParameterNodeBuilder implements ProducerNodeBuilder {
693     private String parameterName;
694     private String scriptedNodeName;
695
696     public ScriptedProducerParameterNodeBuilder(String aScriptedNodeName, String aParameterName) {
697       parameterName = aParameterName;
698       scriptedNodeName = aScriptedNodeName;
699     }
700
701     public void setSubNode(String aName, ProducerNode aNode) {
702     };
703
704     public Set getAvailableSubNodes() {
705       return new HashSet();
706     };
707
708     public void setAttributes(Map anAttributes) throws ProducerConfigExc {
709       if (!anAttributes.isEmpty())
710         throw new ProducerConfigExc("No parameters allowed here");
711     };
712
713     public ProducerNode constructNode() {
714       return new ScriptedProducerNodeDefinition.NodeParameterProducerNode(scriptedNodeName, parameterName);
715     };
716   }
717
718 ////////////////////////////////////////////////////////////////////////////////
719
720   public static class ScriptedProducerNodeBuilder implements ProducerNodeBuilder {
721     private ScriptedProducerNodeDefinition definition;
722     private Map nodeParameterValues;
723     private Map integerParameterValues;
724     private Map stringParameterValues;
725
726     public ScriptedProducerNodeBuilder(ScriptedProducerNodeDefinition aDefinition) {
727       definition = aDefinition;
728
729       stringParameterValues = new HashMap();
730       stringParameterValues.putAll(definition.getStringParameters());
731
732       integerParameterValues = new HashMap();
733       integerParameterValues.putAll(definition.getIntegerParameters());
734
735       nodeParameterValues = new HashMap();
736     }
737
738     public void setSubNode(String aName, ProducerNode aNode) {
739       nodeParameterValues.put(aName, aNode);
740     };
741
742     public Set getAvailableSubNodes() {
743       return definition.getNodeParameters();
744     };
745
746     public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLReader.XMLReaderExc {
747       XMLReaderTool.checkAttributeSet(anAttributes.keySet(), definition.getRequiredAttributes(), definition.getOptionalAttributes());
748
749       Iterator i = anAttributes.entrySet().iterator();
750       while (i.hasNext()) {
751         Map.Entry entry = (Map.Entry) i.next();
752
753         if (definition.getIntegerParameters().keySet().contains(entry.getKey()))
754           integerParameterValues.put(entry.getKey(), entry.getValue());
755         else
756           stringParameterValues.put(entry.getKey(), entry.getValue());
757       }
758     };
759
760     public ProducerNode constructNode() {
761       return new ScriptedProducerNode(definition, stringParameterValues, integerParameterValues, nodeParameterValues);
762     };
763
764     public static class factory implements ProducerNodeBuilderFactory {
765       private ScriptedProducerNodeDefinition definition;
766
767       public factory(ScriptedProducerNodeDefinition aDefinition) {
768         definition = aDefinition;
769       }
770
771       public ProducerNodeBuilder makeBuilder() {
772         return new ScriptedProducerNodeBuilder(definition);
773       }
774     }
775   }
776 }