View Javadoc
1   package org.codehaus.modello.plugin.java;
2   
3   /*
4    * Copyright (c) 2004, Codehaus.org
5    *
6    * Permission is hereby granted, free of charge, to any person obtaining a copy of
7    * this software and associated documentation files (the "Software"), to deal in
8    * the Software without restriction, including without limitation the rights to
9    * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10   * of the Software, and to permit persons to whom the Software is furnished to do
11   * so, subject to the following conditions:
12   *
13   * The above copyright notice and this permission notice shall be included in all
14   * copies or substantial portions of the Software.
15   *
16   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22   * SOFTWARE.
23   */
24  
25  import java.io.File;
26  import java.io.IOException;
27  import java.text.DateFormat;
28  import java.text.ParseException;
29  import java.text.SimpleDateFormat;
30  import java.util.ArrayList;
31  import java.util.Date;
32  import java.util.List;
33  import java.util.Locale;
34  import java.util.Map;
35  
36  import org.codehaus.modello.ModelloException;
37  import org.codehaus.modello.ModelloParameterConstants;
38  import org.codehaus.modello.model.BaseElement;
39  import org.codehaus.modello.model.Model;
40  import org.codehaus.modello.model.ModelAssociation;
41  import org.codehaus.modello.model.ModelClass;
42  import org.codehaus.modello.model.ModelDefault;
43  import org.codehaus.modello.model.ModelField;
44  import org.codehaus.modello.model.ModelInterface;
45  import org.codehaus.modello.model.ModelType;
46  import org.codehaus.modello.plugin.AbstractModelloGenerator;
47  import org.codehaus.modello.plugin.java.javasource.JClass;
48  import org.codehaus.modello.plugin.java.javasource.JComment;
49  import org.codehaus.modello.plugin.java.javasource.JInterface;
50  import org.codehaus.modello.plugin.java.javasource.JSourceWriter;
51  import org.codehaus.modello.plugin.java.javasource.JStructure;
52  import org.codehaus.modello.plugin.java.metadata.JavaClassMetadata;
53  import org.codehaus.modello.plugin.java.metadata.JavaFieldMetadata;
54  import org.codehaus.modello.plugin.java.metadata.JavaModelMetadata;
55  import org.codehaus.modello.plugin.model.ModelClassMetadata;
56  import org.codehaus.plexus.util.StringUtils;
57  
58  import static org.codehaus.plexus.util.StringUtils.replaceOnce;
59  
60  /**
61   * AbstractJavaModelloGenerator - similar in scope to {@link AbstractModelloGenerator} but with features that
62   * java generators can use.
63   *
64   * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
65   */
66  public abstract class AbstractJavaModelloGenerator extends AbstractModelloGenerator {
67  
68      protected boolean domAsXpp3 = true;
69  
70      protected void initialize(Model model, Map<String, Object> parameters) throws ModelloException {
71          super.initialize(model, parameters);
72          domAsXpp3 = !"false".equals(parameters.get(ModelloParameterConstants.DOM_AS_XPP3));
73      }
74  
75      /**
76       * Create a new java source file writer, with configured encoding.
77       *
78       * @param packageName the package of the source file to create
79       * @param className the class of the source file to create
80       * @return a JSourceWriter with configured encoding
81       * @throws IOException
82       */
83      protected JSourceWriter newJSourceWriter(String packageName, String className) throws IOException {
84          String directory = packageName.replace('.', File.separatorChar);
85  
86          File f = new File(new File(getOutputDirectory(), directory), className + ".java");
87  
88          if (!f.getParentFile().exists()) {
89              f.getParentFile().mkdirs();
90          }
91  
92          return new JSourceWriter(newWriter(f.toPath()));
93      }
94  
95      private JComment getHeaderComment() {
96          JComment comment = new JComment();
97          comment.setComment(String.join(System.lineSeparator(), getHeader()));
98          return comment;
99      }
100 
101     protected void initHeader(JClass clazz) {
102         clazz.setHeader(getHeaderComment());
103     }
104 
105     protected void initHeader(JInterface interfaze) {
106         interfaze.setHeader(getHeaderComment());
107     }
108 
109     protected void suppressAllWarnings(Model objectModel, JStructure structure) {
110         JavaModelMetadata javaModelMetadata = (JavaModelMetadata) objectModel.getMetadata(JavaModelMetadata.ID);
111 
112         if (javaModelMetadata.isSuppressAllWarnings()) {
113             structure.appendAnnotation("@SuppressWarnings( \"all\" )");
114         }
115     }
116 
117     protected void addModelImports(JClass jClass, BaseElement baseElem) throws ModelloException {
118         String basePackageName = null;
119         if (baseElem instanceof ModelType) {
120             basePackageName = ((ModelType) baseElem).getPackageName(isPackageWithVersion(), getGeneratedVersion());
121         }
122 
123         // import interfaces
124         for (ModelInterface modelInterface : getModel().getInterfaces(getGeneratedVersion())) {
125             addModelImport(jClass, modelInterface, basePackageName);
126         }
127 
128         // import classes
129         for (ModelClass modelClass : getClasses(getModel())) {
130             addModelImport(jClass, modelClass, basePackageName);
131         }
132     }
133 
134     protected void addModelImport(JClass jClass, ModelType modelType, String basePackageName) {
135         String packageName = modelType.getPackageName(isPackageWithVersion(), getGeneratedVersion());
136 
137         if (!packageName.equals(basePackageName)) {
138             jClass.addImport(packageName + '.' + modelType.getName());
139         }
140     }
141 
142     protected String getPrefix(JavaFieldMetadata javaFieldMetadata) {
143         return javaFieldMetadata.isBooleanGetter() ? "is" : "get";
144     }
145 
146     protected String getDefaultValue(ModelAssociation association) {
147         return replaceOnce(replaceOnce(association.getDefaultValue(), "/*", ""), "*/", "");
148     }
149 
150     protected static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS";
151 
152     protected String getJavaDefaultValue(ModelField modelField) throws ModelloException {
153         String type = modelField.getType();
154         String value = modelField.getDefaultValue();
155 
156         if ("String".equals(type)) {
157             return '"' + escapeStringLiteral(value) + '"';
158         } else if ("char".equals(type)) {
159             return '\'' + escapeStringLiteral(value) + '\'';
160         } else if ("long".equals(type)) {
161             return value + 'L';
162         } else if ("float".equals(type)) {
163             return value + 'f';
164         } else if ("Date".equals(type)) {
165             DateFormat format = new SimpleDateFormat(DEFAULT_DATE_FORMAT, Locale.US);
166             try {
167                 Date date = format.parse(value);
168                 return "new java.util.Date( " + date.getTime() + "L )";
169             } catch (ParseException pe) {
170                 throw new ModelloException("Unparseable default date: " + value, pe);
171             }
172         } else if (value != null && !value.isEmpty()) {
173             if ("Character".equals(type) && !value.contains(type)) {
174                 return "Character.valueOf( " + "'" + escapeStringLiteral(value) + "'" + ")";
175             } else if ("Boolean".equals(type) && !value.contains(type)) {
176                 return "Boolean.valueOf( " + value + ")";
177             } else if ("Byte".equals(type) && !value.contains(type)) {
178                 return "Byte.valueOf((byte) " + value + ")";
179             } else if ("Short".equals(type) && !value.contains(type)) {
180                 return "Short.valueOf((short) " + value + ")";
181             } else if ("Integer".equals(type) && !value.contains(type)) {
182                 return "Integer.valueOf(" + value + ")";
183             } else if ("Long".equals(type) && !value.contains(type)) {
184                 return "Long.valueOf(" + value + 'L' + ")";
185             } else if ("Float".equals(type) && !value.contains(type)) {
186                 return "Float.valueOf(" + value + 'f' + ")";
187             } else if ("Double".equals(type) && !value.contains(type)) {
188                 return "Double.valueOf(" + value + ")";
189             }
190         }
191 
192         return value;
193     }
194 
195     private String escapeStringLiteral(String str) {
196         StringBuilder buffer = new StringBuilder(str.length() + 32);
197 
198         for (int i = 0, n = str.length(); i < n; i++) {
199             char c = str.charAt(i);
200             switch (c) {
201                 case '\0':
202                     buffer.append("\\0");
203                     break;
204                 case '\t':
205                     buffer.append("\\t");
206                     break;
207                 case '\r':
208                     buffer.append("\\r");
209                     break;
210                 case '\n':
211                     buffer.append("\\n");
212                     break;
213                 case '\\':
214                     buffer.append("\\\\");
215                     break;
216                 default:
217                     buffer.append(c);
218             }
219         }
220 
221         return buffer.toString();
222     }
223 
224     protected String getValueChecker(String type, String value, ModelField field) throws ModelloException {
225         String retVal;
226         if ("boolean".equals(type)
227                 || "double".equals(type)
228                 || "float".equals(type)
229                 || "int".equals(type)
230                 || "long".equals(type)
231                 || "short".equals(type)
232                 || "byte".equals(type)
233                 || "char".equals(type)) {
234             retVal = "if ( " + value + " != " + getJavaDefaultValue(field) + " )";
235         } else if (ModelDefault.LIST.equals(type)
236                 || ModelDefault.SET.equals(type)
237                 || ModelDefault.MAP.equals(type)
238                 || ModelDefault.PROPERTIES.equals(type)) {
239             retVal = "if ( ( " + value + " != null ) && ( " + value + ".size() > 0 ) )";
240         } else if ("String".equals(type) && field.getDefaultValue() != null) {
241             retVal = "if ( ( " + value + " != null ) && !" + value + ".equals( \"" + field.getDefaultValue() + "\" ) )";
242         } else if ("Date".equals(type) && field.getDefaultValue() != null) {
243             retVal = "if ( ( " + value + " != null ) && !" + value + ".equals( " + getJavaDefaultValue(field) + " ) )";
244         } else {
245             retVal = "if ( " + value + " != null )";
246         }
247         return retVal;
248     }
249 
250     protected List<ModelClass> getClasses(Model model) {
251         List<ModelClass> modelClasses = new ArrayList<ModelClass>();
252 
253         for (ModelClass modelClass : model.getClasses(getGeneratedVersion())) {
254             if (isRelevant(modelClass)) {
255                 modelClasses.add(modelClass);
256             }
257         }
258 
259         return modelClasses;
260     }
261 
262     protected boolean isRelevant(ModelClass modelClass) {
263         return isJavaEnabled(modelClass) && !isTrackingSupport(modelClass);
264     }
265 
266     protected boolean isJavaEnabled(ModelClass modelClass) {
267         JavaClassMetadata javaClassMetadata = (JavaClassMetadata) modelClass.getMetadata(JavaClassMetadata.ID);
268         return javaClassMetadata.isEnabled();
269     }
270 
271     protected boolean isTrackingSupport(ModelClass modelClass) {
272         ModelClassMetadata modelClassMetadata = (ModelClassMetadata) modelClass.getMetadata(ModelClassMetadata.ID);
273         if (StringUtils.isNotEmpty(modelClassMetadata.getLocationTracker())) {
274             return true;
275         }
276         if (StringUtils.isNotEmpty(modelClassMetadata.getSourceTracker())) {
277             return true;
278         }
279         return false;
280     }
281 }