KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > apt > core > internal > util > Factory


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 BEA Systems, Inc.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * tyeung@bea.com - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.jdt.apt.core.internal.util;
13
14 import com.sun.mirror.declaration.AnnotationMirror;
15 import com.sun.mirror.declaration.AnnotationValue;
16 import com.sun.mirror.declaration.ParameterDeclaration;
17 import com.sun.mirror.type.AnnotationType;
18 import com.sun.mirror.type.ArrayType;
19 import com.sun.mirror.type.ClassType;
20 import com.sun.mirror.type.InterfaceType;
21 import com.sun.mirror.type.PrimitiveType;
22 import com.sun.mirror.type.TypeMirror;
23
24 import java.util.ArrayList JavaDoc;
25 import java.util.Collections JavaDoc;
26 import java.util.List JavaDoc;
27
28 import org.eclipse.core.resources.IFile;
29 import org.eclipse.jdt.apt.core.internal.declaration.*;
30 import org.eclipse.jdt.apt.core.internal.env.BaseProcessorEnv;
31 import org.eclipse.jdt.apt.core.internal.type.ArrayTypeImpl;
32 import org.eclipse.jdt.apt.core.internal.type.ErrorType;
33 import org.eclipse.jdt.apt.core.internal.type.WildcardTypeImpl;
34 import org.eclipse.jdt.core.dom.ASTNode;
35 import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
36 import org.eclipse.jdt.core.dom.IAnnotationBinding;
37 import org.eclipse.jdt.core.dom.IBinding;
38 import org.eclipse.jdt.core.dom.IMethodBinding;
39 import org.eclipse.jdt.core.dom.ITypeBinding;
40 import org.eclipse.jdt.core.dom.IVariableBinding;
41 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
42 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
43
44 public class Factory
45 {
46     private static final String JavaDoc NULL_BINDING_NAME = "[NullBinding]"; //$NON-NLS-1$
47
// using auto-boxing to take advantage of caching, if any.
48
// the dummy value picked here falls within the caching range.
49
public static final Byte JavaDoc DUMMY_BYTE = 0;
50     public static final Character JavaDoc DUMMY_CHAR = '0';
51     public static final Double JavaDoc DUMMY_DOUBLE = 0d;
52     public static final Float JavaDoc DUMMY_FLOAT = 0f;
53     public static final Integer JavaDoc DUMMY_INTEGER = 0;
54     public static final Long JavaDoc DUMMY_LONG = 0l;
55     public static final Short JavaDoc DUMMY_SHORT = 0;
56     public static TypeDeclarationImpl createReferenceType(ITypeBinding binding, BaseProcessorEnv env)
57     {
58         if(binding == null || binding.isNullType()) return null;
59         TypeDeclarationImpl mirror = null;
60         // must test for annotation type before interface since annotation
61
// is an interface
62
if( binding.isAnnotation() )
63             mirror = new AnnotationDeclarationImpl(binding, env);
64         else if (binding.isInterface() )
65             mirror = new InterfaceDeclarationImpl(binding, env);
66         // must test for enum first since enum is also a class.
67
else if( binding.isEnum() )
68             mirror = new EnumDeclarationImpl(binding, env);
69         else if( binding.isClass() )
70             mirror = new ClassDeclarationImpl(binding, env);
71         else
72             throw new IllegalStateException JavaDoc("cannot create type declaration from " + binding); //$NON-NLS-1$
73

74         return mirror;
75     }
76
77     public static EclipseDeclarationImpl createDeclaration(IBinding binding, BaseProcessorEnv env)
78     {
79         if(binding == null) return null;
80        
81         switch(binding.getKind())
82         {
83         case IBinding.TYPE:
84             final ITypeBinding typeBinding = (ITypeBinding)binding;
85             if( typeBinding.isAnonymous() || typeBinding.isArray() ||
86                 typeBinding.isWildcardType() || typeBinding.isPrimitive() )
87                 throw new IllegalStateException JavaDoc("failed to create declaration from " + binding); //$NON-NLS-1$
88
if( typeBinding.isTypeVariable() )
89                 return new TypeParameterDeclarationImpl(typeBinding, env);
90             else
91                 return createReferenceType(typeBinding, env);
92         case IBinding.VARIABLE:
93             final IVariableBinding varBinding = (IVariableBinding)binding;
94             if(varBinding.isEnumConstant())
95                 return new EnumConstantDeclarationImpl(varBinding, env);
96             else
97                 return new FieldDeclarationImpl(varBinding, env);
98         case IBinding.METHOD:
99             final IMethodBinding method = (IMethodBinding)binding;
100             if( method.isConstructor() )
101                 return new ConstructorDeclarationImpl(method, env);
102             final ITypeBinding declaringType = method.getDeclaringClass();
103             if( declaringType != null && declaringType.isAnnotation() )
104                 return new AnnotationElementDeclarationImpl(method, env);
105             else
106                 return new MethodDeclarationImpl(method, env);
107         default:
108             throw new IllegalStateException JavaDoc("failed to create declaration from " + binding); //$NON-NLS-1$
109
}
110     }
111     
112     public static EclipseDeclarationImpl createDeclaration(
113             ASTNode node,
114             IFile file,
115             BaseProcessorEnv env)
116     {
117          if( node == null )
118              return null;
119          switch( node.getNodeType() )
120          {
121          case ASTNode.SINGLE_VARIABLE_DECLARATION:
122              return new SourceParameterDeclarationImpl((SingleVariableDeclaration)node, file, env);
123          case ASTNode.VARIABLE_DECLARATION_FRAGMENT:
124              return new ASTBasedFieldDeclarationImpl( (VariableDeclarationFragment)node, file, env );
125          case ASTNode.METHOD_DECLARATION :
126              final org.eclipse.jdt.core.dom.MethodDeclaration methodDecl =
127                  (org.eclipse.jdt.core.dom.MethodDeclaration)node;
128              if( methodDecl.isConstructor() )
129                  return new ASTBasedConstructorDeclarationImpl(methodDecl, file, env);
130              else
131                  return new ASTBasedMethodDeclarationImpl(methodDecl, file, env );
132          case ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION:
133              return new ASTBasedMethodDeclarationImpl((AnnotationTypeMemberDeclaration)node, file, env);
134          default :
135              throw new UnsupportedOperationException JavaDoc(
136                      "cannot create mirror type from " + //$NON-NLS-1$
137
node.getClass().getName() );
138          }
139     }
140
141     public static EclipseMirrorType createTypeMirror(ITypeBinding binding, BaseProcessorEnv env)
142     {
143         if( binding == null ) return null;
144
145         if( binding.isPrimitive() ){
146             if( "int".equals(binding.getName()) ) //$NON-NLS-1$
147
return env.getIntType();
148             else if( "byte".equals(binding.getName()) ) //$NON-NLS-1$
149
return env.getByteType();
150             else if( "short".equals(binding.getName()) ) //$NON-NLS-1$
151
return env.getShortType();
152             else if( "char".equals(binding.getName()) ) //$NON-NLS-1$
153
return env.getCharType();
154             else if( "long".equals(binding.getName()) ) //$NON-NLS-1$
155
return env.getLongType();
156             else if( "float".equals(binding.getName()) ) //$NON-NLS-1$
157
return env.getFloatType();
158             else if( "double".equals(binding.getName()) ) //$NON-NLS-1$
159
return env.getDoubleType();
160             else if( "boolean".equals(binding.getName())) //$NON-NLS-1$
161
return env.getBooleanType();
162             else if( "void".equals(binding.getName()) ) //$NON-NLS-1$
163
return env.getVoidType();
164             else
165                 throw new IllegalStateException JavaDoc("unrecognized primitive type: " + binding); //$NON-NLS-1$
166
}
167         else if( binding.isArray() )
168             return new ArrayTypeImpl(binding, env);
169         else if( binding.isWildcardType() ){
170             return new WildcardTypeImpl(binding, env);
171         }
172         else if( binding.isTypeVariable() )
173             return new TypeParameterDeclarationImpl(binding, env);
174         else
175             return createReferenceType(binding, env);
176     }
177     
178     public static ParameterDeclaration createParameterDeclaration(
179             final SingleVariableDeclaration param,
180             final IFile file,
181             final BaseProcessorEnv env)
182     {
183         return new SourceParameterDeclarationImpl(param, file, env);
184     }
185     
186     
187     public static ParameterDeclaration createParameterDeclaration(
188             final ExecutableDeclarationImpl exec,
189             final int paramIndex,
190             final ITypeBinding type,
191             final BaseProcessorEnv env )
192     {
193         return new BinaryParameterDeclarationImpl(exec, type, paramIndex, env);
194     }
195    
196   
197     /**
198      * @param annotation the ast node.
199      * @param annotated the declaration that <code>annotation</code> annotated
200      * @param env
201      * @return a newly created {@link AnnotationMirror} object
202      */

203     public static AnnotationMirror createAnnotationMirror(final IAnnotationBinding annotation,
204                                                           final EclipseDeclarationImpl annotated,
205                                                           final BaseProcessorEnv env)
206     {
207         return new AnnotationMirrorImpl(annotation, annotated, env);
208     }
209     
210     public static AnnotationValue createDefaultValue(
211             Object JavaDoc domValue,
212             AnnotationElementDeclarationImpl decl,
213             BaseProcessorEnv env)
214     {
215         if( domValue == null ) return null;
216         final Object JavaDoc converted = convertDOMValueToMirrorValue(
217                 domValue, null, decl, decl, env, decl.getReturnType());
218         
219         return createAnnotationValueFromDOMValue(converted, null, -1, decl, env);
220     }
221     
222     /**
223      * Build an {@link AnnotationValue} object based on the given dom value.
224      * @param domValue default value according to the DOM API.
225      * @param decl the element declaration whose default value is <code>domValue</code>
226      * if domValue is an annotation, then this is the declaration it annotated.
227      * In all other case, this parameter is ignored.
228      * @param env
229      * @return an annotation value
230      */

231     public static AnnotationValue createDefaultValue(Object JavaDoc domValue,
232                                                      ASTBasedAnnotationElementDeclarationImpl decl,
233                                                      BaseProcessorEnv env)
234     {
235         if( domValue == null ) return null;
236         final Object JavaDoc converted = convertDOMValueToMirrorValue(
237                 domValue, null, decl, decl, env, decl.getReturnType());
238         
239         return createAnnotationValueFromDOMValue(converted, null, -1, decl, env);
240     }
241     
242     /**
243      * Build an {@link AnnotationValue} object based on the given dom value.
244      * @param domValue annotation member value according to the DOM API.
245      * @param elementName the name of the member value
246      * @param anno the annotation that directly contains <code>domValue</code>
247      * @param env
248      * @return an annotation value
249      */

250     public static AnnotationValue createAnnotationMemberValue(Object JavaDoc domValue,
251                                                               String JavaDoc elementName,
252                                                               AnnotationMirrorImpl anno,
253                                                               BaseProcessorEnv env,
254                                                               TypeMirror expectedType)
255     {
256         if( domValue == null ) return null;
257         final Object JavaDoc converted = convertDOMValueToMirrorValue(
258                 domValue, elementName, anno,
259                 anno.getAnnotatedDeclaration(), env, expectedType);
260         return createAnnotationValueFromDOMValue(converted, elementName, -1, anno, env);
261     }
262     
263     /**
264      * @param convertedValue value in mirror form.
265      * @param name the name of the annotation member or null for default value
266      * @param index the number indicate the source order of the annotation member value
267      * in the annotation instance.
268      * @param mirror either {@link AnnotationMirrorImpl } or {@link AnnotationElementDeclarationImpl}
269      * @param env
270      */

271     public static AnnotationValue createAnnotationValueFromDOMValue(Object JavaDoc convertedValue,
272                                                                     String JavaDoc name,
273                                                                     int index,
274                                                                     EclipseMirrorObject mirror,
275                                                                     BaseProcessorEnv env)
276     {
277         if( convertedValue == null ) return null;
278         if( mirror instanceof AnnotationMirrorImpl )
279             return new AnnotationValueImpl(convertedValue, name, index, (AnnotationMirrorImpl)mirror, env);
280         else
281             return new AnnotationValueImpl(convertedValue, index, (AnnotationElementDeclarationImpl)mirror, env);
282     }
283
284
285     /**
286      * Building an annotation value object based on the dom value.
287      *
288      * @param dom the dom value to convert to the mirror specification.
289      * @see com.sun.mirror.declaration.AnnotationValue#getObject()
290      * @param name the name of the element if <code>domValue</code> is an
291      * element member value of an annotation
292      * @param parent the parent of this annotation value.
293      * @param decl if <code>domValue</code> is a default value, then this is the
294      * annotation element declaration where the default value originates
295      * if <code>domValue</code> is an annotation, then <code>decl</code>
296      * is the declaration that it annotates.
297      * @param expectedType the declared type of the member value.
298      * @param needBoxing <code>true</code> indicate an array should be returned.
299      * @return the converted annotation value or null if the conversion failed
300      */

301     private static Object JavaDoc convertDOMValueToMirrorValue(Object JavaDoc domValue,
302                                                        String JavaDoc name,
303                                                        EclipseMirrorObject parent,
304                                                        EclipseDeclarationImpl decl,
305                                                        BaseProcessorEnv env,
306                                                        TypeMirror expectedType)
307     {
308         if( domValue == null ) return null;
309         
310         final Object JavaDoc returnValue;
311         if( domValue instanceof Boolean JavaDoc ||
312             domValue instanceof Byte JavaDoc ||
313             domValue instanceof Character JavaDoc ||
314             domValue instanceof Double JavaDoc ||
315             domValue instanceof Float JavaDoc ||
316             domValue instanceof Integer JavaDoc ||
317             domValue instanceof Long JavaDoc ||
318             domValue instanceof Short JavaDoc ||
319             domValue instanceof String JavaDoc )
320             returnValue = domValue;
321         
322         else if( domValue instanceof IVariableBinding )
323         {
324             returnValue = Factory.createDeclaration((IVariableBinding)domValue, env);
325         }
326         else if (domValue instanceof Object JavaDoc[])
327         {
328             final Object JavaDoc[] elements = (Object JavaDoc[])domValue;
329             final int len = elements.length;
330             final List JavaDoc<AnnotationValue> annoValues = new ArrayList JavaDoc<AnnotationValue>(len);
331             final TypeMirror leaf;
332             if( expectedType instanceof ArrayType )
333                 leaf = ((ArrayType)expectedType).getComponentType();
334             else
335                 leaf = expectedType; // doing our best here.
336
for( int i=0; i<len; i++ ){
337                 if( elements[i] == null ) continue;
338                 // can't have multi-dimensional array.
339
// there should be already a java compile time error
340
else if( elements[i] instanceof Object JavaDoc[] )
341                     return null;
342
343                 Object JavaDoc o = convertDOMValueToMirrorValue( elements[i], name, parent, decl, env, leaf );
344                 if( o == null )
345                     return null;
346                 assert( !( o instanceof IAnnotationBinding ) ) :
347                     "Unexpected return value from convertDomValueToMirrorValue! o.getClass().getName() = " //$NON-NLS-1$
348
+ o.getClass().getName();
349                 
350                 final AnnotationValue annoValue = createAnnotationValueFromDOMValue(o, name, i, parent, env);
351                 if( annoValue != null )
352                     annoValues.add(annoValue);
353             }
354             return annoValues;
355         }
356         // caller should have caught this case.
357
else if( domValue instanceof ITypeBinding )
358             returnValue = Factory.createTypeMirror((ITypeBinding)domValue, env);
359         
360         else if( domValue instanceof IAnnotationBinding )
361         {
362             returnValue = Factory.createAnnotationMirror((IAnnotationBinding)domValue, decl, env);
363         }
364         else
365             // should never reach this point
366
throw new IllegalStateException JavaDoc("cannot build annotation value object from " + domValue); //$NON-NLS-1$
367

368         return performNecessaryTypeConversion(expectedType, returnValue, name, parent, env);
369     }
370     
371     public static Object JavaDoc getMatchingDummyValue(final Class JavaDoc<?> expectedType){
372         if( expectedType.isPrimitive() ){
373             if(expectedType == boolean.class)
374                 return Boolean.FALSE;
375             else if( expectedType == byte.class )
376                 return DUMMY_BYTE;
377             else if( expectedType == char.class )
378                 return DUMMY_CHAR;
379             else if( expectedType == double.class)
380                 return DUMMY_DOUBLE;
381             else if( expectedType == float.class )
382                 return DUMMY_FLOAT;
383             else if( expectedType == int.class )
384                 return DUMMY_INTEGER;
385             else if( expectedType == long.class )
386                 return DUMMY_LONG;
387             else if(expectedType == short.class)
388                 return DUMMY_SHORT;
389             else // expectedType == void.class. can this happen?
390
return DUMMY_INTEGER; // anything would work
391
}
392         else
393             return null;
394     }
395     
396     /**
397      * This method is designed to be invoke by the invocation handler and anywhere that requires
398      * a AnnotationValue (AnnotationMirror member values and default values from anonotation member).
399      *
400      * Regardless of the path, there are common primitive type conversion that needs to take place.
401      * The type conversions are respects the type widening and narrowing rules from JLS 5.1.2 and 5.1.2.
402      *
403      * The only question remains is what is the type of the return value when the type conversion fails? *
404      * When <code>avoidReflectException</code> is set to <code>true</code>
405      * Return <code>false</code> if the expected type is <code>boolean</code>
406      * Return numeric 0 for all numeric primitive types and '0' for <code>char</code>
407      *
408      * Otherwise:
409      * Return the value unchanged.
410      *
411      * In the invocation handler case:
412      * The value returned by {@link java.lang.reflect.InvocationHandler#invoke}
413      * will be converted into the expected type by the {@link java.lang.reflect.Proxy}.
414      * If the value and the expected type does not agree, and the value is not null,
415      * a ClassCastException will be thrown. A NullPointerException will be resulted if the
416      * expected type is a primitive type and the value is null.
417      * This behavior is currently causing annotation processor a lot of pain and the decision is
418      * to not throw such unchecked exception. In the case where a ClassCastException or
419      * NullPointerException will be thrown return some dummy value. Otherwise, return
420      * the original value.
421      * Chosen dummy values:
422      * Return <code>false</code> if the expected type is <code>boolean</code>
423      * Return numeric 0 for all numeric primitive types and '0' for <code>char</code>
424      *
425      * This behavior is triggered by setting <code>avoidReflectException</code> to <code>true</code>
426      *
427      * Note: the new behavior deviates from what's documented in
428      * {@link java.lang.reflect.InvocationHandler#invoke} and also deviates from
429      * Sun's implementation.
430      *
431      * see CR260743 and 260563.
432      * @param value the current value from the annotation instance.
433      * @param expectedType the expected type of the value.
434      *
435      */

436     public static Object JavaDoc performNecessaryPrimitiveTypeConversion(
437             final Class JavaDoc<?> expectedType,
438             final Object JavaDoc value,
439             final boolean avoidReflectException)
440     {
441         assert expectedType.isPrimitive() : "expectedType is not a primitive type: " + expectedType.getName(); //$NON-NLS-1$
442
if( value == null)
443             return avoidReflectException ? getMatchingDummyValue(expectedType) : null;
444         // apply widening conversion based on JLS 5.1.2 and 5.1.3
445
final String JavaDoc typeName = expectedType.getName();
446         final char expectedTypeChar = typeName.charAt(0);
447         final int nameLen = typeName.length();
448         // widening byte -> short, int, long, float or double
449
// narrowing byte -> char
450
if( value instanceof Byte JavaDoc )
451         {
452             final byte b = ((Byte JavaDoc)value).byteValue();
453             switch( expectedTypeChar )
454             {
455             case 'b':
456                 if(nameLen == 4) // byte
457
return value; // exact match.
458
else
459                     return avoidReflectException ? Boolean.FALSE : value;
460             case 'c':
461                 return new Character JavaDoc((char)b); // narrowing.
462
case 'd':
463                 return new Double JavaDoc(b); // widening.
464
case 'f':
465                 return new Float JavaDoc(b); // widening.
466
case 'i':
467                 return new Integer JavaDoc(b); // widening.
468
case 'l':
469                 return new Long JavaDoc(b); // widening.
470
case 's':
471                 return new Short JavaDoc(b); // widening.
472
default:
473                 throw new IllegalStateException JavaDoc("unknown type " + expectedTypeChar); //$NON-NLS-1$
474
}
475         }
476         // widening short -> int, long, float, or double
477
// narrowing short -> byte or char
478
else if( value instanceof Short JavaDoc )
479         {
480             final short s = ((Short JavaDoc)value).shortValue();
481             switch( expectedTypeChar )
482             {
483             case 'b':
484                 if(nameLen == 4) // byte
485
return new Byte JavaDoc((byte)s); // narrowing.
486
else
487                     return avoidReflectException ? Boolean.FALSE : value; // completely wrong.
488
case 'c':
489                 return new Character JavaDoc((char)s); // narrowing.
490
case 'd':
491                 return new Double JavaDoc(s); // widening.
492
case 'f':
493                 return new Float JavaDoc(s); // widening.
494
case 'i':
495                 return new Integer JavaDoc(s); // widening.
496
case 'l':
497                 return new Long JavaDoc(s); // widening.
498
case 's':
499                 return value; // exact match
500
default:
501                 throw new IllegalStateException JavaDoc("unknown type " + expectedTypeChar); //$NON-NLS-1$
502
}
503         }
504         // widening char -> int, long, float, or double
505
// narrowing char -> byte or short
506
else if( value instanceof Character JavaDoc )
507         {
508             final char c = ((Character JavaDoc)value).charValue();
509             switch( expectedTypeChar )
510             {
511             case 'b':
512                 if(nameLen == 4) // byte
513
return new Byte JavaDoc((byte)c); // narrowing.
514
else
515                     return avoidReflectException ? Boolean.FALSE : value; // completely wrong.
516
case 'c':
517                 return value; // exact match
518
case 'd':
519                 return new Double JavaDoc(c); // widening.
520
case 'f':
521                 return new Float JavaDoc(c); // widening.
522
case 'i':
523                 return new Integer JavaDoc(c); // widening.
524
case 'l':
525                 return new Long JavaDoc(c); // widening.
526
case 's':
527                 return new Short JavaDoc((short)c); // narrowing.
528
default:
529                 throw new IllegalStateException JavaDoc("unknown type " + expectedTypeChar); //$NON-NLS-1$
530
}
531         }
532         
533         // widening int -> long, float, or double
534
// narrowing int -> byte, short, or char
535
else if( value instanceof Integer JavaDoc )
536         {
537             final int i = ((Integer JavaDoc)value).intValue();
538             switch( expectedTypeChar )
539             {
540             case 'b':
541                 if(nameLen == 4) // byte
542
return new Byte JavaDoc((byte)i); // narrowing.
543
else
544                     return avoidReflectException ? Boolean.FALSE : value; // completely wrong.
545
case 'c':
546                 return new Character JavaDoc((char)i); // narrowing
547
case 'd':
548                 return new Double JavaDoc(i); // widening.
549
case 'f':
550                 return new Float JavaDoc(i); // widening.
551
case 'i':
552                 return value; // exact match
553
case 'l':
554                 return new Long JavaDoc(i); // widening.
555
case 's':
556                 return new Short JavaDoc((short)i); // narrowing.
557
default:
558                 throw new IllegalStateException JavaDoc("unknown type " + expectedTypeChar); //$NON-NLS-1$
559
}
560         }
561         // widening long -> float or double
562
else if( value instanceof Long JavaDoc )
563         {
564             final long l = ((Long JavaDoc)value).longValue();
565             switch( expectedTypeChar )
566             {
567             case 'b': // both byte and boolean
568
case 'c':
569             case 'i':
570             case 's':
571                 // completely wrong.
572
return avoidReflectException ? getMatchingDummyValue(expectedType) : value;
573             case 'd':
574                 return new Double JavaDoc(l); // widening.
575
case 'f':
576                 return new Float JavaDoc(l); // widening.
577
case 'l':
578                 return value; // exact match.
579

580             default:
581                 throw new IllegalStateException JavaDoc("unknown type " + expectedTypeChar); //$NON-NLS-1$
582
}
583         }
584         
585         // widening float -> double
586
else if( value instanceof Float JavaDoc )
587         {
588             final float f = ((Float JavaDoc)value).floatValue();
589             switch( expectedTypeChar )
590             {
591             case 'b': // both byte and boolean
592
case 'c':
593             case 'i':
594             case 's':
595             case 'l':
596                 // completely wrong.
597
return avoidReflectException ? getMatchingDummyValue(expectedType) : value;
598             case 'd':
599                 return new Double JavaDoc(f); // widening.
600
case 'f':
601                 return value; // exact match.
602
default:
603                 throw new IllegalStateException JavaDoc("unknown type " + expectedTypeChar); //$NON-NLS-1$
604
}
605         }
606         else if( value instanceof Double JavaDoc ){
607             if(expectedTypeChar == 'd' )
608                 return value; // exact match
609
else{
610                 return avoidReflectException ? getMatchingDummyValue(expectedType) : value; // completely wrong.
611
}
612         }
613         else if( value instanceof Boolean JavaDoc ){
614             if( expectedTypeChar == 'b' && nameLen == 7) // "boolean".length() == 7
615
return value;
616             else
617                 return avoidReflectException ? getMatchingDummyValue(expectedType) : value; // completely wrong.
618
}
619         else // can't convert
620
return avoidReflectException ? getMatchingDummyValue(expectedType) : value;
621     }
622     
623     private static Class JavaDoc<?> getJavaLangClass_Primitive(final PrimitiveType primitiveType){
624         switch( primitiveType.getKind() ){
625         case BOOLEAN: return boolean.class;
626         case BYTE: return byte.class;
627         case CHAR: return char.class;
628         case DOUBLE: return double.class;
629         case FLOAT: return float.class;
630         case INT: return int.class;
631         case LONG: return long.class;
632         case SHORT: return short.class;
633         default:
634             throw new IllegalStateException JavaDoc("unknow primitive type " + primitiveType ); //$NON-NLS-1$
635
}
636     }
637     
638     /**
639      * Apply type conversion according to JLS 5.1.2 and 5.1.3 and / or auto-boxing.
640      * @param expectedType the expected type
641      * @param value the value where conversion may be applied to
642      * @param name name of the member value
643      * @param parent the of the annotation of the member value
644      * @param env
645      * @return the value matching the expected type or itself if no conversion can be applied.
646      */

647     private static Object JavaDoc performNecessaryTypeConversion(final TypeMirror expectedType,
648                                                          final Object JavaDoc value,
649                                                          final String JavaDoc name,
650                                                          final EclipseMirrorObject parent,
651                                                          final BaseProcessorEnv env)
652     {
653         if( expectedType == null )return value;
654         if( expectedType instanceof PrimitiveType )
655         {
656             final Class JavaDoc<?> primitiveClass = getJavaLangClass_Primitive( (PrimitiveType)expectedType );
657             return performNecessaryPrimitiveTypeConversion(primitiveClass, value, false);
658         }
659         // handle auto-boxing
660
else if( expectedType instanceof ArrayType)
661         {
662             final TypeMirror componentType = ((ArrayType)expectedType).getComponentType();
663             Object JavaDoc converted = value;
664             // if it is an error case, will just leave it as is.
665
if( !(componentType instanceof ArrayType ) )
666                 converted = performNecessaryTypeConversion(componentType, value, name, parent, env);
667             
668             final AnnotationValue annoValue = createAnnotationValueFromDOMValue(converted, name, 0, parent, env);
669             return Collections.singletonList(annoValue);
670         }
671         else // no change
672
return value;
673     }
674
675     public static InterfaceType createErrorInterfaceType(final ITypeBinding binding)
676     {
677         String JavaDoc name = null == binding ? NULL_BINDING_NAME : binding.getName();
678         return new ErrorType.ErrorInterface(name);
679     }
680
681     public static ClassType createErrorClassType(final ITypeBinding binding)
682     {
683         String JavaDoc name = null == binding ? NULL_BINDING_NAME : binding.getName();
684         return createErrorClassType(name);
685     }
686     
687     public static ClassType createErrorClassType(final String JavaDoc name)
688     {
689         return new ErrorType.ErrorClass(name);
690     }
691
692     public static AnnotationType createErrorAnnotationType(final ITypeBinding binding)
693     {
694         String JavaDoc name = null == binding ? NULL_BINDING_NAME : binding.getName();
695         return createErrorAnnotationType(name);
696     }
697     
698     public static AnnotationType createErrorAnnotationType(String JavaDoc name)
699     {
700         return new ErrorType.ErrorAnnotation(name);
701     }
702     
703     public static ArrayType createErrorArrayType(final String JavaDoc name, final int dimension)
704     {
705         return new ErrorType.ErrorArrayType(name, dimension);
706     }
707 }
708
Popular Tags