Updated Spring formatting conventions to disallow spaces as leading whitespace. Only tabs are allowed now. Some spelling updates as well.

This commit is contained in:
Ben Hale
2007-08-13 16:05:54 +00:00
parent 17bb793f8c
commit 2e4ed776c1
7 changed files with 591 additions and 615 deletions

View File

@@ -1,4 +1,4 @@
#Tue Jul 31 15:11:23 EDT 2007
#Mon Aug 13 12:00:34 EDT 2007
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.3
@@ -142,7 +142,7 @@ org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.jdt.core.formatter.indentation.size=4
org.eclipse.jdt.core.formatter.indentation.size=8
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
@@ -322,7 +322,7 @@ org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=mixed
org.eclipse.jdt.core.formatter.tabulation.size=8
org.eclipse.jdt.core.formatter.tabulation.char=tab
org.eclipse.jdt.core.formatter.tabulation.size=4
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true

View File

@@ -1,4 +1,4 @@
#Tue Jul 31 15:11:23 EDT 2007
#Mon Aug 13 12:00:31 EDT 2007
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.3
@@ -142,7 +142,7 @@ org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.jdt.core.formatter.indentation.size=4
org.eclipse.jdt.core.formatter.indentation.size=8
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
@@ -322,7 +322,7 @@ org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=mixed
org.eclipse.jdt.core.formatter.tabulation.size=8
org.eclipse.jdt.core.formatter.tabulation.char=tab
org.eclipse.jdt.core.formatter.tabulation.size=4
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true

View File

@@ -1,60 +1,56 @@
/*
* 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.webflow.definition.registry;
import org.springframework.webflow.definition.FlowDefinition;
/**
* A container of flow definitions. Extends the {@link FlowDefinitionRegistryMBean}
* management interface exposing registry monitoring and management operations.
* Also extends {@link FlowDefinitionLocator} for accessing registered Flow
* definitions for execution at runtime.
* <p>
* Flow definition registries can be configured with a "parent" registry to provide a hook
* into a larger flow definition registry hierarchy.
*
* @author Keith Donald
*/
public interface FlowDefinitionRegistry extends FlowDefinitionLocator, FlowDefinitionRegistryMBean {
/**
* Sets this registry's parent registry. When asked by a client to locate a
* flow definition this registry will query it's parent if it cannot
* fullfill the lookup request itself.
* @param parent the parent flow definition registry, may be null
*/
public void setParent(FlowDefinitionRegistry parent);
/**
* Return all flow definitions registered in this registry. Note that this
* will trigger flow assemply for all registered flow definitions (which may
* be expensive).
* @return the flow definitions
* @throws FlowDefinitionConstructionException if there is a problem constructing
* one of the registered flow definitions
*/
public FlowDefinition[] getFlowDefinitions() throws FlowDefinitionConstructionException;
/**
* Register a flow definition in this registry. Registers a "holder", not
* the Flow definition itself. This allows the actual Flow definition to be
* loaded lazily only when needed, and also rebuilt at runtime when its
* underlying resource changes without redeploy.
* @param flowHolder a holder holding the flow definition to register
*/
public void registerFlowDefinition(FlowDefinitionHolder flowHolder);
/*
* 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.webflow.definition.registry;
import org.springframework.webflow.definition.FlowDefinition;
/**
* A container of flow definitions. Extends the {@link FlowDefinitionRegistryMBean} management interface exposing
* registry monitoring and management operations. Also extends {@link FlowDefinitionLocator} for accessing registered
* Flow definitions for execution at runtime.
* <p>
* Flow definition registries can be configured with a "parent" registry to provide a hook into a larger flow definition
* registry hierarchy.
*
* @author Keith Donald
*/
public interface FlowDefinitionRegistry extends FlowDefinitionLocator, FlowDefinitionRegistryMBean {
/**
* Sets this registry's parent registry. When asked by a client to locate a flow definition this registry will query
* it's parent if it cannot fulfill the lookup request itself.
* @param parent the parent flow definition registry, may be null
*/
public void setParent(FlowDefinitionRegistry parent);
/**
* Return all flow definitions registered in this registry. Note that this will trigger flow assembly for all
* registered flow definitions (which may be expensive).
* @return the flow definitions
* @throws FlowDefinitionConstructionException if there is a problem constructing one of the registered flow
* definitions
*/
public FlowDefinition[] getFlowDefinitions() throws FlowDefinitionConstructionException;
/**
* Register a flow definition in this registry. Registers a "holder", not the Flow definition itself. This allows
* the actual Flow definition to be loaded lazily only when needed, and also rebuilt at runtime when its underlying
* resource changes without redeploy.
* @param flowHolder a holder holding the flow definition to register
*/
public void registerFlowDefinition(FlowDefinitionHolder flowHolder);
}

View File

@@ -1,235 +1,233 @@
/*
* 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.webflow.definition.registry;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.style.ToStringCreator;
import org.springframework.util.Assert;
import org.springframework.webflow.definition.FlowDefinition;
/**
* A generic registry implementation for housing one or more flow definitions.
* <p>
* This registry may be refreshed at runtime to "hot reload" refreshable flow
* definitions. Note that the refresh will only reload already registered
* flow definitions but will not detect any new flow definitions or remove
* flow definitions that no longer exist.
*
* @author Keith Donald
*/
public class FlowDefinitionRegistryImpl implements FlowDefinitionRegistry {
private static final Log logger = LogFactory.getLog(FlowDefinitionRegistryImpl.class);
/**
* The map of loaded Flow definitions maintained in this registry.
*/
private Map flowDefinitions = new TreeMap();
/**
* An optional parent flow definition registry.
*/
private FlowDefinitionRegistry parent;
// implementing FlowDefinitionRegistryMBean
public String[] getFlowDefinitionIds() {
return (String[])flowDefinitions.keySet().toArray(new String[flowDefinitions.size()]);
}
public int getFlowDefinitionCount() {
return flowDefinitions.size();
}
public boolean containsFlowDefinition(String id) {
Assert.hasText(id, "The flow id is required");
return flowDefinitions.get(id) != null;
}
public void refresh() throws FlowDefinitionConstructionException {
if (logger.isDebugEnabled()) {
logger.debug("Refreshing flow definition registry '" + this + "'");
}
ClassLoader loader = Thread.currentThread().getContextClassLoader();
try {
// workaround for JMX
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
LinkedList needsReindexing = new LinkedList();
Iterator it = flowDefinitions.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String key = (String)entry.getKey();
FlowDefinitionHolder holder = (FlowDefinitionHolder)entry.getValue();
holder.refresh();
if (!holder.getFlowDefinitionId().equals(key)) {
needsReindexing.add(new Indexed(key, holder));
}
}
it = needsReindexing.iterator();
while (it.hasNext()) {
Indexed indexed = (Indexed)it.next();
reindex(indexed.holder, indexed.key);
}
}
finally {
Thread.currentThread().setContextClassLoader(loader);
}
}
public void refresh(String flowId)
throws NoSuchFlowDefinitionException, FlowDefinitionConstructionException {
if (logger.isDebugEnabled()) {
logger.debug("Refreshing flow with id '" + flowId + "'");
}
ClassLoader loader = Thread.currentThread().getContextClassLoader();
try {
// workaround for JMX
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
FlowDefinitionHolder holder = getFlowDefinitionHolder(flowId);
holder.refresh();
if (!holder.getFlowDefinitionId().equals(flowId)) {
reindex(holder, flowId);
}
}
finally {
Thread.currentThread().setContextClassLoader(loader);
}
}
// implementing FlowDefinitionLocator
public FlowDefinition getFlowDefinition(String id)
throws NoSuchFlowDefinitionException, FlowDefinitionConstructionException {
Assert.hasText(id,
"Unable to load a flow definition: no flow id was provided. Please provide a valid flow identifier.");
if (logger.isDebugEnabled()) {
logger.debug("Getting flow definition with id '" + id + "'");
}
try {
return getFlowDefinitionHolder(id).getFlowDefinition();
}
catch (NoSuchFlowDefinitionException e) {
if (parent != null) {
// try parent
return parent.getFlowDefinition(id);
}
throw e;
}
}
// implementing FlowDefinitionRegistry
public void setParent(FlowDefinitionRegistry parent) {
if (logger.isDebugEnabled()) {
logger.debug("Setting parent flow definition registry to '" + parent + "'");
}
this.parent = parent;
}
public FlowDefinition[] getFlowDefinitions() throws FlowDefinitionConstructionException {
FlowDefinition[] flows = new FlowDefinition[flowDefinitions.size()];
Iterator it = flowDefinitions.values().iterator();
int i = 0;
while (it.hasNext()) {
FlowDefinitionHolder holder = (FlowDefinitionHolder)it.next();
flows[i] = holder.getFlowDefinition();
i++;
}
return flows;
}
public void registerFlowDefinition(FlowDefinitionHolder flowHolder) {
Assert.notNull(flowHolder, "The flow definition holder to register is required");
if (logger.isDebugEnabled()) {
logger.debug("Registering flow definition with id '" + flowHolder.getFlowDefinitionId() + "'");
}
index(flowHolder);
}
/**
* Remove identified flow definition from this registry. If the given
* id is not known in this registry, nothing will happen.
* @param id the flow definition id
*/
public void removeFlowDefinition(String id) {
Assert.hasText(id, "The flow id is required");
if (logger.isDebugEnabled()) {
logger.debug("Removing flow definition with id '" + id + "'");
}
flowDefinitions.remove(id);
}
// internal helpers
/**
* Reindex given flow definition.
* @param holder the holder holding the flow definition to reindex
* @param oldId the id that was previously assigned to given flow definition
*/
private void reindex(FlowDefinitionHolder holder, String oldId) {
flowDefinitions.remove(oldId);
index(holder);
}
/**
* Index given flow definition.
* @param holder the holder holding the flow definition to index
*/
private void index(FlowDefinitionHolder holder) {
Assert.hasText(holder.getFlowDefinitionId(), "The flow holder to index must return a non-blank flow id");
flowDefinitions.put(holder.getFlowDefinitionId(), holder);
}
/**
* Returns the identified flow definition holder. Throws an exception
* if it cannot be found.
*/
private FlowDefinitionHolder getFlowDefinitionHolder(String id) throws NoSuchFlowDefinitionException {
FlowDefinitionHolder flowHolder = (FlowDefinitionHolder)flowDefinitions.get(id);
if (flowHolder == null) {
throw new NoSuchFlowDefinitionException(id, getFlowDefinitionIds());
}
return flowHolder;
}
/**
* Simple value object that holds the key for an indexed flow definition
* holder in this registry. Used to support reindexing on a refresh.
*
* @author Keith Donald
*/
private static class Indexed {
private String key;
private FlowDefinitionHolder holder;
public Indexed(String key, FlowDefinitionHolder holder) {
this.key = key;
this.holder = holder;
}
}
public String toString() {
return new ToStringCreator(this).append("flowDefinitions", flowDefinitions).append("parent", parent).toString();
}
/*
* 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.webflow.definition.registry;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.style.ToStringCreator;
import org.springframework.util.Assert;
import org.springframework.webflow.definition.FlowDefinition;
/**
* A generic registry implementation for housing one or more flow definitions.
* <p>
* This registry may be refreshed at runtime to "hot reload" refreshable flow definitions. Note that the refresh will
* only reload already registered flow definitions but will not detect any new flow definitions or remove flow
* definitions that no longer exist.
*
* @author Keith Donald
*/
public class FlowDefinitionRegistryImpl implements FlowDefinitionRegistry {
private static final Log logger = LogFactory.getLog(FlowDefinitionRegistryImpl.class);
/**
* The map of loaded Flow definitions maintained in this registry.
*/
private Map flowDefinitions;
/**
* An optional parent flow definition registry.
*/
private FlowDefinitionRegistry parent;
public FlowDefinitionRegistryImpl() {
flowDefinitions = new TreeMap();
}
// implementing FlowDefinitionRegistryMBean
public String[] getFlowDefinitionIds() {
return (String[]) flowDefinitions.keySet().toArray(new String[flowDefinitions.size()]);
}
public int getFlowDefinitionCount() {
return flowDefinitions.size();
}
public boolean containsFlowDefinition(String id) {
Assert.hasText(id, "The flow id is required");
return flowDefinitions.get(id) != null;
}
public void refresh() throws FlowDefinitionConstructionException {
if (logger.isDebugEnabled()) {
logger.debug("Refreshing flow definition registry '" + this + "'");
}
ClassLoader loader = Thread.currentThread().getContextClassLoader();
try {
// workaround for JMX
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
LinkedList needsReindexing = new LinkedList();
Iterator it = flowDefinitions.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
FlowDefinitionHolder holder = (FlowDefinitionHolder) entry.getValue();
holder.refresh();
if (!holder.getFlowDefinitionId().equals(key)) {
needsReindexing.add(new Indexed(key, holder));
}
}
it = needsReindexing.iterator();
while (it.hasNext()) {
Indexed indexed = (Indexed) it.next();
reindex(indexed.holder, indexed.key);
}
} finally {
Thread.currentThread().setContextClassLoader(loader);
}
}
public void refresh(String flowId) throws NoSuchFlowDefinitionException, FlowDefinitionConstructionException {
if (logger.isDebugEnabled()) {
logger.debug("Refreshing flow with id '" + flowId + "'");
}
ClassLoader loader = Thread.currentThread().getContextClassLoader();
try {
// workaround for JMX
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
FlowDefinitionHolder holder = getFlowDefinitionHolder(flowId);
holder.refresh();
if (!holder.getFlowDefinitionId().equals(flowId)) {
reindex(holder, flowId);
}
} finally {
Thread.currentThread().setContextClassLoader(loader);
}
}
// implementing FlowDefinitionLocator
public FlowDefinition getFlowDefinition(String id) throws NoSuchFlowDefinitionException,
FlowDefinitionConstructionException {
Assert.hasText(id,
"Unable to load a flow definition: no flow id was provided. Please provide a valid flow identifier.");
if (logger.isDebugEnabled()) {
logger.debug("Getting flow definition with id '" + id + "'");
}
try {
return getFlowDefinitionHolder(id).getFlowDefinition();
} catch (NoSuchFlowDefinitionException e) {
if (parent != null) {
// try parent
return parent.getFlowDefinition(id);
}
throw e;
}
}
// implementing FlowDefinitionRegistry
public void setParent(FlowDefinitionRegistry parent) {
if (logger.isDebugEnabled()) {
logger.debug("Setting parent flow definition registry to '" + parent + "'");
}
this.parent = parent;
}
public FlowDefinition[] getFlowDefinitions() throws FlowDefinitionConstructionException {
FlowDefinition[] flows = new FlowDefinition[flowDefinitions.size()];
Iterator it = flowDefinitions.values().iterator();
int i = 0;
while (it.hasNext()) {
FlowDefinitionHolder holder = (FlowDefinitionHolder) it.next();
flows[i] = holder.getFlowDefinition();
i++;
}
return flows;
}
public void registerFlowDefinition(FlowDefinitionHolder flowHolder) {
Assert.notNull(flowHolder, "The flow definition holder to register is required");
if (logger.isDebugEnabled()) {
logger.debug("Registering flow definition with id '" + flowHolder.getFlowDefinitionId() + "'");
}
index(flowHolder);
}
/**
* Remove identified flow definition from this registry. If the given id is not known in this registry, nothing will
* happen.
* @param id the flow definition id
*/
public void removeFlowDefinition(String id) {
Assert.hasText(id, "The flow id is required");
if (logger.isDebugEnabled()) {
logger.debug("Removing flow definition with id '" + id + "'");
}
flowDefinitions.remove(id);
}
// internal helpers
/**
* Reindex given flow definition.
* @param holder the holder holding the flow definition to reindex
* @param oldId the id that was previously assigned to given flow definition
*/
private void reindex(FlowDefinitionHolder holder, String oldId) {
flowDefinitions.remove(oldId);
index(holder);
}
/**
* Index given flow definition.
* @param holder the holder holding the flow definition to index
*/
private void index(FlowDefinitionHolder holder) {
Assert.hasText(holder.getFlowDefinitionId(), "The flow holder to index must return a non-blank flow id");
flowDefinitions.put(holder.getFlowDefinitionId(), holder);
}
/**
* Returns the identified flow definition holder. Throws an exception if it cannot be found.
*/
private FlowDefinitionHolder getFlowDefinitionHolder(String id) throws NoSuchFlowDefinitionException {
FlowDefinitionHolder flowHolder = (FlowDefinitionHolder) flowDefinitions.get(id);
if (flowHolder == null) {
throw new NoSuchFlowDefinitionException(id, getFlowDefinitionIds());
}
return flowHolder;
}
/**
* Simple value object that holds the key for an indexed flow definition holder in this registry. Used to support
* reindexing on a refresh.
*
* @author Keith Donald
*/
private static class Indexed {
private String key;
private FlowDefinitionHolder holder;
public Indexed(String key, FlowDefinitionHolder holder) {
this.key = key;
this.holder = holder;
}
}
public String toString() {
return new ToStringCreator(this).append("flowDefinitions", flowDefinitions).append("parent", parent).toString();
}
}

View File

@@ -1,118 +1,111 @@
/*
* 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.webflow.engine.support;
import org.springframework.binding.expression.EvaluationContext;
import org.springframework.binding.expression.EvaluationException;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.SettableExpression;
import org.springframework.core.style.ToStringCreator;
import org.springframework.util.Assert;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.MutableAttributeMap;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.ScopeType;
/**
* Expression evaluator that can evalute attribute maps and supported
* request context scope types.
*
* @see org.springframework.webflow.execution.RequestContext
* @see org.springframework.webflow.core.collection.AttributeMap
*
* @author Keith Donald
* @author Erwin Vervaet
*/
public class AttributeExpression implements SettableExpression {
/**
* The expression to evaluate.
*/
private Expression expression;
/**
* The scope type.
*/
private ScopeType scopeType;
/**
* Create a new expression evaluator that executes given expression in an
* attribute map. When using this wrapper to set a property value, make
* sure the given expression is a {@link SettableExpression}}.
* @param expression the nested evaluator to execute
*/
public AttributeExpression(Expression expression) {
this(expression, null);
}
/**
* Create a new expression evaluator that executes given expression in the
* specified scope. When using this wrapper to set a property value, make
* sure the given expression is a {@link SettableExpression}}.
* @param expression the nested evaluator to execute
* @param scopeType the scopeType
*/
public AttributeExpression(Expression expression, ScopeType scopeType) {
this.expression = expression;
this.scopeType = scopeType;
}
/**
* Returns the expression that will be evaluated.
*/
protected Expression getExpression() {
return expression;
}
public Object evaluate(Object target, EvaluationContext context) throws EvaluationException {
if (target instanceof RequestContext) {
RequestContext requestContext = (RequestContext)target;
AttributeMap scope = scopeType.getScope(requestContext);
return expression.evaluate(scope, context);
}
else if (target instanceof AttributeMap) {
return expression.evaluate(target, context);
}
else {
throw new IllegalArgumentException(
"Only supports evaluation against a [RequestContext] or [AttributeMap] instance, but was a ["
+ target.getClass() + "]");
}
}
public void evaluateToSet(Object target, Object value, EvaluationContext context) throws EvaluationException {
Assert.isInstanceOf(SettableExpression.class, expression,
"When an AttributeExpression is used to set a property value, the nested expression needs "
+ "to be a SettableExpression");
if (target instanceof RequestContext) {
RequestContext requestContext = (RequestContext)target;
MutableAttributeMap scope = scopeType.getScope(requestContext);
((SettableExpression)expression).evaluateToSet(scope, value, context);
}
else if (target instanceof AttributeMap) {
((SettableExpression)expression).evaluateToSet(target, value, context);
}
else {
throw new IllegalArgumentException(
"Only supports evaluation against a [RequestContext] or [AttributeMap] instance, but was a ["
+ target.getClass() + "]");
}
}
public String toString() {
return new ToStringCreator(this).append("expression", expression).toString();
}
/*
* 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.webflow.engine.support;
import org.springframework.binding.expression.EvaluationContext;
import org.springframework.binding.expression.EvaluationException;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.SettableExpression;
import org.springframework.core.style.ToStringCreator;
import org.springframework.util.Assert;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.MutableAttributeMap;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.ScopeType;
/**
* Expression evaluator that can evaluate attribute maps and supported request context scope types.
*
* @see org.springframework.webflow.execution.RequestContext
* @see org.springframework.webflow.core.collection.AttributeMap
*
* @author Keith Donald
* @author Erwin Vervaet
*/
public class AttributeExpression implements SettableExpression {
/**
* The expression to evaluate.
*/
private Expression expression;
/**
* The scope type.
*/
private ScopeType scopeType;
/**
* Create a new expression evaluator that executes given expression in an attribute map. When using this wrapper to
* set a property value, make sure the given expression is a {@link SettableExpression}}.
* @param expression the nested evaluator to execute
*/
public AttributeExpression(Expression expression) {
this(expression, null);
}
/**
* Create a new expression evaluator that executes given expression in the specified scope. When using this wrapper
* to set a property value, make sure the given expression is a {@link SettableExpression}}.
* @param expression the nested evaluator to execute
* @param scopeType the scopeType
*/
public AttributeExpression(Expression expression, ScopeType scopeType) {
this.expression = expression;
this.scopeType = scopeType;
}
/**
* Returns the expression that will be evaluated.
*/
protected Expression getExpression() {
return expression;
}
public Object evaluate(Object target, EvaluationContext context) throws EvaluationException {
if (target instanceof RequestContext) {
RequestContext requestContext = (RequestContext) target;
AttributeMap scope = scopeType.getScope(requestContext);
return expression.evaluate(scope, context);
} else if (target instanceof AttributeMap) {
return expression.evaluate(target, context);
} else {
throw new IllegalArgumentException(
"Only supports evaluation against a [RequestContext] or [AttributeMap] instance, but was a ["
+ target.getClass() + "]");
}
}
public void evaluateToSet(Object target, Object value, EvaluationContext context) throws EvaluationException {
Assert.isInstanceOf(SettableExpression.class, expression,
"When an AttributeExpression is used to set a property value, the nested expression needs "
+ "to be a SettableExpression");
if (target instanceof RequestContext) {
RequestContext requestContext = (RequestContext) target;
MutableAttributeMap scope = scopeType.getScope(requestContext);
((SettableExpression) expression).evaluateToSet(scope, value, context);
} else if (target instanceof AttributeMap) {
((SettableExpression) expression).evaluateToSet(target, value, context);
} else {
throw new IllegalArgumentException(
"Only supports evaluation against a [RequestContext] or [AttributeMap] instance, but was a ["
+ target.getClass() + "]");
}
}
public String toString() {
return new ToStringCreator(this).append("expression", expression).toString();
}
}

View File

@@ -1,87 +1,84 @@
/*
* 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.webflow.engine.support;
import java.io.Serializable;
import org.springframework.util.Assert;
import org.springframework.webflow.engine.TransitionCriteria;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
/**
* Simple transition criteria that matches on an eventId and nothing else.
* Specifically, if the id of the last event that occured equals
* {@link #getEventId()} this criteria will return true.
*
* @see RequestContext#getLastEvent()
*
* @author Erwin Vervaet
* @author Keith Donald
*/
public class EventIdTransitionCriteria implements TransitionCriteria, Serializable {
/**
* The event id to match.
*/
private String eventId;
/**
* Whether or not to match case sensitively. Default is true.
*/
private boolean caseSensitive = true;
/**
* Create a new event id matching criteria object.
* @param eventId the event id
*/
public EventIdTransitionCriteria(String eventId) {
Assert.hasText(eventId, "The event id is required");
this.eventId = eventId;
}
/**
* Returns the event id to match.
*/
public String getEventId() {
return eventId;
}
/**
* Set whether or not the event id should be matched in a case sensitve
* manner. Defaults to true.
*/
public void setCaseSensitive(boolean caseSensitive) {
this.caseSensitive = caseSensitive;
}
public boolean test(RequestContext context) {
Event lastEvent = context.getLastEvent();
if (lastEvent == null) {
return false;
}
if (caseSensitive) {
return eventId.equals(lastEvent.getId());
}
else {
return eventId.equalsIgnoreCase(lastEvent.getId());
}
}
public String toString() {
return "[eventId = '" + eventId + "']";
}
/*
* 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.webflow.engine.support;
import java.io.Serializable;
import org.springframework.util.Assert;
import org.springframework.webflow.engine.TransitionCriteria;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
/**
* Simple transition criteria that matches on an eventId and nothing else. Specifically, if the id of the last event
* that occurred equals {@link #getEventId()} this criteria will return true.
*
* @see RequestContext#getLastEvent()
*
* @author Erwin Vervaet
* @author Keith Donald
*/
public class EventIdTransitionCriteria implements TransitionCriteria, Serializable {
/**
* The event id to match.
*/
private String eventId;
/**
* Whether or not to match case sensitively. Default is true.
*/
private boolean caseSensitive = true;
/**
* Create a new event id matching criteria object.
* @param eventId the event id
*/
public EventIdTransitionCriteria(String eventId) {
Assert.hasText(eventId, "The event id is required");
this.eventId = eventId;
}
/**
* Returns the event id to match.
*/
public String getEventId() {
return eventId;
}
/**
* Set whether or not the event id should be matched in a case sensitive manner. Defaults to true.
*/
public void setCaseSensitive(boolean caseSensitive) {
this.caseSensitive = caseSensitive;
}
public boolean test(RequestContext context) {
Event lastEvent = context.getLastEvent();
if (lastEvent == null) {
return false;
}
if (caseSensitive) {
return eventId.equals(lastEvent.getId());
} else {
return eventId.equalsIgnoreCase(lastEvent.getId());
}
}
public String toString() {
return "[eventId = '" + eventId + "']";
}
}

View File

@@ -1,112 +1,104 @@
/*
* 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.webflow.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Simple utility class for working with the java reflection API. Only intended for
* internal use. Will likely disappear in a future release of Spring Web Flow and
* simply rely on {@link org.springframework.util.ReflectionUtils} if necessary.
*
* @author Keith Donald
*/
public class ReflectionUtils {
/**
* Invoke the specified {@link Method} against the supplied target object
* with no arguments. The target object can be <code>null</code> when
* invoking a static {@link Method}. All exceptions are treated as fatal and will be
* converted to unchecked exceptions.
* @see #invokeMethod(java.lang.reflect.Method, Object, Object[])
* @throws RuntimeException when something goes wrong invoking the method or
* when the method itself throws an exception
*/
public static Object invokeMethod(Method method, Object target) throws RuntimeException {
return invokeMethod(method, target, null);
}
/**
* Invoke the specified {@link Method} against the supplied target object
* with the supplied arguments. The target object can be null when invoking a
* static {@link Method}. All exceptions are treated as fatal and will be
* converted to unchecked exceptions.
* @see #invokeMethod(java.lang.reflect.Method, Object, Object[])
* @throws RuntimeException when something goes wrong invoking the method or
* when the method itself throws an exception
*/
public static Object invokeMethod(Method method, Object target, Object[] args) throws RuntimeException {
try {
return method.invoke(target, args);
}
catch (IllegalAccessException ex) {
handleReflectionException(ex);
throw new IllegalStateException("Unexpected reflection exception - " + ex.getClass().getName() + ": "
+ ex.getMessage());
}
catch (InvocationTargetException ex) {
handleReflectionException(ex);
throw new IllegalStateException("Unexpected reflection exception - " + ex.getClass().getName() + ": "
+ ex.getMessage());
}
}
/**
* Handle the given reflection exception.
* Should only be called if no checked exception is expected to
* be thrown by the target method.
* <p>
* Throws the underlying RuntimeException or Error in case
* of an InvocationTargetException with such a root cause. Throws
* an IllegalStateException with an appropriate message else.
* @param ex the reflection exception to handle
*/
private static void handleReflectionException(Exception ex) {
if (ex instanceof NoSuchMethodException) {
throw new IllegalStateException("Method not found: " + ex.getMessage());
}
if (ex instanceof IllegalAccessException) {
throw new IllegalStateException("Could not access method: " + ex.getMessage());
}
if (ex instanceof InvocationTargetException) {
handleInvocationTargetException((InvocationTargetException) ex);
}
throw new IllegalStateException(
"Unexpected reflection exception - " + ex.getClass().getName() + ": " + ex.getMessage());
}
/**
* Handle the given invocation target exception.
* Should only be called if no checked exception is expected to
* be thrown by the target method.
* <p>
* Throws the underlying RuntimeException or Error in case
* of such a root cause. Throws an IllegalStateException else.
* @param ex the invocation target exception to handle
*/
private static void handleInvocationTargetException(InvocationTargetException ex) {
if (ex.getTargetException() instanceof RuntimeException) {
throw (RuntimeException) ex.getTargetException();
}
if (ex.getTargetException() instanceof Error) {
throw (Error) ex.getTargetException();
}
throw new IllegalStateException(
"Unexpected exception thrown by method - " + ex.getTargetException().getClass().getName() +
": " + ex.getTargetException().getMessage());
}
/*
* 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.webflow.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Simple utility class for working with the java reflection API. Only intended for internal use. Will likely disappear
* in a future release of Spring Web Flow and simply rely on {@link org.springframework.util.ReflectionUtils} if
* necessary.
*
* @author Keith Donald
*/
public class ReflectionUtils {
/**
* Invoke the specified {@link Method} against the supplied target object with no arguments. The target object can
* be <code>null</code> when invoking a static {@link Method}. All exceptions are treated as fatal and will be
* converted to unchecked exceptions.
* @see #invokeMethod(java.lang.reflect.Method, Object, Object[])
* @throws RuntimeException when something goes wrong invoking the method or when the method itself throws an
* exception
*/
public static Object invokeMethod(Method method, Object target) throws RuntimeException {
return invokeMethod(method, target, null);
}
/**
* Invoke the specified {@link Method} against the supplied target object with the supplied arguments. The target
* object can be null when invoking a static {@link Method}. All exceptions are treated as fatal and will be
* converted to unchecked exceptions.
* @see #invokeMethod(java.lang.reflect.Method, Object, Object[])
* @throws RuntimeException when something goes wrong invoking the method or when the method itself throws an
* exception
*/
public static Object invokeMethod(Method method, Object target, Object[] args) throws RuntimeException {
try {
return method.invoke(target, args);
} catch (IllegalAccessException ex) {
handleReflectionException(ex);
throw new IllegalStateException("Unexpected reflection exception - " + ex.getClass().getName() + ": "
+ ex.getMessage());
} catch (InvocationTargetException ex) {
handleReflectionException(ex);
throw new IllegalStateException("Unexpected reflection exception - " + ex.getClass().getName() + ": "
+ ex.getMessage());
}
}
/**
* Handle the given reflection exception. Should only be called if no checked exception is expected to be thrown by
* the target method.
* <p>
* Throws the underlying RuntimeException or Error in case of an InvocationTargetException with such a root cause.
* Throws an IllegalStateException with an appropriate message else.
* @param ex the reflection exception to handle
*/
private static void handleReflectionException(Exception ex) {
if (ex instanceof NoSuchMethodException) {
throw new IllegalStateException("Method not found: " + ex.getMessage());
}
if (ex instanceof IllegalAccessException) {
throw new IllegalStateException("Could not access method: " + ex.getMessage());
}
if (ex instanceof InvocationTargetException) {
handleInvocationTargetException((InvocationTargetException) ex);
}
throw new IllegalStateException("Unexpected reflection exception - " + ex.getClass().getName() + ": "
+ ex.getMessage());
}
/**
* Handle the given invocation target exception. Should only be called if no checked exception is expected to be
* thrown by the target method.
* <p>
* Throws the underlying RuntimeException or Error in case of such a root cause. Throws an IllegalStateException
* else.
* @param ex the invocation target exception to handle
*/
private static void handleInvocationTargetException(InvocationTargetException ex) {
if (ex.getTargetException() instanceof RuntimeException) {
throw (RuntimeException) ex.getTargetException();
}
if (ex.getTargetException() instanceof Error) {
throw (Error) ex.getTargetException();
}
throw new IllegalStateException("Unexpected exception thrown by method - "
+ ex.getTargetException().getClass().getName() + ": " + ex.getTargetException().getMessage());
}
}