KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > wsdl > toJava > JavaWriter


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.axis.wsdl.toJava;
17
18 import org.apache.axis.utils.Messages;
19 import org.apache.axis.wsdl.gen.Generator;
20 import org.w3c.dom.Element JavaDoc;
21 import org.w3c.dom.Node JavaDoc;
22
23 import java.io.File JavaDoc;
24 import java.io.FileWriter JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.PrintWriter JavaDoc;
27 import java.util.StringTokenizer JavaDoc;
28
29 /**
30  * Emitter knows about WSDL writers, one each for PortType, Binding, Service,
31  * Definition, Type. But for some of these WSDL types, Wsdl2java generates
32  * multiple files. Each of these files has a corresponding writer that extends
33  * JavaWriter. So the Java WSDL writers (JavaPortTypeWriter, JavaBindingWriter,
34  * etc.) each calls a file writer (JavaStubWriter, JavaSkelWriter, etc.) for
35  * each file that that WSDL generates.
36  * <p/>
37  * <p>For example, when Emitter calls JavaWriterFactory for a Binding Writer, it
38  * returns a JavaBindingWriter. JavaBindingWriter, in turn, contains a
39  * JavaStubWriter, JavaSkelWriter, and JavaImplWriter since a Binding may cause
40  * a stub, skeleton, and impl template to be generated.
41  * <p/>
42  * <p>Note that the writers that are given to Emitter by JavaWriterFactory DO NOT
43  * extend JavaWriter. They simply implement Writer and delegate the actual
44  * task of writing to extensions of JavaWriter.
45  * <p/>
46  * <p>All of Wsdl2java's Writer implementations follow a common behaviour.
47  * JavaWriter is the abstract base class that dictates this common behaviour.
48  * This behaviour is primarily placed within the generate method. The generate
49  * method calls, in succession (note: the starred methods are the ones you are
50  * probably most interested in):
51  * <dl>
52  * <dt> * getFileName
53  * <dd> This is an abstract method that must be implemented by the subclass.
54  * It returns the fully-qualified file name.
55  * <dt> isFileGenerated(file)
56  * <dd> You should not need to override this method. It checks to see whether
57  * this file is in the List returned by emitter.getGeneratedFileNames.
58  * <dt> registerFile(file)
59  * <dd> You should not need to override this method. It registers this file by
60  * calling emitter.getGeneratedFileInfo().add(...).
61  * <dt> * verboseMessage(file)
62  * <dd> You may override this method if you want to provide more information.
63  * The generate method only calls verboseMessage if verbose is turned on.
64  * <dt> getPrintWriter(file)
65  * <dd> You should not need to override this method. Given the file name, it
66  * creates a PrintWriter for it.
67  * <dt> * writeFileHeader(pw)
68  * <dd> You may want to override this method. The default implementation
69  * generates nothing.
70  * <dt> * writeFileBody(pw)
71  * <dd> This is an abstract method that must be implemented by the subclass.
72  * This is where the body of a file is generated.
73  * <dt> * writeFileFooter(pw)
74  * <dd> You may want to override this method. The default implementation
75  * generates nothing.
76  * <dt> closePrintWriter(pw)
77  * <dd> You should not need to override this method. It simply closes the
78  * PrintWriter.
79  * </dl>
80  */

81 public abstract class JavaWriter implements Generator {
82
83     /** This controls how many characters per line for javadoc comments */
84     protected final static int LINE_LENGTH = 65;
85
86     /** Field emitter */
87     protected Emitter emitter;
88
89     /** Field type */
90     protected String JavaDoc type;
91
92     /**
93      * Constructor.
94      *
95      * @param emitter
96      * @param type
97      */

98     protected JavaWriter(Emitter emitter, String JavaDoc type) {
99         this.emitter = emitter;
100         this.type = type;
101     } // ctor
102

103     /**
104      * Generate a file.
105      *
106      * @throws IOException
107      */

108     public void generate() throws IOException JavaDoc {
109
110         String JavaDoc file = getFileName();
111
112         if (isFileGenerated(file)) {
113             throw new DuplicateFileException(
114                     Messages.getMessage("duplicateFile00", file), file);
115         }
116
117         registerFile(file);
118
119         if (emitter.isVerbose()) {
120             String JavaDoc msg = verboseMessage(file);
121
122             if (msg != null) {
123                 System.out.println(msg);
124             }
125         }
126
127         PrintWriter JavaDoc pw = getPrintWriter(file);
128
129         writeFileHeader(pw);
130         writeFileBody(pw);
131         writeFileFooter(pw);
132         closePrintWriter(pw);
133     } // generate
134

135     /**
136      * This method must be implemented by a subclass. It
137      * returns the fully-qualified name of the file to be
138      * generated.
139      *
140      * @return
141      */

142     protected abstract String JavaDoc getFileName();
143
144     /**
145      * You should not need to override this method. It checks
146      * to see whether the given file is in the List returned
147      * by emitter.getGeneratedFileNames.
148      *
149      * @param file
150      * @return
151      */

152     protected boolean isFileGenerated(String JavaDoc file) {
153         return emitter.getGeneratedFileNames().contains(file);
154     } // isFileGenerated
155

156     /**
157      * You should not need to override this method.
158      * It registers the given file by calling
159      * emitter.getGeneratedFileInfo().add(...).
160      *
161      * @param file
162      */

163     protected void registerFile(String JavaDoc file) {
164         emitter.getGeneratedFileInfo().add(file, null, type);
165     } // registerFile
166

167     /**
168      * Return the string: "Generating <file>". Override this
169      * method if you want to provide more information.
170      *
171      * @param file
172      * @return
173      */

174     protected String JavaDoc verboseMessage(String JavaDoc file) {
175         return Messages.getMessage("generating", file);
176     } // verboseMessage
177

178     /**
179      * You should not need to override this method.
180      * Given the file name, it creates a PrintWriter for it.
181      *
182      * @param filename
183      * @return
184      * @throws IOException
185      */

186     protected PrintWriter JavaDoc getPrintWriter(String JavaDoc filename) throws IOException JavaDoc {
187
188         File JavaDoc file = new File JavaDoc(filename);
189         File JavaDoc parent = new File JavaDoc(file.getParent());
190
191         parent.mkdirs();
192
193         return new PrintWriter JavaDoc(new FileWriter JavaDoc(file));
194     } // getPrintWriter
195

196     /**
197      * This method is intended to be overridden as necessary
198      * to generate file header information. This default
199      * implementation does nothing.
200      *
201      * @param pw
202      * @throws IOException
203      */

204     protected void writeFileHeader(PrintWriter JavaDoc pw)
205             throws IOException JavaDoc {
206     } // writeFileHeader
207

208     /**
209      * This method must be implemented by a subclass. This
210      * is where the body of a file is generated.
211      *
212      * @param pw
213      * @throws IOException
214      */

215     protected abstract void writeFileBody(PrintWriter JavaDoc pw) throws IOException JavaDoc;
216
217     /**
218      * You may want to override this method. This default
219      * implementation generates nothing.
220      *
221      * @param pw
222      * @throws IOException
223      */

224     protected void writeFileFooter(PrintWriter JavaDoc pw)
225             throws IOException JavaDoc {
226     } // writeFileFooter
227

228     /**
229      * Close the print writer.
230      *
231      * @param pw
232      */

233     protected void closePrintWriter(PrintWriter JavaDoc pw) {
234         pw.close();
235     } // closePrintWriter
236

237     /**
238      * Takes out new lines and wraps at Javadoc tags
239      * @param documentation the raw comments from schema
240      * @param addTab if true adds a tab character when wrapping (methods)
241      */

242     protected String JavaDoc getJavadocDescriptionPart(String JavaDoc documentation, boolean addTab) {
243         if (documentation == null) {
244             return "";
245         }
246
247         String JavaDoc doc = documentation.trim();
248
249         if (documentation.trim().length() == 0) {
250             //nothing to do
251
return doc;
252         }
253
254         // make @ tags start a new line (for javadoc tags mostly)
255
StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(doc, "@");
256         StringBuffer JavaDoc newComments;
257         if (st.hasMoreTokens()) {
258             String JavaDoc token = st.nextToken();
259             boolean startLine = Character.isWhitespace(token.charAt(token.length() - 1))
260                 && (token.charAt(token.length() - 1) != '\n');
261             newComments = new StringBuffer JavaDoc(token);
262             
263             while (st.hasMoreTokens()) {
264                 token = st.nextToken();
265                 // don't span links across lines
266
if (startLine) {
267                     newComments.append('\n');
268                 }
269                 newComments.append('@');
270                 startLine = Character.isWhitespace(token.charAt(token.length() - 1))
271             & (token.charAt(token.length() - 1) != '\n');
272
273                 newComments.append(token);
274             }
275         } else {
276             newComments = new StringBuffer JavaDoc(doc);
277         }
278         newComments.insert(0, addTab ? " * " : " * ");
279
280         // tweak comment ending tags by insterting a
281
// space between the star and the slash, BUG13407
282
int pos = newComments.toString().indexOf("*/");
283         while (pos >= 0) {
284             newComments.insert(pos + 1, ' ');
285             pos = newComments.toString().indexOf("*/");
286         }
287         
288         // now pretty it up based on column length
289
int lineStart = 0;
290         int newlinePos = 0;
291         while (lineStart < newComments.length()) {
292             newlinePos = newComments.toString().indexOf("\n", lineStart);
293             if (newlinePos == -1) {
294                 newlinePos = newComments.length();
295             }
296             if ((newlinePos - lineStart) > LINE_LENGTH) {
297                 // find first whitespace after length
298
lineStart += LINE_LENGTH;
299                 while ((lineStart < newComments.length())
300                     && !Character.isWhitespace(newComments.charAt(lineStart))) {
301                     lineStart++;
302                 }
303
304                 if (lineStart < newComments.length()) {
305                     // don't insert if line wold break at EOF
306
char next = newComments.charAt(lineStart);
307                     // insert new line header
308
if ((next == '\r') || (next == '\n')) {
309                         //newline exists at the break point, don't put in another one
310
newComments.insert(lineStart + 1, addTab ? " * " : " * ");
311                         lineStart += addTab ? 8 : 4;
312                     } else {
313                         newComments.insert(lineStart, addTab ? "\n * " : "\n * ");
314                         lineStart += addTab ? 8 : 4;
315                     }
316                 }
317
318                 // chew up witespace after newline
319
while ((lineStart < newComments.length())
320                     && (newComments.charAt(lineStart) == ' ')) { // only chew up simple spaces
321
newComments.delete(lineStart, lineStart + 1);
322                 }
323             } else {
324                 if (++newlinePos < newComments.length()) {
325                     newComments.insert(newlinePos, addTab ? " * " : " * ");
326                 }
327                 lineStart = newlinePos;
328                 lineStart += addTab ? 7 : 3;
329             }
330         }
331
332         return newComments.toString();
333     }
334
335     /**
336      * Output a documentation element as a Java comment.
337      *
338      * @param pw
339      * @param element
340      */

341     protected void writeComment(PrintWriter JavaDoc pw, Element JavaDoc element) {
342        writeComment(pw, element, true);
343     }
344
345     /**
346      * Output a documentation element as a Java comment.
347      *
348      * @param pw
349      * @param element
350      * @param addTab
351      */

352     protected void writeComment(PrintWriter JavaDoc pw, Element JavaDoc element, boolean addTab) {
353
354         if (element == null) {
355             return;
356         }
357
358         Node JavaDoc child = element.getFirstChild();
359
360         if (child == null) {
361             return;
362         }
363
364         String JavaDoc comment = child.getNodeValue();
365
366         if (comment != null) {
367             int start = 0;
368
369             pw.println(); // blank line
370

371             pw.println(addTab ? " /**" : "/**");
372             pw.println(getJavadocDescriptionPart(comment, addTab));
373             pw.println(addTab ? " */" : " */");
374         }
375     } // writeComment
376
} // abstract class JavaWriter
377
Popular Tags