001    /*
002     * Copyright 2002-2004 The Apache Software Foundation
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *     http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.apache.commons.clazz.reflect.common;
017    
018    import java.lang.reflect.Method;
019    import java.util.List;
020    
021    import org.apache.commons.clazz.Clazz;
022    import org.apache.commons.clazz.reflect.ReflectedClazz;
023    
024    /**
025     * Holds parse results for individual accessor methods for a 
026     * list property.
027     * 
028     * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
029     * @version $Id: ReflectedListPropertyParseResults.java 155436 2005-02-26 13:17:48Z dirkv $
030     */
031    public class ReflectedListPropertyParseResults 
032                extends ReflectedPropertyParseResults
033    {
034        private AccessorMethodParseResults getMethodParseResults;
035        private AccessorMethodParseResults setMethodParseResults;
036        private AccessorMethodParseResults addMethodParseResults;
037        private AccessorMethodParseResults addIndexedMethodParseResults;
038        private AccessorMethodParseResults removeMethodParseResults;
039        private AccessorMethodParseResults removeIndexedMethodParseResults;
040        
041        private AccessorMethodParseResults sizeMethodParseResults;
042        
043    
044        /**
045         * Constructor for ReflectedMappedPropertyParseResults.
046         */
047        public ReflectedListPropertyParseResults(
048                ReflectedClazz clazz, String propertyName) 
049        {
050            super(clazz, propertyName);
051        }
052        
053        protected String getPropertyCategory() {
054            return "list";
055        }
056        
057        /**
058         * Returns <code>true</code> if the property is an array or 
059         * implements java.util.List.
060         */
061        public boolean isList() {
062            if (readMethodParseResults != null
063                && isList(readMethodParseResults.getType())) {
064                return true;
065            }
066            if (writeMethodParseResults != null
067                && isList(writeMethodParseResults.getType())) {
068                return true;
069            }
070            return false;
071        }
072            
073        /**
074         * Returns <code>true</code> if javaClass is an array or 
075         * implements java.util.List.
076         */
077        protected boolean isList(Class javaClass) {
078            return javaClass != null
079                && (List.class.isAssignableFrom(javaClass) || javaClass.isArray());
080        }
081        
082        /**
083         * Returns the type of the list/array element, if known. 
084         * Returns <code>null</code> otherwise.
085         */
086        public Class getContentType() {
087            if (getMethodParseResults != null) {
088                return getMethodParseResults.getType();
089            }
090            if (setMethodParseResults != null) {
091                return setMethodParseResults.getType();
092            }
093            if (addMethodParseResults != null) {
094                return addMethodParseResults.getType();
095            }
096            if (addIndexedMethodParseResults != null) {
097                return addIndexedMethodParseResults.getType();
098            }
099            if (removeMethodParseResults != null) {
100                return removeMethodParseResults.getType();
101            }
102            if (readMethodParseResults != null) {
103                Class type = readMethodParseResults.getType();
104                if (type.isArray()) {
105                    return type.getComponentType();
106                }
107            }
108            if (writeMethodParseResults != null) {
109                Class type = writeMethodParseResults.getType();
110                if (type.isArray()) {
111                    return type.getComponentType();
112                }
113            }
114            return null;
115        }
116    
117        public void setGetMethodParseResults(
118                    AccessorMethodParseResults getMethodParseResults) 
119        {
120            checkForExtraneousAccessor(
121                this.getMethodParseResults,
122                getMethodParseResults);
123            this.getMethodParseResults = getMethodParseResults;
124        }
125    
126        public Method getGetMethod() {
127            if (getMethodParseResults == null) {
128                return null;
129            }
130            return getMethodParseResults.getMethod();
131        }
132        
133        public void setSetMethodParseResults(
134                    AccessorMethodParseResults setMethodParseResults) 
135        {
136            checkForExtraneousAccessor(
137                this.setMethodParseResults,
138                setMethodParseResults);
139            this.setMethodParseResults = setMethodParseResults;
140        }
141    
142        public Method getSetMethod() {
143            if (setMethodParseResults == null) {
144                return null;
145            }
146            return setMethodParseResults.getMethod();
147        }
148        
149        public void setAddMethodParseResults(
150                    AccessorMethodParseResults addMethodParseResults) 
151        {
152            checkForExtraneousAccessor(
153                this.addMethodParseResults,
154                addMethodParseResults);
155            this.addMethodParseResults = addMethodParseResults;
156        }
157    
158        public Method getAddMethod() {
159            if (addMethodParseResults == null) {
160                return null;
161            }
162            return addMethodParseResults.getMethod();
163        }
164        
165        public void setAddIndexedMethodParseResults(
166                    AccessorMethodParseResults addIndexedMethodParseResults) 
167        {
168            checkForExtraneousAccessor(
169                this.addIndexedMethodParseResults,
170                addIndexedMethodParseResults);
171            this.addIndexedMethodParseResults = addIndexedMethodParseResults;
172        }
173        
174        public Method getAddIndexedMethod() {
175            if (addIndexedMethodParseResults == null) {
176                return null;
177            }
178            return addIndexedMethodParseResults.getMethod();
179        }
180            
181        public void setRemoveMethodParseResults(
182                    AccessorMethodParseResults removeMethodParseResults) 
183        {
184            checkForExtraneousAccessor(
185                this.removeMethodParseResults,
186                removeMethodParseResults);
187            this.removeMethodParseResults = removeMethodParseResults;
188        }
189        
190        public Method getRemoveMethod() {
191            if (removeMethodParseResults == null) {
192                return null;
193            }
194            return removeMethodParseResults.getMethod();
195        }
196        
197        public void setRemoveIndexedMethodParseResults(
198                    AccessorMethodParseResults removeIndexedMethodParseResults)
199        {
200            checkForExtraneousAccessor(
201                this.removeIndexedMethodParseResults,
202                removeIndexedMethodParseResults);
203            this.removeIndexedMethodParseResults = removeIndexedMethodParseResults;
204        }
205    
206        public Method getRemoveIndexedMethod() {
207            if (removeIndexedMethodParseResults == null) {
208                return null;
209            }
210            return removeIndexedMethodParseResults.getMethod();
211        }
212    
213    
214        public void setSizeMethodParseResults(
215                    AccessorMethodParseResults sizeMethodParseResults) 
216        {
217            checkForExtraneousAccessor(
218                this.sizeMethodParseResults,
219                sizeMethodParseResults);
220            this.sizeMethodParseResults = sizeMethodParseResults;
221        }
222        
223        public Method getSizeMethod() {
224            if (sizeMethodParseResults == null) {
225                return null;
226            }
227            return sizeMethodParseResults.getMethod();
228        }
229        
230        /**
231         * Combines parse results from another instance of 
232         * <code>ReflectedMappedPropertyParseResults</code> with
233         * results contained by this object.
234         * <p>
235         * Node that the property name is not copied from the 
236         * <code>other</code> object.
237         */        
238        public void merge(ReflectedListPropertyParseResults other) {
239            super.merge(other);
240            if (other.readMethodParseResults != null) {
241                setReadMethodParseResults(other.readMethodParseResults);
242            }
243            if (other.writeMethodParseResults != null) {
244                setWriteMethodParseResults(other.writeMethodParseResults);
245            }
246            if (other.getMethodParseResults != null) {
247                setGetMethodParseResults(other.getMethodParseResults);
248            }
249            if (other.setMethodParseResults != null) {
250                setSetMethodParseResults(other.setMethodParseResults);
251            }
252            if (other.addMethodParseResults != null) {
253                setAddMethodParseResults(other.addMethodParseResults);
254            }
255            if (other.addIndexedMethodParseResults != null) {
256                setAddIndexedMethodParseResults(other.addIndexedMethodParseResults);
257            }
258            if (other.removeMethodParseResults != null) {
259                setRemoveMethodParseResults(other.removeMethodParseResults);
260            }
261            if (other.sizeMethodParseResults != null) {
262                setSizeMethodParseResults(other.sizeMethodParseResults);
263            }
264        }
265        
266        protected void appendDescription(StringBuffer buffer) {
267            super.appendDescription(buffer);
268            Class contentType = getContentType();
269            if (contentType != null) {
270                buffer.append("\n  [content type]   ");
271                buffer.append(Clazz.getCanonicalClassName(contentType));
272            }
273        }
274        
275        protected void appendMethodDescriptions(StringBuffer buffer) {
276            super.appendMethodDescriptions(buffer);
277            if (getMethodParseResults != null) {
278                buffer.append("\n    [get~(int)]    ");
279                buffer.append(getMethodParseResults.getMethod());
280            }
281            if (setMethodParseResults != null) {
282                buffer.append("\n    [set~(int,v)]  ");
283                buffer.append(setMethodParseResults.getMethod());
284            }
285            if (addMethodParseResults != null) {
286                buffer.append("\n    [add~(v)]      ");
287                buffer.append(addMethodParseResults.getMethod());
288            }
289            if (addIndexedMethodParseResults != null) {
290                buffer.append("\n    [add~(int,v)]  ");
291                buffer.append(addIndexedMethodParseResults.getMethod());
292            }
293            if (removeMethodParseResults != null) {
294                buffer.append("\n    [remove~(v)]   ");
295                buffer.append(removeMethodParseResults.getMethod());
296            }
297            if (removeIndexedMethodParseResults != null) {
298                buffer.append("\n    [remove~(i)]   ");
299                buffer.append(removeIndexedMethodParseResults.getMethod());
300            }
301            if (sizeMethodParseResults != null) {
302                buffer.append("\n    [get~Count()]  ");
303                buffer.append(sizeMethodParseResults.getMethod());
304            }
305        }
306        
307        public boolean checkConsistency() {        
308            if (!super.checkConsistency()) {
309                return false;
310            }
311                    
312            if (readMethodParseResults == null && getMethodParseResults == null) {
313                return false;
314            }
315    
316            if (readMethodParseResults != null) {
317                Class type = readMethodParseResults.getType();
318                if (writeMethodParseResults != null) {
319                    if (!type.equals(writeMethodParseResults.getType())) {
320                        return false;
321                    }
322                }
323            }
324                    
325            Class contentType = null;
326             
327            if (getMethodParseResults != null) {
328                contentType = getMethodParseResults.getType();
329            }
330            
331            if (setMethodParseResults != null) {
332                if (contentType == null) {
333                    contentType = setMethodParseResults.getType();
334                }
335                else {
336                    if (!contentType.equals(setMethodParseResults.getType())) {
337                        return false;
338                    }
339                }
340            }
341            
342            if (addMethodParseResults != null) {
343                if (contentType == null) {
344                    contentType = addMethodParseResults.getType();
345                }
346                else {
347                    if (!contentType.equals(addMethodParseResults.getType())) {
348                        return false;
349                    }
350                }
351            }
352            
353            if (addIndexedMethodParseResults != null) {
354                if (contentType == null) {
355                    contentType = addIndexedMethodParseResults.getType();
356                }
357                else {
358                    if (!contentType.equals(
359                            addIndexedMethodParseResults.getType())) {
360                        return false;
361                    }
362                }
363            }
364            
365            if (removeMethodParseResults != null) {
366                if (contentType != null) {
367                    if (!contentType.equals(removeMethodParseResults.getType())) {
368                        return false;
369                    }
370                }
371            }
372            
373            return true;
374        }
375            
376        protected boolean appendInconsistencyDescriptions(StringBuffer buffer) {
377            if (!super.appendInconsistencyDescriptions(buffer)) {
378                return false;
379            }        
380            
381            if (readMethodParseResults == null && getMethodParseResults == null) {
382                buffer.append(
383                    "\n     - Does not have either get() or get(int) method");
384                return true;
385            }
386    
387            if (readMethodParseResults != null) {
388                Class type = readMethodParseResults.getType();
389                if (writeMethodParseResults != null) {
390                    if (!type.equals(writeMethodParseResults.getType())) {
391                        buffer.append(
392                            "\n     - Get() and set(v) types do not match");
393                    }
394                }
395            }
396            
397            Class contentType = null;
398             
399            if (getMethodParseResults != null) {
400                contentType = getMethodParseResults.getType();
401            }
402            
403            if (setMethodParseResults != null) {
404                if (contentType == null) {
405                    contentType = setMethodParseResults.getType();
406                }
407                else {
408                    if (!contentType.equals(setMethodParseResults.getType())) {
409                        buffer.append(
410                            "\n     - Content type mismatch between "
411                                + "get(int) and set(int,v)");
412                    }
413                }
414            }
415            
416            if (addMethodParseResults != null) {
417                if (contentType == null) {
418                    contentType = addMethodParseResults.getType();
419                }
420                else {
421                    if (!contentType.equals(addMethodParseResults.getType())) {
422                        buffer.append(
423                            "\n     - Content type mismatch between "
424                                + "get(int) and add(v)");
425                    }
426                }
427            }
428            
429            if (addIndexedMethodParseResults != null) {
430                if (contentType == null) {
431                    contentType = addIndexedMethodParseResults.getType();
432                }
433                else {
434                    if (!contentType.equals(
435                            addIndexedMethodParseResults.getType())) {
436                        buffer.append(
437                            "\n     - Content type mismatch between "
438                                + "get(int) and add(int,v)");
439                    }
440                }
441            }
442            
443            if (removeMethodParseResults != null) {
444                if (contentType != null) {
445                    Class removeType = removeMethodParseResults.getType(); 
446                    if (removeType != null && !contentType.equals(removeType)) {
447                        buffer.append(
448                            "\n     - Content type mismatch between "
449                                + "get(int) and remove(v)");
450                    }
451                }
452            }        
453            return true;
454        }  
455    }