View Javadoc
1   package net.sourceforge.jenesis4java;
2   
3   /*
4    * #%L
5    * Jenesis 4 Java Code Generator
6    * %%
7    * Copyright (C) 2000 - 2015 jenesis4java
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * #L%
23   */
24  
25  /**
26   * Copyright (C) 2008, 2010 Richard van Nieuwenhoven - ritchie [at] gmx [dot] at
27   * Copyright (C) 2000, 2001 Paul Cody Johnston - pcj@inxar.org <br>
28   * This file is part of Jenesis4java. Jenesis4java is free software: you can
29   * redistribute it and/or modify it under the terms of the GNU Lesser General
30   * Public License as published by the Free Software Foundation, either version 3
31   * of the License, or (at your option) any later version.<br>
32   * Jenesis4java is distributed in the hope that it will be useful, but WITHOUT
33   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
34   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
35   * details.<br>
36   * You should have received a copy of the GNU Lesser General Public License
37   * along with Jenesis4java. If not, see <http://www.gnu.org/licenses/>.
38   */
39  import java.io.BufferedInputStream;
40  import java.io.File;
41  import java.io.FileInputStream;
42  import java.io.IOException;
43  import java.io.InputStream;
44  import java.util.Comparator;
45  import java.util.Properties;
46  import java.util.logging.Level;
47  import java.util.logging.Logger;
48  
49  /**
50   * The {@code VirtualMachine} acts as a factory method for
51   * {@code CompilationUnit}, {@code Type}, {@code Literal}, and
52   * {@code Expression} objects. Most {@code Statement} factory methods are
53   * located on {@code Block}; most {@code Declaration} factory methods are
54   * located on the objects that contain them.
55   */
56  public abstract class VirtualMachine {
57  
58      private static final Logger LOGGER = Logger.getLogger(VirtualMachine.class.getName());
59  
60      private static final String JENESIS_PROPERTY_PREFIX = "jenesis.";
61  
62      /**
63       * The default {@code VirtualMachine} implementation.
64       */
65      private static VirtualMachine virtualMachine;
66  
67      /**
68       * Returns the default {@code VirtualMachine} implementation previously set
69       * using the static {@code setVirtualMachine(VirtualMachine)} method OR
70       * returns the reference implementation ( {@code com.inxar.jenesis.MVM}. <br>
71       * <br>
72       * The settings for the coding style are read from the file specified by the
73       * system property "jenesis.blockstyle-properties-filename" (a real file or
74       * available in the classpath). If there was non specified, a fall back to
75       * /META-INF/blockstyle.properties will be used.<br>
76       * <br>
77       * All properties may be overwritten by specifying them in the system
78       * properties with a "jenesis." prefix.<br>
79       * For example you can specify to use the
80       * net.sourceforge.jenesis4java.jaloppy.JenesisJalopyEncoder encoder by
81       * setting the property "jenesis.encoder" and "jenesis.encoder.jalopyconfig"
82       */
83      public static VirtualMachine getVirtualMachine() {
84          if (VirtualMachine.virtualMachine == null) {
85  
86              InputStream in = null;
87              BufferedInputStream bufferedStream = null;
88              try {
89                  String filename = System.getProperty("jenesis.blockstyle-properties-filename");
90                  if (filename != null) {
91                      if (new File(filename).exists()) {
92                          in = new FileInputStream(filename);
93                      } else {
94                          in = Thread.currentThread().getContextClassLoader().getResourceAsStream(filename);
95                      }
96                  } else {
97                      filename = "blockstyle.properties";
98                      in = net.sourceforge.jenesis4java.VirtualMachine.class.getClassLoader().getResourceAsStream(filename);
99                  }
100 
101                 if (in == null) {
102                     throw new RuntimeException("Cannot instantiate VirtualMachine: " //
103                             + "Could not find blockstyle.properties file in system classpath " //
104                             + "or from -Djenesis.blockstyle-properties-filename!");
105                 }
106 
107                 Properties p = new Properties();
108                 bufferedStream = new BufferedInputStream(in);
109                 p.load(bufferedStream);
110                 bufferedStream.close();
111                 in.close();
112                 in = null;
113 
114                 Properties systemproperties = System.getProperties();
115                 for (String systemProperty : systemproperties.stringPropertyNames()) {
116                     if (systemProperty.startsWith(VirtualMachine.JENESIS_PROPERTY_PREFIX)) {
117                         p.put(systemProperty.substring(VirtualMachine.JENESIS_PROPERTY_PREFIX.length()), systemproperties.get(systemProperty));
118                     }
119                 }
120                 VirtualMachine.virtualMachine = new net.sourceforge.jenesis4java.impl.MVM(p);
121 
122             } catch (IOException ioex) {
123                 RuntimeException rex = new RuntimeException("Could not load VirtualMachine blockstyles: " + ioex.getMessage());
124                 ioex.printStackTrace();
125                 throw rex;
126             } finally {
127                 Exception exception = null;
128                 if (bufferedStream != null) {
129                     try {
130                         bufferedStream.close();
131                     } catch (Exception ex) {
132                         exception = ex;
133                     }
134                 }
135                 if (in != null) {
136                     try {
137                         in.close();
138                     } catch (Exception ex) {
139                         exception = ex;
140                     }
141                 }
142                 if (exception != null) {
143                     LOGGER.log(Level.SEVERE, "Exception during InputStreamReader.close(). ", exception);
144                 }
145             }
146         }
147 
148         return VirtualMachine.virtualMachine;
149     }
150 
151     /**
152      * Sets the default {@code VirtualMachine} implementation.
153      */
154     public static VirtualMachine setVirtualMachine(VirtualMachine vm) {
155         VirtualMachine.virtualMachine = vm;
156         return vm;
157     }
158 
159     /**
160      * Removes all cached compilationUnits.
161      */
162     public abstract VirtualMachine clear();
163 
164     /**
165      * Writes out the source code to all enclosed {@code CompilationUnit}
166      * instances.
167      */
168     public abstract VirtualMachine encode();
169 
170     /**
171      * @return the current active encoder.
172      */
173     public abstract CompilationUnitEncoder getEncoder();
174 
175     public abstract FieldAccess newAccess(Class<?> qualifierClass, Object object);
176 
177     /**
178      * {@code Expression} factory method which returns a new field access with
179      * the given qualifier and name.
180      */
181     public abstract FieldAccess newAccess(Expression qualifier, String name);
182 
183     /**
184      * {@code Expression} factory method which returns a new field access with
185      * the given qualifier and name.
186      */
187     public abstract FieldAccess newAccess(String name);
188 
189     /**
190      * {@code Expression} factory method which returns a new field access with
191      * the given qualifier and name.
192      */
193     public abstract FieldAccess newAccess(String qualifier, String name);
194 
195     public abstract Annotation newAnnotation(Class<?> annotationClass);
196 
197     /**
198      * Creates a new annotation with the given name. For a given name "Example"
199      * this will result in an annotation {@code @Example}.
200      * 
201      * @param text
202      *            The name of the annotation. Must not start with "@".
203      * @return The newly created Annotation.
204      */
205     public abstract Annotation newAnnotation(String text);
206 
207     /**
208      * Creates a new annotation attribute with the given name and the given
209      * value.
210      * 
211      * @return The newly created annotation attribute.
212      */
213     public abstract AnnotationAttribute newAnnotationAttribute(String key, Expression value, Expression... additionalValues);
214 
215     /**
216      * {@code Expression} factory method which returns a new anonymous class
217      * instance creation expression for the given type.
218      */
219     public abstract NewAnonymousClass newAnon(Type type);
220 
221     public abstract NewAnonymousClass newAnon(Type type, Comparator comparator);
222 
223     public abstract NewAnonymousClass newAnonymousClass(String className, String... genericTypes);
224 
225     public abstract NewAnonymousClass newAnonymousClass(String className, Comparator comparator, String... genericTypes);
226 
227     /**
228      * {@code Type} factory method which returns an array of primitive type with
229      * the given constant and dimensions.
230      */
231     public abstract ArrayType newArray(int type, int dims);
232 
233     /**
234      * {@code Type} factory method which returns an array of class type with the
235      * given name and dimensions.
236      */
237     public abstract ArrayType newArray(String type, int dims);
238 
239     /**
240      * {@code Expression} factory method which returns a new array instance
241      * creation expression for the given type.
242      */
243     public abstract NewArray newArray(Type type);
244 
245     /**
246      * {@code Expression} factory method which returns a new array access
247      * expression with the given qualifier and name.
248      */
249     public abstract ArrayAccess newArrayAccess(Expression qual, String name);
250 
251     /**
252      * {@code Expression} factory method which returns a new array access
253      * expression with the given qualifier and name.
254      */
255     public abstract ArrayAccess newArrayAccess(String name);
256 
257     /**
258      * {@code Expression} factory method which returns a new array access
259      * expression with the given qualifier and name.
260      */
261     public abstract ArrayAccess newArrayAccess(String qual, String name);
262 
263     /**
264      * {@code Expression} factory method which returns a new array initializer
265      * with the given arguments.
266      */
267     public abstract ArrayInitializer newArrayInit(Expression[] expressions);
268 
269     /**
270      * {@code Expression} factory method which returns a new array initializer
271      * with the given arguments.
272      */
273     public abstract ArrayInitializer newArrayInit(Object o);
274 
275     /**
276      * {@code Expression} factory method which returns a new assignment of the
277      * given type.
278      */
279     public abstract Assign newAssign(int type, Variable left, Expression right);
280 
281     /**
282      * {@code Expression} factory method which returns a new assignment of the
283      * SIMPLE type. This is a convenience * method.
284      */
285     public abstract Assign newAssign(Variable left, Expression right);
286 
287     /**
288      * {@code Expression} factory method which returns a new unary function of
289      * the given type.
290      */
291     public abstract Binary newBinary(int type, Expression left, Expression right);
292 
293     /**
294      * {@code Expression} factory method which returns the blank expression.
295      */
296     public abstract Blank newBlank();
297 
298     /**
299      * {@code Literal} factory method which returns a new {@code boolean}
300      * literal.
301      */
302     public abstract BooleanLiteral newBoolean(boolean value);
303 
304     /**
305      * {@code Expression} factory method which returns a new expression that
306      * wraps brackets around the expression.
307      */
308     public abstract Cast newBrackets(Expression value);
309 
310     /**
311      * {@code Literal} factory method which returns a new {@code byte} literal.
312      */
313     public abstract ByteLiteral newByte(byte val);
314 
315     /**
316      * {@code Type} factory method which returns a calendar type with the given
317      * pattern as representation storage.
318      */
319     public abstract CalendarClassType newCalendarType(String pattern);
320 
321     /**
322      * {@code Expression} factory method which returns a new cast function
323      * having the given type and value.
324      */
325     public abstract Cast newCast(Type type, Expression value);
326 
327     /**
328      * {@code Literal} factory method which returns a new {@code char} literal.
329      */
330     public abstract CharLiteral newChar(char val);
331 
332     /**
333      * {@code Expression} factory method which returns a new class instance
334      * creation expression for the given type.
335      */
336     public abstract NewClass newClass(Type type);
337 
338     /**
339      * {@code Literal} factory method which returns a new {@code Class} literal.
340      */
341     public abstract ClassLiteral newClassLiteral(ClassType type);
342 
343     /**
344      * {@code Literal} factory method which returns a new {@code Class} literal.
345      */
346     public abstract ClassLiteral newClassLiteral(String className);
347 
348     /**
349      * Creates a new {@code CompilationUnit} in this {@code Machine} and returns
350      * it.
351      */
352     public abstract CompilationUnit newCompilationUnit(String sourcepath);
353 
354     /**
355      * Creates a new {@code CompilationUnit} in this {@code Machine} sets the
356      * namespace and returns it.
357      */
358     public abstract CompilationUnit newCompilationUnit(String sourceDirectory, String packageName);
359 
360     /**
361      * {@code Literal} factory method which returns a new {@code double}
362      * literal.
363      */
364     public abstract DoubleLiteral newDouble(double val);
365 
366     /**
367      * {@code Literal} factory method which returns the boolean {@code false}
368      * literal.
369      */
370     public abstract False newFalse();
371 
372     /**
373      * {@code Literal} factory method which returns a new {@code float} literal.
374      */
375     public abstract FloatLiteral newFloat(float val);
376 
377     /**
378      * {@code Expression} factory method which returns a new freeform expression
379      * with the given code.
380      */
381     public abstract Freeform newFree(String code);
382 
383     /**
384      * {@code Literal} factory method which returns a new {@code int} literal.
385      */
386     public abstract IntLiteral newInt(int val);
387 
388     public abstract Invoke newInvoke(Class<?> qualifyingClass, String name);
389 
390     /**
391      * {@code Expression} factory method which returns a new method invocation
392      * with the given qualifier and name.
393      */
394     public abstract Invoke newInvoke(Expression qualifier, String name);
395 
396     /**
397      * {@code Expression} factory method which returns a new method invocation
398      * with the given qualifier and name.
399      */
400     public abstract Invoke newInvoke(String name);
401 
402     /**
403      * {@code Expression} factory method which returns a new method invocation
404      * with the given qualifier and name.
405      */
406     public abstract Invoke newInvoke(String qualifier, String name);
407 
408     /**
409      * {@code Literal} factory method which returns a new {@code long} literal.
410      */
411     public abstract LongLiteral newLong(long val);
412 
413     /**
414      * {@code Literal} factory method which returns the {@code null} literal.
415      */
416     public abstract Null newNull();
417 
418     /**
419      * {@code Literal} factory method which returns a new octal {@code char}
420      * literal.
421      */
422     public abstract OctalLiteral newOctal(char val);
423 
424     /**
425      * {@code Literal} factory method which returns a new scientific floating
426      * point {@code char} literal.
427      */
428     public abstract ScientificLiteral newScientific(int precision, int scale, int exponent);
429 
430     /**
431      * {@code Literal} factory method which returns a new {@code short} literal.
432      */
433     public abstract ShortLiteral newShort(short val);
434 
435     public abstract ClassType newSimpleType(Class<?> type);
436 
437     /**
438      * {@code Literal} factory method which returns a new {@code String}
439      * literal.
440      */
441     public abstract StringLiteral newString(String val);
442 
443     /**
444      * {@code Expression} factory method which returns a new unary function of
445      * the given type.
446      */
447     public abstract Ternary newTernary(int type, Expression one, Expression two, Expression three);
448 
449     /**
450      * {@code Literal} factory method which returns the boolean {@code true}
451      * literal.
452      */
453     public abstract True newTrue();
454 
455     /**
456      * {@code Type} factory method which returns a class type named with the
457      * given {@code Class}.
458      */
459     public abstract ClassType newType(Class<?> clazz);
460 
461     /**
462      * {@code Type} factory method which returns a primitive type named by the
463      * given {@code int} as allowed by the constants listed in the {@code Type}
464      * interface.
465      * 
466      * @param type
467      *            A primitive type constant. Must not be array or class.
468      */
469     public abstract PrimitiveType newType(int type);
470 
471     /**
472      * {@code Type} factory method which returns a class type named with the
473      * given {@code String}.
474      */
475     public abstract ClassType newType(String name);
476 
477     /**
478      * {@code Expression} factory method which returns a new unary function of
479      * the given type.
480      */
481     public abstract Unary newUnary(int type, Expression value);
482 
483     /**
484      * {@code Literal} factory method which returns a new unicode {@code char}
485      * literal.
486      */
487     public abstract UnicodeLiteral newUnicode(char val);
488 
489     /**
490      * {@code Expression} factory method which returns a new variable with the
491      * given name.
492      */
493     public abstract Variable newVar(String name);
494 
495     /**
496      * {@code Expression} factory method which returns a new variable with the
497      * given name.
498      */
499     public abstract Variable newVar(Type type);
500 
501     public abstract This newThis();
502 
503     public abstract This newThis(ClassType typeOfOuterClass);
504 
505     /**
506      * @return type representing:
507      */
508     public abstract Type type_boolean();
509 
510     /**
511      * @return type representing:
512      */
513     public abstract Type type_byte();
514 
515     /**
516      * @return type representing:
517      */
518     public abstract Type type_char();
519 
520     /**
521      * @return type representing:
522      */
523     public abstract Type type_double();
524 
525     /**
526      * @return type representing:
527      */
528     public abstract Type type_float();
529 
530     /**
531      * @return type representing:
532      */
533     public abstract Type type_int();
534 
535     /**
536      * @return type representing:
537      */
538     public abstract Type type_long();
539 
540     /**
541      * @return type representing:
542      */
543     public abstract Type type_short();
544 
545     /**
546      * @return type representing:
547      */
548     public abstract Type type_void();
549 
550     /**
551      * @return type representing:
552      */
553     public abstract ClassType typeBigDecimal();
554 
555     /**
556      * @return type representing:
557      */
558     public abstract ClassType typeBoolean();
559 
560     /**
561      * @return type representing:
562      */
563     public abstract ClassType typeCalendar();
564 
565     /**
566      * @return type representing:
567      */
568     public abstract ClassType typeInteger();
569 
570     /**
571      * @return type representing:
572      */
573     public abstract ClassType typeLong();
574 
575     /**
576      * @return type representing:
577      */
578     public abstract ClassType typeString();
579 
580     public abstract Super newSuper();
581 }