Revision: 1573 http://svn.sourceforge.net/spring-rich-c/?rev=1573&view=rev Author: kdonald Date: 2006-11-21 22:34:37 -0800 (Tue, 21 Nov 2006)
Log Message: ----------- changed DefaultConversionService to DefaultConversionServiceFactoryBean, and made it a FactoryBean. Initialization logic in constructor prevented customization. Factory is more appropriate for configuring an extended conversion service implementation. Modified Paths: -------------- trunk/spring-richclient/support/src/main/java/org/springframework/binding/form/support/AbstractFormModel.java trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/PageComponentContext.java trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/support/DefaultApplicationServices.java Added Paths: ----------- trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/DefaultConversionServiceFactoryBean.java Removed Paths: ------------- trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/DefaultConversionService.java Modified: trunk/spring-richclient/support/src/main/java/org/springframework/binding/form/support/AbstractFormModel.java =================================================================== --- trunk/spring-richclient/support/src/main/java/org/springframework/binding/form/support/AbstractFormModel.java 2006-11-22 06:33:18 UTC (rev 1572) +++ trunk/spring-richclient/support/src/main/java/org/springframework/binding/form/support/AbstractFormModel.java 2006-11-22 06:34:37 UTC (rev 1573) @@ -32,13 +32,15 @@ import org.springframework.binding.convert.ConversionExecutor; import org.springframework.binding.convert.ConversionService; import org.springframework.binding.convert.Converter; +import org.springframework.binding.convert.support.DefaultConversionService; +import org.springframework.binding.convert.support.GenericConversionService; import org.springframework.binding.form.CommitListener; import org.springframework.binding.form.ConfigurableFormModel; -import org.springframework.binding.form.FormModel; import org.springframework.binding.form.FieldFace; import org.springframework.binding.form.FieldFaceSource; +import org.springframework.binding.form.FieldMetadata; +import org.springframework.binding.form.FormModel; import org.springframework.binding.form.HierarchicalFormModel; -import org.springframework.binding.form.FieldMetadata; import org.springframework.binding.support.BeanPropertyAccessStrategy; import org.springframework.binding.value.CommitTrigger; import org.springframework.binding.value.ValueModel; @@ -49,7 +51,6 @@ import org.springframework.binding.value.support.TypeConverter; import org.springframework.binding.value.support.ValueHolder; import org.springframework.richclient.application.ApplicationServicesLocator; -import org.springframework.richclient.application.DefaultConversionService; import org.springframework.richclient.util.Assert; import org.springframework.richclient.util.ClassUtils; import org.springframework.richclient.util.EventListenerListHelper; @@ -329,7 +330,8 @@ // Check for locally registered property converters if (propertyConversionServices.containsKey(formProperty)) { - final DefaultConversionService propertyConversionService = (DefaultConversionService)propertyConversionServices.get(formProperty); + //TODO - extract ConfigurableConversionService interface... + final GenericConversionService propertyConversionService = (GenericConversionService)propertyConversionServices.get(formProperty); if (propertyConversionService != null) { convertTo = propertyConversionService.getConversionExecutor(sourceClass, targetClass); Deleted: trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/DefaultConversionService.java =================================================================== --- trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/DefaultConversionService.java 2006-11-22 06:33:18 UTC (rev 1572) +++ trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/DefaultConversionService.java 2006-11-22 06:34:37 UTC (rev 1573) @@ -1,247 +0,0 @@ -/* - * Copyright 2002-2004 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.springframework.richclient.application; - -import org.springframework.binding.convert.ConversionContext; -import org.springframework.binding.convert.support.AbstractConverter; -import org.springframework.binding.convert.support.AbstractFormattingConverter; -import org.springframework.binding.format.FormatterFactory; -import org.springframework.binding.format.support.SimpleFormatterFactory; -import org.springframework.richclient.convert.support.CollectionConverter; -import org.springframework.richclient.convert.support.ListModelConverter; -import org.springframework.util.StringUtils; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Date; - -public class DefaultConversionService extends org.springframework.binding.convert.support.DefaultConversionService { - - public DefaultConversionService() { - addDefaultConverters(); - } - - protected void addDefaultConverters() { - super.addDefaultConverters(); - addConverter(new TextToDate(getFormatterLocator(), true)); - addConverter(new DateToText(getFormatterLocator(), true)); - addConverter(new TextToNumber(getFormatterLocator(), true)); - addConverter(new NumberToText(getFormatterLocator(), true)); - addConverter(new BooleanToText()); - addConverter(new TextToBoolean()); - addConverter(new CollectionConverter()); - addConverter(new ListModelConverter()); - } - - private FormatterFactory getFormatterLocator() { - return new SimpleFormatterFactory(); - } - - public static final class TextToDate extends AbstractFormattingConverter { - - private final boolean allowEmpty; - - protected TextToDate(FormatterFactory formatterFactory, boolean allowEmpty) { - super(formatterFactory); - this.allowEmpty = allowEmpty; - } - - public Class[] getSourceClasses() { - return new Class[] { String.class }; - } - - public Class[] getTargetClasses() { - return new Class[] { Date.class }; - } - - protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception { - return (!allowEmpty || StringUtils.hasText((String)source)) ? getFormatterFactory().getDateTimeFormatter() - .parseValue((String) source, Date.class) : null; - } - } - - public static final class DateToText extends AbstractFormattingConverter { - - private final boolean allowEmpty; - - protected DateToText(FormatterFactory formatterLocator, boolean allowEmpty) { - super(formatterLocator); - this.allowEmpty = allowEmpty; - } - - public Class[] getSourceClasses() { - return new Class[] { Date.class }; - } - - public Class[] getTargetClasses() { - return new Class[] { String.class }; - } - - protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception { - return (!allowEmpty || source != null) ? getFormatterFactory().getDateTimeFormatter().formatValue(source) - : ""; - } - } - - public static final class TextToNumber extends AbstractFormattingConverter { - - private final boolean allowEmpty; - - protected TextToNumber(FormatterFactory formatterLocator, boolean allowEmpty) { - super(formatterLocator); - this.allowEmpty = allowEmpty; - } - - public Class[] getSourceClasses() { - return new Class[] { String.class }; - } - - public Class[] getTargetClasses() { - return new Class[] { Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, - BigInteger.class, BigDecimal.class, }; - } - - protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception { - return (!allowEmpty || StringUtils.hasText((String)source)) ? getFormatterFactory().getNumberFormatter( - targetClass).parseValue((String) source, targetClass) : null; - } - } - - public static final class NumberToText extends AbstractFormattingConverter { - - private final boolean allowEmpty; - - protected NumberToText(FormatterFactory formatterLocator, boolean allowEmpty) { - super(formatterLocator); - this.allowEmpty = allowEmpty; - } - - public Class[] getSourceClasses() { - return new Class[] { Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, - BigInteger.class, BigDecimal.class, }; - } - - public Class[] getTargetClasses() { - return new Class[] { String.class }; - } - - protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception { - return (!allowEmpty || source != null) ? getFormatterFactory().getNumberFormatter(source.getClass()) - .formatValue(source) : ""; - } - } - - public static final class TextToBoolean extends AbstractConverter { - - public static final String VALUE_TRUE = "true"; - - public static final String VALUE_FALSE = "false"; - - public static final String VALUE_ON = "on"; - - public static final String VALUE_OFF = "off"; - - public static final String VALUE_YES = "yes"; - - public static final String VALUE_NO = "no"; - - public static final String VALUE_1 = "1"; - - public static final String VALUE_0 = "0"; - - private String trueString; - - private String falseString; - - public TextToBoolean() { - } - - public TextToBoolean(String trueString, String falseString) { - this.trueString = trueString; - this.falseString = falseString; - } - - public Class[] getSourceClasses() { - return new Class[] { String.class }; - } - - public Class[] getTargetClasses() { - return new Class[] { Boolean.class }; - } - - protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception { - String text = (String) source; - if (!StringUtils.hasText(text)) { - return null; - } else if (this.trueString != null && text.equalsIgnoreCase(this.trueString)) { - return Boolean.TRUE; - } else if (this.falseString != null && text.equalsIgnoreCase(this.falseString)) { - return Boolean.FALSE; - } else if (this.trueString == null - && (text.equalsIgnoreCase(VALUE_TRUE) || text.equalsIgnoreCase(VALUE_ON) - || text.equalsIgnoreCase(VALUE_YES) || text.equals(VALUE_1))) { - return Boolean.TRUE; - } else if (this.falseString == null - && (text.equalsIgnoreCase(VALUE_FALSE) || text.equalsIgnoreCase(VALUE_OFF) - || text.equalsIgnoreCase(VALUE_NO) || text.equals(VALUE_0))) { - return Boolean.FALSE; - } else { - throw new IllegalArgumentException("Invalid boolean value [" + text + "]"); - } - } - } - - public static final class BooleanToText extends AbstractConverter { - - public static final String VALUE_YES = "yes"; - - public static final String VALUE_NO = "no"; - - private String trueString; - - private String falseString; - - public BooleanToText() { - } - - public BooleanToText(String trueString, String falseString) { - this.trueString = trueString; - this.falseString = falseString; - } - - public Class[] getSourceClasses() { - return new Class[] { Boolean.class }; - } - - public Class[] getTargetClasses() { - return new Class[] { String.class }; - } - - protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception { - Boolean bool = (Boolean) source; - if (this.trueString != null && bool.booleanValue()) { - return trueString; - } else if (this.falseString != null && !bool.booleanValue()) { - return falseString; - } else if (bool.booleanValue()) { - return VALUE_YES; - } else { - return VALUE_NO; - } - } - } - -} Copied: trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/DefaultConversionServiceFactoryBean.java (from rev 1570, trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/DefaultConversionService.java) =================================================================== --- trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/DefaultConversionServiceFactoryBean.java (rev 0) +++ trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/DefaultConversionServiceFactoryBean.java 2006-11-22 06:34:37 UTC (rev 1573) @@ -0,0 +1,297 @@ +/* + * Copyright 2002-2004 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.springframework.richclient.application; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Date; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.binding.convert.ConversionContext; +import org.springframework.binding.convert.ConversionService; +import org.springframework.binding.convert.support.AbstractConverter; +import org.springframework.binding.convert.support.AbstractFormattingConverter; +import org.springframework.binding.convert.support.DefaultConversionService; +import org.springframework.binding.format.FormatterFactory; +import org.springframework.binding.format.support.SimpleFormatterFactory; +import org.springframework.richclient.convert.support.CollectionConverter; +import org.springframework.richclient.convert.support.ListModelConverter; +import org.springframework.util.StringUtils; + +/** + * A factory bean that produces a conversion service installed with most converters + * needed by Spring Rich. Subclasses may extend and customize. The factory approach + * here is superior to subclassing as it minimizes conversion service constructor logic. + * + * @author Oliver Hutchison + * @author Keith Donald + */ +public class DefaultConversionServiceFactoryBean implements FactoryBean { + + private ConversionService conversionService; + + private FormatterFactory formatterFactory = new SimpleFormatterFactory(); + + public DefaultConversionServiceFactoryBean() { + } + + protected FormatterFactory getFormatterFactory() { + return formatterFactory; + } + + public void setFormatterFactory(FormatterFactory formatterFactory) { + this.formatterFactory = formatterFactory; + } + + public Object getObject() throws Exception { + return getConversionService(); + } + + public Class getObjectType() { + return ConversionService.class; + } + + public boolean isSingleton() { + return true; + } + + public final ConversionService getConversionService() { + if (conversionService == null) { + conversionService = createConversionService(); + } + return conversionService; + } + + /** + * Creates the conversion service. Subclasses may override to customize creation. + * @return the configured conversion service + */ + protected ConversionService createConversionService() { + DefaultConversionService service = new DefaultConversionService(); + service.addConverter(new TextToNumber(getFormatterFactory(), true)); + service.addConverter(new TextToDate(getFormatterFactory(), true)); + service.addConverter(new DateToText(getFormatterFactory(), true)); + service.addConverter(new TextToNumber(getFormatterFactory(), true)); + service.addConverter(new NumberToText(getFormatterFactory(), true)); + service.addConverter(new BooleanToText()); + service.addConverter(new TextToBoolean()); + service.addConverter(new CollectionConverter()); + service.addConverter(new ListModelConverter()); + return service; + } + + static final class TextToDate extends AbstractFormattingConverter { + + private final boolean allowEmpty; + + protected TextToDate(FormatterFactory formatterFactory, boolean allowEmpty) { + super(formatterFactory); + this.allowEmpty = allowEmpty; + } + + public Class[] getSourceClasses() { + return new Class[] { String.class }; + } + + public Class[] getTargetClasses() { + return new Class[] { Date.class }; + } + + protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception { + return (!allowEmpty || StringUtils.hasText((String) source)) ? getFormatterFactory().getDateTimeFormatter() + .parseValue((String) source, Date.class) : null; + } + } + + static final class DateToText extends AbstractFormattingConverter { + + private final boolean allowEmpty; + + protected DateToText(FormatterFactory formatterLocator, boolean allowEmpty) { + super(formatterLocator); + this.allowEmpty = allowEmpty; + } + + public Class[] getSourceClasses() { + return new Class[] { Date.class }; + } + + public Class[] getTargetClasses() { + return new Class[] { String.class }; + } + + protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception { + return (!allowEmpty || source != null) ? getFormatterFactory().getDateTimeFormatter().formatValue(source) + : ""; + } + } + + static final class TextToNumber extends AbstractFormattingConverter { + + private final boolean allowEmpty; + + protected TextToNumber(FormatterFactory formatterLocator, boolean allowEmpty) { + super(formatterLocator); + this.allowEmpty = allowEmpty; + } + + public Class[] getSourceClasses() { + return new Class[] { String.class }; + } + + public Class[] getTargetClasses() { + return new Class[] { Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, + BigInteger.class, BigDecimal.class, }; + } + + protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception { + return (!allowEmpty || StringUtils.hasText((String) source)) ? getFormatterFactory().getNumberFormatter( + targetClass).parseValue((String) source, targetClass) : null; + } + } + + static final class NumberToText extends AbstractFormattingConverter { + + private final boolean allowEmpty; + + protected NumberToText(FormatterFactory formatterLocator, boolean allowEmpty) { + super(formatterLocator); + this.allowEmpty = allowEmpty; + } + + public Class[] getSourceClasses() { + return new Class[] { Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, + BigInteger.class, BigDecimal.class, }; + } + + public Class[] getTargetClasses() { + return new Class[] { String.class }; + } + + protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception { + return (!allowEmpty || source != null) ? getFormatterFactory().getNumberFormatter(source.getClass()) + .formatValue(source) : ""; + } + } + + static final class TextToBoolean extends AbstractConverter { + + public static final String VALUE_TRUE = "true"; + + public static final String VALUE_FALSE = "false"; + + public static final String VALUE_ON = "on"; + + public static final String VALUE_OFF = "off"; + + public static final String VALUE_YES = "yes"; + + public static final String VALUE_NO = "no"; + + public static final String VALUE_1 = "1"; + + public static final String VALUE_0 = "0"; + + private String trueString; + + private String falseString; + + public TextToBoolean() { + } + + public TextToBoolean(String trueString, String falseString) { + this.trueString = trueString; + this.falseString = falseString; + } + + public Class[] getSourceClasses() { + return new Class[] { String.class }; + } + + public Class[] getTargetClasses() { + return new Class[] { Boolean.class }; + } + + protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception { + String text = (String) source; + if (!StringUtils.hasText(text)) { + return null; + } + else if (this.trueString != null && text.equalsIgnoreCase(this.trueString)) { + return Boolean.TRUE; + } + else if (this.falseString != null && text.equalsIgnoreCase(this.falseString)) { + return Boolean.FALSE; + } + else if (this.trueString == null + && (text.equalsIgnoreCase(VALUE_TRUE) || text.equalsIgnoreCase(VALUE_ON) + || text.equalsIgnoreCase(VALUE_YES) || text.equals(VALUE_1))) { + return Boolean.TRUE; + } + else if (this.falseString == null + && (text.equalsIgnoreCase(VALUE_FALSE) || text.equalsIgnoreCase(VALUE_OFF) + || text.equalsIgnoreCase(VALUE_NO) || text.equals(VALUE_0))) { + return Boolean.FALSE; + } + else { + throw new IllegalArgumentException("Invalid boolean value [" + text + "]"); + } + } + } + + static final class BooleanToText extends AbstractConverter { + + public static final String VALUE_YES = "yes"; + + public static final String VALUE_NO = "no"; + + private String trueString; + + private String falseString; + + public BooleanToText() { + } + + public BooleanToText(String trueString, String falseString) { + this.trueString = trueString; + this.falseString = falseString; + } + + public Class[] getSourceClasses() { + return new Class[] { Boolean.class }; + } + + public Class[] getTargetClasses() { + return new Class[] { String.class }; + } + + protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception { + Boolean bool = (Boolean) source; + if (this.trueString != null && bool.booleanValue()) { + return trueString; + } + else if (this.falseString != null && !bool.booleanValue()) { + return falseString; + } + else if (bool.booleanValue()) { + return VALUE_YES; + } + else { + return VALUE_NO; + } + } + } +} \ No newline at end of file Modified: trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/PageComponentContext.java =================================================================== --- trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/PageComponentContext.java 2006-11-22 06:33:18 UTC (rev 1572) +++ trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/PageComponentContext.java 2006-11-22 06:34:37 UTC (rev 1573) @@ -26,6 +26,11 @@ public ActionCommandExecutor getLocalCommandExecutor(String commandId); + /** + * Register a local handler for a global command. + * @param commandId the global command id + * @param localExecutor the local handler + */ public void register(String commandId, ActionCommandExecutor localExecutor); } \ No newline at end of file Modified: trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/support/DefaultApplicationServices.java =================================================================== --- trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/support/DefaultApplicationServices.java 2006-11-22 06:33:18 UTC (rev 1572) +++ trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/support/DefaultApplicationServices.java 2006-11-22 06:34:37 UTC (rev 1573) @@ -38,7 +38,7 @@ import org.springframework.richclient.application.ApplicationPageFactory; import org.springframework.richclient.application.ApplicationServices; import org.springframework.richclient.application.ApplicationWindowFactory; -import org.springframework.richclient.application.DefaultConversionService; +import org.springframework.richclient.application.DefaultConversionServiceFactoryBean; import org.springframework.richclient.application.PageComponentPaneFactory; import org.springframework.richclient.application.ViewDescriptorRegistry; import org.springframework.richclient.application.config.ApplicationObjectConfigurer; @@ -868,7 +868,7 @@ protected static final ImplBuilder conversionServiceImplBuilder = new ImplBuilder() { public Object build( DefaultApplicationServices applicationServices ) { logger.info( "Creating default service impl: ConversionService" ); - return new DefaultConversionService(); + return new DefaultConversionServiceFactoryBean().getConversionService(); } }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys - and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ spring-rich-c-cvs mailing list spring-rich-c-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spring-rich-c-cvs