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.extended;
017    
018    import java.lang.reflect.Method;
019    import java.util.Map;
020    
021    import org.apache.commons.clazz.Clazz;
022    import org.apache.commons.clazz.reflect.ReflectedClazz;
023    import org.apache.commons.clazz.reflect.common.AccessorMethodParseResults;
024    import org.apache.commons.clazz.reflect.common.ReflectedPropertyParseResults;
025    
026    /**
027     * Holds parse results for individual accessor methods for a 
028     * mapped property.
029     * 
030     * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
031     * @version $Id: ReflectedMappedPropertyParseResults.java 155436 2005-02-26 13:17:48Z dirkv $
032     */
033    public class ReflectedMappedPropertyParseResults 
034                extends ReflectedPropertyParseResults
035    {
036        private AccessorMethodParseResults getMethodParseResults;
037        private AccessorMethodParseResults putMethodParseResults;
038        private AccessorMethodParseResults removeMethodParseResults;
039        private AccessorMethodParseResults keySetMethodParseResults;
040    
041        /**
042         * Constructor for ReflectedMappedPropertyParseResults.
043         */
044        public ReflectedMappedPropertyParseResults(
045                ReflectedClazz clazz, String propertyName) 
046        {
047            super(clazz, propertyName);
048        }
049        
050        protected String getPropertyCategory() {
051            return "mapped";
052        }
053    
054        /**
055         * Returns <code>true</code> if the property is 
056         * java.util.Map or implements java.util.Map.
057         */
058        protected boolean isMap() {
059            if (readMethodParseResults != null
060                && isMap(readMethodParseResults.getType())) {
061                return true;
062            }
063            if (writeMethodParseResults != null
064                && isMap(writeMethodParseResults.getType())) {
065                return true;
066            }
067            return false;
068        }
069            
070        private boolean isMap(Class javaClass) {
071            return javaClass != null && Map.class.isAssignableFrom(javaClass);
072        }
073        
074        public Class getKeyType() {
075            if (getMethodParseResults != null) {
076                return getMethodParseResults.getParameterType();
077            }
078            if (putMethodParseResults != null) {
079                return putMethodParseResults.getParameterType();
080            }
081            if (removeMethodParseResults != null) {
082                return removeMethodParseResults.getParameterType();
083            }
084            return null;        
085        }
086    
087        public Class getContentType() {
088            if (getMethodParseResults != null) {
089                return getMethodParseResults.getType();
090            }
091            if (putMethodParseResults != null) {
092                return putMethodParseResults.getType();
093            }
094            if (removeMethodParseResults != null) {
095                return removeMethodParseResults.getType();
096            }
097            return null;
098            
099        }
100    
101        public void setGetMethodParseResults(
102                    AccessorMethodParseResults getMethodParseResults) 
103        {
104            checkForExtraneousAccessor(
105                this.getMethodParseResults,
106                getMethodParseResults);
107            this.getMethodParseResults = getMethodParseResults;
108        }
109    
110        public Method getGetMethod() {
111            if (getMethodParseResults == null) {
112                return null;
113            }
114            return getMethodParseResults.getMethod();
115        }
116        
117    
118        public void setPutMethodParseResults(
119                    AccessorMethodParseResults putMethodParseResults) 
120        {
121            checkForExtraneousAccessor(
122                this.putMethodParseResults,
123                putMethodParseResults);
124            this.putMethodParseResults = putMethodParseResults;
125        }
126        
127        public Method getPutMethod() {
128            if (putMethodParseResults == null) {
129                return null;
130            }
131            return putMethodParseResults.getMethod();
132        }
133            
134        public void setRemoveMethodParseResults(
135                    AccessorMethodParseResults removeMethodParseResults) 
136        {
137            checkForExtraneousAccessor(
138                this.removeMethodParseResults,
139                removeMethodParseResults);
140            this.removeMethodParseResults = removeMethodParseResults;
141        }
142        
143        public Method getRemoveMethod() {
144            if (removeMethodParseResults == null) {
145                return null;
146            }
147            return removeMethodParseResults.getMethod();
148        }
149        
150        public void setKeySetMethodParseResults(
151                    AccessorMethodParseResults keySetMethodParseResults) 
152        {
153            checkForExtraneousAccessor(
154                this.keySetMethodParseResults,
155                keySetMethodParseResults);
156            this.keySetMethodParseResults = keySetMethodParseResults;
157        }
158        
159        public Method getKeySetMethod() {
160            if (keySetMethodParseResults == null) {
161                return null;
162            }
163            return keySetMethodParseResults.getMethod();
164        }
165        
166        /**
167         * Combines parse results from another instance of 
168         * <code>ReflectedMappedPropertyParseResults</code> with
169         * results contained by this object.
170         * <p>
171         * Node that the property name is not copied from the 
172         * <code>other</code> object.
173         */        
174        public void merge(ReflectedMappedPropertyParseResults other) {
175            super.merge(other);
176            if (other.readMethodParseResults != null) {
177                setReadMethodParseResults(other.readMethodParseResults);
178            }
179            if (other.writeMethodParseResults != null) {
180                setWriteMethodParseResults(other.writeMethodParseResults);
181            }
182            if (other.getMethodParseResults != null) {
183                setGetMethodParseResults(other.getMethodParseResults);
184            }
185            if (other.putMethodParseResults != null) {
186                setPutMethodParseResults(other.putMethodParseResults);
187            }
188            if (other.removeMethodParseResults != null) {
189                setRemoveMethodParseResults(other.removeMethodParseResults);
190            }
191            if (other.keySetMethodParseResults != null) {
192                setKeySetMethodParseResults(other.keySetMethodParseResults);
193            }
194        }
195        
196        protected void appendDescription(StringBuffer buffer) {
197            super.appendDescription(buffer);
198            Class keyType = getKeyType();
199            if (keyType != null) {
200                buffer.append("\n  [key type]       ");
201                buffer.append(Clazz.getCanonicalClassName(keyType));
202            }
203            
204            Class contentType = getContentType();
205            if (contentType != null) {
206                buffer.append("\n  [content type]   ");
207                buffer.append(Clazz.getCanonicalClassName(contentType));
208            }
209        }
210        
211        protected void appendMethodDescriptions(StringBuffer buffer) {
212            super.appendMethodDescriptions(buffer);
213            if (getMethodParseResults != null) {
214                buffer.append("\n    [get~(key)]    ");
215                buffer.append(getMethodParseResults.getMethod());
216            }
217            if (putMethodParseResults != null) {
218                buffer.append("\n    [set~(key,v)]  ");
219                buffer.append(putMethodParseResults.getMethod());
220            }
221            if (removeMethodParseResults != null) {
222                buffer.append("\n    [remove~(key)] ");
223                buffer.append(removeMethodParseResults.getMethod());
224            }
225            if (keySetMethodParseResults != null) {
226                buffer.append("\n    [get~KeySet()] ");
227                buffer.append(keySetMethodParseResults.getMethod());
228            }
229        }
230        
231        public boolean checkConsistency() {        
232            if (!super.checkConsistency()) {
233                return false;
234            }
235                    
236            if (readMethodParseResults == null && getMethodParseResults == null) {
237                return false;
238            }
239    
240            if (readMethodParseResults != null) {
241                Class type = readMethodParseResults.getType();
242                if (writeMethodParseResults != null) {
243                    if (!type.equals(writeMethodParseResults.getType())) {
244                        return false;
245                    }
246                }
247            }
248                    
249            Class keyType = null;
250            Class contentType = null;
251             
252            if (getMethodParseResults != null) {
253                keyType = getMethodParseResults.getParameterType();
254                contentType = getMethodParseResults.getType();
255            }
256            
257            if (putMethodParseResults != null) {
258                if (keyType == null) {
259                    keyType = putMethodParseResults.getParameterType();
260                }
261                else {
262                    if (!keyType.equals(putMethodParseResults.getParameterType())) {
263                        return false;
264                    }
265                }
266                
267                if (contentType == null) {
268                    contentType = putMethodParseResults.getType();
269                }
270                else {
271                    if (!contentType.equals(
272                            putMethodParseResults.getType())) {
273                        return false;
274                    }
275                }
276            }
277            
278            if (removeMethodParseResults != null) {
279                if (keyType != null
280                    && !keyType.
281                            equals(removeMethodParseResults.getParameterType())) {
282                    return false;
283                }
284                            
285                if (contentType != null) {
286                    Class removeType = removeMethodParseResults.getType(); 
287                    if (removeType != null && !contentType.equals(removeType)) {
288                        return false;
289                    }
290                }
291            }
292            
293            return true;
294        }
295            
296        protected boolean appendInconsistencyDescriptions(StringBuffer buffer) {
297            if (!super.appendInconsistencyDescriptions(buffer)) {
298                return false;
299            }        
300            
301            if (readMethodParseResults == null && getMethodParseResults == null) {
302                buffer.append(
303                    "\n     - Does not have either get() or get(key) method");
304                return true;
305            }
306    
307            if (readMethodParseResults != null) {
308                Class type = readMethodParseResults.getType();
309                if (writeMethodParseResults != null) {
310                    if (!type.equals(writeMethodParseResults.getType())) {
311                        buffer.append(
312                            "\n     - Get() and set(v) types do not match");
313                    }
314                }
315            }
316            
317            Class keyType = null;
318            Class contentType = null;
319             
320            if (getMethodParseResults != null) {
321                keyType = getMethodParseResults.getParameterType();
322                contentType = getMethodParseResults.getType();
323            }
324            
325            if (putMethodParseResults != null) {
326                if (keyType == null) {
327                    keyType = putMethodParseResults.getParameterType();
328                }
329                else {
330                    if (!keyType.equals(putMethodParseResults.getParameterType())) {
331                        buffer.append(
332                            "\n     - Key type mismatch between "
333                                + "get(key) and set(key,v)");
334                    }
335                }
336                
337                if (contentType == null) {
338                    contentType = putMethodParseResults.getType();
339                }
340                else {
341                    if (!contentType.equals(
342                            putMethodParseResults.getType())) {
343                        buffer.append(
344                            "\n     - Content type mismatch between "
345                                + "get(key) and set(key,v)");
346                    }
347                }
348            }
349            
350            if (removeMethodParseResults != null) {
351                if (keyType != null
352                    && !keyType.
353                            equals(removeMethodParseResults.getParameterType())) {
354                    buffer.append(
355                        "\n     - Key type mismatch between "
356                            + "get(key) and remove(key)");
357                }
358                            
359                if (contentType != null) {
360                    Class removeType = removeMethodParseResults.getType(); 
361                    if (removeType != null && !contentType.equals(removeType)) {
362                        buffer.append(
363                            "\n     - Content type mismatch between "
364                                + "get(key) and set(key,v)");
365                    }
366                }
367            }        
368            return true;
369        }  
370    }