Author: alexsmirnov
Date: 2010-10-28 21:43:38 -0400 (Thu, 28 Oct 2010)
New Revision: 19749
Added:
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/validator/BeanValidatorFactory.java
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/BeanValidatorDescriptor.java
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/BeanValidatorServiceImpl.java
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/RichFacesBeanValidatorFactory.java
Modified:
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/el/ValueDescriptor.java
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/el/CapturingELContext.java
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/el/ValueExpressionAnalayserImpl.java
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/el/ValueExpressionAnalayserTest.java
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/el/model/Bean.java
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/validator/BeanValidatorServiceConstrainsTest.java
Log:
CODING IN PROGRESS - issue RF-9510: BeanValidatorService tests and implementation
https://jira.jboss.org/browse/RF-9510
Modified:
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/el/ValueDescriptor.java
===================================================================
---
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/el/ValueDescriptor.java 2010-10-28
20:31:56 UTC (rev 19748)
+++
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/el/ValueDescriptor.java 2010-10-29
01:43:38 UTC (rev 19749)
@@ -11,9 +11,7 @@
public class ValueDescriptor {
private final String name;
-
- private final boolean readOnly;
-
+
private final Class<?> beanType;
private final Class<?> propertyType;
@@ -24,15 +22,14 @@
* @param propertyType
* @param readOnly
*/
- ValueDescriptor(Class<?> beanType, String name, Class<?> propertyType,
boolean readOnly) {
+ public ValueDescriptor(Class<?> beanType, String name, Class<?>
propertyType) {
this.beanType = beanType;
this.name = name;
this.propertyType = propertyType;
- this.readOnly = readOnly;
}
- ValueDescriptor(Class<?> beanType, String name) {
- this(beanType,name,Object.class,false);
+ public ValueDescriptor(Class<?> beanType, String name) {
+ this(beanType,name,Object.class);
}
/**
@@ -42,12 +39,6 @@
return name;
}
- /**
- * @return the readOnly
- */
- public boolean isReadOnly() {
- return readOnly;
- }
/**
* @return the beanType
Added:
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/validator/BeanValidatorFactory.java
===================================================================
---
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/validator/BeanValidatorFactory.java
(rev 0)
+++
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/validator/BeanValidatorFactory.java 2010-10-29
01:43:38 UTC (rev 19749)
@@ -0,0 +1,17 @@
+/**
+ *
+ */
+package org.richfaces.validator;
+
+import javax.faces.context.FacesContext;
+import javax.validation.Validator;
+
+/**
+ * @author asmirnov
+ *
+ */
+public interface BeanValidatorFactory {
+
+ Validator getValidator(FacesContext context);
+
+}
Property changes on:
branches/RF-8742/ui/validator/api/src/main/java/org/richfaces/validator/BeanValidatorFactory.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:eol-style
+ native
Modified:
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/el/CapturingELContext.java
===================================================================
---
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/el/CapturingELContext.java 2010-10-28
20:31:56 UTC (rev 19748)
+++
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/el/CapturingELContext.java 2010-10-29
01:43:38 UTC (rev 19749)
@@ -118,7 +118,7 @@
context.setPropertyResolved(true);
reference = new ValueReference(base, property, reference);
}
- return Object.class;
+ return delegate.getType(context, base, property);
}
@Override
Modified:
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/el/ValueExpressionAnalayserImpl.java
===================================================================
---
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/el/ValueExpressionAnalayserImpl.java 2010-10-28
20:31:56 UTC (rev 19748)
+++
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/el/ValueExpressionAnalayserImpl.java 2010-10-29
01:43:38 UTC (rev 19749)
@@ -1,20 +1,25 @@
package org.richfaces.el;
+import javax.el.ELException;
import javax.el.ValueExpression;
import javax.faces.context.FacesContext;
public class ValueExpressionAnalayserImpl implements ValueExpressionAnalayser {
- public ValueDescriptor getPropertyDescriptor(FacesContext context, ValueExpression
expression) {
+ public ValueDescriptor getPropertyDescriptor(FacesContext context, ValueExpression
expression) throws ELException {
+ if(null == context || null == expression){
+ throw new NullPointerException();
+ }
CapturingELContext capturingContext = new
CapturingELContext(context.getELContext());
- expression.getType(capturingContext);
+ Class<?> type = expression.getType(capturingContext);
ValueReference reference = capturingContext.getReference();
if(null != reference && null != reference.getBase() && null !=
reference.getProperty()){
// TODO - detect arrays, maps and lists. Check JSF implementation code -
seems that Mojarra dosn't validate such fields.
- ValueDescriptor descriptor = new
ValueDescriptor(reference.getBase().getClass(),reference.getProperty().toString());
+ ValueDescriptor descriptor = new
ValueDescriptor(reference.getBase().getClass(),reference.getProperty().toString(),type);
return descriptor;
+ } else {
+ throw new ELException("Cannot determine property for expression
"+expression.getExpressionString());
}
- return null;
}
}
Added:
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/BeanValidatorDescriptor.java
===================================================================
---
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/BeanValidatorDescriptor.java
(rev 0)
+++
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/BeanValidatorDescriptor.java 2010-10-29
01:43:38 UTC (rev 19749)
@@ -0,0 +1,13 @@
+package org.richfaces.validator;
+
+import java.lang.annotation.Annotation;
+
+import javax.faces.application.FacesMessage;
+
+public class BeanValidatorDescriptor extends BaseFacesObjectDescriptor<Annotation>
implements ValidatorDescriptor {
+
+ public BeanValidatorDescriptor(Class<? extends Annotation> validatorClass,
FacesMessage message) {
+ super(validatorClass, message);
+ }
+
+}
Property changes on:
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/BeanValidatorDescriptor.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/BeanValidatorServiceImpl.java
===================================================================
---
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/BeanValidatorServiceImpl.java
(rev 0)
+++
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/BeanValidatorServiceImpl.java 2010-10-29
01:43:38 UTC (rev 19749)
@@ -0,0 +1,85 @@
+/**
+ *
+ */
+package org.richfaces.validator;
+
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.el.ELException;
+import javax.el.ValueExpression;
+import javax.faces.context.FacesContext;
+import javax.validation.Validator;
+import javax.validation.metadata.ConstraintDescriptor;
+
+import org.richfaces.el.ValueDescriptor;
+import org.richfaces.el.ValueExpressionAnalayser;
+
+/**
+ * @author asmirnov
+ *
+ */
+public class BeanValidatorServiceImpl implements BeanValidatorService {
+
+ private final ValueExpressionAnalayser analayser;
+ private final BeanValidatorFactory validatorFactory;
+
+ public BeanValidatorServiceImpl(ValueExpressionAnalayser analayser,
BeanValidatorFactory validatorFactory) {
+ this.analayser = analayser;
+ this.validatorFactory = validatorFactory;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
org.richfaces.validator.BeanValidatorService#getConstrains(javax.faces.context.FacesContext,
+ * javax.el.ValueExpression, java.lang.Class<?>[])
+ */
+ public Collection<ValidatorDescriptor> getConstrains(FacesContext context,
ValueExpression expression,
+ Class<?>... groups) {
+ try {
+ ValueDescriptor propertyDescriptor = analayser.getPropertyDescriptor(context,
expression);
+ return processBeanAttribute(context, propertyDescriptor, groups);
+ } catch (ELException e) {
+ return Collections.emptySet();
+ }
+ }
+
+ private Validator getValidator(FacesContext context) {
+ return validatorFactory.getValidator(context);
+ }
+
+ Collection<ValidatorDescriptor> processBeanAttribute(FacesContext context,
ValueDescriptor descriptor,
+ Class<?>... groups) {
+ Set<ConstraintDescriptor<?>> constraints = getValidator(context)
+
.getConstraintsForClass(descriptor.getBeanType()).getConstraintsForProperty(descriptor.getName())
+ .findConstraints().unorderedAndMatchingGroups(groups) // or the requested
list of groups)
+ .getConstraintDescriptors();
+
+ // ContextHolder is an arbitrary object, it will depend on the implementation
+ Set<ValidatorDescriptor> descriptors = new
HashSet<ValidatorDescriptor>(constraints.size());
+ processConstraints(context, constraints, descriptors);
+ return descriptors;
+ }
+
+ void processConstraints(FacesContext context,
Set<ConstraintDescriptor<?>> constraints,
+ Collection<ValidatorDescriptor> descriptors) {
+ for (ConstraintDescriptor cd : constraints) {
+ Annotation a = cd.getAnnotation();
+ Map<String, Object> parameters = cd.getAttributes();
+ // TODO if cd.isReportedAsSingleConstraint() make sure than only the root
constraint raises an error message
+ // if one or several of the composing constraints are invalid)
+ BeanValidatorDescriptor beanValidatorDescriptor = new
BeanValidatorDescriptor(a.getClass(), null);
+ for (Map.Entry<String, Object> entry : parameters.entrySet()) {
+ beanValidatorDescriptor.addParameter(entry.getKey(), entry.getValue());
+ }
+ beanValidatorDescriptor.makeImmutable();
+ descriptors.add(beanValidatorDescriptor);
+ processConstraints(context, cd.getComposingConstraints(), descriptors); //
process the composing constraints
+ }
+ }
+}
Property changes on:
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/BeanValidatorServiceImpl.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/RichFacesBeanValidatorFactory.java
===================================================================
---
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/RichFacesBeanValidatorFactory.java
(rev 0)
+++
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/RichFacesBeanValidatorFactory.java 2010-10-29
01:43:38 UTC (rev 19749)
@@ -0,0 +1,72 @@
+/**
+ *
+ */
+package org.richfaces.validator;
+
+import java.util.Locale;
+
+import javax.faces.context.FacesContext;
+import javax.validation.MessageInterpolator;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import javax.validation.ValidatorContext;
+import javax.validation.ValidatorFactory;
+
+/**
+ * @author asmirnov
+ *
+ */
+public class RichFacesBeanValidatorFactory implements BeanValidatorFactory {
+
+ private ValidatorFactory validatorFactory;
+ private ValidatorContext validatorContext;
+
+ public RichFacesBeanValidatorFactory() {
+ // Enforce class to load
+ ValidatorFactory.class.getName();
+ // Check Factory, to avoid instantiation errors
+ //
https://jira.jboss.org/jira/browse/RF-7226
+ validatorFactory = Validation.buildDefaultValidatorFactory();
+ validatorContext = validatorFactory.usingContext();
+ MessageInterpolator jsfMessageInterpolator =
+ new JsfMessageInterpolator(validatorFactory.getMessageInterpolator());
+ validatorContext.messageInterpolator(jsfMessageInterpolator);
+ }
+
+ /* (non-Javadoc)
+ * @see
org.richfaces.validator.BeanValidatorFactory#getValidator(javax.faces.context.FacesContext)
+ */
+ public Validator getValidator(FacesContext context) {
+ return validatorContext.getValidator();
+ }
+
+ private static class JsfMessageInterpolator implements MessageInterpolator {
+
+ private MessageInterpolator delegate;
+
+ public JsfMessageInterpolator(MessageInterpolator delegate) {
+ this.delegate = delegate;
+ }
+
+ public String interpolate(String messageTemplate, Context context) {
+
+ Locale locale =
ObjectValidator.calculateLocale(FacesContext.getCurrentInstance());
+ if (null != locale) {
+ return delegate.interpolate(messageTemplate, context, locale);
+ } else {
+ return delegate.interpolate(messageTemplate, context);
+ }
+ }
+
+ public String interpolate(String messageTemplate, Context context, Locale locale)
{
+ Locale faceslocale =
ObjectValidator.calculateLocale(FacesContext.getCurrentInstance());
+ if (null != faceslocale) {
+ return delegate.interpolate(messageTemplate, context, faceslocale);
+ } else {
+ return delegate.interpolate(messageTemplate, context, locale);
+ }
+ }
+
+ }
+
+}
Property changes on:
branches/RF-8742/ui/validator/impl/src/main/java/org/richfaces/validator/RichFacesBeanValidatorFactory.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:eol-style
+ native
Modified:
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/el/ValueExpressionAnalayserTest.java
===================================================================
---
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/el/ValueExpressionAnalayserTest.java 2010-10-28
20:31:56 UTC (rev 19748)
+++
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/el/ValueExpressionAnalayserTest.java 2010-10-29
01:43:38 UTC (rev 19749)
@@ -1,17 +1,57 @@
package org.richfaces.el;
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.*;
+
+import javax.el.ELException;
+import javax.el.ValueExpression;
+import javax.faces.context.FacesContext;
+
+import org.jboss.test.faces.mock.FacesMock;
+import org.jboss.test.faces.mock.Mock;
+import org.jboss.test.faces.mock.MockTestRunner;
import org.junit.After;
import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.richfaces.el.model.Bean;
-public class ValueExpressionAnalayserTest {
+(a)RunWith(MockTestRunner.class)
+public class ValueExpressionAnalayserTest extends ELTestBase {
+
+
+ private ValueExpressionAnalayser analayser;
+
+ @Mock
+ private FacesContext facesContext;
@Before
- public void setUp() throws Exception {
+ public void setUpAnalayser() throws Exception {
+ analayser = new ValueExpressionAnalayserImpl();
}
@After
- public void tearDown() throws Exception {
+ public void tearDownAnalayser() throws Exception {
+ analayser = null;
}
-
+ @Test
+ public void testGetDescriptionPositive() throws Exception {
+ ValueExpression expression = parse("#{bean.string}");
+ expect(facesContext.getELContext()).andReturn(elContext);
+ FacesMock.replay(facesContext);
+ ValueDescriptor propertyDescriptor =
analayser.getPropertyDescriptor(facesContext, expression);
+ assertEquals(Bean.class, propertyDescriptor.getBeanType());
+ assertEquals("string", propertyDescriptor.getName());
+ assertEquals(String.class,propertyDescriptor.getPropertyType());
+ FacesMock.verify(facesContext);
+ }
+
+ @Test(expected=ELException.class)
+ public void testGetDescriptionNegative() throws Exception {
+ ValueExpression expression = parse("#{bean}");
+ expect(facesContext.getELContext()).andReturn(elContext);
+ FacesMock.replay(facesContext);
+ ValueDescriptor propertyDescriptor =
analayser.getPropertyDescriptor(facesContext, expression);
+ }
}
Modified:
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/el/model/Bean.java
===================================================================
---
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/el/model/Bean.java 2010-10-28
20:31:56 UTC (rev 19748)
+++
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/el/model/Bean.java 2010-10-29
01:43:38 UTC (rev 19749)
@@ -4,6 +4,8 @@
import java.util.List;
import java.util.Map;
+import javax.validation.constraints.Size;
+
public class Bean {
private List<String> list;
@@ -28,6 +30,7 @@
this.map = map;
}
+ @Size(max=2)
public String getString() {
return string;
}
Modified:
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/validator/BeanValidatorServiceConstrainsTest.java
===================================================================
---
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/validator/BeanValidatorServiceConstrainsTest.java 2010-10-28
20:31:56 UTC (rev 19748)
+++
branches/RF-8742/ui/validator/impl/src/test/java/org/richfaces/validator/BeanValidatorServiceConstrainsTest.java 2010-10-29
01:43:38 UTC (rev 19749)
@@ -1,17 +1,94 @@
package org.richfaces.validator;
+import static junit.framework.Assert.assertEquals;
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.*;
+
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+
+import javax.el.ValueExpression;
+import javax.validation.constraints.Size;
+
+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;
+import org.richfaces.el.ValueDescriptor;
+import org.richfaces.el.ValueExpressionAnalayser;
+import org.richfaces.el.model.Bean;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+
+(a)RunWith(MockTestRunner.class)
public class BeanValidatorServiceConstrainsTest {
+
+ @Mock
+ @Environment(Feature.EL_CONTEXT)
+ private MockFacesEnvironment environment;
+
+ @Mock
+ private ValueExpression expression;
+
+ @Mock
+ private ValueExpressionAnalayser analayser;
+
+ private MockController controller;
+ private BeanValidatorServiceImpl validatorService;
+
+
@Before
public void setUp() throws Exception {
+ validatorService = new BeanValidatorServiceImpl(analayser);
}
@After
public void tearDown() throws Exception {
+ validatorService = null;
}
+
+ @Test
+ public void testGetSingleValidator() throws Exception {
+ forProperty(Bean.class,
"string");expectValidatorWithParameter(Size.class,"max",2);
+ }
+
+ @Test
+ public void testGetNoValidator() throws Exception {
+ forProperty(Bean.class, "list");expectValidators();
+ }
+ private void forProperty(Class<?> beanClass,String property){
+ expect(analayser.getPropertyDescriptor(environment.getFacesContext(),
expression)).andReturn(new ValueDescriptor(beanClass,property));
+ }
+
+ private void expectValidatorWithParameter(Class<? extends Annotation>
validator,String param,Object value) {
+ Collection<ValidatorDescriptor> validators = expectValidators(validator);
+ ValidatorDescriptor validatorDescriptor = Iterables.getOnlyElement(validators);
+ assertTrue(validatorDescriptor.getAdditionalParameters().containsKey(param));
+ assertEquals(value, validatorDescriptor.getAdditionalParameters().get(param));
+ }
+ private Collection<ValidatorDescriptor> expectValidators(Class<? extends
Annotation>... validators) {
+ controller.replay();
+ Collection<ValidatorDescriptor> constrains =
validatorService.getConstrains(environment.getFacesContext(), expression);
+ controller.verify();
+ assertEquals(validators.length, constrains.size());
+ for (final Class<? extends Annotation> class1 : validators) {
+ Iterables.find(constrains, new Predicate<ValidatorDescriptor>(){
+ public boolean apply(ValidatorDescriptor input) {
+ return class1.equals(input.getImplementationClass());
+ }
+
+ });
+ }
+ return constrains;
+ }
}