KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > xml > xmlc > compiler > AccessMethods


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
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
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  *
19  * Contributor(s):
20  *
21  * $Id: AccessMethods.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
22  */

23
24 package org.enhydra.xml.xmlc.compiler;
25
26 import java.io.PrintWriter JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.Iterator JavaDoc;
29
30 import org.enhydra.xml.xmlc.codegen.IndentWriter;
31 import org.enhydra.xml.xmlc.codegen.JavaClass;
32 import org.enhydra.xml.xmlc.codegen.JavaCode;
33 import org.enhydra.xml.xmlc.codegen.JavaLang;
34 import org.enhydra.xml.xmlc.codegen.JavaMethod;
35 import org.enhydra.xml.xmlc.codegen.JavaModifiers;
36 import org.enhydra.xml.xmlc.codegen.JavaParameter;
37 import org.enhydra.xml.xmlc.dom.AccessorGenerator;
38 import org.enhydra.xml.xmlc.metadata.MetaData;
39
40 /**
41  * Data collection and code generation for element access methods.
42  */

43 class AccessMethods {
44     /**
45      * Information collected about each element.
46      */

47     private ElementTable fElementTable;
48
49     /**
50      * Should delegation support be create.
51      */

52     private boolean fCreateDelegation;
53
54     /**
55      * Class being generated.
56      */

57     private JavaClass fDocClass;
58
59     /**
60      * DOM Accessor generator.
61      */

62     private AccessorGenerator fAccessorGenerator;
63
64     /**
65      * List of accessor methods, indexed by element info object.
66      */

67     private HashMap JavaDoc fAccessorMethods = new HashMap JavaDoc();
68
69     /**
70      * Parameter for syncWithDocument methods.
71      * A static since in can be shared.
72      */

73     private static final JavaParameter[] syncWithDocParam = {
74         new JavaParameter("node", "Node",
75                           "Root of subtree to sync.")
76     };
77
78     /**
79      * Constructor.
80      */

81     public AccessMethods(MetaData metaData,
82                          ElementTable elementTable,
83                          AccessorGenerator accessorGenerator) {
84         fCreateDelegation = metaData.getDocumentClass().getDelegateSupport();
85         fElementTable = elementTable;
86         fAccessorGenerator = accessorGenerator;
87     }
88
89     /**
90      * Create the access methods and field definitions for an element.
91      */

92     private void createAccessMethods(ElementInfo elementInfo) {
93         ElementInfo.AccessorInfo[] accessors = elementInfo.getAccessors();
94         int methodIdx = 0;
95         JavaMethod[] methods = new JavaMethod[elementInfo.getNumAccessMethods()];
96         if (accessors != null) {
97             for (int idx = 0; idx < accessors.length; idx++) {
98                 methods[methodIdx++]
99                     = fAccessorGenerator.createAccessorMethod(elementInfo,
100                                                               accessors[idx],
101                                                               fCreateDelegation,
102                                                               fDocClass);
103             }
104         }
105         if (elementInfo.createSetText()) {
106             methods[methodIdx++]
107                 = fAccessorGenerator.createSetTextMethod(elementInfo,
108                                                          fCreateDelegation,
109                                                          fDocClass);
110         }
111         fAccessorMethods.put(elementInfo, methods);
112     }
113
114
115     /**
116      * Generate access methods and field definitions.
117      */

118     private void createAccessMethods() {
119         JavaMethod method;
120         Iterator JavaDoc elements = fElementTable.getJavaIdElements();
121         while (elements.hasNext()) {
122             ElementInfo elementInfo = (ElementInfo)elements.next();
123             if (elementInfo.getNumAccessMethods() > 0) {
124                 createAccessMethods(elementInfo);
125             }
126         }
127     }
128
129     /**
130      * Create code for initializing accessor fields from ElementInfo objects.
131      */

132     private void createAccessorFieldInits(JavaCode body,
133                                           Iterator JavaDoc elements) {
134         while (elements.hasNext()) {
135             ElementInfo elementInfo = (ElementInfo)elements.next();
136             if (elementInfo.getNumAccessMethods() > 0) {
137                 body.addln("} else if (id.equals(" + JavaLang.createStringConst(elementInfo.getXmlId()) + ")) {");
138                 body.enter();
139                 fAccessorGenerator.createResetElementAccess(elementInfo, "node", body);
140                 body.leave();
141             }
142         }
143     }
144
145     /**
146      * Create body of code to set all element access fields to null.
147      */

148     private void createNullAccessFieldsInit(JavaCode body) {
149         Iterator JavaDoc elements = fElementTable.getJavaIdElements();
150         while (elements.hasNext()) {
151             ElementInfo elementInfo = (ElementInfo)elements.next();
152             if (elementInfo.getNumAccessMethods() > 0) {
153                 fAccessorGenerator.createNullElementAccess(elementInfo, body);
154             }
155         }
156         body.addln();
157     }
158
159     /**
160      * Create body of field initialization method for global id attribute
161      * mode.
162      */

163     private void createGlobalIdModeInit(JavaCode body) {
164         String JavaDoc idAttr = fElementTable.getXMLCDocument().getGlobalIdAttribute();
165         body.addln("if (node instanceof Element) {");
166         body.enter();
167         body.addln("String id = ((Element)node).getAttribute("
168                     + JavaLang.createStringConst(idAttr) + ");");
169         body.addln("if (id.length() == 0) {"); // Block contains empty statement.
170

171         createAccessorFieldInits(body, fElementTable.getJavaIdElements());
172
173         body.addln("}"); // Closes last else-if
174
body.leave();
175         body.addln("}");
176     }
177
178     //FIXME: need to get the terminalogy straight:
179
// global/local attribute id or single/multiple attribute id.
180

181     /**
182      * Create field initialization code for a tag in multple id attribute
183      * mode.
184      */

185     private void createMultipleIdModeTagInit(String JavaDoc tagName,
186                                              JavaCode body) {
187         String JavaDoc idAttr = fElementTable.getIdAttributeName(tagName);
188         if (idAttr == null) {
189             return; // no id attribute
190
}
191         body.addln("if (tag.equals(" + JavaLang.createStringConst(tagName) + ")) {");
192         body.enter();
193         body.addln("String id = element.getAttribute("
194                     + JavaLang.createStringConst(idAttr) + ");");
195         // First block contains empty statement if id is empty
196
body.addln("if (id.length() == 0) {");
197
198         // Generate code for each id field for this tag.
199
createAccessorFieldInits(body, fElementTable.getElementsByTagName(tagName));
200         body.addln("}"); // Closes last else-if
201
body.leave();
202         body.addln("}"); // Closes tag.equals(xxx) block
203
}
204
205     /**
206      * Create body of field initialization method for multple id attribute
207      * mode.
208      */

209     private void createMultipleIdModeInit(JavaCode body) {
210         body.addln(new String JavaDoc[] {
211             "if (node instanceof Element) {",
212             " Element element = (Element)node;",
213             " String tag = element.getTagName();"
214         });
215         body.enter();
216         
217         // For each element tag name, generate code for all ids associated
218
// with it.
219
Iterator JavaDoc tags = fElementTable.getTagNames();
220         while (tags.hasNext()) {
221             createMultipleIdModeTagInit((String JavaDoc)tags.next(), body);
222         }
223         body.leave();
224         body.addln("}");
225     }
226
227     /**
228      * Generate access method field initialization function used in clone.
229      * There are two versions of the code that can be generated:
230      * <UL>
231      * <LI> Global id attribute mode. One attribute names is used for
232      * all ids and is not used anywhere else. That is,
233      * <CODE>XMLCDocument.getGlobalIdAttribute()</CODE> returns a name.
234      * <LI> Multiple id attribute mode. Multiple attributes are declared
235      * of type ID.
236      * </UL>
237      */

238     private void createAccessMethodSync() {
239         String JavaDoc[] doc = {
240             "Recursive function to do set access method fields from the DOM.",
241             "Missing ids have fields set to null.",
242         };
243         JavaMethod method
244             = new JavaMethod("syncWithDocument",
245                              "void",
246                              JavaModifiers.PROTECTED,
247                              syncWithDocParam, doc);
248         fDocClass.addMethod(method);
249         JavaCode body = method.getCode();
250
251         // Generate body to initialize.
252
if (fElementTable.isGlobalIdAttrMode()) {
253             createGlobalIdModeInit(body);
254         } else {
255             createMultipleIdModeInit(body);
256         }
257         
258         // Generate recursion down the tree.
259
body.addln(new String JavaDoc[] {
260             "Node child = node.getFirstChild();",
261             "while (child != null) {",
262             " syncWithDocument(child);",
263             " child = child.getNextSibling();",
264             "}"
265         });
266     }
267
268     /**
269      * Generate the code for the access methods.
270      * @param docClass Object containing the class being generated.
271      */

272     public void generateCode(JavaClass docClass) {
273         fDocClass = docClass;
274         createAccessMethodSync();
275         createAccessMethods();
276     }
277     
278     /**
279      * Print the signatures of the access methods are created.
280      */

281     public void printAccessMethods(PrintWriter JavaDoc out) {
282         IndentWriter iout = new IndentWriter(out);
283         Iterator JavaDoc elements = fElementTable.getJavaIdElements();
284         while (elements.hasNext()) {
285             ElementInfo elementInfo = (ElementInfo)elements.next();
286             JavaMethod[] methods = (JavaMethod[])fAccessorMethods.get(elementInfo);
287             if (methods != null) {
288                 for (int idx = 0; idx < methods.length; idx++) {
289                     methods[idx].printMethodSignature(iout, false);
290                 }
291             }
292         }
293         iout.flush();
294     }
295
296     /**
297      * Print ids that didn't have accessors generated due to being illegal
298      * Java identifiers. We keep them sorted so that the test always work.
299      */

300     public void printOmittedIds(PrintWriter JavaDoc out) {
301         Iterator JavaDoc ids = fElementTable.getInvalidElementIds();
302         if ((ids != null) && ids.hasNext()) {
303             out.println("Access methods not created for these element IDs");
304             out.println("since they are not legal Java identifiers:");
305             while (ids.hasNext()) {
306                 out.print("`");
307                 out.print((String JavaDoc)ids.next());
308                 out.println("'");
309             }
310         }
311     }
312 }
313
Popular Tags