Author: alexsmirnov
Date: 2010-10-27 19:34:28 -0400 (Wed, 27 Oct 2010)
New Revision: 19718
Added:
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/validator/ValidatorDescriptor.java
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/ConverterDescriptorImpl.java
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/ConverterServiceImpl.java
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/MessageFactory.java
Modified:
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/validator/FacesValidatorService.java
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/application/ValidatorModule.java
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/validator/FacesConverterServiceTest.java
branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/component/behavior/BehaviorGetValidatorTest.java
Log:
RESOLVED - issue RF-9520: ConverterService unit tests and implementation
https://jira.jboss.org/browse/RF-9520
Modified:
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/validator/FacesValidatorService.java
===================================================================
---
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/validator/FacesValidatorService.java 2010-10-27
23:29:43 UTC (rev 19717)
+++
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/validator/FacesValidatorService.java 2010-10-27
23:34:28 UTC (rev 19718)
@@ -6,5 +6,5 @@
public interface FacesValidatorService {
- FacesObjectDescriptor getValidatorDescription(FacesContext context,Validator
validator);
+ ValidatorDescriptor getValidatorDescription(FacesContext context,Validator
validator);
}
Added:
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/validator/ValidatorDescriptor.java
===================================================================
---
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/validator/ValidatorDescriptor.java
(rev 0)
+++
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/validator/ValidatorDescriptor.java 2010-10-27
23:34:28 UTC (rev 19718)
@@ -0,0 +1,12 @@
+/**
+ *
+ */
+package org.richfaces.validator;
+
+/**
+ * @author asmirnov
+ *
+ */
+public interface ValidatorDescriptor extends FacesObjectDescriptor {
+
+}
Property changes on:
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/validator/ValidatorDescriptor.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:eol-style
+ native
Modified:
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/application/ValidatorModule.java
===================================================================
---
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/application/ValidatorModule.java 2010-10-27
23:29:43 UTC (rev 19717)
+++
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/application/ValidatorModule.java 2010-10-27
23:34:28 UTC (rev 19718)
@@ -26,6 +26,8 @@
import javax.validation.ValidationException;
import org.richfaces.validator.BeanValidator;
+import org.richfaces.validator.ConverterServiceImpl;
+import org.richfaces.validator.FacesConverterService;
import org.richfaces.validator.NullValidator;
import org.richfaces.validator.ObjectValidator;
@@ -46,7 +48,7 @@
*/
public void configure(ServicesFactory factory) {
factory.setInstance(ObjectValidator.class, createInstance());
-
+ factory.setInstance(FacesConverterService.class, new ConverterServiceImpl());
}
/**
Added:
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/ConverterDescriptorImpl.java
===================================================================
---
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/ConverterDescriptorImpl.java
(rev 0)
+++
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/ConverterDescriptorImpl.java 2010-10-27
23:34:28 UTC (rev 19718)
@@ -0,0 +1,61 @@
+/**
+ *
+ */
+package org.richfaces.validator;
+
+import java.util.Map;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.convert.Converter;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+
+/**
+ * @author asmirnov
+ *
+ */
+public class ConverterDescriptorImpl implements ConverterDescriptor {
+
+
+ private final Class<? extends Converter> converterClass;
+
+ private Map<String, Object> parameters = Maps.newHashMap();
+
+ private final FacesMessage message;
+
+ ConverterDescriptorImpl(Class<? extends Converter> converterClass,FacesMessage
message) {
+ this.converterClass = converterClass;
+ this.message = message;
+
+ }
+ /* (non-Javadoc)
+ * @see org.richfaces.validator.FacesObjectDescriptor#getImplementationClass()
+ */
+ public Class<?> getImplementationClass() {
+ return converterClass;
+ }
+
+ /* (non-Javadoc)
+ * @see org.richfaces.validator.FacesObjectDescriptor#getAdditionalParameters()
+ */
+ public Map<String, ? extends Object> getAdditionalParameters() {
+ return parameters;
+ }
+
+ /* (non-Javadoc)
+ * @see org.richfaces.validator.FacesObjectDescriptor#getMessage()
+ */
+ public FacesMessage getMessage() {
+ return message;
+ }
+
+ void addParameter(String name, Object value){
+ parameters.put(name, value);
+ }
+
+ void makeImmutable(){
+ parameters = ImmutableMap.copyOf(parameters);
+ }
+
+}
Property changes on:
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/ConverterDescriptorImpl.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:eol-style
+ native
Added:
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/ConverterServiceImpl.java
===================================================================
---
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/ConverterServiceImpl.java
(rev 0)
+++
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/ConverterServiceImpl.java 2010-10-27
23:34:28 UTC (rev 19718)
@@ -0,0 +1,132 @@
+/**
+ *
+ */
+package org.richfaces.validator;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIInput;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.BigDecimalConverter;
+import javax.faces.convert.BigIntegerConverter;
+import javax.faces.convert.BooleanConverter;
+import javax.faces.convert.ByteConverter;
+import javax.faces.convert.CharacterConverter;
+import javax.faces.convert.Converter;
+import javax.faces.convert.DateTimeConverter;
+import javax.faces.convert.DoubleConverter;
+import javax.faces.convert.EnumConverter;
+import javax.faces.convert.FloatConverter;
+import javax.faces.convert.IntegerConverter;
+import javax.faces.convert.LongConverter;
+import javax.faces.convert.NumberConverter;
+import javax.faces.convert.ShortConverter;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author asmirnov
+ *
+ */
+public class ConverterServiceImpl implements FacesConverterService {
+
+ private static final String DEFAULT_CONVERTER_MESSAGE_ID =
UIInput.CONVERSION_MESSAGE_ID;
+
+ private static final ImmutableSet<String> HIDDEN_PROPERTIES =
ImmutableSet.of("class", "transient");
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
org.richfaces.validator.FacesConverterService#getConverterDescription(javax.faces.context.FacesContext,
+ * javax.faces.convert.Converter)
+ */
+ public ConverterDescriptor getConverterDescription(FacesContext context, Converter
converter) {
+ // determine converter message.
+ FacesMessage message = getConverterMessage(context, converter);
+ ConverterDescriptorImpl descriptor = new
ConverterDescriptorImpl(converter.getClass(), message);
+ fillConverterParameters(descriptor, converter);
+ descriptor.makeImmutable();
+ return descriptor;
+ }
+
+ private void fillConverterParameters(ConverterDescriptorImpl descriptor, Converter
converter) {
+ // get bean attributes for converter, put them into parameters.
+ try {
+ BeanInfo beanInfo = Introspector.getBeanInfo(converter.getClass());
+ PropertyDescriptor[] propertyDescriptors =
beanInfo.getPropertyDescriptors();
+ for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
+ String name = propertyDescriptor.getName();
+ if (!HIDDEN_PROPERTIES.contains(name)) {
+ try {
+ Object value =
propertyDescriptor.getReadMethod().invoke(converter);
+ if (null != value) {
+ descriptor.addParameter(name, value);
+ }
+ } catch (IllegalArgumentException e) {
+ // Ignore
+ } catch (IllegalAccessException e) {
+ // Ignore
+ } catch (InvocationTargetException e) {
+ // Ignore
+ }
+ }
+ }
+ } catch (IntrospectionException e) {
+ // Ignore.
+ }
+ }
+
+ /**
+ * Creates message for converter, using current locale.
+ *
+ * @param context
+ * @param converter
+ * @return
+ */
+ private FacesMessage getConverterMessage(FacesContext context, Converter converter)
{
+ String messageId = getMessageId(converter);
+ return MessageFactory.createMessage(context, messageId);
+ }
+
+ private String getMessageId(Converter converter) {
+ String messageId;
+ if (converter instanceof BigDecimalConverter) {
+ messageId = BigDecimalConverter.DECIMAL_ID;
+ } else if (converter instanceof BigIntegerConverter) {
+ messageId = BigIntegerConverter.BIGINTEGER_ID;
+ } else if (converter instanceof BooleanConverter) {
+ messageId = BooleanConverter.BOOLEAN_ID;
+ } else if (converter instanceof ByteConverter) {
+ messageId = ByteConverter.BYTE_ID;
+ } else if (converter instanceof CharacterConverter) {
+ messageId = CharacterConverter.CHARACTER_ID;
+ } else if (converter instanceof DateTimeConverter) {
+ // TODO - distinguish Date, Time, and DateTime.
+ messageId = DateTimeConverter.DATETIME_ID;
+ } else if (converter instanceof DoubleConverter) {
+ messageId = DoubleConverter.DOUBLE_ID;
+ } else if (converter instanceof EnumConverter) {
+ messageId = EnumConverter.ENUM_ID;
+ } else if (converter instanceof FloatConverter) {
+ messageId = FloatConverter.FLOAT_ID;
+ } else if (converter instanceof IntegerConverter) {
+ messageId = IntegerConverter.INTEGER_ID;
+ } else if (converter instanceof LongConverter) {
+ messageId = LongConverter.LONG_ID;
+ } else if (converter instanceof NumberConverter) {
+ // TODO - detect case ( currency, percent etc ).
+ messageId = NumberConverter.NUMBER_ID;
+ } else if (converter instanceof ShortConverter) {
+ messageId = ShortConverter.SHORT_ID;
+ } else {
+ messageId = DEFAULT_CONVERTER_MESSAGE_ID;
+ }
+ return messageId;
+ }
+
+}
Property changes on:
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/ConverterServiceImpl.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:eol-style
+ native
Added:
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/MessageFactory.java
===================================================================
---
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/MessageFactory.java
(rev 0)
+++
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/MessageFactory.java 2010-10-27
23:34:28 UTC (rev 19718)
@@ -0,0 +1,75 @@
+/**
+ *
+ */
+package org.richfaces.validator;
+
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+
+/**
+ * @author asmirnov
+ *
+ */
+public final class MessageFactory {
+
+ private MessageFactory(){}
+
+ public static FacesMessage createMessage(FacesContext context, String messageId) {
+ Locale locale = getCurrentLocale(context);
+ String messageBundle = context.getApplication().getMessageBundle();
+ FacesMessage message;
+ try {
+ if (null != messageBundle) {
+ try {
+ message = getMessageFromBundle(locale, messageBundle, messageId);
+ } catch (MissingResourceException e) {
+ message = getMessageFromBundle(locale, FacesMessage.FACES_MESSAGES,
messageId);
+ }
+ } else {
+ message = getMessageFromBundle(locale, FacesMessage.FACES_MESSAGES,
messageId);
+ }
+ } catch (MissingResourceException e) {
+ // No bundles at all, fall back message.
+ return new FacesMessage("conversion error");
+ }
+ return message;
+ }
+
+ private static FacesMessage getMessageFromBundle(Locale locale, String messageBundle,
String messageId)
+ throws MissingResourceException {
+ ResourceBundle bundle = ResourceBundle.getBundle(messageBundle, locale,
getCurrentLoader(messageId));
+ String summary = bundle.getString(messageId);
+ String detail;
+ try {
+ detail = bundle.getString(messageId + "_detail");
+ } catch (MissingResourceException e) {
+ return new FacesMessage(summary);
+ }
+ return new FacesMessage(summary, detail);
+ }
+
+ private static Locale getCurrentLocale(FacesContext context) {
+ UIViewRoot viewRoot = context.getViewRoot();
+ Locale locale;
+ if (null == viewRoot) {
+ locale = Locale.getDefault();
+ } else {
+ locale = viewRoot.getLocale();
+ }
+ return locale;
+ }
+
+ private static ClassLoader getCurrentLoader(Object fallbackClass) {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ if (loader == null) {
+ loader = fallbackClass.getClass().getClassLoader();
+ }
+ return loader;
+ }
+
+}
Property changes on:
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/MessageFactory.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:eol-style
+ native
Modified:
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/validator/FacesConverterServiceTest.java
===================================================================
---
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/validator/FacesConverterServiceTest.java 2010-10-27
23:29:43 UTC (rev 19717)
+++
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/validator/FacesConverterServiceTest.java 2010-10-27
23:34:28 UTC (rev 19718)
@@ -1,37 +1,109 @@
package org.richfaces.validator;
-import static org.junit.Assert.*;
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
-import javax.faces.context.FacesContext;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIInput;
+import javax.faces.component.UIViewRoot;
+import javax.faces.convert.BooleanConverter;
import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+import javax.faces.convert.DateTimeConverter;
+import javax.faces.convert.IntegerConverter;
+import javax.faces.render.ClientBehaviorRenderer;
+import org.jboss.test.faces.mock.Environment;
+import org.jboss.test.faces.mock.Environment.Feature;
+import org.jboss.test.faces.mock.Mock;
+import org.jboss.test.faces.mock.MockController;
+import org.jboss.test.faces.mock.MockFacesEnvironment;
+import org.jboss.test.faces.mock.MockTestRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
-
+(a)RunWith(MockTestRunner.class)
public class FacesConverterServiceTest {
- FacesConverterService serviceImpl;
-
- Converter converter;
+ @Mock()
+ @Environment({ Feature.APPLICATION })
+ protected MockFacesEnvironment environment;
+ protected FacesConverterService serviceImpl;
+ @Mock
+ protected UIViewRoot viewRoot;
+ @Mock
+ protected UIInput input;
+ @Mock
+ protected ClientBehaviorRenderer behaviorRenderer;
+ protected MockController controller;
+ protected Converter converter;
- private FacesContext context;
@Before
public void setUp() {
// create service impl.
+ serviceImpl = new ConverterServiceImpl();
+ expect(environment.getFacesContext().getViewRoot()).andStubReturn(viewRoot);
+ expect(viewRoot.getLocale()).andStubReturn(Locale.ENGLISH);
+
expect(environment.getApplication().getMessageBundle()).andStubReturn("com.sun.faces.resources.Messages");
+ HashMap<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put("label", "foo");
+ expect(input.getAttributes()).andStubReturn(attributes);
}
@After
public void tearDown() {
+ controller.verify();
serviceImpl = null;
}
@Test
- public void getConverterDescription() throws Exception {
- ConverterDescriptor converterDescription =
serviceImpl.getConverterDescription(context, converter);
+ public void getConverterClass() throws Exception {
+ converter = new BooleanConverter();
+ controller.replay();
+ ConverterDescriptor converterDescription =
serviceImpl.getConverterDescription(environment.getFacesContext(), converter);
assertEquals(converter.getClass(),
converterDescription.getImplementationClass());
}
+ @Test
+ public void getConverterMessage() throws Exception {
+ converter = new IntegerConverter();
+ FacesMessage facesMessage = null;
+ controller.replay();
+ try{
+ converter.getAsObject(environment.getFacesContext(), input,
"abc");
+ } catch(ConverterException e){
+ facesMessage = e.getFacesMessage();
+ }
+ assertNotNull(facesMessage);
+ ConverterDescriptor converterDescription =
serviceImpl.getConverterDescription(environment.getFacesContext(), converter);
+ String summary = converterDescription.getMessage().getSummary();
+ summary = summary.replace("{2}", "foo");
+ summary = summary.replace("'{0}'", "abc");
+ assertEquals(facesMessage.getSummary(), summary);
+ }
+
+ @Test
+ public void getConverterParameters() throws Exception {
+ DateTimeConverter converter = new DateTimeConverter();
+
+ converter.setDateStyle("short");
+ converter.setPattern("MM/DD/YYYY");
+ converter.setTimeStyle("full");
+ converter.setType("both");
+ converter.setTimeZone(TimeZone.getTimeZone("EST"));
+ controller.replay();
+ ConverterDescriptor converterDescription =
serviceImpl.getConverterDescription(environment.getFacesContext(), converter);
+ Map<String, ? extends Object> additionalParameters =
converterDescription.getAdditionalParameters();
+ assertEquals("short",
additionalParameters.get("dateStyle"));
+ assertEquals("MM/DD/YYYY",
additionalParameters.get("pattern"));
+ }
}
Modified:
branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/component/behavior/BehaviorGetValidatorTest.java
===================================================================
---
branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/component/behavior/BehaviorGetValidatorTest.java 2010-10-27
23:29:43 UTC (rev 19717)
+++
branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/component/behavior/BehaviorGetValidatorTest.java 2010-10-27
23:34:28 UTC (rev 19718)
@@ -23,6 +23,7 @@
import org.richfaces.validator.BeanValidatorService;
import org.richfaces.validator.FacesValidatorService;
import org.richfaces.validator.FacesObjectDescriptor;
+import org.richfaces.validator.ValidatorDescriptor;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@@ -104,7 +105,7 @@
private void setupComponentValidator(Validator... validators) {
expect(input.getValidators()).andStubReturn(validators);
for (Validator validator : validators) {
- FacesObjectDescriptor validatorDescriptor =
environment.createMock(FacesObjectDescriptor.class);
+ ValidatorDescriptor validatorDescriptor =
environment.createMock(ValidatorDescriptor.class);
expect((Class)
validatorDescriptor.getImplementationClass()).andStubReturn(validator.getClass());
expect(validatorDescriptor.getMessage()).andStubReturn(VALIDATION_ERROR);
expect(facesValidatorService.getValidatorDescription(environment.getFacesContext(),
validator))