KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > javacore > jmiimpl > javamodel > JavaClassImpl


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.javacore.jmiimpl.javamodel;
20
21 import java.lang.ref.WeakReference JavaDoc;
22 import java.lang.reflect.Modifier JavaDoc;
23 import java.util.*;
24 import javax.jmi.reflect.ConstraintViolationException;
25 import javax.jmi.reflect.RefFeatured;
26 import javax.jmi.reflect.RefObject;
27 import org.netbeans.api.mdr.events.AssociationEvent;
28 import org.netbeans.jmi.javamodel.*;
29 import org.netbeans.lib.java.parser.ASTree;
30 import org.netbeans.lib.java.parser.ParserTokens;
31 import org.netbeans.lib.java.parser.Token;
32 import org.netbeans.mdr.handlers.AttrListWrapper;
33 import org.netbeans.mdr.handlers.BaseObjectHandler;
34 import org.netbeans.mdr.persistence.MOFID;
35 import org.netbeans.mdr.persistence.StorageException;
36 import org.netbeans.mdr.storagemodel.StorableBaseObject;
37 import org.netbeans.mdr.storagemodel.StorableObject;
38 import org.netbeans.modules.javacore.ClassIndex;
39 import org.netbeans.modules.javacore.JMManager;
40 import org.netbeans.modules.javacore.internalapi.JavaMetamodel;
41 import org.netbeans.modules.javacore.internalapi.JavaModelUtil;
42 import org.netbeans.modules.javacore.parser.*;
43 import org.openide.ErrorManager;
44 import org.openide.util.Utilities;
45
46 /**
47  * Implementation of the JavaClass model element.
48  *
49  * @author Martin Matula
50  * @author Vlado Hudec
51  * @author Pavel Flaska
52  */

53 public abstract class JavaClassImpl extends FeatureImpl implements JavaClass {
54     static final ElementInfo DEFAULT_INFO = new ClassInfo(null, ClassInfo.CLASS_TYPE, null, 0, null, null, null, null, null);
55
56     public static boolean DEBUG = false;
57     
58     public static final String JavaDoc CONTENTS_ATTR = "contents"; // NOI18N
59

60     private LightAttrList contents = null;
61
62     /** List of interfaces */
63     private ReferenceListWrapper interfaces = null;
64
65     private WeakReference JavaDoc subClasses = null;
66     private WeakReference JavaDoc implementors = null;
67
68     private boolean internalSetName = false;
69
70     private boolean elementsInited = false;
71     private MultipartId superClassName;
72     private LightAttrList interfaceNames;
73     private final List featuresList;
74     private LightAttrList typeParameters;
75
76     /** Creates a new instance of JavaClassImpl */
77     public JavaClassImpl(StorableObject s) {
78         super(s);
79         featuresList = new FeaturesList(this);
80     }
81
82     // overrides functionality from FeatureImpl which extracts modifiers from ASTInfo
83
public int getModifiers() {
84         int mods = super_getModifiers();
85         if (isInner()) {
86             ClassDefinition cd = getDeclaringClass();
87             if (cd instanceof JavaClass && ((JavaClass)cd).isInterface()) {
88                 mods |= Modifier.STATIC | Modifier.PUBLIC;
89             }
90         }
91         return ~DEPRECATED & mods;
92     }
93
94     protected abstract void super_setName(String JavaDoc name);
95
96     /** This method enables to set the whole name of the class (including the package prefix).
97      * It is for internal use to synchronize name with changes of the parent package.
98      * Users are not able to change other than the simple name part of the name via the standard
99      * API.
100      */

101     void internalSetName(String JavaDoc name) {
102         internalSetName = true;
103         try {
104             if (JMManager.INCONSISTENCY_DEBUG) System.err.println("JavaClassImpl: Changing name of a class using internalSetName.");
105             if (!name.equals(getName())) {
106                 setName(name);
107             }
108         } finally {
109             internalSetName = false;
110         }
111     }
112
113     public void setName(String JavaDoc name) {
114         if (name.equals(getName())) return;
115         if (JMManager.INCONSISTENCY_DEBUG) System.err.println("JavaClassImpl: Renaming class " + getName() + " to " + name);
116         boolean isTransient = isTransient();
117         if (!internalSetName) {
118             if (!isTransient && getResource()!=null && getResource().getPackageName() != null && !name.startsWith(getResource().getPackageName())) {
119                 throw new ConstraintViolationException(null, null, "Unable to change the package of the class by setting its name (old name: " + getName() + " new name: " + name + " resource package name: " + getResource().getPackageName() + ").");
120             }
121         }
122         
123         objectChanged(CHANGED_NAME);
124
125         if (isInitialized() && !isNew()) {
126             getElementInfo().hardRefAST();
127         }
128         
129         if (!isTransient) {
130             JavaModelPackage srcExtent=(JavaModelPackage)refOutermostPackage();
131             ClassIndex index=ClassIndex.getIndex(srcExtent);
132             if (getName() != null) {
133                 // we have to do rename in class index only in case of there was
134
// any name in this class. (Old name was not null.) This is
135
// related to issue #44244.
136
index.renameClass(this, name);
137             } else {
138                 // the class has no name yet, we have to create it in index
139
// right now.
140
index.addClass(this, name, this.getSimpleName(name));
141             }
142         }
143         super_setName(name);
144         if (isPersisted()) {
145             Object JavaDoc[] features=getContents().toArray();
146             for (int i=0;i<features.length;i++) {
147                 Object JavaDoc temp = features[i];
148                 if (temp instanceof JavaClassImpl && !isTransient) {
149                     JavaClassImpl cls = (JavaClassImpl) temp;
150                     boolean changes = cls.disableChanges;
151                     cls.disableChanges |= this.disableChanges;
152                     try {
153                         cls.internalSetName(name.concat('.' + cls.getSimpleName()));
154                     } finally {
155                         cls.disableChanges = changes;
156                     }
157                 } else if ((temp instanceof ConstructorImpl) && !disableChanges) {
158                     ((ConstructorImpl) temp).objectChanged(CHANGED_NAME);
159                 }
160             }
161         } else {
162             // iterate through inner classes
163
List list = (List) _getDelegate().getSlot3();
164             if (list != null) {
165                 HashSet inner = new HashSet(list);
166                 for (Iterator it = inner.iterator(); it.hasNext();) {
167                     JavaClassImpl cls = (JavaClassImpl) it.next();
168                     boolean changes = cls.disableChanges;
169                     cls.disableChanges |= this.disableChanges;
170                     try {
171                         cls.internalSetName(name.concat('.' + cls.getSimpleName()));
172                     } finally {
173                         cls.disableChanges = changes;
174                     }
175                 }
176             }
177         }
178     }
179
180     public boolean isInner() {
181         if (isTransient()) return true;
182         String JavaDoc name=getName();
183         int lastDot=name.lastIndexOf('.');
184         
185         if (lastDot!=-1) {
186             String JavaDoc outerName=name.substring(0, lastDot);
187             ClassIndex index=ClassIndex.getIndex((JavaModelPackage)refImmediatePackage());
188             
189             return !index.doesnotExist(outerName);
190         }
191         return false;
192     }
193     
194     /**
195      * Returns the value of attribute isInterface.
196      * @return Value of attribute isInterface.
197      */

198     public boolean isInterface() {
199         return Modifier.isInterface(getSourceModifiers());
200     }
201
202     /**
203      * Sets the value of isInterface attribute. See {@link #isInterface} for description
204      * on the attribute.
205      * @param newValue New value to be set.
206      */

207     public void setInterface(boolean newValue) {
208         if (newValue) {
209             setModifiers(getSourceModifiers() | Modifier.INTERFACE);
210         } else {
211             setModifiers(getSourceModifiers() & ~Modifier.INTERFACE);
212         }
213     }
214
215     /**
216      * Returns the value of reference superInterfaces.
217      * @return Value of reference superInterfaces.
218      */

219     public List getInterfaces() {
220         checkUpToDate();
221         if (interfaces == null) {
222             initInterfaces();
223         }
224         return interfaces;
225     }
226     
227     private void initInterfaces() {
228         List interfaceNames = getInterfaceRefs();
229         if (interfaceNames == null) {
230             interfaceNames = new ArrayList();
231         } else if (!(interfaceNames instanceof ArrayList)) {
232             interfaceNames = new ArrayList(interfaceNames);
233         }
234         // list of superinterfaces is transient
235
TypeList _interfaces = new TypeList(this, (ArrayList) interfaceNames) {
236             protected void updateParent() {
237                 setInterfaceRefs(innerList);
238             }
239
240             protected void fireChange(int attrType, TypeRef newTR, int position) {
241                 Object JavaDoc newValue, oldValue;
242                 if (elementsInited) {
243                     newValue = typeRefToTypeReference(newTR, 0);
244                     // [TODO] pass a correct oldValue
245
oldValue = null;
246                 } else {
247                     newValue = oldValue = null;
248                 }
249                 fireAttrChange("interfaceNames", oldValue, newValue, position); // NOI18N
250
}
251         };
252         if (interfaces == null) {
253             ImplementsImpl implementsImpl = (ImplementsImpl)(((JavaModelPackage) refImmediatePackage()).getImplements());
254             interfaces = new ReferenceListWrapper(_getDelegate().getMdrStorage(), implementsImpl, this, "interfaces", this, CHANGED_IMPLEMENTS, _interfaces); // NOI18N
255
} else {
256             interfaces.setInnerList(_interfaces);
257         }
258     }
259
260     private void fireSCNameChange(MultipartId typeReference) {
261         Object JavaDoc oldValue = null;
262         Object JavaDoc newValue = null;
263         if (elementsInited) {
264             oldValue = getSuperClassName();
265             newValue = typeReference;
266         }
267         fireAttrChange("superClassName", oldValue, newValue); // NOI18N
268
}
269     
270     /**
271      * Sets the value of reference superClass. See {@link #getSuperClass} for
272      * description on the reference.
273      * @param newValue New value to be set.
274      */

275     public void setSuperClass(JavaClass newValue) {
276         Extends source = ((JavaModelPackage) refImmediatePackage()).getExtends();
277         if (_getMdrStorage().eventsEnabled()) {
278             AssociationEvent event = new AssociationEvent(
279                 source,
280                 AssociationEvent.EVENT_ASSOCIATION_SET,
281                 this,
282                 "subClasses", // NOI18N
283
getSuperClass(),
284                 newValue,
285                 AssociationEvent.POSITION_NONE);
286             _getMdrStorage().getEventNotifier().ASSOCIATION.firePlannedChange(source, event);
287         }
288         NameRef sc;
289         if (newValue == null) {
290             sc = NameRef.java_lang_Object;
291             newValue = (JavaClass) resolveType(sc);
292         } else {
293             sc = (NameRef) typeToTypeRef(newValue);
294         }
295         MultipartId mpi = (MultipartId) typeRefToTypeReference(sc, 0);
296         fireSCNameChange(mpi);
297         _setSuperClass(sc, mpi);
298     }
299     
300     private void _setSuperClass(NameRef superClass, MultipartId superClassName) {
301         if (!disableChanges) {
302             objectChanged(CHANGED_EXTENDS);
303             changeChild(getSuperClassName(), superClassName);
304             this.superClassName = superClassName;
305         }
306         setSuperclassRef(superClass);
307     }
308
309     public org.netbeans.jmi.javamodel.MultipartId getSuperClassName() {
310         checkUpToDate();
311         if (!elementsInited) {
312             initASTElements();
313         }
314         return superClassName;
315     }
316
317     public void setSuperClassName(org.netbeans.jmi.javamodel.MultipartId newValue) {
318         NameRef sc = (NameRef) typeReferenceToTypeRef(newValue, 0);
319         if (sc == null) {
320             sc = NameRef.java_lang_Object;
321         }
322         _setSuperClass(sc, newValue);
323     }
324
325     /**
326      * Returns the value of reference superClass.
327      * @return Value of reference superClass.
328      */

329     public JavaClass getSuperClass() {
330         JavaClass result;
331         checkUpToDate();
332
333         // for interfaces and java.lang.Object the superclass is always null
334
if ("java.lang.Object".equals(getName())) { // NOI18N
335
result = null;
336         } else if (isInterface()) {
337             result = (JavaClass) resolveType(NameRef.java_lang_Object);
338
339         // if the superclass has changed, the superClass variable is
340
// initialized -> return its content
341
} else {
342             NameRef superClass = getSuperclassRef();
343             if (superClass == null) {
344                 superClass = NameRef.java_lang_Object;
345                 setSuperclassRef(superClass);
346             }
347             result = (JavaClass) resolveType(superClass);
348         }
349
350         if (DEBUG) {
351             System.out.println("getSuperClass: "+result); // NOI18N
352
if (result != null)
353                 System.out.println("getSuperClass: "+result.getName()); // NOI18N
354
}
355         return result;
356     }
357
358     private Collection getSubClasses(boolean deterministicProgress) {
359         if (isInterface()) return Collections.EMPTY_LIST;
360         // see whether there already is a reference to the collection of subClasses for
361
// the passed class/interface
362
ReferenceColWrapper subClasses;
363         if (this.subClasses == null || (subClasses = (ReferenceColWrapper) this.subClasses.get()) == null) {
364             SubClassesCollection coll = new SubClassesCollection(this, deterministicProgress);
365             subClasses = new ReferenceColWrapper(_getMdrStorage(), null, this, null, null, 0, coll);
366             this.subClasses = new WeakReference JavaDoc(subClasses);
367         }
368         return subClasses;
369     }
370     
371     private Collection getImplementors(boolean deterministicProgress) {
372         if (!isInterface()) return Collections.EMPTY_LIST;
373         ReferenceColWrapper implementors;
374         if (this.implementors == null || (implementors = (ReferenceColWrapper) this.implementors.get()) == null) {
375             ImplementorsCollection coll = new ImplementorsCollection(this, deterministicProgress);
376             implementors = new ReferenceColWrapper(_getMdrStorage(), null, this, null, null, 0, coll);
377             this.implementors = new WeakReference JavaDoc(implementors);
378         }
379         return implementors;
380     }
381     
382     public Collection getSubClasses() {
383         return getSubClasses(true);
384     }
385     
386     public Collection getImplementors() {
387         return getImplementors(true);
388     }
389     
390     public Collection findSubTypes(boolean transitively) {
391         if (!transitively) {
392             return isInterface() ? getImplementors() : getSubClasses();
393         } else {
394             JavaMetamodel.getManager().getProgressSupport().fireProgressListenerStart(0, -1);
395             List q = new ArrayList(getImplementors(false));
396             q.addAll(getSubClasses(false));
397             HashSet result = new HashSet();
398             while (!q.isEmpty()) {
399                 JavaClassImpl clazz = (JavaClassImpl) q.remove(0);
400                 result.add(clazz);
401                 q.addAll(clazz.getImplementors(false));
402                 q.addAll(clazz.getSubClasses(false));
403             }
404             JavaMetamodel.getManager().getProgressSupport().fireProgressListenerStop();
405             return result;
406         }
407     }
408
409     public List getPersistentContents() {
410         AttrListWrapper list = (AttrListWrapper) super_getContents();
411         return ClassDefinitionImpl.getPersistentContent(list);
412     }
413
414     /**
415      * Returns the value of attribute contents.
416      * @return Value of contents attribute.
417      */

418     public List getContents() {
419         checkUpToDate();
420         if (contents == null) {
421             contents = createChildrenList(CONTENTS_ATTR, (AttrListWrapper) super_getContents(), null, CHANGED_FEATURES);
422         }
423         return contents;
424     }
425
426     public List getFeatures() {
427         return featuresList;
428     }
429
430     public List getPersistentTypeParameters() {
431         AttrListWrapper list = (AttrListWrapper) super_getTypeParameters();
432         list.setAttrName(TYPE_PARAMETERS_ATTR);
433         return list;
434     }
435     
436     public List getTypeParameters() {
437         checkUpToDate();
438         if (typeParameters == null) {
439             typeParameters = createChildrenList(TYPE_PARAMETERS_ATTR, (AttrListWrapper) super_getTypeParameters(), null, CHANGED_TYPE_PARAMETERS);
440         }
441         return typeParameters;
442     }
443
444     protected abstract List super_getContents();
445
446     public Field getField(String JavaDoc name, boolean includeSupertypes) {
447         return ClassDefinitionImpl.getField(this, name, includeSupertypes);
448     }
449
450     public Method getMethod(String JavaDoc name, List parameters, boolean includeSupertypes) {
451         return ClassDefinitionImpl.getMethod(this, name, parameters, includeSupertypes);
452     }
453
454     public JavaClass getInnerClass(String JavaDoc simpleName, boolean includeSupertypes) {
455         return ClassDefinitionImpl.getInnerClass(this, simpleName, includeSupertypes);
456     }
457
458     public Constructor getConstructor(List parameters, boolean includeSupertypes) {
459         return ClassDefinitionImpl.getConstructor(this, parameters, includeSupertypes);
460     }
461
462     // ---------------------------------------------------------------------
463
// -- Non-JMI public methods -------------------------------------------
464
// ---------------------------------------------------------------------
465

466     public void reinitContents() {
467         assert contents!=null;
468         contents.setInnerList(getPersistentContents(), false);
469     }
470     
471     public boolean contentsInited() {
472         return contents != null;
473     }
474     
475     public Collection getInnerClasses() {
476         Collection inners;
477         
478         if (!isPersisted()) {
479             StorableBaseObject delegate = _getDelegate();
480
481             inners = (Collection) delegate.getSlot3();
482             if (inners==null) {
483                 return Collections.EMPTY_LIST;
484             }
485         } else {
486             Object JavaDoc[] features = getContents().toArray();
487             
488             inners=new ArrayList();
489             for(int i=0;i<features.length;i++) {
490                 Object JavaDoc obj = features[i];
491                 if (obj instanceof JavaClass) {
492                     inners.add(obj);
493                 }
494             }
495         }
496         return Collections.unmodifiableCollection(inners);
497     }
498     
499     public void setParentClass(JavaClassImpl jcls) {
500         try {
501             if (jcls == null) {
502                 Object JavaDoc parent = refImmediateComposite();
503                 ((StorableObject) _getDelegate()).clearComposite();
504                 if (parent instanceof JavaClassImpl) {
505                     ((JavaClassImpl) parent).removeInnerClass(this);
506                 }
507             } else {
508                 ((StorableObject) _getDelegate()).setComposite(jcls._getDelegate(), null, null);
509                 jcls.addInnerClass(this);
510             }
511         } catch (StorageException ex) {
512             ErrorManager.getDefault().notify(ex);
513         }
514     }
515
516     private void addInnerClass(JavaClass javaClass) {
517         StorableBaseObject delegate = _getDelegate();
518         List inner = (List) delegate.getSlot3();
519         if (inner == null) {
520             inner = new ArrayList();
521         }
522         inner.add(javaClass);
523         delegate.setSlot3(inner);
524     }
525
526     private void removeInnerClass(JavaClass javaClass) {
527         StorableBaseObject delegate = _getDelegate();
528         List inner = (List) delegate.getSlot3();
529         if (inner == null) return;
530         if (!inner.remove(javaClass)) {
531             inner.remove(((BaseObjectHandler) javaClass)._getDelegate().getMofId());
532         }
533         delegate.setSlot3(inner);
534     }
535
536     // ----------------------------------------------------------------------
537
// --- Infrastructural methods ------------------------------------------
538
// ----------------------------------------------------------------------
539

540     protected ElementInfo getDefaultInfo() {
541         return DEFAULT_INFO;
542     }
543
544     protected void matchName(ElementInfo info) {
545         if (!Utilities.compareObjects(info.name, this.getName())) {
546             internalSetName(info.name);
547         }
548     }
549     
550     protected void matchPersistent(ElementInfo info) {
551         super.matchPersistent(info);
552
553         ClassInfo newInfo = (ClassInfo) info;
554         
555         if (!isPersisted()) {
556             setPersisted(true);
557             persist();
558             persistChildren(getPersistentList("annotations", super_getAnnotations()), ((FeatureInfo) info).annotations);
559             persistChildren(getPersistentList(TYPE_PARAMETERS_ATTR, super_getTypeParameters()), newInfo.typeParams);
560             setSuperclassRef(newInfo.superclass);
561             setInterfaceRefs(Arrays.asList(newInfo.interfaces));
562             Collection innerClasses = (Collection) _getDelegate().getSlot3();
563             _getDelegate().setSlot3(null);
564             persistChildren(getPersistentList(CONTENTS_ATTR, super_getContents()), newInfo.features);
565             
566             if (innerClasses != null) {
567                 HashSet contents = new HashSet(super_getContents());
568                 for (Iterator it = innerClasses.iterator(); it.hasNext();) {
569                     Object JavaDoc temp = it.next();
570                     if (temp instanceof MOFID) {
571                         temp = _getRepository().getByMofId((MOFID) temp);
572                     }
573                     JavaClassImpl cls = (JavaClassImpl) temp;
574                     if (!contents.contains(cls)) {
575                         try {
576                             ((StorableObject) cls._getDelegate()).clearComposite();
577                         } catch (StorageException e) {
578                             // ignore
579
}
580                         cls.refDelete();
581                     }
582                 }
583             }
584             
585         } else {
586             if (!(this instanceof AnnotationType)) {
587                 processMembers(getTypeParameters(), newInfo.typeParams);
588                 if (!Utilities.compareObjects(newInfo.superclass, getSuperclassRef())) {
589                     setSuperClass((JavaClass) resolveType(newInfo.superclass));
590                 }
591                 processMembers(getInterfaces(), newInfo.interfaces);
592             }
593             processMembers(getAnnotations(), newInfo.annotations);
594             normalizeContents();
595             processMembers(getContents(), newInfo.features);
596         }
597     }
598     
599     protected final void normalizeContents() {
600         for (ListIterator it = getContents().listIterator(); it.hasNext();) {
601             SemiPersistentElement element = (SemiPersistentElement) it.next();
602             if (element instanceof FieldGroupImpl) {
603                 Iterator it2 = ((FieldGroupImpl) element).getPersistentFields().iterator();
604                 SemiPersistentElement field = null;
605                 if (it2.hasNext()) {
606                     field = (SemiPersistentElement) it2.next();
607                 }
608                 if (!it2.hasNext()) {
609                     it.remove();
610                     if (field != null) {
611                         it2.remove();
612                         ((FieldGroupImpl) element).reinitFields();
613                         it.add(field);
614                     }
615                     element.refDelete();
616                 }
617             }
618         }
619     }
620     
621     /** The method has to make sure that the AST infos of children are also updated.
622      */

623     protected void matchElementInfo(ElementInfo newInfo) {
624         super.matchElementInfo(newInfo);
625         resetASTElements();
626     }
627
628     public void childChanged(MetadataElement mpi) {
629         super.childChanged(mpi);
630         if (elementsInited) {
631             if (mpi == superClassName) {
632                 setSuperClassName((MultipartId) mpi);
633             }
634         }
635     }
636
637     public String JavaDoc toString() {
638         return "class " + getName(); // NOI18N
639
}
640
641     protected void resetChildren() {
642         super.resetChildren();
643         if (contents != null) contents.setInnerList(getPersistentContents());
644         if (typeParameters != null) typeParameters.setInnerList(getPersistentList(TYPE_PARAMETERS_ATTR, super_getTypeParameters()));
645         if (childrenInited) {
646             resetASTElements();
647             initChildren();
648         }
649         if (interfaces != null) {
650             initInterfaces();
651         }
652     }
653
654     protected List getInitedChildren() {
655         List list = super.getInitedChildren();
656         if (childrenInited) {
657             list.addAll(getTypeParameters());
658             list.addAll(getContents());
659         }
660         if (elementsInited) {
661             addIfNotNull(list, superClassName);
662             list.addAll(interfaceNames);
663         }
664         return list;
665     }
666
667     public List getChildren() {
668         List list = super.getChildren();
669         list.addAll(getTypeParameters());
670         addIfNotNull(list, getSuperClassName());
671         list.addAll(getInterfaceNames());
672         list.addAll(getContents());
673         return list;
674     }
675
676     public void fixImports(Element scope, Element original) {
677         JavaClass jcls=(JavaClass)original;
678
679         if (!(jcls instanceof AnnotationType)) {
680             fixImports(scope,getTypeParameters(),jcls.getTypeParameters());
681             if (getSuperClassName()!=null) {
682                 setSuperClassName(JavaModelUtil.resolveImportsForClass(scope,jcls.getSuperClass()));
683             }
684             fixImportsInClassList(scope,getInterfaceNames(),jcls.getInterfaces());
685         }
686         fixImports(scope,getContents(),jcls.getContents());
687         super.fixImports(scope,original);
688     }
689
690     /** This method is called when this element is accessed while bypassing
691      * parent (e.g. using getByMofId()) and thus its ASTInfo needs to be
692      * initialized by its parent.
693      *
694      * Preciselly: This method is invoked from getElementInfo of a child object
695      * if it finds out that ASTInfo was not initialized by its parent (i.e.
696      * this object), yet.
697      * This method should also be called whenever a getter method
698      * for children of this object is called and the children have not
699      * been initialized yet.
700      */

701     protected void initChildren() {
702         // initialization of contents requires writable lock
703
boolean fail = true;
704         _lock(true);
705         try {
706             childrenInited = false;
707             FeatureInfo[] featureInfos = ((ClassInfo) getElementInfo()).features;
708             List featuresCollection = ClassDefinitionImpl.getNakedFeatures(this);
709             boolean needsReset = false;
710             
711             // contents collection was not empty, so it was initialized
712
// in the past and should be in sync. - we just need to
713
// set ASTInfo to all the elements
714
if (!isNew() && (featuresCollection.size() != featureInfos.length)) {
715                 fixMembers(featuresCollection, featureInfos);
716                 needsReset = true;
717             } else {
718                 ListIterator it = featuresCollection.listIterator();
719                 for (int i = 0; i < featureInfos.length; i++) {
720                     SemiPersistentElement element = (SemiPersistentElement) it.next();
721                     if (element instanceof FieldGroup && featureInfos[i] instanceof FieldInfo) {
722                         it.remove();
723                         Iterator it2 = ((FieldGroup) element).getFields().iterator();
724                         SemiPersistentElement field;
725                         if (it2.hasNext()) {
726                             field = (SemiPersistentElement) it.next();
727                             it2.remove();
728                             field.setElementInfo(featureInfos[i]);
729                         } else {
730                             field = createElement(featureInfos[i]);
731                         }
732                         element.refDelete();
733                         it.add(field);
734                         needsReset = true;
735                     } else {
736                         if (checkElementType(featureInfos[i], element)) {
737                             element.setElementInfo(featureInfos[i]);
738                         } else {
739                             JMManager.getLog().log(ErrorManager.WARNING, "Inconsistent storage - feature types do not match.");
740                             fixMembers(featuresCollection, featureInfos);
741                             needsReset = true;
742                             break;
743                         }
744                     }
745                 }
746             }
747
748             // now we need to either create a new wrapper for the
749
// contents collection, or if the wrapper already exists,
750
// we need to set the collection to it.
751
// It is important not to discard the wrapper when doing
752
// rollback, so that clients that hold references to it
753
// will not break (we will just replace the inner list of
754
// the wrapper)
755
if (contents != null && needsReset) {
756                 contents.setInnerList(getPersistentContents());
757             }
758
759             typeParameters = createChildrenList(typeParameters, TYPE_PARAMETERS_ATTR, (AttrListWrapper) super_getTypeParameters(), ((ClassInfo) getElementInfo()).typeParams, CHANGED_TYPE_PARAMETERS); // NOI18N
760
super.initChildren();
761
762             childrenInited = true;
763
764             if (elementsInited) {
765                 initASTElements();
766             }
767             fail = false;
768         } catch (RuntimeException JavaDoc e) {
769             e.printStackTrace();
770             throw e;
771         } finally {
772             // I do not need to set featuresInitialized to false in
773
// case fail == true, since rollback will follow, thus the
774
// reset method that already does that will be invoked
775
_unlock(fail);
776         }
777     }
778
779     protected void setData(List annotations, java.lang.String JavaDoc javadocText, JavaDoc javadoc, List features, MultipartId superClassName, List interfaceNames, List typeParameters) {
780         super.setData(annotations, javadocText, javadoc);
781         this.contents = createChildrenList(CONTENTS_ATTR, (AttrListWrapper) super_getContents(), features, CHANGED_FEATURES); // NOI18N
782
changeChild(null, superClassName);
783         this.superClassName = superClassName;
784         this.interfaceNames = createChildrenList("interfaceNames", interfaceNames, CHANGED_IMPLEMENTS); // NOI18N
785
this.typeParameters = createChildrenList(TYPE_PARAMETERS_ATTR, (AttrListWrapper) super_getTypeParameters(), typeParameters, CHANGED_TYPE_PARAMETERS); // NOI18N
786
elementsInited = true;
787     }
788     
789     protected abstract List super_getTypeParameters();
790
791     // .........................................................................
792
// printing and formatting fuctionality
793
// .........................................................................
794

795     /**
796      * For the top level classes, do not do indent (use empty string),
797      * otherwise use default indentation.
798      *
799      * @return indentation or empty string in case of top level class
800      */

801     protected String JavaDoc getIndentation() {
802         // if this is inner class, use default indentation defined in
803
// semipersitent element, otherwise return empty string as indentation
804
RefFeatured composite = refImmediateComposite();
805         if (composite instanceof JavaClass)
806             return super.getIndentation();
807         else
808             return "";
809     }
810
811     String JavaDoc getRawText() {
812         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
813         if (isNew()) {
814             generateNewJavaDoc(buf);
815         }
816         generateNewModifiers(buf);
817         if (!isInterface()) {
818             buf.append("class "); // NOI18N
819
} else {
820             buf.append("interface "); // NOI18N
821
}
822         buf.append(getSimpleName());
823         generateNewTypeParameters(buf);
824         if (superClassName != null) {
825             formatElementPart(EXTENDS_KEYWORD, buf);
826             buf.append(((MetadataElement)superClassName).getSourceText());
827         }
828         generateNewImplements(buf);
829         ClassDefinitionImpl.generateNewFeatures(this, buf, true);
830         return buf.toString();
831     }
832
833     private void generateNewTypeParameters(StringBuffer JavaDoc buf) {
834         Collection typeParameters = getTypeParameters();
835         if (!typeParameters.isEmpty()) {
836             buf.append('<');
837             Iterator it = typeParameters.iterator();
838             while (it.hasNext()) {
839                 buf.append(((TypeParameterImpl) it.next()).getSourceText());
840                 if (it.hasNext()) {
841                     formatElementPart(COMMA, buf);
842                 }
843             }
844             buf.append('>');
845         }
846     }
847
848     /**
849      *
850      */

851     public void getDiff(List diffList) {
852         ClassInfo astInfo = (ClassInfo) getElementInfo();
853         ASTProvider parser = getParser();
854         ASTree[] children = getASTree().getSubTrees();
855
856         // javadoc print
857
replaceJavaDoc(diffList);
858         // print modifiers
859
if (isChanged(CHANGED_MODIFIERS | CHANGED_ANNOTATION)) {
860             diffModifiers(diffList, parser.getToken(children[IDENTIFIER].getFirstToken() - 1), parser);
861         } else if (children[0] != null) {
862             getCollectionDiff(diffList, parser, CHANGED_ANNOTATION, astInfo.annotations, getAnnotations(), parser.getToken(children[0].getLastToken()).getEndOffset(), " "); // NOI18N
863
}
864         // print name
865
if (isChanged(CHANGED_NAME)) {
866             replaceNode(diffList, parser, children[IDENTIFIER], getSimpleName(), 0, null);
867         }
868
869         if (astInfo.typeParams.length == 0) {
870             if (isChanged(CHANGED_TYPE_PARAMETERS)) {
871                 StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
872                 generateNewTypeParameters(buf);
873                 int endOffset = getEndOffset(parser, children[IDENTIFIER]);
874                 diffList.add(new DiffElement(endOffset, endOffset, buf.toString()));
875             }
876         } else if (getTypeParameters().isEmpty()) {
877             if (isChanged(CHANGED_TYPE_PARAMETERS)) {
878                 replaceNode(diffList, parser, children[2], "", 0, null);
879             }
880         } else {
881             getCollectionDiff(diffList, parser, CHANGED_TYPE_PARAMETERS, astInfo.typeParams, getTypeParameters(), parser.getToken(children[2].getLastToken()).getStartOffset(), ", "); // NOI18N
882
}
883
884         // print superclass
885

886         if (isChanged(CHANGED_EXTENDS)) {
887             int startOffset, endOffset;
888             String JavaDoc extendsText = superClassName == null?"":((MetadataElement) superClassName).getSourceText();
889             // if the extends clause exists
890
if (children[SUPERCLASS] != null) {
891                 startOffset = parser.getToken(children[SUPERCLASS].getFirstToken()+(superClassName==null?0:1)).getStartOffset();
892                 endOffset = parser.getToken(children[SUPERCLASS].getLastToken()).getEndOffset();
893                 diffList.add(new DiffElement(startOffset, endOffset, extendsText));
894             }
895             // add whole extends clause
896
else if (superClassName != null) {
897                 int index = children[TYPE_PARAMETERS] != null ? TYPE_PARAMETERS : IDENTIFIER;
898                 startOffset = endOffset = parser.getToken(children[index].getLastToken()).getEndOffset();
899                 extendsText = formatElementPart(EXTENDS_KEYWORD) + extendsText;
900                 diffList.add(new DiffElement(startOffset, endOffset, extendsText));
901             }
902         } else {
903             getChildDiff(diffList, parser, children[SUPERCLASS], (MetadataElement) getSuperClassName(), CHANGED_EXTENDS);
904         }
905
906         // interfaces
907
int index = children[SUPERCLASS] != null ? SUPERCLASS : (children[TYPE_PARAMETERS] != null ? TYPE_PARAMETERS : IDENTIFIER);
908         int startOffset = parser.getToken(children[index].getLastToken()).getEndOffset();
909         String JavaDoc prefix = isInterface() ? formatElementPart(EXTENDS_KEYWORD) : formatElementPart(IMPLEMENTS_KEYWORD);
910         getCollectionDiff(diffList, parser, CHANGED_IMPLEMENTS, getASTree().getSubTrees()[INTERFACES],
911                 getInterfaceNames(), startOffset, formatElementPart(COMMA), prefix);
912         // contents diff
913
getCollectionDiff(diffList, parser, CHANGED_FEATURES, astInfo.features, getContents(), getContentsEndOffset(parser, getASTree()), "\n"); // NOI18N
914
}
915     
916     protected int getStartOffset2(ASTProvider parser, ASTree tree) {
917         Token startToken = parser.getToken(tree.getFirstToken());
918         Token firstToken = startToken;
919         int startOffset = -1;
920         Token[] pad = startToken.getPadding();
921         if (pad.length > 0) {
922             startToken = pad[0];
923             for (int i = 0; i < pad.length; i++) {
924                 if (pad[i].getType() == ParserTokens.EOL && startOffset < 0) {
925                     String JavaDoc value = parser.getText(pad[i]);
926                     startOffset = pad[i].getStartOffset() + value.indexOf('\n') + 1;
927                 } else if (pad[i].getType() == ParserTokens.DOC_COMMENT) {
928                     break;
929                 } else if ((pad[i].getType() == ParserTokens.COMMENT) || (pad[i].getType() == ParserTokens.EOL_COMMENT)) {
930                     startOffset = -1;
931                     startToken = i + 1 < pad.length ? pad[i + 1] : firstToken;
932                 }
933             }
934         }
935         if (startOffset > -1) {
936             return startOffset;
937         }
938         return startToken.getStartOffset();
939     }
940     
941     
942     protected final int getContentsEndOffset(ASTProvider parser, ASTree tree) {
943         Token closeBrace = parser.getToken(tree.getLastToken());
944         Token[] pad = closeBrace.getPadding();
945         int endOffset = closeBrace.getStartOffset();
946         for (int i = pad.length - 1; i >= 0; i--) {
947             switch (pad[i].getType()) {
948                 case ParserTokens.EOL_COMMENT:
949                 case ParserTokens.COMMENT:
950                 case ParserTokens.DOC_COMMENT:
951                     i = 0;
952                     break;
953                 case ParserTokens.EOL:
954                     endOffset = pad[i].getStartOffset();
955             }
956         }
957         return endOffset;
958     }
959
960     protected ASTree getPartTree(ElementPartKind part) {
961         if (ElementPartKindEnum.NAME.equals(part)) {
962             return getASTree().getSubTrees()[IDENTIFIER];
963         }
964         throw new IllegalArgumentException JavaDoc("Invalid part for this element: " + part); // NOI18N
965
}
966
967     public void replaceChild(Element oldElement, Element newElement) {
968         if (oldElement instanceof JavaClass && newElement == null) {
969             removeInnerClass((JavaClass) oldElement);
970         }
971         List contents, typeParameters;
972         if (isPersisted()) {
973             contents = getContents();
974             typeParameters = getTypeParameters();
975         } else {
976             contents = super_getContents();
977             typeParameters = super_getTypeParameters();
978         }
979         if (replaceObject(contents, oldElement, newElement)) return;
980         if (replaceObject(typeParameters, oldElement, newElement)) return;
981         if (elementsInited) {
982             if (oldElement.equals(superClassName)) {
983                 setSuperClassName((MultipartId) newElement);
984                 return;
985             }
986             if (replaceObject(interfaceNames, oldElement, newElement)) return;
987         }
988         super.replaceChild(oldElement, newElement);
989     }
990
991     protected ASTree getPartStartTree(ElementPartKind part) {
992         if (ElementPartKindEnum.HEADER.equals(part)) {
993             return getASTree();
994         }
995         return super.getPartStartTree(part);
996     }
997
998     protected ASTree getPartEndTree(ElementPartKind part) {
999         if (ElementPartKindEnum.HEADER.equals(part)) {
1000            for (int i = 4; true; i--) {
1001                ASTree result = getASTree().getSubTrees()[i];
1002                if (result != null) {
1003                    return result;
1004                }
1005            }
1006        }
1007        return super.getPartEndTree(part);
1008    }
1009
1010    // useful constants
1011
private static final int IDENTIFIER = 1;
1012    private static final int TYPE_PARAMETERS = 2;
1013    private static final int SUPERCLASS = 3;
1014    private static final int INTERFACES = 4;
1015
1016    // ---------------------------------------------------------------------
1017
// --- Private methods -------------------------------------------------
1018
// ---------------------------------------------------------------------
1019
/**
1020     * Prints the whole interfaces clause with the appropriate formatting.
1021     * (E.g. ' implements java.io.Serializable, java.io.Externalizable ').
1022     *
1023     * @param buf buffer to append implements clause to
1024     */

1025    protected void generateNewImplements(StringBuffer JavaDoc buf) {
1026        Collection interfaces = getInterfaceNames();
1027        if (!interfaces.isEmpty()) {
1028            if (isInterface()) {
1029                formatElementPart(EXTENDS_KEYWORD, buf);
1030            } else {
1031                formatElementPart(IMPLEMENTS_KEYWORD, buf);
1032            }
1033            Iterator it = interfaces.iterator();
1034            MultipartIdImpl impl = (MultipartIdImpl) it.next();
1035            buf.append(impl.getSourceText());
1036            while (it.hasNext()) {
1037                formatElementPart(COMMA, buf);
1038                impl = (MultipartIdImpl) it.next();
1039                buf.append(impl.getSourceText());
1040            }
1041        }
1042    }
1043
1044    public static String JavaDoc getSimpleName(String JavaDoc name) {
1045        if (name == null) return null;
1046        int lastDot = name.lastIndexOf('.');
1047
1048        if (lastDot != -1)
1049            return name.substring(lastDot + 1);
1050        return name;
1051    }
1052
1053    public String JavaDoc getSimpleName() {
1054        return getSimpleName(getName());
1055    }
1056
1057    public void setSimpleName(String JavaDoc name) {
1058        String JavaDoc fullName = getName();
1059        if (fullName!=null) {
1060            int index = fullName.lastIndexOf('.');
1061            if (index >= 0) {
1062                name = fullName.substring(0, index + 1) + name;
1063            }
1064        }
1065        setName(name);
1066    }
1067
1068    protected void _delete() {
1069        if (DEBUG) {
1070            System.out.println("removing class: " + getName() + " MOFID: " + refMofId()); // NOI18N
1071
if (refImmediateComposite() != null) {
1072                System.out.println(" in resource: " + ((NamedElement) refImmediateComposite()).getName()); // NOI18N
1073
}
1074            Thread.dumpStack();
1075        }
1076        // --- delete components -------------------------------------------
1077
// delete all parameters (if initialized)
1078
deleteChildren(TYPE_PARAMETERS_ATTR, (AttrListWrapper) super_getTypeParameters());
1079        // delete all contents
1080
if (isPersisted()) {
1081            for (Iterator it = getPersistentContents().iterator(); it.hasNext();) {
1082                RefObject feature = (RefObject) it.next();
1083                it.remove();
1084                feature.refDelete();
1085            }
1086        } else {
1087            List inner = (List) _getDelegate().getSlot3();
1088            if (inner != null) {
1089                for (Iterator it = inner.iterator(); it.hasNext();) {
1090                    Object JavaDoc temp = it.next();
1091                    if (temp instanceof MOFID) {
1092                        temp = _getRepository().getByMofId((MOFID) temp);
1093                    }
1094                    JavaClass cls = (JavaClass) temp;
1095                    it.remove();
1096                    cls.refDelete();
1097                }
1098            }
1099        }
1100        _getDelegate().setSlot3(null);
1101        if (elementsInited) {
1102            deleteChild(superClassName);
1103            deleteChildren(interfaceNames);
1104        }
1105        super._delete();
1106    }
1107
1108    protected void parentChanged() {
1109        parent = refImmediateComposite();
1110        String JavaDoc prefix;
1111        if (parent instanceof Resource) {
1112            prefix = ((Resource) parent).getPackageName();
1113        } else if (parent instanceof JavaClass) {
1114            prefix = ((JavaClass) parent).getName();
1115        } else {
1116            prefix = "";
1117        }
1118        boolean changes = disableChanges;
1119        disableChanges = true;
1120        try {
1121            internalSetName((prefix == null || prefix.length() == 0) ? getSimpleName() : (prefix + '.' + getSimpleName()));
1122        } finally {
1123            disableChanges = changes;
1124        }
1125    }
1126
1127    public java.util.List JavaDoc getInterfaceNames() {
1128        if (!elementsInited) {
1129            initASTElements();
1130        }
1131        return interfaceNames;
1132    }
1133
1134    protected void initASTElements() {
1135        elementsInited = false;
1136        if (!childrenInited) {
1137            initChildren();
1138        }
1139        ClassInfo info = (ClassInfo) getElementInfo();
1140        ASTree superClass = info.getTypeAST(this);
1141        ASTree[] interfaces = info.getInterfacesAST(this);
1142        superClassName = (MultipartId) initOrCreate(superClassName, superClass);
1143        interfaceNames = createChildrenList(interfaceNames, "interfaceNames", interfaces, CHANGED_IMPLEMENTS, false); // NOI18N
1144
elementsInited = true;
1145    }
1146
1147    protected void resetASTElements() {
1148        if (elementsInited) {
1149            if (superClassName != null) {
1150                MultipartId temp = superClassName;
1151                changeChild(superClassName, null);
1152                superClassName = null;
1153                temp.refDelete();
1154            }
1155            deleteChildren(interfaceNames);
1156            interfaceNames = null;
1157            elementsInited = false;
1158        }
1159    }
1160    
1161    public boolean isSubTypeOf(ClassDefinition clazz) {
1162        return ClassDefinitionImpl.isSubTypeOf(this, clazz);
1163    }
1164    
1165    protected void setSuperclassRef(NameRef sc) {
1166        _getDelegate().setSlot1(sc);
1167    }
1168    
1169    public NameRef getSuperclassRef() {
1170        return (NameRef) _getDelegate().getSlot1();
1171    }
1172    
1173    protected void setInterfaceRefs(List ifcs) {
1174        _getDelegate().setSlot2(ifcs);
1175    }
1176    
1177    public List getInterfaceRefs() {
1178        return (List) _getDelegate().getSlot2();
1179    }
1180    
1181    public Element duplicate(JavaModelPackage targetExtent) {
1182        return targetExtent.getJavaClass().createJavaClass(
1183                getName(),
1184                duplicateList(getAnnotations(), targetExtent),
1185                getModifiers(),
1186                null,
1187                (JavaDoc) duplicateElement(getJavadoc(), targetExtent),
1188                duplicateList(getContents(), targetExtent),
1189                (MultipartId) duplicateElement(getSuperClassName(), targetExtent),
1190                duplicateList(getInterfaceNames(), targetExtent),
1191                duplicateList(getTypeParameters(), targetExtent)
1192               );
1193    }
1194}
1195
Popular Tags