1 /*
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.codemodel.internal;
27
28 import java.io.File;
29 import java.io.IOException;
30 import java.io.PrintStream;
31 import java.lang.reflect.Modifier;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.HashMap;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Map;
38
39 import com.sun.codemodel.internal.writer.FileCodeWriter;
40 import com.sun.codemodel.internal.writer.ProgressCodeWriter;
41
42
43 /**
44 * Root of the code DOM.
45 *
46 * <p>
47 * Here's your typical CodeModel application.
48 *
49 * <pre>
50 * JCodeModel cm = new JCodeModel();
51 *
52 * // generate source code by populating the 'cm' tree.
53 * cm._class(...);
54 * ...
55 *
56 * // write them out
57 * cm.build(new File("."));
58 * </pre>
59 *
60 * <p>
61 * Every CodeModel node is always owned by one {@link JCodeModel} object
62 * at any given time (which can be often accesesd by the {@code owner()} method.)
63 *
64 * As such, when you generate Java code, most of the operation works
65 * in a top-down fashion. For example, you create a class from {@link JCodeModel},
66 * which gives you a {@link JDefinedClass}. Then you invoke a method on it
67 * to generate a new method, which gives you {@link JMethod}, and so on.
68 *
69 * There are a few exceptions to this, most notably building {@link JExpression}s,
70 * but generally you work with CodeModel in a top-down fashion.
71 *
72 * Because of this design, most of the CodeModel classes aren't directly instanciable.
73 *
74 *
75 * <h2>Where to go from here?</h2>
76 * <p>
77 * Most of the time you'd want to populate new type definitions in a {@link JCodeModel}.
78 * See {@link #_class(String, ClassType)}.
79 */
80 public final class JCodeModel {
81
82 /** The packages that this JCodeWriter contains. */
83 private HashMap<String,JPackage> packages = new HashMap<String,JPackage>();
84
85 /** All JReferencedClasses are pooled here. */
86 private final HashMap<Class<?>,JReferencedClass> refClasses = new HashMap<Class<?>,JReferencedClass>();
87
88
89 /** Obtains a reference to the special "null" type. */
90 public final JNullType NULL = new JNullType(this);
91 // primitive types
92 public final JPrimitiveType VOID = new JPrimitiveType(this,"void", Void.class);
93 public final JPrimitiveType BOOLEAN = new JPrimitiveType(this,"boolean",Boolean.class);
94 public final JPrimitiveType BYTE = new JPrimitiveType(this,"byte", Byte.class);
95 public final JPrimitiveType SHORT = new JPrimitiveType(this,"short", Short.class);
96 public final JPrimitiveType CHAR = new JPrimitiveType(this,"char", Character.class);
97 public final JPrimitiveType INT = new JPrimitiveType(this,"int", Integer.class);
98 public final JPrimitiveType FLOAT = new JPrimitiveType(this,"float", Float.class);
99 public final JPrimitiveType LONG = new JPrimitiveType(this,"long", Long.class);
100 public final JPrimitiveType DOUBLE = new JPrimitiveType(this,"double", Double.class);
101
102 /**
103 * If the flag is true, we will consider two classes "Foo" and "foo"
104 * as a collision.
105 */
106 protected static final boolean isCaseSensitiveFileSystem = getFileSystemCaseSensitivity();
107
108 private static boolean getFileSystemCaseSensitivity() {
109 try {
110 // let the system property override, in case the user really
111 // wants to override.
112 if( System.getProperty("com.sun.codemodel.internal.FileSystemCaseSensitive")!=null )
113 return true;
114 } catch( Exception e ) {}
115
116 // on Unix, it's case sensitive.
117 return (File.separatorChar == '/');
118 }
119
120
121 public JCodeModel() {}
122
123 /**
124 * Add a package to the list of packages to be generated
125 *
126 * @param name
127 * Name of the package. Use "" to indicate the root package.
128 *
129 * @return Newly generated package
130 */
131 public JPackage _package(String name) {
132 JPackage p = packages.get(name);
133 if (p == null) {
134 p = new JPackage(name, this);
135 packages.put(name, p);
136 }
137 return p;
138 }
139
140 public final JPackage rootPackage() {
141 return _package("");
142 }
143
144 /**
145 * Returns an iterator that walks the packages defined using this code
146 * writer.
147 */
148 public Iterator<JPackage> packages() {
149 return packages.values().iterator();
150 }
151
152 /**
153 * Creates a new generated class.
154 *
155 * @exception JClassAlreadyExistsException
156 * When the specified class/interface was already created.
157 */
158 public JDefinedClass _class(String fullyqualifiedName) throws JClassAlreadyExistsException {
159 return _class(fullyqualifiedName,ClassType.CLASS);
275 /**
276 * A convenience method for <code>build(srcDir,resourceDir,System.out)</code>.
277 */
278 public void build( File srcDir, File resourceDir ) throws IOException {
279 build(srcDir,resourceDir,System.out);
280 }
281
282 /**
283 * A convenience method for <code>build(out,out)</code>.
284 */
285 public void build( CodeWriter out ) throws IOException {
286 build(out,out);
287 }
288
289 /**
290 * Generates Java source code.
291 */
292 public void build( CodeWriter source, CodeWriter resource ) throws IOException {
293 JPackage[] pkgs = packages.values().toArray(new JPackage[packages.size()]);
294 // avoid concurrent modification exception
295 for( JPackage pkg : pkgs )
296 pkg.build(source,resource);
297 source.close();
298 resource.close();
299 }
300
301 /**
302 * Returns the number of files to be generated if
303 * {@link #build} is invoked now.
304 */
305 public int countArtifacts() {
306 int r = 0;
307 JPackage[] pkgs = packages.values().toArray(new JPackage[packages.size()]);
308 // avoid concurrent modification exception
309 for( JPackage pkg : pkgs )
310 r += pkg.countArtifacts();
311 return r;
312 }
313
314
315 /**
316 * Obtains a reference to an existing class from its Class object.
|
1 /*
2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.codemodel.internal;
27
28 import java.io.File;
29 import java.io.IOException;
30 import java.io.PrintStream;
31 import java.lang.reflect.Modifier;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.HashMap;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Map;
38
39 import com.sun.codemodel.internal.writer.FileCodeWriter;
40 import com.sun.codemodel.internal.writer.ProgressCodeWriter;
41
42 /**
43 * Root of the code DOM.
44 *
45 * <p>
46 * Here's your typical CodeModel application.
47 *
48 * <pre>
49 * JCodeModel cm = new JCodeModel();
50 *
51 * // generate source code by populating the 'cm' tree.
52 * cm._class(...);
53 * ...
54 *
55 * // write them out
56 * cm.build(new File("."));
57 * </pre>
58 *
59 * <p>
60 * Every CodeModel node is always owned by one {@link JCodeModel} object
61 * at any given time (which can be often accesesd by the {@code owner()} method.)
62 *
63 * As such, when you generate Java code, most of the operation works
64 * in a top-down fashion. For example, you create a class from {@link JCodeModel},
65 * which gives you a {@link JDefinedClass}. Then you invoke a method on it
66 * to generate a new method, which gives you {@link JMethod}, and so on.
67 *
68 * There are a few exceptions to this, most notably building {@link JExpression}s,
69 * but generally you work with CodeModel in a top-down fashion.
70 *
71 * Because of this design, most of the CodeModel classes aren't directly instanciable.
72 *
73 *
74 * <h2>Where to go from here?</h2>
75 * <p>
76 * Most of the time you'd want to populate new type definitions in a {@link JCodeModel}.
77 * See {@link #_class(String, ClassType)}.
78 */
79 public final class JCodeModel {
80
81 /** The packages that this JCodeWriter contains. */
82 private final HashMap<String,JPackage> packages = new HashMap<>();
83
84 /** Java module in {@code module-info.java} file. */
85 private JModule module;
86
87 /** All JReferencedClasses are pooled here. */
88 private final HashMap<Class<?>,JReferencedClass> refClasses = new HashMap<>();
89
90
91 /** Obtains a reference to the special "null" type. */
92 public final JNullType NULL = new JNullType(this);
93 // primitive types
94 public final JPrimitiveType VOID = new JPrimitiveType(this,"void", Void.class);
95 public final JPrimitiveType BOOLEAN = new JPrimitiveType(this,"boolean",Boolean.class);
96 public final JPrimitiveType BYTE = new JPrimitiveType(this,"byte", Byte.class);
97 public final JPrimitiveType SHORT = new JPrimitiveType(this,"short", Short.class);
98 public final JPrimitiveType CHAR = new JPrimitiveType(this,"char", Character.class);
99 public final JPrimitiveType INT = new JPrimitiveType(this,"int", Integer.class);
100 public final JPrimitiveType FLOAT = new JPrimitiveType(this,"float", Float.class);
101 public final JPrimitiveType LONG = new JPrimitiveType(this,"long", Long.class);
102 public final JPrimitiveType DOUBLE = new JPrimitiveType(this,"double", Double.class);
103
104 /**
105 * If the flag is true, we will consider two classes "Foo" and "foo"
106 * as a collision.
107 */
108 protected static final boolean isCaseSensitiveFileSystem = getFileSystemCaseSensitivity();
109
110 private static boolean getFileSystemCaseSensitivity() {
111 try {
112 // let the system property override, in case the user really
113 // wants to override.
114 if( System.getProperty("com.sun.codemodel.internal.FileSystemCaseSensitive")!=null )
115 return true;
116 } catch( Exception e ) {}
117
118 // on Unix, it's case sensitive.
119 return (File.separatorChar == '/');
120 }
121
122
123 public JCodeModel() {}
124
125 /**
126 * Add a package to the list of packages to be generated.
127 *
128 * @param name
129 * Name of the package. Use "" to indicate the root package.
130 *
131 * @return Newly generated package
132 */
133 public JPackage _package(String name) {
134 JPackage p = packages.get(name);
135 if (p == null) {
136 p = new JPackage(name, this);
137 packages.put(name, p);
138 }
139 return p;
140 }
141
142 /**
143 * Creates and returns Java module to be generated.
144 * @param name The Name of Java module.
145 * @return New Java module.
146 */
147 public JModule _moduleInfo(final String name) {
148 return module = new JModule(name);
149 }
150
151 /**
152 * Returns existing Java module to be generated.
153 * @return Java module or {@code null} if Java module was not created yet.
154 */
155 public JModule _getModuleInfo() {
156 return module;
157 }
158
159 /**
160 * Creates Java module instance and adds existing packages with classes to the Java module info.
161 * Used to initialize and build Java module instance with existing packages content.
162 * @param name The Name of Java module.
163 * @param requires Requires directives to add.
164 * @throws IllegalStateException when Java module instance was not initialized.
165 */
166 public void _prepareModuleInfo(final String name, final String ...requires) {
167 _moduleInfo(name);
168 _updateModuleInfo(requires);
169 }
170
171 /**
172 * Adds existing packages with classes to the Java module info.
173 * Java module instance must exist before calling this method.
174 * Used to update Java module instance with existing packages content after it was prepared on client side.
175 * @param requires Requires directives to add.
176 * @throws IllegalStateException when Java module instance was not initialized.
177 */
178 public void _updateModuleInfo(final String ...requires) {
179 if (module == null) {
180 throw new IllegalStateException("Java module instance was not initialized yet.");
181 }
182 module._exports(packages.values(), false);
183 module._requires(requires);
184 }
185
186 public final JPackage rootPackage() {
187 return _package("");
188 }
189
190 /**
191 * Returns an iterator that walks the packages defined using this code
192 * writer.
193 */
194 public Iterator<JPackage> packages() {
195 return packages.values().iterator();
196 }
197
198 /**
199 * Creates a new generated class.
200 *
201 * @exception JClassAlreadyExistsException
202 * When the specified class/interface was already created.
203 */
204 public JDefinedClass _class(String fullyqualifiedName) throws JClassAlreadyExistsException {
205 return _class(fullyqualifiedName,ClassType.CLASS);
321 /**
322 * A convenience method for <code>build(srcDir,resourceDir,System.out)</code>.
323 */
324 public void build( File srcDir, File resourceDir ) throws IOException {
325 build(srcDir,resourceDir,System.out);
326 }
327
328 /**
329 * A convenience method for <code>build(out,out)</code>.
330 */
331 public void build( CodeWriter out ) throws IOException {
332 build(out,out);
333 }
334
335 /**
336 * Generates Java source code.
337 */
338 public void build( CodeWriter source, CodeWriter resource ) throws IOException {
339 JPackage[] pkgs = packages.values().toArray(new JPackage[packages.size()]);
340 // avoid concurrent modification exception
341 for( JPackage pkg : pkgs ) {
342 pkg.build(source,resource);
343 }
344 if (module != null) {
345 module.build(source);
346 }
347 source.close();
348 resource.close();
349 }
350
351 /**
352 * Returns the number of files to be generated if
353 * {@link #build} is invoked now.
354 */
355 public int countArtifacts() {
356 int r = 0;
357 JPackage[] pkgs = packages.values().toArray(new JPackage[packages.size()]);
358 // avoid concurrent modification exception
359 for( JPackage pkg : pkgs )
360 r += pkg.countArtifacts();
361 return r;
362 }
363
364
365 /**
366 * Obtains a reference to an existing class from its Class object.
|