KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > bridge > ClassElementImpl


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

21
22 import java.beans.*;
23 import java.util.*;
24 import java.lang.reflect.Modifier JavaDoc;
25 import org.netbeans.api.mdr.events.AssociationEvent;
26 import org.netbeans.jmi.javamodel.ParameterizedType;
27 import org.openide.ErrorManager;
28
29 import org.openide.nodes.Node;
30 import org.openide.src.*;
31
32 import org.netbeans.api.mdr.events.*;
33
34 import javax.jmi.reflect.RefObject;
35 import javax.jmi.reflect.RefBaseObject;
36 import org.netbeans.jmi.javamodel.AnnotationType;
37
38 import org.netbeans.jmi.javamodel.JavaClass;
39 import org.netbeans.jmi.javamodel.ClassDefinition;
40 import org.netbeans.jmi.javamodel.Method;
41 import org.netbeans.jmi.javamodel.Constructor;
42 import org.netbeans.jmi.javamodel.Feature;
43 import org.netbeans.jmi.javamodel.Field;
44 import org.netbeans.jmi.javamodel.Initializer;
45 import org.netbeans.jmi.javamodel.Extends;
46 import org.netbeans.jmi.javamodel.Implements;
47 import org.netbeans.jmi.javamodel.MultipartId;
48 import org.netbeans.jmi.javamodel.TypeReference;
49 import org.netbeans.jmi.javamodel.JavaEnum;
50
51 /**
52  * Models a class in a source - either a nested/local class, top-level class or an inner class.
53  *
54  * @author Svatopluk Dedic
55  * @version 0.1
56  * @since 24/11/2000
57  */

58 class ClassElementImpl extends MemberElementImpl implements ClassElement.Impl, ElementOrder {
59     /** Uplink to the implementation of the source element. The link is made during
60      * attaching the abstract Element to the implementation.
61      */

62     private SourceElementImpl sourceImpl;
63     
64     /**
65      * Reference to the enclosing element's implementation; the reference is identical
66      * to getDeclaringImpl() if the class is an inner class, but it is different, if
67      * the class is a nested or local class.
68      */

69     private ElementImpl parentImpl;
70         
71     transient FieldsCollection fields;
72     
73     transient MethodsCollection methods;
74     
75     transient ConstructorsCollection constructors;
76     
77     transient InitializersCollection initializers;
78     
79     transient ClassesCollection innerClasses;
80     
81     transient FeaturesCollection members;
82
83     private static IdentifierArrayProperty identSupport;
84     
85     private IdentContextSupport identSupp;
86
87     private static final long serialVersionUID = -7718381719188756697L;
88     
89     private ElementImpl.ElementListener classListener, featuresListener;
90     
91     // Construction
92
///////////////////////////////////////////////////////////////////////////////////
93

94     static {
95         // initialize flyweight property support.
96
identSupport = new InterfaceSupport();
97     }
98     
99     ClassElementImpl(DefaultLangModel model, JavaClass javaClass) {
100         super(model, javaClass);
101         init ();
102     }
103     
104     public void connectListener () {
105         classListener = new ClassListener (this);
106         classListener.connect ();
107         featuresListener = new ObjectsCollection.FeaturesListener (this);
108         featuresListener.connect ();
109     }
110         
111     private void init () {
112         identSupp = new IdentContextSupport(37);
113         javadoc = new JavaDocImpl.Class(null, this);
114
115         members = new FeaturesCollection (this);
116         fields = new FieldsCollection (members);
117         methods = new MethodsCollection (members);
118         constructors = new ConstructorsCollection (members);
119         initializers = new InitializersCollection (members);
120         innerClasses = new ClassesCollection (members);
121     }
122     
123     protected Identifier createName(String JavaDoc fullName) {
124         String JavaDoc simpleName = fullName;
125         int index = simpleName.lastIndexOf('.');
126         
127         if (index!=-1) {
128             simpleName=simpleName.substring(index+1);
129         }
130         return Identifier.create(fullName,simpleName,Identifier.RESOLVED);
131     }
132     
133     protected void createFromModel(Element model) throws SourceException {
134         ClassElement c = (ClassElement)model;
135
136         // PENDING: set these directly.
137
super.createFromModel(model);
138         setClassOrInterface(c.isClassOrInterface());
139         setSuperclass(c.getSuperclass());
140
141         // member elements need the Element already.
142
changeInterfaces(c.getInterfaces(), ClassElement.Impl.ADD);
143         changeInitializers(c.getInitializers(), ClassElement.Impl.ADD);
144         
145         changeFields(c.getFields(), ClassElement.Impl.ADD);
146         changeConstructors(c.getConstructors(), ClassElement.Impl.ADD);
147         changeMethods(c.getMethods(), ClassElement.Impl.ADD);
148         changeClasses(c.getClasses(), ClassElement.Impl.ADD);
149         
150         setJavaDocText(c.getJavaDoc().getRawText(), true);
151     }
152     
153     public JavaDoc.Class getJavaDoc() {
154         updateJavadoc();
155         return (JavaDoc.Class)javadoc;
156     }
157     
158     public final void setParent(ElementImpl impl) {
159         super.setParent(impl);
160         if (impl instanceof SourceElementImpl) {
161             sourceImpl = (SourceElementImpl)impl;
162         }
163     }
164             
165     // Public operations
166
///////////////////////////////////////////////////////////////////////////////////
167
/*
168     public final Node.Cookie getCookie(Class clazz) {
169         Node.Cookie ret = super.getCookie(clazz);
170         if (ret != null || sourceImpl == null)
171             return ret;
172         return sourceImpl.getCookie(clazz);
173     }
174      */

175
176     // Getters
177
///////////////////////////////////////////////////////////////////////////////////
178
/**
179      * Returns true, iff the class is a proper class. False, if the element represents
180      * an interface.
181      * @return true, if representing a class.
182      */

183     public boolean isClassOrInterface() {
184         repository.beginTrans(false);
185         try {
186             if (javaElement.isValid())
187                 return !((JavaClass) javaElement).isInterface ();
188             else
189                 return false;
190         } finally {
191             repository.endTrans();
192         }
193     }
194     
195     public Identifier getName() {
196         repository.beginTrans(false);
197         try {
198             if (javaElement.isValid()) {
199                 setClassPath();
200                 return createName (typeToFullName((JavaClass) javaElement));
201             } else {
202                 return cachedName != null ? cachedName : Identifier.create ("");
203             }
204         } finally {
205             repository.endTrans(false);
206         }
207     }
208     
209     public int getModifiers () {
210         return super.getModifiers () & ~Modifier.INTERFACE;
211     }
212     
213     public Identifier getSuperclass() {
214         repository.beginTrans(false);
215         try {
216             if (javaElement.isValid()) {
217                 setClassPath();
218                 JavaClass sup = ((JavaClass) javaElement).getSuperClass ();
219                 return sup != null ? createClassIdentifier (typeToFullName(sup)) : null;
220             } else {
221                 return Identifier.create (""); // NOI18N
222
}
223         } finally {
224             repository.endTrans(false);
225         }
226     }
227     
228     public Identifier[] getInterfaces() {
229         repository.beginTrans (false);
230         try {
231             if (javaElement.isValid()) {
232                 setClassPath();
233                 Collection list = ((JavaClass) javaElement).getInterfaceNames ();
234                 Identifier [] superinterfaces = new Identifier [list.size ()];
235                 Iterator iter = list.iterator ();
236                 for (int x = 0; iter.hasNext (); x++) {
237                     superinterfaces [x] = createClassIdentifier ((MultipartId) iter.next ());
238                 }
239                 return superinterfaces;
240             } else {
241                 return new Identifier[0];
242             }
243         } finally {
244             repository.endTrans (false);
245         }
246     }
247     
248     // Setters/changers
249
///////////////////////////////////////////////////////////////////////////////////
250

251     /**
252      * Sets the desired superclass. The implementation will attempt to check the
253      * passed identifier and will attempt to preserve the semantic meaning of the
254      * Identifier when updating the model.
255      * @param superclass the identifier of the new superclass.
256      * @throw SourceException if the source cannot be locked, veto on the property change is
257      * issued, the superclass' identifier is not reachable or there's some I/O or race error
258      * during the operation.
259      */

260     public void setSuperclass(Identifier superclass) throws SourceException {
261         checkWritable(true);
262         checkDocument();
263         boolean failed = false;
264         repository.beginTrans (true);
265         try {
266             if (javaElement.isValid()) {
267                 setClassPath();
268                 superclass = resolveIdent(superclass);
269                 Identifier old = getSuperclass ();
270                 PropertyChangeEvent evt;
271
272                 if (superclass == old ||
273                     (superclass != null && old != null &&
274                     compareSourceIdentifiers(old, superclass))) {
275                     // no change at all.
276
return;
277                 }
278                 evt = new PropertyChangeEvent(getElement(), PROP_SUPERCLASS,
279                     old, superclass
280                 );
281                 checkVetoablePropertyChange(evt);
282
283                 String JavaDoc superName = superclass != null ? superclass.getFullName() : JAVA_LANG_OBJECT;
284                 MultipartId superClass = javaModelPackage.getMultipartId().createMultipartId(superName, null, null);
285                 ((JavaClass) javaElement).setSuperClassName(superClass);
286                 failed = false;
287             } else {
288                 failed = false;
289                 throwIsInvalid ();
290             }
291         } finally {
292             repository.endTrans (failed);
293         }
294     }
295     
296     public void fireSuperclassChange (Identifier oldValue, Identifier newValue) {
297         if ((oldValue == newValue) ||
298             (oldValue != null && newValue != null &&
299             compareSourceIdentifiers(oldValue, newValue)))
300             return;
301         PropertyChangeEvent evt = new PropertyChangeEvent(getElement(), PROP_SUPERCLASS, oldValue, newValue);
302         fireOwnPropertyChange(evt);
303         
304         ClassElement old = (ClassElement) cloneSelf ();
305         try {
306             old.setSuperclass (oldValue);
307         } catch (SourceException e) {
308             e.printStackTrace ();
309         }
310         notifyConnectionChange (old);
311     }
312     
313     Identifier[] filterInterfaces(Identifier[] its) {
314         if (its.length == 0)
315             return its;
316         Identifier[] oldIts = getInterfaces();
317         Collection newState = null;
318         for (int i = 0; i < its.length; i++) {
319             boolean matches = false;
320             for (int j = 0; j < oldIts.length; j++) {
321                 if (its[i].getSourceName().equals(oldIts[j].getSourceName())) {
322                     matches = true;
323                     break;
324                 }
325             }
326             if (!matches) {
327                 if (newState != null)
328                     newState.add(its[i]);
329             } else if (newState == null) {
330                 newState = new ArrayList(its.length);
331                 for (int k = 0; k < i; k++)
332                     newState.add(its[k]);
333             }
334         }
335         if (newState == null)
336             return its;
337         else
338             return (Identifier[])newState.toArray(new Identifier[newState.size()]);
339     }
340         
341     /**
342      * Sets the interfaces implemented by the class.
343      * @param interfaces collection of affected interfaces. If added, the values are
344      * appended at the end of the interface property.
345      * @param operation ADD, REMOVE or SET depending on the operation being performed.
346      */

347     public void changeInterfaces(Identifier[] interfaces, int operation) throws SourceException {
348         checkWritable(operation == SET);
349         checkDocument();
350         boolean failed = true;
351         repository.beginTrans (true);
352         try {
353             if (javaElement.isValid()) {
354                 setClassPath();
355                 Identifier[] newValue;
356                 PropertyChangeEvent evt;
357
358                 // TODO: resolve interface identifiers, one by one, to preserve the semantic
359
// meaning and create a suitable representation.
360
switch (operation) {
361                     case ADD:
362                         evt = identSupport.add(this, filterInterfaces(interfaces));
363                         if (evt == null) {
364                             failed = false;
365                             return;
366                         }
367                         newValue = (Identifier[])evt.getNewValue();
368                         break;
369                     case REMOVE:
370                         evt = identSupport.remove(this, interfaces);
371                         if (evt == null) {
372                             failed = false;
373                             return;
374                         }
375                         newValue = (Identifier[])evt.getNewValue();
376                         break;
377                     // ugly generic case:
378
case SET:
379                         newValue = interfaces;
380                         evt = identSupport.createChangeEvent(getElement(),
381                             getInterfaces (), interfaces);
382                         if (evt == null) {
383                             failed = false;
384                             return;
385                         }
386                         break;
387                     default:
388                         throw new IllegalArgumentException JavaDoc("Unknown operation: " + operation); // NOI18N
389
}
390
391                 checkVetoablePropertyChange(evt);
392
393                 List inters = ((JavaClass)javaElement).getInterfaceNames ();
394
395                 if (operation == REMOVE) {
396                     for (int x = 0; x < interfaces.length; x++) {
397                         String JavaDoc fqn = interfaces[x].getSourceName();
398                         ListIterator iter = inters.listIterator ();
399                         while (iter.hasNext ()) {
400                             MultipartId id = (MultipartId) iter.next ();
401                             if (fqn.equals(multipartIdToName(id))) {
402                                 iter.remove ();
403                                 break;
404                             }
405                         } // while
406
} // for
407
} else { // SET or ADD
408
Collection oldInters = new LinkedList ();
409                     Collection temp = new LinkedList ();
410                     for (int x = 0; x < interfaces.length; x++) {
411                         temp.add(javaModelPackage.getMultipartId().createMultipartId(interfaces[x].getFullName(), null, null));
412                     }
413                     if (operation == SET)
414                         inters.clear();
415                     inters.addAll (temp);
416                 }
417                 failed = false;
418             } else {
419                 failed = false;
420                 throwIsInvalid ();
421             }
422         } finally {
423             repository.endTrans (failed);
424         }
425     }
426
427     public void fireInterfacesChange (Identifier[] oldValue, Identifier[] newValue) {
428         // [PENDING] an interfaces change is always translated as SET operation
429
PropertyChangeEvent evt = identSupport.createChangeEvent(getElement(),
430                         oldValue, newValue);
431         
432         /*
433         System.out.println("## fireInterfacesChange ##");
434         System.out.print("old: ");
435         for (int x = 0; x < oldValue.length; x++) {
436             System.out.print(oldValue [x].getName () + " ");
437         }
438         System.out.println("");
439         System.out.print("new: ");
440         for (int x = 0; x < newValue.length; x++) {
441             System.out.print(newValue [x].getName () + " ");
442         }
443         System.out.println("");
444          */

445         
446         if (evt == null)
447             return;
448         fireOwnPropertyChange(evt);
449         
450         ClassElement old = (ClassElement) cloneSelf ();
451         try {
452             old.setInterfaces (oldValue);
453         } catch (SourceException e) {
454             e.printStackTrace ();
455         }
456         notifyConnectionChange (old);
457     }
458     
459     public void setModifiers(int mod) throws SourceException {
460         checkWritable(false);
461         checkDocument();
462         super.setModifiers ((mod & ~Modifier.INTERFACE) | (getModifiers () & Modifier.INTERFACE));
463     }
464     
465     /**
466      * Converts a class into an interface or vice-versa.
467      * @param classFlag true, if the element should turn itself into a class def,
468      * false if it should become an interface.
469      */

470     public void setClassOrInterface(boolean classFlag) throws SourceException {
471         checkWritable(false);
472         checkDocument();
473         boolean failed = true;
474         repository.beginTrans (true);
475         try {
476             if (javaElement.isValid()) {
477                 PropertyChangeEvent evt;
478                 setClassPath();
479                 if (isClassOrInterface () == classFlag) {
480                     failed = false;
481                     return;
482                 }
483
484                 evt = new PropertyChangeEvent(getElement(), PROP_CLASS_OR_INTERFACE,
485                     classFlag ? Boolean.FALSE : Boolean.TRUE,
486                     classFlag ? Boolean.TRUE : Boolean.FALSE);
487
488                 // TODO: constraint the class -> interface change so that methods cannot
489
// contain bodies.
490
checkVetoablePropertyChange(evt);
491                 // perform the change in the source.
492

493                 ((JavaClass) javaElement).setInterface (!classFlag);
494                 failed = false;
495             } else {
496                 failed = false;
497                 throwIsInvalid ();
498             }
499         } finally {
500             repository.endTrans (failed);
501         }
502     }
503
504     public void fireModifiersChange (Integer JavaDoc oldValue, Integer JavaDoc newValue) {
505         int oldInt = oldValue.intValue ();
506         int newInt = newValue.intValue ();
507         boolean oldIsClass = (oldInt & Modifier.INTERFACE) == 0;
508         boolean newIsClass = (newInt & Modifier.INTERFACE) == 0;
509         if (oldIsClass != newIsClass) {
510             fireIsClassChange (oldIsClass, newIsClass);
511         }
512         
513         oldInt = oldInt & ~Modifier.INTERFACE;
514         newInt = newInt & ~Modifier.INTERFACE;
515         if (oldInt == newInt)
516             return;
517         
518         PropertyChangeEvent evt = new PropertyChangeEvent(
519             getElement(),
520             PROP_MODIFIERS,
521             new Integer JavaDoc (oldInt),
522             new Integer JavaDoc (newInt)
523         );
524         fireOwnPropertyChange(evt);
525         
526         MemberElement old = (MemberElement) cloneSelf ();
527         try {
528             old.setModifiers (oldInt);
529         } catch (SourceException e) {
530             e.printStackTrace ();
531         }
532         notifyConnectionChange (old);
533     }
534     
535     public void fireIsClassChange (boolean oldValue, boolean newValue) {
536         PropertyChangeEvent evt = new PropertyChangeEvent(
537             getElement(),
538             PROP_CLASS_OR_INTERFACE,
539             oldValue ? Boolean.TRUE : Boolean.FALSE,
540             newValue ? Boolean.TRUE : Boolean.FALSE
541         );
542         fireOwnPropertyChange(evt);
543         
544         ClassElement old = (ClassElement) cloneSelf ();
545         try {
546             old.setClassOrInterface (oldValue);
547         } catch (SourceException e) {
548             e.printStackTrace ();
549         }
550         notifyConnectionChange (old);
551     }
552         
553     // Member management methods
554
// - will delegate to collection helpers.
555
///////////////////////////////////////////////////////////////////////////////////
556
public FieldElement[] getFields() {
557         return (FieldElement[]) fields.getFields().clone ();
558     }
559     
560     public FieldElement getField(Identifier name) {
561         return fields.getField (name);
562     }
563     
564     public void changeFields(FieldElement[] flds, int operation) throws SourceException {
565         checkWritable(false);
566         checkDocument();
567         fields.changeMembers(flds, operation);
568     }
569     
570     public MethodElement[] getMethods() {
571         return (MethodElement[]) methods.getMethods().clone();
572     }
573     
574     public MethodElement getMethod(Identifier id, Type[] argtypes) {
575         return methods.getMethod (id, argtypes);
576     }
577     
578     public void changeMethods(MethodElement[] m, int operation) throws SourceException {
579         checkWritable(false);
580         checkDocument();
581         methods.changeMembers(m, operation);
582     }
583     
584     public ConstructorElement[] getConstructors() {
585         return (ConstructorElement[]) constructors.getConstructors ().clone ();
586     }
587     
588     public ConstructorElement getConstructor(Type[] argtypes) {
589         return constructors.getConstructor (argtypes);
590     }
591     
592     public void changeConstructors(ConstructorElement[] cons, int operation) throws SourceException {
593         checkWritable(false);
594         checkDocument();
595         constructors.changeMembers(cons, operation);
596     }
597     
598     public ClassElement[] getClasses() {
599         return (ClassElement[]) innerClasses.getClasses ().clone ();
600     }
601     
602     public ClassElement getClass(Identifier id) {
603         return innerClasses.getClass (id);
604     }
605     
606     public void changeClasses(ClassElement[] classes, int operation) throws SourceException {
607         checkWritable(false);
608         checkDocument();
609         innerClasses.changeMembers(classes, operation);
610     }
611     
612     public InitializerElement[] getInitializers() {
613         return (InitializerElement[]) initializers.getInitializers ().clone ();
614     }
615     
616     public void changeInitializers(InitializerElement[] el, int operation) throws SourceException {
617         checkWritable(false);
618         checkDocument();
619         initializers.changeMembers(el, operation);
620     }
621     
622     // Local element management
623
///////////////////////////////////////////////////////////////////////////////////
624

625     /**
626      * Local classes of a class are its inner classes.
627      */

628     public ClassElement[] getLocalClasses() {
629         return getClasses();
630     }
631     
632     // Utility methods
633
///////////////////////////////////////////////////////////////////////////////////
634

635     protected void checkWritable(boolean unsafeOp) throws SourceException {
636         SourceException e = null;
637         if (javaElement instanceof JavaEnum) {
638             e = new SourceException.IO("Enumeration cannot be modified: " + getName().getFullName()); // NOI18N
639
} else if (javaElement instanceof AnnotationType) {
640             e = new SourceException.IO("Annotation type cannot be modified: " + getName().getFullName()); // NOI18N
641
}
642         if (e != null) {
643             if (JDK15_CHECKS_DISABLED) {
644                 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
645             } else {
646                 throw e;
647             }
648         } else {
649             super.checkWritable(unsafeOp);
650         }
651     }
652     
653     /** Return the implementation for the SourceElement - directly, since all classes
654      * have a link to the source.
655      */

656     protected final SourceElementImpl findSourceImpl() {
657         return this.sourceImpl;
658     }
659     
660     protected SourceElementImpl findSource() {
661         if (sourceImpl != null)
662             return sourceImpl;
663         else {
664             ClassElementImpl declClass = getDeclaringImpl();
665             if (declClass != null)
666                 return declClass.findSource();
667         }
668         return null;
669     }
670     
671     public void updateMembers(String JavaDoc propName, Element[] els, int[] indices, int[] optMap) {
672         if (propName == ElementProperties.PROP_INITIALIZERS) {
673             // initializers.updateMembers(els, indices, optMap);
674
} else if (propName == ElementProperties.PROP_FIELDS) {
675             // fields.updateMembers(els, indices, optMap);
676
} else if (propName == ElementProperties.PROP_CONSTRUCTORS) {
677             // constructors.updateMembers(els, indices, optMap);
678
} else if (propName == ElementProperties.PROP_METHODS) {
679             // methods.updateMembers(els, indices, optMap);
680
} else if (propName == ElementProperties.PROP_CLASSES) {
681             // innerClasses.updateMembers(els, indices, optMap);
682
}
683     }
684     
685     public void updateMemberOrder(Element[] ordered) {
686         // members.updateOrder(ordered);
687
}
688             
689     protected final void createAfter(Binding.Container cb, Binding refBinding) throws SourceException {
690         /*
691         Element[] els = members.getElements();
692         ElementImpl impl;
693         Binding ref = null;
694         
695         for (int i = 0; i < els.length; i++) {
696             impl = members.getElementImpl(els[i]);
697             // impl.createAfter(getClassBinding(), ref);
698             ref = impl.getBinding();
699         }
700          */

701     }
702     
703     // Serialization support
704
///////////////////////////////////////////////////////////////////////////////////
705
public Object JavaDoc readResolve() {
706         return null;
707     }
708     
709     // Support classes
710
///////////////////////////////////////////////////////////////////////////////////
711
private static final class InterfaceSupport extends IdentifierArrayProperty {
712         InterfaceSupport() {
713             super(PROP_INTERFACES);
714         }
715         
716         public Object JavaDoc[] getValue(ElementImpl bean) {
717             return ((ClassElementImpl)bean).getInterfaces ();
718         }
719         
720         public PropertyChangeEvent add(ClassElementImpl beanImpl, Identifier[] adding)
721             throws SourceException {
722             Identifier[] cur = (Identifier[])getValue(beanImpl);
723             Collection remains = null;
724             
725             for (int i = 0; i < adding.length; i++) {
726                 for (int j = 0; j < cur.length; j++) {
727                     if (adding[i].getSourceName().equals(cur[j].getSourceName())) {
728                         if (remains == null)
729                             remains = new ArrayList(adding.length - 1);
730                         for (int k = 0; k < i; k++) {
731                             remains.add(adding[k]);
732                         }
733                         break;
734                     }
735                 }
736             }
737             if (remains == null) {
738                 return super.add(beanImpl, adding);
739             } else {
740                 // PENDING: throw an exception under different mode ??
741
return super.add(beanImpl, remains.toArray(new Identifier[remains.size()]));
742             }
743         }
744         
745         public boolean compareValues(Object JavaDoc o1, Object JavaDoc o2) {
746             return compareSourceIdentifiers((Identifier)o1, (Identifier)o2);
747         }
748     }
749     
750     public String JavaDoc toString() {
751         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
752         
753         sb.append("ClassElement["); // NOI18N
754
sb.append(getName().getFullName());
755         sb.append("/"); // NOI18N
756
sb.append(getName().getSourceName());
757         sb.append("]"); // NOI18N
758
return sb.toString();
759     }
760     
761     /**
762      * This implementation only clones the class element itself, not its subitems.
763      */

764     protected Element cloneSelf() {
765         ClassElement clone = new ClassElement();
766         try {
767             clone.setClassOrInterface(isClassOrInterface());
768             clone.setName(getName());
769             clone.setSuperclass(getSuperclass());
770             clone.setInterfaces(getInterfaces());
771             clone.setModifiers(getModifiers());
772         } catch (SourceException ex) {
773         }
774         return clone;
775     }
776     
777     /**
778      * Called by outer classes during their rename operation. The inner classes
779      * should fire Property Change on their name property, but without Vetoable change.
780      * And, of course, change their names.
781      */

782     protected void updateName(String JavaDoc outerPrefix) throws SourceException {
783         Identifier curName = getName();
784         if (curName.getQualifier().equals(outerPrefix))
785             return;
786         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
787         if (outerPrefix != null && !"".equals(outerPrefix)) {
788             sb.append(outerPrefix);
789             sb.append('.');
790         }
791         String JavaDoc simpleName = curName.getName();
792         sb.append(simpleName);
793         String JavaDoc fullName = sb.toString();
794         Identifier newName = Identifier.create(fullName, simpleName);
795         setName(newName);
796         updateInnerClasses(fullName);
797     }
798     
799     private void updateInnerClasses(String JavaDoc fullName) throws SourceException {
800         ClassElement[] cls = getClasses();
801         for (int i = 0; i < cls.length; i++) {
802             ClassElementImpl impl = (ClassElementImpl)cls[i].getCookie(ClassElementImpl.class);
803             impl.updateName(fullName);
804         }
805     }
806     
807     protected Element getParent() {
808         Element p = super.getParent();
809         if (p == null)
810             return ((ClassElement)getElement()).getSource();
811         else
812             return p;
813     }
814     
815     protected Identifier createLocalIdentifier(Identifier id, int status) {
816         return identSupp.create(id, status);
817     }
818     
819     protected boolean checkIdentifierContext(Identifier id) {
820         return identSupp.checkContext(id);
821     }
822     
823     protected void checkRemove() throws SourceException {
824         super.checkRemove();
825     }
826     
827     protected void notifyRemove() {
828         super.notifyRemove();
829     }
830     
831     protected void notifyCreate() {
832         /*
833         Element[] allElems = members.getElements();
834         for (int i = 0; i < allElems.length; i++) {
835             ElementImpl impl = members.getElementImpl(allElems[i]);
836             impl.notifyCreate();
837         }
838         super.notifyCreate();
839         members.sanityCheck();
840         if (innerClasses != null)
841             innerClasses.sanityCheck();
842         if (fields != null)
843             fields.sanityCheck();
844         if (methods != null)
845             methods.sanityCheck();
846         if (constructors != null)
847             constructors.sanityCheck();
848         if (initializers != null)
849             initializers.sanityCheck();
850          */

851     }
852     
853     protected boolean parentValid() {
854         return declaringClassImpl == null ?
855             sourceImpl.isValid() : declaringClassImpl.isValid();
856     }
857     
858     public Element[] getElements() {
859         repository.beginTrans (false);
860         try {
861             if (javaElement.isValid()) {
862                 setClassPath();
863                 Collection coll = ((JavaClass) javaElement).getFeatures();
864                 int size = coll.size ();
865                 Iterator iter = coll.iterator();
866                 ArrayList list = new ArrayList();
867
868                 while (iter.hasNext()) {
869                     Feature f = (Feature)iter.next();
870                     if (f instanceof Method) {
871                         list.add(methods.cachedElement(f));
872                     } else if (f instanceof Constructor) {
873                         list.add(constructors.cachedElement(f));
874                     } else if (f instanceof Field) {
875                         list.add(fields.cachedElement(f));
876                     } else if (f instanceof Initializer) {
877                         list.add(initializers.cachedElement(f));
878                     } else if (f instanceof JavaClass) {
879                         list.add(innerClasses.cachedElement(f));
880                     }
881                 }
882                 Element[] res = new Element[list.size()];
883                 list.toArray(res);
884                 return res;
885             } else {
886                 return new Element [0];
887             }
888         } finally {
889             repository.endTrans (false);
890         }
891     }
892     
893     // ..........................................................................
894

895     static class ClassListener extends MemberElementImpl.MemberElementListener implements MDRPreChangeListener {
896         
897         private static final Identifier[] NO_INTERFACES = new Identifier[0];
898         private InterfacesListener interfaces = new InterfacesListener (this);
899         private Identifier superClass;
900         private Map eventsMap = new HashMap();
901         
902         ClassListener (ClassElementImpl impl) {
903             super (impl);
904         }
905                 
906         public void connect () {
907             if (REGISTER_LISTENER) {
908                 super.connect ();
909                 impl = (ElementImpl) ref.get();
910                 if (impl != null) {
911                     interfaces.initElements ();
912                     
913                     JavaClass superCls = ((ClassDefinition) javaElement).getSuperClass();
914                     if (superCls != null) {
915                         superClass = Identifier.create(superCls.getName());
916                     } else {
917                         superClass = null;
918                     }
919                 }
920                 impl = null;
921             }
922         }
923
924         public void remove () {
925             super.remove ();
926             interfaces.removeAll ();
927         }
928
929         public void doChange(MDRChangeEvent event) {
930             super.doChange (event);
931             if (source instanceof Extends) {
932                 AssociationEvent assocEvent = (AssociationEvent) event;
933                 if ("subClasses".equals(assocEvent.getEndName())) { // NOI18N
934
EventInfo info = (EventInfo) eventsMap.get(event);
935                     Identifier oldSuperClass = superClass;
936                     superClass = info.newName != null ? Identifier.create(info.newName) : null;
937                     ((ClassElementImpl) impl).fireSuperclassChange(oldSuperClass, superClass);
938                 }
939                 /*
940                 System.out.println("end name: " + assocEvent.getEndName());
941                 System.out.println("fixed: " + assocEvent.getFixedElement());
942                 System.out.println("new: " + assocEvent.getNewElement());
943                  */

944             }
945         }
946                 
947         public void changeCancelled(MDRChangeEvent e) {
948             eventsMap.remove(e);
949         }
950         
951         public void plannedChange(MDRChangeEvent event) {
952             RefBaseObject source = (RefBaseObject) event.getSource ();
953             if (source instanceof Extends) {
954                 AssociationEvent assocEvent = (AssociationEvent) event;
955                 if ("subClasses".equals(assocEvent.getEndName())) { // NOI18N
956
JavaClass jc = (JavaClass) assocEvent.getNewElement();
957                     EventInfo info = new EventInfo();
958                     info.newName = jc != null ? jc.getName() : null;
959                     eventsMap.put(event, info);
960                 }
961             }
962         }
963         
964         class EventInfo {
965             String JavaDoc newName;
966         }
967         
968     } // ClassListener ..........................................................
969

970     static class InterfacesListener extends CallableImpl.ExceptionsListener {
971
972         InterfacesListener(ElementImpl.ElementListener parentListener) {
973             super(parentListener);
974         }
975
976         public List getElements() {
977             return ((JavaClass) javaElement).getInterfaces();
978         }
979         
980         public String JavaDoc getEndName() {
981             return "interfaces"; // NOI18N
982
}
983         
984         public void fireChange (ElementImpl impl, ArrayList oldValues, ArrayList newValues) {
985             Identifier [] oldPars = (Identifier []) oldValues.toArray (ClassListener.NO_INTERFACES);
986             Identifier [] newPars = (Identifier []) newValues.toArray (ClassListener.NO_INTERFACES);
987             ((ClassElementImpl) impl).fireInterfacesChange (oldPars, newPars);
988         }
989
990     } // InterfacesListener .....................................................
991

992 }
993
Popular Tags