View Javadoc
1   /*
2    * Copyright 2005 Werner Guttmann
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.exolab.castor.builder.factory;
17  
18  import java.util.Enumeration;
19  
20  import org.castor.xml.JavaNaming;
21  import org.exolab.castor.builder.BuilderConfiguration;
22  import org.exolab.castor.builder.GroupNaming;
23  import org.exolab.castor.builder.SourceGenerator;
24  import org.exolab.castor.xml.schema.Annotated;
25  import org.exolab.castor.xml.schema.Annotation;
26  import org.exolab.castor.xml.schema.AttributeDecl;
27  import org.exolab.castor.xml.schema.Documentation;
28  import org.exolab.castor.xml.schema.ElementDecl;
29  import org.exolab.castor.xml.schema.Structure;
30  
31  /**
32   * This class defines a base type for the source generator code factory classes.
33   *
34   * @author <a href="mailto:werner DOT guttmann AT gmx DOT net">Werner Guttmann</a>
35   * @version $Revision: 6287 $ $Date: $
36   */
37  public class BaseFactory {
38  
39      /** The BuilderConfiguration instance, for callbacks to obtain certain
40       *  configured properties. */
41      private final BuilderConfiguration _config;
42      
43      /** The type factory. */
44      private final FieldInfoFactory _infoFactory;
45      
46      /** A GroupNaming helper class used to named anonymous groups. */
47      private GroupNaming _groupNaming = null;
48      
49      /**
50       * The calling instance of {@link SourceGenerator}.
51       */
52      private SourceGenerator _sourceGenerator;
53  
54      /**
55       * Creates an instance of this class.
56       * @param config XML code generator configuration
57       * @param infoFactory the FieldInfoFactory to use
58       * @param groupNaming Group naming scheme to be used.
59       * @param sourceGenerator The calling source generator.
60       */
61      public BaseFactory(final BuilderConfiguration config,
62              final FieldInfoFactory infoFactory, 
63              final GroupNaming groupNaming,
64              final SourceGenerator sourceGenerator) {
65          if (config == null) {
66              String err = "The 'BuilderConfiguration' argument must not be null.";
67              throw new IllegalArgumentException(err);
68          }
69          _config = config;
70  
71          if (infoFactory == null) {
72             if (getConfig().useOldFieldNaming()) {
73                this._infoFactory = new FieldInfoFactory();
74             } else {
75                this._infoFactory = new FieldInfoFactory(false);
76             }
77          } else {
78              this._infoFactory = infoFactory;
79          }
80          _groupNaming = groupNaming;
81          _sourceGenerator = sourceGenerator;
82      }
83      
84      /**
85       * Get BuilderConfiguration instance, for callbacks to obtain certain configured properties.
86       * 
87       * @return BuilderConfiguration instance.
88       */
89      protected final BuilderConfiguration getConfig() {
90          return _config;
91      }
92      
93      /**
94       * Get type factory.
95       * 
96       * @return Type factory.
97       */
98      protected final FieldInfoFactory getInfoFactory() {
99          return _infoFactory;
100     }
101     
102     /**
103      * Normalizes the given string for use in comments.
104      *
105      * @param value
106      *            the String to normalize
107      * @return the given string, normalized, for use in comments.
108      */
109     protected final String normalize(final String value) {
110         if (value == null) {
111             return null;
112         }
113 
114         char[]  chars    = value.toCharArray();
115         char[]  newChars = new char[chars.length * 2];
116         int     count    = 0;
117         int     i        = 0;
118         boolean skip     = false;
119 
120         while (i < chars.length) {
121             char ch = chars[i++];
122 
123             if ((ch == ' ') || (ch == '\t')) {
124                 if ((!skip) && (count != 0)) {
125                     newChars[count++] = ' ';
126                 }
127                 skip = true;
128             } else if (ch == '*') {
129                 if (i < chars.length && chars[i] == '/') {
130                     newChars[count++] = ch;
131                     newChars[count++] = '\\';
132                 }
133             } else {
134                 if (count == 0) {
135                     //-- ignore new lines only if count == 0
136                     if ((ch == '\r') || (ch == '\n')) {
137                         continue;
138                     }
139                 }
140                 newChars[count++] = ch;
141                 skip = false;
142             }
143         }
144         return new String(newChars, 0, count);
145     }
146 
147     /**
148      * Returns the group naming helper class for naming nested anonymous groups.
149      * 
150      * @return the group naming helper class for naming nested anonymous groups.
151      */
152     public final GroupNaming getGroupNaming() {
153         return _groupNaming;
154     }
155 
156     /**
157      * Sets the group naming helper class for naming nested anonymous groups.
158      * @param groupNaming the group naming helper class for naming nested anonymous groups.
159      */
160     public final void setGroupNaming(final GroupNaming groupNaming) {
161         _groupNaming = groupNaming;
162     }
163 
164     /**
165      * Returns the calling {@link SourceGenerator} instance.
166      * @return the calling source generator 
167      */
168     protected SourceGenerator getSourceGenerator() {
169         return _sourceGenerator;
170     }
171 
172     /**
173      * Creates and returns a Javadoc comment from the given annotations.
174      * @param annotated The {@link Annotated} instance holding annotations.
175      * @return The Javadoc comment created from the annotations.  
176      */
177     protected String createComment(final Annotated annotated) {
178         //-- process annotations
179         Enumeration<Annotation> enumeration = annotated.getAnnotations();
180         if (enumeration.hasMoreElements()) {
181             //-- just use first annotation
182             return createComment(enumeration.nextElement());
183         }
184         //-- there were no annotations...try possible references
185         switch(annotated.getStructureType()) {
186             case Structure.ELEMENT:
187                 ElementDecl elem = (ElementDecl) annotated;
188                 if (elem.isReference()) {
189                     return createComment(elem.getReference());
190                 }
191                 break;
192             case Structure.ATTRIBUTE:
193                 AttributeDecl att = (AttributeDecl) annotated;
194                 if (att.isReference()) {
195                     return createComment(att.getReference());
196                 }
197                 break;
198             default:
199                 break;
200         }
201         return null;
202     } //-- createComment
203 
204     /**
205      * Creates and returns a Javadoc comment from a given {@link Annotation}.
206      * @param annotation The {@link Annotation} instance to be used for comment creation.
207      * @return The Javdoc comment assembled from the AnnotationItem instance
208      */
209     private String createComment(final Annotation annotation) {
210         if (annotation == null) {
211             return null;
212         }
213     
214         Enumeration<Documentation> enumeration = annotation.getDocumentation();
215         if (enumeration.hasMoreElements()) {
216             //-- just use first <info>
217             Documentation documentation = enumeration.nextElement();
218             return normalize(documentation.getContent());
219         }
220         return null;
221     }
222 
223     /**
224      * Creates Comments from Schema annotations.
225      * @param annotated the Annotated structure to process
226      * @return the generated comment.
227      * 
228      */
229     // TODO: refactor to avoid duplication with createComment() methods
230     protected String extractCommentsFromAnnotations(final Annotated annotated) {
231         //-- process annotations
232         Enumeration<Annotation> enumeration = annotated.getAnnotations();
233         if (enumeration.hasMoreElements()) {
234             StringBuilder comment = new StringBuilder();
235             while (enumeration.hasMoreElements()) {
236                 Annotation ann = enumeration.nextElement();
237                 Enumeration<Documentation> documentations = ann.getDocumentation();
238                 while (documentations.hasMoreElements()) {
239                     Documentation documentation = documentations.nextElement();
240                     String content = documentation.getContent();
241                     if (content != null) {
242                         comment.append(content);
243                     }
244                 }
245             }
246             return normalize(comment.toString());
247         }
248         return null;
249     }
250 
251     /**
252      * To get the {@link JavaNaming} to be used.
253      * @return {@link JavaNaming} instance to be used
254      * @since 1.1.3
255      */
256     public final JavaNaming getJavaNaming() {
257         return _config.getJavaNaming();
258     }
259 }