/** * Populate the given {@code registry} with the following resource editors: * ResourceEditor, InputStreamEditor, InputSourceEditor, FileEditor, URLEditor, * URIEditor, ClassEditor, ClassArrayEditor. * <p>If this registrar has been configured with a {@link ResourcePatternResolver}, * a ResourceArrayPropertyEditor will be registered as well. * @see org.springframework.core.io.ResourceEditor * @see org.springframework.beans.propertyeditors.InputStreamEditor * @see org.springframework.beans.propertyeditors.InputSourceEditor * @see org.springframework.beans.propertyeditors.FileEditor * @see org.springframework.beans.propertyeditors.URLEditor * @see org.springframework.beans.propertyeditors.URIEditor * @see org.springframework.beans.propertyeditors.ClassEditor * @see org.springframework.beans.propertyeditors.ClassArrayEditor * @see org.springframework.core.io.support.ResourceArrayPropertyEditor */ @Override public void registerCustomEditors(PropertyEditorRegistry registry) { ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver); doRegisterEditor(registry, Resource.class, baseEditor); doRegisterEditor(registry, ContextResource.class, baseEditor); doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor)); doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor)); doRegisterEditor(registry, File.class, new FileEditor(baseEditor)); doRegisterEditor(registry, URL.class, new URLEditor(baseEditor)); ClassLoader classLoader = this.resourceLoader.getClassLoader(); doRegisterEditor(registry, URI.class, new URIEditor(classLoader)); doRegisterEditor(registry, Class.class, new ClassEditor(classLoader)); doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader)); if (this.resourceLoader instanceof ResourcePatternResolver) { doRegisterEditor(registry, Resource[].class, new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver)); } }
/** * Populate the given {@code registry} with the following resource editors: * ResourceEditor, InputStreamEditor, InputSourceEditor, FileEditor, URLEditor, * URIEditor, ClassEditor, ClassArrayEditor. * <p>If this registrar has been configured with a {@link ResourcePatternResolver}, * a ResourceArrayPropertyEditor will be registered as well. * @see org.springframework.core.io.ResourceEditor * @see org.springframework.beans.propertyeditors.InputStreamEditor * @see org.springframework.beans.propertyeditors.InputSourceEditor * @see org.springframework.beans.propertyeditors.FileEditor * @see org.springframework.beans.propertyeditors.URLEditor * @see org.springframework.beans.propertyeditors.URIEditor * @see org.springframework.beans.propertyeditors.ClassEditor * @see org.springframework.beans.propertyeditors.ClassArrayEditor * @see org.springframework.core.io.support.ResourceArrayPropertyEditor */ @Override public void registerCustomEditors(PropertyEditorRegistry registry) { ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver); doRegisterEditor(registry, Resource.class, baseEditor); doRegisterEditor(registry, ContextResource.class, baseEditor); doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor)); doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor)); doRegisterEditor(registry, File.class, new FileEditor(baseEditor)); doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor)); doRegisterEditor(registry, URL.class, new URLEditor(baseEditor)); ClassLoader classLoader = this.resourceLoader.getClassLoader(); doRegisterEditor(registry, URI.class, new URIEditor(classLoader)); doRegisterEditor(registry, Class.class, new ClassEditor(classLoader)); doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader)); if (this.resourceLoader instanceof ResourcePatternResolver) { doRegisterEditor(registry, Resource[].class, new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver)); } }
@Test public void testCustomEditor() { DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); lbf.addPropertyEditorRegistrar(new PropertyEditorRegistrar() { @Override public void registerCustomEditors(PropertyEditorRegistry registry) { NumberFormat nf = NumberFormat.getInstance(Locale.GERMAN); registry.registerCustomEditor(Float.class, new CustomNumberEditor(Float.class, nf, true)); } }); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.add("myFloat", "1,1"); RootBeanDefinition bd = new RootBeanDefinition(TestBean.class); bd.setPropertyValues(pvs); lbf.registerBeanDefinition("testBean", bd); TestBean testBean = (TestBean) lbf.getBean("testBean"); assertTrue(testBean.getMyFloat().floatValue() == 1.1f); }
@Test public void testCustomEditorWithBeanReference() { DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); lbf.addPropertyEditorRegistrar(new PropertyEditorRegistrar() { @Override public void registerCustomEditors(PropertyEditorRegistry registry) { NumberFormat nf = NumberFormat.getInstance(Locale.GERMAN); registry.registerCustomEditor(Float.class, new CustomNumberEditor(Float.class, nf, true)); } }); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.add("myFloat", new RuntimeBeanReference("myFloat")); RootBeanDefinition bd = new RootBeanDefinition(TestBean.class); bd.setPropertyValues(pvs); lbf.registerBeanDefinition("testBean", bd); lbf.registerSingleton("myFloat", "1,1"); TestBean testBean = (TestBean) lbf.getBean("testBean"); assertTrue(testBean.getMyFloat().floatValue() == 1.1f); }
@Override public void registerCustomEditors(PropertyEditorRegistry registry) { if (!(registry instanceof BeanWrapperImpl)) { return; } BeanWrapperImpl beanWrapper = (BeanWrapperImpl) registry; Class<?> clazz = null; try { clazz = Class.forName(SchedulerFactoryBean, true, registry.getClass().getClassLoader()); } catch (Throwable e) { LOGGER.info("cannot find class for " + SchedulerFactoryBean, e); } if (null == clazz || null == beanWrapper.getWrappedClass() || !clazz.isAssignableFrom(beanWrapper.getWrappedClass())) { return; } registry.registerCustomEditor(Object.class, "triggers", new QuartzSchedulerBeanTargetEditor(context)); }
/** * Registers a default set of property editors for use with KRAD in a given property editor registry. * * @param registry property editor registry */ public static void registerPropertyEditors(PropertyEditorRegistry registry) { DataDictionaryService dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService(); Map<Class<?>, String> propertyEditorMap = dataDictionaryService.getPropertyEditorMap(); if (propertyEditorMap == null) { LOG.warn("No propertyEditorMap defined in data dictionary"); return; } for (Entry<Class<?>, String> propertyEditorEntry : propertyEditorMap.entrySet()) { PropertyEditor editor = (PropertyEditor) dataDictionaryService.getDataDictionary().getDictionaryPrototype( propertyEditorEntry.getValue()); registry.registerCustomEditor(propertyEditorEntry.getKey(), editor); if (LOG.isDebugEnabled()) { LOG.debug("registered " + propertyEditorEntry); } } }
/** * Get a property editor given a property type. * * @param propertyType The property type to look up an editor for. * @param path The property path, if applicable. * @return property editor */ public static PropertyEditor getPropertyEditor(Class<?> propertyType) { PropertyEditorRegistry registry = getPropertyEditorRegistry(); PropertyEditor editor = null; if (registry != null) { editor = registry.findCustomEditor(propertyType, null); } else { DataDictionaryService dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService(); Map<Class<?>, String> editorMap = dataDictionaryService.getPropertyEditorMap(); String editorPrototypeName = editorMap == null ? null : editorMap.get(propertyType); if (editorPrototypeName != null) { editor = (PropertyEditor) dataDictionaryService.getDataDictionary().getDictionaryPrototype(editorPrototypeName); } } if (editor == null && propertyType != null) { // Fall back to default beans lookup editor = PropertyEditorManager.findEditor(propertyType); } return editor; }
public static void registerProtertyEditor(DefaultListableBeanFactory dlbf, Class<? extends PropertyEditor> propertyEditorType, Class<?>... targetType) { final Class<?> theTargetType = getTargetType(propertyEditorType, targetType); if (theTargetType == null) return; final PropertyEditor propertyEditor = newProtertyEditor(propertyEditorType, theTargetType); if (propertyEditor == null) return; PropertyEditorRegistrar myPropertyEditorRegistrar = new PropertyEditorRegistrar() { public void registerCustomEditors(PropertyEditorRegistry registry) { registry.registerCustomEditor(theTargetType, propertyEditor); } }; dlbf.addPropertyEditorRegistrar(myPropertyEditorRegistrar); }
/** * Collects all PropertyEditorRegistrars in the application context and * calls them to register their custom editors * * @param registry The PropertyEditorRegistry instance */ private static void registerCustomEditors(PropertyEditorRegistry registry) { final ServletContext servletContext = ServletContextHolder.getServletContext(); if (servletContext == null) { return; } WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext); if (context == null) { return; } Map<String, PropertyEditorRegistrar> editors = context.getBeansOfType(PropertyEditorRegistrar.class); for (PropertyEditorRegistrar editorRegistrar : editors.values()) { editorRegistrar.registerCustomEditors(registry); } }
/** * Registers all known * * @param registry * @param locale */ public static void registerCustomEditors(PropertyEditorRegistry registry, Locale locale) { // Formatters for the different number types. NumberFormat floatFormat = NumberFormat.getInstance(locale); NumberFormat integerFormat = NumberFormat.getIntegerInstance(locale); DateFormat dateFormat = new SimpleDateFormat(DEFAULT_DATE_FORMAT, locale); registry.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true)); registry.registerCustomEditor(BigDecimal.class, new CustomNumberEditor(BigDecimal.class, floatFormat, true)); registry.registerCustomEditor(BigInteger.class, new CustomNumberEditor(BigInteger.class, floatFormat, true)); registry.registerCustomEditor(Double.class, new CustomNumberEditor(Double.class, floatFormat, true)); registry.registerCustomEditor(double.class, new CustomNumberEditor(Double.class, floatFormat, true)); registry.registerCustomEditor(Float.class, new CustomNumberEditor(Float.class, floatFormat, true)); registry.registerCustomEditor(float.class, new CustomNumberEditor(Float.class, floatFormat, true)); registry.registerCustomEditor(Long.class, new CustomNumberEditor(Long.class, integerFormat, true)); registry.registerCustomEditor(long.class, new CustomNumberEditor(Long.class, integerFormat, true)); registry.registerCustomEditor(Integer.class, new CustomNumberEditor(Integer.class, integerFormat, true)); registry.registerCustomEditor(int.class, new CustomNumberEditor(Integer.class, integerFormat, true)); registry.registerCustomEditor(Short.class, new CustomNumberEditor(Short.class, integerFormat, true)); registry.registerCustomEditor(short.class, new CustomNumberEditor(Short.class, integerFormat, true)); registry.registerCustomEditor(Date.class, new StructuredDateEditor(dateFormat, true)); registry.registerCustomEditor(Calendar.class, new StructuredDateEditor(dateFormat, true)); registerCustomEditors(registry); }
/** * Populate the given {@code registry} with the following resource editors: * ResourceEditor, InputStreamEditor, InputSourceEditor, FileEditor, URLEditor, * URIEditor, ClassEditor, ClassArrayEditor. * <p>If this registrar has been configured with a {@link ResourcePatternResolver}, * a ResourceArrayPropertyEditor will be registered as well. * @see org.springframework.core.io.ResourceEditor * @see org.springframework.beans.propertyeditors.InputStreamEditor * @see org.springframework.beans.propertyeditors.InputSourceEditor * @see org.springframework.beans.propertyeditors.FileEditor * @see org.springframework.beans.propertyeditors.URLEditor * @see org.springframework.beans.propertyeditors.URIEditor * @see org.springframework.beans.propertyeditors.ClassEditor * @see org.springframework.beans.propertyeditors.ClassArrayEditor * @see org.springframework.core.io.support.ResourceArrayPropertyEditor */ public void registerCustomEditors(PropertyEditorRegistry registry) { ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver); doRegisterEditor(registry, Resource.class, baseEditor); doRegisterEditor(registry, ContextResource.class, baseEditor); doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor)); doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor)); doRegisterEditor(registry, File.class, new FileEditor(baseEditor)); doRegisterEditor(registry, URL.class, new URLEditor(baseEditor)); ClassLoader classLoader = this.resourceLoader.getClassLoader(); doRegisterEditor(registry, URI.class, new URIEditor(classLoader)); doRegisterEditor(registry, Class.class, new ClassEditor(classLoader)); doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader)); if (this.resourceLoader instanceof ResourcePatternResolver) { doRegisterEditor(registry, Resource[].class, new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver)); } }
/** * @see org.springframework.beans.PropertyEditorRegistrar#registerCustomEditors(org.springframework.beans.PropertyEditorRegistry) */ @Override public void registerCustomEditors(PropertyEditorRegistry registry) { // add custom QName editor registry.registerCustomEditor(QName.class, new QNameTypeEditor(namespaceService)); }
public void registerCustomEditors(PropertyEditorRegistry registry) { for (Map.Entry<Class<?>, Class<? extends PropertyEditor>> entry : editors.entrySet()) { Class<?> type = entry.getKey(); PropertyEditor editorInstance; editorInstance = BeanUtils.instantiate(entry.getValue()); registry.registerCustomEditor(type, editorInstance); } // register non-externalized types registry.registerCustomEditor(Dictionary.class, new CustomMapEditor(Hashtable.class)); registry.registerCustomEditor(Properties.class, new PropertiesEditor()); registry.registerCustomEditor(Class.class, new ClassEditor(userClassLoader)); registry.registerCustomEditor(Class[].class, new ClassArrayEditor(userClassLoader)); }
public void registerCustomEditors(PropertyEditorRegistry registry) { // Date registry.registerCustomEditor(Date.class, new DateEditor()); // Collection concrete types registry.registerCustomEditor(Stack.class, new BlueprintCustomCollectionEditor(Stack.class)); registry.registerCustomEditor(Vector.class, new BlueprintCustomCollectionEditor(Vector.class)); // Spring creates a LinkedHashSet for Collection, RFC mandates an ArrayList // reinitialize default editors registry.registerCustomEditor(Collection.class, new BlueprintCustomCollectionEditor(Collection.class)); registry.registerCustomEditor(Set.class, new BlueprintCustomCollectionEditor(Set.class)); registry.registerCustomEditor(SortedSet.class, new BlueprintCustomCollectionEditor(SortedSet.class)); registry.registerCustomEditor(List.class, new BlueprintCustomCollectionEditor(List.class)); registry.registerCustomEditor(SortedMap.class, new CustomMapEditor(SortedMap.class)); registry.registerCustomEditor(HashSet.class, new BlueprintCustomCollectionEditor(HashSet.class)); registry.registerCustomEditor(LinkedHashSet.class, new BlueprintCustomCollectionEditor(LinkedHashSet.class)); registry.registerCustomEditor(TreeSet.class, new BlueprintCustomCollectionEditor(TreeSet.class)); registry.registerCustomEditor(ArrayList.class, new BlueprintCustomCollectionEditor(ArrayList.class)); registry.registerCustomEditor(LinkedList.class, new BlueprintCustomCollectionEditor(LinkedList.class)); // Map concrete types registry.registerCustomEditor(HashMap.class, new CustomMapEditor(HashMap.class)); registry.registerCustomEditor(LinkedHashMap.class, new CustomMapEditor(LinkedHashMap.class)); registry.registerCustomEditor(Hashtable.class, new CustomMapEditor(Hashtable.class)); registry.registerCustomEditor(TreeMap.class, new CustomMapEditor(TreeMap.class)); registry.registerCustomEditor(Properties.class, new PropertiesEditor()); // JDK 5 types registry.registerCustomEditor(ConcurrentMap.class, new CustomMapEditor(ConcurrentHashMap.class)); registry.registerCustomEditor(ConcurrentHashMap.class, new CustomMapEditor(ConcurrentHashMap.class)); registry.registerCustomEditor(Queue.class, new BlueprintCustomCollectionEditor(LinkedList.class)); // Legacy types registry.registerCustomEditor(Dictionary.class, new CustomMapEditor(Hashtable.class)); }
/** * This implementation delegates to the * {@link #getPropertyEditorRegistry() PropertyEditorRegistry}'s * editor lookup facility, if available. */ @Override public PropertyEditor findEditor(String field, Class<?> valueType) { PropertyEditorRegistry editorRegistry = getPropertyEditorRegistry(); if (editorRegistry != null) { Class<?> valueTypeToUse = valueType; if (valueTypeToUse == null) { valueTypeToUse = getFieldType(field); } return editorRegistry.findCustomEditor(valueTypeToUse, fixedField(field)); } else { return null; } }
/** * Return the underlying TypeConverter of this binder's BindingResult. */ protected PropertyEditorRegistry getPropertyEditorRegistry() { if (getTarget() != null) { return getInternalBindingResult().getPropertyAccessor(); } else { return getSimpleTypeConverter(); } }
/** * Initialize the given PropertyEditorRegistry with the custom editors * that have been registered with this BeanFactory. * <p>To be called for BeanWrappers that will create and populate bean * instances, and for SimpleTypeConverter used for constructor argument * and factory method type conversion. * @param registry the PropertyEditorRegistry to initialize */ protected void registerCustomEditors(PropertyEditorRegistry registry) { PropertyEditorRegistrySupport registrySupport = (registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null); if (registrySupport != null) { registrySupport.useConfigValueEditors(); } if (!this.propertyEditorRegistrars.isEmpty()) { for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) { try { registrar.registerCustomEditors(registry); } catch (BeanCreationException ex) { Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; if (isCurrentlyInCreation(bce.getBeanName())) { if (logger.isDebugEnabled()) { logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() + "] failed because it tried to obtain currently created bean '" + ex.getBeanName() + "': " + ex.getMessage()); } onSuppressedException(ex); continue; } } throw ex; } } } if (!this.customEditors.isEmpty()) { for (Map.Entry<Class<?>, Class<? extends PropertyEditor>> entry : this.customEditors.entrySet()) { Class<?> requiredType = entry.getKey(); Class<? extends PropertyEditor> editorClass = entry.getValue(); registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass)); } } }
/** * Override default editor, if possible (since that's what we really mean to do here); * otherwise register as a custom editor. */ private void doRegisterEditor(PropertyEditorRegistry registry, Class<?> requiredType, PropertyEditor editor) { if (registry instanceof PropertyEditorRegistrySupport) { ((PropertyEditorRegistrySupport) registry).overrideDefaultEditor(requiredType, editor); } else { registry.registerCustomEditor(requiredType, editor); } }
@Test public void testGenericMapWithCollectionValueConstructor() throws MalformedURLException { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); bf.addPropertyEditorRegistrar(new PropertyEditorRegistrar() { @Override public void registerCustomEditors(PropertyEditorRegistry registry) { registry.registerCustomEditor(Number.class, new CustomNumberEditor(Integer.class, false)); } }); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); Map<String, AbstractCollection<?>> input = new HashMap<String, AbstractCollection<?>>(); HashSet<Integer> value1 = new HashSet<Integer>(); value1.add(new Integer(1)); input.put("1", value1); ArrayList<Boolean> value2 = new ArrayList<Boolean>(); value2.add(Boolean.TRUE); input.put("2", value2); rbd.getConstructorArgumentValues().addGenericArgumentValue(Boolean.TRUE); rbd.getConstructorArgumentValues().addGenericArgumentValue(input); bf.registerBeanDefinition("genericBean", rbd); GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); assertTrue(gb.getCollectionMap().get(new Integer(1)) instanceof HashSet); assertTrue(gb.getCollectionMap().get(new Integer(2)) instanceof ArrayList); }
@Test public void testGenericMapWithCollectionValueFactoryMethod() throws MalformedURLException { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); bf.addPropertyEditorRegistrar(new PropertyEditorRegistrar() { @Override public void registerCustomEditors(PropertyEditorRegistry registry) { registry.registerCustomEditor(Number.class, new CustomNumberEditor(Integer.class, false)); } }); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); rbd.setFactoryMethodName("createInstance"); Map<String, AbstractCollection<?>> input = new HashMap<String, AbstractCollection<?>>(); HashSet<Integer> value1 = new HashSet<Integer>(); value1.add(new Integer(1)); input.put("1", value1); ArrayList<Boolean> value2 = new ArrayList<Boolean>(); value2.add(Boolean.TRUE); input.put("2", value2); rbd.getConstructorArgumentValues().addGenericArgumentValue(Boolean.TRUE); rbd.getConstructorArgumentValues().addGenericArgumentValue(input); bf.registerBeanDefinition("genericBean", rbd); GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); assertTrue(gb.getCollectionMap().get(new Integer(1)) instanceof HashSet); assertTrue(gb.getCollectionMap().get(new Integer(2)) instanceof ArrayList); }
@Before public void setUp() throws Exception { Assume.group(TestGroup.PERFORMANCE); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); new XmlBeanDefinitionReader(factory).loadBeanDefinitions(CONTEXT); factory.addPropertyEditorRegistrar(new PropertyEditorRegistrar() { @Override public void registerCustomEditors(PropertyEditorRegistry registry) { registry.registerCustomEditor(Date.class, new CustomDateEditor((DateFormat) DATE_FORMAT.clone(), false)); } }); this.factory = factory; }
/** * Gets a property editor given a specific bean and property path. * * @param bean The bean instance. * @param path The property path. * @return property editor */ public static PropertyEditor getPropertyEditor(Object bean, String path) { Class<?> propertyType = getPrimitiveType(getPropertyType(bean, path)); PropertyEditor editor = null; PropertyEditorRegistry registry = getPropertyEditorRegistry(); if (registry != null) { editor = registry.findCustomEditor(propertyType, path); if (editor != null && editor != registry.findCustomEditor(propertyType, null)) { return editor; } if (registry instanceof BeanWrapper && bean == ((BeanWrapper) registry).getWrappedInstance() && (bean instanceof ViewModel)) { ViewModel viewModel = (ViewModel) bean; ViewPostMetadata viewPostMetadata = viewModel.getViewPostMetadata(); PropertyEditor editorFromView = viewPostMetadata == null ? null : viewPostMetadata.getFieldEditor(path); if (editorFromView != null) { registry.registerCustomEditor(propertyType, path, editorFromView); editor = registry.findCustomEditor(propertyType, path); } } } if (editor != null) { return editor; } return getPropertyEditor(propertyType); }
/** * Registers a {@link CustomCollectionEditor} to translate a multiple select bind value into a sorted collection of * the proper model elements. * * @param binder The binder to register the editor into. * @param collectionClass The class of the collection. * @param propertyPath The path of the property to convert. * @param collectionModelClass The class of the model in the collection. * @param comparator The comparator to use for {@link SortedSet}s. * @param <C> The class of the collection. */ protected <C extends Collection<?>> void registerCollectionEditor(PropertyEditorRegistry binder, final Class<C> collectionClass, String propertyPath, final Class<? extends IModel> collectionModelClass, final Comparator<?> comparator) { if (collectionClass.isInstance(SortedSet.class) && comparator == null) { throw new NullPointerException("comparator cannot be null if the collection is sorted"); } binder.registerCustomEditor(collectionClass, propertyPath, new CustomCollectionEditor(collectionClass) { @Override protected Object convertElement(Object element) { IModel model; try { model = collectionModelClass.newInstance(); } catch (InstantiationException | IllegalAccessException e) { throw new RuntimeException(e); } if (element != null) { Long id = Long.valueOf(element.toString()); model.setId(id); } return model; } @Override @SuppressWarnings({ "unchecked", "rawtypes" }) // Also warnings in CustomCollectionEditor, do don't mind the @SuppressWarnings protected Collection<Object> createCollection(Class<? extends Collection> clazz, int size) { if (SortedSet.class.isAssignableFrom(clazz)) { return new TreeSet(comparator); } return super.createCollection(clazz, size); } }); }
@InitBinder private void initBinder(PropertyEditorRegistry binder) throws Exception { AuthorComparator authComp = new AuthorComparator(); registerCollectionEditor(binder, SortedSet.class, "writers", Author.class, authComp); registerCollectionEditor(binder, SortedSet.class, "artists", Author.class, authComp); registerCollectionEditor(binder, SortedSet.class, "colorists", Author.class, authComp); registerCollectionEditor(binder, SortedSet.class, "inkers", Author.class, authComp); registerCollectionEditor(binder, SortedSet.class, "translators", Author.class, authComp); registerCollectionEditor(binder, SortedSet.class, "tags", Tag.class, new IdentifyingNameComparator()); registerCollectionEditor(binder, Set.class, "images", Image.class); }