Source Code Cross Referenced for PropertyEditorRegistrySupport.java in  » J2EE » spring-framework-2.5 » org » springframework » beans » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.5 » org.springframework.beans 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2002-2007 the original author or authors.
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:
017:        package org.springframework.beans;
018:
019:        import java.beans.PropertyEditor;
020:        import java.io.File;
021:        import java.io.InputStream;
022:        import java.math.BigDecimal;
023:        import java.math.BigInteger;
024:        import java.net.URI;
025:        import java.net.URL;
026:        import java.util.Collection;
027:        import java.util.HashMap;
028:        import java.util.HashSet;
029:        import java.util.Iterator;
030:        import java.util.LinkedHashMap;
031:        import java.util.LinkedList;
032:        import java.util.List;
033:        import java.util.Locale;
034:        import java.util.Map;
035:        import java.util.Properties;
036:        import java.util.Set;
037:        import java.util.SortedMap;
038:        import java.util.SortedSet;
039:        import java.util.regex.Pattern;
040:
041:        import org.springframework.beans.propertyeditors.ByteArrayPropertyEditor;
042:        import org.springframework.beans.propertyeditors.CharArrayPropertyEditor;
043:        import org.springframework.beans.propertyeditors.CharacterEditor;
044:        import org.springframework.beans.propertyeditors.ClassArrayEditor;
045:        import org.springframework.beans.propertyeditors.ClassEditor;
046:        import org.springframework.beans.propertyeditors.CustomBooleanEditor;
047:        import org.springframework.beans.propertyeditors.CustomCollectionEditor;
048:        import org.springframework.beans.propertyeditors.CustomMapEditor;
049:        import org.springframework.beans.propertyeditors.CustomNumberEditor;
050:        import org.springframework.beans.propertyeditors.FileEditor;
051:        import org.springframework.beans.propertyeditors.InputStreamEditor;
052:        import org.springframework.beans.propertyeditors.LocaleEditor;
053:        import org.springframework.beans.propertyeditors.PatternEditor;
054:        import org.springframework.beans.propertyeditors.PropertiesEditor;
055:        import org.springframework.beans.propertyeditors.StringArrayPropertyEditor;
056:        import org.springframework.beans.propertyeditors.URIEditor;
057:        import org.springframework.beans.propertyeditors.URLEditor;
058:        import org.springframework.core.io.Resource;
059:        import org.springframework.core.io.support.ResourceArrayPropertyEditor;
060:        import org.springframework.util.ClassUtils;
061:
062:        /**
063:         * Base implementation of the {@link PropertyEditorRegistry} interface.
064:         * Provides management of default editors and custom editors.
065:         * Mainly serves as base class for {@link BeanWrapperImpl}.
066:         *
067:         * @author Juergen Hoeller
068:         * @author Rob Harrop
069:         * @since 1.2.6
070:         * @see java.beans.PropertyEditorManager
071:         * @see java.beans.PropertyEditorSupport#setAsText
072:         * @see java.beans.PropertyEditorSupport#setValue
073:         */
074:        public class PropertyEditorRegistrySupport implements 
075:                PropertyEditorRegistry {
076:
077:            private boolean defaultEditorsActive = false;
078:
079:            private boolean configValueEditorsActive = false;
080:
081:            private boolean propertySpecificEditorsRegistered = false;
082:
083:            private Map defaultEditors;
084:
085:            private Map customEditors;
086:
087:            private Set sharedEditors;
088:
089:            private Map customEditorCache;
090:
091:            //---------------------------------------------------------------------
092:            // Management of default editors
093:            //---------------------------------------------------------------------
094:
095:            /**
096:             * Activate the default editors for this registry instance,
097:             * allowing for lazily registering default editors when needed.
098:             */
099:            protected void registerDefaultEditors() {
100:                this .defaultEditorsActive = true;
101:            }
102:
103:            /**
104:             * Activate config value editors which are only intended for configuration purposes,
105:             * such as {@link org.springframework.beans.propertyeditors.StringArrayPropertyEditor}.
106:             * <p>Those editors are not registered by default simply because they are in
107:             * general inappropriate for data binding purposes. Of course, you may register
108:             * them individually in any case, through {@link #registerCustomEditor}.
109:             */
110:            public void useConfigValueEditors() {
111:                this .configValueEditorsActive = true;
112:            }
113:
114:            /**
115:             * Retrieve the default editor for the given property type, if any.
116:             * <p>Lazily registers the default editors, if they are active.
117:             * @param requiredType type of the property
118:             * @return the default editor, or <code>null</code> if none found
119:             * @see #registerDefaultEditors
120:             */
121:            public PropertyEditor getDefaultEditor(Class requiredType) {
122:                if (!this .defaultEditorsActive) {
123:                    return null;
124:                }
125:                if (this .defaultEditors == null) {
126:                    doRegisterDefaultEditors();
127:                }
128:                return (PropertyEditor) this .defaultEditors.get(requiredType);
129:            }
130:
131:            /**
132:             * Actually register the default editors for this registry instance.
133:             * @see org.springframework.beans.propertyeditors.ByteArrayPropertyEditor
134:             * @see org.springframework.beans.propertyeditors.ClassEditor
135:             * @see org.springframework.beans.propertyeditors.CharacterEditor
136:             * @see org.springframework.beans.propertyeditors.CustomBooleanEditor
137:             * @see org.springframework.beans.propertyeditors.CustomNumberEditor
138:             * @see org.springframework.beans.propertyeditors.CustomCollectionEditor
139:             * @see org.springframework.beans.propertyeditors.CustomMapEditor
140:             * @see org.springframework.beans.propertyeditors.FileEditor
141:             * @see org.springframework.beans.propertyeditors.InputStreamEditor
142:             * @see org.springframework.jndi.JndiTemplateEditor
143:             * @see org.springframework.beans.propertyeditors.LocaleEditor
144:             * @see org.springframework.beans.propertyeditors.PropertiesEditor
145:             * @see org.springframework.beans.PropertyValuesEditor
146:             * @see org.springframework.core.io.support.ResourceArrayPropertyEditor
147:             * @see org.springframework.core.io.ResourceEditor
148:             * @see org.springframework.transaction.interceptor.TransactionAttributeEditor
149:             * @see org.springframework.transaction.interceptor.TransactionAttributeSourceEditor
150:             * @see org.springframework.beans.propertyeditors.URLEditor
151:             */
152:            private void doRegisterDefaultEditors() {
153:                this .defaultEditors = new HashMap(64);
154:
155:                // Simple editors, without parameterization capabilities.
156:                // The JDK does not contain a default editor for any of these target types.
157:                this .defaultEditors.put(Class.class, new ClassEditor());
158:                this .defaultEditors.put(Class[].class, new ClassArrayEditor());
159:                this .defaultEditors.put(File.class, new FileEditor());
160:                this .defaultEditors.put(InputStream.class,
161:                        new InputStreamEditor());
162:                this .defaultEditors.put(Locale.class, new LocaleEditor());
163:                this .defaultEditors.put(Pattern.class, new PatternEditor());
164:                this .defaultEditors.put(Properties.class,
165:                        new PropertiesEditor());
166:                this .defaultEditors.put(Resource[].class,
167:                        new ResourceArrayPropertyEditor());
168:                this .defaultEditors.put(URI.class, new URIEditor());
169:                this .defaultEditors.put(URL.class, new URLEditor());
170:
171:                // Default instances of collection editors.
172:                // Can be overridden by registering custom instances of those as custom editors.
173:                this .defaultEditors.put(Collection.class,
174:                        new CustomCollectionEditor(Collection.class));
175:                this .defaultEditors.put(Set.class, new CustomCollectionEditor(
176:                        Set.class));
177:                this .defaultEditors.put(SortedSet.class,
178:                        new CustomCollectionEditor(SortedSet.class));
179:                this .defaultEditors.put(List.class, new CustomCollectionEditor(
180:                        List.class));
181:                this .defaultEditors.put(SortedMap.class, new CustomMapEditor(
182:                        SortedMap.class));
183:
184:                // Default editors for primitive arrays.
185:                this .defaultEditors.put(byte[].class,
186:                        new ByteArrayPropertyEditor());
187:                this .defaultEditors.put(char[].class,
188:                        new CharArrayPropertyEditor());
189:
190:                // The JDK does not contain a default editor for char!
191:                this .defaultEditors.put(char.class, new CharacterEditor(false));
192:                this .defaultEditors.put(Character.class, new CharacterEditor(
193:                        true));
194:
195:                // Spring's CustomBooleanEditor accepts more flag values than the JDK's default editor.
196:                this .defaultEditors.put(boolean.class, new CustomBooleanEditor(
197:                        false));
198:                this .defaultEditors.put(Boolean.class, new CustomBooleanEditor(
199:                        true));
200:
201:                // The JDK does not contain default editors for number wrapper types!
202:                // Override JDK primitive number editors with our own CustomNumberEditor.
203:                this .defaultEditors.put(byte.class, new CustomNumberEditor(
204:                        Byte.class, false));
205:                this .defaultEditors.put(Byte.class, new CustomNumberEditor(
206:                        Byte.class, true));
207:                this .defaultEditors.put(short.class, new CustomNumberEditor(
208:                        Short.class, false));
209:                this .defaultEditors.put(Short.class, new CustomNumberEditor(
210:                        Short.class, true));
211:                this .defaultEditors.put(int.class, new CustomNumberEditor(
212:                        Integer.class, false));
213:                this .defaultEditors.put(Integer.class, new CustomNumberEditor(
214:                        Integer.class, true));
215:                this .defaultEditors.put(long.class, new CustomNumberEditor(
216:                        Long.class, false));
217:                this .defaultEditors.put(Long.class, new CustomNumberEditor(
218:                        Long.class, true));
219:                this .defaultEditors.put(float.class, new CustomNumberEditor(
220:                        Float.class, false));
221:                this .defaultEditors.put(Float.class, new CustomNumberEditor(
222:                        Float.class, true));
223:                this .defaultEditors.put(double.class, new CustomNumberEditor(
224:                        Double.class, false));
225:                this .defaultEditors.put(Double.class, new CustomNumberEditor(
226:                        Double.class, true));
227:                this .defaultEditors.put(BigDecimal.class,
228:                        new CustomNumberEditor(BigDecimal.class, true));
229:                this .defaultEditors.put(BigInteger.class,
230:                        new CustomNumberEditor(BigInteger.class, true));
231:
232:                // Only register config value editors if explicitly requested.
233:                if (this .configValueEditorsActive) {
234:                    this .defaultEditors.put(String[].class,
235:                            new StringArrayPropertyEditor());
236:                }
237:            }
238:
239:            /**
240:             * Copy the default editors registered in this instance to the given target registry.
241:             * @param target the target registry to copy to
242:             */
243:            protected void copyDefaultEditorsTo(
244:                    PropertyEditorRegistrySupport target) {
245:                target.defaultEditors = this .defaultEditors;
246:                target.defaultEditorsActive = this .defaultEditorsActive;
247:                target.configValueEditorsActive = this .configValueEditorsActive;
248:            }
249:
250:            //---------------------------------------------------------------------
251:            // Management of custom editors
252:            //---------------------------------------------------------------------
253:
254:            public void registerCustomEditor(Class requiredType,
255:                    PropertyEditor propertyEditor) {
256:                registerCustomEditor(requiredType, null, propertyEditor);
257:            }
258:
259:            public void registerCustomEditor(Class requiredType,
260:                    String propertyPath, PropertyEditor propertyEditor) {
261:                if (requiredType == null && propertyPath == null) {
262:                    throw new IllegalArgumentException(
263:                            "Either requiredType or propertyPath is required");
264:                }
265:                if (this .customEditors == null) {
266:                    this .customEditors = new LinkedHashMap(16);
267:                }
268:                if (propertyPath != null) {
269:                    this .customEditors
270:                            .put(propertyPath, new CustomEditorHolder(
271:                                    propertyEditor, requiredType));
272:                    this .propertySpecificEditorsRegistered = true;
273:                } else {
274:                    this .customEditors.put(requiredType, propertyEditor);
275:                    this .customEditorCache = null;
276:                }
277:            }
278:
279:            /**
280:             * Register the given custom property editor for all properties
281:             * of the given type, indicating that the given instance is a
282:             * shared editor that might be used concurrently.
283:             * @param requiredType the type of the property
284:             * @param propertyEditor the shared editor to register
285:             */
286:            public void registerSharedEditor(Class requiredType,
287:                    PropertyEditor propertyEditor) {
288:                registerCustomEditor(requiredType, null, propertyEditor);
289:                if (this .sharedEditors == null) {
290:                    this .sharedEditors = new HashSet();
291:                }
292:                this .sharedEditors.add(propertyEditor);
293:            }
294:
295:            /**
296:             * Check whether the given editor instance is a shared editor, that is,
297:             * whether the given editor instance might be used concurrently.
298:             * @param propertyEditor the editor instance to check
299:             * @return whether the editor is a shared instance
300:             */
301:            public boolean isSharedEditor(PropertyEditor propertyEditor) {
302:                return (this .sharedEditors != null && this .sharedEditors
303:                        .contains(propertyEditor));
304:            }
305:
306:            public PropertyEditor findCustomEditor(Class requiredType,
307:                    String propertyPath) {
308:                if (this .customEditors == null) {
309:                    return null;
310:                }
311:                Class requiredTypeToUse = requiredType;
312:                if (propertyPath != null) {
313:                    if (this .propertySpecificEditorsRegistered) {
314:                        // Check property-specific editor first.
315:                        PropertyEditor editor = getCustomEditor(propertyPath,
316:                                requiredType);
317:                        if (editor == null) {
318:                            List strippedPaths = new LinkedList();
319:                            addStrippedPropertyPaths(strippedPaths, "",
320:                                    propertyPath);
321:                            for (Iterator it = strippedPaths.iterator(); it
322:                                    .hasNext()
323:                                    && editor == null;) {
324:                                String strippedPath = (String) it.next();
325:                                editor = getCustomEditor(strippedPath,
326:                                        requiredType);
327:                            }
328:                        }
329:                        if (editor != null) {
330:                            return editor;
331:                        }
332:                    }
333:                    if (requiredType == null) {
334:                        requiredTypeToUse = getPropertyType(propertyPath);
335:                    }
336:                }
337:                // No property-specific editor -> check type-specific editor.
338:                return getCustomEditor(requiredTypeToUse);
339:            }
340:
341:            /**
342:             * Determine whether this registry contains a custom editor
343:             * for the specified array/collection element.
344:             * @param elementType the target type of the element
345:             * (can be <code>null</code> if not known)
346:             * @param propertyPath the property path (typically of the array/collection;
347:             * can be <code>null</code> if not known)
348:             * @return whether a matching custom editor has been found
349:             */
350:            public boolean hasCustomEditorForElement(Class elementType,
351:                    String propertyPath) {
352:                if (this .customEditors == null) {
353:                    return false;
354:                }
355:                if (propertyPath != null
356:                        && this .propertySpecificEditorsRegistered) {
357:                    for (Iterator it = this .customEditors.entrySet().iterator(); it
358:                            .hasNext();) {
359:                        Map.Entry entry = (Map.Entry) it.next();
360:                        if (entry.getKey() instanceof  String) {
361:                            String regPath = (String) entry.getKey();
362:                            if (PropertyAccessorUtils.matchesProperty(regPath,
363:                                    propertyPath)) {
364:                                CustomEditorHolder editorHolder = (CustomEditorHolder) entry
365:                                        .getValue();
366:                                if (editorHolder.getPropertyEditor(elementType) != null) {
367:                                    return true;
368:                                }
369:                            }
370:                        }
371:                    }
372:                }
373:                // No property-specific editor -> check type-specific editor.
374:                return (elementType != null && this .customEditors
375:                        .containsKey(elementType));
376:            }
377:
378:            /**
379:             * Determine the property type for the given property path.
380:             * <p>Called by {@link #findCustomEditor} if no required type has been specified,
381:             * to be able to find a type-specific editor even if just given a property path.
382:             * <p>The default implementation always returns <code>null</code>.
383:             * BeanWrapperImpl overrides this with the standard <code>getPropertyType</code>
384:             * method as defined by the BeanWrapper interface.
385:             * @param propertyPath the property path to determine the type for
386:             * @return the type of the property, or <code>null</code> if not determinable
387:             * @see BeanWrapper#getPropertyType(String)
388:             */
389:            protected Class getPropertyType(String propertyPath) {
390:                return null;
391:            }
392:
393:            /**
394:             * Get custom editor that has been registered for the given property.
395:             * @param propertyName the property path to look for
396:             * @param requiredType the type to look for
397:             * @return the custom editor, or <code>null</code> if none specific for this property
398:             */
399:            private PropertyEditor getCustomEditor(String propertyName,
400:                    Class requiredType) {
401:                CustomEditorHolder holder = (CustomEditorHolder) this .customEditors
402:                        .get(propertyName);
403:                return (holder != null ? holder.getPropertyEditor(requiredType)
404:                        : null);
405:            }
406:
407:            /**
408:             * Get custom editor for the given type. If no direct match found,
409:             * try custom editor for superclass (which will in any case be able
410:             * to render a value as String via <code>getAsText</code>).
411:             * @param requiredType the type to look for
412:             * @return the custom editor, or <code>null</code> if none found for this type
413:             * @see java.beans.PropertyEditor#getAsText()
414:             */
415:            private PropertyEditor getCustomEditor(Class requiredType) {
416:                if (requiredType == null) {
417:                    return null;
418:                }
419:                // Check directly registered editor for type.
420:                PropertyEditor editor = (PropertyEditor) this .customEditors
421:                        .get(requiredType);
422:                if (editor == null) {
423:                    // Check cached editor for type, registered for superclass or interface.
424:                    if (this .customEditorCache != null) {
425:                        editor = (PropertyEditor) this .customEditorCache
426:                                .get(requiredType);
427:                    }
428:                    if (editor == null) {
429:                        // Find editor for superclass or interface.
430:                        for (Iterator it = this .customEditors.keySet()
431:                                .iterator(); it.hasNext() && editor == null;) {
432:                            Object key = it.next();
433:                            if (key instanceof  Class
434:                                    && ((Class) key)
435:                                            .isAssignableFrom(requiredType)) {
436:                                editor = (PropertyEditor) this .customEditors
437:                                        .get(key);
438:                                // Cache editor for search type, to avoid the overhead
439:                                // of repeated assignable-from checks.
440:                                if (this .customEditorCache == null) {
441:                                    this .customEditorCache = new HashMap();
442:                                }
443:                                this .customEditorCache
444:                                        .put(requiredType, editor);
445:                            }
446:                        }
447:                    }
448:                }
449:                return editor;
450:            }
451:
452:            /**
453:             * Guess the property type of the specified property from the registered
454:             * custom editors (provided that they were registered for a specific type).
455:             * @param propertyName the name of the property
456:             * @return the property type, or <code>null</code> if not determinable
457:             */
458:            protected Class guessPropertyTypeFromEditors(String propertyName) {
459:                if (this .customEditors != null) {
460:                    CustomEditorHolder editorHolder = (CustomEditorHolder) this .customEditors
461:                            .get(propertyName);
462:                    if (editorHolder == null) {
463:                        List strippedPaths = new LinkedList();
464:                        addStrippedPropertyPaths(strippedPaths, "",
465:                                propertyName);
466:                        for (Iterator it = strippedPaths.iterator(); it
467:                                .hasNext()
468:                                && editorHolder == null;) {
469:                            String strippedName = (String) it.next();
470:                            editorHolder = (CustomEditorHolder) this .customEditors
471:                                    .get(strippedName);
472:                        }
473:                    }
474:                    if (editorHolder != null) {
475:                        return editorHolder.getRegisteredType();
476:                    }
477:                }
478:                return null;
479:            }
480:
481:            /**
482:             * Copy the custom editors registered in this instance to the given target registry.
483:             * @param target the target registry to copy to
484:             * @param nestedProperty the nested property path of the target registry, if any.
485:             * If this is non-null, only editors registered for a path below this nested property
486:             * will be copied. If this is null, all editors will be copied.
487:             */
488:            protected void copyCustomEditorsTo(PropertyEditorRegistry target,
489:                    String nestedProperty) {
490:                String actualPropertyName = (nestedProperty != null ? PropertyAccessorUtils
491:                        .getPropertyName(nestedProperty)
492:                        : null);
493:                if (this .customEditors != null) {
494:                    for (Iterator it = this .customEditors.entrySet().iterator(); it
495:                            .hasNext();) {
496:                        Map.Entry entry = (Map.Entry) it.next();
497:                        if (entry.getKey() instanceof  Class) {
498:                            Class requiredType = (Class) entry.getKey();
499:                            PropertyEditor editor = (PropertyEditor) entry
500:                                    .getValue();
501:                            target.registerCustomEditor(requiredType, editor);
502:                        } else if (entry.getKey() instanceof  String) {
503:                            String editorPath = (String) entry.getKey();
504:                            CustomEditorHolder editorHolder = (CustomEditorHolder) entry
505:                                    .getValue();
506:                            if (nestedProperty != null) {
507:                                int pos = PropertyAccessorUtils
508:                                        .getFirstNestedPropertySeparatorIndex(editorPath);
509:                                if (pos != -1) {
510:                                    String editorNestedProperty = editorPath
511:                                            .substring(0, pos);
512:                                    String editorNestedPath = editorPath
513:                                            .substring(pos + 1);
514:                                    if (editorNestedProperty
515:                                            .equals(nestedProperty)
516:                                            || editorNestedProperty
517:                                                    .equals(actualPropertyName)) {
518:                                        target.registerCustomEditor(
519:                                                editorHolder
520:                                                        .getRegisteredType(),
521:                                                editorNestedPath, editorHolder
522:                                                        .getPropertyEditor());
523:                                    }
524:                                }
525:                            } else {
526:                                target.registerCustomEditor(editorHolder
527:                                        .getRegisteredType(), editorPath,
528:                                        editorHolder.getPropertyEditor());
529:                            }
530:                        }
531:                    }
532:                }
533:            }
534:
535:            /**
536:             * Add property paths with all variations of stripped keys and/or indexes.
537:             * Invokes itself recursively with nested paths.
538:             * @param strippedPaths the result list to add to
539:             * @param nestedPath the current nested path
540:             * @param propertyPath the property path to check for keys/indexes to strip
541:             */
542:            private void addStrippedPropertyPaths(List strippedPaths,
543:                    String nestedPath, String propertyPath) {
544:                int startIndex = propertyPath
545:                        .indexOf(PropertyAccessor.PROPERTY_KEY_PREFIX_CHAR);
546:                if (startIndex != -1) {
547:                    int endIndex = propertyPath
548:                            .indexOf(PropertyAccessor.PROPERTY_KEY_SUFFIX_CHAR);
549:                    if (endIndex != -1) {
550:                        String prefix = propertyPath.substring(0, startIndex);
551:                        String key = propertyPath.substring(startIndex,
552:                                endIndex + 1);
553:                        String suffix = propertyPath.substring(endIndex + 1,
554:                                propertyPath.length());
555:                        // Strip the first key.
556:                        strippedPaths.add(nestedPath + prefix + suffix);
557:                        // Search for further keys to strip, with the first key stripped.
558:                        addStrippedPropertyPaths(strippedPaths, nestedPath
559:                                + prefix, suffix);
560:                        // Search for further keys to strip, with the first key not stripped.
561:                        addStrippedPropertyPaths(strippedPaths, nestedPath
562:                                + prefix + key, suffix);
563:                    }
564:                }
565:            }
566:
567:            /**
568:             * Holder for a registered custom editor with property name.
569:             * Keeps the PropertyEditor itself plus the type it was registered for.
570:             */
571:            private static class CustomEditorHolder {
572:
573:                private final PropertyEditor propertyEditor;
574:
575:                private final Class registeredType;
576:
577:                private CustomEditorHolder(PropertyEditor propertyEditor,
578:                        Class registeredType) {
579:                    this .propertyEditor = propertyEditor;
580:                    this .registeredType = registeredType;
581:                }
582:
583:                private PropertyEditor getPropertyEditor() {
584:                    return this .propertyEditor;
585:                }
586:
587:                private Class getRegisteredType() {
588:                    return this .registeredType;
589:                }
590:
591:                private PropertyEditor getPropertyEditor(Class requiredType) {
592:                    // Special case: If no required type specified, which usually only happens for
593:                    // Collection elements, or required type is not assignable to registered type,
594:                    // which usually only happens for generic properties of type Object -
595:                    // then return PropertyEditor if not registered for Collection or array type.
596:                    // (If not registered for Collection or array, it is assumed to be intended
597:                    // for elements.)
598:                    if (this .registeredType == null
599:                            || (requiredType != null && (ClassUtils
600:                                    .isAssignable(this .registeredType,
601:                                            requiredType) || ClassUtils
602:                                    .isAssignable(requiredType,
603:                                            this .registeredType)))
604:                            || (requiredType == null && (!Collection.class
605:                                    .isAssignableFrom(this.registeredType) && !this.registeredType
606:                                    .isArray()))) {
607:                        return this.propertyEditor;
608:                    } else {
609:                        return null;
610:                    }
611:                }
612:            }
613:
614:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.