KickJava   Java API By Example, From Geeks To Geeks.

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


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.Collection JavaDoc;
22 import java.util.List JavaDoc;
23 import javax.jmi.reflect.ConstraintViolationException;
24 import org.netbeans.jmi.javamodel.*;
25 import org.netbeans.lib.java.parser.ASTree;
26 import org.netbeans.lib.java.parser.Token;
27 import org.netbeans.mdr.storagemodel.StorableObject;
28 import org.netbeans.modules.javacore.JMManager;
29 import org.netbeans.modules.javacore.parser.*;
30 import org.openide.util.Utilities;
31
32 /**
33  * Represents an attribute of an annotation. Consider annotation
34  * <code>
35  * public @interface RequestForEnhancement {
36  * int id();
37  * String synopsis();
38  * String engineer() default "[unassigned]"
39  * String date(); default "[unimplemented]"
40  * }
41  * </code>
42  *
43  * Such an annotation contains four instances of the Attribute element. They
44  * are named id, synopsis, engineer and date. Two elements have not the default
45  * value. (Calling of getDefaultValue() method returns null.)
46  *
47  * @author Pavel Flaska
48  */

49 public abstract class AttributeImpl extends FeatureImpl implements Attribute {
50     
51     InitialValue defaultValue;
52     String JavaDoc defaultValueText;
53     TypeReference typeName;
54     
55     boolean defaultValueInited;
56     protected TypeRef type;
57     
58     private static final ElementInfo DEFAULT_INFO = new AttributeInfo(null, 0, null, 0, null, null, null);
59
60     private boolean elementsInited;
61
62     /** Creates a new instance of AttributeImpl */
63     public AttributeImpl(StorableObject s) {
64         super(s);
65         defaultValueInited = false;
66     }
67     
68     protected void matchPersistent(ElementInfo info) {
69         super.matchPersistent(info);
70         AttributeInfo newInfo = (AttributeInfo) info;
71         
72         if (!isPersisted()) {
73             setPersisted(true);
74             persist();
75             setTypeRef(newInfo.type);
76             persistChildren(getPersistentList("annotations", super_getAnnotations()), ((FeatureInfo) info).annotations);
77         } else {
78             if (!Utilities.compareObjects(newInfo.type, getTypeRef())) {
79                 setType(resolveType(newInfo.type));
80             }
81             processMembers(getAnnotations(), newInfo.annotations);
82         }
83     }
84     
85     protected void matchElementInfo(ElementInfo info) {
86         super.matchElementInfo(info);
87         resetASTElements();
88     }
89     
90     /**
91      * Returns the default value of the annotation attribute.
92      * In the following example, the value is represented by "[unassigned]".
93      *
94      * <code>
95      * String engineer() default "[unassigned]"
96      * </code>
97      *
98      * @return InitialValue default attribute's value
99      */

100     public InitialValue getDefaultValue() {
101         checkUpToDate();
102         if (!defaultValueInited) {
103             initDefaultValue();
104         }
105         return defaultValue;
106     }
107     
108     /**
109      * Sets the default value of the annotation attribute.
110      * {@link #getDefaultValue} for description of annotation attribute.
111      *
112      * @param initial value tree representing new default value
113      */

114     public void setDefaultValue(InitialValue newValue) {
115         if (!defaultValueInited) {
116             initDefaultValue();
117             defaultValueInited = true;
118         }
119         changeChild(defaultValue, newValue);
120         defaultValue = newValue;
121         defaultValueText = null;
122         objectChanged(CHANGED_INITIAL_VALUE);
123     }
124     
125     /**
126      * Returns the default value of the annotation attribute in string
127      * representation. In the following example, the value is represented
128      * by "[unassigned]".
129      *
130      * <code>
131      * String engineer() default "[unassigned]"
132      * </code>
133      *
134      * @return InitialValue default attribute's value
135      */

136     public String JavaDoc getDefaultValueText() {
137         checkUpToDate();
138         if (isChanged(CHANGED_INITIAL_VALUE)) {
139             if (defaultValue != null) {
140                 throw new ConstraintViolationException(null, null,
141                     "Cannot ask for default value text after the default value was changed."); // NOI18N
142
}
143             return defaultValueText;
144         } else {
145             return extractDefaultValueText();
146         }
147     }
148     
149     /**
150      * Sets the default value of annotation attribute.
151      * See {@link #getDefaultText} for description of annotation attribute.
152      *
153      * @param newValue New value to be set.
154      */

155     public void setDefaultValueText(String JavaDoc newValue) {
156         if (!elementsInited) {
157             initASTElements();
158         }
159         if (defaultValueInited && defaultValue != null) {
160             changeChild(defaultValue, null);
161         }
162         objectChanged(CHANGED_INITIAL_VALUE);
163         defaultValueText = newValue;
164         defaultValue = null;
165         defaultValueInited = true;
166     }
167     
168     public List JavaDoc getChildren() {
169         List JavaDoc result = super.getChildren();
170         addIfNotNull(result, getTypeName());
171         if (!isChanged(CHANGED_INITIAL_VALUE) || defaultValueText == null) {
172             addIfNotNull(result, getDefaultValue());
173         }
174         return result;
175     }
176     
177     protected List JavaDoc getInitedChildren() {
178         List JavaDoc result = super.getInitedChildren();
179         if (elementsInited) {
180             addIfNotNull(result, getTypeName());
181             if (defaultValueInited) {
182                 if (!isChanged(CHANGED_INITIAL_VALUE) || defaultValueText == null) {
183                     addIfNotNull(result, getDefaultValue());
184                 }
185             }
186         }
187         return result;
188     }
189     
190     /**
191      * Returns the value of type. You will get resolved Type model element.
192      * Method can return null value on new attributes created by
193      * createAttribute() method on its class proxy.
194      *
195      * @return value of type or null if new attribute has not set type
196      */

197     public Type getType() {
198         checkUpToDate();
199         return resolveType(getTypeRef());
200     }
201
202     private void fireTypeNameChange(TypeReference typeReference) {
203         Object JavaDoc oldValue = null;
204         Object JavaDoc newValue = null;
205         if (elementsInited && !disableChanges) {
206             oldValue = getTypeName();
207             newValue = typeReference;
208         }
209         fireAttrChange("typeName", oldValue, newValue); // NOI18N
210
}
211     
212     /**
213      * Sets the value of type. You have to provide resolved model element.
214      * The method guarantee the sync values between type and typeName.
215      *
216      * @param newValue new value to be set to type
217      */

218     public void setType(Type newValue) {
219         TypeRef tr = typeToTypeRef(newValue);
220         TypeReference typeReference = (TypeReference) typeRefToTypeReference(tr, 0);
221         fireTypeNameChange(typeReference);
222         _setTypeName(typeReference, tr);
223     }
224
225     public TypeReference getTypeName() {
226         checkUpToDate();
227         if (!elementsInited) {
228             initASTElements();
229         }
230         return typeName;
231     }
232
233     public void setTypeName(TypeReference typeName) {
234         _setTypeName(typeName, typeReferenceToTypeRef(typeName, 0));
235     }
236
237     private void _setTypeName(TypeReference typeName, TypeRef typeRef) {
238         if (!disableChanges) {
239             objectChanged(CHANGED_TYPE);
240             changeChild(getTypeName(), typeName);
241             this.typeName = typeName;
242         }
243         setTypeRef(typeRef);
244     }
245
246     public Collection JavaDoc getValues() {
247         throw new UnsupportedOperationException JavaDoc("getValues()"); // NOI18N
248
}
249     
250     /**
251      * Returns the source representation of the attribute element. If the
252      * element is not changed, it cuts the representation from the original
253      * source text. Otherwise it creates it.
254      *
255      * @return source text representation of the instance
256      */

257     public String JavaDoc getSourceText() {
258         String JavaDoc origElem;
259         if ((origElem = checkChange()) != null)
260             return origElem;
261         
262         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(27);
263         buf.append('\n'); // todo (#pf): use options for leaving empty line before the element
264
generateNewJavaDoc(buf);
265         buf.append(getIndentation());
266         buf.append(((MetadataElement) getTypeName()).getSourceText());
267         buf.append(' ').append(getName());
268         buf.append(formatElementPart(MetadataElement.PAR_OPEN_BRACKET));
269         buf.append(formatElementPart(MetadataElement.PAR_CLOSE_BRACKET));
270         String JavaDoc defValText = defaultValue == null ? defaultValueText :
271             ((MetadataElement) getDefaultValue()).getSourceText();
272         if (defValText != null) {
273             buf.append(" default "); // todo (#pf): use formatter! // NOI18N
274
buf.append(defValText);
275         }
276         buf.append(';');
277         
278         return buf.toString();
279     }
280     
281     /**
282      * Returns a list of changes which have been done on element.
283      *
284      * @param diff diff elements representing changes (list to add to)
285      */

286     public void getDiff(List JavaDoc diff) {
287         ASTree tree = getASTree();
288         ASTProvider parser = getParser();
289         ASTree[] children = tree.getSubTrees();
290
291        // javadoc print
292
replaceJavaDoc(diff);
293         // modifiers
294
if (isChanged(CHANGED_MODIFIERS | CHANGED_ANNOTATION)) {
295             diffModifiers(diff, children[1], parser);
296         } else if (children[0] != null) {
297             AttributeInfo astInfo=(AttributeInfo)getElementInfo();
298             getCollectionDiff(diff, parser, CHANGED_ANNOTATION, astInfo.annotations, getAnnotations(), parser.getToken(children[0].getLastToken()).getEndOffset(), " "); // NOI18N
299
}
300         // type
301
getChildDiff(diff, getParser(), tree.getSubTrees()[1], (MetadataElement) getTypeName(), CHANGED_TYPE);
302         // name
303
if (isChanged(CHANGED_NAME)) {
304             Token identifier = (Token) tree.getSubTrees()[2];
305             int startOffset = identifier.getStartOffset();
306             int endOffset = identifier.getEndOffset();
307             diff.add(new DiffElement(startOffset, endOffset, getName()));
308         }
309         if (isChanged(CHANGED_INITIAL_VALUE)) {
310             String JavaDoc newText = defaultValue == null ? defaultValueText :
311                 ((MetadataElement) getDefaultValue()).getSourceText();
312             ASTree initValT = extractDefaultValue();
313             // there was an default value in original source
314
int startOffset, endOffset;
315             endOffset = parser.getToken(tree.getLastToken()).getStartOffset();
316             if (initValT != null) {
317                 // changing old default value
318
int initValFirstToken = initValT.getFirstToken();
319                 if (newText != null) {
320                     startOffset = parser.getToken(initValFirstToken).getStartOffset();
321                 } else {
322                     startOffset = parser.getToken(initValFirstToken - 2).getEndOffset();
323                 }
324             } else {
325                 if (newText == null) return;
326                 // adding new default value
327
newText = " default " + newText; // NOI18N
328
startOffset = endOffset;
329             }
330             diff.add(new DiffElement(startOffset, endOffset, newText == null ? "" : newText));
331         } else if (isChanged(CHANGED_CHILDREN)) {
332             // children changed in initial value.
333
MetadataElement defaultValue = (MetadataElement) getDefaultValue();
334             if (defaultValue.isChanged()) {
335                 defaultValue.getDiff(diff);
336             }
337         }
338     }
339     
340     ////////////////////////////////////////////////////////////////////////////
341
protected ElementInfo getDefaultInfo() {
342         return DEFAULT_INFO;
343     }
344     
345     protected void setData(List JavaDoc annotations,
346                            String JavaDoc javadocText,
347                            JavaDoc javadoc,
348                            TypeReference typeName,
349                            InitialValue defaultValue,
350                            String JavaDoc defaultValueText)
351     {
352         super.setData(annotations, javadocText, javadoc);
353         if (defaultValueText == null) {
354             changeChild(null, defaultValue);
355             this.defaultValue = defaultValue;
356         } else {
357             if (defaultValue != null) {
358                 throw new ConstraintViolationException(null, null, "Cannot set both defaultValue and defaultValueText."); // NOI18N
359
}
360             this.defaultValueText = defaultValueText;
361         }
362         defaultValueInited = true;
363         changeChild(null, typeName);
364         this.typeName = typeName;
365         elementsInited = true;
366     }
367
368     protected void initChildren() {
369         childrenInited = false;
370         super.initChildren();
371         childrenInited = true;
372         if (elementsInited) {
373             initASTElements();
374         }
375         if (defaultValueInited) {
376             JMManager.getTransactionMutex().addBFeatureToInitQueue(this);
377         }
378     }
379     
380     protected void initASTElements() {
381         elementsInited = false;
382         if (!childrenInited) {
383             initChildren();
384         }
385         AttributeInfo info = (AttributeInfo) getElementInfo();
386         ASTree tree = info.getTypeAST(this);
387         typeName = (TypeReference) initOrCreate(typeName, tree);
388         //info.setSemanticInfo(this);
389
elementsInited = true;
390     }
391     
392     protected void resetChildren() {
393         super.resetChildren();
394         resetASTElements();
395     }
396
397     protected void resetASTElements() {
398         if (defaultValue != null) {
399             InitialValue temp = defaultValue;
400             defaultValue = null;
401             changeChild(temp, null);
402             temp.refDelete();
403         }
404         if (typeName != null) {
405             TypeReference temp = typeName;
406             typeName = null;
407             changeChild(temp, null);
408             temp.refDelete();
409         }
410         defaultValueInited = false;
411         elementsInited = false;
412     }
413     
414     public Element duplicate(JavaModelPackage targetExtent) {
415         InitialValue defVal;
416         String JavaDoc defValText;
417         
418         if (isChanged(CHANGED_INITIAL_VALUE) && defaultValueText != null) {
419             defVal = null;
420             defValText = defaultValueText;
421         } else {
422             defVal = (InitialValue) duplicateElement(getDefaultValue(), targetExtent);
423             defValText = null;
424         }
425         
426         return targetExtent.getAttribute().createAttribute(
427                 getName(),
428                 duplicateList(getAnnotations(), targetExtent),
429                 getModifiers(),
430                 null,
431                 (JavaDoc) duplicateElement(getJavadoc(), targetExtent),
432                 (TypeReference) duplicateElement(getTypeName(), targetExtent),
433                 defVal,
434                 defValText
435                );
436     }
437     
438     public void initDefaultValue() {
439         defaultValueInited = false;
440         if (!elementsInited) {
441             initASTElements();
442         }
443         AttributeInfo defaultValInfo = (AttributeInfo) getElementInfo();
444         if (defaultValInfo != null) {
445             defaultValInfo.doAttribution(this);
446             defaultValue = (InitialValue) initOrCreate(defaultValue, extractDefaultValue());
447         }
448         defaultValueInited = true;
449     }
450     
451     ////////////////////////////////////////////////////////////////////////////
452
// PRIVATE MEMBERS
453
////////////////////////////////////////////////////////////////////////////
454
private ASTree extractDefaultValue() {
455         ASTree defValTree = getASTree().getSubTrees()[3];
456         return defValTree == null ? null : defValTree.getSubTrees()[0];
457     }
458
459     private String JavaDoc extractDefaultValueText() {
460         ASTProvider parser = getParser();
461         if (parser == null)
462             return null;
463         ASTree attributeDefaultValue = extractDefaultValue();
464         if (attributeDefaultValue == null)
465             return null;
466         return parser.getText(attributeDefaultValue);
467     }
468
469     protected void _delete() {
470         // --- delete components -------------------------------------------
471
if (elementsInited) {
472             deleteChild(typeName);
473         }
474         if (defaultValueInited) {
475             deleteChild(defaultValue);
476         }
477         // --- delete links -----------------------------------------------
478
// no links to delete
479
// [TODO] should Throws association be notified?
480
// --- call super -------------------------------------------------
481
super._delete();
482     }
483     
484 }
485
Popular Tags