View Javadoc

1   /*
2    * UML2MMBase module.
3    *
4    * The contents of this file are subject to the Mozilla Public License
5    * Version 1.0 (the "License"); you may not use this file except in
6    * compliance with the License. You may obtain a copy of the License at
7    * http://www.mozilla.org/MPL/
8    *
9    * Software distributed under the License is distributed on an "AS IS"
10   * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
11   * License for the specific language governing rights and limitations
12   * under the License.
13   */
14  
15  package com.finalist.mmbase.wizard;
16  
17  import java.io.File;
18  import java.io.FileNotFoundException;
19  import java.io.FileWriter;
20  import java.util.*;
21  import javax.xml.parsers.DocumentBuilder;
22  import javax.xml.parsers.DocumentBuilderFactory;
23  import org.apache.velocity.Template;
24  import org.apache.velocity.VelocityContext;
25  import org.apache.velocity.app.Velocity;
26  import org.jaxen.dom.DOMXPath;
27  import org.w3c.dom.Document;
28  import org.w3c.dom.Element;
29  import org.w3c.dom.Attr;
30  import org.xml.sax.helpers.DefaultHandler;
31  
32  /***
33   * The com.finalist.mmbase.wizard.WizardMaker walks through all editwizards generated by uml2mmbase
34   * and adds searchlists and relations to them, as indicated by <code>conf/wizard-config.xml</code>.
35   *
36   * @author mdemare
37   * @version $Revision: 1.6 $, $Date: 2005/03/21 14:37:38 $
38   * @created Jul 15, 2003
39   */
40  public class WizardMaker extends DefaultHandler {
41  
42     // the name of the application.xml to use
43     private static String applicationXML = "";
44  
45     // the name of the wizard config to use
46     private static String wizardConfigXML = "";
47  
48     private static String generatedDir = "";
49  
50     private static String searchTemplate = "";
51  
52     private static String editRelatedObjects = "";
53     
54     // Map containing (from + ":" + to  ->  type) entries for all relations.
55     private static Map typeMap = new HashMap();
56  
57     /***
58      * Creates a new com.finalist.mmbase.wizard.WizardMaker.
59      */
60     private WizardMaker() {
61     }
62  
63  
64     /***
65      * Returns all field names defined in the load editwizard of <code>name</code>.
66      * @param name the name of the wizard.
67      * @return a Set of Strings, indicating field names.
68      * @throws java.lang.Exception if anything went wrong.
69      */
70     private static List getFieldSet(String name) throws Exception {
71        String filename = generatedDir + File.separator + "editors" + File.separator + "config" + File.separator
72           + name + File.separator + "load_" + name + ".xml";
73        Document doc = parse(filename);
74  
75        return new DOMXPath("//field/@name").selectNodes(doc);
76     }
77  
78     /***
79      * Creates the <code>search_NAME</code> editwizard for the specified builder.
80      * @param to the builder for which to create the file.
81      * @param type the relation type
82      * @param label the userfriendly label
83      * @param isRequired flag indicating whether this relation is required
84      * @param searchfields a List of Strings, indicating the field names on which can be searched.
85      * @param relationfields a List of Strings, indicating the relation field names on which can be searched.
86      * @throws java.lang.Exception if anything went wrong
87      */
88     private static void createZoek(String from, String to, String type, String label, boolean isRequired,
89                                    List searchfields, List relationfields, String cardinalityLower,
90                                    String cardinalityUpper, String posrelSpecialization,
91                                    String editRelatedObjects) throws Exception {
92        VelocityContext context = new VelocityContext();
93  
94        List searchFieldValues = new ArrayList();
95        Hashtable tl;
96        /*
97        for (Iterator it = searchfields.iterator(); it.hasNext(); ) {
98           Attr attr = (Attr) it.next();
99           searchFieldValues.add(attr.getValue());
100       }
101       */
102       for (Iterator it = searchfields.iterator(); it.hasNext(); ) {
103          Element element = (Element) it.next();
104          tl = new Hashtable();
105          tl.put("fieldname",element.getAttribute("name"));
106          tl.put("fieldtype",element.getAttribute("type"));
107          tl.put("optionlist",element.getAttribute("optionlist"));
108          tl.put("minsize",element.getAttribute("minsize"));
109          tl.put("maxsize",element.getAttribute("maxsize"));
110          tl.put("reqired",element.getAttribute("required"));
111          tl.put("prompt",element.getAttribute("prompt"));
112          //System.out.println("fieldname: "+element.getAttribute("name")+"  type: "+element.getAttribute("type"));
113          searchFieldValues.add(tl);
114       }
115       
116       List relationFieldValues = new ArrayList();
117       for (Iterator it = relationfields.iterator(); it.hasNext(); ) {
118          Element element = (Element) it.next();
119          tl = new Hashtable();
120          tl.put("fieldname",element.getAttribute("name"));
121          tl.put("fieldtype",element.getAttribute("type"));
122          tl.put("optionlist",element.getAttribute("optionlist"));
123          tl.put("minsize",element.getAttribute("minsize"));
124          tl.put("maxsize",element.getAttribute("maxsize"));
125          tl.put("reqired",element.getAttribute("required"));
126          tl.put("prompt",element.getAttribute("prompt"));
127          //System.out.println("relation fieldname: "+element.getAttribute("name")+"  type: "+element.getAttribute("type"));
128          relationFieldValues.add(tl);
129       }
130 
131       context.put("builder", to);
132       context.put("type", type);
133       context.put("searchfields", searchFieldValues);
134       context.put("relationfields", relationFieldValues);
135       context.put("label", label);
136       context.put("cardinalityLower", cardinalityLower);
137       context.put("cardinalityUpper", cardinalityUpper);
138       context.put("posrelSpecialization", posrelSpecialization);
139       context.put("editRelatedObjects", editRelatedObjects);
140       if (isRequired) {
141          context.put("required", Boolean.TRUE);
142       }
143       Template t = Velocity.getTemplate(searchTemplate);
144       File parent = new File(generatedDir + File.separator + "editors" + File.separator + "config" + File.separator + to);
145       parent.mkdirs();
146       File file = new File(parent, "search_" + from + "_" + type + "_" + to + ".xml");
147       System.out.println("Creating " + file);
148       try {
149          FileWriter fw = new FileWriter(file);
150          t.merge(context, fw);
151          fw.close();
152       }
153       catch (FileNotFoundException e) {
154          System.out.println("File not found(" + file + ") exception occured (does the wizard exist?), skipping generation.");
155       }
156    }
157 
158    /***
159     * Parses an XML file.
160     * @param name the filename of the XML document
161     * @return the XML document
162     * @throws java.lang.Exception if parsing failed
163     */
164    private static Document parse(String name) throws Exception {
165       DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
166       dbf.setValidating(false);
167       DocumentBuilder parser = dbf.newDocumentBuilder();
168       parser.setEntityResolver(new MMBaseDTDResolver());
169       return parser.parse(new File(name));
170    }
171 
172 
173    /***
174     * This method finds all builders and their relations, and creates the search_NAME builders for them.
175     *
176     * @param args the commandline arguments; Path to the search template can be passed. Otherwise a default is used.
177     * @throws Exception velocity might throw an exception.
178     */
179    public static void main(String[] args) throws Exception {
180       if (args.length != 3) {
181          System.out.println("Two parameters expected for WizardMaker!");
182          return;
183       }
184 
185       searchTemplate = args[0];
186       generatedDir = args[1];
187       editRelatedObjects = args[2];
188       
189 
190       applicationXML = generatedDir + File.separator + "WEB-INF" + File.separator + "config" + File.separator
191          + "applications" + File.separator +  "APPLICATION.xml";
192       wizardConfigXML = generatedDir +  File.separator + "wizard-search-config.xml";
193 
194 
195       Velocity.setProperty(Velocity.RUNTIME_LOG, "velocity1.log");
196       Velocity.init();
197       // for each relation in application XML, store type in typeMap
198       Document applicationXml = parse(applicationXML);
199       List applicationRelations = new DOMXPath(".//relation").selectNodes(applicationXml);
200 
201       for (Iterator it = applicationRelations.iterator(); it.hasNext(); ) {
202          Element relation = (Element) it.next();
203          String from = relation.getAttribute("from");
204          String to = relation.getAttribute("to");
205          String type = relation.getAttribute("type");
206 
207          typeMap.put(from + ":" + to + ":" + type, type);
208          typeMap.put(to + ":" + from + ":" + type, type);
209       }
210 
211       Document wizardXml = parse(wizardConfigXML);
212 
213       // for each builder in wizard xml, create zoek
214       List builderSpecList = new DOMXPath(".//builder").selectNodes(wizardXml);
215       for (Iterator it = builderSpecList.iterator(); it.hasNext(); ) {
216          Element builderSpec = (Element) it.next();
217          String builderName = builderSpec.getAttribute("name");
218 
219          // get search list and relations for this builder
220          List relationSpecList = new DOMXPath(".//relation").selectNodes(builderSpec);
221          //Waarom?
222          List fields = getFieldSet(builderName);
223         
224 
225          // create a search_XXX for each relation
226          for (Iterator relIt = relationSpecList.iterator(); relIt.hasNext(); ) {
227             Element relation = (Element) relIt.next();
228             String destination = relation.getAttribute("name");
229             String required = relation.getAttribute("required");
230             boolean isRequired = ("true".equals(required));
231             String label = relation.getAttribute("label");
232             String typeGiven = relation.getAttribute("type");
233             String type = (String) typeMap.get(builderName + ":" + destination + ":" + typeGiven);
234             String posrelSpecialization = relation.getAttribute("posrelspecialization");
235             //the fields of the builder a relation can be made to            
236             List searchFields = new DOMXPath(".//field").selectNodes(relation);
237             //the fields of the relation itself
238             List relationFields = new DOMXPath(".//relation-field").selectNodes(relation);
239             // added to be able to pass the cardinality variable as well
240             String cardinalityLower = relation.getAttribute("cardinality_lower");
241             String cardinalityUpper = relation.getAttribute("cardinality_upper");
242 
243             // go create the searchfile
244             createZoek(builderName, destination, type, label, isRequired, searchFields, relationFields, 
245                cardinalityLower, cardinalityUpper, posrelSpecialization, editRelatedObjects);
246          }
247       }
248    }
249 }