KickJava   Java API By Example, From Geeks To Geeks.

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


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.util.*;
22 import javax.jmi.reflect.InvalidObjectException;
23 import javax.jmi.reflect.RefClass;
24 import javax.jmi.reflect.RefFeatured;
25 import javax.jmi.reflect.RefObject;
26 import org.netbeans.api.mdr.events.AttributeEvent;
27 import org.netbeans.jmi.javamodel.*;
28 import org.netbeans.lib.java.parser.ASTree;
29 import org.netbeans.lib.java.parser.ParserTokens;
30 import org.netbeans.lib.java.parser.Token;
31 import org.netbeans.mdr.handlers.AttrCollWrapper;
32 import org.netbeans.mdr.handlers.AttrListWrapper;
33 import org.netbeans.mdr.handlers.BaseObjectHandler;
34 import org.netbeans.mdr.persistence.StorageException;
35 import org.netbeans.mdr.storagemodel.StorableFeatured;
36 import org.netbeans.mdr.storagemodel.StorableObject;
37 import org.netbeans.modules.javacore.ClassIndex;
38 import org.netbeans.modules.javacore.ExclusiveMutex;
39 import org.netbeans.modules.javacore.JMManager;
40
41 import org.netbeans.modules.javacore.parser.*;
42 import org.openide.ErrorManager;
43 import org.openide.util.Utilities;
44
45 /**
46  * Superclass for the partialy persistent elements.
47  *
48  * @author Martin Matula
49  * @author Pavel Flaska
50  */

51 public abstract class SemiPersistentElement extends MetadataElement {
52     private int modCount = 0;
53     private boolean recentlyPersisted = false;
54     private ElementInfo info;
55     RefFeatured parent; // used for hard-referencing parent
56

57     /** Creates a new instance of SemiPersistentElement */
58     public SemiPersistentElement(StorableObject o) {
59         super(o);
60     }
61     
62     public boolean hasComposite() {
63         return ((StorableObject) _getDelegate()).getImmediateCompositeId() != null;
64     }
65     
66     public boolean isValid() {
67         if (super.isValid() && !isSafeTrans()) {
68             try {
69                 if (this instanceof ResourceImpl) {
70                     this.refImmediatePackage();
71                 } else {
72                     ResourceImpl rsc = (ResourceImpl) getResource();
73                     if (rsc != null) {
74                         rsc.checkUpToDate(false, false, false);
75                     }
76                 }
77             } catch (javax.jmi.reflect.InvalidObjectException e) {
78                 return false;
79             }
80         }
81         return super.isValid();
82     }
83
84     protected final void fireAttrChange(String JavaDoc attrName, Object JavaDoc oldValue, Object JavaDoc newValue) {
85         fireAttrChange(attrName, oldValue, newValue, AttributeEvent.POSITION_NONE);
86     }
87     
88     protected final void fireAttrChange(String JavaDoc attrName, Object JavaDoc oldValue, Object JavaDoc newValue, int position) {
89         if (_getMdrStorage().eventsEnabled()) {
90             AttributeEvent event = new AttributeEvent(
91                 this,
92                 AttributeEvent.EVENT_ATTRIBUTE_SET,
93                 attrName,
94                 oldValue,
95                 newValue,
96                 position
97             );
98             _getMdrStorage().getEventNotifier().INSTANCE.firePlannedChange(this, event);
99         }
100     }
101     
102     /** Should be called by a class proxy whenever a new metadata object is created via
103      * standard API (it has no ASTInfo so a default ASTInfo is set into it)
104      */

105     protected final void setNew() {
106         setChanged();
107         if (this.info != null) {
108             for (Iterator it = getInitedChildren().iterator(); it.hasNext();) {
109                 ((MetadataElement) it.next()).setNew();
110             }
111         }
112         this.info = getDefaultInfo();
113         setPersisted(true);
114         childrenInited = true;
115         // [TODO] uncomment this
116
// ((ExclusiveMutex) _getMdrStorage().getRepositoryMutex()).addNew(this);
117
}
118
119     public void setPersisted(boolean persisted) {
120     }
121
122     protected final boolean isNew() {
123         return this.info == getDefaultInfo();
124     }
125     
126     protected final boolean infoIdenticalTo(ElementInfo info) {
127         return this.info == info;
128     }
129
130     /** This method is called from parent to set ASTInfo of this element. It can be called
131      * basically in two cases:
132      * <ul>
133      * <li>object was not initialized - it needs AST info to be able to read value of some of its attributes
134      * <li>object was changed externally (in editor) - it gets an updated AST and needs to fire
135      * match it with the original AST and fire appropriate change events
136      * </ul>
137      * This method should not be called for new objects. setNew should be called instead.
138      */

139     public final void setElementInfo(ElementInfo info) {
140         if (infoIdenticalTo(info)) return;
141         boolean changes = disableChanges;
142         disableChanges = true;
143         try {
144             if (isInitialized()) {
145                 // whole ASTInfo should be matched
146
matchElementInfo(info);
147             }
148             this.info = info;
149             hardRefParent(true);
150             // go down via containment hierarchy and force ASTInfo renewal
151
if (childrenInited) {
152                 initChildren();
153             }
154         } finally {
155             disableChanges = changes;
156         }
157         resetChange();
158     }
159
160     protected void hardRefParent(boolean enabled) {
161         parent = enabled ? refImmediateComposite() : null;
162     }
163
164     protected void parentChanged() {
165         parent = refImmediateComposite();
166         if (parent == null || ((BaseObjectHandler) parent)._getDelegate() instanceof DeferredObject) {
167             if (!(_getDelegate() instanceof DeferredObject)) mutate(true); // make object transient
168
parent = null;
169         } else {
170             if (_getDelegate() instanceof DeferredObject) mutate(false); // make object persistent
171
}
172     }
173
174     protected void mutate(boolean makeTransient) {
175         StorableObject newDelegate;
176         StorableObject oldDelegate = (StorableObject) _getDelegate();
177         try {
178             if (makeTransient) {
179                 newDelegate = new DeferredObject(oldDelegate);
180             } else {
181                 newDelegate = new StorableObject(oldDelegate);
182             }
183             _setDelegate(newDelegate);
184             oldDelegate.clearComposite();
185             oldDelegate.deleteInstance();
186         } catch (StorageException e) {
187             throw (RuntimeException JavaDoc) ErrorManager.getDefault().annotate(new RuntimeException JavaDoc(), e);
188         }
189     }
190
191     public final ElementInfo getElementInfo() {
192         initCheck();
193         if (info == null && (_getDelegate() instanceof StorableObject)) {
194             String JavaDoc name;
195             if (this instanceof JavaClass) {
196                 name = getName();
197             } else {
198                 name = "<unknown>"; // NOI18N
199
}
200             JMManager.getLog().notify(ErrorManager.INFORMATIONAL, new Exception JavaDoc("***** Info is null for element: " + getName() + " (instanceof: " + getClass().getName() + " MOFID: " + refMofId() + ")")); // NOI18N
201
if (this instanceof ResourceImpl) {
202                 JMManager.getLog().log(ErrorManager.WARNING, "isChanged: " + isChanged() + ", alreadyChecking: " + ((ResourceImpl) this).alreadyChecking);
203                 JMManager.getLog().log(ErrorManager.WARNING, "isValid: " + isValid());
204                 RuntimeException JavaDoc e = ((ResourceImpl) this).alreadyCheckingStackTrace;
205                 if (e != null) {
206                     JMManager.getLog().log(ErrorManager.WARNING, "alreadyChecking stacktrace:");
207                     JMManager.getLog().notify(ErrorManager.INFORMATIONAL, e);
208                     throw new IllegalStateException JavaDoc("Recursive call to getElementInfo()");
209                 }
210                 setNew();
211             } else if (this instanceof JavaClass) {
212                 JavaClass replacement = null;
213                 SemiPersistentElement composite = (SemiPersistentElement) refImmediateComposite();
214                 if (composite == null) {
215                     JMManager.getLog().log(ErrorManager.WARNING, " composite is null - need to find the class with the same name in index...");
216                     JMManager.getLog().log(ErrorManager.WARNING, " classindex classes for the same FQN in this extent:");
217                     for (Iterator it = ClassIndex.getIndex((JavaModelPackage) refImmediatePackage()).getClassesByFqn(getName()).iterator(); it.hasNext();) {
218                         JavaClass feat = (JavaClass) it.next();
219                         if (!feat.isValid()) {
220                             continue;
221                         }
222                         JMManager.getLog().log(ErrorManager.WARNING, " " + feat.getName() + " (instanceof: " + feat.getClass().getName() + " MOFID: " + feat.refMofId() + ")" + (refMofId().equals(feat.refMofId()) && feat != this ? " !! same MOFID as me, but different object" : "") + (feat.refImmediateComposite() == null ? " !! composite is null" : ""));
223                         if (!equals(feat)) {
224                             replacement = feat;
225                         }
226                     }
227                 } else {
228                     JMManager.getLog().log(ErrorManager.WARNING, " composite contains the following features: ");
229                     List features;
230                     if (composite instanceof JavaClass) {
231                         features = ((JavaClass) composite).getFeatures();
232                     } else {
233                         features = ((Resource) composite).getClassifiers();
234                     }
235                     for (Iterator it = features.iterator(); it.hasNext();) {
236                         Feature feat = (Feature) it.next();
237                         JMManager.getLog().log(ErrorManager.WARNING, " " + feat.getName() + " (instanceof: " + feat.getClass().getName() + " MOFID: " + feat.refMofId() + ")" + (refMofId().equals(feat.refMofId()) && feat != this ? " !! same MOFID as me, but different object" : ""));
238                         if ((feat instanceof JavaClass) && Utilities.compareObjects(feat.getName(), getName())) {
239                             replacement = (JavaClass) feat;
240                         }
241                     }
242                 }
243                 if (replacement == null) {
244                     JMManager.getLog().log(ErrorManager.WARNING, "No suitable replacement found in index - we need to create a fake info for class.");
245                     setNew();
246                 } else {
247                     JMManager.getLog().log(ErrorManager.WARNING, "Acquired info from a replacement class: " + replacement.refMofId());
248                     this.info = ((SemiPersistentElement) replacement).info;
249                 }
250             } else {
251                 setNew();
252             }
253             JMManager.getTransactionMutex().invalidateAtCommit(this);
254         }
255         return info;
256     }
257
258     public final boolean isInitialized() {
259         return info != null;
260     }
261
262     protected void uninitialize() {
263         info = null;
264         hardRefParent(false);
265     }
266     
267     protected void checkUpToDate() {
268         if (checkAndUpdateModCount() && !(isSafeTrans() && isPersisted())) {
269             if (this instanceof ResourceImpl) {
270                 ((ResourceImpl) this).checkUpToDate(true, false, true);
271             } else {
272                 Object JavaDoc parent = refImmediateComposite();
273                 if (parent instanceof SemiPersistentElement) {
274                     ((SemiPersistentElement) parent).checkUpToDate();
275                     if (super.isValid() && !isPersisted()) {
276                         initCheck();
277                     }
278                 }
279             }
280         }
281     }
282     
283     protected void persist() {
284         if (!recentlyPersisted) {
285             recentlyPersisted = true;
286             Object JavaDoc parent = refImmediateComposite();
287             if (parent instanceof SemiPersistentElement) {
288                 if (!((SemiPersistentElement) parent).recentlyPersisted) {
289                     ((ExclusiveMutex) _getMdrStorage().getRepositoryMutex()).registerPersisted(this);
290                 }
291             }
292         }
293     }
294     
295     public void clearPersist(boolean fail) {
296         if (fail) {
297             boolean persisted;
298             try {
299                 persisted = isPersisted();
300             } catch (InvalidObjectException e) {
301                 // object is not valid anymore -> return
302
// [TODO] once isValid supports rollback, this should be changed
303
// to simply check isValid
304
return;
305             }
306             modCount = 0;
307             if (!persisted) {
308                 if (info == null) {
309                     recentlyPersisted = false;
310                 } else {
311                     updatePersistent(info);
312                 }
313             }
314         } else {
315             recentlyPersisted = false;
316         }
317     }
318     
319     /** Returns true if the modCount is different */
320     public boolean checkModCount() {
321         return this.modCount != JMManager.getTransactionMutex().getModCount();
322     }
323     
324     /** Updates modCount for this object and returns true if the modCount was different. */
325     public boolean checkAndUpdateModCount() {
326         int modCount = JMManager.getTransactionMutex().getModCount();
327         boolean result = modCount != this.modCount;
328         this.modCount = modCount;
329         return result;
330     }
331     
332     protected final boolean isSafeTrans() {
333         return JMManager.getTransactionMutex().isSafeTrans();
334     }
335     
336     public boolean isPersisted() {
337         return false;
338     }
339
340     /**
341      * Find referenced resources of this element
342      */

343     Resource[] findReferencedResources() {
344         return new Resource[] {getResource()};
345     }
346     
347     public Collection getReferences() {
348         if (this instanceof NamedElement) {
349             Resource[] res = findReferencedResources();
350             UsageFinder finder = new UsageFinder((NamedElement) this);
351             return finder.getUsers(res);
352         } else {
353             return Collections.EMPTY_LIST;
354         }
355     }
356
357     /** Should be overriden by elements that have persistent attributes.
358      * They should implement this method to compare values in newly passed AST info with
359      * values of the persistent attributes and if the values do not match, they should be
360      * updated and proper events should be fired.
361      */

362     protected void matchPersistent(ElementInfo info) {
363         modCount = JMManager.getTransactionMutex().getModCount();
364         matchName(info);
365     }
366     
367     public final void updatePersistent(ElementInfo info) {
368         boolean changes = disableChanges;
369         disableChanges = true;
370         try {
371             matchPersistent(info);
372         } finally {
373             disableChanges = changes;
374         }
375     }
376     
377     protected void matchName(ElementInfo info) {
378         if ((this instanceof NamedElement) && !Utilities.compareObjects(info.name, this.getName())) {
379             setName(info.name);
380         }
381     }
382
383     protected abstract ElementInfo getDefaultInfo();
384
385     /** The method has to make sure that the AST infos of children are also updated.
386      */

387     protected void matchElementInfo(ElementInfo newInfo) {
388         if (info.infoType!=newInfo.infoType) {
389             if ((!(info instanceof ClassInfo) || !(newInfo instanceof ClassInfo)) &&
390                     !(info instanceof AnnotationValueInfo && newInfo instanceof AnnotationValueInfo))
391                 throw new IllegalArgumentException JavaDoc("Illegal element type "+info.infoType+"!="+newInfo.infoType); // NOI18N
392
}
393     }
394
395     public void setName(String JavaDoc name) {
396         objectChanged(CHANGED_NAME);
397         super_setName(name);
398     }
399
400     protected abstract void super_setName(String JavaDoc name);
401     public abstract String JavaDoc getName();
402
403     protected static String JavaDoc getInnerIndentation(int level) {
404         StringBuffer JavaDoc indentation = new StringBuffer JavaDoc();
405         for (int i = 0; i < level; i++) {
406             indentation.append(INDENTATION);
407         }
408         return indentation.toString();
409     }
410
411     /**
412      * Return indentation of the element. If the element is new, it asks
413      * for parent's indentation and appends its own.
414      *
415      * @return indentation
416      */

417     protected String JavaDoc getIndentation() {
418         super.getIndentation();
419         if (isNew()) {
420             // For the new element it asks parent (immediateComposite)
421
// for its indentation and appends its own indentation.
422
return ((MetadataElement) refImmediateComposite()).getIndentation().concat(INDENTATION);
423         }
424         else {
425             // For the existing element, it tries to analyze element to
426
// get the indentation. It asks parent for its indentation,
427
// takes its paddings. In the paddings, it looks for the nearest
428
// end-line char to the first token. Difference between end-line
429
// character and first char of the first token is parent's
430
// indentation.
431
Token firstToken = getParser().getToken(getASTree().getFirstToken());
432             Token[] pad = firstToken.getPadding();
433             Token endLine = null;
434             for (int i = pad.length-1; i >= 0; i--) {
435                 if (pad[i].getType() == ParserTokens.EOL) {
436                     endLine = pad[i];
437                     break;
438                 }
439             }
440             if (endLine != null) {
441                 String JavaDoc src = getParser().getSourceText();
442                 return src.substring(endLine.getEndOffset(), firstToken.getStartOffset());
443             }
444             else {
445                 // What to do when there is no endline character
446
// before the first token? -- We will indent it as a new element.
447
// This branch of code is running e.g. when field group is
448
// splitted by changing of its javadoc. (Use e.g. Autocomment
449
// tool and comment one of the field in field group)
450
return ((MetadataElement) refImmediateComposite()).getIndentation().concat(INDENTATION);
451             }
452
453         }
454     }
455
456     /**
457      * Returns indentation of the body of element
458      *
459      * @return indentation of the body of element
460      */

461     protected String JavaDoc getBodyIndentation() {
462         return getIndentation().concat(INDENTATION);
463     }
464
465     private void deleteCollection(Collection col) {
466         for (Iterator it = col.iterator(); it.hasNext();) {
467             RefObject obj = (RefObject) it.next();
468             boolean del = (obj.refImmediateComposite() == this);
469             it.remove();
470             // if the object was contained by this before its removal
471
// from the collection and after the removal its container is null,
472
// it means that it was removed from the composite collection
473
// i.e. the object needs to be deleted
474
if (del && obj.refImmediateComposite() == null) {
475                 obj.refDelete();
476             }
477         }
478     }
479
480     private void deleteCollection(List mdrList,RefObject[] mdrObjects, List indexes) {
481         Iterator it=indexes.iterator();
482
483         while(it.hasNext()) {
484             int index=((Integer JavaDoc)it.next()).intValue();
485             RefObject obj=mdrObjects[index];
486
487             if (mdrList instanceof LightAttrList || mdrList instanceof SemiPersistentAttrList
488                     || mdrList instanceof DeferredAttrList || mdrList instanceof AttrCollWrapper) {
489                 obj.refDelete();
490             } else {
491                 boolean del = (obj.refImmediateComposite() == this);
492                 mdrList.remove(obj);
493                 // if the object was contained by this before its removal
494
// from the collection and after the removal its container is null,
495
// it means that it was removed from the composite collection
496
// i.e. the object needs to be deleted
497
if (del && obj.refImmediateComposite() == null) {
498                     obj.refDelete();
499                 }
500             }
501         }
502     }
503     
504     public void processMembers(List mdrList,Object JavaDoc[] astMembers) {
505         RefObject[] mdrMembers;
506         ArrayMapper mapper;
507         int[] map;
508         int i;
509
510         if (astMembers==null || astMembers.length==0) {
511             deleteCollection(mdrList);
512             return;
513         }
514         if (mdrList.isEmpty()) {
515             for (i=0;i<astMembers.length;i++) {
516                 mdrList.add(createAnyElement(astMembers[i]));
517             }
518             return;
519         }
520         mdrMembers=(RefObject[])mdrList.toArray(new RefObject[0]);
521         mapper=new ArrayMapper(mdrMembers, astMembers);
522         map=mapper.getMap();
523         if (!mapper.isIdentical()) {
524             deleteCollection(mdrList,mdrMembers,mapper.getDeletedIndexes());
525             if (mapper.hasPermutation()) {
526                 mdrList.clear();
527                 for (i=0;i<astMembers.length;i++) {
528                     Object JavaDoc member=astMembers[i];
529                     int oldIndex=map[i];
530                     RefObject newObj;
531
532                     if (oldIndex!=-1) { // update
533
newObj=mdrMembers[oldIndex];
534                         if (newObj instanceof SemiPersistentElement) {
535                             ((SemiPersistentElement)newObj).matchMember(member);
536                         }
537                     } else { // new object
538
newObj=createAnyElement(member);
539                     }
540                     mdrList.add(newObj);
541                 }
542                 return;
543             }
544         }
545         for (i=0;i<astMembers.length;i++) {
546             Object JavaDoc astMember=astMembers[i];
547             int oldIndex=map[i];
548
549             if (oldIndex==-1) {
550                 RefObject newObj=createAnyElement(astMember);
551
552                 mdrList.add(i,newObj);
553             } else if (mdrMembers[oldIndex] instanceof SemiPersistentElement) {
554                 ((SemiPersistentElement)mdrMembers[oldIndex]).matchMember(astMember);
555             }
556         }
557         return;
558     }
559
560     public void fixMembers(List mdrList, ElementInfo[] infos) {
561         JMManager.getLog().notify(ErrorManager.INFORMATIONAL, new RuntimeException JavaDoc("Inconsistent storage. (mdrList.size == " + mdrList.size() + ", infos.size == " + infos.length + ")")); // NOI18N
562
boolean changes = disableChanges;
563         disableChanges = true;
564         try {
565             ArrayList oldElements = new ArrayList();
566             for (Iterator it = mdrList.iterator(); it.hasNext();) {
567                 oldElements.add(it.next());
568                 it.remove();
569             }
570             for (int i = 0; i < infos.length; i++) {
571                 SemiPersistentElement element = findElement(oldElements, infos[i]);
572                 if (element == null) {
573                     element = createElement(infos[i]);
574                 } else {
575                     element.info = null; // to avoid matching
576
element.setElementInfo(infos[i]);
577                 }
578                 mdrList.add(element);
579             }
580             for (Iterator it = oldElements.iterator(); it.hasNext();) {
581                 SemiPersistentElement element = (SemiPersistentElement) it.next();
582                 element.refDelete();
583             }
584         } finally {
585             disableChanges = changes;
586         }
587     }
588     
589     private SemiPersistentElement findElement(List elements, ElementInfo info) {
590         JavaModelPackage extent = (JavaModelPackage) refImmediatePackage();
591         RefClass classFactory;
592         switch (info.infoType) {
593             case FieldInfo.FIELD_TYPE:
594                 classFactory = extent.getField();
595                 break;
596             case FieldGroupInfo.FIELDGROUP_TYPE:
597                 classFactory = extent.getFieldGroup();
598                 break;
599             case ClassInfo.INTERFACE_TYPE:
600             case ClassInfo.CLASS_TYPE:
601                 classFactory = extent.getJavaClass();
602                 break;
603             case ClassInfo.ANON_CLASS_TYPE:
604                 classFactory = extent.getClassDefinition();
605                 break;
606             case MethodInfo.METHOD_TYPE:
607                 classFactory = extent.getMethod();
608                 break;
609             case FeatureInfo.INSTANCE_INITIALIZER_TYPE:
610             case FeatureInfo.STATIC_INITIALIZER_TYPE:
611                 classFactory = extent.getInitializer();
612                 break;
613             case MethodInfo.CONSTRUCTOR_TYPE:
614                 classFactory = extent.getConstructor();
615                 break;
616             case ElementInfo.IMPORT_ON_DEMAND_TYPE:
617             case ElementInfo.SINGLE_IMPORT_TYPE:
618                 classFactory = extent.getImport();
619                 break;
620             case ParameterInfo.PARAMETER_TYPE:
621                 classFactory = extent.getParameter();
622                 break;
623             case TypeParamInfo.TYPEPARAM_TYPE:
624                 classFactory = extent.getTypeParameter();
625                 break;
626             case FeatureInfo.ENUM_CONSTANT_TYPE:
627                 classFactory = extent.getEnumConstant();
628                 break;
629             case EnumInfo.ENUM_TYPE:
630                 classFactory = extent.getJavaEnum();
631                 break;
632             case EnumInfo.ANNOTATIONTYPE_TYPE:
633                 classFactory = extent.getAnnotationType();
634                 break;
635             case AttributeInfo.ATTRIBUTE_TYPE:
636                 classFactory = extent.getAttribute();
637                 break;
638             case AnnotationInfo.ANNOTATION_TYPE:
639                 classFactory = extent.getAnnotation();
640                 break;
641             case AnnotationValueInfo.ANNOTATIONVALUE_ANNOTATION:
642             case AnnotationValueInfo.ANNOTATIONVALUE_ARRAY:
643             case AnnotationValueInfo.ANNOTATIONVALUE_STRING:
644                 classFactory = extent.getAttributeValue();
645                 break;
646             default:
647                 throw new IllegalArgumentException JavaDoc("Illegal type " + info.infoType); // NOI18N
648
}
649         
650         for (Iterator it = elements.iterator(); it.hasNext();) {
651             SemiPersistentElement element = (SemiPersistentElement) it.next();
652             if (element.refClass().equals(classFactory)) {
653                 it.remove();
654                 return element;
655             }
656         }
657         
658         return null;
659     }
660
661     private void matchMember(Object JavaDoc member) {
662         if (member instanceof ElementInfo) {
663             updatePersistent((ElementInfo) member);
664         }
665     }
666     
667     private RefObject createAnyElement(Object JavaDoc elem) {
668         if (elem instanceof TypeRef) {
669             return resolveType((TypeRef)elem);
670         }
671         return createElement((ElementInfo) elem, false);
672     }
673
674     Type resolveTypeString(String JavaDoc name) {
675         if (name.startsWith("<")) { // NOI18N
676
String JavaDoc typeParamName=name.substring(1);
677             SemiPersistentElement element=this;
678             do {
679                 if (element instanceof GenericElement) {
680                     GenericElement gel=(GenericElement)element;
681                     if (!(gel instanceof CallableFeatureImpl) || ((CallableFeatureImpl)gel).hasTypeParameters()) {
682                         Iterator typeParsIt=gel.getTypeParameters().iterator();
683
684                         while(typeParsIt.hasNext()) {
685                             TypeParameter typePar=(TypeParameter)typeParsIt.next();
686
687                             if (typePar.getName().equals(typeParamName))
688                                 return typePar;
689                         }
690                     }
691                 }
692                 element=(SemiPersistentElement)element.refImmediateComposite();
693             } while (!(element instanceof Resource));
694             // type parameter not found, create unresolved class
695
}
696         TypeClass typeClass = ((JavaModelPackage) refImmediatePackage()).getType();
697         return typeClass.resolve(name);
698     }
699         
700     public static TypeRef typeToTypeRef(Type type) {
701         if (type == null) return null;
702         
703         if (type instanceof TypeParameter) {
704             return new TypeParamRef(type.getName());
705         } else if (type instanceof ParameterizedType) {
706             ParameterizedTypeImpl paramType = (ParameterizedTypeImpl) type;
707             Type typePars[] = (Type[])paramType.getParameters().toArray(new Type[0]);
708             TypeRef args[] = new TypeRef[typePars.length];
709             int i = 0;
710             for (; i<typePars.length; i++) {
711                 args[i] = typeToTypeRef(typePars[i]);
712                 int status = paramType.getWildCardStatus(i);
713                 if (status != 0) {
714                     args[i] = new WildCardRef(status == 1, status == 3 ? null : args[i]);
715                 }
716             }
717             NameRef parentName=(NameRef) typeToTypeRef(paramType.getDeclaringClass());
718             JavaClass def=paramType.getDefinition();
719             String JavaDoc name;
720             
721             if (parentName==null)
722                 name=def.getName();
723             else
724                 name=def.getSimpleName();
725             return new NameRef(name, parentName, args);
726         } else if (type instanceof Array) {
727             int dimCount = 0;
728             Type currType = type;
729             while (currType instanceof Array) {
730                 dimCount++;
731                 currType = ((Array) currType).getType();
732             }
733             return new ArrayRef((PrimitiveTypeRef) typeToTypeRef(currType), dimCount);
734         } else if (type instanceof JavaClass) {
735             if (type instanceof JavaClassImpl && ((JavaClassImpl)type).isTransient()) // local class
736
return new LocalClassNameRef((JavaClass)type);
737             return new NameRef(type.getName());
738         } else if (type instanceof PrimitiveType) {
739             String JavaDoc kind = ((PrimitiveType) type).getKind().toString();
740             PrimitiveTypeRef result = PrimitiveTypeRef.forName(kind);
741             if (result != null) {
742                 return result;
743             }
744             throw new IllegalArgumentException JavaDoc("Unknown primitive type name: " + kind); // NOI18N
745
}
746         throw new IllegalArgumentException JavaDoc("Unable to convert to typeref: " + type.getClass().getName()); // NOI18N
747
}
748     
749     static List typeReferencesToTypeRef(List typeReferences) {
750         ArrayList result = new ArrayList(typeReferences.size());
751         for (Iterator it = typeReferences.iterator(); it.hasNext();) {
752             result.add(typeReferenceToTypeRef((Element) it.next(), 0));
753         }
754         return result;
755     }
756     
757     /** @param dimCount Number of dimensions to be added to the typeRef
758      * and make it an ArrayRef if necessary.
759      */

760     public static TypeRef typeReferenceToTypeRef(Element typeReference, int dimCount) {
761         if (typeReference == null) return null;
762         
763         int resultDimCount = dimCount;
764         TypeRef result;
765         if (typeReference instanceof ArrayReference) {
766             ArrayReference arrayReference = (ArrayReference) typeReference;
767             resultDimCount += arrayReference.getDimCount();
768             result = typeReferenceToTypeRef(arrayReference.getParent(), 0);
769         } else if (typeReference instanceof MultipartId) {
770             MultipartId mpi = (MultipartId) typeReference;
771             NamedElement ne = mpi.getElement();
772             if (ne instanceof PrimitiveType) {
773                 result = PrimitiveTypeRef.forName(ne.getName());
774             } else {
775                 TypeArgument typeArgs[] = (TypeArgument[])mpi.getTypeArguments().toArray(new TypeArgument[0]);
776                 TypeRef args[] = new TypeRef[typeArgs.length];
777                 int i = 0;
778                 for (; i<typeArgs.length; i++) {
779                     args[i] = typeReferenceToTypeRef(typeArgs[i], 0);
780                 }
781                 NameRef parent = (NameRef) typeReferenceToTypeRef(mpi.getParent(), 0);
782                 if (parent != null && parent.parent == null && parent.args.length == 0) {
783                     parent = null;
784                 }
785                 String JavaDoc name;
786                 if (parent != null) {
787                     name = ne.getName();
788                 } else {
789                     name = mpi.getName();
790                 }
791                 result = new NameRef(name, parent, args);
792             }
793         } else if (typeReference instanceof WildCard) {
794             WildCard wc = (WildCard) typeReference;
795             result = new WildCardRef(wc.isLower(), typeReferenceToTypeRef(wc.getBoundName(), 0));
796         } else {
797             throw new IllegalStateException JavaDoc();
798         }
799         if ((resultDimCount > 0) && (result instanceof PrimitiveTypeRef)) {
800             result = new ArrayRef((PrimitiveTypeRef) result, resultDimCount);
801         }
802         return result;
803     }
804     
805     /** @param dimCount Number of dimensions to be subtracted from the typeRef
806      * if it is an ArrayRef. It is a responsibility of the caller of this method
807      * to make sure that if dimCount > 0, typeRef is instance of ArrayRef and
808      * dimCount <= typeRef.dimCount.
809      */

810     public Element typeRefToTypeReference(TypeRef typeRef, int dimCount) {
811         return typeRefToTypeReference((JavaModelPackage) refImmediatePackage(), typeRef, dimCount);
812     }
813     
814     /** @param dimCount Number of dimensions to be subtracted from the typeRef
815      * if it is an ArrayRef. It is a responsibility of the caller of this method
816      * to make sure that if dimCount > 0, typeRef is instance of ArrayRef and
817      * dimCount <= typeRef.dimCount.
818      */

819     public static Element typeRefToTypeReference(JavaModelPackage extent, TypeRef typeRef, int dimCount) {
820         if (typeRef == null) return null;
821         
822         if (typeRef instanceof NameRef) {
823             NameRef nRef = (NameRef) typeRef;
824             ArrayList args = new ArrayList(nRef.args.length);
825             for (int i = 0; i < nRef.args.length; i++) {
826                 args.add(typeRefToTypeReference(extent, nRef.args[i], 0));
827             }
828             return extent.getMultipartId().createMultipartId(nRef.name, (MultipartId) typeRefToTypeReference(extent, nRef.parent, 0), args);
829         } else if (typeRef instanceof PrimitiveTypeRef) {
830             return extent.getMultipartId().createMultipartId(((PrimitiveTypeRef) typeRef).name, null, null);
831         } else if (typeRef instanceof WildCardRef) {
832             WildCardRef wcRef = (WildCardRef) typeRef;
833             return extent.getWildCard().createWildCard(wcRef.isLower, (MultipartId) typeRefToTypeReference(extent, wcRef.bound, 0));
834         } else if (typeRef instanceof ArrayRef) {
835             ArrayRef aRef = (ArrayRef) typeRef;
836             int resultDimCount = aRef.dimCount - dimCount;
837             if (resultDimCount > 0) {
838                 StringBuffer JavaDoc name = new StringBuffer JavaDoc(aRef.parent.name);
839                 for (int i = 0; i < resultDimCount; i++) {
840                     name.append("[]"); // NOI18N
841
}
842                 return extent.getArrayReference().createArrayReference(name.toString(), (MultipartId) typeRefToTypeReference(extent, aRef.parent, 0), resultDimCount);
843             } else {
844                 return typeRefToTypeReference(extent, aRef.parent, 0);
845             }
846         }
847         throw new IllegalStateException JavaDoc();
848     }
849
850     public final MDRParser getParser() {
851         ASTree tree = getASTree();
852         return tree == null ? null : (MDRParser) tree.getASTContext();
853     }
854
855     protected final Object JavaDoc getInternalForm() {
856         return getElementInfo();
857     }
858
859     protected void _delete() {
860         super._delete();
861         // --- delete this instance ---------------------------------------
862
try {
863             ((StorableObject) _getDelegate()).deleteInstance();
864         } catch (StorageException e) {
865             throw (GeneralException) ErrorManager.getDefault().annotate(new GeneralException(e.getMessage()), e);
866         }
867     }
868
869     protected final LightAttrList createChildrenList(LightAttrList currentList, String JavaDoc attrName, ElementInfo[] infos, int changeMask, boolean rebuild) {
870         DeferredAttrList deferredList;
871         try {
872             if (currentList != null) {
873                 deferredList = (DeferredAttrList) ((AttrListWrapper) currentList.getInnerList()).getInnerList();
874                 if (rebuild) {
875                     for (Iterator it = deferredList.iterator(); it.hasNext();) {
876                         MetadataElement temp = (MetadataElement) it.next();
877                         it.remove();
878                         temp.refDelete();
879                     }
880                 } else {
881                     if (!isNew() && (infos.length != currentList.size())) {
882                         JMManager.getLog().log(ErrorManager.WARNING, "Inconsistent storage from attribute: " + attrName);
883                         fixMembers(currentList, infos);
884                     } else {
885                         int i = 0;
886                         for (Iterator it = deferredList.iterator(); it.hasNext(); i++) {
887                             SemiPersistentElement im = (SemiPersistentElement) it.next();
888                             if (isNew()) {
889                                 // if an existing feature is added into a new element,
890
// it needs to be set to new
891
im.setNew();
892                             } else {
893                                 if (checkElementType(infos[i], im)) {
894                                     im.setElementInfo(infos[i]);
895                                 } else {
896                                     JMManager.getLog().log(ErrorManager.WARNING, "Inconsistent storage - element types do not match.");
897                                     fixMembers(currentList, infos);
898                                     break;
899                                 }
900                             }
901                         }
902                     }
903                     deferredList = null;
904                 }
905             } else {
906                 StorableFeatured storable = (StorableFeatured) _getDelegate();
907                 deferredList = new DeferredAttrList(storable, storable.getClassProxy().getAttrDesc(attrName), new ArrayList());
908                 currentList = createWrapper(attrName, deferredList, changeMask);
909             }
910             if (deferredList != null) {
911                 for (int i = 0; i < infos.length; i++) {
912                     SemiPersistentElement s = createElement(infos[i]);
913                     deferredList.add(s);
914                 }
915             }
916         } catch (StorageException e) {
917             throw (GeneralException) ErrorManager.getDefault().annotate(new GeneralException(e.getMessage()), e);
918         }
919         return currentList;
920     }
921     
922     protected final LightAttrList createChildrenList(String JavaDoc attrName, AttrListWrapper persistentList, Collection values, int changeMask) {
923         if (values != null) {
924             List innerList = persistentList.getInnerList();
925             for (Iterator it = values.iterator(); it.hasNext();) {
926                 innerList.add(it.next());
927             }
928         }
929         persistentList.setAttrName(attrName);
930         return new LightAttrList(persistentList, this, changeMask, true);
931     }
932     
933     protected final LightAttrList createChildrenList(LightAttrList currentList, String JavaDoc attrName, AttrListWrapper persistentList, ElementInfo[] infos, int changeMask) {
934         List nakedCollection = persistentList.getInnerList();
935         boolean needsUpdate = false;
936
937         if (!isNew() && (nakedCollection.size() != infos.length)) {
938             fixMembers(nakedCollection, infos);
939             needsUpdate = true;
940         }
941         ListIterator it = nakedCollection.listIterator();
942         for (int i = 0; i < infos.length; i++) {
943             SemiPersistentElement element = (SemiPersistentElement) it.next();
944             element.setElementInfo(infos[i]);
945         }
946
947         persistentList.setAttrName(attrName);
948         if (currentList == null) {
949             currentList = new LightAttrList(persistentList, this, changeMask, true);
950         } else if (needsUpdate) {
951             currentList.setInnerList(persistentList);
952         }
953
954         return currentList;
955     }
956     
957     protected final AttrListWrapper getPersistentList(String JavaDoc attrName, List list) {
958         AttrListWrapper result = (AttrListWrapper) list;
959         result.setAttrName(attrName);
960         return result;
961     }
962     
963     protected final void persistChildren(AttrListWrapper persistentList, ElementInfo[] infos) {
964         List nakedCollection = persistentList.getInnerList();
965         if (!nakedCollection.isEmpty()) {
966             JMManager.getLog().notify(ErrorManager.INFORMATIONAL, new Exception JavaDoc("Inconsistent storage - persistent children collection not empty although parent says it has not been persisted yet. Removing old children...")); // NOI18N
967
processMembers(persistentList, infos);
968         } else {
969             for (int i = 0; i < infos.length; i++) {
970                 SemiPersistentElement element = createElement(infos[i], false);
971                 nakedCollection.add(element);
972             }
973         }
974     }
975     
976     protected final void deleteChildren(String JavaDoc attrName, AttrListWrapper persistentList) {
977         persistentList.setAttrName(attrName);
978         for (Iterator it = persistentList.iterator(); it.hasNext();) {
979             RefObject obj = (RefObject) it.next();
980             it.remove();
981             obj.refDelete();
982         }
983     }
984 }
985
Popular Tags