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 }