001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.websvc.rest.codegen.model;
043:
044: import org.netbeans.modules.websvc.rest.support.*;
045: import com.sun.source.tree.ClassTree;
046: import java.io.IOException;
047: import java.util.ArrayList;
048: import java.util.Collection;
049: import java.util.HashSet;
050: import java.util.List;
051: import java.util.Set;
052: import java.util.logging.Level;
053: import java.util.logging.Logger;
054: import javax.lang.model.element.AnnotationMirror;
055: import javax.lang.model.element.Modifier;
056: import javax.lang.model.element.TypeElement;
057: import javax.lang.model.element.VariableElement;
058: import javax.lang.model.type.DeclaredType;
059: import javax.lang.model.type.TypeKind;
060: import javax.lang.model.type.TypeMirror;
061: import javax.lang.model.util.ElementFilter;
062: import org.netbeans.api.java.source.CompilationController;
063: import org.netbeans.api.java.source.JavaSource;
064: import org.netbeans.api.java.source.JavaSource.Phase;
065: import org.netbeans.api.project.Project;
066: import org.netbeans.modules.j2ee.persistence.api.metadata.orm.Entity;
067:
068: /**
069: *
070: * @author PeterLiu
071: */
072: public class EntityClassInfo {
073:
074: private EntityResourceModelBuilder builder;
075: private Entity entity;
076: private String name;
077: private String type;
078: private String packageName;
079: private Collection<FieldInfo> fieldInfos;
080: private FieldInfo idFieldInfo;
081:
082: /** Creates a new instance of ClassInfo */
083: public EntityClassInfo(Entity entity, Project project,
084: EntityResourceModelBuilder builder) {
085: this .entity = entity;
086: this .fieldInfos = new ArrayList<FieldInfo>();
087: this .builder = builder;
088:
089: extractFields(project);
090:
091: if (idFieldInfo != null && idFieldInfo.isEmbeddedId()) {
092: extractPKFields(project);
093: }
094: }
095:
096: private void extractFields(Project project) {
097: try {
098: final JavaSource source = SourceGroupSupport
099: .getJavaSourceFromClassName(entity.getClass2(),
100: project);
101: source.runUserActionTask(
102: new AbstractTask<CompilationController>() {
103:
104: public void run(CompilationController controller)
105: throws IOException {
106: controller.toPhase(Phase.RESOLVED);
107: ClassTree tree = JavaSourceHelper
108: .getTopLevelClassTree(controller);
109: assert controller.getCompilationUnit() != null : source
110: .getFileObjects().iterator().next()
111: .getPath();
112: assert controller.getCompilationUnit()
113: .getPackageName() != null : "NULL package "
114: + source.getFileObjects()
115: .iterator().next()
116: .getPath();
117: packageName = controller
118: .getCompilationUnit()
119: .getPackageName().toString();
120: name = tree.getSimpleName().toString();
121: type = packageName + "." + name;
122:
123: TypeElement classElement = JavaSourceHelper
124: .getTopLevelClassElement(controller);
125: List<VariableElement> fields = ElementFilter
126: .fieldsIn(classElement
127: .getEnclosedElements());
128:
129: for (VariableElement field : fields) {
130: Set<Modifier> modifiers = field
131: .getModifiers();
132: if (modifiers.contains(Modifier.STATIC)
133: || modifiers
134: .contains(Modifier.TRANSIENT)
135: || modifiers
136: .contains(Modifier.VOLATILE)
137: || modifiers
138: .contains(Modifier.FINAL)) {
139: continue;
140: }
141:
142: FieldInfo fieldInfo = new FieldInfo();
143:
144: fieldInfos.add(fieldInfo);
145: fieldInfo.setName(field.getSimpleName()
146: .toString());
147:
148: TypeMirror fieldType = field.asType();
149:
150: if (fieldType.getKind() == TypeKind.DECLARED) {
151: DeclaredType declType = (DeclaredType) fieldType;
152:
153: fieldInfo.setType(declType
154: .asElement().toString());
155:
156: for (TypeMirror arg : declType
157: .getTypeArguments()) {
158: fieldInfo.setTypeArg(arg
159: .toString());
160: }
161: } else {
162: fieldInfo.setType(fieldType
163: .toString());
164: }
165:
166: for (AnnotationMirror annotation : field
167: .getAnnotationMirrors()) {
168: fieldInfo.addAnnotation(annotation
169: .toString());
170: }
171:
172: if (fieldInfo.isId()) {
173: idFieldInfo = fieldInfo;
174: }
175: }
176: }
177: }, true);
178: } catch (IOException ex) {
179: Logger.getLogger(getClass().getName()).log(Level.INFO,
180: ex.getLocalizedMessage(), ex);
181: }
182: }
183:
184: private void extractPKFields(Project project) {
185: try {
186: final JavaSource source = SourceGroupSupport
187: .getJavaSourceFromClassName(idFieldInfo.getType(),
188: project);
189: source.runUserActionTask(
190: new AbstractTask<CompilationController>() {
191:
192: public void run(CompilationController controller)
193: throws IOException {
194: controller.toPhase(Phase.RESOLVED);
195:
196: TypeElement classElement = JavaSourceHelper
197: .getTopLevelClassElement(controller);
198: List<VariableElement> fields = ElementFilter
199: .fieldsIn(classElement
200: .getEnclosedElements());
201:
202: for (VariableElement field : fields) {
203: Set<Modifier> modifiers = field
204: .getModifiers();
205: if (modifiers.contains(Modifier.STATIC)
206: || modifiers
207: .contains(Modifier.TRANSIENT)
208: || modifiers
209: .contains(Modifier.VOLATILE)
210: || modifiers
211: .contains(Modifier.FINAL)) {
212: continue;
213: }
214:
215: FieldInfo fieldInfo = new FieldInfo();
216:
217: idFieldInfo.addFieldInfo(fieldInfo);
218: fieldInfo.setName(field.getSimpleName()
219: .toString());
220:
221: TypeMirror fieldType = field.asType();
222:
223: if (fieldType.getKind() == TypeKind.DECLARED) {
224: DeclaredType declType = (DeclaredType) fieldType;
225:
226: fieldInfo.setType(declType
227: .asElement().toString());
228:
229: for (TypeMirror arg : declType
230: .getTypeArguments()) {
231: fieldInfo.setTypeArg(arg
232: .toString());
233: }
234: } else {
235: fieldInfo.setType(fieldType
236: .toString());
237: }
238: }
239: }
240: }, true);
241: } catch (IOException ex) {
242: Logger.getLogger(getClass().getName()).log(Level.INFO,
243: ex.getLocalizedMessage(), ex);
244: }
245: }
246:
247: public Entity getEntity() {
248: return entity;
249: }
250:
251: public String getName() {
252: return name;
253: }
254:
255: public String getType() {
256: return type;
257: }
258:
259: public String getPackageName() {
260: return packageName;
261: }
262:
263: public FieldInfo getIdFieldInfo() {
264: return idFieldInfo;
265: }
266:
267: public Collection<FieldInfo> getFieldInfos() {
268: return fieldInfos;
269: }
270:
271: @Override
272: public boolean equals(Object obj) {
273: if (obj == null) {
274: return false;
275: }
276: if (getClass() != obj.getClass()) {
277: return false;
278: }
279: final EntityClassInfo other = (EntityClassInfo) obj;
280: if (this .name != other.name
281: && (this .name == null || !this .name.equals(other.name))) {
282: return false;
283: }
284: if (this .packageName != other.packageName
285: && (this .packageName == null || !this .packageName
286: .equals(other.packageName))) {
287: return false;
288: }
289: return true;
290: }
291:
292: @Override
293: public int hashCode() {
294: int hash = 3;
295: hash = 47 * hash
296: + (this .name != null ? this .name.hashCode() : 0);
297: hash = 47
298: * hash
299: + (this .packageName != null ? this .packageName
300: .hashCode() : 0);
301: return hash;
302: }
303:
304: public Set<EntityClassInfo> getEntityClosure(
305: Set<EntityClassInfo> result) {
306: if (result.contains(this )) {
307: return result;
308: }
309: result.add(this );
310: for (EntityClassInfo info : getRelatedEntities()) {
311: result.addAll(info.getEntityClosure(result));
312: }
313: return result;
314: }
315:
316: private Set<EntityClassInfo> relatedEntities;
317:
318: public Set<EntityClassInfo> getRelatedEntities() {
319: if (relatedEntities != null) {
320: return relatedEntities;
321: }
322: relatedEntities = new HashSet<EntityClassInfo>();
323: Set<String> allEntityNames = builder.getAllEntityNames();
324: for (FieldInfo fi : fieldInfos) {
325: String type = fi.getType();
326: String typeArg = fi.getTypeArg();
327: if (type != null && allEntityNames.contains(type)) {
328: relatedEntities.add(builder.getEntityClassInfo(type));
329: } else if (typeArg != null
330: && allEntityNames.contains(typeArg)) {
331: relatedEntities
332: .add(builder.getEntityClassInfo(typeArg));
333: }
334: }
335: return relatedEntities;
336: }
337:
338: public class FieldInfo {
339:
340: private String name;
341: private String type;
342: private String typeArg;
343: private List<String> annotations;
344: private Collection<FieldInfo> fieldInfos;
345:
346: public FieldInfo() {
347: annotations = new ArrayList<String>();
348: }
349:
350: public void setName(String name) {
351: this .name = name;
352: }
353:
354: public String getName() {
355: return name;
356: }
357:
358: public void setType(String type) {
359: this .type = type;
360: }
361:
362: public String getType() {
363: return type;
364: }
365:
366: public String getSimpleTypeName() {
367: return type.substring(type.lastIndexOf(".") + 1);
368: }
369:
370: public void setTypeArg(String typeArg) {
371: this .typeArg = typeArg;
372: }
373:
374: public String getTypeArg() {
375: return typeArg;
376: }
377:
378: public void addAnnotation(String annotation) {
379: this .annotations.add(annotation);
380: }
381:
382: public boolean isId() {
383: return matchAnnotation("@javax.persistence.Id")
384: || matchAnnotation("@javax.persistence.EmbeddedId"); //NOI18N
385: }
386:
387: public boolean isEmbeddedId() {
388: return matchAnnotation("@javax.persistence.EmbeddedId"); //NOI18N
389: }
390:
391: public boolean isRelationship() {
392: return isOneToOne() || isOneToMany() || isManyToOne()
393: || isManyToMany();
394: }
395:
396: public boolean isOneToOne() {
397: return matchAnnotation("@javax.persistence.OneToOne"); //NOI18N
398: }
399:
400: public boolean isOneToMany() {
401: return matchAnnotation("@javax.persistence.OneToMany"); //NOI18N
402: }
403:
404: public boolean isManyToOne() {
405: return matchAnnotation("@javax.persistence.ManyToOne"); //NOI18N
406: }
407:
408: public boolean isManyToMany() {
409: return matchAnnotation("@javax.persistence.ManyToMany"); //NOI18N
410: }
411:
412: private boolean matchAnnotation(String annotation) {
413: for (String a : annotations) {
414: if (a.startsWith(annotation)) {
415: return true;
416: }
417: }
418:
419: return false;
420: }
421:
422: public void addFieldInfo(FieldInfo info) {
423: if (fieldInfos == null) {
424: fieldInfos = new ArrayList<FieldInfo>();
425: }
426:
427: fieldInfos.add(info);
428: }
429:
430: public Collection<FieldInfo> getFieldInfos() {
431: return fieldInfos;
432: }
433: }
434: }
|