You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2011/05/16 23:08:05 UTC
svn commit: r1103891 - in /myfaces/tomahawk/trunk/sandbox/core20: ./
src/main/java/org/apache/myfaces/custom/validatebeanbehavior/
Author: lu4242
Date: Mon May 16 21:08:04 2011
New Revision: 1103891
URL: http://svn.apache.org/viewvc?rev=1103891&view=rev
Log:
TOMAHAWK-1497 New component: ValidateBeanBehavior (thanks to Jan-Kees van Andel for provide this patch)
Added:
myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/
myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ComponentUtils.java
myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ELContextDecorator.java
myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ExternalSpecifications.java
myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/FacesMessageInterpolatorHolder.java
myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/UIMessagesWrapper.java
myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidateBeanBehavior.java
myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidationPropertyModel.java
myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceResolver.java
myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceWrapper.java
Modified:
myfaces/tomahawk/trunk/sandbox/core20/pom.xml
Modified: myfaces/tomahawk/trunk/sandbox/core20/pom.xml
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/pom.xml?rev=1103891&r1=1103890&r2=1103891&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/pom.xml (original)
+++ myfaces/tomahawk/trunk/sandbox/core20/pom.xml Mon May 16 21:08:04 2011
@@ -34,11 +34,13 @@
<scope>compile</scope>
</dependency>
+ <!--
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<scope>compile</scope>
</dependency>
+ -->
<dependency>
<groupId>commons-logging</groupId>
@@ -59,16 +61,34 @@
</dependency>
<dependency>
+ <groupId>javax.validation</groupId>
+ <artifactId>validation-api</artifactId>
+ <version>1.0.0.GA</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.el</groupId>
+ <artifactId>el-api</artifactId>
+ <version>2.1.2-b05</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <!--
+ <dependency>
<groupId>commons-el</groupId>
<artifactId>commons-el</artifactId>
<scope>compile</scope>
</dependency>
+ -->
+ <!--
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<scope>compile</scope>
</dependency>
+ -->
<dependency>
<groupId>commons-lang</groupId>
@@ -76,18 +96,22 @@
<scope>compile</scope>
</dependency>
+ <!--
<dependency>
<groupId>portlet-api</groupId>
<artifactId>portlet-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
-
+ -->
+
+ <!--
<dependency>
<groupId>poi</groupId>
<artifactId>poi</artifactId>
<scope>compile</scope>
</dependency>
+ -->
<!-- provided dependencies -->
@@ -111,12 +135,13 @@
<version>2.5</version>
<scope>provided</scope>
</dependency>
-
+<!--
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<scope>compile</scope>
</dependency>
+ -->
<dependency>
<groupId>org.apache.myfaces.buildtools</groupId>
@@ -132,10 +157,14 @@
</dependency>
-->
+ <!--
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
- </dependency>
+ </dependency>
+ -->
+
+
<!-- test dependencies -->
@@ -153,27 +182,9 @@
</dependency>
<dependency>
- <groupId>org.apache.shale</groupId>
- <artifactId>shale-test</artifactId>
- <scope>test</scope>
- <exclusions>
- <exclusion>
- <groupId>org.apache.myfaces</groupId>
- <artifactId>myfaces-api</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.apache.myfaces</groupId>
- <artifactId>myfaces-impl</artifactId>
- </exclusion>
- <exclusion>
- <groupId>myfaces</groupId>
- <artifactId>myfaces-api</artifactId>
- </exclusion>
- <exclusion>
- <groupId>myfaces</groupId>
- <artifactId>myfaces-impl</artifactId>
- </exclusion>
- </exclusions>
+ <groupId>org.apache.myfaces.test</groupId>
+ <artifactId>myfaces-test20</artifactId>
+ <scope>test</scope>
</dependency>
</dependencies>
@@ -186,9 +197,11 @@
<exclude>**/*.vm</exclude>
</excludes>
</resource>
+ <!--
<resource>
<directory>target/tomahawk12_resources</directory>
</resource>
+ -->
</resources>
<plugins>
<plugin>
Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ComponentUtils.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ComponentUtils.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ComponentUtils.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ComponentUtils.java Mon May 16 21:08:04 2011
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.myfaces.custom.validatebeanbehavior;
+
+import javax.faces.FacesException;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIForm;
+import javax.faces.component.UIInput;
+import javax.faces.component.UIMessages;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Common component tree utilities.
+ *
+ * @author Jan-Kees van Andel
+ */
+final class ComponentUtils {
+
+ /**
+ * Find and return the parent form for the given component.
+ *
+ * @param component The component.
+ * @return The parent form, never <code>null</code>.
+ * @throws FacesException if no parent form is found.
+ */
+ static UIForm findParentForm(UIComponent component) {
+ while (component.getParent() != null) {
+ component = component.getParent();
+ if (component instanceof UIForm) {
+ return (UIForm) component;
+ }
+ }
+ throw new FacesException("No parent form found");
+ }
+
+ /**
+ * Find and return all UIInput instances in the given form.
+ * <p/>
+ * This method doesn't care about nesting. It looks through the entire form and returns all UIInput components.
+ *
+ * @param form The form to search in.
+ * @return A list with all UIInput components in the form, never <code>null</code>. If nothing is found,
+ * an empty {java.util.List} is returned.
+ */
+ static List<UIInput> findInputsInForm(UIForm form) {
+ return findInputsInTree(form);
+ }
+
+ /**
+ * Find all UIInput instances that are children of the given component tree.
+ *
+ * @param component The component tree to search in.
+ * @return A list with all UIInput components in the component, never <code>null</code>. If nothing is found,
+ * an empty {java.util.List} is returned.
+ */
+ private static List<UIInput> findInputsInTree(final UIComponent component) {
+ final List<UIInput> ret = new ArrayList<UIInput>();
+
+ if (component != null) {
+ final List<UIComponent> children = component.getChildren();
+ for (final UIComponent child : children) {
+ if (child instanceof UIInput) {
+ ret.add((UIInput) child);
+ } else {
+ ret.addAll(findInputsInTree(child));
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ /**
+ * Find the first UIMessages instance in the given component tree.
+ *
+ * @param component The component tree to search in.
+ * @return The first UIMessages instance, or <code>null</code> if nothing is found.
+ */
+ static UIMessages findMessagesInTree(final UIComponent component) {
+ final List<UIComponent> children = component.getChildren();
+ for (final UIComponent child : children) {
+ if (child instanceof UIMessages) {
+ return (UIMessages) child;
+ } else {
+ final UIMessages messages = findMessagesInTree(child);
+ if (messages != null) {
+ return messages;
+ }
+ }
+ }
+ return null;
+ }
+}
Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ELContextDecorator.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ELContextDecorator.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ELContextDecorator.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ELContextDecorator.java Mon May 16 21:08:04 2011
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.myfaces.custom.validatebeanbehavior;
+
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import javax.el.FunctionMapper;
+import javax.el.VariableMapper;
+import java.util.Locale;
+
+/**
+ * This ELContext is used to hook into the EL handling, by decorating the
+ * ELResolver chain with a custom ELResolver.
+ *
+ * Note: Copy from MyFaces Core 2.0.
+ *
+ * @author Jan-Kees van Andel
+ */
+final class ELContextDecorator extends ELContext {
+ private final ELContext ctx;
+ private final ELResolver interceptingResolver;
+
+ /**
+ * Only used by ValueExpressionResolver.
+ *
+ * @param elContext The standard ELContext. All method calls, except getELResolver, are delegated to it.
+ * @param interceptingResolver The ELResolver to be returned by getELResolver.
+ */
+ ELContextDecorator(final ELContext elContext, final ELResolver interceptingResolver) {
+ this.ctx = elContext;
+ this.interceptingResolver = interceptingResolver;
+ }
+
+ /**
+ * This is the important one, it returns the passed ELResolver.
+ *
+ * @return The ELResolver passed into the constructor.
+ */
+ @Override
+ public final ELResolver getELResolver() {
+ return interceptingResolver;
+ }
+
+ // ############################ Standard delegating implementations ############################
+
+ public final FunctionMapper getFunctionMapper() {
+ return ctx.getFunctionMapper();
+ }
+
+ public final VariableMapper getVariableMapper() {
+ return ctx.getVariableMapper();
+ }
+
+ public final void setPropertyResolved(final boolean resolved) {
+ ctx.setPropertyResolved(resolved);
+ }
+
+ public final boolean isPropertyResolved() {
+ return ctx.isPropertyResolved();
+ }
+
+ public final void putContext(final Class key, Object contextObject) {
+ ctx.putContext(key, contextObject);
+ }
+
+ public final Object getContext(final Class key) {
+ return ctx.getContext(key);
+ }
+
+ public final Locale getLocale() {
+ return ctx.getLocale();
+ }
+
+ public final void setLocale(final Locale locale) {
+ ctx.setLocale(locale);
+ }
+}
Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ExternalSpecifications.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ExternalSpecifications.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ExternalSpecifications.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ExternalSpecifications.java Mon May 16 21:08:04 2011
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.myfaces.custom.validatebeanbehavior;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.el.ELContext;
+import javax.validation.Validation;
+import javax.validation.Validator;
+
+/**
+ * <p>
+ * Utility class for determining which specifications are available
+ * in the current process. See JIRA issue: http://issues.apache.org/jira/browse/MYFACES-2386
+ * </p>
+ *
+ * Note: Copy from MyFaces Core 2.0.
+ *
+ * @author Jan-Kees van Andel
+ * @author Jakob Korherr (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ * @since 2.0
+ */
+final class ExternalSpecifications {
+
+ //private static final Log log = LogFactory.getLog(BeanValidator.class);
+ private static final Logger log = Logger.getLogger(ExternalSpecifications.class.getName());
+
+ private static Boolean beanValidationAvailable;
+ private static Boolean unifiedELAvailable;
+
+ /**
+ * Static inner class to prevent NoClassDefFoundErrors when Bean Validation is not available.
+ */
+ private static final class ValidationHolder {
+ static boolean trialErrorValidationInitialization() {
+ try {
+ // Trial-error approach to check for Bean Validation impl existence.
+ // If any Exception occurs here, we assume that Bean Validation is not available.
+ // The cause may be anything, i.e. NoClassDef, config error...
+ final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
+
+ return validator != null;
+ } catch (Throwable t) {
+ log.log(Level.FINE, "Error initializing Bean Validation (could be normal)", t);
+ return false;
+ }
+
+ }
+ }
+
+ /**
+ * This method determines if Bean Validation is present.
+ * <p/>
+ * Eager initialization is used for performance. This means Bean Validation binaries
+ * should not be added at runtime after this variable has been set.
+ *
+ * @return true if Bean Validation is available, false otherwise.
+ */
+ static synchronized boolean isBeanValidationAvailable() {
+ if (beanValidationAvailable == null) {
+ try {
+ beanValidationAvailable = (Class.forName("javax.validation.Validation") != null);
+
+ if (beanValidationAvailable) {
+ beanValidationAvailable = ValidationHolder.trialErrorValidationInitialization();
+ }
+ } catch (Throwable t) {
+ log.log(Level.FINE, "Error loading class (could be normal)", t);
+ beanValidationAvailable = false;
+ }
+
+ log.info("MyFaces Bean Validation support " + (beanValidationAvailable ? "enabled" : "disabled"));
+ }
+ return beanValidationAvailable;
+ }
+
+ /**
+ * This method determines if Unified EL is present.
+ * <p/>
+ * Eager initialization is used for performance. This means Unified EL binaries
+ * should not be added at runtime after this variable has been set.
+ *
+ * @return true if UEL is available, false otherwise.
+ */
+ static synchronized boolean isUnifiedELAvailable() {
+ if (unifiedELAvailable == null) {
+ try {
+ // Check if the UEL classes are available.
+ // If the JSP EL classes are loaded first, UEL will not work
+ // properly, hence it will be disabled.
+ unifiedELAvailable = (
+ Class.forName("javax.el.ValueReference") != null
+ && Class.forName("javax.el.ValueExpression")
+ .getMethod("getValueReference", ELContext.class) != null
+ );
+ } catch (Throwable t) {
+ log.log(Level.FINE, "Error loading class (could be normal)", t);
+ unifiedELAvailable = false;
+ }
+
+ log.info("MyFaces Unified EL support " + (unifiedELAvailable ? "enabled" : "disabled"));
+ }
+ return unifiedELAvailable;
+ }
+
+ /**
+ * this class should not be instantiated.
+ */
+ private ExternalSpecifications() {
+ }
+
+}
Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/FacesMessageInterpolatorHolder.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/FacesMessageInterpolatorHolder.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/FacesMessageInterpolatorHolder.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/FacesMessageInterpolatorHolder.java Mon May 16 21:08:04 2011
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.myfaces.custom.validatebeanbehavior;
+
+import javax.faces.context.FacesContext;
+import javax.validation.MessageInterpolator;
+import javax.validation.ValidatorFactory;
+import java.util.Locale;
+
+/**
+ * Holder class to prevent NoClassDefFoundError in environments without Bean Validation.
+ * <p/>
+ * This is needed, because holder classes are loaded lazily. This means that when it's not
+ * used, it will not be loaded, parsed and initialized. The BeanValidator class is used always,
+ * so the MessageInterpolator references need to be in this separate class.
+ */
+final class FacesMessageInterpolatorHolder {
+
+ // Needs to be volatile.
+ private static volatile FacesMessageInterpolator instance;
+
+ /**
+ * Helper method for initializing the FacesMessageInterpolator.
+ * <p/>
+ * It uses the "Single Check Idiom" as described in Joshua Bloch's Effective Java 2nd Edition.
+ *
+ * @param validatorFactory Used to obtain the MessageInterpolator.
+ * @return The instantiated MessageInterpolator for BeanValidator.
+ */
+ static MessageInterpolator get(final ValidatorFactory validatorFactory) {
+ FacesMessageInterpolatorHolder.FacesMessageInterpolator ret = instance;
+ if (ret == null) {
+ final MessageInterpolator interpolator = validatorFactory.getMessageInterpolator();
+ instance = ret = new FacesMessageInterpolator(interpolator);
+ }
+ return ret;
+ }
+
+ /**
+ * Standard MessageInterpolator, as described in the JSR-314 spec.
+ */
+ private static class FacesMessageInterpolator implements MessageInterpolator {
+ private final MessageInterpolator interpolator;
+
+ FacesMessageInterpolator(final MessageInterpolator interpolator) {
+ this.interpolator = interpolator;
+ }
+
+ public String interpolate(final String s, final Context context) {
+ final Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
+ return interpolator.interpolate(s, context, locale);
+ }
+
+ public String interpolate(final String s, final Context context, final Locale locale) {
+ return interpolator.interpolate(s, context, locale);
+ }
+ }
+}
Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/UIMessagesWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/UIMessagesWrapper.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/UIMessagesWrapper.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/UIMessagesWrapper.java Mon May 16 21:08:04 2011
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.myfaces.custom.validatebeanbehavior;
+
+import java.io.IOException;
+
+import javax.faces.component.UIComponentBase;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
+
+/**
+ * Wrapper component for UIMessages, to make sure there always is a messages placeholder in the DOM.
+ *
+ * @author Jan-Kees van Andel
+ */
+@JSFComponent
+public class UIMessagesWrapper extends UIComponentBase {
+
+ /**
+ * The component type for this component.
+ */
+ public static final String COMPONENT_TYPE = "org.apache.myfaces.custom.validatebeanbehavior.UIMessagesWrapper";
+
+ /**
+ * The component family for this component.
+ */
+ public static final String COMPONENT_FAMILY = "org.apache.myfaces.custom.MessagesWrapper";
+
+ @Override
+ public String getFamily() {
+ return COMPONENT_FAMILY;
+ }
+
+ @Override
+ public void encodeBegin(FacesContext context) throws IOException {
+ super.encodeBegin(context);
+
+ final ResponseWriter writer = context.getResponseWriter();
+ writer.write("<div id=\"");
+ writer.write(getClientId());
+ writer.write("\">");
+ }
+
+ @Override
+ public void encodeEnd(FacesContext context) throws IOException {
+ final ResponseWriter writer = context.getResponseWriter();
+ writer.write("</div>");
+
+ super.encodeEnd(context);
+ }
+}
Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidateBeanBehavior.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidateBeanBehavior.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidateBeanBehavior.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidateBeanBehavior.java Mon May 16 21:08:04 2011
@@ -0,0 +1,331 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.myfaces.custom.validatebeanbehavior;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import javax.el.ELContext;
+import javax.el.ValueExpression;
+import javax.el.ValueReference;
+import javax.faces.FacesException;
+import javax.faces.application.ResourceDependency;
+import javax.faces.component.UICommand;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIForm;
+import javax.faces.component.UIInput;
+import javax.faces.component.UIMessages;
+import javax.faces.component.UIViewRoot;
+import javax.faces.component.behavior.ClientBehaviorBase;
+import javax.faces.component.behavior.ClientBehaviorContext;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.DateTimeConverter;
+import javax.servlet.ServletContext;
+import javax.validation.Validation;
+import javax.validation.ValidatorFactory;
+import javax.validation.constraints.Future;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import javax.validation.metadata.BeanDescriptor;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFClientBehavior;
+
+/**
+ * Behavior for Bean Validation validations in JavaScript.
+ * <p/>
+ * This class can be attached to UIComponent instances and validate the entire form.
+ * Any UIMessages instances in the form are looked up and used for positioning error messages.
+ *
+ * @author Jan-Kees van Andel
+ */
+@JSFClientBehavior(
+ name="s:validateBean",
+ id="org.apache.myfaces.custom.ValidateBeanBehavior")
+@ResourceDependency(name = "validateBeanBehavior.js")
+public class ValidateBeanBehavior extends ClientBehaviorBase {
+
+ /** {@inheritDoc} */
+ @Override
+ public String getScript(final ClientBehaviorContext ctx) {
+ final UIComponent component = ctx.getComponent();
+ if (!(component instanceof UICommand)) {
+ throw new FacesException("Unsupported component: " + component + " Only UICommand components are supported");
+ }
+ final UIViewRoot viewRoot = ctx.getFacesContext().getViewRoot();
+
+ UIForm form = ComponentUtils.findParentForm(component);
+ List<UIInput> inputsInForm = ComponentUtils.findInputsInForm(form);
+ UIMessages messages = ComponentUtils.findMessagesInTree(viewRoot);
+
+ return getSubmitHandler(form, inputsInForm, messages);
+ }
+
+ /**
+ * Fetch all necessary metadata and write a JavaScript submit handler to the client.
+ *
+ * @param form The form which must be validated.
+ * @param inputsInForm The input fields in the form.
+ * @param messages The messages to use for displaying error messages.
+ * @return The JavaScript submit handler call.
+ */
+ private String getSubmitHandler(final UIForm form, final List<UIInput> inputsInForm, final UIMessages messages) {
+ final FacesContext fc = FacesContext.getCurrentInstance();
+
+ final String clientId = form.getClientId(fc);
+ final String messagesId = (messages != null) ? "'" + messages.getClientId(fc) + "'": "null";
+ final List<ValidationPropertyModel> validations = new ArrayList<ValidationPropertyModel>();
+
+ for (final UIInput input : inputsInForm) {
+ final PropertyDescriptor propertyDescriptor = getPropertyDescriptor(fc, input);
+ final Set<ConstraintDescriptor<?>> constraints = propertyDescriptor.getConstraintDescriptors();
+ final ValidationPropertyModel model = createValidationModel(input, propertyDescriptor, constraints);
+ validations.add(model);
+ }
+
+ return writeJavaScript(fc, clientId, messagesId, validations);
+ }
+
+ /**
+ * Write the JavaScript submit handler to the client.
+ *
+ * @param fc The FacesContext.
+ * @param clientId The client ID of the form.
+ * @param messagesId The client ID of the messages component.
+ * @param validations The list with field validations.
+ * @return The JavaScript event handler string.
+ */
+ private String writeJavaScript(final FacesContext fc, final String clientId,
+ final String messagesId, final List<ValidationPropertyModel> validations) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("return org.jkva.validateBean.validateForm(");
+ sb.append("'").append(clientId).append("', ");
+ sb.append("'").append(messagesId).append("', ");
+ sb.append("[");
+ String sep = "";
+
+ for (final ValidationPropertyModel validationModel : validations) {
+ sb.append(sep);
+ final String validation = writeJavaScriptForField(validationModel, fc);
+ sb.append(validation);
+ sep = ",";
+ }
+
+ sb.append("])");
+ return sb.toString();
+ }
+
+ /**
+ * Write a JSON object with all validation metadata for the given field.
+ *
+ * @param model The validation metadata for a field.
+ * @param fc The FacesContext.
+ * @return The JavaScript event handler string, as a JSON object.
+ */
+ private String writeJavaScriptForField(final ValidationPropertyModel model, final FacesContext fc) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("{");
+ sb.append("fieldId: '").append(model.getComponent().getClientId(fc)).append("'");
+ if (model.isRequired()) {
+ sb.append(",required: true");
+ }
+ sb.append(",type: '").append(model.getType()).append("'");
+ if (model.getMin() != null) {
+ sb.append(",min: true");
+ sb.append(",minValue: ").append(model.getMin()).append("");
+ }
+ if (model.getMax() != null) {
+ sb.append(",max: true");
+ sb.append(",maxValue: ").append(model.getMax()).append("");
+ }
+ if (model.isFutureDate()) {
+ String nowStr = new SimpleDateFormat(model.getDateFormat()).format(new Date());
+ sb.append(",future: true");
+ sb.append(",nowStr: '").append(nowStr).append("'");
+ sb.append(",dateFormat: '").append(model.getDateFormat()).append("'");
+ }
+ sb.append("}");
+
+ return sb.toString();
+ }
+
+ /**
+ * Create the Validation metadata, by inspecting the component, managed bean and {ConstraintDescriptor}s.
+ *
+ * @param component The input component.
+ * @param propertyDescriptor The property descriptor
+ * @param constraints The constraint descriptors.
+ * @return The validation metadata.
+ */
+ private ValidationPropertyModel createValidationModel(final UIComponent component,
+ final PropertyDescriptor propertyDescriptor,
+ final Set<ConstraintDescriptor<?>> constraints) {
+ final ValidationPropertyModel model = new ValidationPropertyModel();
+ model.setComponent(component);
+
+ if (component instanceof UIInput) {
+ model.setRequired(((UIInput) component).isRequired());
+ }
+
+ final Class<?> type = propertyDescriptor.getElementClass();
+ if (type.equals(String.class)) {
+ model.setType("text");
+ } else if (Number.class.isAssignableFrom(type)) {
+ model.setType("numeric");
+ } else if (Date.class.isAssignableFrom(type)
+ || Calendar.class.isAssignableFrom(type)) {
+ model.setType("date");
+ }
+
+ for (final ConstraintDescriptor<?> constraint : constraints) {
+ final Annotation annotation = constraint.getAnnotation();
+ if (annotation instanceof NotNull) {
+ model.setRequired(true);
+ } else if (annotation instanceof Min) {
+ model.setMin(((Min) annotation).value());
+ } else if (annotation instanceof Max) {
+ model.setMax(((Max) annotation).value());
+ } else if (annotation instanceof Future) {
+ model.setFutureDate(true);
+ }
+ }
+
+ final Converter converter = ((UIInput) component).getConverter();
+ if (converter instanceof DateTimeConverter) {
+ model.setDateFormat(((DateTimeConverter) converter).getPattern());
+ }
+
+ return model;
+ }
+
+ // Copied from MyFaces Core 2.0.
+ private PropertyDescriptor getPropertyDescriptor(final FacesContext fc, final UIComponent component) {
+ final ValueReferenceWrapper reference = getValueReference(component, fc);
+
+ if (reference != null) {
+ final Object base = reference.getBase();
+ if (base != null) {
+ final Class<?> valueBaseClass = base.getClass();
+ final String valueProperty = (String) reference.getProperty();
+ if (valueBaseClass != null && valueProperty != null) {
+ // Initialize Bean Validation.
+ final ValidatorFactory validatorFactory = createValidatorFactory(fc);
+ final javax.validation.Validator validator = createValidator(validatorFactory);
+ final BeanDescriptor beanDescriptor = validator.getConstraintsForClass(valueBaseClass);
+ if (beanDescriptor.isBeanConstrained()) {
+ return beanDescriptor.getConstraintsForProperty(valueProperty);
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ // Copied from MyFaces Core 2.0.
+ private javax.validation.Validator createValidator(final ValidatorFactory validatorFactory) {
+ return validatorFactory //
+ .usingContext() //
+ .messageInterpolator(FacesMessageInterpolatorHolder.get(validatorFactory)) //
+ .getValidator();
+
+ }
+
+ // Copied from MyFaces Core 2.0.
+ private ValueReferenceWrapper getValueReference(final UIComponent component, final FacesContext context) {
+ final ValueExpression valueExpression = component.getValueExpression("value");
+ final ELContext elCtx = context.getELContext();
+ if (ExternalSpecifications.isUnifiedELAvailable()) {
+ final ValueReference valueReference = getUELValueReference(valueExpression, elCtx);
+ if (valueReference == null) {
+ return null;
+ }
+ return new ValueReferenceWrapper(valueReference.getBase(), valueReference.getProperty());
+ } else {
+ return ValueReferenceResolver.resolve(valueExpression, elCtx);
+ }
+ }
+
+ // Copied from MyFaces Core 2.0.
+ private ValueReference getUELValueReference(final ValueExpression valueExpression, final ELContext elCtx) {
+ final String methodName = "getValueReference";
+ final String methodSignature = valueExpression.getClass().getName() +
+ "." + methodName +
+ "(" + ELContext.class + ")";
+ try {
+ final Method method = valueExpression.getClass().getMethod(methodName, ELContext.class);
+ if (!ValueReference.class.equals(method.getReturnType())
+ && !ValueReference.class.isAssignableFrom(method.getReturnType())) {
+ throw new NoSuchMethodException(
+ methodSignature +
+ "doesn't return " + ValueReference.class +
+ ", but " + method.getReturnType());
+ }
+ return (ValueReference) method.invoke(valueExpression, elCtx);
+ } catch (NoSuchMethodException e) {
+ throw new FacesException(
+ "MyFaces indicates Unified EL is available, but method: " +
+ methodSignature +
+ " is not available", e);
+ } catch (InvocationTargetException e) {
+ throw new FacesException("Exception invoking " + methodSignature, e);
+ } catch (IllegalAccessException e) {
+ throw new FacesException("Exception invoking " + methodSignature, e);
+ }
+ }
+
+ // Copied from MyFaces Core 2.0.
+ private synchronized ValidatorFactory createValidatorFactory(final FacesContext context) {
+ final Object ctx = context.getExternalContext().getContext();
+ if (ctx instanceof ServletContext) {
+ final ServletContext servletCtx = (ServletContext) ctx;
+ final Object attr = servletCtx.getAttribute(VALIDATOR_FACTORY_KEY);
+ if (attr != null) {
+ return (ValidatorFactory) attr;
+ } else {
+ if (ExternalSpecifications.isBeanValidationAvailable()) {
+ final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
+ servletCtx.setAttribute(VALIDATOR_FACTORY_KEY, attr);
+ return factory;
+ } else {
+ throw new FacesException(
+ "Bean Validation (API or implementation) is not present, but required for " +
+ this.getClass().getSimpleName());
+ }
+ }
+ } else {
+ throw new FacesException("Only Servlet environments are supported for " +
+ this.getClass().getSimpleName());
+ }
+ }
+
+ // Copied from MyFaces Core 2.0.
+ public static final String VALIDATOR_FACTORY_KEY = "javax.faces.validator.beanValidator.ValidatorFactory";
+}
+
Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidationPropertyModel.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidationPropertyModel.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidationPropertyModel.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValidationPropertyModel.java Mon May 16 21:08:04 2011
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.myfaces.custom.validatebeanbehavior;
+
+import javax.faces.component.UIComponent;
+
+/**
+ * This class contains all validation related properties for a single UIInput component.
+ *
+ * @author Jan-Kees van Andel
+ */
+final class ValidationPropertyModel {
+
+ /**
+ * Is this field required?
+ */
+ private boolean required;
+
+ /**
+ * The type of the field, for syntactic validation.
+ */
+ private String type;
+
+ /**
+ * The minimum and maximum value of a number.
+ */
+ private Long min, max;
+
+ /**
+ * A validator that checks if a date is in the future. Today is not considered a future date.
+ */
+ private boolean futureDate;
+
+ /**
+ * The format (SimpleDateFormat pattern) of a date field.
+ */
+ private String dateFormat;
+
+ /**
+ * The corresponding component.
+ */
+ private UIComponent component;
+
+ public boolean isRequired() {
+ return required;
+ }
+
+ public void setRequired(boolean required) {
+ this.required = required;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public Long getMin() {
+ return min;
+ }
+
+ public void setMin(Long min) {
+ this.min = min;
+ }
+
+ public Long getMax() {
+ return max;
+ }
+
+ public void setMax(Long max) {
+ this.max = max;
+ }
+
+ public boolean isFutureDate() {
+ return futureDate;
+ }
+
+ public void setFutureDate(boolean futureDate) {
+ this.futureDate = futureDate;
+ }
+
+ public String getDateFormat() {
+ return dateFormat;
+ }
+
+ public void setDateFormat(String dateFormat) {
+ this.dateFormat = dateFormat;
+ }
+
+ public UIComponent getComponent() {
+ return component;
+ }
+
+ public void setComponent(UIComponent component) {
+ this.component = component;
+ }
+}
Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceResolver.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceResolver.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceResolver.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceResolver.java Mon May 16 21:08:04 2011
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.myfaces.custom.validatebeanbehavior;
+
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import javax.el.ValueExpression;
+import java.beans.FeatureDescriptor;
+import java.util.Iterator;
+
+/**
+ * This class inspects the EL expression and returns a ValueReferenceWrapper
+ * when Unified EL is not available.
+ *
+ * Note: Copy from MyFaces Core 2.0.
+ */
+final class ValueReferenceResolver extends ELResolver {
+ private final ELResolver resolver;
+
+ /**
+ * This is a simple solution to keep track of the resolved objects,
+ * since ELResolver provides no way to know if the current ELResolver
+ * is the last one in the chain. By assigning (and effectively overwriting)
+ * this field, we know that the value after invoking the chain is always
+ * the last one.
+ * <p/>
+ * This solution also deals with nested objects (like: #{myBean.prop.prop.prop}.
+ */
+ private ValueReferenceWrapper lastObject;
+
+ /**
+ * Constructor is only used internally.
+ *
+ * @param elResolver An ELResolver from the current ELContext.
+ */
+ ValueReferenceResolver(final ELResolver elResolver) {
+ this.resolver = elResolver;
+ }
+
+ /**
+ * This method can be used to extract the ValueReferenceWrapper from the given ValueExpression.
+ *
+ * @param valueExpression The ValueExpression to resolve.
+ * @param elCtx The ELContext, needed to parse and execute the expression.
+ * @return The ValueReferenceWrapper.
+ */
+ public static ValueReferenceWrapper resolve(final ValueExpression valueExpression, final ELContext elCtx) {
+ final ValueReferenceResolver resolver = new ValueReferenceResolver(elCtx.getELResolver());
+ valueExpression.getValue(new ELContextDecorator(elCtx, resolver));
+ return resolver.lastObject;
+ }
+
+ /**
+ * This method is the only one that matters. It keeps track of the objects in the EL expression.
+ * <p/>
+ * It creates a new ValueReferenceWrapper and assigns it to lastObject.
+ *
+ * @param context The ELContext.
+ * @param base The base object, may be null.
+ * @param property The property, may be null.
+ * @return The resolved value
+ */
+ @Override
+ public Object getValue(final ELContext context, final Object base, final Object property) {
+ lastObject = new ValueReferenceWrapper(base, property);
+ return resolver.getValue(context, base, property);
+ }
+
+ // ############################ Standard delegating implementations ############################
+
+ public final Class<?> getType(final ELContext ctx, final Object base, final Object property) {
+ return resolver.getType(ctx, base, property);
+ }
+
+ public final void setValue(final ELContext ctx, final Object base, final Object property, final Object value) {
+ resolver.setValue(ctx, base, property, value);
+ }
+
+ public final boolean isReadOnly(final ELContext ctx, final Object base, final Object property) {
+ return resolver.isReadOnly(ctx, base, property);
+ }
+
+ public final Iterator<FeatureDescriptor> getFeatureDescriptors(final ELContext ctx, final Object base) {
+ return resolver.getFeatureDescriptors(ctx, base);
+ }
+
+ public final Class<?> getCommonPropertyType(final ELContext ctx, final Object base) {
+ return resolver.getCommonPropertyType(ctx, base);
+ }
+
+}
Added: myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceWrapper.java?rev=1103891&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceWrapper.java (added)
+++ myfaces/tomahawk/trunk/sandbox/core20/src/main/java/org/apache/myfaces/custom/validatebeanbehavior/ValueReferenceWrapper.java Mon May 16 21:08:04 2011
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.myfaces.custom.validatebeanbehavior;
+
+/**
+ * This class provides access to the object pointed to by the EL expression.
+ * <p/>
+ * It makes the BeanValidator work when Unified EL is not available.
+ *
+ * Note: Copy from MyFaces Core 2.0.
+ */
+final class ValueReferenceWrapper {
+ private final Object base, property;
+
+ /**
+ * Full constructor.
+ *
+ * @param base The object the reference points to.
+ * @param property The property the reference points to.
+ */
+ public ValueReferenceWrapper(final Object base, final Object property) {
+ this.base = base;
+ this.property = property;
+ }
+
+ /**
+ * The object the reference points to.
+ *
+ * @return base.
+ */
+ public final Object getBase() {
+ return base;
+ }
+
+ /**
+ * The property the reference points to.
+ *
+ * @return property.
+ */
+ public final Object getProperty() {
+ return property;
+ }
+}