IN PROGRESS - issue SWF-388: Extract all JSF-related code into a separate component project

http://opensource.atlassian.com/projects/spring/browse/SWF-388
This commit is contained in:
Jeremy Grelle
2007-08-16 20:37:09 +00:00
parent c162d6f094
commit 972663fe1a
217 changed files with 118 additions and 51 deletions

View File

@@ -0,0 +1,163 @@
/*
* Copyright 2004-2007 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.faces.el;
import javax.faces.el.EvaluationException;
import javax.faces.el.PropertyNotFoundException;
import javax.faces.el.PropertyResolver;
import javax.faces.el.ReferenceSyntaxException;
import org.springframework.webflow.execution.FlowExecution;
/**
* Base class for property resolvers that get and set flow execution attributes.
*
* @author Keith Donald
*/
public abstract class AbstractFlowExecutionPropertyResolver extends PropertyResolver {
/**
* The standard property resolver to delegate to if this one doesn't apply.
*/
private final PropertyResolver resolverDelegate;
/**
* Creates a new flow executon property resolver
* @param resolverDelegate the resolver to delegate to when the property is not a flow execution attribute
*/
public AbstractFlowExecutionPropertyResolver(PropertyResolver resolverDelegate) {
this.resolverDelegate = resolverDelegate;
}
/**
* Returns the property resolver this resolver delegates to if necessary.
*/
protected final PropertyResolver getResolverDelegate() {
return resolverDelegate;
}
public Class getType(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
if (base instanceof FlowExecution) {
FlowExecution execution = (FlowExecution) base;
assertPropertyNameValid(property);
return doGetAttributeType(execution, (String) property);
} else {
return resolverDelegate.getType(base, property);
}
}
public Class getType(Object base, int index) throws EvaluationException, PropertyNotFoundException {
if (base instanceof FlowExecution) {
// cannot access flow execution by index so we cannot determine type. Return null per JSF spec
return null;
} else {
return resolverDelegate.getType(base, index);
}
}
public Object getValue(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
if (base instanceof FlowExecution) {
FlowExecution execution = (FlowExecution) base;
assertPropertyNameValid(property);
return doGetAttribute(execution, (String) property);
} else {
return resolverDelegate.getValue(base, property);
}
}
public Object getValue(Object base, int index) throws EvaluationException, PropertyNotFoundException {
if (base instanceof FlowExecution) {
throw new ReferenceSyntaxException("Cannot apply an index value to a flow execution");
} else {
return resolverDelegate.getValue(base, index);
}
}
public boolean isReadOnly(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
if (base instanceof FlowExecution) {
return false;
} else {
return resolverDelegate.isReadOnly(base, property);
}
}
public boolean isReadOnly(Object base, int index) throws EvaluationException, PropertyNotFoundException {
if (base instanceof FlowExecution) {
return false;
} else {
return resolverDelegate.isReadOnly(base, index);
}
}
public void setValue(Object base, Object property, Object value) throws EvaluationException,
PropertyNotFoundException {
if ((base instanceof FlowExecution)) {
FlowExecution execution = (FlowExecution) base;
assertPropertyNameValid(property);
doSetAttribute(execution, (String) property, value);
} else {
resolverDelegate.setValue(base, property, value);
}
}
public void setValue(Object base, int index, Object value) throws EvaluationException, PropertyNotFoundException {
if (base instanceof FlowExecution) {
throw new ReferenceSyntaxException("Cannot apply an index value to a flow execution");
} else {
resolverDelegate.setValue(base, index, value);
}
}
// helpers
private void assertPropertyNameValid(Object property) {
if (property == null) {
throw new PropertyNotFoundException("The name of the flow execution attribute cannot be null");
}
if (!(property instanceof String)) {
throw new PropertyNotFoundException("Flow execution attribute names must be strings but " + property
+ " was not");
}
if (((String) property).length() == 0) {
throw new PropertyNotFoundException("The name of the flow execution attribute cannot be blank");
}
}
/**
* Gets the type of value returned by the flow execution attribute.
* @param execution the flow execution
* @param attributeName the name of the attribute
* @return the type of value returned by the attribute
*/
protected abstract Class doGetAttributeType(FlowExecution execution, String attributeName);
/**
* Gets the value of the flow execution attribute.
* @param execution the flow execution
* @param attributeName the name of the attribute
* @return the attribute value
*/
protected abstract Object doGetAttribute(FlowExecution execution, String attributeName);
/**
* Sets the value of the flow execution attribute.
* @param execution the flow execution
* @param attributeName the name of the attribute
* @param attributeValue the attribute value
*/
protected abstract void doSetAttribute(FlowExecution execution, String attributeName, Object attributeValue);
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2004-2007 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.faces.el;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.VariableResolver;
import org.springframework.faces.webflow.FlowExecutionHolderUtils;
import org.springframework.web.jsf.DelegatingVariableResolver;
import org.springframework.webflow.execution.FlowExecution;
/**
* Custom variable resolver that searches the current flow execution for variables to resolve. The search algorithm
* looks in flash scope first, then flow scope, then conversation scope. If no variable is found this resolver delegates
* to the next resolver in the chain.
*
* Suitable for use along side other variable resolvers to support EL binding expressions like {#bean.property} where
* "bean" could be a property in any supported scope.
*
* Consider combining use of this class with a Spring {@link DelegatingVariableResolver} to also support
* lazy-initialized binding variables managed by a Spring application context using custom bean scopes. Also consider
* such a Spring-backed managed bean facility as the sole-provider for centralized JSF managed bean references.
*
* @author Keith Donald
*/
public class DelegatingFlowVariableResolver extends VariableResolver {
/**
* The standard variable resolver to delegate to if this one doesn't apply.
*/
private VariableResolver resolverDelegate;
/**
* Create a new FlowExecutionVariableResolver, using the given original VariableResolver.
* <p>
* A JSF implementation will automatically pass its original resolver into the constructor of a configured resolver,
* provided that there is a corresponding constructor argument.
*
* @param resolverDelegate the original VariableResolver
*/
public DelegatingFlowVariableResolver(VariableResolver resolverDelegate) {
this.resolverDelegate = resolverDelegate;
}
/**
* Return the original VariableResolver that this resolver delegates to.
*/
protected final VariableResolver getResolverDelegate() {
return resolverDelegate;
}
public Object resolveVariable(FacesContext context, String name) throws EvaluationException {
FlowExecution execution = FlowExecutionHolderUtils.getCurrentFlowExecution(context);
if (execution != null) {
if (execution.isActive()) {
// flow execution is active: try flash/flow/conversation scope
if (execution.getActiveSession().getFlashMap().contains(name)) {
return execution.getActiveSession().getFlashMap().get(name);
} else if (execution.getActiveSession().getScope().contains(name)) {
return execution.getActiveSession().getScope().get(name);
} else if (execution.getConversationScope().contains(name)) {
return execution.getConversationScope().get(name);
}
} else {
// flow execution has ended: check for end-state attributes exposed in the request map
if (context.getExternalContext().getRequestMap().containsKey(name)) {
return context.getExternalContext().getRequestMap().get(name);
}
}
}
// no flow execution bound or flow execution attribute found with that name - delegate
return resolverDelegate.resolveVariable(context, name);
}
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright 2004-2007 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.faces.el;
import java.util.Map;
import javax.faces.el.PropertyNotFoundException;
import javax.faces.el.PropertyResolver;
import org.springframework.webflow.execution.FlowExecution;
/**
* Custom property resolver that resolves supported properties of the current flow execution. Supports resolving all
* scopes as java.util.Maps: "flowScope", "conversationScope", and "flashScope". Also supports attribute searching when
* no scope prefix is specified. The search order is flash, flow, conversation.
*
* @author Keith Donald
*/
public class FlowExecutionPropertyResolver extends AbstractFlowExecutionPropertyResolver {
/**
* The name of the special flash scope execution property.
*/
private static final String FLASH_SCOPE_PROPERTY = "flashScope";
/**
* The name of the special flow scope execution property.
*/
private static final String FLOW_SCOPE_PROPERTY = "flowScope";
/**
* The name of the special conversation scope execution property.
*/
private static final String CONVERSATION_SCOPE_PROPERTY = "conversationScope";
/**
* Creates a new flow executon property resolver that resolves flash, flow, and conversation scope attributes.
* @param resolverDelegate the resolver to delegate to when the property is not a flow execution attribute
*/
public FlowExecutionPropertyResolver(PropertyResolver resolverDelegate) {
super(resolverDelegate);
}
protected Class doGetAttributeType(FlowExecution execution, String attributeName) {
if (FLASH_SCOPE_PROPERTY.equals(attributeName)) {
return Map.class;
} else if (FLOW_SCOPE_PROPERTY.equals(attributeName)) {
return Map.class;
} else if (CONVERSATION_SCOPE_PROPERTY.equals(attributeName)) {
return Map.class;
} else {
// perform an attribute search
// try flash scope first
Object value = execution.getActiveSession().getFlashMap().get(attributeName);
if (value != null) {
return value.getClass();
}
// try flow scope
value = execution.getActiveSession().getScope().get(attributeName);
if (value != null) {
return value.getClass();
}
// try conversation scope
value = execution.getConversationScope().get(attributeName);
if (value != null) {
return value.getClass();
}
// cannot determine
return null;
}
}
protected Object doGetAttribute(FlowExecution execution, String attributeName) {
if (FLASH_SCOPE_PROPERTY.equals(attributeName)) {
return execution.getActiveSession().getFlashMap().asMap();
} else if (FLOW_SCOPE_PROPERTY.equals(attributeName)) {
return execution.getActiveSession().getScope().asMap();
} else if (CONVERSATION_SCOPE_PROPERTY.equals(attributeName)) {
return execution.getConversationScope().asMap();
} else {
// perform an attribute search
// try flash scope
Object value = execution.getActiveSession().getFlashMap().get(attributeName);
if (value != null) {
return value;
}
// try flow scope
value = execution.getActiveSession().getScope().get(attributeName);
if (value != null) {
return value;
}
// try conversation scope
value = execution.getConversationScope().get(attributeName);
if (value != null) {
return value;
}
// cannot resolve as expected
throw new PropertyNotFoundException("Readable flow execution attribute '" + attributeName
+ "' not found in any scope (flash, flow, or conversation)");
}
}
protected void doSetAttribute(FlowExecution execution, String attributeName, Object attributeValue) {
// perform a search
if (execution.getActiveSession().getFlashMap().contains(attributeName)) {
execution.getActiveSession().getFlashMap().put(attributeName, attributeValue);
} else if (execution.getActiveSession().getScope().contains(attributeName)) {
execution.getActiveSession().getScope().put(attributeName, attributeValue);
} else if (execution.getConversationScope().contains(attributeName)) {
execution.getConversationScope().put(attributeName, attributeValue);
} else {
// cannot resolve as expected
throw new PropertyNotFoundException("Settable flow execution attribute '" + attributeName
+ "' not found in any scope (flash, flow, or conversation)");
}
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2004-2007 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.faces.el;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.VariableResolver;
import org.springframework.faces.webflow.FlowExecutionHolderUtils;
import org.springframework.webflow.execution.FlowExecution;
/**
* Custom variable resolver that resolves to a thread-bound FlowExecution object for binding expressions prefixed with a
* {@link #FLOW_EXECUTION_VARIABLE_NAME}. For instance "flowExecution.conversationScope.myProperty".
*
* This class is designed to be used with a {@link FlowExecutionPropertyResolver}.
*
* This class is a more flexible alternative to the {@link FlowVariableResolver} which is expected to be used ONLY with
* a {@link FlowPropertyResolver} to resolve flow scope variables ONLY. It is more flexible because it provides access
* to any scope structure of a {@link FlowExecution} object.
*
* @author Keith Donald
*/
public class FlowExecutionVariableResolver extends VariableResolver {
/**
* Name of the flow execution variable.
*/
public static final String FLOW_EXECUTION_VARIABLE_NAME = "flowExecution";
/**
* The standard variable resolver to delegate to if this one doesn't apply.
*/
private VariableResolver resolverDelegate;
/**
* Creates a new flow executon variable resolver that resolves the current FlowExecution object.
* @param resolverDelegate the resolver to delegate to when the variable is not named "flowExecution".
*/
public FlowExecutionVariableResolver(VariableResolver resolverDelegate) {
this.resolverDelegate = resolverDelegate;
}
/**
* Returns the variable resolver this resolver delegates to if necessary.
*/
protected final VariableResolver getResolverDelegate() {
return resolverDelegate;
}
public Object resolveVariable(FacesContext context, String name) throws EvaluationException {
if (FLOW_EXECUTION_VARIABLE_NAME.equals(name)) {
return FlowExecutionHolderUtils.getRequiredCurrentFlowExecution(context);
} else {
return resolverDelegate.resolveVariable(context, name);
}
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2004-2007 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.faces.el;
import javax.faces.context.FacesContext;
import javax.faces.el.PropertyResolver;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.util.Assert;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.jsf.DelegatingVariableResolver;
import org.springframework.web.jsf.FacesContextUtils;
import org.springframework.webflow.execution.FlowExecution;
/**
* Custom property resolver that resolves flow session scope attributes of the current flow execution. This resolver
* will also create and set the attribute value to a bean from the root Spring Web Application Context if the value does
* not already exist, allowing for lazy-initialized binding variables.
*
* Designed mainly to be used with the {@link FlowVariableResolver}. This is the original property resolver implemented
* with Spring Web Flow 1.0. In general, prefer {@link DelegatingFlowVariableResolver} or
* {@link FlowExecutionVariableResolver} over use of this class. Also, consider use of the
* {@link DelegatingVariableResolver} as an alternative to accessing lazy-initialized binding variables managed by a
* Spring application context that uses custom bean scopes.
*
* @author Colin Sampaleanu
* @author Keith Donald
*/
public class FlowPropertyResolver extends AbstractFlowExecutionPropertyResolver {
/**
* Creates a new flow execution property resolver that resolves flow scope attributes.
* @param resolverDelegate the resolver to delegate to when the property is not a flow execution attribute
*/
public FlowPropertyResolver(PropertyResolver resolverDelegate) {
super(resolverDelegate);
}
protected Class doGetAttributeType(FlowExecution execution, String attributeName) {
// we want to access flow scope of the active session (conversation)
Object value = execution.getActiveSession().getScope().get(attributeName);
// note that MyFaces returns Object.class for a null value here, but
// as I read the JSF spec, null should be returned when the object
// type can not be determined this certainly seems to be the case
// for a map value which doesn' even exist
return (value == null) ? null : value.getClass();
}
protected Object doGetAttribute(FlowExecution execution, String attributeName) {
Object value = execution.getActiveSession().getScope().get(attributeName);
if (value == null) {
FacesContext facesContext = FacesContext.getCurrentInstance();
Assert.notNull(facesContext, "The current FacesContext must be present during property resolution stage");
BeanFactory beanFactory = getWebApplicationContext(facesContext);
if (beanFactory.containsBean(attributeName)) {
// note: this resolver doesn't care, but this should be
// a stateless bean with singleton scope or a stateful bean with prototype scope
value = beanFactory.getBean(attributeName);
execution.getActiveSession().getScope().put(attributeName, value);
}
}
return value;
}
protected void doSetAttribute(FlowExecution execution, String attributeName, Object attributeValue) {
execution.getActiveSession().getScope().put(attributeName, attributeValue);
}
/**
* Retrieve the web application context to delegate bean name resolution to. Default implementation delegates to
* FacesContextUtils.
* @param facesContext the current JSF context
* @return the Spring web application context (never <code>null</code>)
* @see FacesContextUtils#getRequiredWebApplicationContext
*/
protected WebApplicationContext getWebApplicationContext(FacesContext facesContext) {
return FacesContextUtils.getRequiredWebApplicationContext(facesContext);
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2004-2007 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.faces.el;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.VariableResolver;
import org.springframework.faces.webflow.FlowExecutionHolderUtils;
/**
* Custom variable resolver that resolves the current FlowExecution object for binding expressions prefixed with
* {@link #FLOW_SCOPE_VARIABLE}. For instance "flowScope.myBean.myProperty". Designed to be used in conjunction with
* {@link FlowPropertyResolver} only.
*
* This class is the original flow execution variable resolver implementation introduced in Spring Web Flow's JSF
* support available since 1.0. In general, prefer use of {@link DelegatingFlowVariableResolver} or
* {@link FlowExecutionVariableResolver} to this implementation as they are both considerably more flexible.
*
* This resolver should only be used with the {@link FlowPropertyResolver} which can only resolve flow-scoped variables.
* May be deprecated in a future release of Spring Web Flow.
*
* @author Colin Sampaleanu
*/
public class FlowVariableResolver extends VariableResolver {
/**
* Name of the exposed flow scope variable ("flowScope").
*/
public static final String FLOW_SCOPE_VARIABLE = "flowScope";
/**
* The standard variable resolver to delegate to if this one doesn't apply.
*/
private VariableResolver resolverDelegate;
/**
* Create a new FlowVariableResolver, using the given original VariableResolver.
* <p>
* A JSF implementation will automatically pass its original resolver into the constructor of a configured resolver,
* provided that there is a corresponding constructor argument.
*
* @param resolverDelegate the original VariableResolver
*/
public FlowVariableResolver(VariableResolver resolverDelegate) {
this.resolverDelegate = resolverDelegate;
}
/**
* Return the original VariableResolver that this resolver delegates to.
*/
protected final VariableResolver getResolverDelegate() {
return resolverDelegate;
}
public Object resolveVariable(FacesContext context, String name) throws EvaluationException {
if (FLOW_SCOPE_VARIABLE.equals(name)) {
return FlowExecutionHolderUtils.getRequiredCurrentFlowExecution(context);
} else {
return resolverDelegate.resolveVariable(context, name);
}
}
}

View File

@@ -0,0 +1,52 @@
package org.springframework.faces.el;
import javax.el.ELContext;
import javax.el.ELResolver;
import javax.el.ExpressionFactory;
import javax.el.FunctionMapper;
import javax.el.VariableMapper;
import javax.faces.context.FacesContext;
import org.springframework.binding.expression.el.DefaultELContextFactory;
import org.springframework.binding.expression.el.ELExpressionParser;
/**
* A JSF-aware ExpressionParser that allows JSF 1.1 managed beans to be referenced in expressions in the FlowDefinition.
* @author Jeremy Grelle
*
*/
public class Jsf11ELExpressionParser extends ELExpressionParser {
public Jsf11ELExpressionParser(ExpressionFactory expressionFactory) {
super(expressionFactory, new Jsf11ELContextFactory());
}
private static class Jsf11ELContextFactory extends DefaultELContextFactory {
public ELContext getEvaluationContext(Object target) {
return new Jsf11ELContext(FacesContext.getCurrentInstance());
}
private static class Jsf11ELContext extends ELContext {
ELResolver baseResolver;
public Jsf11ELContext(FacesContext context) {
baseResolver = new Jsf11ELResolverAdapter(context);
}
public ELResolver getELResolver() {
return baseResolver;
}
public FunctionMapper getFunctionMapper() {
return null;
}
public VariableMapper getVariableMapper() {
return null;
}
}
}
}

View File

@@ -0,0 +1,132 @@
package org.springframework.faces.el;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.ELResolver;
import javax.el.PropertyNotWritableException;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.PropertyNotFoundException;
import javax.faces.el.PropertyResolver;
import javax.faces.el.VariableResolver;
/**
* An adapter for using JSF 1.1 {@link VariableResolver}s and {@link PropertyResolver}s in an {@link ELContext}.
* @author Jeremy Grelle
*
*/
public class Jsf11ELResolverAdapter extends ELResolver {
private FacesContext facesContext;
public Jsf11ELResolverAdapter(FacesContext facesContext) {
this.facesContext = facesContext;
}
public Class getCommonPropertyType(ELContext context, Object base) {
return Object.class;
}
public Iterator getFeatureDescriptors(ELContext context, Object base) {
return Collections.EMPTY_LIST.iterator();
}
public Class getType(ELContext context, Object base, Object property) {
if (property == null) {
return null;
}
try {
context.setPropertyResolved(true);
if (base == null) {
Object var = getVariableResolver().resolveVariable(facesContext, property.toString());
return (var != null) ? var.getClass() : null;
} else {
if (base instanceof List || base.getClass().isArray()) {
return getPropertyResolver().getType(base, Integer.parseInt(property.toString()));
} else {
return getPropertyResolver().getType(base, property);
}
}
} catch (PropertyNotFoundException ex) {
throw new javax.el.PropertyNotFoundException(ex.getMessage(), ex.getCause());
} catch (EvaluationException ex) {
throw new ELException(ex.getMessage(), ex.getCause());
}
}
public Object getValue(ELContext context, Object base, Object property) {
if (property == null) {
return null;
}
try {
context.setPropertyResolved(true);
if (base == null) {
return getVariableResolver().resolveVariable(facesContext, property.toString());
} else {
if (base instanceof List || base.getClass().isArray()) {
return getPropertyResolver().getValue(base, Integer.parseInt(property.toString()));
} else {
return getPropertyResolver().getValue(base, property);
}
}
} catch (PropertyNotFoundException ex) {
throw new javax.el.PropertyNotFoundException(ex.getMessage(), ex.getCause());
} catch (EvaluationException ex) {
throw new ELException(ex.getMessage(), ex.getCause());
}
}
public boolean isReadOnly(ELContext context, Object base, Object property) {
if (property == null) {
return true;
}
try {
context.setPropertyResolved(true);
if (base == null) {
return false; // VariableResolver provides no way to determine isReadOnly
} else {
if (base instanceof List || base.getClass().isArray()) {
return getPropertyResolver().isReadOnly(base, Integer.parseInt(property.toString()));
} else {
return getPropertyResolver().isReadOnly(base, property);
}
}
} catch (PropertyNotFoundException ex) {
throw new javax.el.PropertyNotFoundException(ex.getMessage(), ex.getCause());
} catch (EvaluationException ex) {
throw new ELException(ex.getMessage(), ex.getCause());
}
}
public void setValue(ELContext context, Object base, Object property, Object value) {
if (property == null) {
throw new PropertyNotWritableException("Property is Null");
}
try {
context.setPropertyResolved(true);
if (base instanceof List || base.getClass().isArray()) {
getPropertyResolver().setValue(base, Integer.parseInt(property.toString()), value);
} else {
getPropertyResolver().setValue(base, property, value);
}
} catch (PropertyNotFoundException ex) {
throw new javax.el.PropertyNotFoundException(ex.getMessage(), ex.getCause());
} catch (EvaluationException ex) {
throw new ELException(ex.getMessage(), ex.getCause());
}
}
private VariableResolver getVariableResolver() {
return facesContext.getApplication().getVariableResolver();
}
private PropertyResolver getPropertyResolver() {
return facesContext.getApplication().getPropertyResolver();
}
}

View File

@@ -0,0 +1,27 @@
package org.springframework.faces.el;
import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.faces.context.FacesContext;
import org.springframework.binding.expression.el.DefaultELContextFactory;
import org.springframework.binding.expression.el.ELExpressionParser;
/**
* A JSF-aware ExpressionParser that allows JSF 1.2 managed beans to be referenced in expressions in the FlowDefinition.
* @author Jeremy Grelle
*
*/
public class Jsf12ELExpressionParser extends ELExpressionParser {
public Jsf12ELExpressionParser(ExpressionFactory expressionFactory) {
super(expressionFactory, new Jsf12ELContextFactory());
}
private static class Jsf12ELContextFactory extends DefaultELContextFactory {
public ELContext getEvaluationContext(Object target) {
return FacesContext.getCurrentInstance().getELContext();
}
}
}

View File

@@ -0,0 +1,258 @@
package org.springframework.faces.ui;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
public class ClientDateValidator extends ClientTextValidator {
private static final String EXT_COMPONENT_TYPE = "Ext.form.DateField";
private static final String[] EXT_ATTRS_INTERNAL = new String[] { "altFormats", "disabledDates",
"disabledDatesText", "disabledDays", "disabledDaysText", "format", "maxText", "maxValue", "minText",
"minValue", "triggerClass" };
protected static final String[] EXT_ATTRS;
static {
EXT_ATTRS = new String[ClientTextValidator.EXT_ATTRS.length + EXT_ATTRS_INTERNAL.length];
System.arraycopy(ClientTextValidator.EXT_ATTRS, 0, EXT_ATTRS, 0, ClientTextValidator.EXT_ATTRS.length);
System.arraycopy(EXT_ATTRS_INTERNAL, 0, EXT_ATTRS, ClientTextValidator.EXT_ATTRS.length,
EXT_ATTRS_INTERNAL.length);
}
/**
* Multiple date formats separated by "|" to try when parsing a user input value and it doesn't match the defined
* format (defaults to 'm/d/Y|m-d-y|m-d-Y|m/d|m-d|d').
*/
private String altFormats;
/**
* An array of "dates" to disable, as strings. These strings will be used to build a dynamic regular expression so
* they are very powerful. Some examples:
*
* ["03/08/2003", "09/16/2003"] would disable those exact dates ["03/08", "09/16"] would disable those days for
* every year ["^03/08"] would only match the beginning (useful if you are using short years) ["03/../2006"] would
* disable every day in March 2006 ["^03"] would disable every day in every March
*
* In order to support regular expressions, if you are using a date format that has "." in it, you will have to
* escape the dot when restricting dates. For example: ["03\\.08\\.03"].
*/
private String disabledDates;
/**
* The tooltip text to display when the date falls on a disabled date (defaults to 'Disabled')
*/
private String disabledDatesText;
/**
* An array of days to disable, 0 based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
*/
private String disabledDays;
/**
* The tooltip to display when the date falls on a disabled day (defaults to 'Disabled')
*/
private String disabledDaysText;
/**
* The default date format string which can be overriden for localization support. The format must be valid
* according to Date.parseDate (defaults to 'm/d/y').
*/
private String format;
/**
* The error text to display when the date in the field is invalid (defaults to '{value} is not a valid date - it
* must be in the format {format}').
*/
private String invalidText;
/**
* The error text to display when the date in the cell is after maxValue (defaults to 'The date in this field must
* be before {maxValue}').
*/
private String maxText;
/**
* The maximum allowed date. Can be either a Javascript date object or a string date in a valid format (defaults to
* null).
*/
private String maxValue;
/**
* The error text to display when the date in the cell is before minValue (defaults to 'The date in this field must
* be after {minValue}').
*/
private String minText;
/**
* The minimum allowed date. Can be either a Javascript date object or a string date in a valid format (defaults to
* null).
*/
private String minValue;
/**
* An additional CSS class used to style the trigger button. The trigger will always get the class 'x-form-trigger'
* and triggerClass will be appended if specified (defaults to 'x-form-date-trigger' which displays a calendar
* icon).
*/
private String triggerClass;
public String getAltFormats() {
return altFormats;
}
public void setAltFormats(String altFormats) {
this.altFormats = altFormats;
}
public String getDisabledDates() {
return disabledDates;
}
public void setDisabledDates(String disabledDates) {
this.disabledDates = disabledDates;
}
public String getDisabledDatesText() {
if (disabledDatesText != null) {
return disabledDatesText;
}
ValueBinding vb = getValueBinding("disabledDatesText");
return vb != null ? (String) vb.getValue(getFacesContext()) : null;
}
public void setDisabledDatesText(String disabledDatesText) {
this.disabledDatesText = disabledDatesText;
}
public String getDisabledDays() {
return disabledDays;
}
public void setDisabledDays(String disabledDays) {
this.disabledDays = disabledDays;
}
public String getDisabledDaysText() {
if (disabledDaysText != null) {
return disabledDaysText;
}
ValueBinding vb = getValueBinding("disabledDaysText");
return vb != null ? (String) vb.getValue(getFacesContext()) : null;
}
public void setDisabledDaysText(String disabledDaysText) {
this.disabledDaysText = disabledDaysText;
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
public String getInvalidText() {
if (invalidText != null) {
return invalidText;
}
ValueBinding vb = getValueBinding("invalidText");
return vb != null ? (String) vb.getValue(getFacesContext()) : null;
}
public void setInvalidText(String invalidText) {
this.invalidText = invalidText;
}
public String getMaxText() {
if (maxText != null) {
return maxText;
}
ValueBinding vb = getValueBinding("maxText");
return vb != null ? (String) vb.getValue(getFacesContext()) : null;
}
public void setMaxText(String maxText) {
this.maxText = maxText;
}
public String getMaxValue() {
return maxValue;
}
public void setMaxValue(String maxValue) {
this.maxValue = maxValue;
}
public String getMinText() {
if (minText != null) {
return minText;
}
ValueBinding vb = getValueBinding("minText");
return vb != null ? (String) vb.getValue(getFacesContext()) : null;
}
public void setMinText(String minText) {
this.minText = minText;
}
public String getMinValue() {
return minValue;
}
public void setMinValue(String minValue) {
this.minValue = minValue;
}
public String getTriggerClass() {
return triggerClass;
}
public void setTriggerClass(String triggerClass) {
this.triggerClass = triggerClass;
}
protected String[] getExtAttributes() {
return EXT_ATTRS;
}
public String getExtComponentType() {
return EXT_COMPONENT_TYPE;
}
public Object saveState(FacesContext context) {
Object[] values = new Object[13];
values[0] = super.saveState(context);
values[1] = altFormats;
values[2] = disabledDates;
values[3] = disabledDatesText;
values[4] = disabledDays;
values[5] = disabledDaysText;
values[6] = format;
values[7] = invalidText;
values[8] = maxText;
values[9] = maxValue;
values[10] = minText;
values[11] = minValue;
values[12] = triggerClass;
return values;
}
public void restoreState(FacesContext context, Object state) {
Object values[] = (Object[]) state;
super.restoreState(context, values[0]);
altFormats = (String) values[1];
disabledDates = (String) values[2];
disabledDatesText = (String) values[3];
disabledDays = (String) values[4];
disabledDaysText = (String) values[5];
format = (String) values[6];
invalidText = (String) values[7];
maxText = (String) values[8];
maxValue = (String) values[9];
minText = (String) values[10];
minValue = (String) values[11];
triggerClass = (String) values[12];
}
}

View File

@@ -0,0 +1,206 @@
package org.springframework.faces.ui;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
public class ClientNumberValidator extends ClientTextValidator {
private static final String EXT_COMPONENT_TYPE = "Ext.form.NumberField";
private static final String[] EXT_ATTRS_INTERNAL = new String[] { "allowDecimals", "allowNegative",
"decimalPrecision", "decimalSeparator", "maxText", "maxValue", "minText", "minValue", "nanText" };
protected static final String[] EXT_ATTRS;
static {
EXT_ATTRS = new String[ClientTextValidator.EXT_ATTRS.length + EXT_ATTRS_INTERNAL.length];
System.arraycopy(ClientTextValidator.EXT_ATTRS, 0, EXT_ATTRS, 0, ClientTextValidator.EXT_ATTRS.length);
System.arraycopy(EXT_ATTRS_INTERNAL, 0, EXT_ATTRS, ClientTextValidator.EXT_ATTRS.length,
EXT_ATTRS_INTERNAL.length);
}
/**
* False to disallow decimal values (defaults to true)
*/
private Boolean allowDecimals;
/**
* False to prevent entering a negative sign (defaults to true)
*/
private Boolean allowNegative;
/**
* The maximum precision to display after the decimal separator (defaults to 2)
*/
private Integer decimalPrecision;
/**
* Character(s) to allow as the decimal separator (defaults to '.')
*/
private String decimalSeparator;
/**
* The default CSS class for the field (defaults to "x-form-field x-form-num-field")
*/
private String fieldClass;
/**
* Error text to display if the maximum value validation fails (defaults to "The maximum value for this field is
* {maxValue}")
*/
private String maxText;
/**
* The maximum allowed value (defaults to Number.MAX_VALUE)
*/
private Integer maxValue;
/**
* Error text to display if the minimum value validation fails (defaults to "The minimum value for this field is
* {minValue}")
*/
private String minText;
/**
* The minimum allowed value (defaults to Number.NEGATIVE_INFINITY)
*/
private Integer minValue;
/**
* Error text to display if the value is not a valid number. For example, this can happen if a valid character like
* '.' or '-' is left in the field with no number (defaults to "{value} is not a valid number")
*/
private String nanText;
public Boolean getAllowDecimals() {
return allowDecimals;
}
public void setAllowDecimals(Boolean allowDecimals) {
this.allowDecimals = allowDecimals;
}
public Boolean getAllowNegative() {
return allowNegative;
}
public void setAllowNegative(Boolean allowNegative) {
this.allowNegative = allowNegative;
}
public Integer getDecimalPrecision() {
return decimalPrecision;
}
public void setDecimalPrecision(Integer decimalPrecision) {
this.decimalPrecision = decimalPrecision;
}
public String getDecimalSeparator() {
return decimalSeparator;
}
public void setDecimalSeparator(String decimalSeparator) {
this.decimalSeparator = decimalSeparator;
}
public String getFieldClass() {
return fieldClass;
}
public void setFieldClass(String fieldClass) {
this.fieldClass = fieldClass;
}
public String getMaxText() {
if (maxText != null) {
return maxText;
}
ValueBinding vb = getValueBinding("maxText");
return vb != null ? (String) vb.getValue(getFacesContext()) : null;
}
public void setMaxText(String maxText) {
this.maxText = maxText;
}
public Integer getMaxValue() {
return maxValue;
}
public void setMaxValue(Integer maxValue) {
this.maxValue = maxValue;
}
public String getMinText() {
if (minText != null) {
return minText;
}
ValueBinding vb = getValueBinding("minText");
return vb != null ? (String) vb.getValue(getFacesContext()) : null;
}
public void setMinText(String minText) {
this.minText = minText;
}
public Integer getMinValue() {
return minValue;
}
public void setMinValue(Integer minValue) {
this.minValue = minValue;
}
public String getNanText() {
if (nanText != null) {
return nanText;
}
ValueBinding vb = getValueBinding("nanText");
return vb != null ? (String) vb.getValue(getFacesContext()) : null;
}
public void setNanText(String nanText) {
this.nanText = nanText;
}
protected String[] getExtAttributes() {
return EXT_ATTRS;
}
public String getExtComponentType() {
return EXT_COMPONENT_TYPE;
}
public Object saveState(FacesContext context) {
Object[] values = new Object[11];
values[0] = super.saveState(context);
values[1] = allowDecimals;
values[2] = allowNegative;
values[3] = decimalPrecision;
values[4] = decimalSeparator;
values[5] = fieldClass;
values[6] = maxText;
values[7] = maxValue;
values[8] = minText;
values[9] = minValue;
values[10] = nanText;
return values;
}
public void restoreState(FacesContext context, Object state) {
Object values[] = (Object[]) state;
super.restoreState(context, values[0]);
allowDecimals = (Boolean) values[1];
allowNegative = (Boolean) values[2];
decimalPrecision = (Integer) values[3];
decimalSeparator = (String) values[4];
fieldClass = (String) values[5];
maxText = (String) values[6];
maxValue = (Integer) values[7];
minText = (String) values[8];
minValue = (Integer) values[9];
nanText = (String) values[10];
}
}

View File

@@ -0,0 +1,306 @@
package org.springframework.faces.ui;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
public class ClientTextValidator extends ExtAdvisor {
private static final String EXT_COMPONENT_TYPE = "Ext.form.TextField";
private static final String[] EXT_ATTRS_INTERNAL = new String[] { "allowBlank", "blankText", "disableKeyFilter",
"emptyClass", "emptyText", "grow", "growMax", "growMin", "maskRe", "maxLength", "maxLengthText",
"minLength", "minLengthText", "regex", "regexText", "selectOnFocus" };
protected static final String[] EXT_ATTRS;
static {
EXT_ATTRS = new String[ExtAdvisor.EXT_ATTRS.length + EXT_ATTRS_INTERNAL.length];
System.arraycopy(ExtAdvisor.EXT_ATTRS, 0, EXT_ATTRS, 0, ExtAdvisor.EXT_ATTRS.length);
System.arraycopy(EXT_ATTRS_INTERNAL, 0, EXT_ATTRS, ExtAdvisor.EXT_ATTRS.length, EXT_ATTRS_INTERNAL.length);
}
/**
* False to validate that the value length > 0 (defaults to true)
*/
private Boolean allowBlank;
/**
* Error text to display if the allow blank validation fails (defaults to "This field is required")
*/
private String blankText;
/**
* True to disable input keystroke filtering (defaults to false)
*/
private Boolean disableKeyFilter;
/**
* The CSS class to apply to an empty field to style the emptyText (defaults to 'x-form-empty-field'). This class is
* automatically added and removed as needed depending on the current field value.
*/
private String emptyClass;
/**
* The default text to display in an empty field (defaults to null).
*/
private String emptyText;
/**
* True if this field should automatically grow and shrink to its content
*/
private Boolean grow;
/**
* The maximum width to allow when grow = true (defaults to 800)
*/
private Integer growMax;
/**
* The minimum width to allow when grow = true (defaults to 30)
*/
private Integer growMin;
/**
* An input mask regular expression that will be used to filter keystrokes that don't match (defaults to null)
*/
private String maskRe;
/**
* Maximum input field length allowed (defaults to Number.MAX_VALUE)
*/
private Integer maxLength;
/**
* Error text to display if the maximum length validation fails (defaults to "The maximum length for this field is
* {maxLength}")
*/
private String maxLengthText;
/**
* Minimum input field length required (defaults to 0)
*/
private Integer minLength;
/**
* Error text to display if the minimum length validation fails (defaults to "The minimum length for this field is
* {minLength}")
*/
private String minLengthText;
/**
* A JavaScript RegExp object to be tested against the field value during validation (defaults to null). If
* available, this regex will be evaluated only after the basic validators all return true, and will be passed the
* current field value. If the test fails, the field will be marked invalid using regexText.
*/
private String regex;
/**
* The error text to display if regex is used and the test fails during validation (defaults to "")
*/
private String regexText;
/**
* True to automatically select any existing field text when the field receives input focus (defaults to false)
*/
private Boolean selectOnFocus;
public Boolean getAllowBlank() {
return allowBlank;
}
public void setAllowBlank(Boolean allowBlank) {
this.allowBlank = allowBlank;
}
public String getBlankText() {
if (blankText != null) {
return blankText;
}
ValueBinding vb = getValueBinding("blankText");
return vb != null ? (String) vb.getValue(getFacesContext()) : null;
}
public void setBlankText(String blankText) {
this.blankText = blankText;
}
public Boolean getDisableKeyFilter() {
return disableKeyFilter;
}
public void setDisableKeyFilter(Boolean disableKeyFilter) {
this.disableKeyFilter = disableKeyFilter;
}
public String getEmptyClass() {
return emptyClass;
}
public void setEmptyClass(String emptyClass) {
this.emptyClass = emptyClass;
}
public String getEmptyText() {
if (emptyText != null) {
return emptyText;
}
ValueBinding vb = getValueBinding("emptyText");
return vb != null ? (String) vb.getValue(getFacesContext()) : null;
}
public void setEmptyText(String emptyText) {
this.emptyText = emptyText;
}
public Boolean getGrow() {
return grow;
}
public void setGrow(Boolean grow) {
this.grow = grow;
}
public Integer getGrowMax() {
return growMax;
}
public void setGrowMax(Integer growMax) {
this.growMax = growMax;
}
public Integer getGrowMin() {
return growMin;
}
public void setGrowMin(Integer growMin) {
this.growMin = growMin;
}
public String getMaskRe() {
return maskRe;
}
public void setMaskRe(String maskRe) {
this.maskRe = maskRe;
}
public Integer getMaxLength() {
return maxLength;
}
public void setMaxLength(Integer maxLength) {
this.maxLength = maxLength;
}
public String getMaxLengthText() {
if (maxLengthText != null) {
return maxLengthText;
}
ValueBinding vb = getValueBinding("maxLengthText");
return vb != null ? (String) vb.getValue(getFacesContext()) : null;
}
public void setMaxLengthText(String maskLengthText) {
this.maxLengthText = maskLengthText;
}
public Integer getMinLength() {
return minLength;
}
public void setMinLength(Integer minLength) {
this.minLength = minLength;
}
public String getMinLengthText() {
if (minLengthText != null) {
return minLengthText;
}
ValueBinding vb = getValueBinding("minLengthText");
return vb != null ? (String) vb.getValue(getFacesContext()) : null;
}
public void setMinLengthText(String minLengthText) {
this.minLengthText = minLengthText;
}
public String getRegex() {
return regex;
}
public void setRegex(String regex) {
this.regex = regex;
}
public String getRegexText() {
if (regexText != null) {
return regexText;
}
ValueBinding vb = getValueBinding("regexText");
return vb != null ? (String) vb.getValue(getFacesContext()) : null;
}
public void setRegexText(String regexText) {
this.regexText = regexText;
}
public Boolean getSelectOnFocus() {
return selectOnFocus;
}
public void setSelectOnFocus(Boolean selectOnFocus) {
this.selectOnFocus = selectOnFocus;
}
protected String[] getExtAttributes() {
return EXT_ATTRS;
}
public String getExtComponentType() {
return EXT_COMPONENT_TYPE;
}
public Object saveState(FacesContext context) {
Object[] values = new Object[17];
values[0] = super.saveState(context);
values[1] = allowBlank;
values[2] = blankText;
values[3] = disableKeyFilter;
values[4] = emptyClass;
values[5] = emptyText;
values[6] = grow;
values[7] = growMax;
values[8] = growMin;
values[9] = maskRe;
values[10] = maxLength;
values[11] = maxLengthText;
values[12] = minLength;
values[13] = minLengthText;
values[14] = regex;
values[15] = regexText;
values[16] = selectOnFocus;
return values;
}
public void restoreState(FacesContext context, Object state) {
Object values[] = (Object[]) state;
super.restoreState(context, values[0]);
allowBlank = (Boolean) values[1];
blankText = (String) values[2];
disableKeyFilter = (Boolean) values[3];
emptyClass = (String) values[4];
emptyText = (String) values[5];
grow = (Boolean) values[6];
growMax = (Integer) values[7];
growMin = (Integer) values[8];
maskRe = (String) values[9];
maxLength = (Integer) values[10];
maxLengthText = (String) values[11];
minLength = (Integer) values[12];
minLengthText = (String) values[13];
regex = (String) values[14];
regexText = (String) values[15];
selectOnFocus = (Boolean) values[16];
}
}

View File

@@ -0,0 +1,271 @@
package org.springframework.faces.ui;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
public abstract class ExtAdvisor extends ExtJsComponent {
protected static final String[] EXT_ATTRS = new String[] { "cls", "disableClass", "disabled", "fieldClass",
"focusClass", "hideMode", "invalidClass", "invalidText", "msgDisplay", "readOnly", "validateOnBlur",
"validationDelay", "validationEvent", "width" };
/**
* A CSS class to apply to the field's underlying element.
*/
private String cls;
/**
* CSS class added to the component when it is disabled (defaults to "x-item-disabled").
*/
private String disableClass;
/**
* True to disable the field (defaults to false).
*/
private Boolean disabled;
/**
* The default CSS class for the field (defaults to "x-form-field")
*/
private String fieldClass;
/**
* The CSS class to use when the field receives focus (defaults to "x-form-focus")
*/
private String focusClass;
/**
* How this component should hidden. Supported values are "visibility" (css visibility), "offsets" (negative offset
* position) and "display" (css display) - defaults to "display".
*/
private String hideMode;
/**
* The CSS class to use when marking a field invalid (defaults to "x-form-invalid")
*/
private String invalidClass;
/**
* The error text to use when marking a field invalid and no message is provided (defaults to "The value in this
* field is invalid")
*/
private String invalidText;
/**
* The CSS class to be applied to the message div when displaying validation messages
*/
private String msgClass;
/**
* The 'display' style to be applied to the message div when displaying validation messages.
*/
private String msgDisplay;
/**
* True to mark the field as readOnly in HTML (defaults to false) -- Note: this only sets the element's readOnly DOM
* attribute.
*/
private Boolean readOnly;
/**
* Whether the field should validate when it loses focus (defaults to true).
*/
private Boolean validateOnBlur;
/**
* The length of time in milliseconds after user input begins until validation is initiated (defaults to 250)
*/
private Integer validationDelay;
/**
* The event that should initiate field validation. Set to false to disable automatic validation (defaults to
* "keyup").
*/
private String validationEvent;
/**
* The width to be applied to the field
*/
private Integer width;
public String getCls() {
return cls;
}
public void setCls(String cls) {
this.cls = cls;
}
public String getDisableClass() {
return disableClass;
}
public void setDisableClass(String disableClass) {
this.disableClass = disableClass;
}
public Boolean getDisabled() {
if (disabled != null) {
return disabled;
}
ValueBinding vb = getValueBinding("disabled");
return vb != null ? (Boolean) vb.getValue(getFacesContext()) : null;
}
public void setDisabled(Boolean disabled) {
this.disabled = disabled;
}
public String getFieldClass() {
return fieldClass;
}
public void setFieldClass(String fieldClass) {
this.fieldClass = fieldClass;
}
public String getFocusClass() {
return focusClass;
}
public void setFocusClass(String focusClass) {
this.focusClass = focusClass;
}
public String getHideMode() {
return hideMode;
}
public void setHideMode(String hideMode) {
this.hideMode = hideMode;
}
public String getInvalidClass() {
return invalidClass;
}
public void setInvalidClass(String invalidClass) {
this.invalidClass = invalidClass;
}
public String getInvalidText() {
if (invalidText != null) {
return invalidText;
}
ValueBinding vb = getValueBinding("invalidText");
return vb != null ? (String) vb.getValue(getFacesContext()) : null;
}
public void setInvalidText(String invalidText) {
this.invalidText = invalidText;
}
public String getMsgClass() {
if (msgClass != null) {
return msgClass;
}
ValueBinding vb = getValueBinding("msgClass");
return vb != null ? (String) vb.getValue(getFacesContext()) : null;
}
public void setMsgClass(String msgClass) {
this.msgClass = msgClass;
}
public String getMsgDisplay() {
return msgDisplay;
}
public void setMsgDisplay(String msgDisplay) {
this.msgDisplay = msgDisplay;
}
public Boolean getReadOnly() {
if (readOnly != null) {
return readOnly;
}
ValueBinding vb = getValueBinding("readOnly");
return vb != null ? (Boolean) vb.getValue(getFacesContext()) : null;
}
public void setReadOnly(boolean readOnly) {
this.readOnly = new Boolean(readOnly);
}
public Boolean getValidateOnBlur() {
return validateOnBlur;
}
public void setValidateOnBlur(Boolean validateOnBlur) {
this.validateOnBlur = validateOnBlur;
}
public Integer getValidationDelay() {
return validationDelay;
}
public void setValidationDelay(Integer validationDelay) {
this.validationDelay = validationDelay;
}
public String getValidationEvent() {
return validationEvent;
}
public void setValidationEvent(String validationEvent) {
this.validationEvent = validationEvent;
}
public Integer getWidth() {
return width;
}
public void setWidth(Integer width) {
this.width = width;
}
protected abstract String[] getExtAttributes();
public abstract String getExtComponentType();
public Object saveState(FacesContext context) {
Object[] values = new Object[16];
values[0] = super.saveState(context);
values[1] = cls;
values[2] = disableClass;
values[3] = disabled;
values[4] = fieldClass;
values[5] = focusClass;
values[6] = hideMode;
values[7] = invalidClass;
values[8] = invalidText;
values[9] = msgClass;
values[10] = msgDisplay;
values[11] = readOnly;
values[12] = validateOnBlur;
values[13] = validationDelay;
values[14] = validationEvent;
values[15] = width;
return values;
}
public void restoreState(FacesContext context, Object state) {
Object values[] = (Object[]) state;
super.restoreState(context, values[0]);
cls = (String) values[1];
disableClass = (String) values[2];
disabled = (Boolean) values[3];
fieldClass = (String) values[4];
focusClass = (String) values[5];
hideMode = (String) values[6];
invalidClass = (String) values[7];
invalidText = (String) values[8];
msgClass = (String) values[9];
msgDisplay = (String) values[10];
readOnly = (Boolean) values[11];
validateOnBlur = (Boolean) values[12];
validationDelay = (Integer) values[13];
validationEvent = (String) values[14];
width = (Integer) values[15];
}
}

View File

@@ -0,0 +1,83 @@
package org.springframework.faces.ui;
import java.io.IOException;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
/**
* A base implementation for use in rendering Ext based components that enhance existing DOM elements.
*
* @author Jeremy Grelle
*
*/
public class ExtAdvisorRenderer extends ExtJsRenderer {
private static final String CLASS_ATTR = "class";
private static final String ID_ATTR = "id";
private static final String SCRIPT_ELEMENT = "script";
private static final String DIV_ELEMENT = "div";
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
ResponseWriter writer = context.getResponseWriter();
if (component.getChildCount() == 0)
throw new FacesException("A Spring Faces advisor expects to have at least one child component.");
UIComponent advisedChild = (UIComponent) component.getChildren().get(0);
writer.startElement(DIV_ELEMENT, component);
writer.writeAttribute(ID_ATTR, advisedChild.getClientId(context) + ":msg", null);
writer.writeAttribute(CLASS_ATTR, ((ExtAdvisor) component).getMsgClass(), null);
writer.endElement(DIV_ELEMENT);
writer.startElement(SCRIPT_ELEMENT, component);
StringBuffer script = new StringBuffer();
script.append(" SpringFaces.advisors.push(new SpringFaces.ExtGenericFieldAdvisor({ ");
script.append(" targetElId : '" + advisedChild.getClientId(context) + "', ");
script.append(" msgElId : '" + advisedChild.getClientId(context) + ":msg', ");
script.append(" decoratorType : '" + ((ExtAdvisor) component).getExtComponentType() + "', ");
script.append(" decoratorAttrs : \"{ ");
script.append(getExtAttributesAsString(context, component));
script.append(" }\"})); ");
writer.writeText(script, null);
writer.endElement(SCRIPT_ELEMENT);
}
protected String getExtAttributesAsString(FacesContext context, UIComponent component) {
ExtAdvisor advisor = (ExtAdvisor) component;
StringBuffer attrs = new StringBuffer();
for (int i = 0; i < advisor.getExtAttributes().length; i++) {
String key = advisor.getExtAttributes()[i];
Object value = advisor.getAttributes().get(key);
if (value != null) {
if (attrs.length() > 0)
attrs.append(", ");
attrs.append(key + " : ");
if (value instanceof String) {
attrs.append("'" + value + "'");
} else {
attrs.append(value);
}
}
}
return attrs.toString();
}
}

View File

@@ -0,0 +1,57 @@
package org.springframework.faces.ui;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
public class ExtJsComponent extends UIComponentBase {
/**
* The component will render the default ExtJs css resources by default. This may be set to false if the page
* developer wants to include their own stylesheet.
*/
private Boolean includeExtStyles = new Boolean(true);
/**
* The component will render an optimized version of the ExtJs javascript that contains only the pieces of the
* library used by SpringFaces. This may be set to false if the page developer wants to include their own ExtJs
* resources.
*/
private Boolean includeExtScript = new Boolean(true);
public String getFamily() {
return "spring.faces.ExtAdvisor";
}
public Boolean getIncludeExtStyles() {
return includeExtStyles;
}
public void setIncludeExtStyles(Boolean includeExtStyles) {
this.includeExtStyles = includeExtStyles;
}
public Boolean getIncludeExtScript() {
return includeExtScript;
}
public void setIncludeExtScript(Boolean includeExtScript) {
this.includeExtScript = includeExtScript;
}
public Object saveState(FacesContext context) {
Object[] values = new Object[3];
values[0] = super.saveState(context);
values[1] = includeExtScript;
values[2] = includeExtStyles;
return values;
}
public void restoreState(FacesContext context, Object state) {
Object values[] = (Object[]) state;
super.restoreState(context, values[0]);
includeExtScript = (Boolean) values[1];
includeExtStyles = (Boolean) values[2];
}
}

View File

@@ -0,0 +1,37 @@
package org.springframework.faces.ui;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.Renderer;
import org.apache.shale.remoting.Mechanism;
import org.apache.shale.remoting.XhtmlHelper;
public class ExtJsRenderer extends Renderer {
private static final String EXT_CSS = "/org/springframework/faces/ui/ext/resources/css/ext-all.css";
private static final String EXT_SCRIPT = "/org/springframework/faces/ui/ext/ext.js";
private static final String SPRING_FACES_SCRIPT = "/org/springframework/faces/ui/SpringFaces.js";
private XhtmlHelper resourceHelper = new XhtmlHelper();
public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
ExtJsComponent extJsComponent = (ExtJsComponent) component;
ResponseWriter writer = context.getResponseWriter();
if (extJsComponent.getIncludeExtStyles().equals(Boolean.TRUE))
resourceHelper.linkStylesheet(context, extJsComponent, writer, Mechanism.CLASS_RESOURCE, EXT_CSS);
if (extJsComponent.getIncludeExtScript().equals(Boolean.TRUE))
resourceHelper.linkJavascript(context, extJsComponent, writer, Mechanism.CLASS_RESOURCE, EXT_SCRIPT);
resourceHelper.linkJavascript(context, extJsComponent, writer, Mechanism.CLASS_RESOURCE, SPRING_FACES_SCRIPT);
}
}

View File

@@ -0,0 +1,44 @@
package org.springframework.faces.ui;
import java.io.IOException;
import javax.faces.FacesException;
import javax.faces.component.UICommand;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
public class ExtValidateAllRenderer extends ExtJsRenderer {
private static final String SCRIPT_ELEMENT = "script";
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
ResponseWriter writer = context.getResponseWriter();
if (component.getChildCount() == 0)
throw new FacesException("A Spring Faces advisor expects to have at least one child component.");
if (!(component.getChildren().get(0) instanceof UICommand))
throw new FacesException("ValidateAll expects to have a child of type UICommand.");
UIComponent advisedChild = (UIComponent) component.getChildren().get(0);
String elementVar = advisedChild.getClientId(context).replaceAll(":", "_") + "_element";
String handlerVar = advisedChild.getClientId(context).replaceAll(":", "_") + "_handler";
writer.startElement(SCRIPT_ELEMENT, component);
StringBuffer script = new StringBuffer();
script
.append(" var " + elementVar + " = document.getElementById('" + advisedChild.getClientId(context)
+ "');");
script.append(" var " + handlerVar + " = " + elementVar + ".onclick;");
script.append(elementVar + ".onclick" + " = function(){");
script.append(" if(!SpringFaces.validateAll()) return false; ");
script.append(handlerVar + "();");
script.append("};");
writer.writeText(script, null);
writer.endElement(SCRIPT_ELEMENT);
}
}

View File

@@ -0,0 +1,48 @@
SpringFaces = {};
SpringFaces.advisors = [];
SpringFaces.ExtGenericFieldAdvisor = function(config){
Ext.apply(this, config);
};
SpringFaces.ExtGenericFieldAdvisor.prototype = {
targetElId : "",
msgElId : "",
decoratorType : "",
decorator : null,
decoratorAttrs : "",
apply : function(){
var target = document.getElementById(this.targetElId);
var msgEl = document.getElementById(this.msgElId);
this.decorator = eval("new "+ this.decoratorType + "(" + this.decoratorAttrs +");" );
this.decorator.msgTarget=msgEl;
this.decorator.applyTo(target);
}
};
SpringFaces.applyAdvisors = function(){
for (x in SpringFaces.advisors) {
SpringFaces.advisors[x].apply();
}
};
SpringFaces.validateAll = function(){
var valid = true;
for(x in SpringFaces.advisors) {
if (SpringFaces.advisors[x].decorator &&
!SpringFaces.advisors[x].decorator.validate()) {
valid = false;
}
}
return valid;
};
Ext.onReady(SpringFaces.applyAdvisors);

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 893 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 865 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 995 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 884 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 992 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 833 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1010 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1005 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1001 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1016 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 995 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 825 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 825 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 868 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 869 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 947 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 834 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 817 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 855 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 817 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 823 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 955 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 815 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 875 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 884 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 923 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 875 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1015 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 955 B

Some files were not shown because too many files have changed in this diff Show More