KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > compiler > grammar > UniqueValueType


1 /*
2  * Copyright 2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * $Header:$
17  */

18 package org.apache.beehive.netui.compiler.grammar;
19
20 import org.apache.beehive.netui.compiler.AnnotationGrammar;
21 import org.apache.beehive.netui.compiler.AnnotationMemberType;
22 import org.apache.beehive.netui.compiler.CompilerUtils;
23 import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationInstance;
24 import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationTypeElementDeclaration;
25 import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationValue;
26 import org.apache.beehive.netui.compiler.typesystem.declaration.MemberDeclaration;
27 import org.apache.beehive.netui.compiler.typesystem.env.AnnotationProcessorEnvironment;
28
29 import java.util.List JavaDoc;
30 import java.util.HashSet JavaDoc;
31 import java.util.HashMap JavaDoc;
32
33
34 public class UniqueValueType
35         extends AnnotationMemberType
36 {
37     private boolean _allowEmptyString;
38     private boolean _checkDefaultValues;
39     
40     /** the name of the attribute on the parent annotation that is the list of annotations to check for duplicates */
41     private String JavaDoc _memberGroupName;
42     
43
44     public UniqueValueType( String JavaDoc memberGroupName, boolean allowEmptyString, boolean checkDefaultValues,
45                             String JavaDoc requiredRuntimeVersion, AnnotationGrammar parentGrammar )
46     {
47         this( memberGroupName, allowEmptyString, checkDefaultValues, requiredRuntimeVersion, parentGrammar, null );
48     }
49     
50     public UniqueValueType( String JavaDoc memberGroupName, boolean allowEmptyString, boolean checkDefaultValues,
51                             String JavaDoc requiredRuntimeVersion, AnnotationGrammar parentGrammar,
52                             AnnotationMemberType nextInChain )
53     {
54         super( requiredRuntimeVersion, parentGrammar, nextInChain );
55
56         _allowEmptyString = allowEmptyString;
57         _memberGroupName = memberGroupName;
58         _checkDefaultValues = checkDefaultValues;
59     }
60
61     /**
62      * @return a result (any Object) that will be passed back to the parent checker. May be null</code>.
63      */

64     
65     public Object JavaDoc onCheck( AnnotationTypeElementDeclaration valueDecl, AnnotationValue value,
66                            AnnotationInstance[] parentAnnotations, MemberDeclaration classMember,
67                            int annotationArrayIndex )
68     {
69         String JavaDoc val = value.getValue().toString();
70         
71         if ( ! _allowEmptyString && val.length() == 0 )
72         {
73             addError( value, "error.empty-string-not-allowed" );
74             return null;
75         }
76         
77         if ( parentAnnotations.length < 2 ) return null; // invalid parents -- will be caught elsewhere
78
AnnotationInstance parentElement = parentAnnotations[ parentAnnotations.length - 2 ];
79         List JavaDoc memberGroup = CompilerUtils.getAnnotationArray( parentElement, _memberGroupName, true );
80         
81         //
82
// If memberGroup is null, then this annotation was in the wrong place, and there will be other errors.
83
//
84
if ( memberGroup != null )
85         {
86             String JavaDoc valueName = valueDecl.getSimpleName();
87             AnnotationInstance parentAnnotation = parentAnnotations[ parentAnnotations.length - 1 ];
88             checkForDuplicates( value, valueName, parentAnnotation, classMember, memberGroup, false,
89                                 annotationArrayIndex );
90             
91             //
92
// Get a list of additional annotations (presumably not from the this one's parent) to check.
93
//
94
List JavaDoc additionalAnnsToCheck = getAdditionalAnnotationsToCheck( classMember );
95             
96             if ( additionalAnnsToCheck != null )
97             {
98                 // Check this value against the list of additional annotations.
99
checkForDuplicates( value, valueName, parentAnnotation, classMember, additionalAnnsToCheck, true, -1 );
100                 
101                 // Check for duplicates *within* within the list of additional annotations.
102
for ( int i = 0; i < additionalAnnsToCheck.size(); ++i )
103                 {
104                     AnnotationInstance ann = ( AnnotationInstance ) additionalAnnsToCheck.get( i );
105                     AnnotationValue valueToCheck = CompilerUtils.getAnnotationValue( ann, valueName, true );
106                     checkForDuplicates( valueToCheck, valueName, ann, classMember, additionalAnnsToCheck, true, -1 );
107                 }
108             }
109         }
110         
111         return null;
112     }
113     
114     /**
115      * Plugin point for derived class -- if there should be no duplicates across another entity too.
116      * @return a List of AnnotationInstance
117      */

118     protected List JavaDoc getAdditionalAnnotationsToCheck( MemberDeclaration classMember )
119     {
120         return null;
121     }
122     
123     protected String JavaDoc getErrorMessageExtraInfo()
124     {
125         return null;
126     }
127     
128     protected void checkForDuplicates( AnnotationValue member, String JavaDoc memberName, AnnotationInstance parentAnnotation,
129                                        MemberDeclaration classMember, List JavaDoc annotationsToCheck,
130                                        boolean includeEntityInMsg, int annotationArrayIndex )
131     {
132         Object JavaDoc memberValue = member.getValue();
133         
134         for ( int i = 0; i < annotationsToCheck.size(); ++i )
135         {
136             AnnotationInstance annotation = ( AnnotationInstance ) annotationsToCheck.get( i );
137             
138             if ( ( annotationArrayIndex != -1 && annotationArrayIndex != i ) ||
139                  ! CompilerUtils.annotationsAreEqual( annotation, parentAnnotation, allowExactDuplicates(), getEnv() ) )
140             {
141                 AnnotationValue valueToCheck =
142                         CompilerUtils.getAnnotationValue( annotation, memberName, _checkDefaultValues );
143                 
144                 if ( valueToCheck != null && ! valueToCheck.equals( member )
145                      && valueToCheck.getValue().equals( memberValue ) )
146                 {
147                     if ( alreadyAddedErrorForValue( classMember, parentAnnotation, memberValue, getEnv() ) ) return;
148                     
149                     String JavaDoc annotationName =
150                             CompilerUtils.getDeclaration( parentAnnotation.getAnnotationType() ).getSimpleName();
151                     
152                     if ( includeEntityInMsg )
153                     {
154                         String JavaDoc extra = getErrorMessageExtraInfo();
155                         Object JavaDoc[] args = new Object JavaDoc[]
156                             {
157                                 annotationName,
158                                 memberName,
159                                 memberValue,
160                                 classMember.getSimpleName(),
161                                 extra
162                             };
163                         addError( member, "error.duplicate-attr2", args );
164                     }
165                     else
166                     {
167                         addError( member, "error.duplicate-attr",
168                                   new Object JavaDoc[]{ annotationName, memberName, memberValue } );
169                     }
170                     
171                     return;
172                 }
173             }
174         }
175     }
176     
177     static boolean alreadyAddedErrorForValue( MemberDeclaration classMember, AnnotationInstance parentAnn,
178                                               Object JavaDoc memberValue, AnnotationProcessorEnvironment env )
179     {
180         // Map of String class-member-name ->
181
// [ Map of String annotation name -> Set of values for which errors were added ]
182
HashMap JavaDoc errorsAddedRootMap = ( HashMap JavaDoc ) env.getAttribute( "uniqueValueErrors" );
183         if ( errorsAddedRootMap == null )
184         {
185             errorsAddedRootMap = new HashMap JavaDoc();
186             env.setAttribute( "uniqueValueErrors", errorsAddedRootMap );
187         }
188         
189         String JavaDoc classMemberName = classMember.getSimpleName();
190         HashMap JavaDoc errorsAddedByAnnotation = ( HashMap JavaDoc ) errorsAddedRootMap.get( classMemberName );
191         if ( errorsAddedByAnnotation == null )
192         {
193             errorsAddedByAnnotation = new HashMap JavaDoc();
194             errorsAddedRootMap.put( classMemberName, errorsAddedByAnnotation );
195         }
196         
197         String JavaDoc parentAnnName = parentAnn.getAnnotationType().getAnnotationTypeDeclaration().getQualifiedName();
198         HashSet JavaDoc errorsAdded = ( HashSet JavaDoc ) errorsAddedByAnnotation.get( parentAnnName );
199         if ( errorsAdded == null )
200         {
201             errorsAdded = new HashSet JavaDoc();
202             errorsAddedByAnnotation.put( parentAnnName, errorsAdded );
203         }
204         
205         if ( errorsAdded.contains( memberValue ) ) return true;
206         
207         errorsAdded.add( memberValue );
208         return false;
209     }
210     
211     protected boolean allowExactDuplicates()
212     {
213         return false;
214     }
215 }
216
Popular Tags