Per CONTRIBUTING, convert text files to use LF instead of CRLF
It is easier to standardise this now in one commit rather than during later bulk changes where it would complicate the review process. This is literally the result of running "dos2unix" on appropriate files. There is no attempt here to likewise standardise the spaces/tabs conventions in the codebase.
This commit is contained in:
@@ -1,45 +1,45 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.binding.collection;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A simple subinterface of {@link Map} that exposes a mutex that application code can synchronize on.
|
||||
* <p>
|
||||
* Expected to be implemented by Maps that are backed by shared objects that require synchronization between multiple
|
||||
* threads. An example would be the HTTP session map.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface SharedMap<K, V> extends Map<K, V> {
|
||||
|
||||
/**
|
||||
* Returns the shared mutex that may be synchronized on using a synchronized block. The returned mutex is guaranteed
|
||||
* to be non-null.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* <pre>
|
||||
* synchronized (sharedMap.getMutex()) {
|
||||
* // do synchronized work
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @return the mutex
|
||||
*/
|
||||
Object getMutex();
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.binding.collection;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A simple subinterface of {@link Map} that exposes a mutex that application code can synchronize on.
|
||||
* <p>
|
||||
* Expected to be implemented by Maps that are backed by shared objects that require synchronization between multiple
|
||||
* threads. An example would be the HTTP session map.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface SharedMap<K, V> extends Map<K, V> {
|
||||
|
||||
/**
|
||||
* Returns the shared mutex that may be synchronized on using a synchronized block. The returned mutex is guaranteed
|
||||
* to be non-null.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* <pre>
|
||||
* synchronized (sharedMap.getMutex()) {
|
||||
* // do synchronized work
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @return the mutex
|
||||
*/
|
||||
Object getMutex();
|
||||
}
|
||||
|
||||
@@ -1,105 +1,105 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.binding.collection;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
|
||||
/**
|
||||
* A map decorator that implements <code>SharedMap</code>. By default, simply returns the map itself as the mutex.
|
||||
* Subclasses may override to return a different mutex object.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class SharedMapDecorator<K, V> implements SharedMap<K, V>, Serializable {
|
||||
|
||||
/**
|
||||
* The wrapped, target map.
|
||||
*/
|
||||
private Map<K, V> map;
|
||||
|
||||
/**
|
||||
* Creates a new shared map decorator.
|
||||
* @param map the map that is shared by multiple threads, to be synced
|
||||
*/
|
||||
public SharedMapDecorator(Map<K, V> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
// implementing Map
|
||||
|
||||
public void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
return map.containsKey(key);
|
||||
}
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
return map.containsValue(value);
|
||||
}
|
||||
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
return map.entrySet();
|
||||
}
|
||||
|
||||
public V get(Object key) {
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
public Set<K> keySet() {
|
||||
return map.keySet();
|
||||
}
|
||||
|
||||
public V put(K key, V value) {
|
||||
return map.put(key, value);
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends K, ? extends V> map) {
|
||||
this.map.putAll(map);
|
||||
}
|
||||
|
||||
public V remove(Object key) {
|
||||
return map.remove(key);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public Collection<V> values() {
|
||||
return map.values();
|
||||
}
|
||||
|
||||
// implementing SharedMap
|
||||
|
||||
public Object getMutex() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("map", map).append("mutex", getMutex()).toString();
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.binding.collection;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
|
||||
/**
|
||||
* A map decorator that implements <code>SharedMap</code>. By default, simply returns the map itself as the mutex.
|
||||
* Subclasses may override to return a different mutex object.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class SharedMapDecorator<K, V> implements SharedMap<K, V>, Serializable {
|
||||
|
||||
/**
|
||||
* The wrapped, target map.
|
||||
*/
|
||||
private Map<K, V> map;
|
||||
|
||||
/**
|
||||
* Creates a new shared map decorator.
|
||||
* @param map the map that is shared by multiple threads, to be synced
|
||||
*/
|
||||
public SharedMapDecorator(Map<K, V> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
// implementing Map
|
||||
|
||||
public void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
return map.containsKey(key);
|
||||
}
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
return map.containsValue(value);
|
||||
}
|
||||
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
return map.entrySet();
|
||||
}
|
||||
|
||||
public V get(Object key) {
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
public Set<K> keySet() {
|
||||
return map.keySet();
|
||||
}
|
||||
|
||||
public V put(K key, V value) {
|
||||
return map.put(key, value);
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends K, ? extends V> map) {
|
||||
this.map.putAll(map);
|
||||
}
|
||||
|
||||
public V remove(Object key) {
|
||||
return map.remove(key);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public Collection<V> values() {
|
||||
return map.values();
|
||||
}
|
||||
|
||||
// implementing SharedMap
|
||||
|
||||
public Object getMutex() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("map", map).append("mutex", getMutex()).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,289 +1,289 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.binding.collection;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Base class for map adapters whose keys are String values. Concrete classes need only implement the abstract hook
|
||||
* methods defined by this class.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public abstract class StringKeyedMapAdapter<V> implements Map<String, V> {
|
||||
|
||||
private Set<String> keySet;
|
||||
|
||||
private Collection<V> values;
|
||||
|
||||
private Set<Entry<String, V>> entrySet;
|
||||
|
||||
// implementing Map
|
||||
|
||||
public void clear() {
|
||||
for (Iterator<String> it = getAttributeNames(); it.hasNext();) {
|
||||
removeAttribute(it.next());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
return getAttribute(key.toString()) != null;
|
||||
}
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
for (Iterator<String> it = getAttributeNames(); it.hasNext();) {
|
||||
Object aValue = getAttribute(it.next());
|
||||
if (value.equals(aValue)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Set<Entry<String, V>> entrySet() {
|
||||
return (entrySet != null) ? entrySet : (entrySet = new EntrySet());
|
||||
}
|
||||
|
||||
public V get(Object key) {
|
||||
return getAttribute(key.toString());
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return !getAttributeNames().hasNext();
|
||||
}
|
||||
|
||||
public Set<String> keySet() {
|
||||
return (keySet != null) ? keySet : (keySet = new KeySet());
|
||||
}
|
||||
|
||||
public V put(String key, V value) {
|
||||
String stringKey = String.valueOf(key);
|
||||
V previousValue = getAttribute(stringKey);
|
||||
setAttribute(stringKey, value);
|
||||
return previousValue;
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends String, ? extends V> map) {
|
||||
for (Entry<? extends String, ? extends V> entry : map.entrySet()) {
|
||||
setAttribute(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public V remove(Object key) {
|
||||
String stringKey = key.toString();
|
||||
V retval = getAttribute(stringKey);
|
||||
removeAttribute(stringKey);
|
||||
return retval;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
int size = 0;
|
||||
for (Iterator<String> it = getAttributeNames(); it.hasNext();) {
|
||||
size++;
|
||||
it.next();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public Collection<V> values() {
|
||||
return (values != null) ? values : (values = new Values());
|
||||
}
|
||||
|
||||
// hook methods
|
||||
|
||||
/**
|
||||
* Hook method that needs to be implemented by concrete subclasses. Gets a value associated with a key.
|
||||
* @param key the key to lookup
|
||||
* @return the associated value, or null if none
|
||||
*/
|
||||
protected abstract V getAttribute(String key);
|
||||
|
||||
/**
|
||||
* Hook method that needs to be implemented by concrete subclasses. Puts a key-value pair in the map, overwriting
|
||||
* any possible earlier value associated with the same key.
|
||||
* @param key the key to associate the value with
|
||||
* @param value the value to associate with the key
|
||||
*/
|
||||
protected abstract void setAttribute(String key, V value);
|
||||
|
||||
/**
|
||||
* Hook method that needs to be implemented by concrete subclasses. Removes a key and its associated value from the
|
||||
* map.
|
||||
* @param key the key to remove
|
||||
*/
|
||||
protected abstract void removeAttribute(String key);
|
||||
|
||||
/**
|
||||
* Hook method that needs to be implemented by concrete subclasses. Returns an enumeration listing all keys known to
|
||||
* the map.
|
||||
* @return the key enumeration
|
||||
*/
|
||||
protected abstract Iterator<String> getAttributeNames();
|
||||
|
||||
// internal helper classes
|
||||
|
||||
private abstract class AbstractSet<T> extends java.util.AbstractSet<T> {
|
||||
public boolean isEmpty() {
|
||||
return StringKeyedMapAdapter.this.isEmpty();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return StringKeyedMapAdapter.this.size();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
StringKeyedMapAdapter.this.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private class KeySet extends AbstractSet<String> {
|
||||
public Iterator<String> iterator() {
|
||||
return new KeyIterator();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return StringKeyedMapAdapter.this.containsKey(o);
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
return StringKeyedMapAdapter.this.remove(o) != null;
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class AbstractKeyIterator {
|
||||
private final Iterator<String> it = getAttributeNames();
|
||||
|
||||
private String currentKey;
|
||||
|
||||
public void remove() {
|
||||
if (currentKey == null) {
|
||||
throw new NoSuchElementException("You must call next() at least once");
|
||||
}
|
||||
StringKeyedMapAdapter.this.remove(currentKey);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
protected String nextKey() {
|
||||
return currentKey = it.next();
|
||||
}
|
||||
}
|
||||
|
||||
private class KeyIterator extends AbstractKeyIterator implements Iterator<String> {
|
||||
public String next() {
|
||||
return nextKey();
|
||||
}
|
||||
}
|
||||
|
||||
private class Values extends AbstractSet<V> {
|
||||
public Iterator<V> iterator() {
|
||||
return new ValuesIterator();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return StringKeyedMapAdapter.this.containsValue(o);
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
for (Iterator<V> it = iterator(); it.hasNext();) {
|
||||
if (o.equals(it.next())) {
|
||||
it.remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class ValuesIterator extends AbstractKeyIterator implements Iterator<V> {
|
||||
public V next() {
|
||||
return StringKeyedMapAdapter.this.get(nextKey());
|
||||
}
|
||||
}
|
||||
|
||||
private class EntrySet extends AbstractSet<Entry<String, V>> {
|
||||
public Iterator<Entry<String, V>> iterator() {
|
||||
return new EntryIterator();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
Entry<String, V> entry = getAsEntry(o);
|
||||
if (entry == null || entry.getKey() == null || entry.getValue() == null) {
|
||||
return false;
|
||||
}
|
||||
V valueFromThisMap = StringKeyedMapAdapter.this.get(entry.getKey());
|
||||
return entry.getValue().equals(valueFromThisMap);
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
Entry<String, V> entry = getAsEntry(o);
|
||||
if (entry == null || entry.getKey() == null || entry.getValue() == null) {
|
||||
return false;
|
||||
}
|
||||
V valueFromThisMap = StringKeyedMapAdapter.this.get(entry.getKey());
|
||||
if (!entry.getValue().equals(valueFromThisMap)) {
|
||||
return false;
|
||||
}
|
||||
return StringKeyedMapAdapter.this.remove(entry.getKey()) != null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Entry<String, V> getAsEntry(Object o) {
|
||||
if (o instanceof Entry) {
|
||||
return (Entry<String, V>) o;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class EntryIterator extends AbstractKeyIterator implements Iterator<Entry<String, V>> {
|
||||
public Entry<String, V> next() {
|
||||
return new EntrySetEntry(nextKey());
|
||||
}
|
||||
}
|
||||
|
||||
private class EntrySetEntry implements Entry<String, V> {
|
||||
private final String currentKey;
|
||||
|
||||
public EntrySetEntry(String currentKey) {
|
||||
this.currentKey = currentKey;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return currentKey;
|
||||
}
|
||||
|
||||
public V getValue() {
|
||||
return StringKeyedMapAdapter.this.get(currentKey);
|
||||
}
|
||||
|
||||
public V setValue(V value) {
|
||||
return StringKeyedMapAdapter.this.put(currentKey, value);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.binding.collection;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Base class for map adapters whose keys are String values. Concrete classes need only implement the abstract hook
|
||||
* methods defined by this class.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public abstract class StringKeyedMapAdapter<V> implements Map<String, V> {
|
||||
|
||||
private Set<String> keySet;
|
||||
|
||||
private Collection<V> values;
|
||||
|
||||
private Set<Entry<String, V>> entrySet;
|
||||
|
||||
// implementing Map
|
||||
|
||||
public void clear() {
|
||||
for (Iterator<String> it = getAttributeNames(); it.hasNext();) {
|
||||
removeAttribute(it.next());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
return getAttribute(key.toString()) != null;
|
||||
}
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
for (Iterator<String> it = getAttributeNames(); it.hasNext();) {
|
||||
Object aValue = getAttribute(it.next());
|
||||
if (value.equals(aValue)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Set<Entry<String, V>> entrySet() {
|
||||
return (entrySet != null) ? entrySet : (entrySet = new EntrySet());
|
||||
}
|
||||
|
||||
public V get(Object key) {
|
||||
return getAttribute(key.toString());
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return !getAttributeNames().hasNext();
|
||||
}
|
||||
|
||||
public Set<String> keySet() {
|
||||
return (keySet != null) ? keySet : (keySet = new KeySet());
|
||||
}
|
||||
|
||||
public V put(String key, V value) {
|
||||
String stringKey = String.valueOf(key);
|
||||
V previousValue = getAttribute(stringKey);
|
||||
setAttribute(stringKey, value);
|
||||
return previousValue;
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends String, ? extends V> map) {
|
||||
for (Entry<? extends String, ? extends V> entry : map.entrySet()) {
|
||||
setAttribute(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public V remove(Object key) {
|
||||
String stringKey = key.toString();
|
||||
V retval = getAttribute(stringKey);
|
||||
removeAttribute(stringKey);
|
||||
return retval;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
int size = 0;
|
||||
for (Iterator<String> it = getAttributeNames(); it.hasNext();) {
|
||||
size++;
|
||||
it.next();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public Collection<V> values() {
|
||||
return (values != null) ? values : (values = new Values());
|
||||
}
|
||||
|
||||
// hook methods
|
||||
|
||||
/**
|
||||
* Hook method that needs to be implemented by concrete subclasses. Gets a value associated with a key.
|
||||
* @param key the key to lookup
|
||||
* @return the associated value, or null if none
|
||||
*/
|
||||
protected abstract V getAttribute(String key);
|
||||
|
||||
/**
|
||||
* Hook method that needs to be implemented by concrete subclasses. Puts a key-value pair in the map, overwriting
|
||||
* any possible earlier value associated with the same key.
|
||||
* @param key the key to associate the value with
|
||||
* @param value the value to associate with the key
|
||||
*/
|
||||
protected abstract void setAttribute(String key, V value);
|
||||
|
||||
/**
|
||||
* Hook method that needs to be implemented by concrete subclasses. Removes a key and its associated value from the
|
||||
* map.
|
||||
* @param key the key to remove
|
||||
*/
|
||||
protected abstract void removeAttribute(String key);
|
||||
|
||||
/**
|
||||
* Hook method that needs to be implemented by concrete subclasses. Returns an enumeration listing all keys known to
|
||||
* the map.
|
||||
* @return the key enumeration
|
||||
*/
|
||||
protected abstract Iterator<String> getAttributeNames();
|
||||
|
||||
// internal helper classes
|
||||
|
||||
private abstract class AbstractSet<T> extends java.util.AbstractSet<T> {
|
||||
public boolean isEmpty() {
|
||||
return StringKeyedMapAdapter.this.isEmpty();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return StringKeyedMapAdapter.this.size();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
StringKeyedMapAdapter.this.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private class KeySet extends AbstractSet<String> {
|
||||
public Iterator<String> iterator() {
|
||||
return new KeyIterator();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return StringKeyedMapAdapter.this.containsKey(o);
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
return StringKeyedMapAdapter.this.remove(o) != null;
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class AbstractKeyIterator {
|
||||
private final Iterator<String> it = getAttributeNames();
|
||||
|
||||
private String currentKey;
|
||||
|
||||
public void remove() {
|
||||
if (currentKey == null) {
|
||||
throw new NoSuchElementException("You must call next() at least once");
|
||||
}
|
||||
StringKeyedMapAdapter.this.remove(currentKey);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
protected String nextKey() {
|
||||
return currentKey = it.next();
|
||||
}
|
||||
}
|
||||
|
||||
private class KeyIterator extends AbstractKeyIterator implements Iterator<String> {
|
||||
public String next() {
|
||||
return nextKey();
|
||||
}
|
||||
}
|
||||
|
||||
private class Values extends AbstractSet<V> {
|
||||
public Iterator<V> iterator() {
|
||||
return new ValuesIterator();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return StringKeyedMapAdapter.this.containsValue(o);
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
for (Iterator<V> it = iterator(); it.hasNext();) {
|
||||
if (o.equals(it.next())) {
|
||||
it.remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class ValuesIterator extends AbstractKeyIterator implements Iterator<V> {
|
||||
public V next() {
|
||||
return StringKeyedMapAdapter.this.get(nextKey());
|
||||
}
|
||||
}
|
||||
|
||||
private class EntrySet extends AbstractSet<Entry<String, V>> {
|
||||
public Iterator<Entry<String, V>> iterator() {
|
||||
return new EntryIterator();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
Entry<String, V> entry = getAsEntry(o);
|
||||
if (entry == null || entry.getKey() == null || entry.getValue() == null) {
|
||||
return false;
|
||||
}
|
||||
V valueFromThisMap = StringKeyedMapAdapter.this.get(entry.getKey());
|
||||
return entry.getValue().equals(valueFromThisMap);
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
Entry<String, V> entry = getAsEntry(o);
|
||||
if (entry == null || entry.getKey() == null || entry.getValue() == null) {
|
||||
return false;
|
||||
}
|
||||
V valueFromThisMap = StringKeyedMapAdapter.this.get(entry.getKey());
|
||||
if (!entry.getValue().equals(valueFromThisMap)) {
|
||||
return false;
|
||||
}
|
||||
return StringKeyedMapAdapter.this.remove(entry.getKey()) != null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Entry<String, V> getAsEntry(Object o) {
|
||||
if (o instanceof Entry) {
|
||||
return (Entry<String, V>) o;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class EntryIterator extends AbstractKeyIterator implements Iterator<Entry<String, V>> {
|
||||
public Entry<String, V> next() {
|
||||
return new EntrySetEntry(nextKey());
|
||||
}
|
||||
}
|
||||
|
||||
private class EntrySetEntry implements Entry<String, V> {
|
||||
private final String currentKey;
|
||||
|
||||
public EntrySetEntry(String currentKey) {
|
||||
this.currentKey = currentKey;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return currentKey;
|
||||
}
|
||||
|
||||
public V getValue() {
|
||||
return StringKeyedMapAdapter.this.get(currentKey);
|
||||
}
|
||||
|
||||
public V setValue(V value) {
|
||||
return StringKeyedMapAdapter.this.put(currentKey, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,58 +1,58 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.binding.convert.service;
|
||||
|
||||
import org.springframework.binding.convert.converters.Converter;
|
||||
|
||||
/**
|
||||
* Package private converter that is a "no op".
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
class NoOpConverter implements Converter {
|
||||
|
||||
private Class<?> sourceClass;
|
||||
|
||||
private Class<?> targetClass;
|
||||
|
||||
/**
|
||||
* Create a "no op" converter from given source to given target class.
|
||||
*/
|
||||
public NoOpConverter(Class<?> sourceClass, Class<?> targetClass) {
|
||||
this.sourceClass = sourceClass;
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
|
||||
public Class<?> getSourceClass() {
|
||||
return sourceClass;
|
||||
}
|
||||
|
||||
public Class<?> getTargetClass() {
|
||||
return targetClass;
|
||||
}
|
||||
|
||||
public Object convertSourceToTargetClass(Object source, Class<?> targetClass) {
|
||||
return source;
|
||||
}
|
||||
|
||||
public boolean isTwoWay() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Object convertTargetToSourceClass(Object target, Class<?> sourceClass) {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.binding.convert.service;
|
||||
|
||||
import org.springframework.binding.convert.converters.Converter;
|
||||
|
||||
/**
|
||||
* Package private converter that is a "no op".
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
class NoOpConverter implements Converter {
|
||||
|
||||
private Class<?> sourceClass;
|
||||
|
||||
private Class<?> targetClass;
|
||||
|
||||
/**
|
||||
* Create a "no op" converter from given source to given target class.
|
||||
*/
|
||||
public NoOpConverter(Class<?> sourceClass, Class<?> targetClass) {
|
||||
this.sourceClass = sourceClass;
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
|
||||
public Class<?> getSourceClass() {
|
||||
return sourceClass;
|
||||
}
|
||||
|
||||
public Class<?> getTargetClass() {
|
||||
return targetClass;
|
||||
}
|
||||
|
||||
public Object convertSourceToTargetClass(Object source, Class<?> targetClass) {
|
||||
return source;
|
||||
}
|
||||
|
||||
public boolean isTwoWay() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Object convertTargetToSourceClass(Object target, Class<?> sourceClass) {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,76 +1,76 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.binding.expression.support;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A settable expression that adds non-null values to a collection.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class CollectionAddingExpression implements Expression {
|
||||
|
||||
/**
|
||||
* The expression that resolves a mutable collection reference.
|
||||
*/
|
||||
private Expression collectionExpression;
|
||||
|
||||
/**
|
||||
* Creates a collection adding property expression.
|
||||
* @param collectionExpression the collection expression
|
||||
*/
|
||||
public CollectionAddingExpression(Expression collectionExpression) {
|
||||
this.collectionExpression = collectionExpression;
|
||||
}
|
||||
|
||||
public Object getValue(Object context) throws EvaluationException {
|
||||
return collectionExpression.getValue(context);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setValue(Object context, Object value) throws EvaluationException {
|
||||
Object result = getValue(context);
|
||||
if (result == null) {
|
||||
throw new EvaluationException(context.getClass(), collectionExpression.getExpressionString(),
|
||||
"Unable to access collection value for expression '" + collectionExpression.getExpressionString()
|
||||
+ "'", new IllegalStateException(
|
||||
"The collection expression evaluated to a [null] reference"));
|
||||
}
|
||||
Assert.isInstanceOf(Collection.class, result, "Not a collection: ");
|
||||
if (value != null) {
|
||||
// add the value to the collection
|
||||
((Collection<Object>) result).add(value);
|
||||
}
|
||||
}
|
||||
|
||||
public Class<?> getValueType(Object context) {
|
||||
return Object.class;
|
||||
}
|
||||
|
||||
public String getExpressionString() {
|
||||
return collectionExpression.getExpressionString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("collectionExpression", collectionExpression).toString();
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.binding.expression.support;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A settable expression that adds non-null values to a collection.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class CollectionAddingExpression implements Expression {
|
||||
|
||||
/**
|
||||
* The expression that resolves a mutable collection reference.
|
||||
*/
|
||||
private Expression collectionExpression;
|
||||
|
||||
/**
|
||||
* Creates a collection adding property expression.
|
||||
* @param collectionExpression the collection expression
|
||||
*/
|
||||
public CollectionAddingExpression(Expression collectionExpression) {
|
||||
this.collectionExpression = collectionExpression;
|
||||
}
|
||||
|
||||
public Object getValue(Object context) throws EvaluationException {
|
||||
return collectionExpression.getValue(context);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setValue(Object context, Object value) throws EvaluationException {
|
||||
Object result = getValue(context);
|
||||
if (result == null) {
|
||||
throw new EvaluationException(context.getClass(), collectionExpression.getExpressionString(),
|
||||
"Unable to access collection value for expression '" + collectionExpression.getExpressionString()
|
||||
+ "'", new IllegalStateException(
|
||||
"The collection expression evaluated to a [null] reference"));
|
||||
}
|
||||
Assert.isInstanceOf(Collection.class, result, "Not a collection: ");
|
||||
if (value != null) {
|
||||
// add the value to the collection
|
||||
((Collection<Object>) result).add(value);
|
||||
}
|
||||
}
|
||||
|
||||
public Class<?> getValueType(Object context) {
|
||||
return Object.class;
|
||||
}
|
||||
|
||||
public String getExpressionString() {
|
||||
return collectionExpression.getExpressionString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("collectionExpression", collectionExpression).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +1,70 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.binding.convert.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.convert.converters.StringToDate;
|
||||
|
||||
public class StaticConversionExecutorImplTests {
|
||||
|
||||
private StaticConversionExecutor conversionExecutor;
|
||||
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.binding.convert.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.convert.converters.StringToDate;
|
||||
|
||||
public class StaticConversionExecutorImplTests {
|
||||
|
||||
private StaticConversionExecutor conversionExecutor;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
StringToDate stringToDate = new StringToDate();
|
||||
conversionExecutor = new StaticConversionExecutor(String.class, Date.class, stringToDate);
|
||||
}
|
||||
|
||||
public void setUp() {
|
||||
StringToDate stringToDate = new StringToDate();
|
||||
conversionExecutor = new StaticConversionExecutor(String.class, Date.class, stringToDate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTypeConversion() {
|
||||
assertTrue(conversionExecutor.execute("2008-10-10").getClass().equals(Date.class));
|
||||
}
|
||||
|
||||
public void testTypeConversion() {
|
||||
assertTrue(conversionExecutor.execute("2008-10-10").getClass().equals(Date.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAssignmentCompatibleTypeConversion() {
|
||||
java.sql.Date date = new java.sql.Date(123L);
|
||||
try {
|
||||
assertSame(date, conversionExecutor.execute(date));
|
||||
fail("Should have failed");
|
||||
} catch (ConversionExecutionException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void testAssignmentCompatibleTypeConversion() {
|
||||
java.sql.Date date = new java.sql.Date(123L);
|
||||
try {
|
||||
assertSame(date, conversionExecutor.execute(date));
|
||||
fail("Should have failed");
|
||||
} catch (ConversionExecutionException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertNull() {
|
||||
assertNull(conversionExecutor.execute(null));
|
||||
}
|
||||
|
||||
public void testConvertNull() {
|
||||
assertNull(conversionExecutor.execute(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIllegalType() {
|
||||
try {
|
||||
conversionExecutor.execute(new StringBuilder());
|
||||
fail();
|
||||
} catch (ConversionExecutionException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
}
|
||||
public void testIllegalType() {
|
||||
try {
|
||||
conversionExecutor.execute(new StringBuilder());
|
||||
fail();
|
||||
} catch (ConversionExecutionException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,60 +1,60 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.binding.method;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for {@link MethodInvocationException}.
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class MethodInvocationExceptionTests {
|
||||
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.binding.method;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for {@link MethodInvocationException}.
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class MethodInvocationExceptionTests {
|
||||
|
||||
@Test
|
||||
public void testGetTargetException() {
|
||||
// runtime exception
|
||||
IllegalArgumentException iae = new IllegalArgumentException("test");
|
||||
MethodInvocationException ex = testException(iae);
|
||||
assertSame(iae, ex.getTargetException());
|
||||
|
||||
// exception
|
||||
IOException ioe = new IOException("test");
|
||||
ex = testException(ioe);
|
||||
assertSame(ioe, ex.getTargetException());
|
||||
|
||||
// nested
|
||||
InvocationTargetException ite = new InvocationTargetException(ioe);
|
||||
ex = testException(ite);
|
||||
assertSame(ioe, ex.getTargetException());
|
||||
|
||||
// deep nesting
|
||||
ite = new InvocationTargetException(new InvocationTargetException(ioe));
|
||||
ex = testException(ite);
|
||||
assertSame(ioe, ex.getTargetException());
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private MethodInvocationException testException(Throwable cause) {
|
||||
return new MethodInvocationException(new MethodSignature("test"), null, cause);
|
||||
}
|
||||
}
|
||||
public void testGetTargetException() {
|
||||
// runtime exception
|
||||
IllegalArgumentException iae = new IllegalArgumentException("test");
|
||||
MethodInvocationException ex = testException(iae);
|
||||
assertSame(iae, ex.getTargetException());
|
||||
|
||||
// exception
|
||||
IOException ioe = new IOException("test");
|
||||
ex = testException(ioe);
|
||||
assertSame(ioe, ex.getTargetException());
|
||||
|
||||
// nested
|
||||
InvocationTargetException ite = new InvocationTargetException(ioe);
|
||||
ex = testException(ite);
|
||||
assertSame(ioe, ex.getTargetException());
|
||||
|
||||
// deep nesting
|
||||
ite = new InvocationTargetException(new InvocationTargetException(ioe));
|
||||
ex = testException(ite);
|
||||
assertSame(ioe, ex.getTargetException());
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private MethodInvocationException testException(Throwable cause) {
|
||||
return new MethodInvocationException(new MethodSignature("test"), null, cause);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,98 +1,98 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.binding.method;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.binding.expression.support.StaticExpression;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link org.springframework.binding.method.MethodInvoker}.
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class MethodInvokerTests {
|
||||
|
||||
private MethodInvoker methodInvoker;
|
||||
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.binding.method;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.binding.expression.support.StaticExpression;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link org.springframework.binding.method.MethodInvoker}.
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class MethodInvokerTests {
|
||||
|
||||
private MethodInvoker methodInvoker;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
this.methodInvoker = new MethodInvoker();
|
||||
}
|
||||
|
||||
public void setUp() {
|
||||
this.methodInvoker = new MethodInvoker();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvocationTargetException() {
|
||||
try {
|
||||
methodInvoker.invoke(new MethodSignature("test"), new TestObject(), null);
|
||||
fail();
|
||||
} catch (MethodInvocationException e) {
|
||||
assertTrue(e.getTargetException() instanceof IllegalArgumentException);
|
||||
assertEquals("just testing", e.getTargetException().getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testInvocationTargetException() {
|
||||
try {
|
||||
methodInvoker.invoke(new MethodSignature("test"), new TestObject(), null);
|
||||
fail();
|
||||
} catch (MethodInvocationException e) {
|
||||
assertTrue(e.getTargetException() instanceof IllegalArgumentException);
|
||||
assertEquals("just testing", e.getTargetException().getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidMethod() {
|
||||
try {
|
||||
methodInvoker.invoke(new MethodSignature("bogus"), new TestObject(), null);
|
||||
fail();
|
||||
} catch (MethodInvocationException e) {
|
||||
assertTrue(e.getTargetException() instanceof InvalidMethodKeyException);
|
||||
}
|
||||
}
|
||||
|
||||
public void testInvalidMethod() {
|
||||
try {
|
||||
methodInvoker.invoke(new MethodSignature("bogus"), new TestObject(), null);
|
||||
fail();
|
||||
} catch (MethodInvocationException e) {
|
||||
assertTrue(e.getTargetException() instanceof InvalidMethodKeyException);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBeanArg() {
|
||||
Parameters parameters = new Parameters();
|
||||
Bean bean = new Bean();
|
||||
parameters.add(new Parameter(Bean.class, new StaticExpression(bean)));
|
||||
MethodSignature method = new MethodSignature("testBeanArg", parameters);
|
||||
assertSame(bean, methodInvoker.invoke(method, new TestObject(), null));
|
||||
}
|
||||
|
||||
public void testBeanArg() {
|
||||
Parameters parameters = new Parameters();
|
||||
Bean bean = new Bean();
|
||||
parameters.add(new Parameter(Bean.class, new StaticExpression(bean)));
|
||||
MethodSignature method = new MethodSignature("testBeanArg", parameters);
|
||||
assertSame(bean, methodInvoker.invoke(method, new TestObject(), null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrimitiveArg() {
|
||||
Parameters parameters = new Parameters();
|
||||
parameters.add(new Parameter(Boolean.class, new StaticExpression(true)));
|
||||
MethodSignature method = new MethodSignature("testPrimitiveArg", parameters);
|
||||
assertEquals(Boolean.TRUE, methodInvoker.invoke(method, new TestObject(), null));
|
||||
}
|
||||
|
||||
static class TestObject {
|
||||
|
||||
public void test() {
|
||||
throw new IllegalArgumentException("just testing");
|
||||
}
|
||||
|
||||
public Object testBeanArg(Bean bean) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public boolean testPrimitiveArg(boolean primitive) {
|
||||
return primitive;
|
||||
}
|
||||
}
|
||||
|
||||
static class Bean {
|
||||
String value;
|
||||
}
|
||||
}
|
||||
public void testPrimitiveArg() {
|
||||
Parameters parameters = new Parameters();
|
||||
parameters.add(new Parameter(Boolean.class, new StaticExpression(true)));
|
||||
MethodSignature method = new MethodSignature("testPrimitiveArg", parameters);
|
||||
assertEquals(Boolean.TRUE, methodInvoker.invoke(method, new TestObject(), null));
|
||||
}
|
||||
|
||||
static class TestObject {
|
||||
|
||||
public void test() {
|
||||
throw new IllegalArgumentException("just testing");
|
||||
}
|
||||
|
||||
public Object testBeanArg(Bean bean) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public boolean testPrimitiveArg(boolean primitive) {
|
||||
return primitive;
|
||||
}
|
||||
}
|
||||
|
||||
static class Bean {
|
||||
String value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
package org.springframework.faces.webflow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class JSFManagedBean {
|
||||
|
||||
String prop1;
|
||||
JSFModel model;
|
||||
List<String> values = new ArrayList<>();
|
||||
|
||||
public JSFModel getModel() {
|
||||
return this.model;
|
||||
}
|
||||
|
||||
public void setModel(JSFModel model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public String getProp1() {
|
||||
return this.prop1;
|
||||
}
|
||||
|
||||
public void setProp1(String prop1) {
|
||||
this.prop1 = prop1;
|
||||
}
|
||||
|
||||
public void addValue(String value) {
|
||||
this.values.add(value);
|
||||
}
|
||||
|
||||
public List<String> getValues() {
|
||||
return this.values;
|
||||
}
|
||||
}
|
||||
package org.springframework.faces.webflow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class JSFManagedBean {
|
||||
|
||||
String prop1;
|
||||
JSFModel model;
|
||||
List<String> values = new ArrayList<>();
|
||||
|
||||
public JSFModel getModel() {
|
||||
return this.model;
|
||||
}
|
||||
|
||||
public void setModel(JSFModel model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public String getProp1() {
|
||||
return this.prop1;
|
||||
}
|
||||
|
||||
public void setProp1(String prop1) {
|
||||
this.prop1 = prop1;
|
||||
}
|
||||
|
||||
public void addValue(String value) {
|
||||
this.values.add(value);
|
||||
}
|
||||
|
||||
public List<String> getValues() {
|
||||
return this.values;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,240 +1,240 @@
|
||||
package org.springframework.faces.webflow;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
import javax.faces.FactoryFinder;
|
||||
import javax.faces.application.Application;
|
||||
import javax.faces.application.ApplicationFactory;
|
||||
import javax.faces.component.UIViewRoot;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.context.FacesContextFactory;
|
||||
import javax.faces.lifecycle.LifecycleFactory;
|
||||
import javax.faces.render.RenderKitFactory;
|
||||
|
||||
import org.apache.myfaces.test.base.AbstractJsfTestCase;
|
||||
import org.apache.myfaces.test.mock.MockApplicationFactory;
|
||||
import org.apache.myfaces.test.mock.MockExternalContext;
|
||||
import org.apache.myfaces.test.mock.MockHttpServletRequest;
|
||||
import org.apache.myfaces.test.mock.MockHttpServletResponse;
|
||||
import org.apache.myfaces.test.mock.MockHttpSession;
|
||||
import org.apache.myfaces.test.mock.MockPartialViewContextFactory;
|
||||
import org.apache.myfaces.test.mock.MockPrintWriter;
|
||||
import org.apache.myfaces.test.mock.MockRenderKit;
|
||||
import org.apache.myfaces.test.mock.MockRenderKitFactory;
|
||||
import org.apache.myfaces.test.mock.MockResponseWriter;
|
||||
import org.apache.myfaces.test.mock.MockServletConfig;
|
||||
import org.apache.myfaces.test.mock.MockServletContext;
|
||||
import org.apache.myfaces.test.mock.lifecycle.MockLifecycle;
|
||||
import org.apache.myfaces.test.mock.lifecycle.MockLifecycleFactory;
|
||||
import org.apache.myfaces.test.mock.visit.MockVisitContextFactory;
|
||||
|
||||
/**
|
||||
* Helper for using the mock JSF environment provided by shale-test inside unit tests that do not extend
|
||||
* {@link AbstractJsfTestCase}
|
||||
*
|
||||
* @author Jeremy Grelle
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class JSFMockHelper {
|
||||
|
||||
private final JSFMock mock = new JSFMock();
|
||||
|
||||
public Application application() {
|
||||
return this.mock.application();
|
||||
}
|
||||
|
||||
public MockServletConfig config() {
|
||||
return this.mock.config();
|
||||
}
|
||||
|
||||
public String contentAsString() throws IOException {
|
||||
return this.mock.contentAsString();
|
||||
}
|
||||
|
||||
public MockExternalContext externalContext() {
|
||||
return this.mock.externalContext();
|
||||
}
|
||||
|
||||
public FacesContext facesContext() {
|
||||
return this.mock.facesContext();
|
||||
}
|
||||
|
||||
public FacesContextFactory facesContextFactory() {
|
||||
return this.mock.facesContextFactory();
|
||||
}
|
||||
|
||||
public MockLifecycle lifecycle() {
|
||||
return this.mock.lifecycle();
|
||||
}
|
||||
|
||||
public MockLifecycleFactory lifecycleFactory() {
|
||||
return this.mock.lifecycleFactory();
|
||||
}
|
||||
|
||||
public MockRenderKit renderKit() {
|
||||
return this.mock.renderKit();
|
||||
}
|
||||
|
||||
public MockHttpServletRequest request() {
|
||||
return this.mock.request();
|
||||
}
|
||||
|
||||
public MockHttpServletResponse response() {
|
||||
return this.mock.response();
|
||||
}
|
||||
|
||||
public MockServletContext servletContext() {
|
||||
return this.mock.servletContext();
|
||||
}
|
||||
|
||||
public MockHttpSession session() {
|
||||
return this.mock.session();
|
||||
}
|
||||
|
||||
public void setUp() throws Exception {
|
||||
this.mock.setUp();
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
this.mock.tearDown();
|
||||
}
|
||||
|
||||
private static class JSFMock extends AbstractJsfTestCase {
|
||||
|
||||
private ClassLoader threadContextClassLoader;
|
||||
|
||||
public JSFMock() {
|
||||
super("JSFMock");
|
||||
}
|
||||
|
||||
FacesContext facesContext;
|
||||
FacesContextFactory facesContextFactory;
|
||||
|
||||
public void setUp() throws Exception {
|
||||
|
||||
// Ensure no pre-existing FacesContext ..
|
||||
if (FacesContext.getCurrentInstance() != null) {
|
||||
FacesContext.getCurrentInstance().release();
|
||||
}
|
||||
|
||||
// Set up a new thread context class loader
|
||||
this.threadContextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(
|
||||
new URLClassLoader(new URL[0], this.getClass().getClassLoader()));
|
||||
|
||||
// Set up Servlet API Objects
|
||||
this.servletContext = new MockServletContext();
|
||||
this.config = new MockServletConfig(this.servletContext);
|
||||
this.session = new MockHttpSession();
|
||||
this.session.setServletContext(this.servletContext);
|
||||
this.request = new MockHttpServletRequest(this.session);
|
||||
this.request.setServletContext(this.servletContext);
|
||||
this.response = new MockHttpServletResponse();
|
||||
|
||||
// Set up JSF API Objects
|
||||
FactoryFinder.setFactory(FactoryFinder.APPLICATION_FACTORY, MockApplicationFactory.class.getName());
|
||||
FactoryFinder.setFactory(FactoryFinder.FACES_CONTEXT_FACTORY, MockBaseFacesContextFactory.class.getName());
|
||||
FactoryFinder.setFactory(FactoryFinder.LIFECYCLE_FACTORY, MockLifecycleFactory.class.getName());
|
||||
FactoryFinder.setFactory(FactoryFinder.RENDER_KIT_FACTORY, MockRenderKitFactory.class.getName());
|
||||
FactoryFinder.setFactory(FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY,
|
||||
MockPartialViewContextFactory.class.getName());
|
||||
FactoryFinder.setFactory(FactoryFinder.VISIT_CONTEXT_FACTORY, MockVisitContextFactory.class.getName());
|
||||
this.lifecycleFactory = (MockLifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
|
||||
this.lifecycle = (MockLifecycle) this.lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
|
||||
this.facesContextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
|
||||
this.facesContext = this.facesContextFactory.getFacesContext(this.servletContext, this.request, this.response, this.lifecycle);
|
||||
this.externalContext = (MockExternalContext) this.facesContext.getExternalContext();
|
||||
this.facesContext.setResponseWriter(new MockResponseWriter(this.response.getWriter()));
|
||||
|
||||
UIViewRoot root = new UIViewRoot();
|
||||
root.setViewId("/viewId");
|
||||
root.setRenderKitId(RenderKitFactory.HTML_BASIC_RENDER_KIT);
|
||||
this.facesContext.setViewRoot(root);
|
||||
ApplicationFactory applicationFactory = (ApplicationFactory) FactoryFinder
|
||||
.getFactory(FactoryFinder.APPLICATION_FACTORY);
|
||||
this.application = (org.apache.myfaces.test.mock.MockApplication) applicationFactory.getApplication();
|
||||
RenderKitFactory renderKitFactory = (RenderKitFactory) FactoryFinder
|
||||
.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
|
||||
this.renderKit = new MockRenderKit();
|
||||
renderKitFactory.addRenderKit(RenderKitFactory.HTML_BASIC_RENDER_KIT, this.renderKit);
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
this.application = null;
|
||||
this.config = null;
|
||||
this.externalContext = null;
|
||||
if (this.facesContext != null) {
|
||||
this.facesContext.release();
|
||||
}
|
||||
this.facesContext = null;
|
||||
this.lifecycle = null;
|
||||
this.lifecycleFactory = null;
|
||||
this.renderKit = null;
|
||||
this.request = null;
|
||||
this.response = null;
|
||||
this.servletContext = null;
|
||||
this.session = null;
|
||||
FactoryFinder.releaseFactories();
|
||||
|
||||
Thread.currentThread().setContextClassLoader(this.threadContextClassLoader);
|
||||
this.threadContextClassLoader = null;
|
||||
}
|
||||
|
||||
public org.apache.myfaces.test.mock.MockApplication application() {
|
||||
return this.application;
|
||||
}
|
||||
|
||||
public MockServletConfig config() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
public String contentAsString() throws IOException {
|
||||
MockPrintWriter writer = (MockPrintWriter) this.response.getWriter();
|
||||
return new String(writer.content());
|
||||
}
|
||||
|
||||
public MockExternalContext externalContext() {
|
||||
return this.externalContext;
|
||||
}
|
||||
|
||||
public FacesContext facesContext() {
|
||||
return this.facesContext;
|
||||
}
|
||||
|
||||
public FacesContextFactory facesContextFactory() {
|
||||
return this.facesContextFactory;
|
||||
}
|
||||
|
||||
public MockLifecycle lifecycle() {
|
||||
return this.lifecycle;
|
||||
}
|
||||
|
||||
public MockLifecycleFactory lifecycleFactory() {
|
||||
return this.lifecycleFactory;
|
||||
}
|
||||
|
||||
public MockRenderKit renderKit() {
|
||||
return this.renderKit;
|
||||
}
|
||||
|
||||
public MockHttpServletRequest request() {
|
||||
return this.request;
|
||||
}
|
||||
|
||||
public MockHttpServletResponse response() {
|
||||
return this.response;
|
||||
}
|
||||
|
||||
public MockServletContext servletContext() {
|
||||
return this.servletContext;
|
||||
}
|
||||
|
||||
public MockHttpSession session() {
|
||||
return this.session;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
package org.springframework.faces.webflow;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
import javax.faces.FactoryFinder;
|
||||
import javax.faces.application.Application;
|
||||
import javax.faces.application.ApplicationFactory;
|
||||
import javax.faces.component.UIViewRoot;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.context.FacesContextFactory;
|
||||
import javax.faces.lifecycle.LifecycleFactory;
|
||||
import javax.faces.render.RenderKitFactory;
|
||||
|
||||
import org.apache.myfaces.test.base.AbstractJsfTestCase;
|
||||
import org.apache.myfaces.test.mock.MockApplicationFactory;
|
||||
import org.apache.myfaces.test.mock.MockExternalContext;
|
||||
import org.apache.myfaces.test.mock.MockHttpServletRequest;
|
||||
import org.apache.myfaces.test.mock.MockHttpServletResponse;
|
||||
import org.apache.myfaces.test.mock.MockHttpSession;
|
||||
import org.apache.myfaces.test.mock.MockPartialViewContextFactory;
|
||||
import org.apache.myfaces.test.mock.MockPrintWriter;
|
||||
import org.apache.myfaces.test.mock.MockRenderKit;
|
||||
import org.apache.myfaces.test.mock.MockRenderKitFactory;
|
||||
import org.apache.myfaces.test.mock.MockResponseWriter;
|
||||
import org.apache.myfaces.test.mock.MockServletConfig;
|
||||
import org.apache.myfaces.test.mock.MockServletContext;
|
||||
import org.apache.myfaces.test.mock.lifecycle.MockLifecycle;
|
||||
import org.apache.myfaces.test.mock.lifecycle.MockLifecycleFactory;
|
||||
import org.apache.myfaces.test.mock.visit.MockVisitContextFactory;
|
||||
|
||||
/**
|
||||
* Helper for using the mock JSF environment provided by shale-test inside unit tests that do not extend
|
||||
* {@link AbstractJsfTestCase}
|
||||
*
|
||||
* @author Jeremy Grelle
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class JSFMockHelper {
|
||||
|
||||
private final JSFMock mock = new JSFMock();
|
||||
|
||||
public Application application() {
|
||||
return this.mock.application();
|
||||
}
|
||||
|
||||
public MockServletConfig config() {
|
||||
return this.mock.config();
|
||||
}
|
||||
|
||||
public String contentAsString() throws IOException {
|
||||
return this.mock.contentAsString();
|
||||
}
|
||||
|
||||
public MockExternalContext externalContext() {
|
||||
return this.mock.externalContext();
|
||||
}
|
||||
|
||||
public FacesContext facesContext() {
|
||||
return this.mock.facesContext();
|
||||
}
|
||||
|
||||
public FacesContextFactory facesContextFactory() {
|
||||
return this.mock.facesContextFactory();
|
||||
}
|
||||
|
||||
public MockLifecycle lifecycle() {
|
||||
return this.mock.lifecycle();
|
||||
}
|
||||
|
||||
public MockLifecycleFactory lifecycleFactory() {
|
||||
return this.mock.lifecycleFactory();
|
||||
}
|
||||
|
||||
public MockRenderKit renderKit() {
|
||||
return this.mock.renderKit();
|
||||
}
|
||||
|
||||
public MockHttpServletRequest request() {
|
||||
return this.mock.request();
|
||||
}
|
||||
|
||||
public MockHttpServletResponse response() {
|
||||
return this.mock.response();
|
||||
}
|
||||
|
||||
public MockServletContext servletContext() {
|
||||
return this.mock.servletContext();
|
||||
}
|
||||
|
||||
public MockHttpSession session() {
|
||||
return this.mock.session();
|
||||
}
|
||||
|
||||
public void setUp() throws Exception {
|
||||
this.mock.setUp();
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
this.mock.tearDown();
|
||||
}
|
||||
|
||||
private static class JSFMock extends AbstractJsfTestCase {
|
||||
|
||||
private ClassLoader threadContextClassLoader;
|
||||
|
||||
public JSFMock() {
|
||||
super("JSFMock");
|
||||
}
|
||||
|
||||
FacesContext facesContext;
|
||||
FacesContextFactory facesContextFactory;
|
||||
|
||||
public void setUp() throws Exception {
|
||||
|
||||
// Ensure no pre-existing FacesContext ..
|
||||
if (FacesContext.getCurrentInstance() != null) {
|
||||
FacesContext.getCurrentInstance().release();
|
||||
}
|
||||
|
||||
// Set up a new thread context class loader
|
||||
this.threadContextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(
|
||||
new URLClassLoader(new URL[0], this.getClass().getClassLoader()));
|
||||
|
||||
// Set up Servlet API Objects
|
||||
this.servletContext = new MockServletContext();
|
||||
this.config = new MockServletConfig(this.servletContext);
|
||||
this.session = new MockHttpSession();
|
||||
this.session.setServletContext(this.servletContext);
|
||||
this.request = new MockHttpServletRequest(this.session);
|
||||
this.request.setServletContext(this.servletContext);
|
||||
this.response = new MockHttpServletResponse();
|
||||
|
||||
// Set up JSF API Objects
|
||||
FactoryFinder.setFactory(FactoryFinder.APPLICATION_FACTORY, MockApplicationFactory.class.getName());
|
||||
FactoryFinder.setFactory(FactoryFinder.FACES_CONTEXT_FACTORY, MockBaseFacesContextFactory.class.getName());
|
||||
FactoryFinder.setFactory(FactoryFinder.LIFECYCLE_FACTORY, MockLifecycleFactory.class.getName());
|
||||
FactoryFinder.setFactory(FactoryFinder.RENDER_KIT_FACTORY, MockRenderKitFactory.class.getName());
|
||||
FactoryFinder.setFactory(FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY,
|
||||
MockPartialViewContextFactory.class.getName());
|
||||
FactoryFinder.setFactory(FactoryFinder.VISIT_CONTEXT_FACTORY, MockVisitContextFactory.class.getName());
|
||||
this.lifecycleFactory = (MockLifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
|
||||
this.lifecycle = (MockLifecycle) this.lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
|
||||
this.facesContextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
|
||||
this.facesContext = this.facesContextFactory.getFacesContext(this.servletContext, this.request, this.response, this.lifecycle);
|
||||
this.externalContext = (MockExternalContext) this.facesContext.getExternalContext();
|
||||
this.facesContext.setResponseWriter(new MockResponseWriter(this.response.getWriter()));
|
||||
|
||||
UIViewRoot root = new UIViewRoot();
|
||||
root.setViewId("/viewId");
|
||||
root.setRenderKitId(RenderKitFactory.HTML_BASIC_RENDER_KIT);
|
||||
this.facesContext.setViewRoot(root);
|
||||
ApplicationFactory applicationFactory = (ApplicationFactory) FactoryFinder
|
||||
.getFactory(FactoryFinder.APPLICATION_FACTORY);
|
||||
this.application = (org.apache.myfaces.test.mock.MockApplication) applicationFactory.getApplication();
|
||||
RenderKitFactory renderKitFactory = (RenderKitFactory) FactoryFinder
|
||||
.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
|
||||
this.renderKit = new MockRenderKit();
|
||||
renderKitFactory.addRenderKit(RenderKitFactory.HTML_BASIC_RENDER_KIT, this.renderKit);
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
this.application = null;
|
||||
this.config = null;
|
||||
this.externalContext = null;
|
||||
if (this.facesContext != null) {
|
||||
this.facesContext.release();
|
||||
}
|
||||
this.facesContext = null;
|
||||
this.lifecycle = null;
|
||||
this.lifecycleFactory = null;
|
||||
this.renderKit = null;
|
||||
this.request = null;
|
||||
this.response = null;
|
||||
this.servletContext = null;
|
||||
this.session = null;
|
||||
FactoryFinder.releaseFactories();
|
||||
|
||||
Thread.currentThread().setContextClassLoader(this.threadContextClassLoader);
|
||||
this.threadContextClassLoader = null;
|
||||
}
|
||||
|
||||
public org.apache.myfaces.test.mock.MockApplication application() {
|
||||
return this.application;
|
||||
}
|
||||
|
||||
public MockServletConfig config() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
public String contentAsString() throws IOException {
|
||||
MockPrintWriter writer = (MockPrintWriter) this.response.getWriter();
|
||||
return new String(writer.content());
|
||||
}
|
||||
|
||||
public MockExternalContext externalContext() {
|
||||
return this.externalContext;
|
||||
}
|
||||
|
||||
public FacesContext facesContext() {
|
||||
return this.facesContext;
|
||||
}
|
||||
|
||||
public FacesContextFactory facesContextFactory() {
|
||||
return this.facesContextFactory;
|
||||
}
|
||||
|
||||
public MockLifecycle lifecycle() {
|
||||
return this.lifecycle;
|
||||
}
|
||||
|
||||
public MockLifecycleFactory lifecycleFactory() {
|
||||
return this.lifecycleFactory;
|
||||
}
|
||||
|
||||
public MockRenderKit renderKit() {
|
||||
return this.renderKit;
|
||||
}
|
||||
|
||||
public MockHttpServletRequest request() {
|
||||
return this.request;
|
||||
}
|
||||
|
||||
public MockHttpServletResponse response() {
|
||||
return this.response;
|
||||
}
|
||||
|
||||
public MockServletContext servletContext() {
|
||||
return this.servletContext;
|
||||
}
|
||||
|
||||
public MockHttpSession session() {
|
||||
return this.session;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package org.springframework.faces.webflow;
|
||||
|
||||
public class JSFModel {
|
||||
String value;
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
package org.springframework.faces.webflow;
|
||||
|
||||
public class JSFModel {
|
||||
String value;
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.springframework.faces.webflow;
|
||||
|
||||
public interface MockService {
|
||||
|
||||
void doSomething(String arg);
|
||||
}
|
||||
package org.springframework.faces.webflow;
|
||||
|
||||
public interface MockService {
|
||||
|
||||
void doSomething(String arg);
|
||||
}
|
||||
|
||||
@@ -1,134 +1,134 @@
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* FORM ELEMENTS */
|
||||
form {
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
form div,
|
||||
form p {
|
||||
margin: 0 0 1em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1em;
|
||||
}
|
||||
label {
|
||||
font-weight: bold;
|
||||
}
|
||||
fieldset {
|
||||
padding: 5px 10px;
|
||||
margin: 0 0 1.5em 0;
|
||||
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
fieldset legend {
|
||||
margin: 0 0 0 0px;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
|
||||
color: #666;
|
||||
background-color: white;
|
||||
}
|
||||
* html fieldset legend {
|
||||
margin: 0 0 10px -10px;
|
||||
}
|
||||
fieldset ul {
|
||||
margin: 0 0 1.5em 0;
|
||||
padding: 0;
|
||||
|
||||
list-style: none;
|
||||
}
|
||||
fieldset ul li {
|
||||
margin: 0 0 0.5em 0;
|
||||
padding: 0;
|
||||
|
||||
list-style: none;
|
||||
}
|
||||
input, select, textarea {
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
|
||||
font-size: 1em;
|
||||
font-family: arial, helvetica, verdana, sans-serif;
|
||||
}
|
||||
|
||||
input, select {
|
||||
vertical-align: middle;
|
||||
}
|
||||
textarea {
|
||||
width: 200px;
|
||||
height: 8em;
|
||||
}
|
||||
|
||||
input.check {
|
||||
width: auto;
|
||||
height: auto;
|
||||
|
||||
margin: 0;
|
||||
|
||||
border: none;
|
||||
}
|
||||
input.radio {
|
||||
width: auto;
|
||||
|
||||
height: auto;
|
||||
margin: 0;
|
||||
|
||||
border: none;
|
||||
}
|
||||
input.file {
|
||||
width: 250px;
|
||||
height: auto;
|
||||
}
|
||||
input.readonly {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
input.button {
|
||||
width: 10em;
|
||||
|
||||
background-color: #ddd;
|
||||
border: 1px solid black;
|
||||
}
|
||||
input.image {
|
||||
width: auto;
|
||||
height: auto;
|
||||
|
||||
border: none;
|
||||
}
|
||||
|
||||
form div.submit {
|
||||
margin: 1em 0;
|
||||
}
|
||||
form div.submit input {
|
||||
width: 15em;
|
||||
height: 2em;
|
||||
}
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* FORM ELEMENTS */
|
||||
form {
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
form div,
|
||||
form p {
|
||||
margin: 0 0 1em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1em;
|
||||
}
|
||||
label {
|
||||
font-weight: bold;
|
||||
}
|
||||
fieldset {
|
||||
padding: 5px 10px;
|
||||
margin: 0 0 1.5em 0;
|
||||
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
fieldset legend {
|
||||
margin: 0 0 0 0px;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
|
||||
color: #666;
|
||||
background-color: white;
|
||||
}
|
||||
* html fieldset legend {
|
||||
margin: 0 0 10px -10px;
|
||||
}
|
||||
fieldset ul {
|
||||
margin: 0 0 1.5em 0;
|
||||
padding: 0;
|
||||
|
||||
list-style: none;
|
||||
}
|
||||
fieldset ul li {
|
||||
margin: 0 0 0.5em 0;
|
||||
padding: 0;
|
||||
|
||||
list-style: none;
|
||||
}
|
||||
input, select, textarea {
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
|
||||
font-size: 1em;
|
||||
font-family: arial, helvetica, verdana, sans-serif;
|
||||
}
|
||||
|
||||
input, select {
|
||||
vertical-align: middle;
|
||||
}
|
||||
textarea {
|
||||
width: 200px;
|
||||
height: 8em;
|
||||
}
|
||||
|
||||
input.check {
|
||||
width: auto;
|
||||
height: auto;
|
||||
|
||||
margin: 0;
|
||||
|
||||
border: none;
|
||||
}
|
||||
input.radio {
|
||||
width: auto;
|
||||
|
||||
height: auto;
|
||||
margin: 0;
|
||||
|
||||
border: none;
|
||||
}
|
||||
input.file {
|
||||
width: 250px;
|
||||
height: auto;
|
||||
}
|
||||
input.readonly {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
input.button {
|
||||
width: 10em;
|
||||
|
||||
background-color: #ddd;
|
||||
border: 1px solid black;
|
||||
}
|
||||
input.image {
|
||||
width: auto;
|
||||
height: auto;
|
||||
|
||||
border: none;
|
||||
}
|
||||
|
||||
form div.submit {
|
||||
margin: 1em 0;
|
||||
}
|
||||
form div.submit input {
|
||||
width: 15em;
|
||||
height: 2em;
|
||||
}
|
||||
/* END FORM ELEMENTS */
|
||||
@@ -1,52 +1,52 @@
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@import url("nav-horizontal.css");
|
||||
|
||||
/* NAV BAR AT THE TOP AND ONE COLUMN OF CONTENT */
|
||||
div#content {
|
||||
position: relative;
|
||||
width: 701px;
|
||||
|
||||
margin: 0 auto 20px auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#main {
|
||||
width: 100%;
|
||||
}
|
||||
div#local {
|
||||
display: none;
|
||||
}
|
||||
div#sub {
|
||||
display: none;
|
||||
}
|
||||
div#nav {
|
||||
display: none;
|
||||
}
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@import url("nav-horizontal.css");
|
||||
|
||||
/* NAV BAR AT THE TOP AND ONE COLUMN OF CONTENT */
|
||||
div#content {
|
||||
position: relative;
|
||||
width: 701px;
|
||||
|
||||
margin: 0 auto 20px auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#main {
|
||||
width: 100%;
|
||||
}
|
||||
div#local {
|
||||
display: none;
|
||||
}
|
||||
div#sub {
|
||||
display: none;
|
||||
}
|
||||
div#nav {
|
||||
display: none;
|
||||
}
|
||||
/* END CONTENT */
|
||||
@@ -1,56 +1,56 @@
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@import url("nav-vertical.css");
|
||||
|
||||
/* NAV BAR ON THE LEFT AND ONE COLUMN OF CONTENT */
|
||||
div#content {
|
||||
position: relative;
|
||||
width: 780px;
|
||||
|
||||
margin: 0 auto 20px auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#main {
|
||||
float: right;
|
||||
width: 560px;
|
||||
display: inline;
|
||||
}
|
||||
div#local {
|
||||
display: none;
|
||||
}
|
||||
div#sub {
|
||||
display: none;
|
||||
}
|
||||
div#nav {
|
||||
float: left;
|
||||
width: 200px;
|
||||
display: inline;
|
||||
}
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@import url("nav-vertical.css");
|
||||
|
||||
/* NAV BAR ON THE LEFT AND ONE COLUMN OF CONTENT */
|
||||
div#content {
|
||||
position: relative;
|
||||
width: 780px;
|
||||
|
||||
margin: 0 auto 20px auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#main {
|
||||
float: right;
|
||||
width: 560px;
|
||||
display: inline;
|
||||
}
|
||||
div#local {
|
||||
display: none;
|
||||
}
|
||||
div#sub {
|
||||
display: none;
|
||||
}
|
||||
div#nav {
|
||||
float: left;
|
||||
width: 200px;
|
||||
display: inline;
|
||||
}
|
||||
/* END CONTENT */
|
||||
@@ -1,64 +1,64 @@
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@import url("nav-vertical.css");
|
||||
|
||||
/* NAV BAR ON THE LEFT AND TWO COLUMNS OF CONTENT */
|
||||
div#content {
|
||||
position: relative;
|
||||
width: 780px;
|
||||
|
||||
margin: 0 auto 20px auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#main {
|
||||
float: right;
|
||||
width: 340px;
|
||||
display: inline;
|
||||
|
||||
margin-right: 220px;
|
||||
margin-left: -220px;
|
||||
}
|
||||
div#local {
|
||||
display: none;
|
||||
}
|
||||
div#sub {
|
||||
float: right;
|
||||
width: 200px;
|
||||
display: inline;
|
||||
|
||||
margin-right: -340px;
|
||||
margin-left: 200px;
|
||||
}
|
||||
div#nav {
|
||||
float: left;
|
||||
width: 200px;
|
||||
display: inline;
|
||||
}
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@import url("nav-vertical.css");
|
||||
|
||||
/* NAV BAR ON THE LEFT AND TWO COLUMNS OF CONTENT */
|
||||
div#content {
|
||||
position: relative;
|
||||
width: 780px;
|
||||
|
||||
margin: 0 auto 20px auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#main {
|
||||
float: right;
|
||||
width: 340px;
|
||||
display: inline;
|
||||
|
||||
margin-right: 220px;
|
||||
margin-left: -220px;
|
||||
}
|
||||
div#local {
|
||||
display: none;
|
||||
}
|
||||
div#sub {
|
||||
float: right;
|
||||
width: 200px;
|
||||
display: inline;
|
||||
|
||||
margin-right: -340px;
|
||||
margin-left: 200px;
|
||||
}
|
||||
div#nav {
|
||||
float: left;
|
||||
width: 200px;
|
||||
display: inline;
|
||||
}
|
||||
/* END CONTENT */
|
||||
@@ -1,57 +1,57 @@
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@import url("nav-horizontal.css");
|
||||
|
||||
/* NAV BAR AT THE TOP AND ONE COLUMN OF CONTENT */
|
||||
div#content {
|
||||
position: relative;
|
||||
width: 701px;
|
||||
|
||||
margin: 0 auto 20px auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#main {
|
||||
width: 100%;
|
||||
}
|
||||
div#local {
|
||||
width: 100%;
|
||||
}
|
||||
div#sub {
|
||||
width: 100%;
|
||||
}
|
||||
div#nav {
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@import url("nav-horizontal.css");
|
||||
|
||||
/* NAV BAR AT THE TOP AND ONE COLUMN OF CONTENT */
|
||||
div#content {
|
||||
position: relative;
|
||||
width: 701px;
|
||||
|
||||
margin: 0 auto 20px auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#main {
|
||||
width: 100%;
|
||||
}
|
||||
div#local {
|
||||
width: 100%;
|
||||
}
|
||||
div#sub {
|
||||
width: 100%;
|
||||
}
|
||||
div#nav {
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
/* END CONTENT */
|
||||
@@ -1,68 +1,68 @@
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@import url("nav-horizontal.css");
|
||||
|
||||
/* NAV BAR AT THE TOP, LOCAL NAV ON THE LEFT AND TWO COLUMNS OF CONTENT */
|
||||
div#content {
|
||||
position: relative;
|
||||
width: 701px;
|
||||
|
||||
margin: 0 auto 20px auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#main {
|
||||
float: left;
|
||||
width: 300px;
|
||||
display: inline;
|
||||
|
||||
margin-right: -200px;
|
||||
margin-left: 200px;
|
||||
}
|
||||
div#sub {
|
||||
float: right;
|
||||
width: 180px;
|
||||
display: inline;
|
||||
}
|
||||
div#local {
|
||||
float: left;
|
||||
width: 180px;
|
||||
display: inline;
|
||||
|
||||
margin-left: -300px;
|
||||
}
|
||||
div#nav {
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
left: 0;
|
||||
width: 701px;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@import url("nav-horizontal.css");
|
||||
|
||||
/* NAV BAR AT THE TOP, LOCAL NAV ON THE LEFT AND TWO COLUMNS OF CONTENT */
|
||||
div#content {
|
||||
position: relative;
|
||||
width: 701px;
|
||||
|
||||
margin: 0 auto 20px auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#main {
|
||||
float: left;
|
||||
width: 300px;
|
||||
display: inline;
|
||||
|
||||
margin-right: -200px;
|
||||
margin-left: 200px;
|
||||
}
|
||||
div#sub {
|
||||
float: right;
|
||||
width: 180px;
|
||||
display: inline;
|
||||
}
|
||||
div#local {
|
||||
float: left;
|
||||
width: 180px;
|
||||
display: inline;
|
||||
|
||||
margin-left: -300px;
|
||||
}
|
||||
div#nav {
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
left: 0;
|
||||
width: 701px;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
/* END CONTENT */
|
||||
@@ -1,61 +1,61 @@
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@import url("nav-horizontal.css");
|
||||
|
||||
/* NAV BAR AT THE TOP, LOCAL NAVIGATION ON THE LEFT AND ONE COLUMN OF CONTENT */
|
||||
div#content {
|
||||
position: relative;
|
||||
width: 701px;
|
||||
|
||||
margin: 0 auto 20px auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#main {
|
||||
float: right;
|
||||
width: 500px;
|
||||
display: inline;
|
||||
}
|
||||
div#local {
|
||||
float: left;
|
||||
width: 200px;
|
||||
display: inline;
|
||||
}
|
||||
div#sub {
|
||||
display: none;
|
||||
}
|
||||
div#nav {
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@import url("nav-horizontal.css");
|
||||
|
||||
/* NAV BAR AT THE TOP, LOCAL NAVIGATION ON THE LEFT AND ONE COLUMN OF CONTENT */
|
||||
div#content {
|
||||
position: relative;
|
||||
width: 701px;
|
||||
|
||||
margin: 0 auto 20px auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#main {
|
||||
float: right;
|
||||
width: 500px;
|
||||
display: inline;
|
||||
}
|
||||
div#local {
|
||||
float: left;
|
||||
width: 200px;
|
||||
display: inline;
|
||||
}
|
||||
div#sub {
|
||||
display: none;
|
||||
}
|
||||
div#nav {
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
/* END CONTENT */
|
||||
@@ -1,61 +1,61 @@
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@import url("nav-horizontal.css");
|
||||
|
||||
/* NAV BAR AT THE TOP AND TWO COLUMNS OF CONTENT */
|
||||
div#content {
|
||||
position: relative;
|
||||
width: 701px;
|
||||
|
||||
margin: 0 auto 20px auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#main {
|
||||
float: left;
|
||||
width: 480px;
|
||||
display: inline;
|
||||
}
|
||||
div#sub {
|
||||
float: right;
|
||||
width: 200px;
|
||||
display: inline;
|
||||
}
|
||||
div#local {
|
||||
display: none;
|
||||
}
|
||||
div#nav {
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@import url("nav-horizontal.css");
|
||||
|
||||
/* NAV BAR AT THE TOP AND TWO COLUMNS OF CONTENT */
|
||||
div#content {
|
||||
position: relative;
|
||||
width: 701px;
|
||||
|
||||
margin: 0 auto 20px auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#main {
|
||||
float: left;
|
||||
width: 480px;
|
||||
display: inline;
|
||||
}
|
||||
div#sub {
|
||||
float: right;
|
||||
width: 200px;
|
||||
display: inline;
|
||||
}
|
||||
div#local {
|
||||
display: none;
|
||||
}
|
||||
div#nav {
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
/* END CONTENT */
|
||||
@@ -1,152 +1,152 @@
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* SITE SPECIFIC LAYOUT */
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
text-align: center;
|
||||
|
||||
background: white;
|
||||
}
|
||||
div#page {
|
||||
width: 780px;
|
||||
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: center;
|
||||
|
||||
background: white;
|
||||
}
|
||||
|
||||
/* HEADER */
|
||||
div#header {
|
||||
margin: 0 0 5em 0;
|
||||
padding: 40px 20px;
|
||||
|
||||
color: white;
|
||||
background: black;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#branding {
|
||||
float: left;
|
||||
width: 40%;
|
||||
|
||||
margin: 0;
|
||||
padding: 10px 0 10px 20px;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#search {
|
||||
float: right;
|
||||
width: 49%;
|
||||
|
||||
margin: 0;
|
||||
padding: 16px 20px 0 0;
|
||||
|
||||
text-align: right;
|
||||
}
|
||||
/* END HEADER */
|
||||
|
||||
|
||||
/* CONTENT */
|
||||
div#content {
|
||||
|
||||
}
|
||||
|
||||
/* MAIN */
|
||||
div#main {
|
||||
|
||||
}
|
||||
/* END MAIN */
|
||||
|
||||
/* SUB */
|
||||
div#sub {
|
||||
|
||||
}
|
||||
/* END SUB */
|
||||
|
||||
/* END CONTENT */
|
||||
|
||||
|
||||
/* FOOTER */
|
||||
div#footer {
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
div#footer p {
|
||||
margin: 0;
|
||||
padding: 15px;
|
||||
|
||||
font-size: 0.8em;
|
||||
}
|
||||
/* END FOOTER */
|
||||
/* END LAYOUT */
|
||||
|
||||
|
||||
/* UL.SUBNAV */
|
||||
ul.subnav {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 0.8em;
|
||||
list-style: none;
|
||||
}
|
||||
ul.subnav li {
|
||||
margin: 0 0 1em 0;
|
||||
padding: 0;
|
||||
|
||||
list-style: none;
|
||||
}
|
||||
ul.subnav li a,
|
||||
ul.subnav li a:link,
|
||||
ul.subnav li a:visited,
|
||||
ul.subnav li a:active {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
|
||||
color: black;
|
||||
}
|
||||
ul.subnav li a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
ul.subnav li strong {
|
||||
padding: 0 0 0 12px;
|
||||
|
||||
background: url("../i/subnav-highlight.gif") left top no-repeat transparent;
|
||||
}
|
||||
ul.subnav li strong a,
|
||||
ul.subnav li strong a:link,
|
||||
ul.subnav li strong a:visited,
|
||||
ul.subnav li strong a:active {
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
/* END UL.SUBNAV */
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* SITE SPECIFIC LAYOUT */
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
text-align: center;
|
||||
|
||||
background: white;
|
||||
}
|
||||
div#page {
|
||||
width: 780px;
|
||||
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: center;
|
||||
|
||||
background: white;
|
||||
}
|
||||
|
||||
/* HEADER */
|
||||
div#header {
|
||||
margin: 0 0 5em 0;
|
||||
padding: 40px 20px;
|
||||
|
||||
color: white;
|
||||
background: black;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#branding {
|
||||
float: left;
|
||||
width: 40%;
|
||||
|
||||
margin: 0;
|
||||
padding: 10px 0 10px 20px;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
div#search {
|
||||
float: right;
|
||||
width: 49%;
|
||||
|
||||
margin: 0;
|
||||
padding: 16px 20px 0 0;
|
||||
|
||||
text-align: right;
|
||||
}
|
||||
/* END HEADER */
|
||||
|
||||
|
||||
/* CONTENT */
|
||||
div#content {
|
||||
|
||||
}
|
||||
|
||||
/* MAIN */
|
||||
div#main {
|
||||
|
||||
}
|
||||
/* END MAIN */
|
||||
|
||||
/* SUB */
|
||||
div#sub {
|
||||
|
||||
}
|
||||
/* END SUB */
|
||||
|
||||
/* END CONTENT */
|
||||
|
||||
|
||||
/* FOOTER */
|
||||
div#footer {
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
div#footer p {
|
||||
margin: 0;
|
||||
padding: 15px;
|
||||
|
||||
font-size: 0.8em;
|
||||
}
|
||||
/* END FOOTER */
|
||||
/* END LAYOUT */
|
||||
|
||||
|
||||
/* UL.SUBNAV */
|
||||
ul.subnav {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 0.8em;
|
||||
list-style: none;
|
||||
}
|
||||
ul.subnav li {
|
||||
margin: 0 0 1em 0;
|
||||
padding: 0;
|
||||
|
||||
list-style: none;
|
||||
}
|
||||
ul.subnav li a,
|
||||
ul.subnav li a:link,
|
||||
ul.subnav li a:visited,
|
||||
ul.subnav li a:active {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
|
||||
color: black;
|
||||
}
|
||||
ul.subnav li a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
ul.subnav li strong {
|
||||
padding: 0 0 0 12px;
|
||||
|
||||
background: url("../i/subnav-highlight.gif") left top no-repeat transparent;
|
||||
}
|
||||
ul.subnav li strong a,
|
||||
ul.subnav li strong a:link,
|
||||
ul.subnav li strong a:visited,
|
||||
ul.subnav li strong a:active {
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
/* END UL.SUBNAV */
|
||||
|
||||
@@ -1,105 +1,105 @@
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* NAV */
|
||||
div#nav {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
* html div#nav {
|
||||
/* hide ie/mac \*/
|
||||
height: 1%;
|
||||
/* end hide */
|
||||
}
|
||||
div#nav div.wrapper {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
div#nav ul {
|
||||
width: 100%;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
line-height: 1em;
|
||||
list-style: none;
|
||||
}
|
||||
div#nav li {
|
||||
float: left;
|
||||
display: inline;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
list-style: none;
|
||||
|
||||
line-height: 1em;
|
||||
border-right: 1px solid #aaa;
|
||||
}
|
||||
div#nav li.last {
|
||||
border-right: none;
|
||||
}
|
||||
div#nav a,
|
||||
div#nav a:link,
|
||||
div#nav a:active,
|
||||
div#nav a:visited {
|
||||
display: inline-block;
|
||||
/* hide from ie/mac \*/
|
||||
display: block;
|
||||
/* end hide */
|
||||
|
||||
margin: 0;
|
||||
padding: 5px 38px 5px 38px;
|
||||
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
|
||||
color: black;
|
||||
background: #ddd;
|
||||
}
|
||||
div#nav a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
div#nav strong {
|
||||
display: inline-block;
|
||||
/* hide from ie/mac \*/
|
||||
display: block;
|
||||
/* end hide */
|
||||
|
||||
color: white;
|
||||
background: black;
|
||||
}
|
||||
div#nav strong a,
|
||||
div#nav strong a:link,
|
||||
div#nav strong a:active,
|
||||
div#nav strong a:visited,
|
||||
div#nav strong a:hover {
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* NAV */
|
||||
div#nav {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
* html div#nav {
|
||||
/* hide ie/mac \*/
|
||||
height: 1%;
|
||||
/* end hide */
|
||||
}
|
||||
div#nav div.wrapper {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
div#nav ul {
|
||||
width: 100%;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
line-height: 1em;
|
||||
list-style: none;
|
||||
}
|
||||
div#nav li {
|
||||
float: left;
|
||||
display: inline;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
list-style: none;
|
||||
|
||||
line-height: 1em;
|
||||
border-right: 1px solid #aaa;
|
||||
}
|
||||
div#nav li.last {
|
||||
border-right: none;
|
||||
}
|
||||
div#nav a,
|
||||
div#nav a:link,
|
||||
div#nav a:active,
|
||||
div#nav a:visited {
|
||||
display: inline-block;
|
||||
/* hide from ie/mac \*/
|
||||
display: block;
|
||||
/* end hide */
|
||||
|
||||
margin: 0;
|
||||
padding: 5px 38px 5px 38px;
|
||||
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
|
||||
color: black;
|
||||
background: #ddd;
|
||||
}
|
||||
div#nav a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
div#nav strong {
|
||||
display: inline-block;
|
||||
/* hide from ie/mac \*/
|
||||
display: block;
|
||||
/* end hide */
|
||||
|
||||
color: white;
|
||||
background: black;
|
||||
}
|
||||
div#nav strong a,
|
||||
div#nav strong a:link,
|
||||
div#nav strong a:active,
|
||||
div#nav strong a:visited,
|
||||
div#nav strong a:hover {
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
/* END NAV */
|
||||
@@ -1,104 +1,104 @@
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* NAV */
|
||||
div#nav {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
* html div#nav {
|
||||
/* hide ie/mac \*/
|
||||
height: 1%;
|
||||
/* end hide */
|
||||
}
|
||||
div#nav div.wrapper {
|
||||
width: 100%;
|
||||
|
||||
background: #ddd;
|
||||
}
|
||||
div#nav ul {
|
||||
width: 100%;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
line-height: 1em;
|
||||
list-style: none;
|
||||
}
|
||||
div#nav li {
|
||||
display: block;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
list-style: none;
|
||||
|
||||
line-height: 1em;
|
||||
}
|
||||
* html div#nav li {
|
||||
/* hide ie/mac \*/
|
||||
height: 1%;
|
||||
/* end hide */
|
||||
}
|
||||
div#nav li.last {
|
||||
|
||||
}
|
||||
div#nav a,
|
||||
div#nav a:link,
|
||||
div#nav a:active,
|
||||
div#nav a:visited {
|
||||
display: block;
|
||||
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
|
||||
margin: 0;
|
||||
padding: 5px 10px 5px 10px;
|
||||
|
||||
color: black;
|
||||
background: white;
|
||||
}
|
||||
div#nav a:hover {
|
||||
text-decoration: underline;
|
||||
|
||||
color: white;
|
||||
background: black;
|
||||
}
|
||||
div#nav strong {
|
||||
display: block;
|
||||
|
||||
color: white;
|
||||
background: black;
|
||||
}
|
||||
div#nav strong a,
|
||||
div#nav strong a:link,
|
||||
div#nav strong a:active,
|
||||
div#nav strong a:visited,
|
||||
div#nav strong a:hover {
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* NAV */
|
||||
div#nav {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
* html div#nav {
|
||||
/* hide ie/mac \*/
|
||||
height: 1%;
|
||||
/* end hide */
|
||||
}
|
||||
div#nav div.wrapper {
|
||||
width: 100%;
|
||||
|
||||
background: #ddd;
|
||||
}
|
||||
div#nav ul {
|
||||
width: 100%;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
line-height: 1em;
|
||||
list-style: none;
|
||||
}
|
||||
div#nav li {
|
||||
display: block;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
list-style: none;
|
||||
|
||||
line-height: 1em;
|
||||
}
|
||||
* html div#nav li {
|
||||
/* hide ie/mac \*/
|
||||
height: 1%;
|
||||
/* end hide */
|
||||
}
|
||||
div#nav li.last {
|
||||
|
||||
}
|
||||
div#nav a,
|
||||
div#nav a:link,
|
||||
div#nav a:active,
|
||||
div#nav a:visited {
|
||||
display: block;
|
||||
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
|
||||
margin: 0;
|
||||
padding: 5px 10px 5px 10px;
|
||||
|
||||
color: black;
|
||||
background: white;
|
||||
}
|
||||
div#nav a:hover {
|
||||
text-decoration: underline;
|
||||
|
||||
color: white;
|
||||
background: black;
|
||||
}
|
||||
div#nav strong {
|
||||
display: block;
|
||||
|
||||
color: white;
|
||||
background: black;
|
||||
}
|
||||
div#nav strong a,
|
||||
div#nav strong a:link,
|
||||
div#nav strong a:active,
|
||||
div#nav strong a:visited,
|
||||
div#nav strong a:hover {
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
/* END NAV */
|
||||
@@ -1,64 +1,64 @@
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* clearing */
|
||||
.stretch,
|
||||
.clear {
|
||||
clear: both;
|
||||
height: 1px;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 15px;
|
||||
line-height: 1px;
|
||||
}
|
||||
.clearfix:after {
|
||||
clear: both;
|
||||
height: 0;
|
||||
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
|
||||
content: ".";
|
||||
}
|
||||
.clearfix {display:inline-block;}
|
||||
/* Hide from IE Mac \*/
|
||||
.clearfix {display:block;}
|
||||
/* End hide from IE Mac */
|
||||
/* end clearing */
|
||||
|
||||
/* accessibility */
|
||||
span.accesskey {
|
||||
text-decoration: none;
|
||||
}
|
||||
.accessibility {
|
||||
position: absolute;
|
||||
top: -999em;
|
||||
left: -999em;
|
||||
}
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* clearing */
|
||||
.stretch,
|
||||
.clear {
|
||||
clear: both;
|
||||
height: 1px;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 15px;
|
||||
line-height: 1px;
|
||||
}
|
||||
.clearfix:after {
|
||||
clear: both;
|
||||
height: 0;
|
||||
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
|
||||
content: ".";
|
||||
}
|
||||
.clearfix {display:inline-block;}
|
||||
/* Hide from IE Mac \*/
|
||||
.clearfix {display:block;}
|
||||
/* End hide from IE Mac */
|
||||
/* end clearing */
|
||||
|
||||
/* accessibility */
|
||||
span.accesskey {
|
||||
text-decoration: none;
|
||||
}
|
||||
.accessibility {
|
||||
position: absolute;
|
||||
top: -999em;
|
||||
left: -999em;
|
||||
}
|
||||
/* end accessibility */
|
||||
@@ -1,228 +1,228 @@
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* TYPOGRAPHY */
|
||||
body {
|
||||
text-align: left;
|
||||
font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
|
||||
font-size: 76%;
|
||||
line-height: 1em;
|
||||
|
||||
color: #333;
|
||||
}
|
||||
div {
|
||||
font-size: 1em;
|
||||
}
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* LINKS */
|
||||
a,
|
||||
a:link,
|
||||
a:active {
|
||||
text-decoration: underline;
|
||||
|
||||
color: blue;
|
||||
background-color: white;
|
||||
}
|
||||
a:visited {
|
||||
color: purple;
|
||||
background-color: transparent;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
/* END LINKS */
|
||||
|
||||
/* HEADINGS */
|
||||
h1 {
|
||||
margin: 0 0 0.5em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 2em;
|
||||
line-height: 1.5em;
|
||||
|
||||
color: black;
|
||||
}
|
||||
h2 {
|
||||
margin: 0 0 0.5em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1.5em;
|
||||
line-height: 1.5em;
|
||||
|
||||
color: black;
|
||||
}
|
||||
h3 {
|
||||
margin: 0 0 0.5em 0;
|
||||
padding:0;
|
||||
|
||||
font-size: 1.3em;
|
||||
line-height: 1.3em;
|
||||
|
||||
color: black;
|
||||
}
|
||||
h4 {
|
||||
margin: 0 0 0.25em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1.2em;
|
||||
line-height: 1.3em;
|
||||
|
||||
color: black;
|
||||
}
|
||||
h5 {
|
||||
margin: 0 0 0.25em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1.1em;
|
||||
line-height: 1.3em;
|
||||
|
||||
color: black;
|
||||
}
|
||||
h6 {
|
||||
margin: 0 0 0.25em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1em;
|
||||
line-height: 1.3em;
|
||||
|
||||
color: black;
|
||||
}
|
||||
/* END HEADINGS */
|
||||
|
||||
/* TEXT */
|
||||
p {
|
||||
margin: 0 0 1.5em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1em;
|
||||
line-height:1.4em;
|
||||
}
|
||||
blockquote {
|
||||
margin-left: 10px;
|
||||
|
||||
border-left: 10px solid #ddd;
|
||||
}
|
||||
pre {
|
||||
font-family: monospace;
|
||||
font-size: 1.0em;
|
||||
}
|
||||
strong, b {
|
||||
font-weight: bold;
|
||||
}
|
||||
em, i {
|
||||
font-style:italic;
|
||||
}
|
||||
code {
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
font-size: 1em;
|
||||
white-space: pre;
|
||||
}
|
||||
/* END TEXT */
|
||||
|
||||
/* LISTS */
|
||||
ul {
|
||||
margin: 0 0 1.5em 0;
|
||||
padding: 0;
|
||||
|
||||
line-height:1.4em;
|
||||
}
|
||||
ul li {
|
||||
margin: 0 0 0.25em 30px;
|
||||
padding: 0;
|
||||
}
|
||||
ol {
|
||||
margin: 0 0 1.5em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1.0em;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
ol li {
|
||||
margin: 0 0 0.25em 30px;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1.0em;
|
||||
}
|
||||
dl {
|
||||
margin: 0 0 1.5em 0;
|
||||
padding: 0;
|
||||
|
||||
line-height: 1.4em;
|
||||
}
|
||||
dl dt {
|
||||
margin: 0.25em 0 0.25em 0;
|
||||
padding: 0;
|
||||
|
||||
font-weight: bold;
|
||||
}
|
||||
dl dd {
|
||||
margin: 0 0 0 30px;
|
||||
padding: 0;
|
||||
}
|
||||
/* END LISTS */
|
||||
|
||||
|
||||
/* TABLE */
|
||||
table {
|
||||
margin: 0 0 1.5em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1em;
|
||||
}
|
||||
table caption {
|
||||
margin: 0;
|
||||
padding: 0 0 1.5em 0;
|
||||
|
||||
font-weight: bold;
|
||||
}
|
||||
th {
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
td {
|
||||
font-size: 1em;
|
||||
}
|
||||
/* END TABLE */
|
||||
|
||||
hr {
|
||||
display: none;
|
||||
}
|
||||
div.hr {
|
||||
height: 1px;
|
||||
|
||||
margin: 1.5em 10px;
|
||||
|
||||
border-bottom: 1px dotted black;
|
||||
}
|
||||
|
||||
/*
|
||||
A CSS Framework by Mike Stenhouse of Content with Style
|
||||
-------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005, Mike Stenhouse of Content with Style
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of CSS Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* TYPOGRAPHY */
|
||||
body {
|
||||
text-align: left;
|
||||
font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
|
||||
font-size: 76%;
|
||||
line-height: 1em;
|
||||
|
||||
color: #333;
|
||||
}
|
||||
div {
|
||||
font-size: 1em;
|
||||
}
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* LINKS */
|
||||
a,
|
||||
a:link,
|
||||
a:active {
|
||||
text-decoration: underline;
|
||||
|
||||
color: blue;
|
||||
background-color: white;
|
||||
}
|
||||
a:visited {
|
||||
color: purple;
|
||||
background-color: transparent;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
/* END LINKS */
|
||||
|
||||
/* HEADINGS */
|
||||
h1 {
|
||||
margin: 0 0 0.5em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 2em;
|
||||
line-height: 1.5em;
|
||||
|
||||
color: black;
|
||||
}
|
||||
h2 {
|
||||
margin: 0 0 0.5em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1.5em;
|
||||
line-height: 1.5em;
|
||||
|
||||
color: black;
|
||||
}
|
||||
h3 {
|
||||
margin: 0 0 0.5em 0;
|
||||
padding:0;
|
||||
|
||||
font-size: 1.3em;
|
||||
line-height: 1.3em;
|
||||
|
||||
color: black;
|
||||
}
|
||||
h4 {
|
||||
margin: 0 0 0.25em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1.2em;
|
||||
line-height: 1.3em;
|
||||
|
||||
color: black;
|
||||
}
|
||||
h5 {
|
||||
margin: 0 0 0.25em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1.1em;
|
||||
line-height: 1.3em;
|
||||
|
||||
color: black;
|
||||
}
|
||||
h6 {
|
||||
margin: 0 0 0.25em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1em;
|
||||
line-height: 1.3em;
|
||||
|
||||
color: black;
|
||||
}
|
||||
/* END HEADINGS */
|
||||
|
||||
/* TEXT */
|
||||
p {
|
||||
margin: 0 0 1.5em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1em;
|
||||
line-height:1.4em;
|
||||
}
|
||||
blockquote {
|
||||
margin-left: 10px;
|
||||
|
||||
border-left: 10px solid #ddd;
|
||||
}
|
||||
pre {
|
||||
font-family: monospace;
|
||||
font-size: 1.0em;
|
||||
}
|
||||
strong, b {
|
||||
font-weight: bold;
|
||||
}
|
||||
em, i {
|
||||
font-style:italic;
|
||||
}
|
||||
code {
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
font-size: 1em;
|
||||
white-space: pre;
|
||||
}
|
||||
/* END TEXT */
|
||||
|
||||
/* LISTS */
|
||||
ul {
|
||||
margin: 0 0 1.5em 0;
|
||||
padding: 0;
|
||||
|
||||
line-height:1.4em;
|
||||
}
|
||||
ul li {
|
||||
margin: 0 0 0.25em 30px;
|
||||
padding: 0;
|
||||
}
|
||||
ol {
|
||||
margin: 0 0 1.5em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1.0em;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
ol li {
|
||||
margin: 0 0 0.25em 30px;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1.0em;
|
||||
}
|
||||
dl {
|
||||
margin: 0 0 1.5em 0;
|
||||
padding: 0;
|
||||
|
||||
line-height: 1.4em;
|
||||
}
|
||||
dl dt {
|
||||
margin: 0.25em 0 0.25em 0;
|
||||
padding: 0;
|
||||
|
||||
font-weight: bold;
|
||||
}
|
||||
dl dd {
|
||||
margin: 0 0 0 30px;
|
||||
padding: 0;
|
||||
}
|
||||
/* END LISTS */
|
||||
|
||||
|
||||
/* TABLE */
|
||||
table {
|
||||
margin: 0 0 1.5em 0;
|
||||
padding: 0;
|
||||
|
||||
font-size: 1em;
|
||||
}
|
||||
table caption {
|
||||
margin: 0;
|
||||
padding: 0 0 1.5em 0;
|
||||
|
||||
font-weight: bold;
|
||||
}
|
||||
th {
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
td {
|
||||
font-size: 1em;
|
||||
}
|
||||
/* END TABLE */
|
||||
|
||||
hr {
|
||||
display: none;
|
||||
}
|
||||
div.hr {
|
||||
height: 1px;
|
||||
|
||||
margin: 1.5em 10px;
|
||||
|
||||
border-bottom: 1px dotted black;
|
||||
}
|
||||
|
||||
/* END TYPOGRAPHY */
|
||||
@@ -1,113 +1,113 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.action;
|
||||
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
import org.springframework.webflow.execution.ActionExecutor;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* An action that evaluates an expression and optionally exposes its result.
|
||||
* <p>
|
||||
* Delegates to a {@link ResultEventFactory} to determine how to map the evaluation result to an action outcome
|
||||
* {@link Event}.
|
||||
*
|
||||
* @see Expression
|
||||
* @see ResultEventFactory
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class EvaluateAction extends AbstractAction {
|
||||
|
||||
/**
|
||||
* The expression to evaluate when this action is invoked. Required.
|
||||
*/
|
||||
private Expression expression;
|
||||
|
||||
/**
|
||||
* The expression to evaluate to set the result of the action. Optional.
|
||||
*/
|
||||
private Expression resultExpression;
|
||||
|
||||
/**
|
||||
* The selector for the factory that will create the action result event callers can respond to.
|
||||
*/
|
||||
private ResultEventFactory resultEventFactory;
|
||||
|
||||
/**
|
||||
* Create a new evaluate action.
|
||||
* @param expression the expression to evaluate (required)
|
||||
* @param resultExpression the expression to evaluate the result (optional)
|
||||
*/
|
||||
public EvaluateAction(Expression expression, Expression resultExpression) {
|
||||
init(expression, resultExpression, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new evaluate action.
|
||||
* @param expression the expression to evaluate (required)
|
||||
* @param resultExpression the strategy for how the expression result will be exposed to the flow (optional)
|
||||
* @param resultEventFactory the factory that will map the evaluation result to a Web Flow event (optional)
|
||||
*/
|
||||
public EvaluateAction(Expression expression, Expression resultExpression, ResultEventFactory resultEventFactory) {
|
||||
init(expression, resultExpression, resultEventFactory);
|
||||
}
|
||||
|
||||
protected Event doExecute(RequestContext context) throws Exception {
|
||||
Object result = expression.getValue(context);
|
||||
if (result instanceof Action) {
|
||||
return ActionExecutor.execute((Action) result, context);
|
||||
} else {
|
||||
if (resultExpression != null) {
|
||||
resultExpression.setValue(context, result);
|
||||
}
|
||||
return resultEventFactory.createResultEvent(this, result, context);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("expression", expression).append("resultExpression", resultExpression)
|
||||
.toString();
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private void init(Expression expression, Expression resultExpression, ResultEventFactory resultEventFactory) {
|
||||
Assert.notNull(expression, "The expression this action should evaluate is required");
|
||||
this.expression = expression;
|
||||
this.resultExpression = resultExpression;
|
||||
this.resultEventFactory = resultEventFactory != null ? resultEventFactory : new DefaultResultEventFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation that uses the ResultEventFactorySelector helper.
|
||||
* @author Keith Donald
|
||||
*/
|
||||
private class DefaultResultEventFactory implements ResultEventFactory {
|
||||
|
||||
private ResultEventFactorySelector selector = new ResultEventFactorySelector();
|
||||
|
||||
public Event createResultEvent(Object source, Object resultObject, RequestContext context) {
|
||||
return selector.forResult(resultObject).createResultEvent(source, resultObject, context);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.action;
|
||||
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
import org.springframework.webflow.execution.ActionExecutor;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* An action that evaluates an expression and optionally exposes its result.
|
||||
* <p>
|
||||
* Delegates to a {@link ResultEventFactory} to determine how to map the evaluation result to an action outcome
|
||||
* {@link Event}.
|
||||
*
|
||||
* @see Expression
|
||||
* @see ResultEventFactory
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class EvaluateAction extends AbstractAction {
|
||||
|
||||
/**
|
||||
* The expression to evaluate when this action is invoked. Required.
|
||||
*/
|
||||
private Expression expression;
|
||||
|
||||
/**
|
||||
* The expression to evaluate to set the result of the action. Optional.
|
||||
*/
|
||||
private Expression resultExpression;
|
||||
|
||||
/**
|
||||
* The selector for the factory that will create the action result event callers can respond to.
|
||||
*/
|
||||
private ResultEventFactory resultEventFactory;
|
||||
|
||||
/**
|
||||
* Create a new evaluate action.
|
||||
* @param expression the expression to evaluate (required)
|
||||
* @param resultExpression the expression to evaluate the result (optional)
|
||||
*/
|
||||
public EvaluateAction(Expression expression, Expression resultExpression) {
|
||||
init(expression, resultExpression, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new evaluate action.
|
||||
* @param expression the expression to evaluate (required)
|
||||
* @param resultExpression the strategy for how the expression result will be exposed to the flow (optional)
|
||||
* @param resultEventFactory the factory that will map the evaluation result to a Web Flow event (optional)
|
||||
*/
|
||||
public EvaluateAction(Expression expression, Expression resultExpression, ResultEventFactory resultEventFactory) {
|
||||
init(expression, resultExpression, resultEventFactory);
|
||||
}
|
||||
|
||||
protected Event doExecute(RequestContext context) throws Exception {
|
||||
Object result = expression.getValue(context);
|
||||
if (result instanceof Action) {
|
||||
return ActionExecutor.execute((Action) result, context);
|
||||
} else {
|
||||
if (resultExpression != null) {
|
||||
resultExpression.setValue(context, result);
|
||||
}
|
||||
return resultEventFactory.createResultEvent(this, result, context);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("expression", expression).append("resultExpression", resultExpression)
|
||||
.toString();
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private void init(Expression expression, Expression resultExpression, ResultEventFactory resultEventFactory) {
|
||||
Assert.notNull(expression, "The expression this action should evaluate is required");
|
||||
this.expression = expression;
|
||||
this.resultExpression = resultExpression;
|
||||
this.resultEventFactory = resultEventFactory != null ? resultEventFactory : new DefaultResultEventFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation that uses the ResultEventFactorySelector helper.
|
||||
* @author Keith Donald
|
||||
*/
|
||||
private class DefaultResultEventFactory implements ResultEventFactory {
|
||||
|
||||
private ResultEventFactorySelector selector = new ResultEventFactorySelector();
|
||||
|
||||
public Event createResultEvent(Object source, Object resultObject, RequestContext context) {
|
||||
return selector.forResult(resultObject).createResultEvent(source, resultObject, context);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,257 +1,257 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.action;
|
||||
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.CollectionUtils;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
|
||||
/**
|
||||
* A convenience support class assisting in the creation of {@link Event} objects.
|
||||
* <p>
|
||||
* This class can be used as a simple utility class when you need to create common event objects. Alternatively you
|
||||
* could extend it as a base support class when creating custom event factories.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class EventFactorySupport {
|
||||
|
||||
/**
|
||||
* The default 'success' result event identifier ("success").
|
||||
*/
|
||||
private static final String SUCCESS_EVENT_ID = "success";
|
||||
|
||||
/**
|
||||
* The default 'error' result event identifier ("error").
|
||||
*/
|
||||
private static final String ERROR_EVENT_ID = "error";
|
||||
|
||||
/**
|
||||
* The default 'yes' result event identifier ("yes").
|
||||
*/
|
||||
private static final String YES_EVENT_ID = "yes";
|
||||
|
||||
/**
|
||||
* The default 'no' result event identifier ("no").
|
||||
*/
|
||||
private static final String NO_EVENT_ID = "no";
|
||||
|
||||
/**
|
||||
* The default 'null' result event identifier ("null").
|
||||
*/
|
||||
private static final String NULL_EVENT_ID = "null";
|
||||
|
||||
/**
|
||||
* The default 'exception' event attribute name ("exception").
|
||||
*/
|
||||
private static final String EXCEPTION_ATTRIBUTE_NAME = "exception";
|
||||
|
||||
/**
|
||||
* The default 'result' event attribute name ("result").
|
||||
*/
|
||||
private static final String RESULT_ATTRIBUTE_NAME = "result";
|
||||
|
||||
/**
|
||||
* The success event identifier.
|
||||
*/
|
||||
private String successEventId = SUCCESS_EVENT_ID;
|
||||
|
||||
/**
|
||||
* The error event identifier.
|
||||
*/
|
||||
private String errorEventId = ERROR_EVENT_ID;
|
||||
|
||||
/**
|
||||
* The yes event identifier.
|
||||
*/
|
||||
private String yesEventId = YES_EVENT_ID;
|
||||
|
||||
/**
|
||||
* The no event identifier.
|
||||
*/
|
||||
private String noEventId = NO_EVENT_ID;
|
||||
|
||||
/**
|
||||
* The null event identifier.
|
||||
*/
|
||||
private String nullEventId = NULL_EVENT_ID;
|
||||
|
||||
/**
|
||||
* The exception event attribute name.
|
||||
*/
|
||||
private String exceptionAttributeName = EXCEPTION_ATTRIBUTE_NAME;
|
||||
|
||||
/**
|
||||
* The result event attribute name.
|
||||
*/
|
||||
private String resultAttributeName = RESULT_ATTRIBUTE_NAME;
|
||||
|
||||
public String getSuccessEventId() {
|
||||
return successEventId;
|
||||
}
|
||||
|
||||
public void setSuccessEventId(String successEventId) {
|
||||
this.successEventId = successEventId;
|
||||
}
|
||||
|
||||
public String getErrorEventId() {
|
||||
return errorEventId;
|
||||
}
|
||||
|
||||
public void setErrorEventId(String errorEventId) {
|
||||
this.errorEventId = errorEventId;
|
||||
}
|
||||
|
||||
public String getYesEventId() {
|
||||
return yesEventId;
|
||||
}
|
||||
|
||||
public void setYesEventId(String yesEventId) {
|
||||
this.yesEventId = yesEventId;
|
||||
}
|
||||
|
||||
public String getNoEventId() {
|
||||
return noEventId;
|
||||
}
|
||||
|
||||
public void setNoEventId(String noEventId) {
|
||||
this.noEventId = noEventId;
|
||||
}
|
||||
|
||||
public String getNullEventId() {
|
||||
return nullEventId;
|
||||
}
|
||||
|
||||
public void setNullEventId(String nullEventId) {
|
||||
this.nullEventId = nullEventId;
|
||||
}
|
||||
|
||||
public String getExceptionAttributeName() {
|
||||
return exceptionAttributeName;
|
||||
}
|
||||
|
||||
public void setExceptionAttributeName(String exceptionAttributeName) {
|
||||
this.exceptionAttributeName = exceptionAttributeName;
|
||||
}
|
||||
|
||||
public String getResultAttributeName() {
|
||||
return resultAttributeName;
|
||||
}
|
||||
|
||||
public void setResultAttributeName(String resultAttributeName) {
|
||||
this.resultAttributeName = resultAttributeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a "success" event.
|
||||
* @param source the source of the event
|
||||
*/
|
||||
public Event success(Object source) {
|
||||
return event(source, getSuccessEventId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a "success" event with the provided result object as an attribute. The result object is identified by the
|
||||
* attribute name {@link #getResultAttributeName()}.
|
||||
* @param source the source of the event
|
||||
* @param result the action success result
|
||||
*/
|
||||
public Event success(Object source, Object result) {
|
||||
return event(source, getSuccessEventId(), getResultAttributeName(), result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an "error" event.
|
||||
* @param source the source of the event
|
||||
*/
|
||||
public Event error(Object source) {
|
||||
return event(source, getErrorEventId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an "error" event caused by the provided exception.
|
||||
* @param source the source of the event
|
||||
* @param e the exception that caused the error event, to be put as an event attribute under the name
|
||||
* {@link #getExceptionAttributeName()}
|
||||
*/
|
||||
public Event error(Object source, Exception e) {
|
||||
return event(source, getErrorEventId(), getExceptionAttributeName(), e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a "yes" event.
|
||||
* @param source the source of the event
|
||||
*/
|
||||
public Event yes(Object source) {
|
||||
return event(source, getYesEventId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a "no" result event.
|
||||
* @param source the source of the event
|
||||
*/
|
||||
public Event no(Object source) {
|
||||
return event(source, getNoEventId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an event to communicate an occurrence of a boolean expression.
|
||||
* @param source the source of the event
|
||||
* @param booleanResult the boolean
|
||||
* @return yes or no
|
||||
*/
|
||||
public Event event(Object source, boolean booleanResult) {
|
||||
if (booleanResult) {
|
||||
return yes(source);
|
||||
} else {
|
||||
return no(source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a event with the specified identifier.
|
||||
* @param source the source of the event
|
||||
* @param eventId the result event identifier
|
||||
* @return the event
|
||||
*/
|
||||
public Event event(Object source, String eventId) {
|
||||
return new Event(source, eventId, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a event with the specified identifier and the specified set of attributes.
|
||||
* @param source the source of the event
|
||||
* @param eventId the result event identifier
|
||||
* @param attributes the event payload attributes
|
||||
* @return the event
|
||||
*/
|
||||
public Event event(Object source, String eventId, AttributeMap<Object> attributes) {
|
||||
return new Event(source, eventId, attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a result event with the specified identifier and a single attribute.
|
||||
* @param source the source of the event
|
||||
* @param eventId the result id
|
||||
* @param attributeName the attribute name
|
||||
* @param attributeValue the attribute value
|
||||
* @return the event
|
||||
*/
|
||||
public Event event(Object source, String eventId, String attributeName, Object attributeValue) {
|
||||
return new Event(source, eventId, CollectionUtils.singleEntryMap(attributeName, attributeValue));
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.action;
|
||||
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.CollectionUtils;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
|
||||
/**
|
||||
* A convenience support class assisting in the creation of {@link Event} objects.
|
||||
* <p>
|
||||
* This class can be used as a simple utility class when you need to create common event objects. Alternatively you
|
||||
* could extend it as a base support class when creating custom event factories.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class EventFactorySupport {
|
||||
|
||||
/**
|
||||
* The default 'success' result event identifier ("success").
|
||||
*/
|
||||
private static final String SUCCESS_EVENT_ID = "success";
|
||||
|
||||
/**
|
||||
* The default 'error' result event identifier ("error").
|
||||
*/
|
||||
private static final String ERROR_EVENT_ID = "error";
|
||||
|
||||
/**
|
||||
* The default 'yes' result event identifier ("yes").
|
||||
*/
|
||||
private static final String YES_EVENT_ID = "yes";
|
||||
|
||||
/**
|
||||
* The default 'no' result event identifier ("no").
|
||||
*/
|
||||
private static final String NO_EVENT_ID = "no";
|
||||
|
||||
/**
|
||||
* The default 'null' result event identifier ("null").
|
||||
*/
|
||||
private static final String NULL_EVENT_ID = "null";
|
||||
|
||||
/**
|
||||
* The default 'exception' event attribute name ("exception").
|
||||
*/
|
||||
private static final String EXCEPTION_ATTRIBUTE_NAME = "exception";
|
||||
|
||||
/**
|
||||
* The default 'result' event attribute name ("result").
|
||||
*/
|
||||
private static final String RESULT_ATTRIBUTE_NAME = "result";
|
||||
|
||||
/**
|
||||
* The success event identifier.
|
||||
*/
|
||||
private String successEventId = SUCCESS_EVENT_ID;
|
||||
|
||||
/**
|
||||
* The error event identifier.
|
||||
*/
|
||||
private String errorEventId = ERROR_EVENT_ID;
|
||||
|
||||
/**
|
||||
* The yes event identifier.
|
||||
*/
|
||||
private String yesEventId = YES_EVENT_ID;
|
||||
|
||||
/**
|
||||
* The no event identifier.
|
||||
*/
|
||||
private String noEventId = NO_EVENT_ID;
|
||||
|
||||
/**
|
||||
* The null event identifier.
|
||||
*/
|
||||
private String nullEventId = NULL_EVENT_ID;
|
||||
|
||||
/**
|
||||
* The exception event attribute name.
|
||||
*/
|
||||
private String exceptionAttributeName = EXCEPTION_ATTRIBUTE_NAME;
|
||||
|
||||
/**
|
||||
* The result event attribute name.
|
||||
*/
|
||||
private String resultAttributeName = RESULT_ATTRIBUTE_NAME;
|
||||
|
||||
public String getSuccessEventId() {
|
||||
return successEventId;
|
||||
}
|
||||
|
||||
public void setSuccessEventId(String successEventId) {
|
||||
this.successEventId = successEventId;
|
||||
}
|
||||
|
||||
public String getErrorEventId() {
|
||||
return errorEventId;
|
||||
}
|
||||
|
||||
public void setErrorEventId(String errorEventId) {
|
||||
this.errorEventId = errorEventId;
|
||||
}
|
||||
|
||||
public String getYesEventId() {
|
||||
return yesEventId;
|
||||
}
|
||||
|
||||
public void setYesEventId(String yesEventId) {
|
||||
this.yesEventId = yesEventId;
|
||||
}
|
||||
|
||||
public String getNoEventId() {
|
||||
return noEventId;
|
||||
}
|
||||
|
||||
public void setNoEventId(String noEventId) {
|
||||
this.noEventId = noEventId;
|
||||
}
|
||||
|
||||
public String getNullEventId() {
|
||||
return nullEventId;
|
||||
}
|
||||
|
||||
public void setNullEventId(String nullEventId) {
|
||||
this.nullEventId = nullEventId;
|
||||
}
|
||||
|
||||
public String getExceptionAttributeName() {
|
||||
return exceptionAttributeName;
|
||||
}
|
||||
|
||||
public void setExceptionAttributeName(String exceptionAttributeName) {
|
||||
this.exceptionAttributeName = exceptionAttributeName;
|
||||
}
|
||||
|
||||
public String getResultAttributeName() {
|
||||
return resultAttributeName;
|
||||
}
|
||||
|
||||
public void setResultAttributeName(String resultAttributeName) {
|
||||
this.resultAttributeName = resultAttributeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a "success" event.
|
||||
* @param source the source of the event
|
||||
*/
|
||||
public Event success(Object source) {
|
||||
return event(source, getSuccessEventId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a "success" event with the provided result object as an attribute. The result object is identified by the
|
||||
* attribute name {@link #getResultAttributeName()}.
|
||||
* @param source the source of the event
|
||||
* @param result the action success result
|
||||
*/
|
||||
public Event success(Object source, Object result) {
|
||||
return event(source, getSuccessEventId(), getResultAttributeName(), result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an "error" event.
|
||||
* @param source the source of the event
|
||||
*/
|
||||
public Event error(Object source) {
|
||||
return event(source, getErrorEventId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an "error" event caused by the provided exception.
|
||||
* @param source the source of the event
|
||||
* @param e the exception that caused the error event, to be put as an event attribute under the name
|
||||
* {@link #getExceptionAttributeName()}
|
||||
*/
|
||||
public Event error(Object source, Exception e) {
|
||||
return event(source, getErrorEventId(), getExceptionAttributeName(), e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a "yes" event.
|
||||
* @param source the source of the event
|
||||
*/
|
||||
public Event yes(Object source) {
|
||||
return event(source, getYesEventId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a "no" result event.
|
||||
* @param source the source of the event
|
||||
*/
|
||||
public Event no(Object source) {
|
||||
return event(source, getNoEventId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an event to communicate an occurrence of a boolean expression.
|
||||
* @param source the source of the event
|
||||
* @param booleanResult the boolean
|
||||
* @return yes or no
|
||||
*/
|
||||
public Event event(Object source, boolean booleanResult) {
|
||||
if (booleanResult) {
|
||||
return yes(source);
|
||||
} else {
|
||||
return no(source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a event with the specified identifier.
|
||||
* @param source the source of the event
|
||||
* @param eventId the result event identifier
|
||||
* @return the event
|
||||
*/
|
||||
public Event event(Object source, String eventId) {
|
||||
return new Event(source, eventId, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a event with the specified identifier and the specified set of attributes.
|
||||
* @param source the source of the event
|
||||
* @param eventId the result event identifier
|
||||
* @param attributes the event payload attributes
|
||||
* @return the event
|
||||
*/
|
||||
public Event event(Object source, String eventId, AttributeMap<Object> attributes) {
|
||||
return new Event(source, eventId, attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a result event with the specified identifier and a single attribute.
|
||||
* @param source the source of the event
|
||||
* @param eventId the result id
|
||||
* @param attributeName the attribute name
|
||||
* @param attributeValue the attribute value
|
||||
* @return the event
|
||||
*/
|
||||
public Event event(Object source, String eventId, String attributeName, Object attributeValue) {
|
||||
return new Event(source, eventId, CollectionUtils.singleEntryMap(attributeName, attributeValue));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,62 +1,62 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.action;
|
||||
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.View;
|
||||
|
||||
/**
|
||||
* An action that sets a special attribute that views use to render partial views called "fragments", instead of the
|
||||
* entire view.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class RenderAction extends AbstractAction {
|
||||
|
||||
/**
|
||||
* The expression for setting the scoped attribute value.
|
||||
*/
|
||||
private Expression[] fragmentExpressions;
|
||||
|
||||
/**
|
||||
* Creates a new render action.
|
||||
* @param fragmentExpressions the set of expressions to resolve the view fragments to render
|
||||
*/
|
||||
public RenderAction(Expression... fragmentExpressions) {
|
||||
if (fragmentExpressions == null || fragmentExpressions.length == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"You must provide at least one fragment expression to this render action");
|
||||
}
|
||||
this.fragmentExpressions = fragmentExpressions;
|
||||
}
|
||||
|
||||
protected Event doExecute(RequestContext context) throws Exception {
|
||||
String[] fragments = new String[fragmentExpressions.length];
|
||||
for (int i = 0; i < fragmentExpressions.length; i++) {
|
||||
Expression exp = fragmentExpressions[i];
|
||||
fragments[i] = (String) exp.getValue(context);
|
||||
}
|
||||
context.getFlashScope().put(View.RENDER_FRAGMENTS_ATTRIBUTE, fragments);
|
||||
return success();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("fragments", fragmentExpressions).toString();
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.action;
|
||||
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.View;
|
||||
|
||||
/**
|
||||
* An action that sets a special attribute that views use to render partial views called "fragments", instead of the
|
||||
* entire view.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class RenderAction extends AbstractAction {
|
||||
|
||||
/**
|
||||
* The expression for setting the scoped attribute value.
|
||||
*/
|
||||
private Expression[] fragmentExpressions;
|
||||
|
||||
/**
|
||||
* Creates a new render action.
|
||||
* @param fragmentExpressions the set of expressions to resolve the view fragments to render
|
||||
*/
|
||||
public RenderAction(Expression... fragmentExpressions) {
|
||||
if (fragmentExpressions == null || fragmentExpressions.length == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"You must provide at least one fragment expression to this render action");
|
||||
}
|
||||
this.fragmentExpressions = fragmentExpressions;
|
||||
}
|
||||
|
||||
protected Event doExecute(RequestContext context) throws Exception {
|
||||
String[] fragments = new String[fragmentExpressions.length];
|
||||
for (int i = 0; i < fragmentExpressions.length; i++) {
|
||||
Expression exp = fragmentExpressions[i];
|
||||
fragments[i] = (String) exp.getValue(context);
|
||||
}
|
||||
context.getFlashScope().put(View.RENDER_FRAGMENTS_ATTRIBUTE, fragments);
|
||||
return success();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("fragments", fragmentExpressions).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,77 +1,77 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.action;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Helper that selects the {@link ResultEventFactory} to use for a particular result object.
|
||||
*
|
||||
* @see EvaluateAction
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class ResultEventFactorySelector {
|
||||
|
||||
/**
|
||||
* The event factory instance for mapping a return value to a success event.
|
||||
*/
|
||||
private SuccessEventFactory successEventFactory = new SuccessEventFactory();
|
||||
|
||||
/**
|
||||
* The event factory instance for mapping a result object to an event, using the type of the result object as the
|
||||
* mapping criteria.
|
||||
*/
|
||||
private ResultObjectBasedEventFactory resultObjectBasedEventFactory = new ResultObjectBasedEventFactory();
|
||||
|
||||
/**
|
||||
* Select the appropriate result event factory for attempts to invoke the given method.
|
||||
* @param method the method
|
||||
* @return the result event factory
|
||||
*/
|
||||
public ResultEventFactory forMethod(Method method) {
|
||||
return forType(method.getReturnType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the appropriate result event factory for the given result.
|
||||
* @param result the result
|
||||
* @return the result event factory
|
||||
*/
|
||||
public ResultEventFactory forResult(Object result) {
|
||||
if (result == null) {
|
||||
return successEventFactory;
|
||||
} else {
|
||||
return forType(result.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the appropriate result event factory for given result type. This implementation returns
|
||||
* {@link ResultObjectBasedEventFactory} if the type is
|
||||
* {@link ResultObjectBasedEventFactory#isMappedValueType(Class) mapped} by that result event factory, otherwise
|
||||
* {@link SuccessEventFactory} is returned.
|
||||
* @param resultType the result type
|
||||
* @return the result event factory
|
||||
*/
|
||||
protected ResultEventFactory forType(Class<?> resultType) {
|
||||
if (resultObjectBasedEventFactory.isMappedValueType(resultType)) {
|
||||
return resultObjectBasedEventFactory;
|
||||
} else {
|
||||
return successEventFactory;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.action;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Helper that selects the {@link ResultEventFactory} to use for a particular result object.
|
||||
*
|
||||
* @see EvaluateAction
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class ResultEventFactorySelector {
|
||||
|
||||
/**
|
||||
* The event factory instance for mapping a return value to a success event.
|
||||
*/
|
||||
private SuccessEventFactory successEventFactory = new SuccessEventFactory();
|
||||
|
||||
/**
|
||||
* The event factory instance for mapping a result object to an event, using the type of the result object as the
|
||||
* mapping criteria.
|
||||
*/
|
||||
private ResultObjectBasedEventFactory resultObjectBasedEventFactory = new ResultObjectBasedEventFactory();
|
||||
|
||||
/**
|
||||
* Select the appropriate result event factory for attempts to invoke the given method.
|
||||
* @param method the method
|
||||
* @return the result event factory
|
||||
*/
|
||||
public ResultEventFactory forMethod(Method method) {
|
||||
return forType(method.getReturnType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the appropriate result event factory for the given result.
|
||||
* @param result the result
|
||||
* @return the result event factory
|
||||
*/
|
||||
public ResultEventFactory forResult(Object result) {
|
||||
if (result == null) {
|
||||
return successEventFactory;
|
||||
} else {
|
||||
return forType(result.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the appropriate result event factory for given result type. This implementation returns
|
||||
* {@link ResultObjectBasedEventFactory} if the type is
|
||||
* {@link ResultObjectBasedEventFactory#isMappedValueType(Class) mapped} by that result event factory, otherwise
|
||||
* {@link SuccessEventFactory} is returned.
|
||||
* @param resultType the result type
|
||||
* @return the result event factory
|
||||
*/
|
||||
protected ResultEventFactory forType(Class<?> resultType) {
|
||||
if (resultObjectBasedEventFactory.isMappedValueType(resultType)) {
|
||||
return resultObjectBasedEventFactory;
|
||||
} else {
|
||||
return successEventFactory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,64 +1,64 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.action;
|
||||
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.ScopeType;
|
||||
|
||||
/**
|
||||
* An action that sets an attribute in a {@link ScopeType scope} when executed. Always returns the "success" event.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class SetAction extends AbstractAction {
|
||||
|
||||
/**
|
||||
* The expression for setting the scoped attribute value.
|
||||
*/
|
||||
private Expression nameExpression;
|
||||
|
||||
/**
|
||||
* The expression for resolving the scoped attribute value.
|
||||
*/
|
||||
private Expression valueExpression;
|
||||
|
||||
/**
|
||||
* Creates a new set attribute action.
|
||||
* @param nameExpression the name of the property to set (required)
|
||||
* @param valueExpression the expression to obtain the new property value (required) expected
|
||||
*/
|
||||
public SetAction(Expression nameExpression, Expression valueExpression) {
|
||||
Assert.notNull(nameExpression, "The name expression is required");
|
||||
Assert.notNull(valueExpression, "The value expression is required");
|
||||
this.nameExpression = nameExpression;
|
||||
this.valueExpression = valueExpression;
|
||||
}
|
||||
|
||||
protected Event doExecute(RequestContext context) throws Exception {
|
||||
Object value = valueExpression.getValue(context);
|
||||
nameExpression.setValue(context, value);
|
||||
return success();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("name", nameExpression).append("value", valueExpression).toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.action;
|
||||
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.ScopeType;
|
||||
|
||||
/**
|
||||
* An action that sets an attribute in a {@link ScopeType scope} when executed. Always returns the "success" event.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class SetAction extends AbstractAction {
|
||||
|
||||
/**
|
||||
* The expression for setting the scoped attribute value.
|
||||
*/
|
||||
private Expression nameExpression;
|
||||
|
||||
/**
|
||||
* The expression for resolving the scoped attribute value.
|
||||
*/
|
||||
private Expression valueExpression;
|
||||
|
||||
/**
|
||||
* Creates a new set attribute action.
|
||||
* @param nameExpression the name of the property to set (required)
|
||||
* @param valueExpression the expression to obtain the new property value (required) expected
|
||||
*/
|
||||
public SetAction(Expression nameExpression, Expression valueExpression) {
|
||||
Assert.notNull(nameExpression, "The name expression is required");
|
||||
Assert.notNull(valueExpression, "The value expression is required");
|
||||
this.nameExpression = nameExpression;
|
||||
this.valueExpression = valueExpression;
|
||||
}
|
||||
|
||||
protected Event doExecute(RequestContext context) throws Exception {
|
||||
Object value = valueExpression.getValue(context);
|
||||
nameExpression.setValue(context, value);
|
||||
return success();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("name", nameExpression).append("value", valueExpression).toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,246 +1,246 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.config;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.convert.service.DefaultConversionService;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.webflow.conversation.ConversationManager;
|
||||
import org.springframework.webflow.conversation.impl.SessionBindingConversationManager;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
|
||||
import org.springframework.webflow.engine.impl.FlowExecutionImplFactory;
|
||||
import org.springframework.webflow.execution.FlowExecutionFactory;
|
||||
import org.springframework.webflow.execution.factory.FlowExecutionListenerLoader;
|
||||
import org.springframework.webflow.execution.repository.FlowExecutionRepository;
|
||||
import org.springframework.webflow.execution.repository.impl.DefaultFlowExecutionRepository;
|
||||
import org.springframework.webflow.execution.repository.snapshot.FlowExecutionSnapshotFactory;
|
||||
import org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshotFactory;
|
||||
import org.springframework.webflow.execution.repository.snapshot.SimpleFlowExecutionSnapshotFactory;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
import org.springframework.webflow.executor.FlowExecutorImpl;
|
||||
|
||||
/**
|
||||
* This factory encapsulates the construction and assembly of a {@link FlowExecutor}, including the provision of its
|
||||
* {@link FlowExecutionRepository} strategy. As a <code>FactoryBean</code>, this class has been designed for use as a
|
||||
* Spring managed bean.
|
||||
* <p>
|
||||
* The definition locator property is required, all other properties are optional.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
class FlowExecutorFactoryBean implements FactoryBean<FlowExecutor>, BeanClassLoaderAware, InitializingBean {
|
||||
|
||||
private static final String ALWAYS_REDIRECT_ON_PAUSE = "alwaysRedirectOnPause";
|
||||
|
||||
private static final String REDIRECT_IN_SAME_STATE = "redirectInSameState";
|
||||
|
||||
private FlowDefinitionLocator flowDefinitionLocator;
|
||||
|
||||
private Integer maxFlowExecutions;
|
||||
|
||||
private Integer maxFlowExecutionSnapshots;
|
||||
|
||||
private Set<FlowElementAttribute> flowExecutionAttributes;
|
||||
|
||||
private FlowExecutionListenerLoader flowExecutionListenerLoader;
|
||||
|
||||
private ConversationManager conversationManager;
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
/**
|
||||
* Sets the flow definition locator that will locate flow definitions needed for execution. Typically also a
|
||||
* {@link FlowDefinitionRegistry}. Required.
|
||||
* @param flowDefinitionLocator the flow definition locator (registry)
|
||||
*/
|
||||
public void setFlowDefinitionLocator(FlowDefinitionLocator flowDefinitionLocator) {
|
||||
this.flowDefinitionLocator = flowDefinitionLocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of allowed flow executions allowed per user.
|
||||
*/
|
||||
public void setMaxFlowExecutions(int maxFlowExecutions) {
|
||||
this.maxFlowExecutions = maxFlowExecutions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of history snapshots allowed per flow execution.
|
||||
*/
|
||||
public void setMaxFlowExecutionSnapshots(int maxFlowExecutionSnapshots) {
|
||||
this.maxFlowExecutionSnapshots = maxFlowExecutionSnapshots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the system attributes that apply to flow executions launched by the executor created by this factory.
|
||||
* Execution attributes may affect flow execution behavior.
|
||||
* @param flowExecutionAttributes the flow execution system attributes
|
||||
*/
|
||||
public void setFlowExecutionAttributes(Set<FlowElementAttribute> flowExecutionAttributes) {
|
||||
this.flowExecutionAttributes = flowExecutionAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strategy for loading the listeners that will observe executions of a flow definition. Allows full
|
||||
* control over what listeners should apply to executions of a flow definition launched by the executor created by
|
||||
* this factory.
|
||||
*/
|
||||
public void setFlowExecutionListenerLoader(FlowExecutionListenerLoader flowExecutionListenerLoader) {
|
||||
this.flowExecutionListenerLoader = flowExecutionListenerLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the service type that manages conversations and effectively controls how state is stored physically when a
|
||||
* flow execution is paused.
|
||||
*/
|
||||
public void setConversationManager(ConversationManager conversationManager) {
|
||||
this.conversationManager = conversationManager;
|
||||
}
|
||||
|
||||
// implement BeanClassLoaderAware
|
||||
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
// implementing InitializingBean
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(flowDefinitionLocator, "The flow definition locator property is required");
|
||||
if (conversionService == null) {
|
||||
conversionService = new DefaultConversionService();
|
||||
}
|
||||
MutableAttributeMap<Object> executionAttributes = createFlowExecutionAttributes();
|
||||
FlowExecutionImplFactory executionFactory = createFlowExecutionFactory(executionAttributes);
|
||||
DefaultFlowExecutionRepository executionRepository = createFlowExecutionRepository(executionFactory);
|
||||
executionFactory.setExecutionKeyFactory(executionRepository);
|
||||
flowExecutor = new FlowExecutorImpl(flowDefinitionLocator, executionFactory, executionRepository);
|
||||
}
|
||||
|
||||
// implementing FactoryBean
|
||||
|
||||
public Class<?> getObjectType() {
|
||||
return FlowExecutor.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public FlowExecutor getObject() throws Exception {
|
||||
return flowExecutor;
|
||||
}
|
||||
|
||||
private MutableAttributeMap<Object> createFlowExecutionAttributes() {
|
||||
LocalAttributeMap<Object> executionAttributes = new LocalAttributeMap<>();
|
||||
if (flowExecutionAttributes != null) {
|
||||
for (FlowElementAttribute attribute : flowExecutionAttributes) {
|
||||
executionAttributes.put(attribute.getName(), getConvertedValue(attribute));
|
||||
}
|
||||
}
|
||||
putDefaultFlowExecutionAttributes(executionAttributes);
|
||||
return executionAttributes;
|
||||
}
|
||||
|
||||
private void putDefaultFlowExecutionAttributes(LocalAttributeMap<Object> executionAttributes) {
|
||||
if (!executionAttributes.contains(ALWAYS_REDIRECT_ON_PAUSE)) {
|
||||
executionAttributes.put(ALWAYS_REDIRECT_ON_PAUSE, true);
|
||||
}
|
||||
if (!executionAttributes.contains(REDIRECT_IN_SAME_STATE)) {
|
||||
executionAttributes.put(REDIRECT_IN_SAME_STATE, true);
|
||||
}
|
||||
}
|
||||
|
||||
private DefaultFlowExecutionRepository createFlowExecutionRepository(FlowExecutionFactory executionFactory) {
|
||||
ConversationManager conversationManager = createConversationManager();
|
||||
FlowExecutionSnapshotFactory snapshotFactory = createFlowExecutionSnapshotFactory(executionFactory);
|
||||
DefaultFlowExecutionRepository rep = new DefaultFlowExecutionRepository(conversationManager, snapshotFactory);
|
||||
if (maxFlowExecutionSnapshots != null) {
|
||||
rep.setMaxSnapshots(maxFlowExecutionSnapshots);
|
||||
}
|
||||
return rep;
|
||||
}
|
||||
|
||||
private ConversationManager createConversationManager() {
|
||||
if (conversationManager == null) {
|
||||
conversationManager = new SessionBindingConversationManager();
|
||||
if (maxFlowExecutions != null) {
|
||||
((SessionBindingConversationManager) conversationManager).setMaxConversations(maxFlowExecutions);
|
||||
}
|
||||
}
|
||||
return this.conversationManager;
|
||||
}
|
||||
|
||||
private FlowExecutionSnapshotFactory createFlowExecutionSnapshotFactory(FlowExecutionFactory executionFactory) {
|
||||
if (maxFlowExecutionSnapshots != null && maxFlowExecutionSnapshots == 0) {
|
||||
maxFlowExecutionSnapshots = 1;
|
||||
return new SimpleFlowExecutionSnapshotFactory(executionFactory, flowDefinitionLocator);
|
||||
} else {
|
||||
return new SerializedFlowExecutionSnapshotFactory(executionFactory, flowDefinitionLocator);
|
||||
}
|
||||
}
|
||||
|
||||
private FlowExecutionImplFactory createFlowExecutionFactory(AttributeMap<Object> executionAttributes) {
|
||||
FlowExecutionImplFactory executionFactory = new FlowExecutionImplFactory();
|
||||
executionFactory.setExecutionAttributes(executionAttributes);
|
||||
if (flowExecutionListenerLoader != null) {
|
||||
executionFactory.setExecutionListenerLoader(flowExecutionListenerLoader);
|
||||
}
|
||||
return executionFactory;
|
||||
}
|
||||
|
||||
// utility methods
|
||||
|
||||
private Object getConvertedValue(FlowElementAttribute attribute) {
|
||||
if (attribute.needsTypeConversion()) {
|
||||
Class<?> targetType = fromStringToClass(attribute.getType());
|
||||
ConversionExecutor converter = conversionService.getConversionExecutor(String.class, targetType);
|
||||
return converter.execute(attribute.getValue());
|
||||
} else {
|
||||
return attribute.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> fromStringToClass(String name) {
|
||||
Class<?> clazz = conversionService.getClassForAlias(name);
|
||||
if (clazz != null) {
|
||||
return clazz;
|
||||
} else {
|
||||
try {
|
||||
return ClassUtils.forName(name, classLoader);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalArgumentException("Unable to load class '" + name + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.config;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.convert.service.DefaultConversionService;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.webflow.conversation.ConversationManager;
|
||||
import org.springframework.webflow.conversation.impl.SessionBindingConversationManager;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
|
||||
import org.springframework.webflow.engine.impl.FlowExecutionImplFactory;
|
||||
import org.springframework.webflow.execution.FlowExecutionFactory;
|
||||
import org.springframework.webflow.execution.factory.FlowExecutionListenerLoader;
|
||||
import org.springframework.webflow.execution.repository.FlowExecutionRepository;
|
||||
import org.springframework.webflow.execution.repository.impl.DefaultFlowExecutionRepository;
|
||||
import org.springframework.webflow.execution.repository.snapshot.FlowExecutionSnapshotFactory;
|
||||
import org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshotFactory;
|
||||
import org.springframework.webflow.execution.repository.snapshot.SimpleFlowExecutionSnapshotFactory;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
import org.springframework.webflow.executor.FlowExecutorImpl;
|
||||
|
||||
/**
|
||||
* This factory encapsulates the construction and assembly of a {@link FlowExecutor}, including the provision of its
|
||||
* {@link FlowExecutionRepository} strategy. As a <code>FactoryBean</code>, this class has been designed for use as a
|
||||
* Spring managed bean.
|
||||
* <p>
|
||||
* The definition locator property is required, all other properties are optional.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
class FlowExecutorFactoryBean implements FactoryBean<FlowExecutor>, BeanClassLoaderAware, InitializingBean {
|
||||
|
||||
private static final String ALWAYS_REDIRECT_ON_PAUSE = "alwaysRedirectOnPause";
|
||||
|
||||
private static final String REDIRECT_IN_SAME_STATE = "redirectInSameState";
|
||||
|
||||
private FlowDefinitionLocator flowDefinitionLocator;
|
||||
|
||||
private Integer maxFlowExecutions;
|
||||
|
||||
private Integer maxFlowExecutionSnapshots;
|
||||
|
||||
private Set<FlowElementAttribute> flowExecutionAttributes;
|
||||
|
||||
private FlowExecutionListenerLoader flowExecutionListenerLoader;
|
||||
|
||||
private ConversationManager conversationManager;
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
/**
|
||||
* Sets the flow definition locator that will locate flow definitions needed for execution. Typically also a
|
||||
* {@link FlowDefinitionRegistry}. Required.
|
||||
* @param flowDefinitionLocator the flow definition locator (registry)
|
||||
*/
|
||||
public void setFlowDefinitionLocator(FlowDefinitionLocator flowDefinitionLocator) {
|
||||
this.flowDefinitionLocator = flowDefinitionLocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of allowed flow executions allowed per user.
|
||||
*/
|
||||
public void setMaxFlowExecutions(int maxFlowExecutions) {
|
||||
this.maxFlowExecutions = maxFlowExecutions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of history snapshots allowed per flow execution.
|
||||
*/
|
||||
public void setMaxFlowExecutionSnapshots(int maxFlowExecutionSnapshots) {
|
||||
this.maxFlowExecutionSnapshots = maxFlowExecutionSnapshots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the system attributes that apply to flow executions launched by the executor created by this factory.
|
||||
* Execution attributes may affect flow execution behavior.
|
||||
* @param flowExecutionAttributes the flow execution system attributes
|
||||
*/
|
||||
public void setFlowExecutionAttributes(Set<FlowElementAttribute> flowExecutionAttributes) {
|
||||
this.flowExecutionAttributes = flowExecutionAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strategy for loading the listeners that will observe executions of a flow definition. Allows full
|
||||
* control over what listeners should apply to executions of a flow definition launched by the executor created by
|
||||
* this factory.
|
||||
*/
|
||||
public void setFlowExecutionListenerLoader(FlowExecutionListenerLoader flowExecutionListenerLoader) {
|
||||
this.flowExecutionListenerLoader = flowExecutionListenerLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the service type that manages conversations and effectively controls how state is stored physically when a
|
||||
* flow execution is paused.
|
||||
*/
|
||||
public void setConversationManager(ConversationManager conversationManager) {
|
||||
this.conversationManager = conversationManager;
|
||||
}
|
||||
|
||||
// implement BeanClassLoaderAware
|
||||
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
// implementing InitializingBean
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(flowDefinitionLocator, "The flow definition locator property is required");
|
||||
if (conversionService == null) {
|
||||
conversionService = new DefaultConversionService();
|
||||
}
|
||||
MutableAttributeMap<Object> executionAttributes = createFlowExecutionAttributes();
|
||||
FlowExecutionImplFactory executionFactory = createFlowExecutionFactory(executionAttributes);
|
||||
DefaultFlowExecutionRepository executionRepository = createFlowExecutionRepository(executionFactory);
|
||||
executionFactory.setExecutionKeyFactory(executionRepository);
|
||||
flowExecutor = new FlowExecutorImpl(flowDefinitionLocator, executionFactory, executionRepository);
|
||||
}
|
||||
|
||||
// implementing FactoryBean
|
||||
|
||||
public Class<?> getObjectType() {
|
||||
return FlowExecutor.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public FlowExecutor getObject() throws Exception {
|
||||
return flowExecutor;
|
||||
}
|
||||
|
||||
private MutableAttributeMap<Object> createFlowExecutionAttributes() {
|
||||
LocalAttributeMap<Object> executionAttributes = new LocalAttributeMap<>();
|
||||
if (flowExecutionAttributes != null) {
|
||||
for (FlowElementAttribute attribute : flowExecutionAttributes) {
|
||||
executionAttributes.put(attribute.getName(), getConvertedValue(attribute));
|
||||
}
|
||||
}
|
||||
putDefaultFlowExecutionAttributes(executionAttributes);
|
||||
return executionAttributes;
|
||||
}
|
||||
|
||||
private void putDefaultFlowExecutionAttributes(LocalAttributeMap<Object> executionAttributes) {
|
||||
if (!executionAttributes.contains(ALWAYS_REDIRECT_ON_PAUSE)) {
|
||||
executionAttributes.put(ALWAYS_REDIRECT_ON_PAUSE, true);
|
||||
}
|
||||
if (!executionAttributes.contains(REDIRECT_IN_SAME_STATE)) {
|
||||
executionAttributes.put(REDIRECT_IN_SAME_STATE, true);
|
||||
}
|
||||
}
|
||||
|
||||
private DefaultFlowExecutionRepository createFlowExecutionRepository(FlowExecutionFactory executionFactory) {
|
||||
ConversationManager conversationManager = createConversationManager();
|
||||
FlowExecutionSnapshotFactory snapshotFactory = createFlowExecutionSnapshotFactory(executionFactory);
|
||||
DefaultFlowExecutionRepository rep = new DefaultFlowExecutionRepository(conversationManager, snapshotFactory);
|
||||
if (maxFlowExecutionSnapshots != null) {
|
||||
rep.setMaxSnapshots(maxFlowExecutionSnapshots);
|
||||
}
|
||||
return rep;
|
||||
}
|
||||
|
||||
private ConversationManager createConversationManager() {
|
||||
if (conversationManager == null) {
|
||||
conversationManager = new SessionBindingConversationManager();
|
||||
if (maxFlowExecutions != null) {
|
||||
((SessionBindingConversationManager) conversationManager).setMaxConversations(maxFlowExecutions);
|
||||
}
|
||||
}
|
||||
return this.conversationManager;
|
||||
}
|
||||
|
||||
private FlowExecutionSnapshotFactory createFlowExecutionSnapshotFactory(FlowExecutionFactory executionFactory) {
|
||||
if (maxFlowExecutionSnapshots != null && maxFlowExecutionSnapshots == 0) {
|
||||
maxFlowExecutionSnapshots = 1;
|
||||
return new SimpleFlowExecutionSnapshotFactory(executionFactory, flowDefinitionLocator);
|
||||
} else {
|
||||
return new SerializedFlowExecutionSnapshotFactory(executionFactory, flowDefinitionLocator);
|
||||
}
|
||||
}
|
||||
|
||||
private FlowExecutionImplFactory createFlowExecutionFactory(AttributeMap<Object> executionAttributes) {
|
||||
FlowExecutionImplFactory executionFactory = new FlowExecutionImplFactory();
|
||||
executionFactory.setExecutionAttributes(executionAttributes);
|
||||
if (flowExecutionListenerLoader != null) {
|
||||
executionFactory.setExecutionListenerLoader(flowExecutionListenerLoader);
|
||||
}
|
||||
return executionFactory;
|
||||
}
|
||||
|
||||
// utility methods
|
||||
|
||||
private Object getConvertedValue(FlowElementAttribute attribute) {
|
||||
if (attribute.needsTypeConversion()) {
|
||||
Class<?> targetType = fromStringToClass(attribute.getType());
|
||||
ConversionExecutor converter = conversionService.getConversionExecutor(String.class, targetType);
|
||||
return converter.execute(attribute.getValue());
|
||||
} else {
|
||||
return attribute.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> fromStringToClass(String name) {
|
||||
Class<?> clazz = conversionService.getClassForAlias(name);
|
||||
if (clazz != null) {
|
||||
return clazz;
|
||||
} else {
|
||||
try {
|
||||
return ClassUtils.forName(name, classLoader);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalArgumentException("Unable to load class '" + name + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.config;
|
||||
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
|
||||
/**
|
||||
* <code>NamespaceHandler</code> for the <code>webflow-config</code> namespace.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Ben Hale
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class WebFlowConfigNamespaceHandler extends NamespaceHandlerSupport {
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("flow-executor", new FlowExecutorBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("flow-execution-listeners", new FlowExecutionListenerLoaderBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("flow-registry", new FlowRegistryBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("flow-builder-services", new FlowBuilderServicesBeanDefinitionParser());
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.config;
|
||||
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
|
||||
/**
|
||||
* <code>NamespaceHandler</code> for the <code>webflow-config</code> namespace.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Ben Hale
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class WebFlowConfigNamespaceHandler extends NamespaceHandlerSupport {
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("flow-executor", new FlowExecutorBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("flow-execution-listeners", new FlowExecutionListenerLoaderBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("flow-registry", new FlowRegistryBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("flow-builder-services", new FlowBuilderServicesBeanDefinitionParser());
|
||||
}
|
||||
}
|
||||
@@ -1,216 +1,216 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.context;
|
||||
|
||||
import java.io.Writer;
|
||||
import java.security.Principal;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.core.collection.ParameterMap;
|
||||
import org.springframework.webflow.core.collection.SharedAttributeMap;
|
||||
|
||||
/**
|
||||
* A facade that provides normalized access to an external system that has called into the Spring Web Flow system.
|
||||
* <p>
|
||||
* This context object provides a normalized interface for internal web flow artifacts to use to reason on and
|
||||
* manipulate the state of an external actor calling into SWF to execute flows. It represents the context about a
|
||||
* single, <i>external</i> client request to manipulate a flow execution.
|
||||
* <p>
|
||||
* The design of this interface was inspired by JSF's own ExternalContext abstraction and shares the same name for
|
||||
* consistency. If a particular external client type does not support all methods defined by this interface, they can
|
||||
* just be implemented as returning an empty map or <code>null</code>.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
* @author Jeremy Grelle
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public interface ExternalContext {
|
||||
|
||||
/**
|
||||
* Returns the logical path to the application hosting this external context.
|
||||
* @return the context path
|
||||
*/
|
||||
String getContextPath();
|
||||
|
||||
/**
|
||||
* Provides access to the parameters associated with the user request that led to SWF being called. This map is
|
||||
* expected to be immutable and cannot be changed.
|
||||
* @return the immutable request parameter map
|
||||
*/
|
||||
ParameterMap getRequestParameterMap();
|
||||
|
||||
/**
|
||||
* Provides access to the external request attribute map, providing a storage for data local to the current user
|
||||
* request and accessible to both internal and external SWF artifacts.
|
||||
* @return the mutable request attribute map
|
||||
*/
|
||||
MutableAttributeMap<Object> getRequestMap();
|
||||
|
||||
/**
|
||||
* Provides access to the external session map, providing a storage for data local to the current user session and
|
||||
* accessible to both internal and external SWF artifacts.
|
||||
* @return the mutable session attribute map
|
||||
*/
|
||||
SharedAttributeMap<Object> getSessionMap();
|
||||
|
||||
/**
|
||||
* Provides access to the <i>global</i> external session map, providing a storage for data globally accross the user
|
||||
* session and accessible to both internal and external SWF artifacts.
|
||||
* <p>
|
||||
* Note: most external context implementations do not distinguish between the concept of a "local" user session
|
||||
* scope and a "global" session scope. Otherwise this method returns the same map as calling {@link #getSessionMap()}.
|
||||
* @return the mutable global session attribute map
|
||||
*/
|
||||
SharedAttributeMap<Object> getGlobalSessionMap();
|
||||
|
||||
/**
|
||||
* Provides access to the external application map, providing a storage for data local to the current user
|
||||
* application and accessible to both internal and external SWF artifacts.
|
||||
* @return the mutable application attribute map
|
||||
*/
|
||||
SharedAttributeMap<Object> getApplicationMap();
|
||||
|
||||
/**
|
||||
* Returns true if the current request is an asynchronous Ajax request.
|
||||
* @return true if the current request is an Ajax request
|
||||
*/
|
||||
boolean isAjaxRequest();
|
||||
|
||||
/**
|
||||
* Get a flow execution URL for the execution with the provided key. Typically used by response writers that write
|
||||
* out references to the flow execution to support postback on a subsequent request. The URL returned is encoded.
|
||||
* @param flowId the flow definition id
|
||||
* @param flowExecutionKey the flow execution key
|
||||
* @return the flow execution URL
|
||||
*/
|
||||
String getFlowExecutionUrl(String flowId, String flowExecutionKey);
|
||||
|
||||
/**
|
||||
* Provides access to the user's principal security object.
|
||||
* @return the user principal
|
||||
*/
|
||||
Principal getCurrentUser();
|
||||
|
||||
/**
|
||||
* Returns the client locale.
|
||||
* @return the locale
|
||||
*/
|
||||
Locale getLocale();
|
||||
|
||||
/**
|
||||
* Provides access to the context object for the current environment.
|
||||
* @return the environment specific context object
|
||||
*/
|
||||
Object getNativeContext();
|
||||
|
||||
/**
|
||||
* Provides access to the request object for the current environment.
|
||||
* @return the environment specific request object.
|
||||
*/
|
||||
Object getNativeRequest();
|
||||
|
||||
/**
|
||||
* Provides access to the response object for the current environment.
|
||||
* @return the environment specific response object.
|
||||
*/
|
||||
Object getNativeResponse();
|
||||
|
||||
/**
|
||||
* Get a writer for writing out a response.
|
||||
* @return the writer
|
||||
* @throws IllegalStateException if the response has completed or is not allowed
|
||||
*/
|
||||
Writer getResponseWriter() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Is a <i>render</i> response allowed to be written for this request? Always return false after a response has been
|
||||
* completed. May return false before that to indicate a response is not allowed to be completed.
|
||||
* @return true if yes, false otherwise
|
||||
*/
|
||||
boolean isResponseAllowed();
|
||||
|
||||
/**
|
||||
* Request that a flow execution redirect be performed by the calling environment. Typically called from within a
|
||||
* flow execution to request a refresh operation, usually to support "refresh after event processing" behavior.
|
||||
* Calling this method also sets responseComplete status to true.
|
||||
* @see #isResponseComplete()
|
||||
* @throws IllegalStateException if the response has completed
|
||||
*/
|
||||
void requestFlowExecutionRedirect() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Request that a flow definition redirect be performed by the calling environment. Typically called from within a
|
||||
* flow execution end state to request starting a new, independent execution of a flow in a chain-like manner.
|
||||
* Calling this method also sets responseComplete status to true.
|
||||
* @see #isResponseComplete()
|
||||
* @param flowId the id of the flow definition to redirect to
|
||||
* @param input input to pass the flow; this input is generally encoded the url to launch the flow
|
||||
* @throws IllegalStateException if the response has completed
|
||||
*/
|
||||
void requestFlowDefinitionRedirect(String flowId, MutableAttributeMap<?> input) throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Request a redirect to an arbitrary resource location. May not be supported in some environments. Calling this
|
||||
* method also sets responseComplete status to true.
|
||||
* @see #isResponseComplete()
|
||||
* @param location the location of the resource to redirect to
|
||||
* @throws IllegalStateException if the response has completed
|
||||
*/
|
||||
void requestExternalRedirect(String location) throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Request that the current redirect requested be sent to the client in a manner that causes the client to issue the
|
||||
* redirect from a popup dialog. Only call this method after a redirect has been requested.
|
||||
* @see #requestFlowExecutionRedirect()
|
||||
* @see #requestFlowDefinitionRedirect(String, MutableAttributeMap)
|
||||
* @see #requestExternalRedirect(String)
|
||||
* @throws IllegalStateException if a redirect has not been requested
|
||||
*/
|
||||
void requestRedirectInPopup() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Called by flow artifacts such as View states and end states to indicate they handled the response, typically by
|
||||
* writing out content to the response stream. Setting this flag allows this external context to know the response
|
||||
* was handled, and that it not need to take additional response handling action itself.
|
||||
*/
|
||||
void recordResponseComplete();
|
||||
|
||||
/**
|
||||
* Has the response been completed? Response complete status can be achieved by:
|
||||
* <ul>
|
||||
* <li>Writing out the response and calling {@link #recordResponseComplete()}, or
|
||||
* <li>Calling one of the redirect request methods
|
||||
* </ul>
|
||||
* @see #getResponseWriter()
|
||||
* @see #recordResponseComplete()
|
||||
* @see #requestFlowExecutionRedirect()
|
||||
* @see #requestFlowDefinitionRedirect(String, MutableAttributeMap)
|
||||
* @see #requestExternalRedirect(String)
|
||||
* @return true if yes, false otherwise
|
||||
*/
|
||||
boolean isResponseComplete();
|
||||
|
||||
/**
|
||||
* Returns true if the response has been completed with flow execution redirect request.
|
||||
* @return true if a redirect response has been completed
|
||||
* @see #isResponseComplete()
|
||||
* @see #requestFlowExecutionRedirect()
|
||||
*/
|
||||
boolean isResponseCompleteFlowExecutionRedirect();
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.context;
|
||||
|
||||
import java.io.Writer;
|
||||
import java.security.Principal;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.core.collection.ParameterMap;
|
||||
import org.springframework.webflow.core.collection.SharedAttributeMap;
|
||||
|
||||
/**
|
||||
* A facade that provides normalized access to an external system that has called into the Spring Web Flow system.
|
||||
* <p>
|
||||
* This context object provides a normalized interface for internal web flow artifacts to use to reason on and
|
||||
* manipulate the state of an external actor calling into SWF to execute flows. It represents the context about a
|
||||
* single, <i>external</i> client request to manipulate a flow execution.
|
||||
* <p>
|
||||
* The design of this interface was inspired by JSF's own ExternalContext abstraction and shares the same name for
|
||||
* consistency. If a particular external client type does not support all methods defined by this interface, they can
|
||||
* just be implemented as returning an empty map or <code>null</code>.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
* @author Jeremy Grelle
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public interface ExternalContext {
|
||||
|
||||
/**
|
||||
* Returns the logical path to the application hosting this external context.
|
||||
* @return the context path
|
||||
*/
|
||||
String getContextPath();
|
||||
|
||||
/**
|
||||
* Provides access to the parameters associated with the user request that led to SWF being called. This map is
|
||||
* expected to be immutable and cannot be changed.
|
||||
* @return the immutable request parameter map
|
||||
*/
|
||||
ParameterMap getRequestParameterMap();
|
||||
|
||||
/**
|
||||
* Provides access to the external request attribute map, providing a storage for data local to the current user
|
||||
* request and accessible to both internal and external SWF artifacts.
|
||||
* @return the mutable request attribute map
|
||||
*/
|
||||
MutableAttributeMap<Object> getRequestMap();
|
||||
|
||||
/**
|
||||
* Provides access to the external session map, providing a storage for data local to the current user session and
|
||||
* accessible to both internal and external SWF artifacts.
|
||||
* @return the mutable session attribute map
|
||||
*/
|
||||
SharedAttributeMap<Object> getSessionMap();
|
||||
|
||||
/**
|
||||
* Provides access to the <i>global</i> external session map, providing a storage for data globally accross the user
|
||||
* session and accessible to both internal and external SWF artifacts.
|
||||
* <p>
|
||||
* Note: most external context implementations do not distinguish between the concept of a "local" user session
|
||||
* scope and a "global" session scope. Otherwise this method returns the same map as calling {@link #getSessionMap()}.
|
||||
* @return the mutable global session attribute map
|
||||
*/
|
||||
SharedAttributeMap<Object> getGlobalSessionMap();
|
||||
|
||||
/**
|
||||
* Provides access to the external application map, providing a storage for data local to the current user
|
||||
* application and accessible to both internal and external SWF artifacts.
|
||||
* @return the mutable application attribute map
|
||||
*/
|
||||
SharedAttributeMap<Object> getApplicationMap();
|
||||
|
||||
/**
|
||||
* Returns true if the current request is an asynchronous Ajax request.
|
||||
* @return true if the current request is an Ajax request
|
||||
*/
|
||||
boolean isAjaxRequest();
|
||||
|
||||
/**
|
||||
* Get a flow execution URL for the execution with the provided key. Typically used by response writers that write
|
||||
* out references to the flow execution to support postback on a subsequent request. The URL returned is encoded.
|
||||
* @param flowId the flow definition id
|
||||
* @param flowExecutionKey the flow execution key
|
||||
* @return the flow execution URL
|
||||
*/
|
||||
String getFlowExecutionUrl(String flowId, String flowExecutionKey);
|
||||
|
||||
/**
|
||||
* Provides access to the user's principal security object.
|
||||
* @return the user principal
|
||||
*/
|
||||
Principal getCurrentUser();
|
||||
|
||||
/**
|
||||
* Returns the client locale.
|
||||
* @return the locale
|
||||
*/
|
||||
Locale getLocale();
|
||||
|
||||
/**
|
||||
* Provides access to the context object for the current environment.
|
||||
* @return the environment specific context object
|
||||
*/
|
||||
Object getNativeContext();
|
||||
|
||||
/**
|
||||
* Provides access to the request object for the current environment.
|
||||
* @return the environment specific request object.
|
||||
*/
|
||||
Object getNativeRequest();
|
||||
|
||||
/**
|
||||
* Provides access to the response object for the current environment.
|
||||
* @return the environment specific response object.
|
||||
*/
|
||||
Object getNativeResponse();
|
||||
|
||||
/**
|
||||
* Get a writer for writing out a response.
|
||||
* @return the writer
|
||||
* @throws IllegalStateException if the response has completed or is not allowed
|
||||
*/
|
||||
Writer getResponseWriter() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Is a <i>render</i> response allowed to be written for this request? Always return false after a response has been
|
||||
* completed. May return false before that to indicate a response is not allowed to be completed.
|
||||
* @return true if yes, false otherwise
|
||||
*/
|
||||
boolean isResponseAllowed();
|
||||
|
||||
/**
|
||||
* Request that a flow execution redirect be performed by the calling environment. Typically called from within a
|
||||
* flow execution to request a refresh operation, usually to support "refresh after event processing" behavior.
|
||||
* Calling this method also sets responseComplete status to true.
|
||||
* @see #isResponseComplete()
|
||||
* @throws IllegalStateException if the response has completed
|
||||
*/
|
||||
void requestFlowExecutionRedirect() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Request that a flow definition redirect be performed by the calling environment. Typically called from within a
|
||||
* flow execution end state to request starting a new, independent execution of a flow in a chain-like manner.
|
||||
* Calling this method also sets responseComplete status to true.
|
||||
* @see #isResponseComplete()
|
||||
* @param flowId the id of the flow definition to redirect to
|
||||
* @param input input to pass the flow; this input is generally encoded the url to launch the flow
|
||||
* @throws IllegalStateException if the response has completed
|
||||
*/
|
||||
void requestFlowDefinitionRedirect(String flowId, MutableAttributeMap<?> input) throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Request a redirect to an arbitrary resource location. May not be supported in some environments. Calling this
|
||||
* method also sets responseComplete status to true.
|
||||
* @see #isResponseComplete()
|
||||
* @param location the location of the resource to redirect to
|
||||
* @throws IllegalStateException if the response has completed
|
||||
*/
|
||||
void requestExternalRedirect(String location) throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Request that the current redirect requested be sent to the client in a manner that causes the client to issue the
|
||||
* redirect from a popup dialog. Only call this method after a redirect has been requested.
|
||||
* @see #requestFlowExecutionRedirect()
|
||||
* @see #requestFlowDefinitionRedirect(String, MutableAttributeMap)
|
||||
* @see #requestExternalRedirect(String)
|
||||
* @throws IllegalStateException if a redirect has not been requested
|
||||
*/
|
||||
void requestRedirectInPopup() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Called by flow artifacts such as View states and end states to indicate they handled the response, typically by
|
||||
* writing out content to the response stream. Setting this flag allows this external context to know the response
|
||||
* was handled, and that it not need to take additional response handling action itself.
|
||||
*/
|
||||
void recordResponseComplete();
|
||||
|
||||
/**
|
||||
* Has the response been completed? Response complete status can be achieved by:
|
||||
* <ul>
|
||||
* <li>Writing out the response and calling {@link #recordResponseComplete()}, or
|
||||
* <li>Calling one of the redirect request methods
|
||||
* </ul>
|
||||
* @see #getResponseWriter()
|
||||
* @see #recordResponseComplete()
|
||||
* @see #requestFlowExecutionRedirect()
|
||||
* @see #requestFlowDefinitionRedirect(String, MutableAttributeMap)
|
||||
* @see #requestExternalRedirect(String)
|
||||
* @return true if yes, false otherwise
|
||||
*/
|
||||
boolean isResponseComplete();
|
||||
|
||||
/**
|
||||
* Returns true if the response has been completed with flow execution redirect request.
|
||||
* @return true if a redirect response has been completed
|
||||
* @see #isResponseComplete()
|
||||
* @see #requestFlowExecutionRedirect()
|
||||
*/
|
||||
boolean isResponseCompleteFlowExecutionRedirect();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.context;
|
||||
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
|
||||
/**
|
||||
* Simple holder class that associates an {@link ExternalContext} instance with the current thread. The ExternalContext
|
||||
* will not be inherited by any child threads spawned by the current thread.
|
||||
* <p>
|
||||
* Used as a central holder for the current ExternalContext in Spring Web Flow, wherever necessary. Often used by
|
||||
* artifacts needing access to the current application session.
|
||||
*
|
||||
* @see ExternalContext
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public final class ExternalContextHolder {
|
||||
|
||||
private static final ThreadLocal<ExternalContext> externalContextHolder = new NamedThreadLocal<>(
|
||||
"Flow ExternalContext");
|
||||
|
||||
/**
|
||||
* Associate the given ExternalContext with the current thread.
|
||||
* @param externalContext the current ExternalContext, or <code>null</code> to reset the thread-bound context
|
||||
*/
|
||||
public static void setExternalContext(ExternalContext externalContext) {
|
||||
externalContextHolder.set(externalContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ExternalContext associated with the current thread, if any.
|
||||
* @return the current ExternalContext
|
||||
*/
|
||||
public static ExternalContext getExternalContext() {
|
||||
return externalContextHolder.get();
|
||||
}
|
||||
|
||||
// not instantiable
|
||||
private ExternalContextHolder() {
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.context;
|
||||
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
|
||||
/**
|
||||
* Simple holder class that associates an {@link ExternalContext} instance with the current thread. The ExternalContext
|
||||
* will not be inherited by any child threads spawned by the current thread.
|
||||
* <p>
|
||||
* Used as a central holder for the current ExternalContext in Spring Web Flow, wherever necessary. Often used by
|
||||
* artifacts needing access to the current application session.
|
||||
*
|
||||
* @see ExternalContext
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public final class ExternalContextHolder {
|
||||
|
||||
private static final ThreadLocal<ExternalContext> externalContextHolder = new NamedThreadLocal<>(
|
||||
"Flow ExternalContext");
|
||||
|
||||
/**
|
||||
* Associate the given ExternalContext with the current thread.
|
||||
* @param externalContext the current ExternalContext, or <code>null</code> to reset the thread-bound context
|
||||
*/
|
||||
public static void setExternalContext(ExternalContext externalContext) {
|
||||
externalContextHolder.set(externalContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ExternalContext associated with the current thread, if any.
|
||||
* @return the current ExternalContext
|
||||
*/
|
||||
public static ExternalContext getExternalContext() {
|
||||
return externalContextHolder.get();
|
||||
}
|
||||
|
||||
// not instantiable
|
||||
private ExternalContextHolder() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,77 +1,77 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.context.web;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpSessionBindingEvent;
|
||||
import javax.servlet.http.HttpSessionBindingListener;
|
||||
|
||||
import org.springframework.webflow.core.collection.AttributeMapBindingEvent;
|
||||
import org.springframework.webflow.core.collection.AttributeMapBindingListener;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
|
||||
/**
|
||||
* Helper class that adapts a generic {@link AttributeMapBindingListener} to a HTTP specific
|
||||
* {@link HttpSessionBindingListener}. Calls will be forwarded to the wrapped listener.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class HttpSessionMapBindingListener implements HttpSessionBindingListener {
|
||||
|
||||
private AttributeMapBindingListener listener;
|
||||
|
||||
private Map<String, Object> sessionMap;
|
||||
|
||||
/**
|
||||
* Create a new wrapper for given listener.
|
||||
* @param listener the listener to wrap
|
||||
* @param sessionMap the session map containing the listener
|
||||
*/
|
||||
public HttpSessionMapBindingListener(AttributeMapBindingListener listener, Map<String, Object> sessionMap) {
|
||||
this.listener = listener;
|
||||
this.sessionMap = sessionMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the wrapped listener.
|
||||
*/
|
||||
public AttributeMapBindingListener getListener() {
|
||||
return listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the session map containing the listener.
|
||||
*/
|
||||
public Map<String, Object> getSessionMap() {
|
||||
return sessionMap;
|
||||
}
|
||||
|
||||
public void valueBound(HttpSessionBindingEvent event) {
|
||||
listener.valueBound(getContextBindingEvent(event));
|
||||
}
|
||||
|
||||
public void valueUnbound(HttpSessionBindingEvent event) {
|
||||
listener.valueUnbound(getContextBindingEvent(event));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a attribute map binding event for given HTTP session binding event.
|
||||
*/
|
||||
private AttributeMapBindingEvent getContextBindingEvent(HttpSessionBindingEvent event) {
|
||||
return new AttributeMapBindingEvent(new LocalAttributeMap<>(sessionMap), event.getName(), listener);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.context.web;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpSessionBindingEvent;
|
||||
import javax.servlet.http.HttpSessionBindingListener;
|
||||
|
||||
import org.springframework.webflow.core.collection.AttributeMapBindingEvent;
|
||||
import org.springframework.webflow.core.collection.AttributeMapBindingListener;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
|
||||
/**
|
||||
* Helper class that adapts a generic {@link AttributeMapBindingListener} to a HTTP specific
|
||||
* {@link HttpSessionBindingListener}. Calls will be forwarded to the wrapped listener.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class HttpSessionMapBindingListener implements HttpSessionBindingListener {
|
||||
|
||||
private AttributeMapBindingListener listener;
|
||||
|
||||
private Map<String, Object> sessionMap;
|
||||
|
||||
/**
|
||||
* Create a new wrapper for given listener.
|
||||
* @param listener the listener to wrap
|
||||
* @param sessionMap the session map containing the listener
|
||||
*/
|
||||
public HttpSessionMapBindingListener(AttributeMapBindingListener listener, Map<String, Object> sessionMap) {
|
||||
this.listener = listener;
|
||||
this.sessionMap = sessionMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the wrapped listener.
|
||||
*/
|
||||
public AttributeMapBindingListener getListener() {
|
||||
return listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the session map containing the listener.
|
||||
*/
|
||||
public Map<String, Object> getSessionMap() {
|
||||
return sessionMap;
|
||||
}
|
||||
|
||||
public void valueBound(HttpSessionBindingEvent event) {
|
||||
listener.valueBound(getContextBindingEvent(event));
|
||||
}
|
||||
|
||||
public void valueUnbound(HttpSessionBindingEvent event) {
|
||||
listener.valueUnbound(getContextBindingEvent(event));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a attribute map binding event for given HTTP session binding event.
|
||||
*/
|
||||
private AttributeMapBindingEvent getContextBindingEvent(HttpSessionBindingEvent event) {
|
||||
return new AttributeMapBindingEvent(new LocalAttributeMap<>(sessionMap), event.getName(), listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,97 +1,97 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.conversation;
|
||||
|
||||
/**
|
||||
* A service interface for working with state associated with a single logical user interaction called a "conversation"
|
||||
* in the scope of a single request. Conversation objects are not thread safe and should not be shared among multiple
|
||||
* threads.
|
||||
* <p>
|
||||
* A conversation provides a "task" context that is begun and eventually ends. Between the beginning and the end
|
||||
* attributes can be placed in and read from a conversation's context.
|
||||
* <p>
|
||||
* A conversation needs to be {@link #lock() locked} to obtain exclusive access to it before it can be manipulated. Once
|
||||
* manipulation is finished, you need to {@link #unlock() unlock} the conversation. So code interacting with a
|
||||
* conversation always looks like this:
|
||||
*
|
||||
* <pre>
|
||||
* Conversation conv = ...;
|
||||
* conv.lock();
|
||||
* try {
|
||||
* // work with the Conversation object, calling methods like
|
||||
* // getAttribute(), putAttribute() and end()
|
||||
* }
|
||||
* finally {
|
||||
* conv.unlock();
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* Note that the attributes associated with a conversation are not "conversation scope" as defined for a flow execution.
|
||||
* They can be any attributes, possibly technical in nature, associated with the conversation.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface Conversation {
|
||||
|
||||
/**
|
||||
* Returns the unique id assigned to this conversation. This id remains the same throughout the life of the
|
||||
* conversation. This method can be safely called without owning the lock of this conversation.
|
||||
* @return the conversation id
|
||||
*/
|
||||
ConversationId getId();
|
||||
|
||||
/**
|
||||
* Lock this conversation. May block until the lock is available, if someone else has acquired the lock.
|
||||
* @throws ConversationLockException if the lock could not be acquired
|
||||
*/
|
||||
void lock() throws ConversationLockException;
|
||||
|
||||
/**
|
||||
* Returns the conversation attribute with the specified name. You need to acquire the lock on this conversation
|
||||
* before calling this method.
|
||||
* @param name the attribute name
|
||||
* @return the attribute value
|
||||
*/
|
||||
Object getAttribute(Object name);
|
||||
|
||||
/**
|
||||
* Puts a conversation attribute into this context. You need to acquire the lock on this conversation before calling
|
||||
* this method.
|
||||
* @param name the attribute name
|
||||
* @param value the attribute value
|
||||
*/
|
||||
void putAttribute(Object name, Object value);
|
||||
|
||||
/**
|
||||
* Removes a conversation attribute. You need to acquire the lock on this conversation before calling this method.
|
||||
* @param name the attribute name
|
||||
*/
|
||||
void removeAttribute(Object name);
|
||||
|
||||
/**
|
||||
* Ends this conversation. This method should only be called once to terminate the conversation and cleanup any
|
||||
* allocated resources. You need to aquire the lock on this conversation before calling this method.
|
||||
*/
|
||||
void end();
|
||||
|
||||
/**
|
||||
* Unlock this conversation, making it available to others for manipulation.
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.conversation;
|
||||
|
||||
/**
|
||||
* A service interface for working with state associated with a single logical user interaction called a "conversation"
|
||||
* in the scope of a single request. Conversation objects are not thread safe and should not be shared among multiple
|
||||
* threads.
|
||||
* <p>
|
||||
* A conversation provides a "task" context that is begun and eventually ends. Between the beginning and the end
|
||||
* attributes can be placed in and read from a conversation's context.
|
||||
* <p>
|
||||
* A conversation needs to be {@link #lock() locked} to obtain exclusive access to it before it can be manipulated. Once
|
||||
* manipulation is finished, you need to {@link #unlock() unlock} the conversation. So code interacting with a
|
||||
* conversation always looks like this:
|
||||
*
|
||||
* <pre>
|
||||
* Conversation conv = ...;
|
||||
* conv.lock();
|
||||
* try {
|
||||
* // work with the Conversation object, calling methods like
|
||||
* // getAttribute(), putAttribute() and end()
|
||||
* }
|
||||
* finally {
|
||||
* conv.unlock();
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* Note that the attributes associated with a conversation are not "conversation scope" as defined for a flow execution.
|
||||
* They can be any attributes, possibly technical in nature, associated with the conversation.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface Conversation {
|
||||
|
||||
/**
|
||||
* Returns the unique id assigned to this conversation. This id remains the same throughout the life of the
|
||||
* conversation. This method can be safely called without owning the lock of this conversation.
|
||||
* @return the conversation id
|
||||
*/
|
||||
ConversationId getId();
|
||||
|
||||
/**
|
||||
* Lock this conversation. May block until the lock is available, if someone else has acquired the lock.
|
||||
* @throws ConversationLockException if the lock could not be acquired
|
||||
*/
|
||||
void lock() throws ConversationLockException;
|
||||
|
||||
/**
|
||||
* Returns the conversation attribute with the specified name. You need to acquire the lock on this conversation
|
||||
* before calling this method.
|
||||
* @param name the attribute name
|
||||
* @return the attribute value
|
||||
*/
|
||||
Object getAttribute(Object name);
|
||||
|
||||
/**
|
||||
* Puts a conversation attribute into this context. You need to acquire the lock on this conversation before calling
|
||||
* this method.
|
||||
* @param name the attribute name
|
||||
* @param value the attribute value
|
||||
*/
|
||||
void putAttribute(Object name, Object value);
|
||||
|
||||
/**
|
||||
* Removes a conversation attribute. You need to acquire the lock on this conversation before calling this method.
|
||||
* @param name the attribute name
|
||||
*/
|
||||
void removeAttribute(Object name);
|
||||
|
||||
/**
|
||||
* Ends this conversation. This method should only be called once to terminate the conversation and cleanup any
|
||||
* allocated resources. You need to aquire the lock on this conversation before calling this method.
|
||||
*/
|
||||
void end();
|
||||
|
||||
/**
|
||||
* Unlock this conversation, making it available to others for manipulation.
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
}
|
||||
@@ -1,41 +1,41 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.conversation;
|
||||
|
||||
/**
|
||||
* The root of the conversation service exception hierarchy.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public abstract class ConversationException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Creates a conversation service exception.
|
||||
* @param message a descriptive message
|
||||
*/
|
||||
public ConversationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a conversation service exception.
|
||||
* @param message a descriptive message
|
||||
* @param cause the root cause of the problem
|
||||
*/
|
||||
public ConversationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.conversation;
|
||||
|
||||
/**
|
||||
* The root of the conversation service exception hierarchy.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public abstract class ConversationException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Creates a conversation service exception.
|
||||
* @param message a descriptive message
|
||||
*/
|
||||
public ConversationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a conversation service exception.
|
||||
* @param message a descriptive message
|
||||
* @param cause the root cause of the problem
|
||||
*/
|
||||
public ConversationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -1,47 +1,47 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.conversation;
|
||||
|
||||
/**
|
||||
* Thrown when no logical conversation exists with the specified <code>conversationId</code>. This might occur if the
|
||||
* conversation ended, expired, or was otherwise invalidated, but a client view still references it.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class NoSuchConversationException extends ConversationException {
|
||||
|
||||
/**
|
||||
* The unique conversation identifier that was invalid.
|
||||
*/
|
||||
private ConversationId conversationId;
|
||||
|
||||
/**
|
||||
* Create a new conversation lookup exception.
|
||||
* @param conversationId the conversation id
|
||||
*/
|
||||
public NoSuchConversationException(ConversationId conversationId) {
|
||||
super("No conversation could be found with id '" + conversationId
|
||||
+ "' -- perhaps this conversation has ended? ");
|
||||
this.conversationId = conversationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the conversation id that was not found.
|
||||
*/
|
||||
public ConversationId getConversationId() {
|
||||
return conversationId;
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.conversation;
|
||||
|
||||
/**
|
||||
* Thrown when no logical conversation exists with the specified <code>conversationId</code>. This might occur if the
|
||||
* conversation ended, expired, or was otherwise invalidated, but a client view still references it.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class NoSuchConversationException extends ConversationException {
|
||||
|
||||
/**
|
||||
* The unique conversation identifier that was invalid.
|
||||
*/
|
||||
private ConversationId conversationId;
|
||||
|
||||
/**
|
||||
* Create a new conversation lookup exception.
|
||||
* @param conversationId the conversation id
|
||||
*/
|
||||
public NoSuchConversationException(ConversationId conversationId) {
|
||||
super("No conversation could be found with id '" + conversationId
|
||||
+ "' -- perhaps this conversation has ended? ");
|
||||
this.conversationId = conversationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the conversation id that was not found.
|
||||
*/
|
||||
public ConversationId getConversationId() {
|
||||
return conversationId;
|
||||
}
|
||||
}
|
||||
@@ -1,135 +1,135 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.conversation.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.webflow.context.ExternalContextHolder;
|
||||
import org.springframework.webflow.conversation.Conversation;
|
||||
import org.springframework.webflow.conversation.ConversationId;
|
||||
import org.springframework.webflow.core.collection.SharedAttributeMap;
|
||||
|
||||
/**
|
||||
* Internal {@link Conversation} implementation used by the conversation container.
|
||||
* <p>
|
||||
* This is an internal helper class of the {@link SessionBindingConversationManager}.
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class ContainedConversation implements Conversation, Serializable {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SessionBindingConversationManager.class);
|
||||
|
||||
private ConversationContainer container;
|
||||
|
||||
private ConversationId id;
|
||||
|
||||
private ConversationLock lock;
|
||||
|
||||
private Map<Object, Object> attributes;
|
||||
|
||||
/**
|
||||
* Create a new contained conversation.
|
||||
* @param container the container containing the conversation
|
||||
* @param id the unique id assigned to the conversation
|
||||
* @param lock the conversation lock
|
||||
*/
|
||||
public ContainedConversation(ConversationContainer container, ConversationId id, ConversationLock lock) {
|
||||
this.container = container;
|
||||
this.id = id;
|
||||
this.lock = lock;
|
||||
this.attributes = new HashMap<>();
|
||||
}
|
||||
|
||||
protected void setContainer(ConversationContainer container) {
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
public ConversationId getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
protected void setId(ConversationId id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void lock() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Locking conversation " + this.id);
|
||||
}
|
||||
this.lock.lock();
|
||||
}
|
||||
|
||||
public Object getAttribute(Object name) {
|
||||
return this.attributes.get(name);
|
||||
}
|
||||
|
||||
public void putAttribute(Object name, Object value) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Putting conversation attribute '" + name + "' with value " + value);
|
||||
}
|
||||
this.attributes.put(name, value);
|
||||
}
|
||||
|
||||
public void removeAttribute(Object name) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Removing conversation attribute '" + name + "'");
|
||||
}
|
||||
this.attributes.remove(name);
|
||||
}
|
||||
|
||||
public void end() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Ending conversation " + this.id);
|
||||
}
|
||||
this.container.removeConversation(getId());
|
||||
}
|
||||
|
||||
public void unlock() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Unlocking conversation " + this.id);
|
||||
}
|
||||
this.lock.unlock();
|
||||
// re-bind the conversation container in the session
|
||||
// this is required to make session replication work correctly in
|
||||
// a clustered environment
|
||||
// we do this after releasing the lock since we're no longer
|
||||
// manipulating the contents of the conversation
|
||||
SharedAttributeMap<Object> sessionMap = ExternalContextHolder.getExternalContext().getSessionMap();
|
||||
synchronized (sessionMap.getMutex()) {
|
||||
sessionMap.put(this.container.getSessionKey(), this.container);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getId().toString();
|
||||
}
|
||||
|
||||
// id based equality
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof ContainedConversation && this.id.equals(((ContainedConversation) obj).id);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.id.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.conversation.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.webflow.context.ExternalContextHolder;
|
||||
import org.springframework.webflow.conversation.Conversation;
|
||||
import org.springframework.webflow.conversation.ConversationId;
|
||||
import org.springframework.webflow.core.collection.SharedAttributeMap;
|
||||
|
||||
/**
|
||||
* Internal {@link Conversation} implementation used by the conversation container.
|
||||
* <p>
|
||||
* This is an internal helper class of the {@link SessionBindingConversationManager}.
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class ContainedConversation implements Conversation, Serializable {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SessionBindingConversationManager.class);
|
||||
|
||||
private ConversationContainer container;
|
||||
|
||||
private ConversationId id;
|
||||
|
||||
private ConversationLock lock;
|
||||
|
||||
private Map<Object, Object> attributes;
|
||||
|
||||
/**
|
||||
* Create a new contained conversation.
|
||||
* @param container the container containing the conversation
|
||||
* @param id the unique id assigned to the conversation
|
||||
* @param lock the conversation lock
|
||||
*/
|
||||
public ContainedConversation(ConversationContainer container, ConversationId id, ConversationLock lock) {
|
||||
this.container = container;
|
||||
this.id = id;
|
||||
this.lock = lock;
|
||||
this.attributes = new HashMap<>();
|
||||
}
|
||||
|
||||
protected void setContainer(ConversationContainer container) {
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
public ConversationId getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
protected void setId(ConversationId id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void lock() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Locking conversation " + this.id);
|
||||
}
|
||||
this.lock.lock();
|
||||
}
|
||||
|
||||
public Object getAttribute(Object name) {
|
||||
return this.attributes.get(name);
|
||||
}
|
||||
|
||||
public void putAttribute(Object name, Object value) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Putting conversation attribute '" + name + "' with value " + value);
|
||||
}
|
||||
this.attributes.put(name, value);
|
||||
}
|
||||
|
||||
public void removeAttribute(Object name) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Removing conversation attribute '" + name + "'");
|
||||
}
|
||||
this.attributes.remove(name);
|
||||
}
|
||||
|
||||
public void end() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Ending conversation " + this.id);
|
||||
}
|
||||
this.container.removeConversation(getId());
|
||||
}
|
||||
|
||||
public void unlock() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Unlocking conversation " + this.id);
|
||||
}
|
||||
this.lock.unlock();
|
||||
// re-bind the conversation container in the session
|
||||
// this is required to make session replication work correctly in
|
||||
// a clustered environment
|
||||
// we do this after releasing the lock since we're no longer
|
||||
// manipulating the contents of the conversation
|
||||
SharedAttributeMap<Object> sessionMap = ExternalContextHolder.getExternalContext().getSessionMap();
|
||||
synchronized (sessionMap.getMutex()) {
|
||||
sessionMap.put(this.container.getSessionKey(), this.container);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getId().toString();
|
||||
}
|
||||
|
||||
// id based equality
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof ContainedConversation && this.id.equals(((ContainedConversation) obj).id);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.id.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.conversation.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.webflow.conversation.ConversationLockException;
|
||||
|
||||
/**
|
||||
* A normalized interface for conversation locks, used to obtain exclusive access to a conversation.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface ConversationLock extends Serializable {
|
||||
|
||||
/**
|
||||
* Acquire the conversation lock.
|
||||
* @throws ConversationLockException if an exception is thrown attempting to acquire this lock
|
||||
*/
|
||||
void lock() throws ConversationLockException;
|
||||
|
||||
/**
|
||||
* Release the conversation lock.
|
||||
*/
|
||||
void unlock();
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.conversation.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.webflow.conversation.ConversationLockException;
|
||||
|
||||
/**
|
||||
* A normalized interface for conversation locks, used to obtain exclusive access to a conversation.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface ConversationLock extends Serializable {
|
||||
|
||||
/**
|
||||
* Acquire the conversation lock.
|
||||
* @throws ConversationLockException if an exception is thrown attempting to acquire this lock
|
||||
*/
|
||||
void lock() throws ConversationLockException;
|
||||
|
||||
/**
|
||||
* Release the conversation lock.
|
||||
*/
|
||||
void unlock();
|
||||
}
|
||||
@@ -1,54 +1,54 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.conversation.impl;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.springframework.webflow.conversation.ConversationLockException;
|
||||
|
||||
/**
|
||||
* A conversation lock that relies on a {@link ReentrantLock} within Java 5's <code>util.concurrent.locks</code>
|
||||
* package.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class JdkConcurrentConversationLock implements ConversationLock {
|
||||
|
||||
private Lock lock = new ReentrantLock();
|
||||
|
||||
private int timeoutSeconds;
|
||||
|
||||
public JdkConcurrentConversationLock(int timeoutSeconds) {
|
||||
this.timeoutSeconds = timeoutSeconds;
|
||||
}
|
||||
|
||||
public void lock() throws ConversationLockException {
|
||||
try {
|
||||
boolean acquired = this.lock.tryLock(this.timeoutSeconds, TimeUnit.SECONDS);
|
||||
if (!acquired) {
|
||||
throw new LockTimeoutException(this.timeoutSeconds);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new LockInterruptedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void unlock() {
|
||||
this.lock.unlock();
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.conversation.impl;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.springframework.webflow.conversation.ConversationLockException;
|
||||
|
||||
/**
|
||||
* A conversation lock that relies on a {@link ReentrantLock} within Java 5's <code>util.concurrent.locks</code>
|
||||
* package.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class JdkConcurrentConversationLock implements ConversationLock {
|
||||
|
||||
private Lock lock = new ReentrantLock();
|
||||
|
||||
private int timeoutSeconds;
|
||||
|
||||
public JdkConcurrentConversationLock(int timeoutSeconds) {
|
||||
this.timeoutSeconds = timeoutSeconds;
|
||||
}
|
||||
|
||||
public void lock() throws ConversationLockException {
|
||||
try {
|
||||
boolean acquired = this.lock.tryLock(this.timeoutSeconds, TimeUnit.SECONDS);
|
||||
if (!acquired) {
|
||||
throw new LockTimeoutException(this.timeoutSeconds);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new LockInterruptedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void unlock() {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
@@ -1,51 +1,51 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.conversation.impl;
|
||||
|
||||
import java.io.ObjectStreamException;
|
||||
|
||||
/**
|
||||
* A singleton lock that doesn't do anything. For use when conversations don't require or choose not to implement
|
||||
* locking.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class NoOpConversationLock implements ConversationLock {
|
||||
|
||||
/**
|
||||
* The singleton instance.
|
||||
*/
|
||||
public static final NoOpConversationLock INSTANCE = new NoOpConversationLock();
|
||||
|
||||
/**
|
||||
* Private constructor to avoid instantiation.
|
||||
*/
|
||||
private NoOpConversationLock() {
|
||||
}
|
||||
|
||||
public void lock() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
public void unlock() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// resolve the singleton instance
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
return INSTANCE;
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.conversation.impl;
|
||||
|
||||
import java.io.ObjectStreamException;
|
||||
|
||||
/**
|
||||
* A singleton lock that doesn't do anything. For use when conversations don't require or choose not to implement
|
||||
* locking.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class NoOpConversationLock implements ConversationLock {
|
||||
|
||||
/**
|
||||
* The singleton instance.
|
||||
*/
|
||||
public static final NoOpConversationLock INSTANCE = new NoOpConversationLock();
|
||||
|
||||
/**
|
||||
* Private constructor to avoid instantiation.
|
||||
*/
|
||||
private NoOpConversationLock() {
|
||||
}
|
||||
|
||||
public void lock() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
public void unlock() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// resolve the singleton instance
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -1,149 +1,149 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.conversation.impl;
|
||||
|
||||
import org.springframework.webflow.context.ExternalContextHolder;
|
||||
import org.springframework.webflow.conversation.Conversation;
|
||||
import org.springframework.webflow.conversation.ConversationException;
|
||||
import org.springframework.webflow.conversation.ConversationId;
|
||||
import org.springframework.webflow.conversation.ConversationManager;
|
||||
import org.springframework.webflow.conversation.ConversationParameters;
|
||||
import org.springframework.webflow.core.collection.SharedAttributeMap;
|
||||
|
||||
/**
|
||||
* Simple implementation of a conversation manager that stores conversations in the session attribute map.
|
||||
* <p>
|
||||
* Using the {@link #setMaxConversations(int) maxConversations} property, you can limit the number of concurrently
|
||||
* active conversations allowed in a single session. If the maximum is exceeded, the conversation manager will
|
||||
* automatically end the oldest conversation. The default is 5, which should be fine for most situations. Set it to -1
|
||||
* for no limit. Setting maxConversations to 1 allows easy resource cleanup in situations where there should only be one
|
||||
* active conversation per session.
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class SessionBindingConversationManager implements ConversationManager {
|
||||
|
||||
/**
|
||||
* The name of the session attribute that will hold the conversation container used by this conversation manager.
|
||||
*
|
||||
* To support multiple independent conversation containers in the same web application, for example, for use with
|
||||
* multiple flow executors each configured with their own session-binding conversation manager, set this field's
|
||||
* value to something unique.
|
||||
* @see #setSessionKey(String)
|
||||
*/
|
||||
private String sessionKey = "webflowConversationContainer";
|
||||
|
||||
/**
|
||||
* The maximum number of active conversations allowed in a session. The default is 5. This is high enough for most
|
||||
* practical situations and low enough to avoid excessive resource usage or easy denial of service attacks.
|
||||
*/
|
||||
private int maxConversations = 5;
|
||||
|
||||
/**
|
||||
* The lock timeout in seconds.
|
||||
*/
|
||||
private int lockTimeoutSeconds = 30;
|
||||
|
||||
/**
|
||||
* Returns the key this conversation manager uses to store conversation data in the session.
|
||||
* @return the session key
|
||||
*/
|
||||
public String getSessionKey() {
|
||||
return sessionKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key this conversation manager uses to store conversation data in the session. If multiple session
|
||||
* binding conversation managers are used in the same web application to back independent flow executors, this value
|
||||
* should be unique among them.
|
||||
* @param sessionKey the session key
|
||||
*/
|
||||
public void setSessionKey(String sessionKey) {
|
||||
this.sessionKey = sessionKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of allowed concurrent conversations. The default is 5.
|
||||
*/
|
||||
public int getMaxConversations() {
|
||||
return maxConversations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of allowed concurrent conversations. Set to -1 for no limit. The default is 5.
|
||||
*/
|
||||
public void setMaxConversations(int maxConversations) {
|
||||
this.maxConversations = maxConversations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time period that can elapse before a timeout occurs on an attempt to acquire a conversation lock. The
|
||||
* default is 30 seconds.
|
||||
*/
|
||||
public int getLockTimeoutSeconds() {
|
||||
return lockTimeoutSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time period that can elapse before a timeout occurs on an attempt to acquire a conversation lock. The
|
||||
* default is 30 seconds.
|
||||
* @param lockTimeoutSeconds the timeout period in seconds
|
||||
*/
|
||||
public void setLockTimeoutSeconds(int lockTimeoutSeconds) {
|
||||
this.lockTimeoutSeconds = lockTimeoutSeconds;
|
||||
}
|
||||
|
||||
// implementing conversation manager
|
||||
|
||||
public Conversation beginConversation(ConversationParameters conversationParameters) throws ConversationException {
|
||||
ConversationLock lock = new JdkConcurrentConversationLock(lockTimeoutSeconds);
|
||||
return getConversationContainer().createConversation(conversationParameters, lock);
|
||||
}
|
||||
|
||||
public Conversation getConversation(ConversationId id) throws ConversationException {
|
||||
return getConversationContainer().getConversation(id);
|
||||
}
|
||||
|
||||
public ConversationId parseConversationId(String encodedId) throws ConversationException {
|
||||
try {
|
||||
return new SimpleConversationId(Integer.valueOf(encodedId));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new BadlyFormattedConversationIdException(encodedId, e);
|
||||
}
|
||||
}
|
||||
|
||||
// hooks for subclassing
|
||||
|
||||
protected ConversationContainer createConversationContainer() {
|
||||
return new ConversationContainer(maxConversations, sessionKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the conversation container from the session. Create a new empty container and add it to the session if no
|
||||
* existing container can be found.
|
||||
*/
|
||||
protected final ConversationContainer getConversationContainer() {
|
||||
SharedAttributeMap<Object> sessionMap = ExternalContextHolder.getExternalContext().getSessionMap();
|
||||
synchronized (sessionMap.getMutex()) {
|
||||
ConversationContainer container = (ConversationContainer) sessionMap.get(sessionKey);
|
||||
if (container == null) {
|
||||
container = createConversationContainer();
|
||||
sessionMap.put(sessionKey, container);
|
||||
}
|
||||
return container;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.conversation.impl;
|
||||
|
||||
import org.springframework.webflow.context.ExternalContextHolder;
|
||||
import org.springframework.webflow.conversation.Conversation;
|
||||
import org.springframework.webflow.conversation.ConversationException;
|
||||
import org.springframework.webflow.conversation.ConversationId;
|
||||
import org.springframework.webflow.conversation.ConversationManager;
|
||||
import org.springframework.webflow.conversation.ConversationParameters;
|
||||
import org.springframework.webflow.core.collection.SharedAttributeMap;
|
||||
|
||||
/**
|
||||
* Simple implementation of a conversation manager that stores conversations in the session attribute map.
|
||||
* <p>
|
||||
* Using the {@link #setMaxConversations(int) maxConversations} property, you can limit the number of concurrently
|
||||
* active conversations allowed in a single session. If the maximum is exceeded, the conversation manager will
|
||||
* automatically end the oldest conversation. The default is 5, which should be fine for most situations. Set it to -1
|
||||
* for no limit. Setting maxConversations to 1 allows easy resource cleanup in situations where there should only be one
|
||||
* active conversation per session.
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class SessionBindingConversationManager implements ConversationManager {
|
||||
|
||||
/**
|
||||
* The name of the session attribute that will hold the conversation container used by this conversation manager.
|
||||
*
|
||||
* To support multiple independent conversation containers in the same web application, for example, for use with
|
||||
* multiple flow executors each configured with their own session-binding conversation manager, set this field's
|
||||
* value to something unique.
|
||||
* @see #setSessionKey(String)
|
||||
*/
|
||||
private String sessionKey = "webflowConversationContainer";
|
||||
|
||||
/**
|
||||
* The maximum number of active conversations allowed in a session. The default is 5. This is high enough for most
|
||||
* practical situations and low enough to avoid excessive resource usage or easy denial of service attacks.
|
||||
*/
|
||||
private int maxConversations = 5;
|
||||
|
||||
/**
|
||||
* The lock timeout in seconds.
|
||||
*/
|
||||
private int lockTimeoutSeconds = 30;
|
||||
|
||||
/**
|
||||
* Returns the key this conversation manager uses to store conversation data in the session.
|
||||
* @return the session key
|
||||
*/
|
||||
public String getSessionKey() {
|
||||
return sessionKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key this conversation manager uses to store conversation data in the session. If multiple session
|
||||
* binding conversation managers are used in the same web application to back independent flow executors, this value
|
||||
* should be unique among them.
|
||||
* @param sessionKey the session key
|
||||
*/
|
||||
public void setSessionKey(String sessionKey) {
|
||||
this.sessionKey = sessionKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of allowed concurrent conversations. The default is 5.
|
||||
*/
|
||||
public int getMaxConversations() {
|
||||
return maxConversations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of allowed concurrent conversations. Set to -1 for no limit. The default is 5.
|
||||
*/
|
||||
public void setMaxConversations(int maxConversations) {
|
||||
this.maxConversations = maxConversations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time period that can elapse before a timeout occurs on an attempt to acquire a conversation lock. The
|
||||
* default is 30 seconds.
|
||||
*/
|
||||
public int getLockTimeoutSeconds() {
|
||||
return lockTimeoutSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time period that can elapse before a timeout occurs on an attempt to acquire a conversation lock. The
|
||||
* default is 30 seconds.
|
||||
* @param lockTimeoutSeconds the timeout period in seconds
|
||||
*/
|
||||
public void setLockTimeoutSeconds(int lockTimeoutSeconds) {
|
||||
this.lockTimeoutSeconds = lockTimeoutSeconds;
|
||||
}
|
||||
|
||||
// implementing conversation manager
|
||||
|
||||
public Conversation beginConversation(ConversationParameters conversationParameters) throws ConversationException {
|
||||
ConversationLock lock = new JdkConcurrentConversationLock(lockTimeoutSeconds);
|
||||
return getConversationContainer().createConversation(conversationParameters, lock);
|
||||
}
|
||||
|
||||
public Conversation getConversation(ConversationId id) throws ConversationException {
|
||||
return getConversationContainer().getConversation(id);
|
||||
}
|
||||
|
||||
public ConversationId parseConversationId(String encodedId) throws ConversationException {
|
||||
try {
|
||||
return new SimpleConversationId(Integer.valueOf(encodedId));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new BadlyFormattedConversationIdException(encodedId, e);
|
||||
}
|
||||
}
|
||||
|
||||
// hooks for subclassing
|
||||
|
||||
protected ConversationContainer createConversationContainer() {
|
||||
return new ConversationContainer(maxConversations, sessionKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the conversation container from the session. Create a new empty container and add it to the session if no
|
||||
* existing container can be found.
|
||||
*/
|
||||
protected final ConversationContainer getConversationContainer() {
|
||||
SharedAttributeMap<Object> sessionMap = ExternalContextHolder.getExternalContext().getSessionMap();
|
||||
synchronized (sessionMap.getMutex()) {
|
||||
ConversationContainer container = (ConversationContainer) sessionMap.get(sessionKey);
|
||||
if (container == null) {
|
||||
container = createConversationContainer();
|
||||
sessionMap.put(sessionKey, container);
|
||||
}
|
||||
return container;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core;
|
||||
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
|
||||
/**
|
||||
* An interface to be implemented by objects that are annotated with attributes they wish to expose to clients.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface Annotated {
|
||||
|
||||
/**
|
||||
* Returns a short summary of this object, suitable for display as an icon caption or tool tip.
|
||||
* @return the caption
|
||||
*/
|
||||
String getCaption();
|
||||
|
||||
/**
|
||||
* Returns a longer, more detailed description of this object.
|
||||
* @return the description
|
||||
*/
|
||||
String getDescription();
|
||||
|
||||
/**
|
||||
* Returns a attribute map containing the attributes annotating this object. These attributes provide descriptive
|
||||
* characteristics or properties that may affect object behavior.
|
||||
* @return the attribute map
|
||||
*/
|
||||
MutableAttributeMap<Object> getAttributes();
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core;
|
||||
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
|
||||
/**
|
||||
* An interface to be implemented by objects that are annotated with attributes they wish to expose to clients.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface Annotated {
|
||||
|
||||
/**
|
||||
* Returns a short summary of this object, suitable for display as an icon caption or tool tip.
|
||||
* @return the caption
|
||||
*/
|
||||
String getCaption();
|
||||
|
||||
/**
|
||||
* Returns a longer, more detailed description of this object.
|
||||
* @return the description
|
||||
*/
|
||||
String getDescription();
|
||||
|
||||
/**
|
||||
* Returns a attribute map containing the attributes annotating this object. These attributes provide descriptive
|
||||
* characteristics or properties that may affect object behavior.
|
||||
* @return the attribute map
|
||||
*/
|
||||
MutableAttributeMap<Object> getAttributes();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,79 +1,79 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core;
|
||||
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
|
||||
/**
|
||||
* A base class for all objects in the web flow system that support annotation using arbitrary properties. Mainly used
|
||||
* to ensure consistent configuration of properties for all annotated objects.
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public abstract class AnnotatedObject implements Annotated {
|
||||
|
||||
/**
|
||||
* The caption property name ("caption"). A caption is also known as a "short description" and may be used in a GUI
|
||||
* tooltip.
|
||||
*/
|
||||
public static final String CAPTION_PROPERTY = "caption";
|
||||
|
||||
/**
|
||||
* The long description property name ("description"). A description provides additional, free-form detail about
|
||||
* this object and might be shown in a GUI text area.
|
||||
*/
|
||||
public static final String DESCRIPTION_PROPERTY = "description";
|
||||
|
||||
/**
|
||||
* Additional properties further describing this object. The properties set in this map may be arbitrary.
|
||||
*/
|
||||
private LocalAttributeMap<Object> attributes = new LocalAttributeMap<>();
|
||||
|
||||
// implementing Annotated
|
||||
|
||||
public String getCaption() {
|
||||
return attributes.getString(CAPTION_PROPERTY);
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return attributes.getString(DESCRIPTION_PROPERTY);
|
||||
}
|
||||
|
||||
public MutableAttributeMap<Object> getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
// mutators
|
||||
|
||||
/**
|
||||
* Sets the short description (suitable for display in a tooltip).
|
||||
* @param caption the caption
|
||||
*/
|
||||
public void setCaption(String caption) {
|
||||
attributes.put(CAPTION_PROPERTY, caption);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the long description.
|
||||
* @param description the long description
|
||||
*/
|
||||
public void setDescription(String description) {
|
||||
attributes.put(DESCRIPTION_PROPERTY, description);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core;
|
||||
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
|
||||
/**
|
||||
* A base class for all objects in the web flow system that support annotation using arbitrary properties. Mainly used
|
||||
* to ensure consistent configuration of properties for all annotated objects.
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public abstract class AnnotatedObject implements Annotated {
|
||||
|
||||
/**
|
||||
* The caption property name ("caption"). A caption is also known as a "short description" and may be used in a GUI
|
||||
* tooltip.
|
||||
*/
|
||||
public static final String CAPTION_PROPERTY = "caption";
|
||||
|
||||
/**
|
||||
* The long description property name ("description"). A description provides additional, free-form detail about
|
||||
* this object and might be shown in a GUI text area.
|
||||
*/
|
||||
public static final String DESCRIPTION_PROPERTY = "description";
|
||||
|
||||
/**
|
||||
* Additional properties further describing this object. The properties set in this map may be arbitrary.
|
||||
*/
|
||||
private LocalAttributeMap<Object> attributes = new LocalAttributeMap<>();
|
||||
|
||||
// implementing Annotated
|
||||
|
||||
public String getCaption() {
|
||||
return attributes.getString(CAPTION_PROPERTY);
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return attributes.getString(DESCRIPTION_PROPERTY);
|
||||
}
|
||||
|
||||
public MutableAttributeMap<Object> getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
// mutators
|
||||
|
||||
/**
|
||||
* Sets the short description (suitable for display in a tooltip).
|
||||
* @param caption the caption
|
||||
*/
|
||||
public void setCaption(String caption) {
|
||||
attributes.put(CAPTION_PROPERTY, caption);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the long description.
|
||||
* @param description the long description
|
||||
*/
|
||||
public void setDescription(String description) {
|
||||
attributes.put(DESCRIPTION_PROPERTY, description);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.core;
|
||||
|
||||
/**
|
||||
* Root class for exceptions thrown by the Spring Web Flow system. All other exceptions within the system should be
|
||||
* assignable to this class.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public abstract class FlowException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Creates a new flow exception.
|
||||
* @param msg the message
|
||||
* @param cause the cause
|
||||
*/
|
||||
public FlowException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new flow exception.
|
||||
* @param msg the message
|
||||
*/
|
||||
public FlowException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.core;
|
||||
|
||||
/**
|
||||
* Root class for exceptions thrown by the Spring Web Flow system. All other exceptions within the system should be
|
||||
* assignable to this class.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public abstract class FlowException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Creates a new flow exception.
|
||||
* @param msg the message
|
||||
* @param cause the cause
|
||||
*/
|
||||
public FlowException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new flow exception.
|
||||
* @param msg the message
|
||||
*/
|
||||
public FlowException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,315 +1,315 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.binding.collection.MapAdaptable;
|
||||
|
||||
/**
|
||||
* An immutable interface for accessing attributes in a backing map with string keys.
|
||||
* <p>
|
||||
* Implementations can optionally support {@link AttributeMapBindingListener listeners} that will be notified when
|
||||
* they're bound in or unbound from the map.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface AttributeMap<V> extends MapAdaptable<String, V> {
|
||||
|
||||
/**
|
||||
* Get an attribute value out of this map, returning <code>null</code> if not found.
|
||||
* @param attributeName the attribute name
|
||||
* @return the attribute value
|
||||
*/
|
||||
V get(String attributeName);
|
||||
|
||||
/**
|
||||
* Returns the size of this map.
|
||||
* @return the number of entries in the map
|
||||
*/
|
||||
int size();
|
||||
|
||||
/**
|
||||
* Is this attribute map empty with a size of 0?
|
||||
* @return true if empty, false if not
|
||||
*/
|
||||
boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Does the attribute with the provided name exist in this map?
|
||||
* @param attributeName the attribute name
|
||||
* @return true if so, false otherwise
|
||||
*/
|
||||
boolean contains(String attributeName);
|
||||
|
||||
/**
|
||||
* Does the attribute with the provided name exist in this map and is its value of the specified required type?
|
||||
* @param attributeName the attribute name
|
||||
* @param requiredType the required class of the attribute value
|
||||
* @return true if so, false otherwise
|
||||
* @throws IllegalArgumentException when the value is not of the required type
|
||||
*/
|
||||
boolean contains(String attributeName, Class<? extends V> requiredType) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get an attribute value, returning the default value if no value is found.
|
||||
* @param attributeName the name of the attribute
|
||||
* @param defaultValue the default value
|
||||
* @return the attribute value, falling back to the default if no such attribute exists
|
||||
*/
|
||||
V get(String attributeName, V defaultValue);
|
||||
|
||||
/**
|
||||
* Get an attribute value, asserting the value is of the required type.
|
||||
* @param attributeName the name of the attribute
|
||||
* @param requiredType the required type of the attribute value
|
||||
* @return the attribute value, or null if not found
|
||||
* @throws IllegalArgumentException when the value is not of the required type
|
||||
*/
|
||||
<T extends V> T get(String attributeName, Class<T> requiredType) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get an attribute value, asserting the value is of the required type and returning the default value if not found.
|
||||
* @param attributeName the name of the attribute
|
||||
* @param requiredType the value required type
|
||||
* @param defaultValue the default value
|
||||
* @return the attribute value, or the default if not found
|
||||
* @throws IllegalArgumentException when the value (if found) is not of the required type
|
||||
*/
|
||||
<T extends V> T get(String attributeName, Class<T> requiredType, T defaultValue)
|
||||
throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Get the value of a required attribute, throwing an exception of no attribute is found.
|
||||
* @param attributeName the name of the attribute
|
||||
* @return the attribute value
|
||||
* @throws IllegalArgumentException when the attribute is not found
|
||||
*/
|
||||
V getRequired(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get the value of a required attribute and make sure it is of the required type.
|
||||
* @param attributeName name of the attribute to get
|
||||
* @param requiredType the required type of the attribute value
|
||||
* @return the attribute value
|
||||
* @throws IllegalArgumentException when the attribute is not found or not of the required type
|
||||
*/
|
||||
<T extends V> T getRequired(String attributeName, Class<T> requiredType) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a string attribute value in the map, returning <code>null</code> if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @return the string attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a string
|
||||
*/
|
||||
String getString(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a string attribute value in the map, returning the default value if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @param defaultValue the default
|
||||
* @return the string attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a string
|
||||
*/
|
||||
String getString(String attributeName, String defaultValue) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a string attribute value in the map, throwing an exception if the attribute is not present and of the
|
||||
* correct type.
|
||||
* @param attributeName the attribute name
|
||||
* @return the string attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or present but not a string
|
||||
*/
|
||||
String getRequiredString(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a collection attribute value in the map.
|
||||
* @param attributeName the attribute name
|
||||
* @return the collection attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a collection
|
||||
*/
|
||||
Collection<V> getCollection(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a collection attribute value in the map and make sure it is of the required type.
|
||||
* @param attributeName the attribute name
|
||||
* @param requiredType the required type of the attribute value
|
||||
* @return the collection attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a collection of the required type
|
||||
*/
|
||||
<T extends Collection<V>> T getCollection(String attributeName, Class<T> requiredType)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a collection attribute value in the map, throwing an exception if the attribute is not present or not a
|
||||
* collection.
|
||||
* @param attributeName the attribute name
|
||||
* @return the collection attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or is present but not a collection
|
||||
*/
|
||||
Collection<V> getRequiredCollection(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a collection attribute value in the map, throwing an exception if the attribute is not present or not a
|
||||
* collection of the required type.
|
||||
* @param attributeName the attribute name
|
||||
* @param requiredType the required collection type
|
||||
* @return the collection attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or is present but not a collection of the
|
||||
* required type
|
||||
*/
|
||||
<T extends Collection<V>> T getRequiredCollection(String attributeName, Class<T> requiredType)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns an array attribute value in the map and makes sure it is of the required type.
|
||||
* @param attributeName the attribute name
|
||||
* @param requiredType the required type of the attribute value
|
||||
* @return the array attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not an array of the required type
|
||||
*/
|
||||
<T extends V> T[] getArray(String attributeName, Class<? extends T[]> requiredType)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns an array attribute value in the map, throwing an exception if the attribute is not present or not an
|
||||
* array of the required type.
|
||||
* @param attributeName the attribute name
|
||||
* @param requiredType the required array type
|
||||
* @return the collection attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or is present but not a array of the required
|
||||
* type
|
||||
*/
|
||||
<T extends V> T[] getRequiredArray(String attributeName, Class<? extends T[]> requiredType)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a number attribute value in the map that is of the specified type, returning <code>null</code> if no
|
||||
* value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @param requiredType the required number type
|
||||
* @return the number attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a number of the required type
|
||||
*/
|
||||
<T extends Number> T getNumber(String attributeName, Class<T> requiredType) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a number attribute value in the map of the specified type, returning the default value if no value was
|
||||
* found.
|
||||
* @param attributeName the attribute name
|
||||
* @param defaultValue the default
|
||||
* @return the number attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a number of the required type
|
||||
*/
|
||||
<T extends Number> T getNumber(String attributeName, Class<T> requiredType, T defaultValue)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a number attribute value in the map, throwing an exception if the attribute is not present and of the
|
||||
* correct type.
|
||||
* @param attributeName the attribute name
|
||||
* @return the number attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or present but not a number of the required type
|
||||
*/
|
||||
<T extends Number> T getRequiredNumber(String attributeName, Class<T> requiredType)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns an integer attribute value in the map, returning <code>null</code> if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @return the integer attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not an integer
|
||||
*/
|
||||
Integer getInteger(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns an integer attribute value in the map, returning the default value if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @param defaultValue the default
|
||||
* @return the integer attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not an integer
|
||||
*/
|
||||
Integer getInteger(String attributeName, Integer defaultValue) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns an integer attribute value in the map, throwing an exception if the attribute is not present and of the
|
||||
* correct type.
|
||||
* @param attributeName the attribute name
|
||||
* @return the integer attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or present but not an integer
|
||||
*/
|
||||
Integer getRequiredInteger(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a long attribute value in the map, returning <code>null</code> if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @return the long attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a long
|
||||
*/
|
||||
Long getLong(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a long attribute value in the map, returning the default value if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @param defaultValue the default
|
||||
* @return the long attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a long
|
||||
*/
|
||||
Long getLong(String attributeName, Long defaultValue) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a long attribute value in the map, throwing an exception if the attribute is not present and of the
|
||||
* correct type.
|
||||
* @param attributeName the attribute name
|
||||
* @return the long attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or present but not a long
|
||||
*/
|
||||
Long getRequiredLong(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a boolean attribute value in the map, returning <code>null</code> if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @return the long attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a boolean
|
||||
*/
|
||||
Boolean getBoolean(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a boolean attribute value in the map, returning the default value if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @param defaultValue the default
|
||||
* @return the boolean attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a boolean
|
||||
*/
|
||||
Boolean getBoolean(String attributeName, Boolean defaultValue) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a boolean attribute value in the map, throwing an exception if the attribute is not present and of the
|
||||
* correct type.
|
||||
* @param attributeName the attribute name
|
||||
* @return the boolean attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or present but is not a boolean
|
||||
*/
|
||||
Boolean getRequiredBoolean(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a new attribute map containing the union of this map with the provided map.
|
||||
* @param attributes the map to combine with this map
|
||||
* @return a new, combined map
|
||||
*/
|
||||
AttributeMap<V> union(AttributeMap<? extends V> attributes);
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.binding.collection.MapAdaptable;
|
||||
|
||||
/**
|
||||
* An immutable interface for accessing attributes in a backing map with string keys.
|
||||
* <p>
|
||||
* Implementations can optionally support {@link AttributeMapBindingListener listeners} that will be notified when
|
||||
* they're bound in or unbound from the map.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface AttributeMap<V> extends MapAdaptable<String, V> {
|
||||
|
||||
/**
|
||||
* Get an attribute value out of this map, returning <code>null</code> if not found.
|
||||
* @param attributeName the attribute name
|
||||
* @return the attribute value
|
||||
*/
|
||||
V get(String attributeName);
|
||||
|
||||
/**
|
||||
* Returns the size of this map.
|
||||
* @return the number of entries in the map
|
||||
*/
|
||||
int size();
|
||||
|
||||
/**
|
||||
* Is this attribute map empty with a size of 0?
|
||||
* @return true if empty, false if not
|
||||
*/
|
||||
boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Does the attribute with the provided name exist in this map?
|
||||
* @param attributeName the attribute name
|
||||
* @return true if so, false otherwise
|
||||
*/
|
||||
boolean contains(String attributeName);
|
||||
|
||||
/**
|
||||
* Does the attribute with the provided name exist in this map and is its value of the specified required type?
|
||||
* @param attributeName the attribute name
|
||||
* @param requiredType the required class of the attribute value
|
||||
* @return true if so, false otherwise
|
||||
* @throws IllegalArgumentException when the value is not of the required type
|
||||
*/
|
||||
boolean contains(String attributeName, Class<? extends V> requiredType) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get an attribute value, returning the default value if no value is found.
|
||||
* @param attributeName the name of the attribute
|
||||
* @param defaultValue the default value
|
||||
* @return the attribute value, falling back to the default if no such attribute exists
|
||||
*/
|
||||
V get(String attributeName, V defaultValue);
|
||||
|
||||
/**
|
||||
* Get an attribute value, asserting the value is of the required type.
|
||||
* @param attributeName the name of the attribute
|
||||
* @param requiredType the required type of the attribute value
|
||||
* @return the attribute value, or null if not found
|
||||
* @throws IllegalArgumentException when the value is not of the required type
|
||||
*/
|
||||
<T extends V> T get(String attributeName, Class<T> requiredType) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get an attribute value, asserting the value is of the required type and returning the default value if not found.
|
||||
* @param attributeName the name of the attribute
|
||||
* @param requiredType the value required type
|
||||
* @param defaultValue the default value
|
||||
* @return the attribute value, or the default if not found
|
||||
* @throws IllegalArgumentException when the value (if found) is not of the required type
|
||||
*/
|
||||
<T extends V> T get(String attributeName, Class<T> requiredType, T defaultValue)
|
||||
throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Get the value of a required attribute, throwing an exception of no attribute is found.
|
||||
* @param attributeName the name of the attribute
|
||||
* @return the attribute value
|
||||
* @throws IllegalArgumentException when the attribute is not found
|
||||
*/
|
||||
V getRequired(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get the value of a required attribute and make sure it is of the required type.
|
||||
* @param attributeName name of the attribute to get
|
||||
* @param requiredType the required type of the attribute value
|
||||
* @return the attribute value
|
||||
* @throws IllegalArgumentException when the attribute is not found or not of the required type
|
||||
*/
|
||||
<T extends V> T getRequired(String attributeName, Class<T> requiredType) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a string attribute value in the map, returning <code>null</code> if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @return the string attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a string
|
||||
*/
|
||||
String getString(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a string attribute value in the map, returning the default value if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @param defaultValue the default
|
||||
* @return the string attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a string
|
||||
*/
|
||||
String getString(String attributeName, String defaultValue) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a string attribute value in the map, throwing an exception if the attribute is not present and of the
|
||||
* correct type.
|
||||
* @param attributeName the attribute name
|
||||
* @return the string attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or present but not a string
|
||||
*/
|
||||
String getRequiredString(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a collection attribute value in the map.
|
||||
* @param attributeName the attribute name
|
||||
* @return the collection attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a collection
|
||||
*/
|
||||
Collection<V> getCollection(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a collection attribute value in the map and make sure it is of the required type.
|
||||
* @param attributeName the attribute name
|
||||
* @param requiredType the required type of the attribute value
|
||||
* @return the collection attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a collection of the required type
|
||||
*/
|
||||
<T extends Collection<V>> T getCollection(String attributeName, Class<T> requiredType)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a collection attribute value in the map, throwing an exception if the attribute is not present or not a
|
||||
* collection.
|
||||
* @param attributeName the attribute name
|
||||
* @return the collection attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or is present but not a collection
|
||||
*/
|
||||
Collection<V> getRequiredCollection(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a collection attribute value in the map, throwing an exception if the attribute is not present or not a
|
||||
* collection of the required type.
|
||||
* @param attributeName the attribute name
|
||||
* @param requiredType the required collection type
|
||||
* @return the collection attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or is present but not a collection of the
|
||||
* required type
|
||||
*/
|
||||
<T extends Collection<V>> T getRequiredCollection(String attributeName, Class<T> requiredType)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns an array attribute value in the map and makes sure it is of the required type.
|
||||
* @param attributeName the attribute name
|
||||
* @param requiredType the required type of the attribute value
|
||||
* @return the array attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not an array of the required type
|
||||
*/
|
||||
<T extends V> T[] getArray(String attributeName, Class<? extends T[]> requiredType)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns an array attribute value in the map, throwing an exception if the attribute is not present or not an
|
||||
* array of the required type.
|
||||
* @param attributeName the attribute name
|
||||
* @param requiredType the required array type
|
||||
* @return the collection attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or is present but not a array of the required
|
||||
* type
|
||||
*/
|
||||
<T extends V> T[] getRequiredArray(String attributeName, Class<? extends T[]> requiredType)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a number attribute value in the map that is of the specified type, returning <code>null</code> if no
|
||||
* value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @param requiredType the required number type
|
||||
* @return the number attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a number of the required type
|
||||
*/
|
||||
<T extends Number> T getNumber(String attributeName, Class<T> requiredType) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a number attribute value in the map of the specified type, returning the default value if no value was
|
||||
* found.
|
||||
* @param attributeName the attribute name
|
||||
* @param defaultValue the default
|
||||
* @return the number attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a number of the required type
|
||||
*/
|
||||
<T extends Number> T getNumber(String attributeName, Class<T> requiredType, T defaultValue)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a number attribute value in the map, throwing an exception if the attribute is not present and of the
|
||||
* correct type.
|
||||
* @param attributeName the attribute name
|
||||
* @return the number attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or present but not a number of the required type
|
||||
*/
|
||||
<T extends Number> T getRequiredNumber(String attributeName, Class<T> requiredType)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns an integer attribute value in the map, returning <code>null</code> if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @return the integer attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not an integer
|
||||
*/
|
||||
Integer getInteger(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns an integer attribute value in the map, returning the default value if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @param defaultValue the default
|
||||
* @return the integer attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not an integer
|
||||
*/
|
||||
Integer getInteger(String attributeName, Integer defaultValue) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns an integer attribute value in the map, throwing an exception if the attribute is not present and of the
|
||||
* correct type.
|
||||
* @param attributeName the attribute name
|
||||
* @return the integer attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or present but not an integer
|
||||
*/
|
||||
Integer getRequiredInteger(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a long attribute value in the map, returning <code>null</code> if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @return the long attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a long
|
||||
*/
|
||||
Long getLong(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a long attribute value in the map, returning the default value if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @param defaultValue the default
|
||||
* @return the long attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a long
|
||||
*/
|
||||
Long getLong(String attributeName, Long defaultValue) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a long attribute value in the map, throwing an exception if the attribute is not present and of the
|
||||
* correct type.
|
||||
* @param attributeName the attribute name
|
||||
* @return the long attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or present but not a long
|
||||
*/
|
||||
Long getRequiredLong(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a boolean attribute value in the map, returning <code>null</code> if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @return the long attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a boolean
|
||||
*/
|
||||
Boolean getBoolean(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a boolean attribute value in the map, returning the default value if no value was found.
|
||||
* @param attributeName the attribute name
|
||||
* @param defaultValue the default
|
||||
* @return the boolean attribute value
|
||||
* @throws IllegalArgumentException if the attribute is present but not a boolean
|
||||
*/
|
||||
Boolean getBoolean(String attributeName, Boolean defaultValue) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a boolean attribute value in the map, throwing an exception if the attribute is not present and of the
|
||||
* correct type.
|
||||
* @param attributeName the attribute name
|
||||
* @return the boolean attribute value
|
||||
* @throws IllegalArgumentException if the attribute is not present or present but is not a boolean
|
||||
*/
|
||||
Boolean getRequiredBoolean(String attributeName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a new attribute map containing the union of this map with the provided map.
|
||||
* @param attributes the map to combine with this map
|
||||
* @return a new, combined map
|
||||
*/
|
||||
AttributeMap<V> union(AttributeMap<? extends V> attributes);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,59 +1,59 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
import java.util.EventObject;
|
||||
|
||||
/**
|
||||
* Holder for information about the binding or unbinding event in an {@link AttributeMap}.
|
||||
*
|
||||
* @see AttributeMapBindingListener
|
||||
*
|
||||
* @author Ben Hale
|
||||
*/
|
||||
public class AttributeMapBindingEvent extends EventObject {
|
||||
|
||||
private String attributeName;
|
||||
|
||||
private Object attributeValue;
|
||||
|
||||
/**
|
||||
* Creates an event for map binding that contains information about the event.
|
||||
* @param source the source map that this attribute was bound in
|
||||
* @param attributeName the name that this attribute was bound with
|
||||
* @param attributeValue the attribute
|
||||
*/
|
||||
public AttributeMapBindingEvent(AttributeMap<?> source, String attributeName, Object attributeValue) {
|
||||
super(source);
|
||||
this.source = source;
|
||||
this.attributeName = attributeName;
|
||||
this.attributeValue = attributeValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name the attribute was bound with.
|
||||
*/
|
||||
public String getAttributeName() {
|
||||
return attributeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the attribute.
|
||||
*/
|
||||
public Object getAttributeValue() {
|
||||
return attributeValue;
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
import java.util.EventObject;
|
||||
|
||||
/**
|
||||
* Holder for information about the binding or unbinding event in an {@link AttributeMap}.
|
||||
*
|
||||
* @see AttributeMapBindingListener
|
||||
*
|
||||
* @author Ben Hale
|
||||
*/
|
||||
public class AttributeMapBindingEvent extends EventObject {
|
||||
|
||||
private String attributeName;
|
||||
|
||||
private Object attributeValue;
|
||||
|
||||
/**
|
||||
* Creates an event for map binding that contains information about the event.
|
||||
* @param source the source map that this attribute was bound in
|
||||
* @param attributeName the name that this attribute was bound with
|
||||
* @param attributeValue the attribute
|
||||
*/
|
||||
public AttributeMapBindingEvent(AttributeMap<?> source, String attributeName, Object attributeValue) {
|
||||
super(source);
|
||||
this.source = source;
|
||||
this.attributeName = attributeName;
|
||||
this.attributeValue = attributeValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name the attribute was bound with.
|
||||
*/
|
||||
public String getAttributeName() {
|
||||
return attributeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the attribute.
|
||||
*/
|
||||
public Object getAttributeValue() {
|
||||
return attributeValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
/**
|
||||
* Causes an object to be notified when it is bound or unbound from an {@link AttributeMap}.
|
||||
* <p>
|
||||
* Note that this is an optional feature and not all {@link AttributeMap} implementations support it.
|
||||
*
|
||||
* @see AttributeMap
|
||||
*
|
||||
* @author Ben Hale
|
||||
*/
|
||||
public interface AttributeMapBindingListener {
|
||||
|
||||
/**
|
||||
* Called when the implementing instance is bound into an <code>AttributeMap</code>.
|
||||
* @param event information about the binding event
|
||||
*/
|
||||
void valueBound(AttributeMapBindingEvent event);
|
||||
|
||||
/**
|
||||
* Called when the implementing instance is unbound from an <code>AttributeMap</code>.
|
||||
* @param event information about the unbinding event
|
||||
*/
|
||||
void valueUnbound(AttributeMapBindingEvent event);
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
/**
|
||||
* Causes an object to be notified when it is bound or unbound from an {@link AttributeMap}.
|
||||
* <p>
|
||||
* Note that this is an optional feature and not all {@link AttributeMap} implementations support it.
|
||||
*
|
||||
* @see AttributeMap
|
||||
*
|
||||
* @author Ben Hale
|
||||
*/
|
||||
public interface AttributeMapBindingListener {
|
||||
|
||||
/**
|
||||
* Called when the implementing instance is bound into an <code>AttributeMap</code>.
|
||||
* @param event information about the binding event
|
||||
*/
|
||||
void valueBound(AttributeMapBindingEvent event);
|
||||
|
||||
/**
|
||||
* Called when the implementing instance is unbound from an <code>AttributeMap</code>.
|
||||
* @param event information about the unbinding event
|
||||
*/
|
||||
void valueUnbound(AttributeMapBindingEvent event);
|
||||
}
|
||||
@@ -1,140 +1,140 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A utility class for working with attribute and parameter collections used by Spring Web FLow.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class CollectionUtils {
|
||||
|
||||
/**
|
||||
* The shared, singleton empty iterator instance.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static final Iterator EMPTY_ITERATOR = new EmptyIterator();
|
||||
|
||||
/**
|
||||
* The shared, singleton empty attribute map instance.
|
||||
*/
|
||||
public static final AttributeMap<Object> EMPTY_ATTRIBUTE_MAP = new LocalAttributeMap<>(Collections.emptyMap());
|
||||
|
||||
/**
|
||||
* Private constructor to avoid instantiation.
|
||||
*/
|
||||
private CollectionUtils() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E> Iterator<E> emptyIterator() {
|
||||
return EMPTY_ITERATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that adapts an enumeration to an iterator.
|
||||
* @param enumeration the enumeration
|
||||
* @return the iterator
|
||||
*/
|
||||
public static <E> Iterator<E> toIterator(Enumeration<E> enumeration) {
|
||||
return new EnumerationIterator<>(enumeration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that returns a unmodifiable attribute map with a single entry.
|
||||
* @param attributeName the attribute name
|
||||
* @param attributeValue the attribute value
|
||||
* @return the unmodifiable map with a single element
|
||||
*/
|
||||
public static <V> AttributeMap<V> singleEntryMap(String attributeName, V attributeValue) {
|
||||
return new LocalAttributeMap<>(attributeName, attributeValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all given objects to given target list. No duplicates will be added. The contains() method of the given
|
||||
* target list will be used to determine whether or not an object is already in the list.
|
||||
* @param target the collection to which to objects will be added
|
||||
* @param objects the objects to add
|
||||
* @return whether or not the target collection changed
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> boolean addAllNoDuplicates(List<T> target, T... objects) {
|
||||
if (objects == null || objects.length == 0) {
|
||||
return false;
|
||||
} else {
|
||||
boolean changed = false;
|
||||
for (T object : objects) {
|
||||
if (!target.contains(object)) {
|
||||
target.add(object);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator iterating over no elements (hasNext() always returns false).
|
||||
*/
|
||||
private static class EmptyIterator<E> implements Iterator<E>, Serializable {
|
||||
|
||||
private EmptyIterator() {
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public E next() {
|
||||
throw new UnsupportedOperationException("There are no elements");
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("There are no elements");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator wrapping an Enumeration.
|
||||
*/
|
||||
private static class EnumerationIterator<E> implements Iterator<E> {
|
||||
|
||||
private Enumeration<E> enumeration;
|
||||
|
||||
public EnumerationIterator(Enumeration<E> enumeration) {
|
||||
this.enumeration = enumeration;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return enumeration.hasMoreElements();
|
||||
}
|
||||
|
||||
public E next() {
|
||||
return enumeration.nextElement();
|
||||
}
|
||||
|
||||
public void remove() throws UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A utility class for working with attribute and parameter collections used by Spring Web FLow.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class CollectionUtils {
|
||||
|
||||
/**
|
||||
* The shared, singleton empty iterator instance.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static final Iterator EMPTY_ITERATOR = new EmptyIterator();
|
||||
|
||||
/**
|
||||
* The shared, singleton empty attribute map instance.
|
||||
*/
|
||||
public static final AttributeMap<Object> EMPTY_ATTRIBUTE_MAP = new LocalAttributeMap<>(Collections.emptyMap());
|
||||
|
||||
/**
|
||||
* Private constructor to avoid instantiation.
|
||||
*/
|
||||
private CollectionUtils() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E> Iterator<E> emptyIterator() {
|
||||
return EMPTY_ITERATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that adapts an enumeration to an iterator.
|
||||
* @param enumeration the enumeration
|
||||
* @return the iterator
|
||||
*/
|
||||
public static <E> Iterator<E> toIterator(Enumeration<E> enumeration) {
|
||||
return new EnumerationIterator<>(enumeration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that returns a unmodifiable attribute map with a single entry.
|
||||
* @param attributeName the attribute name
|
||||
* @param attributeValue the attribute value
|
||||
* @return the unmodifiable map with a single element
|
||||
*/
|
||||
public static <V> AttributeMap<V> singleEntryMap(String attributeName, V attributeValue) {
|
||||
return new LocalAttributeMap<>(attributeName, attributeValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all given objects to given target list. No duplicates will be added. The contains() method of the given
|
||||
* target list will be used to determine whether or not an object is already in the list.
|
||||
* @param target the collection to which to objects will be added
|
||||
* @param objects the objects to add
|
||||
* @return whether or not the target collection changed
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> boolean addAllNoDuplicates(List<T> target, T... objects) {
|
||||
if (objects == null || objects.length == 0) {
|
||||
return false;
|
||||
} else {
|
||||
boolean changed = false;
|
||||
for (T object : objects) {
|
||||
if (!target.contains(object)) {
|
||||
target.add(object);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator iterating over no elements (hasNext() always returns false).
|
||||
*/
|
||||
private static class EmptyIterator<E> implements Iterator<E>, Serializable {
|
||||
|
||||
private EmptyIterator() {
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public E next() {
|
||||
throw new UnsupportedOperationException("There are no elements");
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("There are no elements");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator wrapping an Enumeration.
|
||||
*/
|
||||
private static class EnumerationIterator<E> implements Iterator<E> {
|
||||
|
||||
private Enumeration<E> enumeration;
|
||||
|
||||
public EnumerationIterator(Enumeration<E> enumeration) {
|
||||
this.enumeration = enumeration;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return enumeration.hasMoreElements();
|
||||
}
|
||||
|
||||
public E next() {
|
||||
return enumeration.nextElement();
|
||||
}
|
||||
|
||||
public void remove() throws UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,344 +1,344 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.binding.collection.MapAccessor;
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A generic, mutable attribute map with string keys.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class LocalAttributeMap<V> implements MutableAttributeMap<V>, Serializable {
|
||||
|
||||
/**
|
||||
* The backing map storing the attributes.
|
||||
*/
|
||||
private Map<String, V> attributes;
|
||||
|
||||
/**
|
||||
* A helper for accessing attributes. Marked transient and restored on deserialization.
|
||||
*/
|
||||
private transient MapAccessor<String, V> attributeAccessor;
|
||||
|
||||
/**
|
||||
* Creates a new attribute map, initially empty.
|
||||
*/
|
||||
public LocalAttributeMap() {
|
||||
initAttributes(createTargetMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new attribute map, initially empty.
|
||||
* @param size the initial size
|
||||
* @param loadFactor the load factor
|
||||
*/
|
||||
public LocalAttributeMap(int size, int loadFactor) {
|
||||
initAttributes(createTargetMap(size, loadFactor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new attribute map with a single entry.
|
||||
*/
|
||||
public LocalAttributeMap(String attributeName, V attributeValue) {
|
||||
initAttributes(createTargetMap(1, 1));
|
||||
put(attributeName, attributeValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new attribute map wrapping the specified map.
|
||||
*/
|
||||
public LocalAttributeMap(Map<String, V> map) {
|
||||
Assert.notNull(map, "The target map is required");
|
||||
initAttributes(map);
|
||||
}
|
||||
|
||||
// implementing attribute map
|
||||
|
||||
public Map<String, V> asMap() {
|
||||
return attributeAccessor.asMap();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return attributes.size();
|
||||
}
|
||||
|
||||
public V get(String attributeName) {
|
||||
return attributes.get(attributeName);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return attributes.isEmpty();
|
||||
}
|
||||
|
||||
public boolean contains(String attributeName) {
|
||||
return attributes.containsKey(attributeName);
|
||||
}
|
||||
|
||||
public boolean contains(String attributeName, Class<? extends V> requiredType) throws IllegalArgumentException {
|
||||
return attributeAccessor.containsKey(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public V get(String attributeName, V defaultValue) {
|
||||
return attributeAccessor.get(attributeName, defaultValue);
|
||||
}
|
||||
|
||||
public <T extends V> T get(String attributeName, Class<T> requiredType) throws IllegalArgumentException {
|
||||
return attributeAccessor.get(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public <T extends V> T get(String attributeName, Class<T> requiredType, T defaultValue)
|
||||
throws IllegalStateException {
|
||||
return attributeAccessor.get(attributeName, requiredType, defaultValue);
|
||||
}
|
||||
|
||||
public V getRequired(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequired(attributeName);
|
||||
}
|
||||
|
||||
public <T extends V> T getRequired(String attributeName, Class<T> requiredType) throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequired(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public String getString(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getString(attributeName);
|
||||
}
|
||||
|
||||
public String getString(String attributeName, String defaultValue) throws IllegalArgumentException {
|
||||
return attributeAccessor.getString(attributeName, defaultValue);
|
||||
}
|
||||
|
||||
public String getRequiredString(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredString(attributeName);
|
||||
}
|
||||
|
||||
public Collection<V> getCollection(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getCollection(attributeName);
|
||||
}
|
||||
|
||||
public <T extends Collection<V>> T getCollection(String attributeName, Class<T> requiredType)
|
||||
throws IllegalArgumentException {
|
||||
return attributeAccessor.getCollection(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public Collection<V> getRequiredCollection(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredCollection(attributeName);
|
||||
}
|
||||
|
||||
public <T extends Collection<V>> T getRequiredCollection(String attributeName, Class<T> requiredType)
|
||||
throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredCollection(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public <T extends V> T[] getArray(String attributeName, Class<? extends T[]> requiredType)
|
||||
throws IllegalArgumentException {
|
||||
return attributeAccessor.getArray(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public <T extends V> T[] getRequiredArray(String attributeName, Class<? extends T[]> requiredType)
|
||||
throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredArray(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public <T extends Number> T getNumber(String attributeName, Class<T> requiredType) throws IllegalArgumentException {
|
||||
return attributeAccessor.getNumber(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public <T extends Number> T getNumber(String attributeName, Class<T> requiredType, T defaultValue)
|
||||
throws IllegalArgumentException {
|
||||
return attributeAccessor.getNumber(attributeName, requiredType, defaultValue);
|
||||
}
|
||||
|
||||
public <T extends Number> T getRequiredNumber(String attributeName, Class<T> requiredType)
|
||||
throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredNumber(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public Integer getInteger(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getInteger(attributeName);
|
||||
}
|
||||
|
||||
public Integer getInteger(String attributeName, Integer defaultValue) throws IllegalArgumentException {
|
||||
return attributeAccessor.getInteger(attributeName, defaultValue);
|
||||
}
|
||||
|
||||
public Integer getRequiredInteger(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredInteger(attributeName);
|
||||
}
|
||||
|
||||
public Long getLong(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getLong(attributeName);
|
||||
}
|
||||
|
||||
public Long getLong(String attributeName, Long defaultValue) throws IllegalArgumentException {
|
||||
return attributeAccessor.getLong(attributeName, defaultValue);
|
||||
}
|
||||
|
||||
public Long getRequiredLong(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredLong(attributeName);
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getBoolean(attributeName);
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String attributeName, Boolean defaultValue) throws IllegalArgumentException {
|
||||
return attributeAccessor.getBoolean(attributeName, defaultValue);
|
||||
}
|
||||
|
||||
public Boolean getRequiredBoolean(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredBoolean(attributeName);
|
||||
}
|
||||
|
||||
public AttributeMap<V> union(AttributeMap<? extends V> attributes) {
|
||||
if (attributes == null) {
|
||||
return new LocalAttributeMap<>(getMapInternal());
|
||||
} else {
|
||||
Map<String, V> map = createTargetMap();
|
||||
map.putAll(getMapInternal());
|
||||
map.putAll(attributes.asMap());
|
||||
return new LocalAttributeMap<>(map);
|
||||
}
|
||||
}
|
||||
|
||||
// implementing MutableAttributeMap
|
||||
|
||||
public V put(String attributeName, V attributeValue) {
|
||||
return getMapInternal().put(attributeName, attributeValue);
|
||||
}
|
||||
|
||||
public MutableAttributeMap<V> putAll(AttributeMap<? extends V> attributes) {
|
||||
if (attributes == null) {
|
||||
return this;
|
||||
}
|
||||
getMapInternal().putAll(attributes.asMap());
|
||||
return this;
|
||||
}
|
||||
|
||||
public MutableAttributeMap<V> removeAll(MutableAttributeMap<? extends V> attributes) {
|
||||
if (attributes == null) {
|
||||
return this;
|
||||
}
|
||||
Map<String, V> internal = getMapInternal();
|
||||
for (String attribute : attributes.asMap().keySet()) {
|
||||
internal.remove(attribute);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object remove(String attributeName) {
|
||||
return getMapInternal().remove(attributeName);
|
||||
}
|
||||
|
||||
public Object extract(String attributeName) {
|
||||
Map<String, V> map = getMapInternal();
|
||||
if (map.containsKey(attributeName)) {
|
||||
Object value = map.get(attributeName);
|
||||
map.remove(attributeName);
|
||||
return value;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public MutableAttributeMap<V> clear() throws UnsupportedOperationException {
|
||||
getMapInternal().clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
public MutableAttributeMap<V> replaceWith(AttributeMap<? extends V> attributes)
|
||||
throws UnsupportedOperationException {
|
||||
clear();
|
||||
putAll(attributes);
|
||||
return this;
|
||||
}
|
||||
|
||||
// helpers for subclasses
|
||||
|
||||
/**
|
||||
* Initializes this attribute map.
|
||||
* @param attributes the attributes
|
||||
*/
|
||||
protected void initAttributes(Map<String, V> attributes) {
|
||||
this.attributes = attributes;
|
||||
attributeAccessor = new MapAccessor<>(this.attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the wrapped, modifiable map implementation.
|
||||
*/
|
||||
protected Map<String, V> getMapInternal() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
// helpers
|
||||
|
||||
/**
|
||||
* Factory method that returns the target map storing the data in this attribute map.
|
||||
* @return the target map
|
||||
*/
|
||||
protected Map<String, V> createTargetMap() {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that returns the target map storing the data in this attribute map.
|
||||
* @param size the initial size of the map
|
||||
* @param loadFactor the load factor
|
||||
* @return the target map
|
||||
*/
|
||||
protected Map<String, V> createTargetMap(int size, int loadFactor) {
|
||||
return new HashMap<>(size, loadFactor);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof LocalAttributeMap)) {
|
||||
return false;
|
||||
}
|
||||
LocalAttributeMap<V> other = (LocalAttributeMap<V>) o;
|
||||
return getMapInternal().equals(other.getMapInternal());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return getMapInternal().hashCode();
|
||||
}
|
||||
|
||||
// custom serialization
|
||||
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
out.defaultWriteObject();
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
attributeAccessor = new MapAccessor<>(attributes);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return StylerUtils.style(attributes);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.binding.collection.MapAccessor;
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A generic, mutable attribute map with string keys.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class LocalAttributeMap<V> implements MutableAttributeMap<V>, Serializable {
|
||||
|
||||
/**
|
||||
* The backing map storing the attributes.
|
||||
*/
|
||||
private Map<String, V> attributes;
|
||||
|
||||
/**
|
||||
* A helper for accessing attributes. Marked transient and restored on deserialization.
|
||||
*/
|
||||
private transient MapAccessor<String, V> attributeAccessor;
|
||||
|
||||
/**
|
||||
* Creates a new attribute map, initially empty.
|
||||
*/
|
||||
public LocalAttributeMap() {
|
||||
initAttributes(createTargetMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new attribute map, initially empty.
|
||||
* @param size the initial size
|
||||
* @param loadFactor the load factor
|
||||
*/
|
||||
public LocalAttributeMap(int size, int loadFactor) {
|
||||
initAttributes(createTargetMap(size, loadFactor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new attribute map with a single entry.
|
||||
*/
|
||||
public LocalAttributeMap(String attributeName, V attributeValue) {
|
||||
initAttributes(createTargetMap(1, 1));
|
||||
put(attributeName, attributeValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new attribute map wrapping the specified map.
|
||||
*/
|
||||
public LocalAttributeMap(Map<String, V> map) {
|
||||
Assert.notNull(map, "The target map is required");
|
||||
initAttributes(map);
|
||||
}
|
||||
|
||||
// implementing attribute map
|
||||
|
||||
public Map<String, V> asMap() {
|
||||
return attributeAccessor.asMap();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return attributes.size();
|
||||
}
|
||||
|
||||
public V get(String attributeName) {
|
||||
return attributes.get(attributeName);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return attributes.isEmpty();
|
||||
}
|
||||
|
||||
public boolean contains(String attributeName) {
|
||||
return attributes.containsKey(attributeName);
|
||||
}
|
||||
|
||||
public boolean contains(String attributeName, Class<? extends V> requiredType) throws IllegalArgumentException {
|
||||
return attributeAccessor.containsKey(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public V get(String attributeName, V defaultValue) {
|
||||
return attributeAccessor.get(attributeName, defaultValue);
|
||||
}
|
||||
|
||||
public <T extends V> T get(String attributeName, Class<T> requiredType) throws IllegalArgumentException {
|
||||
return attributeAccessor.get(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public <T extends V> T get(String attributeName, Class<T> requiredType, T defaultValue)
|
||||
throws IllegalStateException {
|
||||
return attributeAccessor.get(attributeName, requiredType, defaultValue);
|
||||
}
|
||||
|
||||
public V getRequired(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequired(attributeName);
|
||||
}
|
||||
|
||||
public <T extends V> T getRequired(String attributeName, Class<T> requiredType) throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequired(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public String getString(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getString(attributeName);
|
||||
}
|
||||
|
||||
public String getString(String attributeName, String defaultValue) throws IllegalArgumentException {
|
||||
return attributeAccessor.getString(attributeName, defaultValue);
|
||||
}
|
||||
|
||||
public String getRequiredString(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredString(attributeName);
|
||||
}
|
||||
|
||||
public Collection<V> getCollection(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getCollection(attributeName);
|
||||
}
|
||||
|
||||
public <T extends Collection<V>> T getCollection(String attributeName, Class<T> requiredType)
|
||||
throws IllegalArgumentException {
|
||||
return attributeAccessor.getCollection(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public Collection<V> getRequiredCollection(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredCollection(attributeName);
|
||||
}
|
||||
|
||||
public <T extends Collection<V>> T getRequiredCollection(String attributeName, Class<T> requiredType)
|
||||
throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredCollection(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public <T extends V> T[] getArray(String attributeName, Class<? extends T[]> requiredType)
|
||||
throws IllegalArgumentException {
|
||||
return attributeAccessor.getArray(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public <T extends V> T[] getRequiredArray(String attributeName, Class<? extends T[]> requiredType)
|
||||
throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredArray(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public <T extends Number> T getNumber(String attributeName, Class<T> requiredType) throws IllegalArgumentException {
|
||||
return attributeAccessor.getNumber(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public <T extends Number> T getNumber(String attributeName, Class<T> requiredType, T defaultValue)
|
||||
throws IllegalArgumentException {
|
||||
return attributeAccessor.getNumber(attributeName, requiredType, defaultValue);
|
||||
}
|
||||
|
||||
public <T extends Number> T getRequiredNumber(String attributeName, Class<T> requiredType)
|
||||
throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredNumber(attributeName, requiredType);
|
||||
}
|
||||
|
||||
public Integer getInteger(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getInteger(attributeName);
|
||||
}
|
||||
|
||||
public Integer getInteger(String attributeName, Integer defaultValue) throws IllegalArgumentException {
|
||||
return attributeAccessor.getInteger(attributeName, defaultValue);
|
||||
}
|
||||
|
||||
public Integer getRequiredInteger(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredInteger(attributeName);
|
||||
}
|
||||
|
||||
public Long getLong(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getLong(attributeName);
|
||||
}
|
||||
|
||||
public Long getLong(String attributeName, Long defaultValue) throws IllegalArgumentException {
|
||||
return attributeAccessor.getLong(attributeName, defaultValue);
|
||||
}
|
||||
|
||||
public Long getRequiredLong(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredLong(attributeName);
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getBoolean(attributeName);
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String attributeName, Boolean defaultValue) throws IllegalArgumentException {
|
||||
return attributeAccessor.getBoolean(attributeName, defaultValue);
|
||||
}
|
||||
|
||||
public Boolean getRequiredBoolean(String attributeName) throws IllegalArgumentException {
|
||||
return attributeAccessor.getRequiredBoolean(attributeName);
|
||||
}
|
||||
|
||||
public AttributeMap<V> union(AttributeMap<? extends V> attributes) {
|
||||
if (attributes == null) {
|
||||
return new LocalAttributeMap<>(getMapInternal());
|
||||
} else {
|
||||
Map<String, V> map = createTargetMap();
|
||||
map.putAll(getMapInternal());
|
||||
map.putAll(attributes.asMap());
|
||||
return new LocalAttributeMap<>(map);
|
||||
}
|
||||
}
|
||||
|
||||
// implementing MutableAttributeMap
|
||||
|
||||
public V put(String attributeName, V attributeValue) {
|
||||
return getMapInternal().put(attributeName, attributeValue);
|
||||
}
|
||||
|
||||
public MutableAttributeMap<V> putAll(AttributeMap<? extends V> attributes) {
|
||||
if (attributes == null) {
|
||||
return this;
|
||||
}
|
||||
getMapInternal().putAll(attributes.asMap());
|
||||
return this;
|
||||
}
|
||||
|
||||
public MutableAttributeMap<V> removeAll(MutableAttributeMap<? extends V> attributes) {
|
||||
if (attributes == null) {
|
||||
return this;
|
||||
}
|
||||
Map<String, V> internal = getMapInternal();
|
||||
for (String attribute : attributes.asMap().keySet()) {
|
||||
internal.remove(attribute);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object remove(String attributeName) {
|
||||
return getMapInternal().remove(attributeName);
|
||||
}
|
||||
|
||||
public Object extract(String attributeName) {
|
||||
Map<String, V> map = getMapInternal();
|
||||
if (map.containsKey(attributeName)) {
|
||||
Object value = map.get(attributeName);
|
||||
map.remove(attributeName);
|
||||
return value;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public MutableAttributeMap<V> clear() throws UnsupportedOperationException {
|
||||
getMapInternal().clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
public MutableAttributeMap<V> replaceWith(AttributeMap<? extends V> attributes)
|
||||
throws UnsupportedOperationException {
|
||||
clear();
|
||||
putAll(attributes);
|
||||
return this;
|
||||
}
|
||||
|
||||
// helpers for subclasses
|
||||
|
||||
/**
|
||||
* Initializes this attribute map.
|
||||
* @param attributes the attributes
|
||||
*/
|
||||
protected void initAttributes(Map<String, V> attributes) {
|
||||
this.attributes = attributes;
|
||||
attributeAccessor = new MapAccessor<>(this.attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the wrapped, modifiable map implementation.
|
||||
*/
|
||||
protected Map<String, V> getMapInternal() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
// helpers
|
||||
|
||||
/**
|
||||
* Factory method that returns the target map storing the data in this attribute map.
|
||||
* @return the target map
|
||||
*/
|
||||
protected Map<String, V> createTargetMap() {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that returns the target map storing the data in this attribute map.
|
||||
* @param size the initial size of the map
|
||||
* @param loadFactor the load factor
|
||||
* @return the target map
|
||||
*/
|
||||
protected Map<String, V> createTargetMap(int size, int loadFactor) {
|
||||
return new HashMap<>(size, loadFactor);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof LocalAttributeMap)) {
|
||||
return false;
|
||||
}
|
||||
LocalAttributeMap<V> other = (LocalAttributeMap<V>) o;
|
||||
return getMapInternal().equals(other.getMapInternal());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return getMapInternal().hashCode();
|
||||
}
|
||||
|
||||
// custom serialization
|
||||
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
out.defaultWriteObject();
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
attributeAccessor = new MapAccessor<>(attributes);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return StylerUtils.style(attributes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,323 +1,323 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.binding.collection.MapAccessor;
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.convert.service.DefaultConversionService;
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* An immutable parameter map storing String-keyed, String-valued parameters in a backing {@link Map} implementation.
|
||||
* This base provides convenient operations for accessing parameters in a typed-manner.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class LocalParameterMap implements ParameterMap, Serializable {
|
||||
|
||||
private static final DefaultConversionService DEFAULT_CONVERSION_SERVICE = new DefaultConversionService();
|
||||
|
||||
/**
|
||||
* The backing map storing the parameters.
|
||||
*/
|
||||
private Map<String, Object> parameters;
|
||||
|
||||
/**
|
||||
* A helper for accessing parameters. Marked transient and restored on deserialization.
|
||||
*/
|
||||
private transient MapAccessor<String, Object> parameterAccessor;
|
||||
|
||||
/**
|
||||
* A helper for converting string parameter values. Marked transient and restored on deserialization.
|
||||
*/
|
||||
private transient ConversionService conversionService;
|
||||
|
||||
/**
|
||||
* Creates a new parameter map from the provided map.
|
||||
* <p>
|
||||
* It is expected that the contents of the backing map adhere to the parameter map contract; that is, map entries
|
||||
* have string keys, string values, and remain unmodifiable.
|
||||
* @param parameters the contents of this parameter map
|
||||
*/
|
||||
public LocalParameterMap(Map<String, Object> parameters) {
|
||||
this(parameters, DEFAULT_CONVERSION_SERVICE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new parameter map from the provided map.
|
||||
* <p>
|
||||
* It is expected that the contents of the backing map adhere to the parameter map contract; that is, map entries
|
||||
* have string keys, string values, and remain unmodifiable.
|
||||
* @param parameters the contents of this parameter map
|
||||
* @param conversionService a helper for performing type conversion of map entry values
|
||||
*/
|
||||
public LocalParameterMap(Map<String, Object> parameters, ConversionService conversionService) {
|
||||
initParameters(parameters);
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof LocalParameterMap)) {
|
||||
return false;
|
||||
}
|
||||
LocalParameterMap other = (LocalParameterMap) o;
|
||||
return parameters.equals(other.parameters);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return parameters.hashCode();
|
||||
}
|
||||
|
||||
public Map<String, Object> asMap() {
|
||||
return Collections.unmodifiableMap(parameterAccessor.asMap());
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return parameters.isEmpty();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return parameters.size();
|
||||
}
|
||||
|
||||
public boolean contains(String parameterName) {
|
||||
return parameters.containsKey(parameterName);
|
||||
}
|
||||
|
||||
public String get(String parameterName) {
|
||||
return get(parameterName, (String) null);
|
||||
}
|
||||
|
||||
public String get(String parameterName, String defaultValue) {
|
||||
if (!parameters.containsKey(parameterName)) {
|
||||
return defaultValue;
|
||||
}
|
||||
Object value = parameters.get(parameterName);
|
||||
if (value.getClass().isArray()) {
|
||||
parameterAccessor.assertKeyValueInstanceOf(parameterName, value, String[].class);
|
||||
String[] array = (String[]) value;
|
||||
if (array.length == 0) {
|
||||
return null;
|
||||
} else {
|
||||
Object first = ((String[]) value)[0];
|
||||
parameterAccessor.assertKeyValueInstanceOf(parameterName, first, String.class);
|
||||
return (String) first;
|
||||
}
|
||||
|
||||
} else {
|
||||
parameterAccessor.assertKeyValueInstanceOf(parameterName, value, String.class);
|
||||
return (String) value;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getArray(String parameterName) {
|
||||
if (!parameters.containsKey(parameterName)) {
|
||||
return null;
|
||||
}
|
||||
Object value = parameters.get(parameterName);
|
||||
if (value.getClass().isArray()) {
|
||||
parameterAccessor.assertKeyValueInstanceOf(parameterName, value, String[].class);
|
||||
return (String[]) value;
|
||||
} else {
|
||||
parameterAccessor.assertKeyValueInstanceOf(parameterName, value, String.class);
|
||||
return new String[] { (String) value };
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T[] getArray(String parameterName, Class<T> targetElementType) throws ConversionExecutionException {
|
||||
String[] parameters = getArray(parameterName);
|
||||
return parameters != null ? convert(parameters, targetElementType) : null;
|
||||
}
|
||||
|
||||
public <T> T get(String parameterName, Class<T> targetType) throws ConversionExecutionException {
|
||||
return get(parameterName, targetType, null);
|
||||
}
|
||||
|
||||
public <T> T get(String parameterName, Class<T> targetType, T defaultValue) throws ConversionExecutionException {
|
||||
if (defaultValue != null) {
|
||||
assertAssignableTo(targetType, defaultValue.getClass());
|
||||
}
|
||||
String parameter = get(parameterName);
|
||||
return parameter != null ? convert(parameter, targetType) : defaultValue;
|
||||
}
|
||||
|
||||
public String getRequired(String parameterName) throws IllegalArgumentException {
|
||||
parameterAccessor.assertContainsKey(parameterName);
|
||||
return get(parameterName);
|
||||
}
|
||||
|
||||
public String[] getRequiredArray(String parameterName) throws IllegalArgumentException {
|
||||
parameterAccessor.assertContainsKey(parameterName);
|
||||
return getArray(parameterName);
|
||||
}
|
||||
|
||||
public <T> T[] getRequiredArray(String parameterName, Class<T> targetElementType) throws IllegalArgumentException,
|
||||
ConversionExecutionException {
|
||||
String[] parameters = getRequiredArray(parameterName);
|
||||
return convert(parameters, targetElementType);
|
||||
}
|
||||
|
||||
public <T> T getRequired(String parameterName, Class<T> targetType) throws IllegalArgumentException,
|
||||
ConversionExecutionException {
|
||||
return convert(getRequired(parameterName), targetType);
|
||||
}
|
||||
|
||||
public <T extends Number> T getNumber(String parameterName, Class<T> targetType)
|
||||
throws ConversionExecutionException {
|
||||
assertAssignableTo(Number.class, targetType);
|
||||
return get(parameterName, targetType);
|
||||
}
|
||||
|
||||
public <T extends Number> T getNumber(String parameterName, Class<T> targetType, T defaultValue)
|
||||
throws ConversionExecutionException {
|
||||
assertAssignableTo(Number.class, targetType);
|
||||
return get(parameterName, targetType, defaultValue);
|
||||
}
|
||||
|
||||
public <T extends Number> T getRequiredNumber(String parameterName, Class<T> targetType)
|
||||
throws IllegalArgumentException, ConversionExecutionException {
|
||||
assertAssignableTo(Number.class, targetType);
|
||||
return getRequired(parameterName, targetType);
|
||||
}
|
||||
|
||||
public Integer getInteger(String parameterName) throws ConversionExecutionException {
|
||||
return get(parameterName, Integer.class);
|
||||
}
|
||||
|
||||
public Integer getInteger(String parameterName, Integer defaultValue) throws ConversionExecutionException {
|
||||
return get(parameterName, Integer.class, defaultValue);
|
||||
}
|
||||
|
||||
public Integer getRequiredInteger(String parameterName) throws IllegalArgumentException,
|
||||
ConversionExecutionException {
|
||||
return getRequired(parameterName, Integer.class);
|
||||
}
|
||||
|
||||
public Long getLong(String parameterName) throws ConversionExecutionException {
|
||||
return get(parameterName, Long.class);
|
||||
}
|
||||
|
||||
public Long getLong(String parameterName, Long defaultValue) throws ConversionExecutionException {
|
||||
return get(parameterName, Long.class, defaultValue);
|
||||
}
|
||||
|
||||
public Long getRequiredLong(String parameterName) throws IllegalArgumentException, ConversionExecutionException {
|
||||
return getRequired(parameterName, Long.class);
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String parameterName) throws ConversionExecutionException {
|
||||
return get(parameterName, Boolean.class);
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String parameterName, Boolean defaultValue) throws ConversionExecutionException {
|
||||
return get(parameterName, Boolean.class, defaultValue);
|
||||
}
|
||||
|
||||
public Boolean getRequiredBoolean(String parameterName) throws IllegalArgumentException,
|
||||
ConversionExecutionException {
|
||||
return getRequired(parameterName, Boolean.class);
|
||||
}
|
||||
|
||||
public MultipartFile getMultipartFile(String parameterName) {
|
||||
return parameterAccessor.get(parameterName, MultipartFile.class);
|
||||
}
|
||||
|
||||
public MultipartFile getRequiredMultipartFile(String parameterName) throws IllegalArgumentException {
|
||||
return parameterAccessor.getRequired(parameterName, MultipartFile.class);
|
||||
}
|
||||
|
||||
public AttributeMap<Object> asAttributeMap() {
|
||||
return new LocalAttributeMap<>(getMapInternal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this parameter map.
|
||||
* @param parameters the parameters
|
||||
*/
|
||||
protected void initParameters(Map<String, Object> parameters) {
|
||||
this.parameters = parameters;
|
||||
parameterAccessor = new MapAccessor<>(this.parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the wrapped, modifiable map implementation.
|
||||
*/
|
||||
protected Map<String, Object> getMapInternal() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
/**
|
||||
* Convert given String parameter to specified target type.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T convert(String parameter, Class<T> targetType) throws ConversionExecutionException {
|
||||
return (T) conversionService.getConversionExecutor(String.class, targetType).execute(parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert given array of String parameters to specified target type and return the resulting array.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T[] convert(String[] parameters, Class<? extends T> targetElementType)
|
||||
throws ConversionExecutionException {
|
||||
List<T> list = new ArrayList<>(parameters.length);
|
||||
ConversionExecutor converter = conversionService.getConversionExecutor(String.class, targetElementType);
|
||||
for (String parameter : parameters) {
|
||||
list.add((T) converter.execute(parameter));
|
||||
}
|
||||
return list.toArray((T[]) Array.newInstance(targetElementType, parameters.length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure clazz is assignable from requiredType.
|
||||
*/
|
||||
private void assertAssignableTo(Class<?> clazz, Class<?> requiredType) {
|
||||
Assert.isTrue(clazz.isAssignableFrom(requiredType), "The provided required type must be assignable to ["
|
||||
+ clazz + "]");
|
||||
}
|
||||
|
||||
// custom serialization
|
||||
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
out.defaultWriteObject();
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
parameterAccessor = new MapAccessor<>(parameters);
|
||||
conversionService = DEFAULT_CONVERSION_SERVICE;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return StylerUtils.style(parameters);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.binding.collection.MapAccessor;
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.convert.service.DefaultConversionService;
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* An immutable parameter map storing String-keyed, String-valued parameters in a backing {@link Map} implementation.
|
||||
* This base provides convenient operations for accessing parameters in a typed-manner.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class LocalParameterMap implements ParameterMap, Serializable {
|
||||
|
||||
private static final DefaultConversionService DEFAULT_CONVERSION_SERVICE = new DefaultConversionService();
|
||||
|
||||
/**
|
||||
* The backing map storing the parameters.
|
||||
*/
|
||||
private Map<String, Object> parameters;
|
||||
|
||||
/**
|
||||
* A helper for accessing parameters. Marked transient and restored on deserialization.
|
||||
*/
|
||||
private transient MapAccessor<String, Object> parameterAccessor;
|
||||
|
||||
/**
|
||||
* A helper for converting string parameter values. Marked transient and restored on deserialization.
|
||||
*/
|
||||
private transient ConversionService conversionService;
|
||||
|
||||
/**
|
||||
* Creates a new parameter map from the provided map.
|
||||
* <p>
|
||||
* It is expected that the contents of the backing map adhere to the parameter map contract; that is, map entries
|
||||
* have string keys, string values, and remain unmodifiable.
|
||||
* @param parameters the contents of this parameter map
|
||||
*/
|
||||
public LocalParameterMap(Map<String, Object> parameters) {
|
||||
this(parameters, DEFAULT_CONVERSION_SERVICE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new parameter map from the provided map.
|
||||
* <p>
|
||||
* It is expected that the contents of the backing map adhere to the parameter map contract; that is, map entries
|
||||
* have string keys, string values, and remain unmodifiable.
|
||||
* @param parameters the contents of this parameter map
|
||||
* @param conversionService a helper for performing type conversion of map entry values
|
||||
*/
|
||||
public LocalParameterMap(Map<String, Object> parameters, ConversionService conversionService) {
|
||||
initParameters(parameters);
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof LocalParameterMap)) {
|
||||
return false;
|
||||
}
|
||||
LocalParameterMap other = (LocalParameterMap) o;
|
||||
return parameters.equals(other.parameters);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return parameters.hashCode();
|
||||
}
|
||||
|
||||
public Map<String, Object> asMap() {
|
||||
return Collections.unmodifiableMap(parameterAccessor.asMap());
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return parameters.isEmpty();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return parameters.size();
|
||||
}
|
||||
|
||||
public boolean contains(String parameterName) {
|
||||
return parameters.containsKey(parameterName);
|
||||
}
|
||||
|
||||
public String get(String parameterName) {
|
||||
return get(parameterName, (String) null);
|
||||
}
|
||||
|
||||
public String get(String parameterName, String defaultValue) {
|
||||
if (!parameters.containsKey(parameterName)) {
|
||||
return defaultValue;
|
||||
}
|
||||
Object value = parameters.get(parameterName);
|
||||
if (value.getClass().isArray()) {
|
||||
parameterAccessor.assertKeyValueInstanceOf(parameterName, value, String[].class);
|
||||
String[] array = (String[]) value;
|
||||
if (array.length == 0) {
|
||||
return null;
|
||||
} else {
|
||||
Object first = ((String[]) value)[0];
|
||||
parameterAccessor.assertKeyValueInstanceOf(parameterName, first, String.class);
|
||||
return (String) first;
|
||||
}
|
||||
|
||||
} else {
|
||||
parameterAccessor.assertKeyValueInstanceOf(parameterName, value, String.class);
|
||||
return (String) value;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getArray(String parameterName) {
|
||||
if (!parameters.containsKey(parameterName)) {
|
||||
return null;
|
||||
}
|
||||
Object value = parameters.get(parameterName);
|
||||
if (value.getClass().isArray()) {
|
||||
parameterAccessor.assertKeyValueInstanceOf(parameterName, value, String[].class);
|
||||
return (String[]) value;
|
||||
} else {
|
||||
parameterAccessor.assertKeyValueInstanceOf(parameterName, value, String.class);
|
||||
return new String[] { (String) value };
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T[] getArray(String parameterName, Class<T> targetElementType) throws ConversionExecutionException {
|
||||
String[] parameters = getArray(parameterName);
|
||||
return parameters != null ? convert(parameters, targetElementType) : null;
|
||||
}
|
||||
|
||||
public <T> T get(String parameterName, Class<T> targetType) throws ConversionExecutionException {
|
||||
return get(parameterName, targetType, null);
|
||||
}
|
||||
|
||||
public <T> T get(String parameterName, Class<T> targetType, T defaultValue) throws ConversionExecutionException {
|
||||
if (defaultValue != null) {
|
||||
assertAssignableTo(targetType, defaultValue.getClass());
|
||||
}
|
||||
String parameter = get(parameterName);
|
||||
return parameter != null ? convert(parameter, targetType) : defaultValue;
|
||||
}
|
||||
|
||||
public String getRequired(String parameterName) throws IllegalArgumentException {
|
||||
parameterAccessor.assertContainsKey(parameterName);
|
||||
return get(parameterName);
|
||||
}
|
||||
|
||||
public String[] getRequiredArray(String parameterName) throws IllegalArgumentException {
|
||||
parameterAccessor.assertContainsKey(parameterName);
|
||||
return getArray(parameterName);
|
||||
}
|
||||
|
||||
public <T> T[] getRequiredArray(String parameterName, Class<T> targetElementType) throws IllegalArgumentException,
|
||||
ConversionExecutionException {
|
||||
String[] parameters = getRequiredArray(parameterName);
|
||||
return convert(parameters, targetElementType);
|
||||
}
|
||||
|
||||
public <T> T getRequired(String parameterName, Class<T> targetType) throws IllegalArgumentException,
|
||||
ConversionExecutionException {
|
||||
return convert(getRequired(parameterName), targetType);
|
||||
}
|
||||
|
||||
public <T extends Number> T getNumber(String parameterName, Class<T> targetType)
|
||||
throws ConversionExecutionException {
|
||||
assertAssignableTo(Number.class, targetType);
|
||||
return get(parameterName, targetType);
|
||||
}
|
||||
|
||||
public <T extends Number> T getNumber(String parameterName, Class<T> targetType, T defaultValue)
|
||||
throws ConversionExecutionException {
|
||||
assertAssignableTo(Number.class, targetType);
|
||||
return get(parameterName, targetType, defaultValue);
|
||||
}
|
||||
|
||||
public <T extends Number> T getRequiredNumber(String parameterName, Class<T> targetType)
|
||||
throws IllegalArgumentException, ConversionExecutionException {
|
||||
assertAssignableTo(Number.class, targetType);
|
||||
return getRequired(parameterName, targetType);
|
||||
}
|
||||
|
||||
public Integer getInteger(String parameterName) throws ConversionExecutionException {
|
||||
return get(parameterName, Integer.class);
|
||||
}
|
||||
|
||||
public Integer getInteger(String parameterName, Integer defaultValue) throws ConversionExecutionException {
|
||||
return get(parameterName, Integer.class, defaultValue);
|
||||
}
|
||||
|
||||
public Integer getRequiredInteger(String parameterName) throws IllegalArgumentException,
|
||||
ConversionExecutionException {
|
||||
return getRequired(parameterName, Integer.class);
|
||||
}
|
||||
|
||||
public Long getLong(String parameterName) throws ConversionExecutionException {
|
||||
return get(parameterName, Long.class);
|
||||
}
|
||||
|
||||
public Long getLong(String parameterName, Long defaultValue) throws ConversionExecutionException {
|
||||
return get(parameterName, Long.class, defaultValue);
|
||||
}
|
||||
|
||||
public Long getRequiredLong(String parameterName) throws IllegalArgumentException, ConversionExecutionException {
|
||||
return getRequired(parameterName, Long.class);
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String parameterName) throws ConversionExecutionException {
|
||||
return get(parameterName, Boolean.class);
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String parameterName, Boolean defaultValue) throws ConversionExecutionException {
|
||||
return get(parameterName, Boolean.class, defaultValue);
|
||||
}
|
||||
|
||||
public Boolean getRequiredBoolean(String parameterName) throws IllegalArgumentException,
|
||||
ConversionExecutionException {
|
||||
return getRequired(parameterName, Boolean.class);
|
||||
}
|
||||
|
||||
public MultipartFile getMultipartFile(String parameterName) {
|
||||
return parameterAccessor.get(parameterName, MultipartFile.class);
|
||||
}
|
||||
|
||||
public MultipartFile getRequiredMultipartFile(String parameterName) throws IllegalArgumentException {
|
||||
return parameterAccessor.getRequired(parameterName, MultipartFile.class);
|
||||
}
|
||||
|
||||
public AttributeMap<Object> asAttributeMap() {
|
||||
return new LocalAttributeMap<>(getMapInternal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this parameter map.
|
||||
* @param parameters the parameters
|
||||
*/
|
||||
protected void initParameters(Map<String, Object> parameters) {
|
||||
this.parameters = parameters;
|
||||
parameterAccessor = new MapAccessor<>(this.parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the wrapped, modifiable map implementation.
|
||||
*/
|
||||
protected Map<String, Object> getMapInternal() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
/**
|
||||
* Convert given String parameter to specified target type.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T convert(String parameter, Class<T> targetType) throws ConversionExecutionException {
|
||||
return (T) conversionService.getConversionExecutor(String.class, targetType).execute(parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert given array of String parameters to specified target type and return the resulting array.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T[] convert(String[] parameters, Class<? extends T> targetElementType)
|
||||
throws ConversionExecutionException {
|
||||
List<T> list = new ArrayList<>(parameters.length);
|
||||
ConversionExecutor converter = conversionService.getConversionExecutor(String.class, targetElementType);
|
||||
for (String parameter : parameters) {
|
||||
list.add((T) converter.execute(parameter));
|
||||
}
|
||||
return list.toArray((T[]) Array.newInstance(targetElementType, parameters.length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure clazz is assignable from requiredType.
|
||||
*/
|
||||
private void assertAssignableTo(Class<?> clazz, Class<?> requiredType) {
|
||||
Assert.isTrue(clazz.isAssignableFrom(requiredType), "The provided required type must be assignable to ["
|
||||
+ clazz + "]");
|
||||
}
|
||||
|
||||
// custom serialization
|
||||
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
out.defaultWriteObject();
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
parameterAccessor = new MapAccessor<>(parameters);
|
||||
conversionService = DEFAULT_CONVERSION_SERVICE;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return StylerUtils.style(parameters);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
import org.springframework.binding.collection.SharedMap;
|
||||
|
||||
/**
|
||||
* An attribute map that exposes a mutex that application code can synchronize on. This class wraps another shared map
|
||||
* in an attribute map.
|
||||
* <p>
|
||||
* The mutex can be used to serialize concurrent access to the shared map's contents by multiple threads.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class LocalSharedAttributeMap<V> extends LocalAttributeMap<V> implements SharedAttributeMap<V> {
|
||||
|
||||
/**
|
||||
* Creates a new shared attribute map.
|
||||
* @param sharedMap the shared map
|
||||
*/
|
||||
public LocalSharedAttributeMap(SharedMap<String, V> sharedMap) {
|
||||
super(sharedMap);
|
||||
}
|
||||
|
||||
public Object getMutex() {
|
||||
return getSharedMap().getMutex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the wrapped shared map.
|
||||
*/
|
||||
protected SharedMap<String, V> getSharedMap() {
|
||||
return (SharedMap<String, V>) getMapInternal();
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
import org.springframework.binding.collection.SharedMap;
|
||||
|
||||
/**
|
||||
* An attribute map that exposes a mutex that application code can synchronize on. This class wraps another shared map
|
||||
* in an attribute map.
|
||||
* <p>
|
||||
* The mutex can be used to serialize concurrent access to the shared map's contents by multiple threads.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class LocalSharedAttributeMap<V> extends LocalAttributeMap<V> implements SharedAttributeMap<V> {
|
||||
|
||||
/**
|
||||
* Creates a new shared attribute map.
|
||||
* @param sharedMap the shared map
|
||||
*/
|
||||
public LocalSharedAttributeMap(SharedMap<String, V> sharedMap) {
|
||||
super(sharedMap);
|
||||
}
|
||||
|
||||
public Object getMutex() {
|
||||
return getSharedMap().getMutex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the wrapped shared map.
|
||||
*/
|
||||
protected SharedMap<String, V> getSharedMap() {
|
||||
return (SharedMap<String, V>) getMapInternal();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,84 +1,84 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
/**
|
||||
* An interface for accessing and modifying attributes in a backing map with string keys.
|
||||
* <p>
|
||||
* Implementations can optionally support {@link AttributeMapBindingListener listeners} that will be notified when
|
||||
* they're bound in or unbound from the map.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface MutableAttributeMap<V> extends AttributeMap<V> {
|
||||
|
||||
/**
|
||||
* Put the attribute into this map.
|
||||
* <p>
|
||||
* If the attribute value is an {@link AttributeMapBindingListener} this map will publish
|
||||
* {@link AttributeMapBindingEvent binding events} such as on "bind" and "unbind" if supported.
|
||||
* <p>
|
||||
* <b>Note</b>: not all <code>MutableAttributeMap</code> implementations support this.
|
||||
* @param attributeName the attribute name
|
||||
* @param attributeValue the attribute value
|
||||
* @return the previous value of the attribute, or <code>null</code> of there was no previous value
|
||||
*/
|
||||
V put(String attributeName, V attributeValue);
|
||||
|
||||
/**
|
||||
* Put all the attributes into this map.
|
||||
* @param attributes the attributes to put into this map
|
||||
* @return this, to support call chaining
|
||||
*/
|
||||
MutableAttributeMap<V> putAll(AttributeMap<? extends V> attributes);
|
||||
|
||||
/**
|
||||
* Remove all attributes in the map provided from this map.
|
||||
* @param attributes the attributes to remove from this map
|
||||
* @return this, to support call chaining
|
||||
*/
|
||||
MutableAttributeMap<V> removeAll(MutableAttributeMap<? extends V> attributes);
|
||||
|
||||
/**
|
||||
* Remove an attribute from this map.
|
||||
* @param attributeName the name of the attribute to remove
|
||||
* @return previous value associated with specified attribute name, or <tt>null</tt> if there was no mapping for the
|
||||
* name
|
||||
*/
|
||||
Object remove(String attributeName);
|
||||
|
||||
/**
|
||||
* Extract an attribute from this map, getting it and removing it in a single operation.
|
||||
* @param attributeName the attribute name
|
||||
* @return the value of the attribute, or <code>null</code> of there was no value
|
||||
*/
|
||||
Object extract(String attributeName);
|
||||
|
||||
/**
|
||||
* Remove all attributes in this map.
|
||||
* @return this, to support call chaining
|
||||
*/
|
||||
MutableAttributeMap<V> clear();
|
||||
|
||||
/**
|
||||
* Replace the contents of this attribute map with the contents of the provided collection.
|
||||
* @param attributes the attribute collection
|
||||
* @return this, to support call chaining
|
||||
*/
|
||||
MutableAttributeMap<V> replaceWith(AttributeMap<? extends V> attributes)
|
||||
throws UnsupportedOperationException;
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
/**
|
||||
* An interface for accessing and modifying attributes in a backing map with string keys.
|
||||
* <p>
|
||||
* Implementations can optionally support {@link AttributeMapBindingListener listeners} that will be notified when
|
||||
* they're bound in or unbound from the map.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface MutableAttributeMap<V> extends AttributeMap<V> {
|
||||
|
||||
/**
|
||||
* Put the attribute into this map.
|
||||
* <p>
|
||||
* If the attribute value is an {@link AttributeMapBindingListener} this map will publish
|
||||
* {@link AttributeMapBindingEvent binding events} such as on "bind" and "unbind" if supported.
|
||||
* <p>
|
||||
* <b>Note</b>: not all <code>MutableAttributeMap</code> implementations support this.
|
||||
* @param attributeName the attribute name
|
||||
* @param attributeValue the attribute value
|
||||
* @return the previous value of the attribute, or <code>null</code> of there was no previous value
|
||||
*/
|
||||
V put(String attributeName, V attributeValue);
|
||||
|
||||
/**
|
||||
* Put all the attributes into this map.
|
||||
* @param attributes the attributes to put into this map
|
||||
* @return this, to support call chaining
|
||||
*/
|
||||
MutableAttributeMap<V> putAll(AttributeMap<? extends V> attributes);
|
||||
|
||||
/**
|
||||
* Remove all attributes in the map provided from this map.
|
||||
* @param attributes the attributes to remove from this map
|
||||
* @return this, to support call chaining
|
||||
*/
|
||||
MutableAttributeMap<V> removeAll(MutableAttributeMap<? extends V> attributes);
|
||||
|
||||
/**
|
||||
* Remove an attribute from this map.
|
||||
* @param attributeName the name of the attribute to remove
|
||||
* @return previous value associated with specified attribute name, or <tt>null</tt> if there was no mapping for the
|
||||
* name
|
||||
*/
|
||||
Object remove(String attributeName);
|
||||
|
||||
/**
|
||||
* Extract an attribute from this map, getting it and removing it in a single operation.
|
||||
* @param attributeName the attribute name
|
||||
* @return the value of the attribute, or <code>null</code> of there was no value
|
||||
*/
|
||||
Object extract(String attributeName);
|
||||
|
||||
/**
|
||||
* Remove all attributes in this map.
|
||||
* @return this, to support call chaining
|
||||
*/
|
||||
MutableAttributeMap<V> clear();
|
||||
|
||||
/**
|
||||
* Replace the contents of this attribute map with the contents of the provided collection.
|
||||
* @param attributes the attribute collection
|
||||
* @return this, to support call chaining
|
||||
*/
|
||||
MutableAttributeMap<V> replaceWith(AttributeMap<? extends V> attributes)
|
||||
throws UnsupportedOperationException;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,279 +1,279 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
import org.springframework.binding.collection.MapAdaptable;
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* An interface for accessing parameters in a backing map. Parameters are immutable and have string keys and string
|
||||
* values.
|
||||
* <p>
|
||||
* The accessor methods offered by this class taking a target type argument only need to support conversions to well
|
||||
* know types like String, Number subclasses, Boolean and so on.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface ParameterMap extends MapAdaptable<String, Object> {
|
||||
|
||||
/**
|
||||
* Is this parameter map empty, with a size of 0?
|
||||
* @return true if empty, false if not
|
||||
*/
|
||||
boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Returns the number of parameters in this map.
|
||||
* @return the parameter count
|
||||
*/
|
||||
int size();
|
||||
|
||||
/**
|
||||
* Does the parameter with the provided name exist in this map?
|
||||
* @param parameterName the parameter name
|
||||
* @return true if so, false otherwise
|
||||
*/
|
||||
boolean contains(String parameterName);
|
||||
|
||||
/**
|
||||
* Get a parameter value, returning <code>null</code> if no value is found.
|
||||
* @param parameterName the parameter name
|
||||
* @return the parameter value
|
||||
*/
|
||||
String get(String parameterName);
|
||||
|
||||
/**
|
||||
* Get a parameter value, returning the defaultValue if no value is found.
|
||||
* @param parameterName the parameter name
|
||||
* @param defaultValue the default
|
||||
* @return the parameter value
|
||||
*/
|
||||
String get(String parameterName, String defaultValue);
|
||||
|
||||
/**
|
||||
* Get a multi-valued parameter value, returning <code>null</code> if no value is found. If the parameter is single
|
||||
* valued an array with a single element is returned.
|
||||
* @param parameterName the parameter name
|
||||
* @return the parameter value array
|
||||
*/
|
||||
String[] getArray(String parameterName);
|
||||
|
||||
/**
|
||||
* Get a multi-valued parameter value, converting each value to the target type or returning <code>null</code> if no
|
||||
* value is found.
|
||||
* @param parameterName the parameter name
|
||||
* @param targetElementType the target type of the array's elements
|
||||
* @return the converterd parameter value array
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
<T> T[] getArray(String parameterName, Class<T> targetElementType) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Get a parameter value, converting it from <code>String</code> to the target type.
|
||||
* @param parameterName the name of the parameter
|
||||
* @param targetType the target type of the parameter value
|
||||
* @return the converted parameter value, or null if not found
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
<T> T get(String parameterName, Class<T> targetType) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Get a parameter value, converting it from <code>String</code> to the target type or returning the defaultValue if
|
||||
* not found.
|
||||
* @param parameterName name of the parameter to get
|
||||
* @param targetType the target type of the parameter value
|
||||
* @param defaultValue the default value
|
||||
* @return the converted parameter value, or the default if not found
|
||||
* @throws ConversionExecutionException when a value could not be converted
|
||||
*/
|
||||
<T> T get(String parameterName, Class<T> targetType, T defaultValue) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Get the value of a required parameter.
|
||||
* @param parameterName the name of the parameter
|
||||
* @return the parameter value
|
||||
* @throws IllegalArgumentException when the parameter is not found
|
||||
*/
|
||||
String getRequired(String parameterName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get a required multi-valued parameter value.
|
||||
* @param parameterName the name of the parameter
|
||||
* @return the parameter value
|
||||
* @throws IllegalArgumentException when the parameter is not found
|
||||
*/
|
||||
String[] getRequiredArray(String parameterName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get a required multi-valued parameter value, converting each value to the target type.
|
||||
* @param parameterName the name of the parameter
|
||||
* @return the parameter value
|
||||
* @throws IllegalArgumentException when the parameter is not found
|
||||
* @throws ConversionExecutionException when a value could not be converted
|
||||
*/
|
||||
<T> T[] getRequiredArray(String parameterName, Class<T> targetElementType) throws IllegalArgumentException,
|
||||
ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Get the value of a required parameter and convert it to the target type.
|
||||
* @param parameterName the name of the parameter
|
||||
* @param targetType the target type of the parameter value
|
||||
* @return the converted parameter value
|
||||
* @throws IllegalArgumentException when the parameter is not found
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
<T> T getRequired(String parameterName, Class<T> targetType) throws IllegalArgumentException,
|
||||
ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a number parameter value in the map that is of the specified type, returning <code>null</code> if no
|
||||
* value was found.
|
||||
* @param parameterName the parameter name
|
||||
* @param targetType the target number type
|
||||
* @return the number parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
<T extends Number> T getNumber(String parameterName, Class<T> targetType)
|
||||
throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a number parameter value in the map of the specified type, returning the defaultValue if no value was
|
||||
* found.
|
||||
* @param parameterName the parameter name
|
||||
* @param defaultValue the default
|
||||
* @return the number parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
<T extends Number> T getNumber(String parameterName, Class<T> targetType, T defaultValue)
|
||||
throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a number parameter value in the map, throwing an exception if the parameter is not present or could not
|
||||
* be converted.
|
||||
* @param parameterName the parameter name
|
||||
* @return the number parameter value
|
||||
* @throws IllegalArgumentException if the parameter is not present
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
<T extends Number> T getRequiredNumber(String parameterName, Class<T> targetType)
|
||||
throws IllegalArgumentException, ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns an integer parameter value in the map, returning <code>null</code> if no value was found.
|
||||
* @param parameterName the parameter name
|
||||
* @return the integer parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Integer getInteger(String parameterName) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns an integer parameter value in the map, returning the defaultValue if no value was found.
|
||||
* @param parameterName the parameter name
|
||||
* @param defaultValue the default
|
||||
* @return the integer parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Integer getInteger(String parameterName, Integer defaultValue) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns an integer parameter value in the map, throwing an exception if the parameter is not present or could not
|
||||
* be converted.
|
||||
* @param parameterName the parameter name
|
||||
* @return the integer parameter value
|
||||
* @throws IllegalArgumentException if the parameter is not present
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Integer getRequiredInteger(String parameterName) throws IllegalArgumentException,
|
||||
ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a long parameter value in the map, returning <code>null</code> if no value was found.
|
||||
* @param parameterName the parameter name
|
||||
* @return the long parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Long getLong(String parameterName) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a long parameter value in the map, returning the defaultValue if no value was found.
|
||||
* @param parameterName the parameter name
|
||||
* @param defaultValue the default
|
||||
* @return the long parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Long getLong(String parameterName, Long defaultValue) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a long parameter value in the map, throwing an exception if the parameter is not present or could not be
|
||||
* converted.
|
||||
* @param parameterName the parameter name
|
||||
* @return the long parameter value
|
||||
* @throws IllegalArgumentException if the parameter is not present
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Long getRequiredLong(String parameterName) throws IllegalArgumentException, ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a boolean parameter value in the map, returning <code>null</code> if no value was found.
|
||||
* @param parameterName the parameter name
|
||||
* @return the long parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Boolean getBoolean(String parameterName) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a boolean parameter value in the map, returning the defaultValue if no value was found.
|
||||
* @param parameterName the parameter name
|
||||
* @param defaultValue the default
|
||||
* @return the boolean parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Boolean getBoolean(String parameterName, Boolean defaultValue) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a boolean parameter value in the map, throwing an exception if the parameter is not present or could not
|
||||
* be converted.
|
||||
* @param parameterName the parameter name
|
||||
* @return the boolean parameter value
|
||||
* @throws IllegalArgumentException if the parameter is not present
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Boolean getRequiredBoolean(String parameterName) throws IllegalArgumentException,
|
||||
ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Get a multi-part file parameter value, returning <code>null</code> if no value is found.
|
||||
* @param parameterName the parameter name
|
||||
* @return the multipart file
|
||||
*/
|
||||
MultipartFile getMultipartFile(String parameterName);
|
||||
|
||||
/**
|
||||
* Get the value of a required multipart file parameter.
|
||||
* @param parameterName the name of the parameter
|
||||
* @return the parameter value
|
||||
* @throws IllegalArgumentException when the parameter is not found
|
||||
*/
|
||||
MultipartFile getRequiredMultipartFile(String parameterName);
|
||||
|
||||
/**
|
||||
* Adapts this parameter map to an {@link AttributeMap}.
|
||||
* @return the underlying map as a unmodifiable attribute map
|
||||
*/
|
||||
AttributeMap<Object> asAttributeMap();
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
import org.springframework.binding.collection.MapAdaptable;
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* An interface for accessing parameters in a backing map. Parameters are immutable and have string keys and string
|
||||
* values.
|
||||
* <p>
|
||||
* The accessor methods offered by this class taking a target type argument only need to support conversions to well
|
||||
* know types like String, Number subclasses, Boolean and so on.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface ParameterMap extends MapAdaptable<String, Object> {
|
||||
|
||||
/**
|
||||
* Is this parameter map empty, with a size of 0?
|
||||
* @return true if empty, false if not
|
||||
*/
|
||||
boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Returns the number of parameters in this map.
|
||||
* @return the parameter count
|
||||
*/
|
||||
int size();
|
||||
|
||||
/**
|
||||
* Does the parameter with the provided name exist in this map?
|
||||
* @param parameterName the parameter name
|
||||
* @return true if so, false otherwise
|
||||
*/
|
||||
boolean contains(String parameterName);
|
||||
|
||||
/**
|
||||
* Get a parameter value, returning <code>null</code> if no value is found.
|
||||
* @param parameterName the parameter name
|
||||
* @return the parameter value
|
||||
*/
|
||||
String get(String parameterName);
|
||||
|
||||
/**
|
||||
* Get a parameter value, returning the defaultValue if no value is found.
|
||||
* @param parameterName the parameter name
|
||||
* @param defaultValue the default
|
||||
* @return the parameter value
|
||||
*/
|
||||
String get(String parameterName, String defaultValue);
|
||||
|
||||
/**
|
||||
* Get a multi-valued parameter value, returning <code>null</code> if no value is found. If the parameter is single
|
||||
* valued an array with a single element is returned.
|
||||
* @param parameterName the parameter name
|
||||
* @return the parameter value array
|
||||
*/
|
||||
String[] getArray(String parameterName);
|
||||
|
||||
/**
|
||||
* Get a multi-valued parameter value, converting each value to the target type or returning <code>null</code> if no
|
||||
* value is found.
|
||||
* @param parameterName the parameter name
|
||||
* @param targetElementType the target type of the array's elements
|
||||
* @return the converterd parameter value array
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
<T> T[] getArray(String parameterName, Class<T> targetElementType) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Get a parameter value, converting it from <code>String</code> to the target type.
|
||||
* @param parameterName the name of the parameter
|
||||
* @param targetType the target type of the parameter value
|
||||
* @return the converted parameter value, or null if not found
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
<T> T get(String parameterName, Class<T> targetType) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Get a parameter value, converting it from <code>String</code> to the target type or returning the defaultValue if
|
||||
* not found.
|
||||
* @param parameterName name of the parameter to get
|
||||
* @param targetType the target type of the parameter value
|
||||
* @param defaultValue the default value
|
||||
* @return the converted parameter value, or the default if not found
|
||||
* @throws ConversionExecutionException when a value could not be converted
|
||||
*/
|
||||
<T> T get(String parameterName, Class<T> targetType, T defaultValue) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Get the value of a required parameter.
|
||||
* @param parameterName the name of the parameter
|
||||
* @return the parameter value
|
||||
* @throws IllegalArgumentException when the parameter is not found
|
||||
*/
|
||||
String getRequired(String parameterName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get a required multi-valued parameter value.
|
||||
* @param parameterName the name of the parameter
|
||||
* @return the parameter value
|
||||
* @throws IllegalArgumentException when the parameter is not found
|
||||
*/
|
||||
String[] getRequiredArray(String parameterName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get a required multi-valued parameter value, converting each value to the target type.
|
||||
* @param parameterName the name of the parameter
|
||||
* @return the parameter value
|
||||
* @throws IllegalArgumentException when the parameter is not found
|
||||
* @throws ConversionExecutionException when a value could not be converted
|
||||
*/
|
||||
<T> T[] getRequiredArray(String parameterName, Class<T> targetElementType) throws IllegalArgumentException,
|
||||
ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Get the value of a required parameter and convert it to the target type.
|
||||
* @param parameterName the name of the parameter
|
||||
* @param targetType the target type of the parameter value
|
||||
* @return the converted parameter value
|
||||
* @throws IllegalArgumentException when the parameter is not found
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
<T> T getRequired(String parameterName, Class<T> targetType) throws IllegalArgumentException,
|
||||
ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a number parameter value in the map that is of the specified type, returning <code>null</code> if no
|
||||
* value was found.
|
||||
* @param parameterName the parameter name
|
||||
* @param targetType the target number type
|
||||
* @return the number parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
<T extends Number> T getNumber(String parameterName, Class<T> targetType)
|
||||
throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a number parameter value in the map of the specified type, returning the defaultValue if no value was
|
||||
* found.
|
||||
* @param parameterName the parameter name
|
||||
* @param defaultValue the default
|
||||
* @return the number parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
<T extends Number> T getNumber(String parameterName, Class<T> targetType, T defaultValue)
|
||||
throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a number parameter value in the map, throwing an exception if the parameter is not present or could not
|
||||
* be converted.
|
||||
* @param parameterName the parameter name
|
||||
* @return the number parameter value
|
||||
* @throws IllegalArgumentException if the parameter is not present
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
<T extends Number> T getRequiredNumber(String parameterName, Class<T> targetType)
|
||||
throws IllegalArgumentException, ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns an integer parameter value in the map, returning <code>null</code> if no value was found.
|
||||
* @param parameterName the parameter name
|
||||
* @return the integer parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Integer getInteger(String parameterName) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns an integer parameter value in the map, returning the defaultValue if no value was found.
|
||||
* @param parameterName the parameter name
|
||||
* @param defaultValue the default
|
||||
* @return the integer parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Integer getInteger(String parameterName, Integer defaultValue) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns an integer parameter value in the map, throwing an exception if the parameter is not present or could not
|
||||
* be converted.
|
||||
* @param parameterName the parameter name
|
||||
* @return the integer parameter value
|
||||
* @throws IllegalArgumentException if the parameter is not present
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Integer getRequiredInteger(String parameterName) throws IllegalArgumentException,
|
||||
ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a long parameter value in the map, returning <code>null</code> if no value was found.
|
||||
* @param parameterName the parameter name
|
||||
* @return the long parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Long getLong(String parameterName) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a long parameter value in the map, returning the defaultValue if no value was found.
|
||||
* @param parameterName the parameter name
|
||||
* @param defaultValue the default
|
||||
* @return the long parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Long getLong(String parameterName, Long defaultValue) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a long parameter value in the map, throwing an exception if the parameter is not present or could not be
|
||||
* converted.
|
||||
* @param parameterName the parameter name
|
||||
* @return the long parameter value
|
||||
* @throws IllegalArgumentException if the parameter is not present
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Long getRequiredLong(String parameterName) throws IllegalArgumentException, ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a boolean parameter value in the map, returning <code>null</code> if no value was found.
|
||||
* @param parameterName the parameter name
|
||||
* @return the long parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Boolean getBoolean(String parameterName) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a boolean parameter value in the map, returning the defaultValue if no value was found.
|
||||
* @param parameterName the parameter name
|
||||
* @param defaultValue the default
|
||||
* @return the boolean parameter value
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Boolean getBoolean(String parameterName, Boolean defaultValue) throws ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Returns a boolean parameter value in the map, throwing an exception if the parameter is not present or could not
|
||||
* be converted.
|
||||
* @param parameterName the parameter name
|
||||
* @return the boolean parameter value
|
||||
* @throws IllegalArgumentException if the parameter is not present
|
||||
* @throws ConversionExecutionException when the value could not be converted
|
||||
*/
|
||||
Boolean getRequiredBoolean(String parameterName) throws IllegalArgumentException,
|
||||
ConversionExecutionException;
|
||||
|
||||
/**
|
||||
* Get a multi-part file parameter value, returning <code>null</code> if no value is found.
|
||||
* @param parameterName the parameter name
|
||||
* @return the multipart file
|
||||
*/
|
||||
MultipartFile getMultipartFile(String parameterName);
|
||||
|
||||
/**
|
||||
* Get the value of a required multipart file parameter.
|
||||
* @param parameterName the name of the parameter
|
||||
* @return the parameter value
|
||||
* @throws IllegalArgumentException when the parameter is not found
|
||||
*/
|
||||
MultipartFile getRequiredMultipartFile(String parameterName);
|
||||
|
||||
/**
|
||||
* Adapts this parameter map to an {@link AttributeMap}.
|
||||
* @return the underlying map as a unmodifiable attribute map
|
||||
*/
|
||||
AttributeMap<Object> asAttributeMap();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
/**
|
||||
* An interface to be implemented by mutable attribute maps accessed by multiple threads that need to be synchronized.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface SharedAttributeMap<V> extends MutableAttributeMap<V> {
|
||||
|
||||
/**
|
||||
* Returns the shared map's mutex, which may be synchronized on to block access to the map by other threads.
|
||||
*/
|
||||
Object getMutex();
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.core.collection;
|
||||
|
||||
/**
|
||||
* An interface to be implemented by mutable attribute maps accessed by multiple threads that need to be synchronized.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface SharedAttributeMap<V> extends MutableAttributeMap<V> {
|
||||
|
||||
/**
|
||||
* Returns the shared map's mutex, which may be synchronized on to block access to the map by other threads.
|
||||
*/
|
||||
Object getMutex();
|
||||
}
|
||||
|
||||
@@ -1,95 +1,95 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.webflow.core.Annotated;
|
||||
|
||||
/**
|
||||
* The definition of a flow, a program that when executed carries out a task on behalf of a single client.
|
||||
* <p>
|
||||
* A flow definition is a reusable, self-contained controller module that defines a blue print for an executable user
|
||||
* task. Flows typically orchestrate controlled navigations or dialogs within web applications to guide users through
|
||||
* fulfillment of a business process/goal that takes place over a series of steps, modeled as states.
|
||||
* <p>
|
||||
* Structurally a flow definition is composed of a set of states. A {@link StateDefinition state} is a point in a flow
|
||||
* where a behavior is executed; for example, showing a view, executing an action, spawning a subflow, or terminating
|
||||
* the flow. Different types of states execute different behaviors in a polymorphic fashion. Most states are
|
||||
* {@link TransitionableStateDefinition transitionable states}, meaning they can respond to events by taking the flow
|
||||
* from one state to another.
|
||||
* <p>
|
||||
* Each flow has exactly one {@link #getStartState() start state} which defines the starting point of the program.
|
||||
* <p>
|
||||
* This interface exposes the flow's identifier, states, and other definitional attributes. It is suitable for
|
||||
* introspection by tools as well as user-code at flow execution time.
|
||||
* <p>
|
||||
* Flow definitions may be annotated with attributes.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface FlowDefinition extends Annotated {
|
||||
|
||||
/**
|
||||
* Returns the unique id of this flow.
|
||||
* @return the flow id
|
||||
*/
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* Return this flow's starting point.
|
||||
* @return the start state
|
||||
*/
|
||||
StateDefinition getStartState();
|
||||
|
||||
/**
|
||||
* Returns the state definition with the specified id.
|
||||
* @param id the state id
|
||||
* @return the state definition
|
||||
* @throws IllegalArgumentException if a state with this id does not exist
|
||||
*/
|
||||
StateDefinition getState(String id) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns the outcomes that are possible for this flow to reach.
|
||||
* @return the possible outcomes
|
||||
*/
|
||||
String[] getPossibleOutcomes();
|
||||
|
||||
/**
|
||||
* Returns the class loader used by this flow definition to load classes.
|
||||
* @return the class loader
|
||||
*/
|
||||
ClassLoader getClassLoader();
|
||||
|
||||
/**
|
||||
* Returns a reference to application context hosting application objects and services used by this flow definition.
|
||||
* @return the application context
|
||||
*/
|
||||
ApplicationContext getApplicationContext();
|
||||
|
||||
/**
|
||||
* Returns true if this flow definition is currently in development (running in development mode).
|
||||
* @return the development flag
|
||||
*/
|
||||
boolean inDevelopment();
|
||||
|
||||
/**
|
||||
* Destroy this flow definition, releasing any resources. After the flow is destroyed it cannot be started again.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.webflow.core.Annotated;
|
||||
|
||||
/**
|
||||
* The definition of a flow, a program that when executed carries out a task on behalf of a single client.
|
||||
* <p>
|
||||
* A flow definition is a reusable, self-contained controller module that defines a blue print for an executable user
|
||||
* task. Flows typically orchestrate controlled navigations or dialogs within web applications to guide users through
|
||||
* fulfillment of a business process/goal that takes place over a series of steps, modeled as states.
|
||||
* <p>
|
||||
* Structurally a flow definition is composed of a set of states. A {@link StateDefinition state} is a point in a flow
|
||||
* where a behavior is executed; for example, showing a view, executing an action, spawning a subflow, or terminating
|
||||
* the flow. Different types of states execute different behaviors in a polymorphic fashion. Most states are
|
||||
* {@link TransitionableStateDefinition transitionable states}, meaning they can respond to events by taking the flow
|
||||
* from one state to another.
|
||||
* <p>
|
||||
* Each flow has exactly one {@link #getStartState() start state} which defines the starting point of the program.
|
||||
* <p>
|
||||
* This interface exposes the flow's identifier, states, and other definitional attributes. It is suitable for
|
||||
* introspection by tools as well as user-code at flow execution time.
|
||||
* <p>
|
||||
* Flow definitions may be annotated with attributes.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface FlowDefinition extends Annotated {
|
||||
|
||||
/**
|
||||
* Returns the unique id of this flow.
|
||||
* @return the flow id
|
||||
*/
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* Return this flow's starting point.
|
||||
* @return the start state
|
||||
*/
|
||||
StateDefinition getStartState();
|
||||
|
||||
/**
|
||||
* Returns the state definition with the specified id.
|
||||
* @param id the state id
|
||||
* @return the state definition
|
||||
* @throws IllegalArgumentException if a state with this id does not exist
|
||||
*/
|
||||
StateDefinition getState(String id) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns the outcomes that are possible for this flow to reach.
|
||||
* @return the possible outcomes
|
||||
*/
|
||||
String[] getPossibleOutcomes();
|
||||
|
||||
/**
|
||||
* Returns the class loader used by this flow definition to load classes.
|
||||
* @return the class loader
|
||||
*/
|
||||
ClassLoader getClassLoader();
|
||||
|
||||
/**
|
||||
* Returns a reference to application context hosting application objects and services used by this flow definition.
|
||||
* @return the application context
|
||||
*/
|
||||
ApplicationContext getApplicationContext();
|
||||
|
||||
/**
|
||||
* Returns true if this flow definition is currently in development (running in development mode).
|
||||
* @return the development flag
|
||||
*/
|
||||
boolean inDevelopment();
|
||||
|
||||
/**
|
||||
* Destroy this flow definition, releasing any resources. After the flow is destroyed it cannot be started again.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
}
|
||||
@@ -1,48 +1,48 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.core.Annotated;
|
||||
|
||||
/**
|
||||
* A step within a {@link FlowDefinition flow definition} where behavior is executed.
|
||||
* <p>
|
||||
* States have identifiers that are local to their containing flow definitions. They may also be annotated with
|
||||
* attributes.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface StateDefinition extends Annotated {
|
||||
|
||||
/**
|
||||
* Returns the flow definition this state belongs to.
|
||||
* @return the owning flow definition
|
||||
*/
|
||||
FlowDefinition getOwner();
|
||||
|
||||
/**
|
||||
* Returns this state's identifier, locally unique to is containing flow definition.
|
||||
* @return the state identifier
|
||||
*/
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* Returns true if this state is a view state.
|
||||
* @return true if a view state, false otherwise
|
||||
*/
|
||||
boolean isViewState();
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.core.Annotated;
|
||||
|
||||
/**
|
||||
* A step within a {@link FlowDefinition flow definition} where behavior is executed.
|
||||
* <p>
|
||||
* States have identifiers that are local to their containing flow definitions. They may also be annotated with
|
||||
* attributes.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface StateDefinition extends Annotated {
|
||||
|
||||
/**
|
||||
* Returns the flow definition this state belongs to.
|
||||
* @return the owning flow definition
|
||||
*/
|
||||
FlowDefinition getOwner();
|
||||
|
||||
/**
|
||||
* Returns this state's identifier, locally unique to is containing flow definition.
|
||||
* @return the state identifier
|
||||
*/
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* Returns true if this state is a view state.
|
||||
* @return true if a view state, false otherwise
|
||||
*/
|
||||
boolean isViewState();
|
||||
}
|
||||
@@ -1,41 +1,41 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.core.Annotated;
|
||||
|
||||
/**
|
||||
* A transition takes a flow from one state to another.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface TransitionDefinition extends Annotated {
|
||||
|
||||
/**
|
||||
* The identifier of this transition. This id value should be unique among all other transitions in a set.
|
||||
* @return the transition identifier
|
||||
*/
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* Returns an identification of the target state of this transition. This could be an actual static state id or
|
||||
* something more dynamic, like a string representation of an expression evaluating the target state id at flow
|
||||
* execution time.
|
||||
* @return the target state identifier
|
||||
*/
|
||||
String getTargetStateId();
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.core.Annotated;
|
||||
|
||||
/**
|
||||
* A transition takes a flow from one state to another.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface TransitionDefinition extends Annotated {
|
||||
|
||||
/**
|
||||
* The identifier of this transition. This id value should be unique among all other transitions in a set.
|
||||
* @return the transition identifier
|
||||
*/
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* Returns an identification of the target state of this transition. This could be an actual static state id or
|
||||
* something more dynamic, like a string representation of an expression evaluating the target state id at flow
|
||||
* execution time.
|
||||
* @return the target state identifier
|
||||
*/
|
||||
String getTargetStateId();
|
||||
}
|
||||
@@ -1,38 +1,38 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
/**
|
||||
* A state that can transition to another state.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface TransitionableStateDefinition extends StateDefinition {
|
||||
|
||||
/**
|
||||
* Returns the available transitions out of this state.
|
||||
* @return the available state transitions
|
||||
*/
|
||||
TransitionDefinition[] getTransitions();
|
||||
|
||||
/**
|
||||
* Returns the transition that matches the event with the provided id.
|
||||
* @param eventId the event id
|
||||
* @return the transition that matches, or null if no match is found.
|
||||
*/
|
||||
TransitionDefinition getTransition(String eventId);
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
/**
|
||||
* A state that can transition to another state.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface TransitionableStateDefinition extends StateDefinition {
|
||||
|
||||
/**
|
||||
* Returns the available transitions out of this state.
|
||||
* @return the available state transitions
|
||||
*/
|
||||
TransitionDefinition[] getTransitions();
|
||||
|
||||
/**
|
||||
* Returns the transition that matches the event with the provided id.
|
||||
* @param eventId the event id
|
||||
* @return the transition that matches, or null if no match is found.
|
||||
*/
|
||||
TransitionDefinition getTransition(String eventId);
|
||||
}
|
||||
@@ -1,50 +1,50 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.core.FlowException;
|
||||
|
||||
/**
|
||||
* Thrown when a flow definition was found during a lookup operation but could not be constructed.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class FlowDefinitionConstructionException extends FlowException {
|
||||
|
||||
/**
|
||||
* The id of the flow that could not be constructed.
|
||||
*/
|
||||
private String flowDefinitionId;
|
||||
|
||||
/**
|
||||
* Creates an exception indicating a flow definition could not be constructed.
|
||||
* @param flowDefinitionId the flow definition identifier
|
||||
* @param cause the underlying cause of the exception
|
||||
*/
|
||||
public FlowDefinitionConstructionException(String flowDefinitionId, Throwable cause) {
|
||||
super("An exception occurred constructing the flow '" + flowDefinitionId + "'", cause);
|
||||
this.flowDefinitionId = flowDefinitionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id of the flow definition that could not be constructed.
|
||||
* @return the flow id
|
||||
*/
|
||||
public String getFlowDefinitionId() {
|
||||
return flowDefinitionId;
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.core.FlowException;
|
||||
|
||||
/**
|
||||
* Thrown when a flow definition was found during a lookup operation but could not be constructed.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class FlowDefinitionConstructionException extends FlowException {
|
||||
|
||||
/**
|
||||
* The id of the flow that could not be constructed.
|
||||
*/
|
||||
private String flowDefinitionId;
|
||||
|
||||
/**
|
||||
* Creates an exception indicating a flow definition could not be constructed.
|
||||
* @param flowDefinitionId the flow definition identifier
|
||||
* @param cause the underlying cause of the exception
|
||||
*/
|
||||
public FlowDefinitionConstructionException(String flowDefinitionId, Throwable cause) {
|
||||
super("An exception occurred constructing the flow '" + flowDefinitionId + "'", cause);
|
||||
this.flowDefinitionId = flowDefinitionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id of the flow definition that could not be constructed.
|
||||
* @return the flow id
|
||||
*/
|
||||
public String getFlowDefinitionId() {
|
||||
return flowDefinitionId;
|
||||
}
|
||||
}
|
||||
@@ -1,66 +1,66 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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 holder holding a reference to a Flow definition. Provides a layer of indirection, enabling things like
|
||||
* "hot-reloadable" flow definitions.
|
||||
*
|
||||
* @see FlowDefinitionRegistry#registerFlowDefinition(FlowDefinitionHolder)
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface FlowDefinitionHolder {
|
||||
|
||||
/**
|
||||
* Returns the <code>id</code> of the flow definition held by this holder. This is a <i>lightweight</i> method
|
||||
* callers may call to obtain the id of the flow without triggering full flow definition assembly (which may be an
|
||||
* expensive operation).
|
||||
*/
|
||||
String getFlowDefinitionId();
|
||||
|
||||
/**
|
||||
* Returns a descriptive string that identifies the source of this FlowDefinition. This is also a lightweight method
|
||||
* callers may call to obtain the logical resource where the flow definition resides without triggering flow
|
||||
* definition assembly. Used for informational purposes.
|
||||
* @return the flow definition resource string
|
||||
*/
|
||||
String getFlowDefinitionResourceString();
|
||||
|
||||
/**
|
||||
* Returns the flow definition held by this holder. Calling this method the first time may trigger flow assembly
|
||||
* (which may be expensive).
|
||||
* @throws FlowDefinitionConstructionException if there is a problem constructing the target flow definition
|
||||
*/
|
||||
FlowDefinition getFlowDefinition() throws FlowDefinitionConstructionException;
|
||||
|
||||
/**
|
||||
* Refresh the flow definition held by this holder. Calling this method typically triggers flow re-assembly, which
|
||||
* may include a refresh from an externalized resource such as a file.
|
||||
* @throws FlowDefinitionConstructionException if there is a problem constructing the target flow definition
|
||||
*/
|
||||
void refresh() throws FlowDefinitionConstructionException;
|
||||
|
||||
/**
|
||||
* Indicates that the system is being shutdown and any resources flow resources should be released. After this
|
||||
* method is called, calls to {@link #getFlowDefinition()} are undefined. Should only be called once. May be a no-op
|
||||
* if the held flow was never constructed to begin with.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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 holder holding a reference to a Flow definition. Provides a layer of indirection, enabling things like
|
||||
* "hot-reloadable" flow definitions.
|
||||
*
|
||||
* @see FlowDefinitionRegistry#registerFlowDefinition(FlowDefinitionHolder)
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface FlowDefinitionHolder {
|
||||
|
||||
/**
|
||||
* Returns the <code>id</code> of the flow definition held by this holder. This is a <i>lightweight</i> method
|
||||
* callers may call to obtain the id of the flow without triggering full flow definition assembly (which may be an
|
||||
* expensive operation).
|
||||
*/
|
||||
String getFlowDefinitionId();
|
||||
|
||||
/**
|
||||
* Returns a descriptive string that identifies the source of this FlowDefinition. This is also a lightweight method
|
||||
* callers may call to obtain the logical resource where the flow definition resides without triggering flow
|
||||
* definition assembly. Used for informational purposes.
|
||||
* @return the flow definition resource string
|
||||
*/
|
||||
String getFlowDefinitionResourceString();
|
||||
|
||||
/**
|
||||
* Returns the flow definition held by this holder. Calling this method the first time may trigger flow assembly
|
||||
* (which may be expensive).
|
||||
* @throws FlowDefinitionConstructionException if there is a problem constructing the target flow definition
|
||||
*/
|
||||
FlowDefinition getFlowDefinition() throws FlowDefinitionConstructionException;
|
||||
|
||||
/**
|
||||
* Refresh the flow definition held by this holder. Calling this method typically triggers flow re-assembly, which
|
||||
* may include a refresh from an externalized resource such as a file.
|
||||
* @throws FlowDefinitionConstructionException if there is a problem constructing the target flow definition
|
||||
*/
|
||||
void refresh() throws FlowDefinitionConstructionException;
|
||||
|
||||
/**
|
||||
* Indicates that the system is being shutdown and any resources flow resources should be released. After this
|
||||
* method is called, calls to {@link #getFlowDefinition()} are undefined. Should only be called once. May be a no-op
|
||||
* if the held flow was never constructed to begin with.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
}
|
||||
@@ -1,38 +1,38 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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 runtime service locator interface for retrieving flow definitions by <code>id</code>. Flow locators are needed by
|
||||
* flow executors at runtime to retrieve fully-configured flow definitions to support launching new flow executions.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface FlowDefinitionLocator {
|
||||
|
||||
/**
|
||||
* Lookup the flow definition with the specified id.
|
||||
* @param id the flow definition identifier
|
||||
* @return the flow definition
|
||||
* @throws NoSuchFlowDefinitionException when the flow definition with the specified id does not exist
|
||||
* @throws FlowDefinitionConstructionException if there is a problem constructing the identified flow definition
|
||||
*/
|
||||
FlowDefinition getFlowDefinition(String id) throws NoSuchFlowDefinitionException,
|
||||
FlowDefinitionConstructionException;
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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 runtime service locator interface for retrieving flow definitions by <code>id</code>. Flow locators are needed by
|
||||
* flow executors at runtime to retrieve fully-configured flow definitions to support launching new flow executions.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface FlowDefinitionLocator {
|
||||
|
||||
/**
|
||||
* Lookup the flow definition with the specified id.
|
||||
* @param id the flow definition identifier
|
||||
* @return the flow definition
|
||||
* @throws NoSuchFlowDefinitionException when the flow definition with the specified id does not exist
|
||||
* @throws FlowDefinitionConstructionException if there is a problem constructing the identified flow definition
|
||||
*/
|
||||
FlowDefinition getFlowDefinition(String id) throws NoSuchFlowDefinitionException,
|
||||
FlowDefinitionConstructionException;
|
||||
}
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.core.FlowException;
|
||||
|
||||
/**
|
||||
* Thrown when no flow definition was found during a lookup operation by a flow locator.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class NoSuchFlowDefinitionException extends FlowException {
|
||||
|
||||
/**
|
||||
* The id of the flow definition that could not be located.
|
||||
*/
|
||||
private String flowDefinitionId;
|
||||
|
||||
/**
|
||||
* Creates an exception indicating a flow definition could not be found.
|
||||
* @param flowDefinitionId the flow definition id
|
||||
*/
|
||||
public NoSuchFlowDefinitionException(String flowDefinitionId) {
|
||||
super("No flow definition '" + flowDefinitionId + "' found");
|
||||
this.flowDefinitionId = flowDefinitionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id of the flow definition that could not be found.
|
||||
*/
|
||||
public String getFlowDefinitionId() {
|
||||
return flowDefinitionId;
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.core.FlowException;
|
||||
|
||||
/**
|
||||
* Thrown when no flow definition was found during a lookup operation by a flow locator.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class NoSuchFlowDefinitionException extends FlowException {
|
||||
|
||||
/**
|
||||
* The id of the flow definition that could not be located.
|
||||
*/
|
||||
private String flowDefinitionId;
|
||||
|
||||
/**
|
||||
* Creates an exception indicating a flow definition could not be found.
|
||||
* @param flowDefinitionId the flow definition id
|
||||
*/
|
||||
public NoSuchFlowDefinitionException(String flowDefinitionId) {
|
||||
super("No flow definition '" + flowDefinitionId + "' found");
|
||||
this.flowDefinitionId = flowDefinitionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id of the flow definition that could not be found.
|
||||
*/
|
||||
public String getFlowDefinitionId() {
|
||||
return flowDefinitionId;
|
||||
}
|
||||
}
|
||||
@@ -1,161 +1,161 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
import org.springframework.webflow.execution.ActionExecutor;
|
||||
import org.springframework.webflow.execution.AnnotatedAction;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* An ordered, typed list of actions, mainly for use internally by flow artifacts that can execute groups of actions.
|
||||
*
|
||||
* @see Flow#getStartActionList()
|
||||
* @see Flow#getEndActionList()
|
||||
* @see State#getEntryActionList()
|
||||
* @see ActionState#getActionList()
|
||||
* @see TransitionableState#getExitActionList()
|
||||
* @see ViewState#getRenderActionList()
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class ActionList implements Iterable<Action> {
|
||||
|
||||
/**
|
||||
* The lists of actions.
|
||||
*/
|
||||
private List<Action> actions = new LinkedList<>();
|
||||
|
||||
/**
|
||||
* Add an action to this list.
|
||||
* @param action the action to add
|
||||
* @return true if this list's contents changed as a result of the add operation
|
||||
*/
|
||||
public boolean add(Action action) {
|
||||
return actions.add(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a collection of actions to this list.
|
||||
* @param actions the actions to add
|
||||
* @return true if this list's contents changed as a result of the add operation
|
||||
*/
|
||||
public boolean addAll(Action... actions) {
|
||||
if (actions == null) {
|
||||
return false;
|
||||
}
|
||||
return this.actions.addAll(Arrays.asList(actions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the action is in this list.
|
||||
* @param action the action
|
||||
* @return true if the action is contained in this list, false otherwise
|
||||
*/
|
||||
public boolean contains(Action action) {
|
||||
return actions.contains(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the action instance from this list.
|
||||
* @param action the action to add
|
||||
* @return true if this list's contents changed as a result of the remove operation
|
||||
*/
|
||||
public boolean remove(Action action) {
|
||||
return actions.remove(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of this action list.
|
||||
* @return the action list size.
|
||||
*/
|
||||
public int size() {
|
||||
return actions.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the action in this list at the provided index.
|
||||
* @param index the action index
|
||||
* @return the action the action
|
||||
*/
|
||||
public Action get(int index) throws IndexOutOfBoundsException {
|
||||
return actions.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the action in this list at the provided index, exposing it as an annotated action. This allows clients to
|
||||
* access specific properties about a target action instance if they exist.
|
||||
* @return the action, as an annotated action
|
||||
*/
|
||||
public AnnotatedAction getAnnotated(int index) throws IndexOutOfBoundsException {
|
||||
Action action = get(index);
|
||||
if (action instanceof AnnotatedAction) {
|
||||
return (AnnotatedAction) action;
|
||||
} else {
|
||||
// wrap the action; no annotations will be available
|
||||
return new AnnotatedAction(action);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over this action list.
|
||||
*/
|
||||
public Iterator<Action> iterator() {
|
||||
return actions.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this list to a typed action array.
|
||||
* @return the action list, as a typed array
|
||||
*/
|
||||
public Action[] toArray() {
|
||||
return actions.toArray(new Action[actions.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of actions in this list as a typed annotated action array. This is a convenience method allowing
|
||||
* clients to access properties about an action if they exist.
|
||||
* @return the annotated action list, as a typed array
|
||||
*/
|
||||
public AnnotatedAction[] toAnnotatedArray() {
|
||||
AnnotatedAction[] annotatedActions = new AnnotatedAction[actions.size()];
|
||||
for (int i = 0; i < size(); i++) {
|
||||
annotatedActions[i] = getAnnotated(i);
|
||||
}
|
||||
return annotatedActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the actions contained within this action list. Simply iterates over each action and calls execute.
|
||||
* Action result events are ignored.
|
||||
* @param context the action execution request context
|
||||
*/
|
||||
public void execute(RequestContext context) {
|
||||
for (Action action : actions) {
|
||||
ActionExecutor.execute(action, context);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return StylerUtils.style(actions);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
import org.springframework.webflow.execution.ActionExecutor;
|
||||
import org.springframework.webflow.execution.AnnotatedAction;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* An ordered, typed list of actions, mainly for use internally by flow artifacts that can execute groups of actions.
|
||||
*
|
||||
* @see Flow#getStartActionList()
|
||||
* @see Flow#getEndActionList()
|
||||
* @see State#getEntryActionList()
|
||||
* @see ActionState#getActionList()
|
||||
* @see TransitionableState#getExitActionList()
|
||||
* @see ViewState#getRenderActionList()
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class ActionList implements Iterable<Action> {
|
||||
|
||||
/**
|
||||
* The lists of actions.
|
||||
*/
|
||||
private List<Action> actions = new LinkedList<>();
|
||||
|
||||
/**
|
||||
* Add an action to this list.
|
||||
* @param action the action to add
|
||||
* @return true if this list's contents changed as a result of the add operation
|
||||
*/
|
||||
public boolean add(Action action) {
|
||||
return actions.add(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a collection of actions to this list.
|
||||
* @param actions the actions to add
|
||||
* @return true if this list's contents changed as a result of the add operation
|
||||
*/
|
||||
public boolean addAll(Action... actions) {
|
||||
if (actions == null) {
|
||||
return false;
|
||||
}
|
||||
return this.actions.addAll(Arrays.asList(actions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the action is in this list.
|
||||
* @param action the action
|
||||
* @return true if the action is contained in this list, false otherwise
|
||||
*/
|
||||
public boolean contains(Action action) {
|
||||
return actions.contains(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the action instance from this list.
|
||||
* @param action the action to add
|
||||
* @return true if this list's contents changed as a result of the remove operation
|
||||
*/
|
||||
public boolean remove(Action action) {
|
||||
return actions.remove(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of this action list.
|
||||
* @return the action list size.
|
||||
*/
|
||||
public int size() {
|
||||
return actions.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the action in this list at the provided index.
|
||||
* @param index the action index
|
||||
* @return the action the action
|
||||
*/
|
||||
public Action get(int index) throws IndexOutOfBoundsException {
|
||||
return actions.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the action in this list at the provided index, exposing it as an annotated action. This allows clients to
|
||||
* access specific properties about a target action instance if they exist.
|
||||
* @return the action, as an annotated action
|
||||
*/
|
||||
public AnnotatedAction getAnnotated(int index) throws IndexOutOfBoundsException {
|
||||
Action action = get(index);
|
||||
if (action instanceof AnnotatedAction) {
|
||||
return (AnnotatedAction) action;
|
||||
} else {
|
||||
// wrap the action; no annotations will be available
|
||||
return new AnnotatedAction(action);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over this action list.
|
||||
*/
|
||||
public Iterator<Action> iterator() {
|
||||
return actions.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this list to a typed action array.
|
||||
* @return the action list, as a typed array
|
||||
*/
|
||||
public Action[] toArray() {
|
||||
return actions.toArray(new Action[actions.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of actions in this list as a typed annotated action array. This is a convenience method allowing
|
||||
* clients to access properties about an action if they exist.
|
||||
* @return the annotated action list, as a typed array
|
||||
*/
|
||||
public AnnotatedAction[] toAnnotatedArray() {
|
||||
AnnotatedAction[] annotatedActions = new AnnotatedAction[actions.size()];
|
||||
for (int i = 0; i < size(); i++) {
|
||||
annotatedActions[i] = getAnnotated(i);
|
||||
}
|
||||
return annotatedActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the actions contained within this action list. Simply iterates over each action and calls execute.
|
||||
* Action result events are ignored.
|
||||
* @param context the action execution request context
|
||||
*/
|
||||
public void execute(RequestContext context) {
|
||||
for (Action action : actions) {
|
||||
ActionExecutor.execute(action, context);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return StylerUtils.style(actions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,168 +1,168 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
import org.springframework.webflow.execution.ActionExecutor;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* A transitionable state that executes one or more actions when entered. When the action(s) are executed this state
|
||||
* responds to their result(s) to decide what state to transition to next.
|
||||
* <p>
|
||||
* If more than one action is configured they are executed in an ordered chain until one returns a result event that
|
||||
* matches a state transition out of this state. This is a form of the Chain of Responsibility (CoR) pattern.
|
||||
* <p>
|
||||
* The result of an action's execution is typically the criteria for a transition out of this state. Additional
|
||||
* information in the current {@link RequestContext} may also be tested as part of custom transitional criteria,
|
||||
* allowing for sophisticated transition expressions that reason on contextual state.
|
||||
*
|
||||
* @see org.springframework.webflow.execution.Action
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class ActionState extends TransitionableState {
|
||||
|
||||
/**
|
||||
* The list of actions to be executed when this state is entered.
|
||||
*/
|
||||
private ActionList actionList = new ActionList();
|
||||
|
||||
/**
|
||||
* Creates a new action state.
|
||||
* @param flow the owning flow
|
||||
* @param id the state identifier (must be unique to the flow)
|
||||
* @throws IllegalArgumentException when this state cannot be added to given flow, e.g. beasue the id is not unique
|
||||
* @see #getActionList()
|
||||
*/
|
||||
public ActionState(Flow flow, String id) throws IllegalArgumentException {
|
||||
super(flow, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of actions executable by this action state. The returned list is mutable.
|
||||
* @return the state action list
|
||||
*/
|
||||
public ActionList getActionList() {
|
||||
return actionList;
|
||||
}
|
||||
|
||||
/*
|
||||
* Overrides getRequiredTransition(RequestContext) to throw a local NoMatchingActionResultTransitionException if a
|
||||
* transition on the occurrence of an action result event cannot be matched. Used to facilitate an action invocation
|
||||
* chain. <p>Note that we cannot catch NoMatchingTransitionException since that could lead to unwanted situations
|
||||
* where we're catching an exception that's generated by another state, e.g. because of a configuration error!
|
||||
*/
|
||||
public Transition getRequiredTransition(RequestContext context) throws NoMatchingTransitionException {
|
||||
Transition transition = getTransitionSet().getTransition(context);
|
||||
if (transition == null) {
|
||||
throw new NoMatchingActionResultTransitionException(this, context.getCurrentEvent());
|
||||
}
|
||||
return transition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialization of State's <code>doEnter</code> template method that executes behavior specific to this state type
|
||||
* in polymorphic fashion.
|
||||
* <p>
|
||||
* This implementation iterates over each configured <code>Action</code> instance and executes it. Execution
|
||||
* continues until an <code>Action</code> returns a result event that matches a transition in this request context,
|
||||
* or the set of all actions is exhausted.
|
||||
* @param context the control context for the currently executing flow, used by this state to manipulate the flow
|
||||
* execution
|
||||
* @throws FlowExecutionException if an exception occurs in this state
|
||||
*/
|
||||
protected void doEnter(RequestControlContext context) throws FlowExecutionException {
|
||||
int executionCount = 0;
|
||||
String[] eventIds = new String[actionList.size()];
|
||||
Iterator<Action> it = actionList.iterator();
|
||||
while (it.hasNext()) {
|
||||
Action action = it.next();
|
||||
Event event = ActionExecutor.execute(action, context);
|
||||
if (event != null) {
|
||||
eventIds[executionCount] = event.getId();
|
||||
try {
|
||||
context.handleEvent(event);
|
||||
return;
|
||||
} catch (NoMatchingActionResultTransitionException e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Action execution ["
|
||||
+ (executionCount + 1)
|
||||
+ "] resulted in no matching transition on event '"
|
||||
+ event.getId()
|
||||
+ "'"
|
||||
+ (it.hasNext() ? ": proceeding to the next action in the list"
|
||||
: ": action list exhausted"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Action execution ["
|
||||
+ (executionCount + 1)
|
||||
+ "] returned a [null] event"
|
||||
+ (it.hasNext() ? ": proceeding to the next action in the list" : ": action list exhausted"));
|
||||
}
|
||||
eventIds[executionCount] = null;
|
||||
}
|
||||
executionCount++;
|
||||
}
|
||||
if (executionCount > 0) {
|
||||
throw new NoMatchingTransitionException(getFlow().getId(), getId(), context.getCurrentEvent(),
|
||||
"No transition was matched on the event(s) signaled by the [" + executionCount
|
||||
+ "] action(s) that executed in this action state '" + getId() + "' of flow '"
|
||||
+ getFlow().getId() + "'; transitions must be defined to handle action result outcomes -- "
|
||||
+ "possible flow configuration error? Note: the eventIds signaled were: '"
|
||||
+ StylerUtils.style(eventIds)
|
||||
+ "', while the supported set of transitional criteria for this action state is '"
|
||||
+ StylerUtils.style(getTransitionSet().getTransitionCriterias()) + "'");
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
"No actions were executed, thus I cannot execute any state transition "
|
||||
+ "-- programmer configuration error; make sure you add at least one action to this state's action list");
|
||||
}
|
||||
}
|
||||
|
||||
protected void appendToString(ToStringCreator creator) {
|
||||
creator.append("actionList", actionList);
|
||||
super.appendToString(creator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Local "no transition found" exception used to report that an action result could not be mapped to a state
|
||||
* transition.
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
private static class NoMatchingActionResultTransitionException extends NoMatchingTransitionException {
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
* @param state the action state
|
||||
* @param resultEvent the action result event
|
||||
*/
|
||||
public NoMatchingActionResultTransitionException(ActionState state, Event resultEvent) {
|
||||
super(state.getFlow().getId(), state.getId(), resultEvent,
|
||||
"Cannot find a transition matching an action result event; continuing with next action...");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
import org.springframework.webflow.execution.ActionExecutor;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* A transitionable state that executes one or more actions when entered. When the action(s) are executed this state
|
||||
* responds to their result(s) to decide what state to transition to next.
|
||||
* <p>
|
||||
* If more than one action is configured they are executed in an ordered chain until one returns a result event that
|
||||
* matches a state transition out of this state. This is a form of the Chain of Responsibility (CoR) pattern.
|
||||
* <p>
|
||||
* The result of an action's execution is typically the criteria for a transition out of this state. Additional
|
||||
* information in the current {@link RequestContext} may also be tested as part of custom transitional criteria,
|
||||
* allowing for sophisticated transition expressions that reason on contextual state.
|
||||
*
|
||||
* @see org.springframework.webflow.execution.Action
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class ActionState extends TransitionableState {
|
||||
|
||||
/**
|
||||
* The list of actions to be executed when this state is entered.
|
||||
*/
|
||||
private ActionList actionList = new ActionList();
|
||||
|
||||
/**
|
||||
* Creates a new action state.
|
||||
* @param flow the owning flow
|
||||
* @param id the state identifier (must be unique to the flow)
|
||||
* @throws IllegalArgumentException when this state cannot be added to given flow, e.g. beasue the id is not unique
|
||||
* @see #getActionList()
|
||||
*/
|
||||
public ActionState(Flow flow, String id) throws IllegalArgumentException {
|
||||
super(flow, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of actions executable by this action state. The returned list is mutable.
|
||||
* @return the state action list
|
||||
*/
|
||||
public ActionList getActionList() {
|
||||
return actionList;
|
||||
}
|
||||
|
||||
/*
|
||||
* Overrides getRequiredTransition(RequestContext) to throw a local NoMatchingActionResultTransitionException if a
|
||||
* transition on the occurrence of an action result event cannot be matched. Used to facilitate an action invocation
|
||||
* chain. <p>Note that we cannot catch NoMatchingTransitionException since that could lead to unwanted situations
|
||||
* where we're catching an exception that's generated by another state, e.g. because of a configuration error!
|
||||
*/
|
||||
public Transition getRequiredTransition(RequestContext context) throws NoMatchingTransitionException {
|
||||
Transition transition = getTransitionSet().getTransition(context);
|
||||
if (transition == null) {
|
||||
throw new NoMatchingActionResultTransitionException(this, context.getCurrentEvent());
|
||||
}
|
||||
return transition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialization of State's <code>doEnter</code> template method that executes behavior specific to this state type
|
||||
* in polymorphic fashion.
|
||||
* <p>
|
||||
* This implementation iterates over each configured <code>Action</code> instance and executes it. Execution
|
||||
* continues until an <code>Action</code> returns a result event that matches a transition in this request context,
|
||||
* or the set of all actions is exhausted.
|
||||
* @param context the control context for the currently executing flow, used by this state to manipulate the flow
|
||||
* execution
|
||||
* @throws FlowExecutionException if an exception occurs in this state
|
||||
*/
|
||||
protected void doEnter(RequestControlContext context) throws FlowExecutionException {
|
||||
int executionCount = 0;
|
||||
String[] eventIds = new String[actionList.size()];
|
||||
Iterator<Action> it = actionList.iterator();
|
||||
while (it.hasNext()) {
|
||||
Action action = it.next();
|
||||
Event event = ActionExecutor.execute(action, context);
|
||||
if (event != null) {
|
||||
eventIds[executionCount] = event.getId();
|
||||
try {
|
||||
context.handleEvent(event);
|
||||
return;
|
||||
} catch (NoMatchingActionResultTransitionException e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Action execution ["
|
||||
+ (executionCount + 1)
|
||||
+ "] resulted in no matching transition on event '"
|
||||
+ event.getId()
|
||||
+ "'"
|
||||
+ (it.hasNext() ? ": proceeding to the next action in the list"
|
||||
: ": action list exhausted"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Action execution ["
|
||||
+ (executionCount + 1)
|
||||
+ "] returned a [null] event"
|
||||
+ (it.hasNext() ? ": proceeding to the next action in the list" : ": action list exhausted"));
|
||||
}
|
||||
eventIds[executionCount] = null;
|
||||
}
|
||||
executionCount++;
|
||||
}
|
||||
if (executionCount > 0) {
|
||||
throw new NoMatchingTransitionException(getFlow().getId(), getId(), context.getCurrentEvent(),
|
||||
"No transition was matched on the event(s) signaled by the [" + executionCount
|
||||
+ "] action(s) that executed in this action state '" + getId() + "' of flow '"
|
||||
+ getFlow().getId() + "'; transitions must be defined to handle action result outcomes -- "
|
||||
+ "possible flow configuration error? Note: the eventIds signaled were: '"
|
||||
+ StylerUtils.style(eventIds)
|
||||
+ "', while the supported set of transitional criteria for this action state is '"
|
||||
+ StylerUtils.style(getTransitionSet().getTransitionCriterias()) + "'");
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
"No actions were executed, thus I cannot execute any state transition "
|
||||
+ "-- programmer configuration error; make sure you add at least one action to this state's action list");
|
||||
}
|
||||
}
|
||||
|
||||
protected void appendToString(ToStringCreator creator) {
|
||||
creator.append("actionList", actionList);
|
||||
super.appendToString(creator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Local "no transition found" exception used to report that an action result could not be mapped to a state
|
||||
* transition.
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
private static class NoMatchingActionResultTransitionException extends NoMatchingTransitionException {
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
* @param state the action state
|
||||
* @param resultEvent the action result event
|
||||
*/
|
||||
public NoMatchingActionResultTransitionException(ActionState state, Event resultEvent) {
|
||||
super(state.getFlow().getId(), state.getId(), resultEvent,
|
||||
"Cannot find a transition matching an action result event; continuing with next action...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,53 +1,53 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* A simple transitionable state that when entered will execute the first transition whose matching criteria evaluates
|
||||
* to <code>true</code> in the {@link RequestContext context} of the current request.
|
||||
* <p>
|
||||
* A decision state is a convenient, simple way to encapsulate reusable state transition logic in one place.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class DecisionState extends TransitionableState {
|
||||
|
||||
/**
|
||||
* Creates a new decision state.
|
||||
* @param flow the owning flow
|
||||
* @param stateId the state identifier (must be unique to the flow)
|
||||
* @throws IllegalArgumentException when this state cannot be added to given flow, e.g. because the id is not unique
|
||||
*/
|
||||
public DecisionState(Flow flow, String stateId) throws IllegalArgumentException {
|
||||
super(flow, stateId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialization of State's <code>doEnter</code> template method that executes behavior specific to this state type
|
||||
* in polymorphic fashion.
|
||||
* <p>
|
||||
* Simply looks up the first transition that matches the state of the context and executes it.
|
||||
* @param context the control context for the currently executing flow, used by this state to manipulate the flow
|
||||
* execution
|
||||
* @throws FlowExecutionException if an exception occurs in this state
|
||||
*/
|
||||
protected void doEnter(RequestControlContext context) throws FlowExecutionException {
|
||||
getRequiredTransition(context).execute(this, context);
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* A simple transitionable state that when entered will execute the first transition whose matching criteria evaluates
|
||||
* to <code>true</code> in the {@link RequestContext context} of the current request.
|
||||
* <p>
|
||||
* A decision state is a convenient, simple way to encapsulate reusable state transition logic in one place.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class DecisionState extends TransitionableState {
|
||||
|
||||
/**
|
||||
* Creates a new decision state.
|
||||
* @param flow the owning flow
|
||||
* @param stateId the state identifier (must be unique to the flow)
|
||||
* @throws IllegalArgumentException when this state cannot be added to given flow, e.g. because the id is not unique
|
||||
*/
|
||||
public DecisionState(Flow flow, String stateId) throws IllegalArgumentException {
|
||||
super(flow, stateId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialization of State's <code>doEnter</code> template method that executes behavior specific to this state type
|
||||
* in polymorphic fashion.
|
||||
* <p>
|
||||
* Simply looks up the first transition that matches the state of the context and executes it.
|
||||
* @param context the control context for the currently executing flow, used by this state to manipulate the flow
|
||||
* execution
|
||||
* @throws FlowExecutionException if an exception occurs in this state
|
||||
*/
|
||||
protected void doEnter(RequestControlContext context) throws FlowExecutionException {
|
||||
getRequiredTransition(context).execute(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,130 +1,130 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.binding.mapping.Mapper;
|
||||
import org.springframework.binding.mapping.MappingResults;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
import org.springframework.webflow.execution.ActionExecutor;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.FlowSession;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* A state that ends a flow when entered. This state ends the active flow session of an ongoing flow execution.
|
||||
* <p>
|
||||
* If the ended session is the "root flow session" the entire flow execution ends, signaling the end of a logical
|
||||
* conversation.
|
||||
* <p>
|
||||
* If the terminated session was acting as a subflow, the flow execution continues and control is returned to the parent
|
||||
* flow session. In that case, this state returns an ending result event the resuming parent flow responds to.
|
||||
* <p>
|
||||
* An end state may be configured with a renderer to render a final response. This renderer will be invoked if the end
|
||||
* state terminates the entire flow execution.
|
||||
*
|
||||
* @see org.springframework.webflow.engine.SubflowState
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Colin Sampaleanu
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class EndState extends State {
|
||||
|
||||
/**
|
||||
* The renderer that will render the final response when a flow execution terminates.
|
||||
*/
|
||||
private Action finalResponseAction;
|
||||
|
||||
/**
|
||||
* The attribute mapper for mapping output attributes exposed by this end state when it is entered.
|
||||
*/
|
||||
private Mapper outputMapper;
|
||||
|
||||
/**
|
||||
* Create a new end state with no associated view.
|
||||
* @param flow the owning flow
|
||||
* @param id the state identifier (must be unique to the flow)
|
||||
* @throws IllegalArgumentException when this state cannot be added to given flow, e.g. because the id is not unique
|
||||
* @see State#State(Flow, String)
|
||||
* @see #setFinalResponseAction(Action)
|
||||
* @see #setOutputMapper(Mapper)
|
||||
*/
|
||||
public EndState(Flow flow, String id) throws IllegalArgumentException {
|
||||
super(flow, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the renderer that will render the final flow execution response.
|
||||
*/
|
||||
public void setFinalResponseAction(Action finalResponseAction) {
|
||||
this.finalResponseAction = finalResponseAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute mapper to use for mapping output attributes exposed by this end state when it is entered.
|
||||
*/
|
||||
public void setOutputMapper(Mapper outputMapper) {
|
||||
this.outputMapper = outputMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialization of State's <code>doEnter</code> template method that executes behavior specific to this state type
|
||||
* in polymorphic fashion.
|
||||
* <p>
|
||||
* This implementation pops the top (active) flow session off the execution stack, ending it, and resumes control in
|
||||
* the parent flow (if necessary). If the ended session is the root flow, a final response is rendered.
|
||||
* @param context the control context for the currently executing flow, used by this state to manipulate the flow
|
||||
* execution
|
||||
* @throws FlowExecutionException if an exception occurs in this state
|
||||
*/
|
||||
protected void doEnter(final RequestControlContext context) throws FlowExecutionException {
|
||||
FlowSession activeSession = context.getFlowExecutionContext().getActiveSession();
|
||||
if (activeSession.isRoot()) {
|
||||
// entire flow execution is ending; issue the final response
|
||||
if (finalResponseAction != null && !context.getExternalContext().isResponseComplete()) {
|
||||
ActionExecutor.execute(finalResponseAction, context);
|
||||
context.getExternalContext().recordResponseComplete();
|
||||
}
|
||||
context.endActiveFlowSession(getId(), createSessionOutput(context));
|
||||
} else {
|
||||
// there is a parent flow that will resume (this flow is a subflow)
|
||||
LocalAttributeMap<Object> sessionOutput = createSessionOutput(context);
|
||||
context.endActiveFlowSession(getId(), sessionOutput);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the subflow output map. This will invoke the output mapper (if any) to map data available in the flow
|
||||
* execution request context into a newly created empty map.
|
||||
*/
|
||||
protected LocalAttributeMap<Object> createSessionOutput(RequestContext context) {
|
||||
LocalAttributeMap<Object> output = new LocalAttributeMap<>();
|
||||
if (outputMapper != null) {
|
||||
MappingResults results = outputMapper.map(context, output);
|
||||
if (results != null && results.hasErrorResults()) {
|
||||
throw new FlowOutputMappingException(getOwner().getId(), getId(), results);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
protected void appendToString(ToStringCreator creator) {
|
||||
creator.append("finalResponseAction", finalResponseAction).append("outputMapper", outputMapper);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.binding.mapping.Mapper;
|
||||
import org.springframework.binding.mapping.MappingResults;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
import org.springframework.webflow.execution.ActionExecutor;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.FlowSession;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* A state that ends a flow when entered. This state ends the active flow session of an ongoing flow execution.
|
||||
* <p>
|
||||
* If the ended session is the "root flow session" the entire flow execution ends, signaling the end of a logical
|
||||
* conversation.
|
||||
* <p>
|
||||
* If the terminated session was acting as a subflow, the flow execution continues and control is returned to the parent
|
||||
* flow session. In that case, this state returns an ending result event the resuming parent flow responds to.
|
||||
* <p>
|
||||
* An end state may be configured with a renderer to render a final response. This renderer will be invoked if the end
|
||||
* state terminates the entire flow execution.
|
||||
*
|
||||
* @see org.springframework.webflow.engine.SubflowState
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Colin Sampaleanu
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class EndState extends State {
|
||||
|
||||
/**
|
||||
* The renderer that will render the final response when a flow execution terminates.
|
||||
*/
|
||||
private Action finalResponseAction;
|
||||
|
||||
/**
|
||||
* The attribute mapper for mapping output attributes exposed by this end state when it is entered.
|
||||
*/
|
||||
private Mapper outputMapper;
|
||||
|
||||
/**
|
||||
* Create a new end state with no associated view.
|
||||
* @param flow the owning flow
|
||||
* @param id the state identifier (must be unique to the flow)
|
||||
* @throws IllegalArgumentException when this state cannot be added to given flow, e.g. because the id is not unique
|
||||
* @see State#State(Flow, String)
|
||||
* @see #setFinalResponseAction(Action)
|
||||
* @see #setOutputMapper(Mapper)
|
||||
*/
|
||||
public EndState(Flow flow, String id) throws IllegalArgumentException {
|
||||
super(flow, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the renderer that will render the final flow execution response.
|
||||
*/
|
||||
public void setFinalResponseAction(Action finalResponseAction) {
|
||||
this.finalResponseAction = finalResponseAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute mapper to use for mapping output attributes exposed by this end state when it is entered.
|
||||
*/
|
||||
public void setOutputMapper(Mapper outputMapper) {
|
||||
this.outputMapper = outputMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialization of State's <code>doEnter</code> template method that executes behavior specific to this state type
|
||||
* in polymorphic fashion.
|
||||
* <p>
|
||||
* This implementation pops the top (active) flow session off the execution stack, ending it, and resumes control in
|
||||
* the parent flow (if necessary). If the ended session is the root flow, a final response is rendered.
|
||||
* @param context the control context for the currently executing flow, used by this state to manipulate the flow
|
||||
* execution
|
||||
* @throws FlowExecutionException if an exception occurs in this state
|
||||
*/
|
||||
protected void doEnter(final RequestControlContext context) throws FlowExecutionException {
|
||||
FlowSession activeSession = context.getFlowExecutionContext().getActiveSession();
|
||||
if (activeSession.isRoot()) {
|
||||
// entire flow execution is ending; issue the final response
|
||||
if (finalResponseAction != null && !context.getExternalContext().isResponseComplete()) {
|
||||
ActionExecutor.execute(finalResponseAction, context);
|
||||
context.getExternalContext().recordResponseComplete();
|
||||
}
|
||||
context.endActiveFlowSession(getId(), createSessionOutput(context));
|
||||
} else {
|
||||
// there is a parent flow that will resume (this flow is a subflow)
|
||||
LocalAttributeMap<Object> sessionOutput = createSessionOutput(context);
|
||||
context.endActiveFlowSession(getId(), sessionOutput);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the subflow output map. This will invoke the output mapper (if any) to map data available in the flow
|
||||
* execution request context into a newly created empty map.
|
||||
*/
|
||||
protected LocalAttributeMap<Object> createSessionOutput(RequestContext context) {
|
||||
LocalAttributeMap<Object> output = new LocalAttributeMap<>();
|
||||
if (outputMapper != null) {
|
||||
MappingResults results = outputMapper.map(context, output);
|
||||
if (results != null && results.hasErrorResults()) {
|
||||
throw new FlowOutputMappingException(getOwner().getId(), getId(), results);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
protected void appendToString(ToStringCreator creator) {
|
||||
creator.append("finalResponseAction", finalResponseAction).append("outputMapper", outputMapper);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,55 +1,55 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
|
||||
/**
|
||||
* A strategy for handling an exception that occurs at runtime during an active flow execution.
|
||||
*
|
||||
* Note: special care should be taken when implementing custom flow execution exception handlers. Exception handlers are
|
||||
* like Transitions in that they direct flow control when exceptions occur. They are more complex than Actions, which
|
||||
* can only execute behaviors and return results that drive flow control. For this reason, if implemented incorrectly, a
|
||||
* FlowExecutionHandler can leave a flow execution in an invalid state, which can render the flow execution unusable or
|
||||
* its future use undefined. For example, if an exception thrown at flow session startup gets routed to an exception
|
||||
* handler, the handler must take responsibility for ensuring the flow execution returns control to the caller in a
|
||||
* consistent state. Concretely, this means the exception handler must transition the flow to its start state. The
|
||||
* handler should not simply return leaving the flow with no current state set.
|
||||
*
|
||||
* Note: Because flow execution handlers are more difficult to implement correctly, consider catching exceptions in your
|
||||
* web flow action code and returning result events that drive standard transitions. Alternatively, consider use of the
|
||||
* existing {@code TransitionExecutingFlowExecutionExceptionHandler} which illustrates the proper way to implement an
|
||||
* exception handler.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface FlowExecutionExceptionHandler {
|
||||
|
||||
/**
|
||||
* Can this handler handle the given exception?
|
||||
* @param exception the exception that occurred
|
||||
* @return true if yes, false if no
|
||||
*/
|
||||
boolean canHandle(FlowExecutionException exception);
|
||||
|
||||
/**
|
||||
* Handle the exception in the context of the current request. An implementation is expected to transition the flow
|
||||
* to a state using {@link RequestControlContext#execute(Transition)}.
|
||||
* @param exception the exception that occurred
|
||||
* @param context the execution control context for this request
|
||||
*/
|
||||
void handle(FlowExecutionException exception, RequestControlContext context);
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
|
||||
/**
|
||||
* A strategy for handling an exception that occurs at runtime during an active flow execution.
|
||||
*
|
||||
* Note: special care should be taken when implementing custom flow execution exception handlers. Exception handlers are
|
||||
* like Transitions in that they direct flow control when exceptions occur. They are more complex than Actions, which
|
||||
* can only execute behaviors and return results that drive flow control. For this reason, if implemented incorrectly, a
|
||||
* FlowExecutionHandler can leave a flow execution in an invalid state, which can render the flow execution unusable or
|
||||
* its future use undefined. For example, if an exception thrown at flow session startup gets routed to an exception
|
||||
* handler, the handler must take responsibility for ensuring the flow execution returns control to the caller in a
|
||||
* consistent state. Concretely, this means the exception handler must transition the flow to its start state. The
|
||||
* handler should not simply return leaving the flow with no current state set.
|
||||
*
|
||||
* Note: Because flow execution handlers are more difficult to implement correctly, consider catching exceptions in your
|
||||
* web flow action code and returning result events that drive standard transitions. Alternatively, consider use of the
|
||||
* existing {@code TransitionExecutingFlowExecutionExceptionHandler} which illustrates the proper way to implement an
|
||||
* exception handler.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface FlowExecutionExceptionHandler {
|
||||
|
||||
/**
|
||||
* Can this handler handle the given exception?
|
||||
* @param exception the exception that occurred
|
||||
* @return true if yes, false if no
|
||||
*/
|
||||
boolean canHandle(FlowExecutionException exception);
|
||||
|
||||
/**
|
||||
* Handle the exception in the context of the current request. An implementation is expected to transition the flow
|
||||
* to a state using {@link RequestControlContext#execute(Transition)}.
|
||||
* @param exception the exception that occurred
|
||||
* @param context the execution control context for this request
|
||||
*/
|
||||
void handle(FlowExecutionException exception, RequestControlContext context);
|
||||
}
|
||||
|
||||
@@ -1,119 +1,119 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.webflow.core.collection.CollectionUtils;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
|
||||
/**
|
||||
* A typed set of state exception handlers, mainly for use internally by artifacts that can apply state exception
|
||||
* handling logic.
|
||||
*
|
||||
* @see FlowExecutionExceptionHandler
|
||||
* @see Flow#getExceptionHandlerSet()
|
||||
* @see State#getExceptionHandlerSet()
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class FlowExecutionExceptionHandlerSet {
|
||||
|
||||
/**
|
||||
* The set of exception handlers.
|
||||
*/
|
||||
private List<FlowExecutionExceptionHandler> exceptionHandlers = new LinkedList<>();
|
||||
|
||||
/**
|
||||
* Add a state exception handler to this set.
|
||||
* @param exceptionHandler the exception handler to add
|
||||
* @return true if this set's contents changed as a result of the add operation
|
||||
*/
|
||||
public boolean add(FlowExecutionExceptionHandler exceptionHandler) {
|
||||
if (contains(exceptionHandler)) {
|
||||
return false;
|
||||
}
|
||||
return exceptionHandlers.add(exceptionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a collection of state exception handler instances to this set.
|
||||
* @param exceptionHandlers the exception handlers to add
|
||||
* @return true if this set's contents changed as a result of the add operation
|
||||
*/
|
||||
public boolean addAll(FlowExecutionExceptionHandler... exceptionHandlers) {
|
||||
return CollectionUtils.addAllNoDuplicates(this.exceptionHandlers, exceptionHandlers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if this state exception handler is in this set.
|
||||
* @param exceptionHandler the exception handler
|
||||
* @return true if the state exception handler is contained in this set, false otherwise
|
||||
*/
|
||||
public boolean contains(FlowExecutionExceptionHandler exceptionHandler) {
|
||||
return exceptionHandlers.contains(exceptionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the exception handler instance from this set.
|
||||
* @param exceptionHandler the exception handler to add
|
||||
* @return true if this set's contents changed as a result of the remove operation
|
||||
*/
|
||||
public boolean remove(FlowExecutionExceptionHandler exceptionHandler) {
|
||||
return exceptionHandlers.remove(exceptionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of this state exception handler set.
|
||||
* @return the exception handler set size
|
||||
*/
|
||||
public int size() {
|
||||
return exceptionHandlers.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this list to a typed state exception handler array.
|
||||
* @return the exception handler list, as a typed array
|
||||
*/
|
||||
public FlowExecutionExceptionHandler[] toArray() {
|
||||
return exceptionHandlers.toArray(new FlowExecutionExceptionHandler[exceptionHandlers.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an exception that occurred during the context of the current flow execution request.
|
||||
* <p>
|
||||
* This implementation iterates over the ordered set of exception handler objects, delegating to each handler in the
|
||||
* set until one handles the exception that occurred.
|
||||
* @param exception the exception that occurred
|
||||
* @param context the flow execution control context
|
||||
* @return true if the exception was handled
|
||||
*/
|
||||
public boolean handleException(FlowExecutionException exception, RequestControlContext context) {
|
||||
for (FlowExecutionExceptionHandler handler : exceptionHandlers) {
|
||||
if (handler.canHandle(exception)) {
|
||||
handler.handle(exception, context);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return StylerUtils.style(exceptionHandlers);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.webflow.core.collection.CollectionUtils;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
|
||||
/**
|
||||
* A typed set of state exception handlers, mainly for use internally by artifacts that can apply state exception
|
||||
* handling logic.
|
||||
*
|
||||
* @see FlowExecutionExceptionHandler
|
||||
* @see Flow#getExceptionHandlerSet()
|
||||
* @see State#getExceptionHandlerSet()
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class FlowExecutionExceptionHandlerSet {
|
||||
|
||||
/**
|
||||
* The set of exception handlers.
|
||||
*/
|
||||
private List<FlowExecutionExceptionHandler> exceptionHandlers = new LinkedList<>();
|
||||
|
||||
/**
|
||||
* Add a state exception handler to this set.
|
||||
* @param exceptionHandler the exception handler to add
|
||||
* @return true if this set's contents changed as a result of the add operation
|
||||
*/
|
||||
public boolean add(FlowExecutionExceptionHandler exceptionHandler) {
|
||||
if (contains(exceptionHandler)) {
|
||||
return false;
|
||||
}
|
||||
return exceptionHandlers.add(exceptionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a collection of state exception handler instances to this set.
|
||||
* @param exceptionHandlers the exception handlers to add
|
||||
* @return true if this set's contents changed as a result of the add operation
|
||||
*/
|
||||
public boolean addAll(FlowExecutionExceptionHandler... exceptionHandlers) {
|
||||
return CollectionUtils.addAllNoDuplicates(this.exceptionHandlers, exceptionHandlers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if this state exception handler is in this set.
|
||||
* @param exceptionHandler the exception handler
|
||||
* @return true if the state exception handler is contained in this set, false otherwise
|
||||
*/
|
||||
public boolean contains(FlowExecutionExceptionHandler exceptionHandler) {
|
||||
return exceptionHandlers.contains(exceptionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the exception handler instance from this set.
|
||||
* @param exceptionHandler the exception handler to add
|
||||
* @return true if this set's contents changed as a result of the remove operation
|
||||
*/
|
||||
public boolean remove(FlowExecutionExceptionHandler exceptionHandler) {
|
||||
return exceptionHandlers.remove(exceptionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of this state exception handler set.
|
||||
* @return the exception handler set size
|
||||
*/
|
||||
public int size() {
|
||||
return exceptionHandlers.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this list to a typed state exception handler array.
|
||||
* @return the exception handler list, as a typed array
|
||||
*/
|
||||
public FlowExecutionExceptionHandler[] toArray() {
|
||||
return exceptionHandlers.toArray(new FlowExecutionExceptionHandler[exceptionHandlers.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an exception that occurred during the context of the current flow execution request.
|
||||
* <p>
|
||||
* This implementation iterates over the ordered set of exception handler objects, delegating to each handler in the
|
||||
* set until one handles the exception that occurred.
|
||||
* @param exception the exception that occurred
|
||||
* @param context the flow execution control context
|
||||
* @return true if the exception was handled
|
||||
*/
|
||||
public boolean handleException(FlowExecutionException exception, RequestControlContext context) {
|
||||
for (FlowExecutionExceptionHandler handler : exceptionHandlers) {
|
||||
if (handler.canHandle(exception)) {
|
||||
handler.handle(exception, context);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return StylerUtils.style(exceptionHandlers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,104 +1,104 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.core.AnnotatedObject;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* A value object that defines a specification for a flow variable. Such a variable is allocated when a flow starts and
|
||||
* destroyed when that flow ends. This class encapsulates information about the variable and the behavior necessary to
|
||||
* allocate the variable instance in flow scope.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class FlowVariable extends AnnotatedObject {
|
||||
|
||||
/**
|
||||
* The variable name.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The value factory that provides this variable's value.
|
||||
*/
|
||||
private VariableValueFactory valueFactory;
|
||||
|
||||
/**
|
||||
* Creates a new flow variable.
|
||||
* @param name the variable name
|
||||
*/
|
||||
public FlowVariable(String name, VariableValueFactory valueFactory) {
|
||||
Assert.hasText(name, "The variable name is required");
|
||||
Assert.notNull(valueFactory, "The variable value factory is required");
|
||||
this.name = name;
|
||||
this.valueFactory = valueFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this variable.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
// name and scope based equality
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof FlowVariable)) {
|
||||
return false;
|
||||
}
|
||||
FlowVariable other = (FlowVariable) o;
|
||||
return name.equals(other.name) && valueFactory.equals(other.valueFactory);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return name.hashCode() + valueFactory.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates this flow variable. This method allocates the variable's value in the correct flow scope.
|
||||
* @param context the executing flow
|
||||
*/
|
||||
public void create(RequestContext context) {
|
||||
Object value = valueFactory.createInitialValue(context);
|
||||
context.getFlowScope().put(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores this variable's dependencies. This method asks the variable's value factory to restore any references
|
||||
* the variable has to transient objects.
|
||||
* @param context the executing flow
|
||||
*/
|
||||
public void restore(RequestContext context) {
|
||||
Object value = context.getFlowScope().get(name);
|
||||
valueFactory.restoreReferences(value, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys this flow variable. This method removes the variable's value in the correct flow scope.
|
||||
* @param context the executing flow
|
||||
*/
|
||||
public Object destroy(RequestContext context) {
|
||||
return context.getFlowScope().remove(name);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("name", name).append("valueFactory", valueFactory).toString();
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.core.AnnotatedObject;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* A value object that defines a specification for a flow variable. Such a variable is allocated when a flow starts and
|
||||
* destroyed when that flow ends. This class encapsulates information about the variable and the behavior necessary to
|
||||
* allocate the variable instance in flow scope.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class FlowVariable extends AnnotatedObject {
|
||||
|
||||
/**
|
||||
* The variable name.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The value factory that provides this variable's value.
|
||||
*/
|
||||
private VariableValueFactory valueFactory;
|
||||
|
||||
/**
|
||||
* Creates a new flow variable.
|
||||
* @param name the variable name
|
||||
*/
|
||||
public FlowVariable(String name, VariableValueFactory valueFactory) {
|
||||
Assert.hasText(name, "The variable name is required");
|
||||
Assert.notNull(valueFactory, "The variable value factory is required");
|
||||
this.name = name;
|
||||
this.valueFactory = valueFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this variable.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
// name and scope based equality
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof FlowVariable)) {
|
||||
return false;
|
||||
}
|
||||
FlowVariable other = (FlowVariable) o;
|
||||
return name.equals(other.name) && valueFactory.equals(other.valueFactory);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return name.hashCode() + valueFactory.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates this flow variable. This method allocates the variable's value in the correct flow scope.
|
||||
* @param context the executing flow
|
||||
*/
|
||||
public void create(RequestContext context) {
|
||||
Object value = valueFactory.createInitialValue(context);
|
||||
context.getFlowScope().put(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores this variable's dependencies. This method asks the variable's value factory to restore any references
|
||||
* the variable has to transient objects.
|
||||
* @param context the executing flow
|
||||
*/
|
||||
public void restore(RequestContext context) {
|
||||
Object value = context.getFlowScope().get(name);
|
||||
valueFactory.restoreReferences(value, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys this flow variable. This method removes the variable's value in the correct flow scope.
|
||||
* @param context the executing flow
|
||||
*/
|
||||
public Object destroy(RequestContext context) {
|
||||
return context.getFlowScope().remove(name);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("name", name).append("valueFactory", valueFactory).toString();
|
||||
}
|
||||
}
|
||||
@@ -1,67 +1,67 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
|
||||
/**
|
||||
* Thrown when no transition can be matched given the occurence of an event in the context of a flow execution request.
|
||||
* <p>
|
||||
* Typically this happens because there is no "handler" transition for the last event that occured.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class NoMatchingTransitionException extends FlowExecutionException {
|
||||
|
||||
/**
|
||||
* The event that occurred that could not be matched to a Transition.
|
||||
*/
|
||||
private Event event;
|
||||
|
||||
/**
|
||||
* Create a new no matching transition exception.
|
||||
* @param flowId the current flow
|
||||
* @param stateId the state that could not be transitioned out of
|
||||
* @param event the event that occured that could not be matched to a transition
|
||||
* @param message the message
|
||||
*/
|
||||
public NoMatchingTransitionException(String flowId, String stateId, Event event, String message) {
|
||||
super(flowId, stateId, message);
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new no matching transition exception.
|
||||
* @param flowId the current flow
|
||||
* @param stateId the state that could not be transitioned out of
|
||||
* @param event the event that occured that could not be matched to a transition
|
||||
* @param message the message
|
||||
* @param cause the underlying cause
|
||||
*/
|
||||
public NoMatchingTransitionException(String flowId, String stateId, Event event, String message, Throwable cause) {
|
||||
super(flowId, stateId, message, cause);
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the event for the current request that did not trigger any supported transition.
|
||||
*/
|
||||
public Event getEvent() {
|
||||
return event;
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
|
||||
/**
|
||||
* Thrown when no transition can be matched given the occurence of an event in the context of a flow execution request.
|
||||
* <p>
|
||||
* Typically this happens because there is no "handler" transition for the last event that occured.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class NoMatchingTransitionException extends FlowExecutionException {
|
||||
|
||||
/**
|
||||
* The event that occurred that could not be matched to a Transition.
|
||||
*/
|
||||
private Event event;
|
||||
|
||||
/**
|
||||
* Create a new no matching transition exception.
|
||||
* @param flowId the current flow
|
||||
* @param stateId the state that could not be transitioned out of
|
||||
* @param event the event that occured that could not be matched to a transition
|
||||
* @param message the message
|
||||
*/
|
||||
public NoMatchingTransitionException(String flowId, String stateId, Event event, String message) {
|
||||
super(flowId, stateId, message);
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new no matching transition exception.
|
||||
* @param flowId the current flow
|
||||
* @param stateId the state that could not be transitioned out of
|
||||
* @param event the event that occured that could not be matched to a transition
|
||||
* @param message the message
|
||||
* @param cause the underlying cause
|
||||
*/
|
||||
public NoMatchingTransitionException(String flowId, String stateId, Event event, String message, Throwable cause) {
|
||||
super(flowId, stateId, message, cause);
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the event for the current request that did not trigger any supported transition.
|
||||
*/
|
||||
public Event getEvent() {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
@@ -1,166 +1,166 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionContext;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.FlowExecutionKey;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.View;
|
||||
|
||||
/**
|
||||
* Mutable control interface used to manipulate an ongoing flow execution in the context of one client request.
|
||||
* Primarily used internally by the various flow artifacts when they are invoked.
|
||||
* <p>
|
||||
* This interface acts as a facade for core definition constructs such as the central <code>Flow</code> and
|
||||
* <code>State</code> classes, abstracting away details about the runtime execution machine.
|
||||
* <p>
|
||||
* Note this type is not the same as the {@link FlowExecutionContext}. Objects of this type are <i>request specific</i>:
|
||||
* they provide a control interface for manipulating exactly one flow execution locally from exactly one request. A
|
||||
* <code>FlowExecutionContext</code> provides information about a single flow execution (conversation), and it's scope
|
||||
* is not local to a specific request (or thread).
|
||||
*
|
||||
* @see org.springframework.webflow.engine.Flow
|
||||
* @see org.springframework.webflow.engine.State
|
||||
* @see org.springframework.webflow.execution.FlowExecution
|
||||
* @see FlowExecutionContext
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface RequestControlContext extends RequestContext {
|
||||
|
||||
/**
|
||||
* Record the current state that has entered in the executing flow. This method will be called as part of entering a
|
||||
* new state by the State type itself.
|
||||
* @param state the current state
|
||||
* @see State#enter(RequestControlContext)
|
||||
*/
|
||||
void setCurrentState(State state);
|
||||
|
||||
/**
|
||||
* Assign the ongoing flow execution its flow execution key. This method will be called before a state is about to
|
||||
* render a view and pause the flow execution.
|
||||
*/
|
||||
FlowExecutionKey assignFlowExecutionKey();
|
||||
|
||||
/**
|
||||
* Sets the current view.
|
||||
* @param view the current view, or null to mark the current view as <code>null</code>
|
||||
*/
|
||||
void setCurrentView(View view);
|
||||
|
||||
/**
|
||||
* Called when the current view is about to be rendered in the current view state.
|
||||
* @param view the view to be rendered
|
||||
*/
|
||||
void viewRendering(View view);
|
||||
|
||||
/**
|
||||
* Called when the current view has completed rendering in the current view state.
|
||||
* @param view the view that rendered
|
||||
*/
|
||||
void viewRendered(View view);
|
||||
|
||||
/**
|
||||
* Signals the occurrence of an event in the current state of this flow execution request context. This method
|
||||
* should be called by clients that report internal event occurrences, such as action states. The
|
||||
* <code>onEvent()</code> method of the flow involved in the flow execution will be called.
|
||||
* @param event the event that occurred
|
||||
* @return a boolean indicating if handling this event caused the current state to exit and a new state to enter
|
||||
* @throws FlowExecutionException if an exception was thrown within a state of the flow during execution of this
|
||||
* signalEvent operation
|
||||
* @see Flow#handleEvent(RequestControlContext)
|
||||
*/
|
||||
boolean handleEvent(Event event) throws FlowExecutionException;
|
||||
|
||||
/**
|
||||
* Execute this transition out of the current source state. Allows for privileged execution of an arbitrary
|
||||
* transition.
|
||||
* @param transition the transition
|
||||
* @see Transition#execute(State, RequestControlContext)
|
||||
*/
|
||||
boolean execute(Transition transition);
|
||||
|
||||
/**
|
||||
* Record the transition executing in the flow. This method will be called as part of executing a transition from
|
||||
* one state to another.
|
||||
* @param transition the transition being executed
|
||||
* @see Transition#execute(State, RequestControlContext)
|
||||
*/
|
||||
void setCurrentTransition(Transition transition);
|
||||
|
||||
/**
|
||||
* Update the current flow execution snapshot to save the current state.
|
||||
*/
|
||||
void updateCurrentFlowExecutionSnapshot();
|
||||
|
||||
/**
|
||||
* Remove the current flow execution snapshot to invalidate the current state.
|
||||
*/
|
||||
void removeCurrentFlowExecutionSnapshot();
|
||||
|
||||
/**
|
||||
* Remove all flow execution snapshots associated with the ongoing conversation. Invalidates previous states.
|
||||
*/
|
||||
void removeAllFlowExecutionSnapshots();
|
||||
|
||||
/**
|
||||
* Spawn a new flow session and activate it in the currently executing flow. Also transitions the spawned flow to
|
||||
* its start state. This method should be called by clients that wish to spawn new flows, such as subflow states.
|
||||
* <p>
|
||||
* This will start a new flow session in the current flow execution, which is already active.
|
||||
* @param flow the flow to start, its <code>start()</code> method will be called
|
||||
* @param input initial contents of the newly created flow session (may be <code>null</code>, e.g. empty)
|
||||
* @throws FlowExecutionException if an exception was thrown within a state of the flow during execution of this
|
||||
* start operation
|
||||
* @see Flow#start(RequestControlContext, MutableAttributeMap)
|
||||
*/
|
||||
void start(Flow flow, MutableAttributeMap<?> input) throws FlowExecutionException;
|
||||
|
||||
/**
|
||||
* End the active flow session of the current flow execution. This method should be called by clients that terminate
|
||||
* flows, such as end states. The <code>end()</code> method of the flow involved in the flow execution will be
|
||||
* called.
|
||||
* @param outcome the logical outcome the ending session should return
|
||||
* @param output output the ending session should return
|
||||
* @throws IllegalStateException when the flow execution is not active
|
||||
* @see Flow#end(RequestControlContext, String, MutableAttributeMap)
|
||||
*/
|
||||
void endActiveFlowSession(String outcome, MutableAttributeMap<Object> output) throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns true if the 'redirect on pause' flow execution attribute is set to true, false otherwise.
|
||||
* @return true or false
|
||||
*/
|
||||
boolean getRedirectOnPause();
|
||||
|
||||
/**
|
||||
* Returns the value of the 'redirect in same state' flow execution attribute if set or otherwise it falls back on
|
||||
* the value returned by {@link #getRedirectOnPause()}.
|
||||
* @return true or false
|
||||
*/
|
||||
boolean getRedirectInSameState();
|
||||
|
||||
/**
|
||||
* Returns true if the flow current flow execution was launched in embedded page mode. When a flow is embedded on a
|
||||
* page it can make different assumptions with regards to whether redirect after post is necessary.
|
||||
*/
|
||||
boolean getEmbeddedMode();
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionContext;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.FlowExecutionKey;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.View;
|
||||
|
||||
/**
|
||||
* Mutable control interface used to manipulate an ongoing flow execution in the context of one client request.
|
||||
* Primarily used internally by the various flow artifacts when they are invoked.
|
||||
* <p>
|
||||
* This interface acts as a facade for core definition constructs such as the central <code>Flow</code> and
|
||||
* <code>State</code> classes, abstracting away details about the runtime execution machine.
|
||||
* <p>
|
||||
* Note this type is not the same as the {@link FlowExecutionContext}. Objects of this type are <i>request specific</i>:
|
||||
* they provide a control interface for manipulating exactly one flow execution locally from exactly one request. A
|
||||
* <code>FlowExecutionContext</code> provides information about a single flow execution (conversation), and it's scope
|
||||
* is not local to a specific request (or thread).
|
||||
*
|
||||
* @see org.springframework.webflow.engine.Flow
|
||||
* @see org.springframework.webflow.engine.State
|
||||
* @see org.springframework.webflow.execution.FlowExecution
|
||||
* @see FlowExecutionContext
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface RequestControlContext extends RequestContext {
|
||||
|
||||
/**
|
||||
* Record the current state that has entered in the executing flow. This method will be called as part of entering a
|
||||
* new state by the State type itself.
|
||||
* @param state the current state
|
||||
* @see State#enter(RequestControlContext)
|
||||
*/
|
||||
void setCurrentState(State state);
|
||||
|
||||
/**
|
||||
* Assign the ongoing flow execution its flow execution key. This method will be called before a state is about to
|
||||
* render a view and pause the flow execution.
|
||||
*/
|
||||
FlowExecutionKey assignFlowExecutionKey();
|
||||
|
||||
/**
|
||||
* Sets the current view.
|
||||
* @param view the current view, or null to mark the current view as <code>null</code>
|
||||
*/
|
||||
void setCurrentView(View view);
|
||||
|
||||
/**
|
||||
* Called when the current view is about to be rendered in the current view state.
|
||||
* @param view the view to be rendered
|
||||
*/
|
||||
void viewRendering(View view);
|
||||
|
||||
/**
|
||||
* Called when the current view has completed rendering in the current view state.
|
||||
* @param view the view that rendered
|
||||
*/
|
||||
void viewRendered(View view);
|
||||
|
||||
/**
|
||||
* Signals the occurrence of an event in the current state of this flow execution request context. This method
|
||||
* should be called by clients that report internal event occurrences, such as action states. The
|
||||
* <code>onEvent()</code> method of the flow involved in the flow execution will be called.
|
||||
* @param event the event that occurred
|
||||
* @return a boolean indicating if handling this event caused the current state to exit and a new state to enter
|
||||
* @throws FlowExecutionException if an exception was thrown within a state of the flow during execution of this
|
||||
* signalEvent operation
|
||||
* @see Flow#handleEvent(RequestControlContext)
|
||||
*/
|
||||
boolean handleEvent(Event event) throws FlowExecutionException;
|
||||
|
||||
/**
|
||||
* Execute this transition out of the current source state. Allows for privileged execution of an arbitrary
|
||||
* transition.
|
||||
* @param transition the transition
|
||||
* @see Transition#execute(State, RequestControlContext)
|
||||
*/
|
||||
boolean execute(Transition transition);
|
||||
|
||||
/**
|
||||
* Record the transition executing in the flow. This method will be called as part of executing a transition from
|
||||
* one state to another.
|
||||
* @param transition the transition being executed
|
||||
* @see Transition#execute(State, RequestControlContext)
|
||||
*/
|
||||
void setCurrentTransition(Transition transition);
|
||||
|
||||
/**
|
||||
* Update the current flow execution snapshot to save the current state.
|
||||
*/
|
||||
void updateCurrentFlowExecutionSnapshot();
|
||||
|
||||
/**
|
||||
* Remove the current flow execution snapshot to invalidate the current state.
|
||||
*/
|
||||
void removeCurrentFlowExecutionSnapshot();
|
||||
|
||||
/**
|
||||
* Remove all flow execution snapshots associated with the ongoing conversation. Invalidates previous states.
|
||||
*/
|
||||
void removeAllFlowExecutionSnapshots();
|
||||
|
||||
/**
|
||||
* Spawn a new flow session and activate it in the currently executing flow. Also transitions the spawned flow to
|
||||
* its start state. This method should be called by clients that wish to spawn new flows, such as subflow states.
|
||||
* <p>
|
||||
* This will start a new flow session in the current flow execution, which is already active.
|
||||
* @param flow the flow to start, its <code>start()</code> method will be called
|
||||
* @param input initial contents of the newly created flow session (may be <code>null</code>, e.g. empty)
|
||||
* @throws FlowExecutionException if an exception was thrown within a state of the flow during execution of this
|
||||
* start operation
|
||||
* @see Flow#start(RequestControlContext, MutableAttributeMap)
|
||||
*/
|
||||
void start(Flow flow, MutableAttributeMap<?> input) throws FlowExecutionException;
|
||||
|
||||
/**
|
||||
* End the active flow session of the current flow execution. This method should be called by clients that terminate
|
||||
* flows, such as end states. The <code>end()</code> method of the flow involved in the flow execution will be
|
||||
* called.
|
||||
* @param outcome the logical outcome the ending session should return
|
||||
* @param output output the ending session should return
|
||||
* @throws IllegalStateException when the flow execution is not active
|
||||
* @see Flow#end(RequestControlContext, String, MutableAttributeMap)
|
||||
*/
|
||||
void endActiveFlowSession(String outcome, MutableAttributeMap<Object> output) throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns true if the 'redirect on pause' flow execution attribute is set to true, false otherwise.
|
||||
* @return true or false
|
||||
*/
|
||||
boolean getRedirectOnPause();
|
||||
|
||||
/**
|
||||
* Returns the value of the 'redirect in same state' flow execution attribute if set or otherwise it falls back on
|
||||
* the value returned by {@link #getRedirectOnPause()}.
|
||||
* @return true or false
|
||||
*/
|
||||
boolean getRedirectInSameState();
|
||||
|
||||
/**
|
||||
* Returns true if the flow current flow execution was launched in embedded page mode. When a flow is embedded on a
|
||||
* page it can make different assumptions with regards to whether redirect after post is necessary.
|
||||
*/
|
||||
boolean getEmbeddedMode();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,240 +1,240 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
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.core.AnnotatedObject;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.definition.StateDefinition;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
|
||||
/**
|
||||
* A point in a flow where something happens. What happens is determined by a state's type. Standard types of states
|
||||
* include action states, view states, subflow states, and end states.
|
||||
* <p>
|
||||
* Each state is associated with exactly one owning flow definition. Specializations of this class capture all the
|
||||
* configuration information needed for a specific kind of state.
|
||||
* <p>
|
||||
* Subclasses should implement the <code>doEnter</code> method to execute the processing that should occur when this
|
||||
* state is entered, acting on its configuration information. The ability to plug-in custom state types that execute
|
||||
* different behaviors is the classic GoF state pattern.
|
||||
* <p>
|
||||
* Equality: Two states are equal if they have the same id and are part of the same flow.
|
||||
*
|
||||
* @see org.springframework.webflow.engine.TransitionableState
|
||||
* @see org.springframework.webflow.engine.ActionState
|
||||
* @see org.springframework.webflow.engine.ViewState
|
||||
* @see org.springframework.webflow.engine.SubflowState
|
||||
* @see org.springframework.webflow.engine.EndState
|
||||
* @see org.springframework.webflow.engine.DecisionState
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public abstract class State extends AnnotatedObject implements StateDefinition {
|
||||
|
||||
/**
|
||||
* Logger, for use in subclasses.
|
||||
*/
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
/**
|
||||
* The state's owning flow.
|
||||
*/
|
||||
private Flow flow;
|
||||
|
||||
/**
|
||||
* The state identifier, unique to the owning flow.
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* The list of actions to invoke when this state is entered.
|
||||
*/
|
||||
private ActionList entryActionList = new ActionList();
|
||||
|
||||
/**
|
||||
* The set of exception handlers for this state.
|
||||
*/
|
||||
private FlowExecutionExceptionHandlerSet exceptionHandlerSet = new FlowExecutionExceptionHandlerSet();
|
||||
|
||||
/**
|
||||
* Creates a state for the provided <code>flow</code> identified by the provided <code>id</code>. The id must be
|
||||
* locally unique to the owning flow. The state will be automatically added to the flow.
|
||||
* @param flow the owning flow
|
||||
* @param id the state identifier (must be unique to the flow)
|
||||
* @throws IllegalArgumentException if this state cannot be added to the flow, for instance when the provided id is
|
||||
* not unique in the owning flow
|
||||
* @see #getEntryActionList()
|
||||
* @see #getExceptionHandlerSet()
|
||||
*/
|
||||
protected State(Flow flow, String id) throws IllegalArgumentException {
|
||||
setId(id);
|
||||
setFlow(flow);
|
||||
}
|
||||
|
||||
// implementing StateDefinition
|
||||
|
||||
public FlowDefinition getOwner() {
|
||||
return flow;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public boolean isViewState() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// implementation specific
|
||||
|
||||
/**
|
||||
* Returns the owning flow.
|
||||
*/
|
||||
public Flow getFlow() {
|
||||
return flow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the owning flow.
|
||||
* @throws IllegalArgumentException if this state cannot be added to the flow
|
||||
*/
|
||||
private void setFlow(Flow flow) throws IllegalArgumentException {
|
||||
Assert.hasText(getId(), "The id of the state should be set before adding the state to a flow");
|
||||
Assert.notNull(flow, "The owning flow is required");
|
||||
this.flow = flow;
|
||||
flow.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state identifier, unique to the owning flow.
|
||||
* @param id the state identifier
|
||||
*/
|
||||
private void setId(String id) {
|
||||
Assert.hasText(id, "This state must have a valid identifier");
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of actions executed by this state when it is entered. The returned list is mutable.
|
||||
* @return the state entry action list
|
||||
*/
|
||||
public ActionList getEntryActionList() {
|
||||
return entryActionList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a mutable set of exception handlers, allowing manipulation of how exceptions are handled when thrown
|
||||
* within this state.
|
||||
* <p>
|
||||
* Exception handlers are invoked when an exception occurs when this state is entered, and can execute custom
|
||||
* exception handling logic as well as select an error view to display.
|
||||
* @return the state exception handler set
|
||||
*/
|
||||
public FlowExecutionExceptionHandlerSet getExceptionHandlerSet() {
|
||||
return exceptionHandlerSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a flag indicating if this state is the start state of its owning flow.
|
||||
* @return true if the flow is the start state, false otherwise
|
||||
*/
|
||||
public boolean isStartState() {
|
||||
return flow.getStartState() == this;
|
||||
}
|
||||
|
||||
// id and flow based equality
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof State)) {
|
||||
return false;
|
||||
}
|
||||
State other = (State) o;
|
||||
return id.equals(other.id) && flow.equals(other.flow);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return id.hashCode() + flow.hashCode();
|
||||
}
|
||||
|
||||
// behavioral methods
|
||||
|
||||
/**
|
||||
* Enter this state in the provided flow control context. This implementation just calls the
|
||||
* {@link #doEnter(RequestControlContext)} hook method, which should be implemented by subclasses, after executing
|
||||
* the entry actions.
|
||||
* @param context the control context for the currently executing flow, used by this state to manipulate the flow
|
||||
* execution
|
||||
* @throws FlowExecutionException if an exception occurs in this state
|
||||
*/
|
||||
public final void enter(RequestControlContext context) throws FlowExecutionException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Entering state '" + getId() + "' of flow '" + getFlow().getId() + "'");
|
||||
}
|
||||
context.setCurrentState(this);
|
||||
doPreEntryActions(context);
|
||||
entryActionList.execute(context);
|
||||
doEnter(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook method to execute before running state entry actions upon state entry. Does nothing by default. Subclasses
|
||||
* may override.
|
||||
* @param context the request control context
|
||||
* @throws FlowExecutionException if an exception occurs
|
||||
*/
|
||||
protected void doPreEntryActions(RequestControlContext context) throws FlowExecutionException {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook method to execute custom behavior as a result of entering this state. By implementing this method subclasses
|
||||
* specialize the behavior of the state.
|
||||
* @param context the control context for the currently executing flow, used by this state to manipulate the flow
|
||||
* execution
|
||||
* @throws FlowExecutionException if an exception occurs in this state
|
||||
*/
|
||||
protected abstract void doEnter(RequestControlContext context) throws FlowExecutionException;
|
||||
|
||||
/**
|
||||
* Handle an exception that occurred in this state during the context of the current flow execution request.
|
||||
* @param exception the exception that occurred
|
||||
* @param context the flow execution control context
|
||||
*/
|
||||
public boolean handleException(FlowExecutionException exception, RequestControlContext context) {
|
||||
return getExceptionHandlerSet().handleException(exception, context);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
ToStringCreator creator = new ToStringCreator(this).append("id", getId()).append("flow", flow.getId())
|
||||
.append("entryActionList", entryActionList).append("exceptionHandlerSet", exceptionHandlerSet);
|
||||
appendToString(creator);
|
||||
return creator.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override this hook method to print their internal state to a string. This default implementation
|
||||
* does nothing.
|
||||
* @param creator the toString creator, to print properties to string
|
||||
* @see #toString()
|
||||
*/
|
||||
protected void appendToString(ToStringCreator creator) {
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
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.core.AnnotatedObject;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.definition.StateDefinition;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
|
||||
/**
|
||||
* A point in a flow where something happens. What happens is determined by a state's type. Standard types of states
|
||||
* include action states, view states, subflow states, and end states.
|
||||
* <p>
|
||||
* Each state is associated with exactly one owning flow definition. Specializations of this class capture all the
|
||||
* configuration information needed for a specific kind of state.
|
||||
* <p>
|
||||
* Subclasses should implement the <code>doEnter</code> method to execute the processing that should occur when this
|
||||
* state is entered, acting on its configuration information. The ability to plug-in custom state types that execute
|
||||
* different behaviors is the classic GoF state pattern.
|
||||
* <p>
|
||||
* Equality: Two states are equal if they have the same id and are part of the same flow.
|
||||
*
|
||||
* @see org.springframework.webflow.engine.TransitionableState
|
||||
* @see org.springframework.webflow.engine.ActionState
|
||||
* @see org.springframework.webflow.engine.ViewState
|
||||
* @see org.springframework.webflow.engine.SubflowState
|
||||
* @see org.springframework.webflow.engine.EndState
|
||||
* @see org.springframework.webflow.engine.DecisionState
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public abstract class State extends AnnotatedObject implements StateDefinition {
|
||||
|
||||
/**
|
||||
* Logger, for use in subclasses.
|
||||
*/
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
/**
|
||||
* The state's owning flow.
|
||||
*/
|
||||
private Flow flow;
|
||||
|
||||
/**
|
||||
* The state identifier, unique to the owning flow.
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* The list of actions to invoke when this state is entered.
|
||||
*/
|
||||
private ActionList entryActionList = new ActionList();
|
||||
|
||||
/**
|
||||
* The set of exception handlers for this state.
|
||||
*/
|
||||
private FlowExecutionExceptionHandlerSet exceptionHandlerSet = new FlowExecutionExceptionHandlerSet();
|
||||
|
||||
/**
|
||||
* Creates a state for the provided <code>flow</code> identified by the provided <code>id</code>. The id must be
|
||||
* locally unique to the owning flow. The state will be automatically added to the flow.
|
||||
* @param flow the owning flow
|
||||
* @param id the state identifier (must be unique to the flow)
|
||||
* @throws IllegalArgumentException if this state cannot be added to the flow, for instance when the provided id is
|
||||
* not unique in the owning flow
|
||||
* @see #getEntryActionList()
|
||||
* @see #getExceptionHandlerSet()
|
||||
*/
|
||||
protected State(Flow flow, String id) throws IllegalArgumentException {
|
||||
setId(id);
|
||||
setFlow(flow);
|
||||
}
|
||||
|
||||
// implementing StateDefinition
|
||||
|
||||
public FlowDefinition getOwner() {
|
||||
return flow;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public boolean isViewState() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// implementation specific
|
||||
|
||||
/**
|
||||
* Returns the owning flow.
|
||||
*/
|
||||
public Flow getFlow() {
|
||||
return flow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the owning flow.
|
||||
* @throws IllegalArgumentException if this state cannot be added to the flow
|
||||
*/
|
||||
private void setFlow(Flow flow) throws IllegalArgumentException {
|
||||
Assert.hasText(getId(), "The id of the state should be set before adding the state to a flow");
|
||||
Assert.notNull(flow, "The owning flow is required");
|
||||
this.flow = flow;
|
||||
flow.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state identifier, unique to the owning flow.
|
||||
* @param id the state identifier
|
||||
*/
|
||||
private void setId(String id) {
|
||||
Assert.hasText(id, "This state must have a valid identifier");
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of actions executed by this state when it is entered. The returned list is mutable.
|
||||
* @return the state entry action list
|
||||
*/
|
||||
public ActionList getEntryActionList() {
|
||||
return entryActionList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a mutable set of exception handlers, allowing manipulation of how exceptions are handled when thrown
|
||||
* within this state.
|
||||
* <p>
|
||||
* Exception handlers are invoked when an exception occurs when this state is entered, and can execute custom
|
||||
* exception handling logic as well as select an error view to display.
|
||||
* @return the state exception handler set
|
||||
*/
|
||||
public FlowExecutionExceptionHandlerSet getExceptionHandlerSet() {
|
||||
return exceptionHandlerSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a flag indicating if this state is the start state of its owning flow.
|
||||
* @return true if the flow is the start state, false otherwise
|
||||
*/
|
||||
public boolean isStartState() {
|
||||
return flow.getStartState() == this;
|
||||
}
|
||||
|
||||
// id and flow based equality
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof State)) {
|
||||
return false;
|
||||
}
|
||||
State other = (State) o;
|
||||
return id.equals(other.id) && flow.equals(other.flow);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return id.hashCode() + flow.hashCode();
|
||||
}
|
||||
|
||||
// behavioral methods
|
||||
|
||||
/**
|
||||
* Enter this state in the provided flow control context. This implementation just calls the
|
||||
* {@link #doEnter(RequestControlContext)} hook method, which should be implemented by subclasses, after executing
|
||||
* the entry actions.
|
||||
* @param context the control context for the currently executing flow, used by this state to manipulate the flow
|
||||
* execution
|
||||
* @throws FlowExecutionException if an exception occurs in this state
|
||||
*/
|
||||
public final void enter(RequestControlContext context) throws FlowExecutionException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Entering state '" + getId() + "' of flow '" + getFlow().getId() + "'");
|
||||
}
|
||||
context.setCurrentState(this);
|
||||
doPreEntryActions(context);
|
||||
entryActionList.execute(context);
|
||||
doEnter(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook method to execute before running state entry actions upon state entry. Does nothing by default. Subclasses
|
||||
* may override.
|
||||
* @param context the request control context
|
||||
* @throws FlowExecutionException if an exception occurs
|
||||
*/
|
||||
protected void doPreEntryActions(RequestControlContext context) throws FlowExecutionException {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook method to execute custom behavior as a result of entering this state. By implementing this method subclasses
|
||||
* specialize the behavior of the state.
|
||||
* @param context the control context for the currently executing flow, used by this state to manipulate the flow
|
||||
* execution
|
||||
* @throws FlowExecutionException if an exception occurs in this state
|
||||
*/
|
||||
protected abstract void doEnter(RequestControlContext context) throws FlowExecutionException;
|
||||
|
||||
/**
|
||||
* Handle an exception that occurred in this state during the context of the current flow execution request.
|
||||
* @param exception the exception that occurred
|
||||
* @param context the flow execution control context
|
||||
*/
|
||||
public boolean handleException(FlowExecutionException exception, RequestControlContext context) {
|
||||
return getExceptionHandlerSet().handleException(exception, context);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
ToStringCreator creator = new ToStringCreator(this).append("id", getId()).append("flow", flow.getId())
|
||||
.append("entryActionList", entryActionList).append("exceptionHandlerSet", exceptionHandlerSet);
|
||||
appendToString(creator);
|
||||
return creator.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override this hook method to print their internal state to a string. This default implementation
|
||||
* does nothing.
|
||||
* @param creator the toString creator, to print properties to string
|
||||
* @see #toString()
|
||||
*/
|
||||
protected void appendToString(ToStringCreator creator) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,124 +1,124 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
|
||||
/**
|
||||
* A transitionable state that spawns a subflow when executed. When the subflow this state spawns ends, the ending
|
||||
* result is used as grounds for a state transition out of this state.
|
||||
* <p>
|
||||
* A subflow state may be configured to map input data from its flow -- acting as the parent flow -- down to the subflow
|
||||
* when the subflow is spawned. In addition, output data produced by the subflow may be mapped up to the parent flow
|
||||
* when the subflow ends and the parent flow resumes. See the {@link SubflowAttributeMapper} interface definition for
|
||||
* more information on how to do this. The logic for ending a subflow is located in the {@link EndState} implementation.
|
||||
*
|
||||
* @see org.springframework.webflow.engine.SubflowAttributeMapper
|
||||
* @see org.springframework.webflow.engine.EndState
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class SubflowState extends TransitionableState {
|
||||
|
||||
/**
|
||||
* The subflow that should be spawned when this subflow state is entered.
|
||||
*/
|
||||
private Expression subflow;
|
||||
|
||||
/**
|
||||
* The attribute mapper that should map attributes from the parent flow down to the spawned subflow and visa versa.
|
||||
*/
|
||||
private SubflowAttributeMapper subflowAttributeMapper;
|
||||
|
||||
/**
|
||||
* Create a new subflow state.
|
||||
* @param flow the owning flow
|
||||
* @param id the state identifier (must be unique to the flow)
|
||||
* @param subflow the subflow to spawn
|
||||
* @throws IllegalArgumentException when this state cannot be added to given flow, e.g. because the id is not unique
|
||||
* @see #setAttributeMapper(SubflowAttributeMapper)
|
||||
*/
|
||||
public SubflowState(Flow flow, String id, Expression subflow) throws IllegalArgumentException {
|
||||
super(flow, id);
|
||||
setSubflow(subflow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the subflow this state will call.
|
||||
*/
|
||||
private void setSubflow(Expression subflow) {
|
||||
Assert.notNull(subflow, "A subflow state must have a subflow; the subflow is required");
|
||||
this.subflow = subflow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the attribute mapper used to map model data between the parent and child flow.
|
||||
*/
|
||||
public void setAttributeMapper(SubflowAttributeMapper attributeMapper) {
|
||||
this.subflowAttributeMapper = attributeMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialization of State's <code>doEnter</code> template method that executes behaviour specific to this state
|
||||
* type in polymorphic fashion.
|
||||
* <p>
|
||||
* Entering this state, creates the subflow input map and spawns the subflow in the current flow execution.
|
||||
* @param context the control context for the currently executing flow, used by this state to manipulate the flow
|
||||
* execution
|
||||
* @throws FlowExecutionException if an exception occurs in this state
|
||||
*/
|
||||
protected void doEnter(RequestControlContext context) throws FlowExecutionException {
|
||||
MutableAttributeMap<Object> flowInput;
|
||||
if (subflowAttributeMapper != null) {
|
||||
flowInput = subflowAttributeMapper.createSubflowInput(context);
|
||||
} else {
|
||||
flowInput = new LocalAttributeMap<>();
|
||||
}
|
||||
Flow subflow = (Flow) this.subflow.getValue(context);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Calling subflow '" + subflow.getId() + "' with input " + flowInput);
|
||||
}
|
||||
context.start(subflow, flowInput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on completion of the subflow to handle the subflow result event as determined by the end state reached by
|
||||
* the subflow.
|
||||
*/
|
||||
public boolean handleEvent(RequestControlContext context) {
|
||||
if (subflowAttributeMapper != null) {
|
||||
AttributeMap<Object> subflowOutput = context.getCurrentEvent().getAttributes();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Mapping subflow output " + subflowOutput);
|
||||
}
|
||||
subflowAttributeMapper.mapSubflowOutput(subflowOutput, context);
|
||||
}
|
||||
return super.handleEvent(context);
|
||||
}
|
||||
|
||||
protected void appendToString(ToStringCreator creator) {
|
||||
creator.append("subflow", subflow).append("subflowAttributeMapper", subflowAttributeMapper);
|
||||
super.appendToString(creator);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
|
||||
/**
|
||||
* A transitionable state that spawns a subflow when executed. When the subflow this state spawns ends, the ending
|
||||
* result is used as grounds for a state transition out of this state.
|
||||
* <p>
|
||||
* A subflow state may be configured to map input data from its flow -- acting as the parent flow -- down to the subflow
|
||||
* when the subflow is spawned. In addition, output data produced by the subflow may be mapped up to the parent flow
|
||||
* when the subflow ends and the parent flow resumes. See the {@link SubflowAttributeMapper} interface definition for
|
||||
* more information on how to do this. The logic for ending a subflow is located in the {@link EndState} implementation.
|
||||
*
|
||||
* @see org.springframework.webflow.engine.SubflowAttributeMapper
|
||||
* @see org.springframework.webflow.engine.EndState
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class SubflowState extends TransitionableState {
|
||||
|
||||
/**
|
||||
* The subflow that should be spawned when this subflow state is entered.
|
||||
*/
|
||||
private Expression subflow;
|
||||
|
||||
/**
|
||||
* The attribute mapper that should map attributes from the parent flow down to the spawned subflow and visa versa.
|
||||
*/
|
||||
private SubflowAttributeMapper subflowAttributeMapper;
|
||||
|
||||
/**
|
||||
* Create a new subflow state.
|
||||
* @param flow the owning flow
|
||||
* @param id the state identifier (must be unique to the flow)
|
||||
* @param subflow the subflow to spawn
|
||||
* @throws IllegalArgumentException when this state cannot be added to given flow, e.g. because the id is not unique
|
||||
* @see #setAttributeMapper(SubflowAttributeMapper)
|
||||
*/
|
||||
public SubflowState(Flow flow, String id, Expression subflow) throws IllegalArgumentException {
|
||||
super(flow, id);
|
||||
setSubflow(subflow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the subflow this state will call.
|
||||
*/
|
||||
private void setSubflow(Expression subflow) {
|
||||
Assert.notNull(subflow, "A subflow state must have a subflow; the subflow is required");
|
||||
this.subflow = subflow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the attribute mapper used to map model data between the parent and child flow.
|
||||
*/
|
||||
public void setAttributeMapper(SubflowAttributeMapper attributeMapper) {
|
||||
this.subflowAttributeMapper = attributeMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialization of State's <code>doEnter</code> template method that executes behaviour specific to this state
|
||||
* type in polymorphic fashion.
|
||||
* <p>
|
||||
* Entering this state, creates the subflow input map and spawns the subflow in the current flow execution.
|
||||
* @param context the control context for the currently executing flow, used by this state to manipulate the flow
|
||||
* execution
|
||||
* @throws FlowExecutionException if an exception occurs in this state
|
||||
*/
|
||||
protected void doEnter(RequestControlContext context) throws FlowExecutionException {
|
||||
MutableAttributeMap<Object> flowInput;
|
||||
if (subflowAttributeMapper != null) {
|
||||
flowInput = subflowAttributeMapper.createSubflowInput(context);
|
||||
} else {
|
||||
flowInput = new LocalAttributeMap<>();
|
||||
}
|
||||
Flow subflow = (Flow) this.subflow.getValue(context);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Calling subflow '" + subflow.getId() + "' with input " + flowInput);
|
||||
}
|
||||
context.start(subflow, flowInput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on completion of the subflow to handle the subflow result event as determined by the end state reached by
|
||||
* the subflow.
|
||||
*/
|
||||
public boolean handleEvent(RequestControlContext context) {
|
||||
if (subflowAttributeMapper != null) {
|
||||
AttributeMap<Object> subflowOutput = context.getCurrentEvent().getAttributes();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Mapping subflow output " + subflowOutput);
|
||||
}
|
||||
subflowAttributeMapper.mapSubflowOutput(subflowOutput, context);
|
||||
}
|
||||
return super.handleEvent(context);
|
||||
}
|
||||
|
||||
protected void appendToString(ToStringCreator creator) {
|
||||
creator.append("subflow", subflow).append("subflowAttributeMapper", subflowAttributeMapper);
|
||||
super.appendToString(creator);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* A strategy for calculating the target state of a transition. This facilitates dynamic transition target state
|
||||
* resolution that takes into account runtime contextual information.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface TargetStateResolver {
|
||||
|
||||
/**
|
||||
* Resolve the target state of the transition from the source state in the current request context. Should never
|
||||
* return null.
|
||||
* @param transition the transition
|
||||
* @param sourceState the source state of the transition, could be null
|
||||
* @param context the current request context
|
||||
* @return the transition's target state - may be null if no state change should occur
|
||||
*/
|
||||
State resolveTargetState(Transition transition, State sourceState, RequestContext context);
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* A strategy for calculating the target state of a transition. This facilitates dynamic transition target state
|
||||
* resolution that takes into account runtime contextual information.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface TargetStateResolver {
|
||||
|
||||
/**
|
||||
* Resolve the target state of the transition from the source state in the current request context. Should never
|
||||
* return null.
|
||||
* @param transition the transition
|
||||
* @param sourceState the source state of the transition, could be null
|
||||
* @param context the current request context
|
||||
* @return the transition's target state - may be null if no state change should occur
|
||||
*/
|
||||
State resolveTargetState(Transition transition, State sourceState, RequestContext context);
|
||||
}
|
||||
@@ -1,249 +1,249 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
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.core.AnnotatedObject;
|
||||
import org.springframework.webflow.definition.TransitionDefinition;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* A path from one {@link TransitionableState state} to another {@link State state}.
|
||||
* <p>
|
||||
* When executed a transition takes a flow execution from its current state, called the <i>source state</i>, to another
|
||||
* state, called the <i>target state</i>. A transition may become eligible for execution on the occurrence of an
|
||||
* {@link Event} from within a transitionable source state.
|
||||
* <p>
|
||||
* When an event occurs within this transition's source <code>TransitionableState</code> the determination of the
|
||||
* eligibility of this transition is made by a <code>TransitionCriteria</code> object called the <i>matching
|
||||
* criteria</i>. If the matching criteria returns <code>true</code> this transition is marked eligible for execution for
|
||||
* that event.
|
||||
* <p>
|
||||
* Determination as to whether an eligible transition should be allowed to execute is made by a
|
||||
* <code>TransitionCriteria</code> object called the <i>execution criteria</i>. If the execution criteria test fails
|
||||
* this transition will <i>roll back</i> and reenter its source state. If the execution criteria test succeeds this
|
||||
* transition will execute and take the flow to the transition's target state.
|
||||
* <p>
|
||||
* The target state of this transition is typically specified at configuration time in a static manner. If the target
|
||||
* state of this transition needs to be calculated in a dynamic fashion at runtime configure a
|
||||
* {@link TargetStateResolver} that supports such calculations.
|
||||
*
|
||||
* @see TransitionableState
|
||||
* @see TransitionCriteria
|
||||
* @see TargetStateResolver
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class Transition extends AnnotatedObject implements TransitionDefinition {
|
||||
|
||||
/**
|
||||
* Logger, for use in subclasses.
|
||||
*/
|
||||
protected final Log logger = LogFactory.getLog(Transition.class);
|
||||
|
||||
/**
|
||||
* The criteria that determine whether or not this transition matches as eligible for execution when an event occurs
|
||||
* in the source state.
|
||||
*/
|
||||
private TransitionCriteria matchingCriteria;
|
||||
|
||||
/**
|
||||
* The criteria that determine whether or not this transition, once matched, should complete execution or should
|
||||
* <i>roll back</i>.
|
||||
*/
|
||||
private TransitionCriteria executionCriteria = WildcardTransitionCriteria.INSTANCE;
|
||||
|
||||
/**
|
||||
* The resolver responsible for calculating the target state of this transition.
|
||||
*/
|
||||
private TargetStateResolver targetStateResolver;
|
||||
|
||||
/**
|
||||
* Create a new transition that always matches and always executes, but its execution does nothing by default.
|
||||
* @see #setMatchingCriteria(TransitionCriteria)
|
||||
* @see #setExecutionCriteria(TransitionCriteria)
|
||||
* @see #setTargetStateResolver(TargetStateResolver)
|
||||
*/
|
||||
public Transition() {
|
||||
this(WildcardTransitionCriteria.INSTANCE, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new transition that always matches and always executes, transitioning to the target state calculated by
|
||||
* the provided targetStateResolver.
|
||||
* @param targetStateResolver the resolver of the target state of this transition
|
||||
* @see #setMatchingCriteria(TransitionCriteria)
|
||||
* @see #setExecutionCriteria(TransitionCriteria)
|
||||
*/
|
||||
public Transition(TargetStateResolver targetStateResolver) {
|
||||
this(WildcardTransitionCriteria.INSTANCE, targetStateResolver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new transition that matches on the specified criteria, transitioning to the target state calculated by
|
||||
* the provided targetStateResolver.
|
||||
* @param matchingCriteria the criteria for matching this transition
|
||||
* @param targetStateResolver the resolver of the target state of this transition
|
||||
* @see #setExecutionCriteria(TransitionCriteria)
|
||||
*/
|
||||
public Transition(TransitionCriteria matchingCriteria, TargetStateResolver targetStateResolver) {
|
||||
setMatchingCriteria(matchingCriteria);
|
||||
setTargetStateResolver(targetStateResolver);
|
||||
}
|
||||
|
||||
// implementing transition definition
|
||||
|
||||
public String getId() {
|
||||
return matchingCriteria.toString();
|
||||
}
|
||||
|
||||
public String getTargetStateId() {
|
||||
if (targetStateResolver != null) {
|
||||
return targetStateResolver.toString();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the criteria that determine whether or not this transition matches as eligible for execution.
|
||||
* @return the transition matching criteria
|
||||
*/
|
||||
public TransitionCriteria getMatchingCriteria() {
|
||||
return matchingCriteria;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the criteria that determine whether or not this transition matches as eligible for execution.
|
||||
* @param matchingCriteria the transition matching criteria
|
||||
*/
|
||||
public void setMatchingCriteria(TransitionCriteria matchingCriteria) {
|
||||
Assert.notNull(matchingCriteria, "The criteria for matching this transition is required");
|
||||
this.matchingCriteria = matchingCriteria;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the criteria that determine whether or not this transition, once matched, should complete execution or
|
||||
* should <i>roll back</i>.
|
||||
* @return the transition execution criteria
|
||||
*/
|
||||
public TransitionCriteria getExecutionCriteria() {
|
||||
return executionCriteria;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the criteria that determine whether or not this transition, once matched, should complete execution or should
|
||||
* <i>roll back</i>.
|
||||
* @param executionCriteria the transition execution criteria
|
||||
*/
|
||||
public void setExecutionCriteria(TransitionCriteria executionCriteria) {
|
||||
this.executionCriteria = executionCriteria;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this transition's target state resolver.
|
||||
*/
|
||||
public TargetStateResolver getTargetStateResolver() {
|
||||
return targetStateResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this transition's target state resolver, to calculate what state to transition to when this transition is
|
||||
* executed.
|
||||
* @param targetStateResolver the target state resolver
|
||||
*/
|
||||
public void setTargetStateResolver(TargetStateResolver targetStateResolver) {
|
||||
this.targetStateResolver = targetStateResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this transition is eligible for execution given the state of the provided flow execution request
|
||||
* context.
|
||||
* @param context the flow execution request context
|
||||
* @return true if this transition should execute, false otherwise
|
||||
*/
|
||||
public boolean matches(RequestContext context) {
|
||||
return matchingCriteria.test(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this transition can complete its execution or should be rolled back, given the state of the flow
|
||||
* execution request context.
|
||||
* @param context the flow execution request context
|
||||
* @return true if this transition can complete execution, false if it should roll back
|
||||
*/
|
||||
public boolean canExecute(RequestContext context) {
|
||||
if (executionCriteria != null) {
|
||||
return executionCriteria.test(context);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute this state transition. Should only be called if the {@link #matches(RequestContext)} method returns true
|
||||
* for the given context.
|
||||
* @param sourceState the source state to transition from, may be null if the current state is null
|
||||
* @param context the flow execution control context
|
||||
* @return a boolean indicating if executing this transition caused the current state to exit and a new state to
|
||||
* enter
|
||||
* @throws FlowExecutionException when transition execution fails
|
||||
*/
|
||||
public boolean execute(State sourceState, RequestControlContext context) throws FlowExecutionException {
|
||||
if (canExecute(context)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Executing " + this);
|
||||
}
|
||||
context.setCurrentTransition(this);
|
||||
if (targetStateResolver != null) {
|
||||
State targetState = targetStateResolver.resolveTargetState(this, sourceState, context);
|
||||
if (targetState != null) {
|
||||
if (sourceState != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Exiting state '" + sourceState.getId() + "'");
|
||||
}
|
||||
if (sourceState instanceof TransitionableState) {
|
||||
((TransitionableState) sourceState).exit(context);
|
||||
}
|
||||
}
|
||||
targetState.enter(context);
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (context.getFlowExecutionContext().isActive()) {
|
||||
logger.debug("Completed transition execution. As a result, the new state is '"
|
||||
+ context.getCurrentState().getId() + "' in flow '"
|
||||
+ context.getActiveFlow().getId() + "'");
|
||||
} else {
|
||||
logger.debug("Completed transition execution. As a result, the flow execution has ended");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("on", getMatchingCriteria()).append("to", getTargetStateResolver())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
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.core.AnnotatedObject;
|
||||
import org.springframework.webflow.definition.TransitionDefinition;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* A path from one {@link TransitionableState state} to another {@link State state}.
|
||||
* <p>
|
||||
* When executed a transition takes a flow execution from its current state, called the <i>source state</i>, to another
|
||||
* state, called the <i>target state</i>. A transition may become eligible for execution on the occurrence of an
|
||||
* {@link Event} from within a transitionable source state.
|
||||
* <p>
|
||||
* When an event occurs within this transition's source <code>TransitionableState</code> the determination of the
|
||||
* eligibility of this transition is made by a <code>TransitionCriteria</code> object called the <i>matching
|
||||
* criteria</i>. If the matching criteria returns <code>true</code> this transition is marked eligible for execution for
|
||||
* that event.
|
||||
* <p>
|
||||
* Determination as to whether an eligible transition should be allowed to execute is made by a
|
||||
* <code>TransitionCriteria</code> object called the <i>execution criteria</i>. If the execution criteria test fails
|
||||
* this transition will <i>roll back</i> and reenter its source state. If the execution criteria test succeeds this
|
||||
* transition will execute and take the flow to the transition's target state.
|
||||
* <p>
|
||||
* The target state of this transition is typically specified at configuration time in a static manner. If the target
|
||||
* state of this transition needs to be calculated in a dynamic fashion at runtime configure a
|
||||
* {@link TargetStateResolver} that supports such calculations.
|
||||
*
|
||||
* @see TransitionableState
|
||||
* @see TransitionCriteria
|
||||
* @see TargetStateResolver
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class Transition extends AnnotatedObject implements TransitionDefinition {
|
||||
|
||||
/**
|
||||
* Logger, for use in subclasses.
|
||||
*/
|
||||
protected final Log logger = LogFactory.getLog(Transition.class);
|
||||
|
||||
/**
|
||||
* The criteria that determine whether or not this transition matches as eligible for execution when an event occurs
|
||||
* in the source state.
|
||||
*/
|
||||
private TransitionCriteria matchingCriteria;
|
||||
|
||||
/**
|
||||
* The criteria that determine whether or not this transition, once matched, should complete execution or should
|
||||
* <i>roll back</i>.
|
||||
*/
|
||||
private TransitionCriteria executionCriteria = WildcardTransitionCriteria.INSTANCE;
|
||||
|
||||
/**
|
||||
* The resolver responsible for calculating the target state of this transition.
|
||||
*/
|
||||
private TargetStateResolver targetStateResolver;
|
||||
|
||||
/**
|
||||
* Create a new transition that always matches and always executes, but its execution does nothing by default.
|
||||
* @see #setMatchingCriteria(TransitionCriteria)
|
||||
* @see #setExecutionCriteria(TransitionCriteria)
|
||||
* @see #setTargetStateResolver(TargetStateResolver)
|
||||
*/
|
||||
public Transition() {
|
||||
this(WildcardTransitionCriteria.INSTANCE, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new transition that always matches and always executes, transitioning to the target state calculated by
|
||||
* the provided targetStateResolver.
|
||||
* @param targetStateResolver the resolver of the target state of this transition
|
||||
* @see #setMatchingCriteria(TransitionCriteria)
|
||||
* @see #setExecutionCriteria(TransitionCriteria)
|
||||
*/
|
||||
public Transition(TargetStateResolver targetStateResolver) {
|
||||
this(WildcardTransitionCriteria.INSTANCE, targetStateResolver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new transition that matches on the specified criteria, transitioning to the target state calculated by
|
||||
* the provided targetStateResolver.
|
||||
* @param matchingCriteria the criteria for matching this transition
|
||||
* @param targetStateResolver the resolver of the target state of this transition
|
||||
* @see #setExecutionCriteria(TransitionCriteria)
|
||||
*/
|
||||
public Transition(TransitionCriteria matchingCriteria, TargetStateResolver targetStateResolver) {
|
||||
setMatchingCriteria(matchingCriteria);
|
||||
setTargetStateResolver(targetStateResolver);
|
||||
}
|
||||
|
||||
// implementing transition definition
|
||||
|
||||
public String getId() {
|
||||
return matchingCriteria.toString();
|
||||
}
|
||||
|
||||
public String getTargetStateId() {
|
||||
if (targetStateResolver != null) {
|
||||
return targetStateResolver.toString();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the criteria that determine whether or not this transition matches as eligible for execution.
|
||||
* @return the transition matching criteria
|
||||
*/
|
||||
public TransitionCriteria getMatchingCriteria() {
|
||||
return matchingCriteria;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the criteria that determine whether or not this transition matches as eligible for execution.
|
||||
* @param matchingCriteria the transition matching criteria
|
||||
*/
|
||||
public void setMatchingCriteria(TransitionCriteria matchingCriteria) {
|
||||
Assert.notNull(matchingCriteria, "The criteria for matching this transition is required");
|
||||
this.matchingCriteria = matchingCriteria;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the criteria that determine whether or not this transition, once matched, should complete execution or
|
||||
* should <i>roll back</i>.
|
||||
* @return the transition execution criteria
|
||||
*/
|
||||
public TransitionCriteria getExecutionCriteria() {
|
||||
return executionCriteria;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the criteria that determine whether or not this transition, once matched, should complete execution or should
|
||||
* <i>roll back</i>.
|
||||
* @param executionCriteria the transition execution criteria
|
||||
*/
|
||||
public void setExecutionCriteria(TransitionCriteria executionCriteria) {
|
||||
this.executionCriteria = executionCriteria;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this transition's target state resolver.
|
||||
*/
|
||||
public TargetStateResolver getTargetStateResolver() {
|
||||
return targetStateResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this transition's target state resolver, to calculate what state to transition to when this transition is
|
||||
* executed.
|
||||
* @param targetStateResolver the target state resolver
|
||||
*/
|
||||
public void setTargetStateResolver(TargetStateResolver targetStateResolver) {
|
||||
this.targetStateResolver = targetStateResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this transition is eligible for execution given the state of the provided flow execution request
|
||||
* context.
|
||||
* @param context the flow execution request context
|
||||
* @return true if this transition should execute, false otherwise
|
||||
*/
|
||||
public boolean matches(RequestContext context) {
|
||||
return matchingCriteria.test(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this transition can complete its execution or should be rolled back, given the state of the flow
|
||||
* execution request context.
|
||||
* @param context the flow execution request context
|
||||
* @return true if this transition can complete execution, false if it should roll back
|
||||
*/
|
||||
public boolean canExecute(RequestContext context) {
|
||||
if (executionCriteria != null) {
|
||||
return executionCriteria.test(context);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute this state transition. Should only be called if the {@link #matches(RequestContext)} method returns true
|
||||
* for the given context.
|
||||
* @param sourceState the source state to transition from, may be null if the current state is null
|
||||
* @param context the flow execution control context
|
||||
* @return a boolean indicating if executing this transition caused the current state to exit and a new state to
|
||||
* enter
|
||||
* @throws FlowExecutionException when transition execution fails
|
||||
*/
|
||||
public boolean execute(State sourceState, RequestControlContext context) throws FlowExecutionException {
|
||||
if (canExecute(context)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Executing " + this);
|
||||
}
|
||||
context.setCurrentTransition(this);
|
||||
if (targetStateResolver != null) {
|
||||
State targetState = targetStateResolver.resolveTargetState(this, sourceState, context);
|
||||
if (targetState != null) {
|
||||
if (sourceState != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Exiting state '" + sourceState.getId() + "'");
|
||||
}
|
||||
if (sourceState instanceof TransitionableState) {
|
||||
((TransitionableState) sourceState).exit(context);
|
||||
}
|
||||
}
|
||||
targetState.enter(context);
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (context.getFlowExecutionContext().isActive()) {
|
||||
logger.debug("Completed transition execution. As a result, the new state is '"
|
||||
+ context.getCurrentState().getId() + "' in flow '"
|
||||
+ context.getActiveFlow().getId() + "'");
|
||||
} else {
|
||||
logger.debug("Completed transition execution. As a result, the flow execution has ended");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("on", getMatchingCriteria()).append("to", getTargetStateResolver())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* Strategy interface encapsulating criteria that determine whether or not a transition should execute given a flow
|
||||
* execution request context.
|
||||
*
|
||||
* @see org.springframework.webflow.engine.Transition
|
||||
* @see org.springframework.webflow.execution.RequestContext
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface TransitionCriteria {
|
||||
|
||||
/**
|
||||
* Check if the transition should fire based on the given flow execution request context.
|
||||
* @param context the flow execution request context
|
||||
* @return true if the transition should fire, false otherwise
|
||||
*/
|
||||
boolean test(RequestContext context);
|
||||
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* Strategy interface encapsulating criteria that determine whether or not a transition should execute given a flow
|
||||
* execution request context.
|
||||
*
|
||||
* @see org.springframework.webflow.engine.Transition
|
||||
* @see org.springframework.webflow.execution.RequestContext
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface TransitionCriteria {
|
||||
|
||||
/**
|
||||
* Check if the transition should fire based on the given flow execution request context.
|
||||
* @param context the flow execution request context
|
||||
* @return true if the transition should fire, false otherwise
|
||||
*/
|
||||
boolean test(RequestContext context);
|
||||
|
||||
}
|
||||
@@ -1,142 +1,142 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.webflow.core.collection.CollectionUtils;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* A typed set of transitions for use internally by artifacts that can apply transition execution logic.
|
||||
*
|
||||
* @see TransitionableState#getTransitionSet()
|
||||
* @see Flow#getGlobalTransitionSet()
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class TransitionSet implements Iterable<Transition> {
|
||||
|
||||
/**
|
||||
* The set of transitions.
|
||||
*/
|
||||
private List<Transition> transitions = new LinkedList<>();
|
||||
|
||||
/**
|
||||
* Add a transition to this set.
|
||||
* @param transition the transition to add
|
||||
* @return true if this set's contents changed as a result of the add operation
|
||||
*/
|
||||
public boolean add(Transition transition) {
|
||||
if (contains(transition)) {
|
||||
return false;
|
||||
}
|
||||
return transitions.add(transition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a collection of transition instances to this set.
|
||||
* @param transitions the transitions to add
|
||||
* @return true if this set's contents changed as a result of the add operation
|
||||
*/
|
||||
public boolean addAll(Transition... transitions) {
|
||||
return CollectionUtils.addAllNoDuplicates(this.transitions, transitions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if this transition is in this set.
|
||||
* @param transition the transition
|
||||
* @return true if the transition is contained in this set, false otherwise
|
||||
*/
|
||||
public boolean contains(Transition transition) {
|
||||
return transitions.contains(transition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the transition instance from this set.
|
||||
* @param transition the transition to remove
|
||||
* @return true if this list's contents changed as a result of the remove operation
|
||||
*/
|
||||
public boolean remove(Transition transition) {
|
||||
return transitions.remove(transition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of this transition set.
|
||||
* @return the exception handler set size
|
||||
*/
|
||||
public int size() {
|
||||
return transitions.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over this transition set.
|
||||
* @return an iterator
|
||||
*/
|
||||
public Iterator<Transition> iterator() {
|
||||
return transitions.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this set to a typed transition array.
|
||||
* @return the transition set as a typed array
|
||||
*/
|
||||
public Transition[] toArray() {
|
||||
return transitions.toArray(new Transition[transitions.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the supported transitional criteria used to match transitions in this state.
|
||||
* @return the list of transitional criteria
|
||||
*/
|
||||
public TransitionCriteria[] getTransitionCriterias() {
|
||||
TransitionCriteria[] criterias = new TransitionCriteria[transitions.size()];
|
||||
int i = 0;
|
||||
for (Transition transition : transitions) {
|
||||
criterias[i++] = transition.getMatchingCriteria();
|
||||
}
|
||||
return criterias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a transition for given flow execution request context. The first matching transition will be returned.
|
||||
* @param context a flow execution context
|
||||
* @return the transition, or null if no transition matches
|
||||
*/
|
||||
public Transition getTransition(RequestContext context) {
|
||||
for (Transition transition : transitions) {
|
||||
if (transition.matches(context)) {
|
||||
return transition;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this list has a transition that will fire for given flow execution request context.
|
||||
* @param context a flow execution context
|
||||
*/
|
||||
public boolean hasMatchingTransition(RequestContext context) {
|
||||
return getTransition(context) != null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return StylerUtils.style(transitions);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.webflow.core.collection.CollectionUtils;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* A typed set of transitions for use internally by artifacts that can apply transition execution logic.
|
||||
*
|
||||
* @see TransitionableState#getTransitionSet()
|
||||
* @see Flow#getGlobalTransitionSet()
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class TransitionSet implements Iterable<Transition> {
|
||||
|
||||
/**
|
||||
* The set of transitions.
|
||||
*/
|
||||
private List<Transition> transitions = new LinkedList<>();
|
||||
|
||||
/**
|
||||
* Add a transition to this set.
|
||||
* @param transition the transition to add
|
||||
* @return true if this set's contents changed as a result of the add operation
|
||||
*/
|
||||
public boolean add(Transition transition) {
|
||||
if (contains(transition)) {
|
||||
return false;
|
||||
}
|
||||
return transitions.add(transition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a collection of transition instances to this set.
|
||||
* @param transitions the transitions to add
|
||||
* @return true if this set's contents changed as a result of the add operation
|
||||
*/
|
||||
public boolean addAll(Transition... transitions) {
|
||||
return CollectionUtils.addAllNoDuplicates(this.transitions, transitions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if this transition is in this set.
|
||||
* @param transition the transition
|
||||
* @return true if the transition is contained in this set, false otherwise
|
||||
*/
|
||||
public boolean contains(Transition transition) {
|
||||
return transitions.contains(transition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the transition instance from this set.
|
||||
* @param transition the transition to remove
|
||||
* @return true if this list's contents changed as a result of the remove operation
|
||||
*/
|
||||
public boolean remove(Transition transition) {
|
||||
return transitions.remove(transition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of this transition set.
|
||||
* @return the exception handler set size
|
||||
*/
|
||||
public int size() {
|
||||
return transitions.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over this transition set.
|
||||
* @return an iterator
|
||||
*/
|
||||
public Iterator<Transition> iterator() {
|
||||
return transitions.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this set to a typed transition array.
|
||||
* @return the transition set as a typed array
|
||||
*/
|
||||
public Transition[] toArray() {
|
||||
return transitions.toArray(new Transition[transitions.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the supported transitional criteria used to match transitions in this state.
|
||||
* @return the list of transitional criteria
|
||||
*/
|
||||
public TransitionCriteria[] getTransitionCriterias() {
|
||||
TransitionCriteria[] criterias = new TransitionCriteria[transitions.size()];
|
||||
int i = 0;
|
||||
for (Transition transition : transitions) {
|
||||
criterias[i++] = transition.getMatchingCriteria();
|
||||
}
|
||||
return criterias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a transition for given flow execution request context. The first matching transition will be returned.
|
||||
* @param context a flow execution context
|
||||
* @return the transition, or null if no transition matches
|
||||
*/
|
||||
public Transition getTransition(RequestContext context) {
|
||||
for (Transition transition : transitions) {
|
||||
if (transition.matches(context)) {
|
||||
return transition;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this list has a transition that will fire for given flow execution request context.
|
||||
* @param context a flow execution context
|
||||
*/
|
||||
public boolean hasMatchingTransition(RequestContext context) {
|
||||
return getTransition(context) != null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return StylerUtils.style(transitions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,131 +1,131 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.webflow.definition.TransitionDefinition;
|
||||
import org.springframework.webflow.definition.TransitionableStateDefinition;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* Abstract superclass for states that can execute a transition in response to an event.
|
||||
*
|
||||
* @see org.springframework.webflow.engine.Transition
|
||||
* @see org.springframework.webflow.engine.TransitionCriteria
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public abstract class TransitionableState extends State implements TransitionableStateDefinition {
|
||||
|
||||
/**
|
||||
* The set of possible transitions out of this state.
|
||||
*/
|
||||
private TransitionSet transitions = new TransitionSet();
|
||||
|
||||
/**
|
||||
* An actions to execute when exiting this state.
|
||||
*/
|
||||
private ActionList exitActionList = new ActionList();
|
||||
|
||||
/**
|
||||
* Create a new transitionable state.
|
||||
* @param flow the owning flow
|
||||
* @param id the state identifier (must be unique to the flow)
|
||||
* @throws IllegalArgumentException when this state cannot be added to given flow, for instance when the id is not
|
||||
* unique
|
||||
* @see State#State(Flow, String)
|
||||
* @see #getTransitionSet()
|
||||
*/
|
||||
protected TransitionableState(Flow flow, String id) throws IllegalArgumentException {
|
||||
super(flow, id);
|
||||
}
|
||||
|
||||
// implementing TranstionableStateDefinition
|
||||
|
||||
public TransitionDefinition[] getTransitions() {
|
||||
return getTransitionSet().toArray();
|
||||
}
|
||||
|
||||
public TransitionDefinition getTransition(String eventId) {
|
||||
for (Transition transition : transitions) {
|
||||
if (transition.getId().equals(eventId)) {
|
||||
return transition;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// impl
|
||||
|
||||
/**
|
||||
* Returns the set of transitions. The returned set is mutable.
|
||||
*/
|
||||
public TransitionSet getTransitionSet() {
|
||||
return transitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a transition in this state for given flow execution request context. Throws and exception when there is no
|
||||
* corresponding transition.
|
||||
* @throws NoMatchingTransitionException when a matching transition cannot be found
|
||||
*/
|
||||
public Transition getRequiredTransition(RequestContext context) throws NoMatchingTransitionException {
|
||||
Transition transition = getTransitionSet().getTransition(context);
|
||||
if (transition == null) {
|
||||
throw new NoMatchingTransitionException(getFlow().getId(), getId(), context.getCurrentEvent(),
|
||||
"No transition found on occurence of event '" + context.getCurrentEvent() + "' in state '"
|
||||
+ getId() + "' of flow '" + getFlow().getId() + "' -- valid transitional criteria are "
|
||||
+ StylerUtils.style(getTransitionSet().getTransitionCriterias())
|
||||
+ " -- likely programmer error, check the set of TransitionCriteria for this state");
|
||||
}
|
||||
return transition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of actions executed by this state when it is exited. The returned list is mutable.
|
||||
* @return the state exit action list
|
||||
*/
|
||||
public ActionList getExitActionList() {
|
||||
return exitActionList;
|
||||
}
|
||||
|
||||
// behavioral methods
|
||||
|
||||
/**
|
||||
* Inform this state definition that an event was signaled in it. The signaled event is the last event available in
|
||||
* given request context ({@link RequestContext#getCurrentEvent()}).
|
||||
* @param context the flow execution control context
|
||||
* @throws NoMatchingTransitionException when a matching transition cannot be found
|
||||
*/
|
||||
public boolean handleEvent(RequestControlContext context) throws NoMatchingTransitionException {
|
||||
return context.execute(getRequiredTransition(context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit this state. This is typically called when a transition takes the flow out of this state into another state.
|
||||
* By default just executes any registered exit actions.
|
||||
* @param context the flow control context
|
||||
*/
|
||||
public void exit(RequestControlContext context) {
|
||||
exitActionList.execute(context);
|
||||
}
|
||||
|
||||
protected void appendToString(ToStringCreator creator) {
|
||||
creator.append("transitions", transitions).append("exitActionList", exitActionList);
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.webflow.definition.TransitionDefinition;
|
||||
import org.springframework.webflow.definition.TransitionableStateDefinition;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* Abstract superclass for states that can execute a transition in response to an event.
|
||||
*
|
||||
* @see org.springframework.webflow.engine.Transition
|
||||
* @see org.springframework.webflow.engine.TransitionCriteria
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public abstract class TransitionableState extends State implements TransitionableStateDefinition {
|
||||
|
||||
/**
|
||||
* The set of possible transitions out of this state.
|
||||
*/
|
||||
private TransitionSet transitions = new TransitionSet();
|
||||
|
||||
/**
|
||||
* An actions to execute when exiting this state.
|
||||
*/
|
||||
private ActionList exitActionList = new ActionList();
|
||||
|
||||
/**
|
||||
* Create a new transitionable state.
|
||||
* @param flow the owning flow
|
||||
* @param id the state identifier (must be unique to the flow)
|
||||
* @throws IllegalArgumentException when this state cannot be added to given flow, for instance when the id is not
|
||||
* unique
|
||||
* @see State#State(Flow, String)
|
||||
* @see #getTransitionSet()
|
||||
*/
|
||||
protected TransitionableState(Flow flow, String id) throws IllegalArgumentException {
|
||||
super(flow, id);
|
||||
}
|
||||
|
||||
// implementing TranstionableStateDefinition
|
||||
|
||||
public TransitionDefinition[] getTransitions() {
|
||||
return getTransitionSet().toArray();
|
||||
}
|
||||
|
||||
public TransitionDefinition getTransition(String eventId) {
|
||||
for (Transition transition : transitions) {
|
||||
if (transition.getId().equals(eventId)) {
|
||||
return transition;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// impl
|
||||
|
||||
/**
|
||||
* Returns the set of transitions. The returned set is mutable.
|
||||
*/
|
||||
public TransitionSet getTransitionSet() {
|
||||
return transitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a transition in this state for given flow execution request context. Throws and exception when there is no
|
||||
* corresponding transition.
|
||||
* @throws NoMatchingTransitionException when a matching transition cannot be found
|
||||
*/
|
||||
public Transition getRequiredTransition(RequestContext context) throws NoMatchingTransitionException {
|
||||
Transition transition = getTransitionSet().getTransition(context);
|
||||
if (transition == null) {
|
||||
throw new NoMatchingTransitionException(getFlow().getId(), getId(), context.getCurrentEvent(),
|
||||
"No transition found on occurence of event '" + context.getCurrentEvent() + "' in state '"
|
||||
+ getId() + "' of flow '" + getFlow().getId() + "' -- valid transitional criteria are "
|
||||
+ StylerUtils.style(getTransitionSet().getTransitionCriterias())
|
||||
+ " -- likely programmer error, check the set of TransitionCriteria for this state");
|
||||
}
|
||||
return transition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of actions executed by this state when it is exited. The returned list is mutable.
|
||||
* @return the state exit action list
|
||||
*/
|
||||
public ActionList getExitActionList() {
|
||||
return exitActionList;
|
||||
}
|
||||
|
||||
// behavioral methods
|
||||
|
||||
/**
|
||||
* Inform this state definition that an event was signaled in it. The signaled event is the last event available in
|
||||
* given request context ({@link RequestContext#getCurrentEvent()}).
|
||||
* @param context the flow execution control context
|
||||
* @throws NoMatchingTransitionException when a matching transition cannot be found
|
||||
*/
|
||||
public boolean handleEvent(RequestControlContext context) throws NoMatchingTransitionException {
|
||||
return context.execute(getRequiredTransition(context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit this state. This is typically called when a transition takes the flow out of this state into another state.
|
||||
* By default just executes any registered exit actions.
|
||||
* @param context the flow control context
|
||||
*/
|
||||
public void exit(RequestControlContext context) {
|
||||
exitActionList.execute(context);
|
||||
}
|
||||
|
||||
protected void appendToString(ToStringCreator creator) {
|
||||
creator.append("transitions", transitions).append("exitActionList", exitActionList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,63 +1,63 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* Transition criteria that always returns true.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class WildcardTransitionCriteria implements TransitionCriteria, Serializable {
|
||||
|
||||
/*
|
||||
* Implementation note: not located in webflow.execution.support package to avoid a cyclic dependency between
|
||||
* webflow.execution and webflow.execution.support.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Event id value ("*") that will cause the transition to match on any event.
|
||||
*/
|
||||
public static final String WILDCARD_EVENT_ID = "*";
|
||||
|
||||
/**
|
||||
* Shared instance of a TransitionCriteria that always returns true.
|
||||
*/
|
||||
public static final WildcardTransitionCriteria INSTANCE = new WildcardTransitionCriteria();
|
||||
|
||||
/**
|
||||
* Private constructor because this is a singleton.
|
||||
*/
|
||||
private WildcardTransitionCriteria() {
|
||||
}
|
||||
|
||||
public boolean test(RequestContext context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// resolve the singleton instance
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return WILDCARD_EVENT_ID;
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* Transition criteria that always returns true.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class WildcardTransitionCriteria implements TransitionCriteria, Serializable {
|
||||
|
||||
/*
|
||||
* Implementation note: not located in webflow.execution.support package to avoid a cyclic dependency between
|
||||
* webflow.execution and webflow.execution.support.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Event id value ("*") that will cause the transition to match on any event.
|
||||
*/
|
||||
public static final String WILDCARD_EVENT_ID = "*";
|
||||
|
||||
/**
|
||||
* Shared instance of a TransitionCriteria that always returns true.
|
||||
*/
|
||||
public static final WildcardTransitionCriteria INSTANCE = new WildcardTransitionCriteria();
|
||||
|
||||
/**
|
||||
* Private constructor because this is a singleton.
|
||||
*/
|
||||
private WildcardTransitionCriteria() {
|
||||
}
|
||||
|
||||
public boolean test(RequestContext context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// resolve the singleton instance
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return WILDCARD_EVENT_ID;
|
||||
}
|
||||
}
|
||||
@@ -1,125 +1,125 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.builder;
|
||||
|
||||
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;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionConstructionException;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionHolder;
|
||||
|
||||
/**
|
||||
* A flow definition holder that can detect changes on an underlying flow definition resource and refresh that resource
|
||||
* automatically.
|
||||
* <p>
|
||||
* This class is thread-safe.
|
||||
* <p>
|
||||
* Note that this {@link FlowDefinition} holder uses a {@link FlowAssembler}. This class bridges the <i>abstract</i>
|
||||
* world of {@link FlowDefinition flow definitions} with the <i>concrete</i> world of flow implementations.
|
||||
*
|
||||
* @see FlowAssembler
|
||||
* @see FlowDefinition
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class DefaultFlowHolder implements FlowDefinitionHolder {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(DefaultFlowHolder.class);
|
||||
|
||||
/**
|
||||
* The flow definition assembled by this assembler, initially null.
|
||||
*/
|
||||
private FlowDefinition flowDefinition;
|
||||
|
||||
/**
|
||||
* The flow assembler.
|
||||
*/
|
||||
private FlowAssembler assembler;
|
||||
|
||||
/**
|
||||
* A flag indicating whether or not this holder is in the middle of the assembly process.
|
||||
*/
|
||||
private boolean assembling;
|
||||
|
||||
/**
|
||||
* Creates a new refreshable flow definition holder that uses the configured assembler (GOF director) to drive flow
|
||||
* assembly, on initial use and on any resource change or refresh.
|
||||
* @param assembler the flow assembler to use
|
||||
*/
|
||||
public DefaultFlowHolder(FlowAssembler assembler) {
|
||||
Assert.notNull(assembler, "The FlowAssembler is required");
|
||||
this.assembler = assembler;
|
||||
}
|
||||
|
||||
public String getFlowDefinitionId() {
|
||||
return assembler.getFlowBuilderContext().getFlowId();
|
||||
}
|
||||
|
||||
public String getFlowDefinitionResourceString() {
|
||||
return assembler.getFlowBuilder().getFlowResourceString();
|
||||
}
|
||||
|
||||
public synchronized FlowDefinition getFlowDefinition() throws FlowDefinitionConstructionException {
|
||||
if (assembling) {
|
||||
// must return early assembly result for when a flow calls itself recursively
|
||||
return getFlowBuilder().getFlow();
|
||||
}
|
||||
if (flowDefinition == null) {
|
||||
logger.debug("Assembling the flow for the first time");
|
||||
assembleFlow();
|
||||
} else {
|
||||
if (flowDefinition.inDevelopment() && getFlowBuilder().hasFlowChanged()) {
|
||||
logger.debug("The flow under development has changed; reassembling...");
|
||||
assembleFlow();
|
||||
}
|
||||
}
|
||||
return flowDefinition;
|
||||
}
|
||||
|
||||
public synchronized void refresh() throws FlowDefinitionConstructionException {
|
||||
assembleFlow();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if (flowDefinition != null) {
|
||||
flowDefinition.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private void assembleFlow() throws FlowDefinitionConstructionException {
|
||||
try {
|
||||
assembling = true;
|
||||
flowDefinition = assembler.assembleFlow();
|
||||
} catch (FlowBuilderException e) {
|
||||
throw new FlowDefinitionConstructionException(assembler.getFlowBuilderContext().getFlowId(), e);
|
||||
} finally {
|
||||
assembling = false;
|
||||
}
|
||||
}
|
||||
|
||||
private FlowBuilder getFlowBuilder() {
|
||||
return assembler.getFlowBuilder();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("flowBuilder", assembler.getFlowBuilder()).toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.builder;
|
||||
|
||||
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;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionConstructionException;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionHolder;
|
||||
|
||||
/**
|
||||
* A flow definition holder that can detect changes on an underlying flow definition resource and refresh that resource
|
||||
* automatically.
|
||||
* <p>
|
||||
* This class is thread-safe.
|
||||
* <p>
|
||||
* Note that this {@link FlowDefinition} holder uses a {@link FlowAssembler}. This class bridges the <i>abstract</i>
|
||||
* world of {@link FlowDefinition flow definitions} with the <i>concrete</i> world of flow implementations.
|
||||
*
|
||||
* @see FlowAssembler
|
||||
* @see FlowDefinition
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class DefaultFlowHolder implements FlowDefinitionHolder {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(DefaultFlowHolder.class);
|
||||
|
||||
/**
|
||||
* The flow definition assembled by this assembler, initially null.
|
||||
*/
|
||||
private FlowDefinition flowDefinition;
|
||||
|
||||
/**
|
||||
* The flow assembler.
|
||||
*/
|
||||
private FlowAssembler assembler;
|
||||
|
||||
/**
|
||||
* A flag indicating whether or not this holder is in the middle of the assembly process.
|
||||
*/
|
||||
private boolean assembling;
|
||||
|
||||
/**
|
||||
* Creates a new refreshable flow definition holder that uses the configured assembler (GOF director) to drive flow
|
||||
* assembly, on initial use and on any resource change or refresh.
|
||||
* @param assembler the flow assembler to use
|
||||
*/
|
||||
public DefaultFlowHolder(FlowAssembler assembler) {
|
||||
Assert.notNull(assembler, "The FlowAssembler is required");
|
||||
this.assembler = assembler;
|
||||
}
|
||||
|
||||
public String getFlowDefinitionId() {
|
||||
return assembler.getFlowBuilderContext().getFlowId();
|
||||
}
|
||||
|
||||
public String getFlowDefinitionResourceString() {
|
||||
return assembler.getFlowBuilder().getFlowResourceString();
|
||||
}
|
||||
|
||||
public synchronized FlowDefinition getFlowDefinition() throws FlowDefinitionConstructionException {
|
||||
if (assembling) {
|
||||
// must return early assembly result for when a flow calls itself recursively
|
||||
return getFlowBuilder().getFlow();
|
||||
}
|
||||
if (flowDefinition == null) {
|
||||
logger.debug("Assembling the flow for the first time");
|
||||
assembleFlow();
|
||||
} else {
|
||||
if (flowDefinition.inDevelopment() && getFlowBuilder().hasFlowChanged()) {
|
||||
logger.debug("The flow under development has changed; reassembling...");
|
||||
assembleFlow();
|
||||
}
|
||||
}
|
||||
return flowDefinition;
|
||||
}
|
||||
|
||||
public synchronized void refresh() throws FlowDefinitionConstructionException {
|
||||
assembleFlow();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if (flowDefinition != null) {
|
||||
flowDefinition.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private void assembleFlow() throws FlowDefinitionConstructionException {
|
||||
try {
|
||||
assembling = true;
|
||||
flowDefinition = assembler.assembleFlow();
|
||||
} catch (FlowBuilderException e) {
|
||||
throw new FlowDefinitionConstructionException(assembler.getFlowBuilderContext().getFlowId(), e);
|
||||
} finally {
|
||||
assembling = false;
|
||||
}
|
||||
}
|
||||
|
||||
private FlowBuilder getFlowBuilder() {
|
||||
return assembler.getFlowBuilder();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("flowBuilder", assembler.getFlowBuilder()).toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,239 +1,239 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.builder;
|
||||
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.mapping.Mapper;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.engine.ActionState;
|
||||
import org.springframework.webflow.engine.DecisionState;
|
||||
import org.springframework.webflow.engine.EndState;
|
||||
import org.springframework.webflow.engine.Flow;
|
||||
import org.springframework.webflow.engine.FlowExecutionExceptionHandler;
|
||||
import org.springframework.webflow.engine.State;
|
||||
import org.springframework.webflow.engine.SubflowAttributeMapper;
|
||||
import org.springframework.webflow.engine.SubflowState;
|
||||
import org.springframework.webflow.engine.TargetStateResolver;
|
||||
import org.springframework.webflow.engine.Transition;
|
||||
import org.springframework.webflow.engine.TransitionCriteria;
|
||||
import org.springframework.webflow.engine.TransitionableState;
|
||||
import org.springframework.webflow.engine.ViewState;
|
||||
import org.springframework.webflow.engine.ViewVariable;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
import org.springframework.webflow.execution.ViewFactory;
|
||||
|
||||
/**
|
||||
* A factory for core web flow elements such as {@link Flow flows}, {@link State states}, and {@link Transition
|
||||
* transitions}.
|
||||
* <p>
|
||||
* This factory encapsulates the construction of each Flow implementation as well as each core artifact type. Subclasses
|
||||
* may customize how the core elements are created.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class FlowArtifactFactory {
|
||||
|
||||
/**
|
||||
* Factory method that creates a new {@link Flow} definition object.
|
||||
* <p>
|
||||
* Note this method does not return a fully configured Flow instance, it only encapsulates the selection of
|
||||
* implementation. A {@link FlowAssembler} delegating to a calling {@link FlowBuilder} is expected to assemble the
|
||||
* Flow fully before returning it to external clients.
|
||||
* @param id the flow identifier, should be unique to all flows in an application (required)
|
||||
* @param attributes attributes to assign to the Flow, which may also be used to affect flow construction; may be
|
||||
* null
|
||||
* @return the initial flow instance, ready for assembly by a FlowBuilder
|
||||
*/
|
||||
public Flow createFlow(String id, AttributeMap<?> attributes) {
|
||||
return Flow.create(id, attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that creates a new view state, a state where a user is allowed to participate in the flow. This
|
||||
* method is an atomic operation that returns a fully initialized state. It encapsulates the selection of the view
|
||||
* state implementation as well as the state assembly.
|
||||
* @param id the identifier to assign to the state, must be unique to its owning flow (required)
|
||||
* @param flow the flow that will own (contain) this state (required)
|
||||
* @param entryActions any state entry actions; may be null
|
||||
* @param viewFactory the state view factory strategy
|
||||
* @param redirect whether to send a flow execution redirect before rendering
|
||||
* @param popup whether to display the view in a popup window
|
||||
* @param renderActions any 'render actions' to execute on entry and refresh; may be null
|
||||
* @param transitions any transitions (paths) out of this state; may be null
|
||||
* @param exceptionHandlers any exception handlers; may be null
|
||||
* @param exitActions any state exit actions; may be null
|
||||
* @param attributes attributes to assign to the State, which may also be used to affect state construction; may be
|
||||
* null
|
||||
* @return the fully initialized view state instance
|
||||
*/
|
||||
public State createViewState(String id, Flow flow, ViewVariable[] variables, Action[] entryActions,
|
||||
ViewFactory viewFactory, Boolean redirect, boolean popup, Action[] renderActions, Transition[] transitions,
|
||||
FlowExecutionExceptionHandler[] exceptionHandlers, Action[] exitActions, AttributeMap<?> attributes) {
|
||||
ViewState viewState = new ViewState(flow, id, viewFactory);
|
||||
viewState.addVariables(variables);
|
||||
viewState.setRedirect(redirect);
|
||||
viewState.setPopup(popup);
|
||||
viewState.getRenderActionList().addAll(renderActions);
|
||||
configureCommonProperties(viewState, entryActions, transitions, exceptionHandlers, exitActions, attributes);
|
||||
return viewState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that creates a new action state, a state where a system action is executed. This method is an
|
||||
* atomic operation that returns a fully initialized state. It encapsulates the selection of the action state
|
||||
* implementation as well as the state assembly.
|
||||
* @param id the identifier to assign to the state, must be unique to its owning flow (required)
|
||||
* @param flow the flow that will own (contain) this state (required)
|
||||
* @param entryActions any state entry actions; may be null
|
||||
* @param actions the actions to execute when the state is entered (required)
|
||||
* @param transitions any transitions (paths) out of this state; may be null
|
||||
* @param exceptionHandlers any exception handlers; may be null
|
||||
* @param exitActions any state exit actions; may be null
|
||||
* @param attributes attributes to assign to the State, which may also be used to affect state construction; may be
|
||||
* null
|
||||
* @return the fully initialized action state instance
|
||||
*/
|
||||
public State createActionState(String id, Flow flow, Action[] entryActions, Action[] actions,
|
||||
Transition[] transitions, FlowExecutionExceptionHandler[] exceptionHandlers, Action[] exitActions,
|
||||
AttributeMap<?> attributes) {
|
||||
ActionState actionState = new ActionState(flow, id);
|
||||
actionState.getActionList().addAll(actions);
|
||||
configureCommonProperties(actionState, entryActions, transitions, exceptionHandlers, exitActions, attributes);
|
||||
return actionState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that creates a new decision state, a state where a flow routing decision is made. This method is
|
||||
* an atomic operation that returns a fully initialized state. It encapsulates the selection of the decision state
|
||||
* implementation as well as the state assembly.
|
||||
* @param id the identifier to assign to the state, must be unique to its owning flow (required)
|
||||
* @param flow the flow that will own (contain) this state (required)
|
||||
* @param entryActions any state entry actions; may be null
|
||||
* @param transitions any transitions (paths) out of this state
|
||||
* @param exceptionHandlers any exception handlers; may be null
|
||||
* @param exitActions any state exit actions; may be null
|
||||
* @param attributes attributes to assign to the State, which may also be used to affect state construction; may be
|
||||
* null
|
||||
* @return the fully initialized decision state instance
|
||||
*/
|
||||
public State createDecisionState(String id, Flow flow, Action[] entryActions, Transition[] transitions,
|
||||
FlowExecutionExceptionHandler[] exceptionHandlers, Action[] exitActions, AttributeMap<?> attributes) {
|
||||
DecisionState decisionState = new DecisionState(flow, id);
|
||||
configureCommonProperties(decisionState, entryActions, transitions, exceptionHandlers, exitActions, attributes);
|
||||
return decisionState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that creates a new subflow state, a state where a parent flow spawns another flow as a subflow.
|
||||
* This method is an atomic operation that returns a fully initialized state. It encapsulates the selection of the
|
||||
* subflow state implementation as well as the state assembly.
|
||||
* @param id the identifier to assign to the state, must be unique to its owning flow (required)
|
||||
* @param flow the flow that will own (contain) this state (required)
|
||||
* @param entryActions any state entry actions; may be null
|
||||
* @param subflow the subflow definition (required)
|
||||
* @param attributeMapper the subflow input and output attribute mapper; may be null
|
||||
* @param transitions any transitions (paths) out of this state
|
||||
* @param exceptionHandlers any exception handlers; may be null
|
||||
* @param exitActions any state exit actions; may be null
|
||||
* @param attributes attributes to assign to the State, which may also be used to affect state construction; may be
|
||||
* null
|
||||
* @return the fully initialized subflow state instance
|
||||
*/
|
||||
public State createSubflowState(String id, Flow flow, Action[] entryActions, Expression subflow,
|
||||
SubflowAttributeMapper attributeMapper, Transition[] transitions,
|
||||
FlowExecutionExceptionHandler[] exceptionHandlers, Action[] exitActions, AttributeMap<?> attributes) {
|
||||
SubflowState subflowState = new SubflowState(flow, id, subflow);
|
||||
if (attributeMapper != null) {
|
||||
subflowState.setAttributeMapper(attributeMapper);
|
||||
}
|
||||
configureCommonProperties(subflowState, entryActions, transitions, exceptionHandlers, exitActions, attributes);
|
||||
return subflowState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that creates a new end state, a state where an executing flow session terminates. This method is
|
||||
* an atomic operation that returns a fully initialized state. It encapsulates the selection of the end state
|
||||
* implementation as well as the state assembly.
|
||||
* @param id the identifier to assign to the state, must be unique to its owning flow (required)
|
||||
* @param flow the flow that will own (contain) this state (required)
|
||||
* @param entryActions any state entry actions; may be null
|
||||
* @param finalResponseAction the state response renderer; may be null
|
||||
* @param outputMapper the state output mapper; may be null
|
||||
* @param exceptionHandlers any exception handlers; may be null
|
||||
* @param attributes attributes to assign to the State, which may also be used to affect state construction; may be
|
||||
* null
|
||||
* @return the fully initialized subflow state instance
|
||||
*/
|
||||
public State createEndState(String id, Flow flow, Action[] entryActions, Action finalResponseAction,
|
||||
Mapper outputMapper, FlowExecutionExceptionHandler[] exceptionHandlers, AttributeMap<?> attributes) {
|
||||
EndState endState = new EndState(flow, id);
|
||||
if (finalResponseAction != null) {
|
||||
endState.setFinalResponseAction(finalResponseAction);
|
||||
}
|
||||
if (outputMapper != null) {
|
||||
endState.setOutputMapper(outputMapper);
|
||||
}
|
||||
configureCommonProperties(endState, entryActions, exceptionHandlers, attributes);
|
||||
return endState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that creates a new transition, a path from one step in a flow to another. This method is an atomic
|
||||
* operation that returns a fully initialized transition. It encapsulates the selection of the transition
|
||||
* implementation as well as the transition assembly.
|
||||
* @param targetStateResolver the resolver of the target state of the transition (required)
|
||||
* @param matchingCriteria the criteria that matches the transition; may be null
|
||||
* @param executionCriteria the criteria that governs execution of the transition after match; may be null
|
||||
* @param attributes attributes to assign to the transition, which may also be used to affect transition
|
||||
* construction; may be null
|
||||
* @return the fully initialized transition instance
|
||||
*/
|
||||
public Transition createTransition(TargetStateResolver targetStateResolver, TransitionCriteria matchingCriteria,
|
||||
TransitionCriteria executionCriteria, AttributeMap<?> attributes) {
|
||||
Transition transition = new Transition(targetStateResolver);
|
||||
if (matchingCriteria != null) {
|
||||
transition.setMatchingCriteria(matchingCriteria);
|
||||
}
|
||||
if (executionCriteria != null) {
|
||||
transition.setExecutionCriteria(executionCriteria);
|
||||
}
|
||||
transition.getAttributes().putAll(attributes);
|
||||
return transition;
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
/**
|
||||
* Configure common properties for a transitionable state.
|
||||
*/
|
||||
private void configureCommonProperties(TransitionableState state, Action[] entryActions, Transition[] transitions,
|
||||
FlowExecutionExceptionHandler[] exceptionHandlers, Action[] exitActions, AttributeMap<?> attributes) {
|
||||
configureCommonProperties(state, entryActions, exceptionHandlers, attributes);
|
||||
state.getTransitionSet().addAll(transitions);
|
||||
state.getExitActionList().addAll(exitActions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure common properties for a state.
|
||||
*/
|
||||
private void configureCommonProperties(State state, Action[] entryActions,
|
||||
FlowExecutionExceptionHandler[] exceptionHandlers, AttributeMap<?> attributes) {
|
||||
state.getEntryActionList().addAll(entryActions);
|
||||
state.getExceptionHandlerSet().addAll(exceptionHandlers);
|
||||
state.getAttributes().putAll(attributes);
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.builder;
|
||||
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.mapping.Mapper;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.engine.ActionState;
|
||||
import org.springframework.webflow.engine.DecisionState;
|
||||
import org.springframework.webflow.engine.EndState;
|
||||
import org.springframework.webflow.engine.Flow;
|
||||
import org.springframework.webflow.engine.FlowExecutionExceptionHandler;
|
||||
import org.springframework.webflow.engine.State;
|
||||
import org.springframework.webflow.engine.SubflowAttributeMapper;
|
||||
import org.springframework.webflow.engine.SubflowState;
|
||||
import org.springframework.webflow.engine.TargetStateResolver;
|
||||
import org.springframework.webflow.engine.Transition;
|
||||
import org.springframework.webflow.engine.TransitionCriteria;
|
||||
import org.springframework.webflow.engine.TransitionableState;
|
||||
import org.springframework.webflow.engine.ViewState;
|
||||
import org.springframework.webflow.engine.ViewVariable;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
import org.springframework.webflow.execution.ViewFactory;
|
||||
|
||||
/**
|
||||
* A factory for core web flow elements such as {@link Flow flows}, {@link State states}, and {@link Transition
|
||||
* transitions}.
|
||||
* <p>
|
||||
* This factory encapsulates the construction of each Flow implementation as well as each core artifact type. Subclasses
|
||||
* may customize how the core elements are created.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class FlowArtifactFactory {
|
||||
|
||||
/**
|
||||
* Factory method that creates a new {@link Flow} definition object.
|
||||
* <p>
|
||||
* Note this method does not return a fully configured Flow instance, it only encapsulates the selection of
|
||||
* implementation. A {@link FlowAssembler} delegating to a calling {@link FlowBuilder} is expected to assemble the
|
||||
* Flow fully before returning it to external clients.
|
||||
* @param id the flow identifier, should be unique to all flows in an application (required)
|
||||
* @param attributes attributes to assign to the Flow, which may also be used to affect flow construction; may be
|
||||
* null
|
||||
* @return the initial flow instance, ready for assembly by a FlowBuilder
|
||||
*/
|
||||
public Flow createFlow(String id, AttributeMap<?> attributes) {
|
||||
return Flow.create(id, attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that creates a new view state, a state where a user is allowed to participate in the flow. This
|
||||
* method is an atomic operation that returns a fully initialized state. It encapsulates the selection of the view
|
||||
* state implementation as well as the state assembly.
|
||||
* @param id the identifier to assign to the state, must be unique to its owning flow (required)
|
||||
* @param flow the flow that will own (contain) this state (required)
|
||||
* @param entryActions any state entry actions; may be null
|
||||
* @param viewFactory the state view factory strategy
|
||||
* @param redirect whether to send a flow execution redirect before rendering
|
||||
* @param popup whether to display the view in a popup window
|
||||
* @param renderActions any 'render actions' to execute on entry and refresh; may be null
|
||||
* @param transitions any transitions (paths) out of this state; may be null
|
||||
* @param exceptionHandlers any exception handlers; may be null
|
||||
* @param exitActions any state exit actions; may be null
|
||||
* @param attributes attributes to assign to the State, which may also be used to affect state construction; may be
|
||||
* null
|
||||
* @return the fully initialized view state instance
|
||||
*/
|
||||
public State createViewState(String id, Flow flow, ViewVariable[] variables, Action[] entryActions,
|
||||
ViewFactory viewFactory, Boolean redirect, boolean popup, Action[] renderActions, Transition[] transitions,
|
||||
FlowExecutionExceptionHandler[] exceptionHandlers, Action[] exitActions, AttributeMap<?> attributes) {
|
||||
ViewState viewState = new ViewState(flow, id, viewFactory);
|
||||
viewState.addVariables(variables);
|
||||
viewState.setRedirect(redirect);
|
||||
viewState.setPopup(popup);
|
||||
viewState.getRenderActionList().addAll(renderActions);
|
||||
configureCommonProperties(viewState, entryActions, transitions, exceptionHandlers, exitActions, attributes);
|
||||
return viewState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that creates a new action state, a state where a system action is executed. This method is an
|
||||
* atomic operation that returns a fully initialized state. It encapsulates the selection of the action state
|
||||
* implementation as well as the state assembly.
|
||||
* @param id the identifier to assign to the state, must be unique to its owning flow (required)
|
||||
* @param flow the flow that will own (contain) this state (required)
|
||||
* @param entryActions any state entry actions; may be null
|
||||
* @param actions the actions to execute when the state is entered (required)
|
||||
* @param transitions any transitions (paths) out of this state; may be null
|
||||
* @param exceptionHandlers any exception handlers; may be null
|
||||
* @param exitActions any state exit actions; may be null
|
||||
* @param attributes attributes to assign to the State, which may also be used to affect state construction; may be
|
||||
* null
|
||||
* @return the fully initialized action state instance
|
||||
*/
|
||||
public State createActionState(String id, Flow flow, Action[] entryActions, Action[] actions,
|
||||
Transition[] transitions, FlowExecutionExceptionHandler[] exceptionHandlers, Action[] exitActions,
|
||||
AttributeMap<?> attributes) {
|
||||
ActionState actionState = new ActionState(flow, id);
|
||||
actionState.getActionList().addAll(actions);
|
||||
configureCommonProperties(actionState, entryActions, transitions, exceptionHandlers, exitActions, attributes);
|
||||
return actionState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that creates a new decision state, a state where a flow routing decision is made. This method is
|
||||
* an atomic operation that returns a fully initialized state. It encapsulates the selection of the decision state
|
||||
* implementation as well as the state assembly.
|
||||
* @param id the identifier to assign to the state, must be unique to its owning flow (required)
|
||||
* @param flow the flow that will own (contain) this state (required)
|
||||
* @param entryActions any state entry actions; may be null
|
||||
* @param transitions any transitions (paths) out of this state
|
||||
* @param exceptionHandlers any exception handlers; may be null
|
||||
* @param exitActions any state exit actions; may be null
|
||||
* @param attributes attributes to assign to the State, which may also be used to affect state construction; may be
|
||||
* null
|
||||
* @return the fully initialized decision state instance
|
||||
*/
|
||||
public State createDecisionState(String id, Flow flow, Action[] entryActions, Transition[] transitions,
|
||||
FlowExecutionExceptionHandler[] exceptionHandlers, Action[] exitActions, AttributeMap<?> attributes) {
|
||||
DecisionState decisionState = new DecisionState(flow, id);
|
||||
configureCommonProperties(decisionState, entryActions, transitions, exceptionHandlers, exitActions, attributes);
|
||||
return decisionState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that creates a new subflow state, a state where a parent flow spawns another flow as a subflow.
|
||||
* This method is an atomic operation that returns a fully initialized state. It encapsulates the selection of the
|
||||
* subflow state implementation as well as the state assembly.
|
||||
* @param id the identifier to assign to the state, must be unique to its owning flow (required)
|
||||
* @param flow the flow that will own (contain) this state (required)
|
||||
* @param entryActions any state entry actions; may be null
|
||||
* @param subflow the subflow definition (required)
|
||||
* @param attributeMapper the subflow input and output attribute mapper; may be null
|
||||
* @param transitions any transitions (paths) out of this state
|
||||
* @param exceptionHandlers any exception handlers; may be null
|
||||
* @param exitActions any state exit actions; may be null
|
||||
* @param attributes attributes to assign to the State, which may also be used to affect state construction; may be
|
||||
* null
|
||||
* @return the fully initialized subflow state instance
|
||||
*/
|
||||
public State createSubflowState(String id, Flow flow, Action[] entryActions, Expression subflow,
|
||||
SubflowAttributeMapper attributeMapper, Transition[] transitions,
|
||||
FlowExecutionExceptionHandler[] exceptionHandlers, Action[] exitActions, AttributeMap<?> attributes) {
|
||||
SubflowState subflowState = new SubflowState(flow, id, subflow);
|
||||
if (attributeMapper != null) {
|
||||
subflowState.setAttributeMapper(attributeMapper);
|
||||
}
|
||||
configureCommonProperties(subflowState, entryActions, transitions, exceptionHandlers, exitActions, attributes);
|
||||
return subflowState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that creates a new end state, a state where an executing flow session terminates. This method is
|
||||
* an atomic operation that returns a fully initialized state. It encapsulates the selection of the end state
|
||||
* implementation as well as the state assembly.
|
||||
* @param id the identifier to assign to the state, must be unique to its owning flow (required)
|
||||
* @param flow the flow that will own (contain) this state (required)
|
||||
* @param entryActions any state entry actions; may be null
|
||||
* @param finalResponseAction the state response renderer; may be null
|
||||
* @param outputMapper the state output mapper; may be null
|
||||
* @param exceptionHandlers any exception handlers; may be null
|
||||
* @param attributes attributes to assign to the State, which may also be used to affect state construction; may be
|
||||
* null
|
||||
* @return the fully initialized subflow state instance
|
||||
*/
|
||||
public State createEndState(String id, Flow flow, Action[] entryActions, Action finalResponseAction,
|
||||
Mapper outputMapper, FlowExecutionExceptionHandler[] exceptionHandlers, AttributeMap<?> attributes) {
|
||||
EndState endState = new EndState(flow, id);
|
||||
if (finalResponseAction != null) {
|
||||
endState.setFinalResponseAction(finalResponseAction);
|
||||
}
|
||||
if (outputMapper != null) {
|
||||
endState.setOutputMapper(outputMapper);
|
||||
}
|
||||
configureCommonProperties(endState, entryActions, exceptionHandlers, attributes);
|
||||
return endState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that creates a new transition, a path from one step in a flow to another. This method is an atomic
|
||||
* operation that returns a fully initialized transition. It encapsulates the selection of the transition
|
||||
* implementation as well as the transition assembly.
|
||||
* @param targetStateResolver the resolver of the target state of the transition (required)
|
||||
* @param matchingCriteria the criteria that matches the transition; may be null
|
||||
* @param executionCriteria the criteria that governs execution of the transition after match; may be null
|
||||
* @param attributes attributes to assign to the transition, which may also be used to affect transition
|
||||
* construction; may be null
|
||||
* @return the fully initialized transition instance
|
||||
*/
|
||||
public Transition createTransition(TargetStateResolver targetStateResolver, TransitionCriteria matchingCriteria,
|
||||
TransitionCriteria executionCriteria, AttributeMap<?> attributes) {
|
||||
Transition transition = new Transition(targetStateResolver);
|
||||
if (matchingCriteria != null) {
|
||||
transition.setMatchingCriteria(matchingCriteria);
|
||||
}
|
||||
if (executionCriteria != null) {
|
||||
transition.setExecutionCriteria(executionCriteria);
|
||||
}
|
||||
transition.getAttributes().putAll(attributes);
|
||||
return transition;
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
/**
|
||||
* Configure common properties for a transitionable state.
|
||||
*/
|
||||
private void configureCommonProperties(TransitionableState state, Action[] entryActions, Transition[] transitions,
|
||||
FlowExecutionExceptionHandler[] exceptionHandlers, Action[] exitActions, AttributeMap<?> attributes) {
|
||||
configureCommonProperties(state, entryActions, exceptionHandlers, attributes);
|
||||
state.getTransitionSet().addAll(transitions);
|
||||
state.getExitActionList().addAll(exitActions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure common properties for a state.
|
||||
*/
|
||||
private void configureCommonProperties(State state, Action[] entryActions,
|
||||
FlowExecutionExceptionHandler[] exceptionHandlers, AttributeMap<?> attributes) {
|
||||
state.getEntryActionList().addAll(entryActions);
|
||||
state.getExceptionHandlerSet().addAll(exceptionHandlers);
|
||||
state.getAttributes().putAll(attributes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,112 +1,112 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.builder;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.engine.Flow;
|
||||
|
||||
/**
|
||||
* A director for assembling flows, delegating to a {@link FlowBuilder} to construct a flow. This class encapsulates the
|
||||
* algorithm for using a FlowBuilder to assemble a Flow properly. It acts as the director in the classic GoF builder
|
||||
* pattern.
|
||||
* <p>
|
||||
* Flow assemblers may be used in a standalone, programmatic fashion as follows:
|
||||
*
|
||||
* <pre>
|
||||
* FlowBuilder builder = ...;
|
||||
* FlowBuilder context = ...;
|
||||
* Flow flow = new FlowAssembler(builder, builderContext).assembleFlow();
|
||||
* </pre>
|
||||
*
|
||||
* @see org.springframework.webflow.engine.builder.FlowBuilder
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class FlowAssembler {
|
||||
|
||||
/**
|
||||
* The flow builder strategy used to construct the flow from its component parts.
|
||||
*/
|
||||
private FlowBuilder flowBuilder;
|
||||
|
||||
/**
|
||||
* Context needed to initialize the builder so it can perform a build operation.
|
||||
*/
|
||||
private FlowBuilderContext flowBuilderContext;
|
||||
|
||||
/**
|
||||
* Create a new flow assembler that will direct Flow assembly using the specified builder strategy.
|
||||
* @param flowBuilder the builder the factory will use to build flows
|
||||
* @param flowBuilderContext context to influence the build process
|
||||
*/
|
||||
public FlowAssembler(FlowBuilder flowBuilder, FlowBuilderContext flowBuilderContext) {
|
||||
Assert.notNull(flowBuilder, "A flow builder is required for flow assembly");
|
||||
Assert.notNull(flowBuilderContext, "A flow builder context is required for flow assembly");
|
||||
this.flowBuilder = flowBuilder;
|
||||
this.flowBuilderContext = flowBuilderContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the flow builder strategy used to construct the flow from its component parts.
|
||||
*/
|
||||
public FlowBuilder getFlowBuilder() {
|
||||
return flowBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the flow builder context.
|
||||
* @return flow builder context
|
||||
*/
|
||||
public FlowBuilderContext getFlowBuilderContext() {
|
||||
return flowBuilderContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles the flow, directing the construction process by delegating to the configured FlowBuilder. Every call to
|
||||
* this method will assemble the Flow instance.
|
||||
* <p>
|
||||
* This will drive the flow construction process as described in the {@link FlowBuilder} JavaDoc, starting with
|
||||
* builder initialization using {@link FlowBuilder#init(FlowBuilderContext)} and finishing by cleaning up the
|
||||
* builder with a call to {@link FlowBuilder#dispose()}.
|
||||
* @return the constructed flow
|
||||
* @throws FlowBuilderException when flow assembly fails
|
||||
*/
|
||||
public Flow assembleFlow() throws FlowBuilderException {
|
||||
try {
|
||||
flowBuilder.init(flowBuilderContext);
|
||||
directAssembly();
|
||||
return flowBuilder.getFlow();
|
||||
} finally {
|
||||
flowBuilder.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build all parts of the flow by directing flow assembly by the flow builder.
|
||||
* @throws FlowBuilderException when flow assembly fails
|
||||
*/
|
||||
protected void directAssembly() throws FlowBuilderException {
|
||||
flowBuilder.buildVariables();
|
||||
flowBuilder.buildInputMapper();
|
||||
flowBuilder.buildStartActions();
|
||||
flowBuilder.buildStates();
|
||||
flowBuilder.buildGlobalTransitions();
|
||||
flowBuilder.buildEndActions();
|
||||
flowBuilder.buildOutputMapper();
|
||||
flowBuilder.buildExceptionHandlers();
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.builder;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.engine.Flow;
|
||||
|
||||
/**
|
||||
* A director for assembling flows, delegating to a {@link FlowBuilder} to construct a flow. This class encapsulates the
|
||||
* algorithm for using a FlowBuilder to assemble a Flow properly. It acts as the director in the classic GoF builder
|
||||
* pattern.
|
||||
* <p>
|
||||
* Flow assemblers may be used in a standalone, programmatic fashion as follows:
|
||||
*
|
||||
* <pre>
|
||||
* FlowBuilder builder = ...;
|
||||
* FlowBuilder context = ...;
|
||||
* Flow flow = new FlowAssembler(builder, builderContext).assembleFlow();
|
||||
* </pre>
|
||||
*
|
||||
* @see org.springframework.webflow.engine.builder.FlowBuilder
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class FlowAssembler {
|
||||
|
||||
/**
|
||||
* The flow builder strategy used to construct the flow from its component parts.
|
||||
*/
|
||||
private FlowBuilder flowBuilder;
|
||||
|
||||
/**
|
||||
* Context needed to initialize the builder so it can perform a build operation.
|
||||
*/
|
||||
private FlowBuilderContext flowBuilderContext;
|
||||
|
||||
/**
|
||||
* Create a new flow assembler that will direct Flow assembly using the specified builder strategy.
|
||||
* @param flowBuilder the builder the factory will use to build flows
|
||||
* @param flowBuilderContext context to influence the build process
|
||||
*/
|
||||
public FlowAssembler(FlowBuilder flowBuilder, FlowBuilderContext flowBuilderContext) {
|
||||
Assert.notNull(flowBuilder, "A flow builder is required for flow assembly");
|
||||
Assert.notNull(flowBuilderContext, "A flow builder context is required for flow assembly");
|
||||
this.flowBuilder = flowBuilder;
|
||||
this.flowBuilderContext = flowBuilderContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the flow builder strategy used to construct the flow from its component parts.
|
||||
*/
|
||||
public FlowBuilder getFlowBuilder() {
|
||||
return flowBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the flow builder context.
|
||||
* @return flow builder context
|
||||
*/
|
||||
public FlowBuilderContext getFlowBuilderContext() {
|
||||
return flowBuilderContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles the flow, directing the construction process by delegating to the configured FlowBuilder. Every call to
|
||||
* this method will assemble the Flow instance.
|
||||
* <p>
|
||||
* This will drive the flow construction process as described in the {@link FlowBuilder} JavaDoc, starting with
|
||||
* builder initialization using {@link FlowBuilder#init(FlowBuilderContext)} and finishing by cleaning up the
|
||||
* builder with a call to {@link FlowBuilder#dispose()}.
|
||||
* @return the constructed flow
|
||||
* @throws FlowBuilderException when flow assembly fails
|
||||
*/
|
||||
public Flow assembleFlow() throws FlowBuilderException {
|
||||
try {
|
||||
flowBuilder.init(flowBuilderContext);
|
||||
directAssembly();
|
||||
return flowBuilder.getFlow();
|
||||
} finally {
|
||||
flowBuilder.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build all parts of the flow by directing flow assembly by the flow builder.
|
||||
* @throws FlowBuilderException when flow assembly fails
|
||||
*/
|
||||
protected void directAssembly() throws FlowBuilderException {
|
||||
flowBuilder.buildVariables();
|
||||
flowBuilder.buildInputMapper();
|
||||
flowBuilder.buildStartActions();
|
||||
flowBuilder.buildStates();
|
||||
flowBuilder.buildGlobalTransitions();
|
||||
flowBuilder.buildEndActions();
|
||||
flowBuilder.buildOutputMapper();
|
||||
flowBuilder.buildExceptionHandlers();
|
||||
}
|
||||
}
|
||||
@@ -1,141 +1,141 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.builder;
|
||||
|
||||
import org.springframework.webflow.engine.Flow;
|
||||
|
||||
/**
|
||||
* Builder interface used to build a flow definition. The process of building a flow consists of the following steps:
|
||||
* <ol>
|
||||
* <li>Initialize this builder, creating the initial flow definition, by calling {@link #init(FlowBuilderContext)}.
|
||||
* <li>Call {@link #buildVariables()} to create any variables of the flow and add them to the flow definition.
|
||||
* <li>Call {@link #buildInputMapper()} to create and set the input mapper for the flow.
|
||||
* <li>Call {@link #buildStartActions()} to create and add any start actions to the flow.
|
||||
* <li>Call {@link #buildStates()} to create the states of the flow and add them to the flow definition.
|
||||
* <li>Call {@link #buildGlobalTransitions()} to create any transitions shared by all states of the flow and add them to
|
||||
* the flow definition.
|
||||
* <li>Call {@link #buildEndActions()} to create and add any end actions to the flow.
|
||||
* <li>Call {@link #buildOutputMapper()} to create and set the output mapper for the flow.
|
||||
* <li>Call {@link #buildExceptionHandlers()} to create the exception handlers of the flow and add them to the flow
|
||||
* definition.
|
||||
* <li>Call {@link #getFlow()} to return the fully-built {@link Flow} definition.
|
||||
* <li>Dispose this builder, releasing any resources allocated during the building process by calling {@link #dispose()}.
|
||||
* </ol>
|
||||
* <p>
|
||||
* Implementations should encapsulate flow construction logic, either for a specific kind of flow, for example, an
|
||||
* <code>OrderFlowBuilder</code> built in Java code, or a generic flow builder strategy, like the
|
||||
* <code>XmlFlowBuilder</code>, for building flows from an XML-definition.
|
||||
* <p>
|
||||
* Flow builders are used by the {@link FlowAssembler}, which acts as an assembler (director). Flow Builders may be
|
||||
* reused, however, exercise caution when doing this as these objects are not thread safe. Also, for each use be sure to
|
||||
* call init, followed by the build* methods, getFlow, and dispose completely in that order.
|
||||
* <p>
|
||||
* This is a good example of the classic GoF builder pattern.
|
||||
*
|
||||
* @see Flow
|
||||
* @see FlowBuilderContext
|
||||
* @see FlowAssembler
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface FlowBuilder {
|
||||
|
||||
/**
|
||||
* Initialize this builder. This could cause the builder to open a stream to an externalized resource representing
|
||||
* the flow definition, for example.
|
||||
* @param context the flow builder context
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void init(FlowBuilderContext context) throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Builds any variables initialized by the flow when it starts.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void buildVariables() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Builds the input mapper responsible for mapping flow input on start.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void buildInputMapper() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Builds any start actions to execute when the flow starts.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void buildStartActions() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Builds the states of the flow.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void buildStates() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Builds any transitions shared by all states of the flow.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void buildGlobalTransitions() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Builds any end actions to execute when the flow ends.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void buildEndActions() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Builds the output mapper responsible for mapping flow output on end.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void buildOutputMapper() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Creates and adds all exception handlers to the flow built by this builder.
|
||||
* @throws FlowBuilderException an exception occurred building this flow
|
||||
*/
|
||||
void buildExceptionHandlers() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Get the fully constructed and configured Flow object. Called by the builder's assembler (director) after
|
||||
* assembly. When this method is called by the assembler, it is expected flow construction has completed and the
|
||||
* returned flow is fully configured and ready for use.
|
||||
* @throws FlowBuilderException an exception occurred building this flow
|
||||
*/
|
||||
Flow getFlow() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Shutdown the builder, releasing any resources it holds. A new flow construction process should start with another
|
||||
* call to the {@link #init(FlowBuilderContext)} method.
|
||||
* @throws FlowBuilderException an exception occurred building this flow
|
||||
*/
|
||||
void dispose() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* As the underlying flow managed by this builder changed since the last build occurred?
|
||||
* @return true if changed, false if not
|
||||
*/
|
||||
boolean hasFlowChanged();
|
||||
|
||||
/**
|
||||
* Returns a string describing the location of the flow resource; the logical location where the source code can be
|
||||
* found. Used for informational purposes.
|
||||
* @return the flow resource string
|
||||
*/
|
||||
String getFlowResourceString();
|
||||
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.builder;
|
||||
|
||||
import org.springframework.webflow.engine.Flow;
|
||||
|
||||
/**
|
||||
* Builder interface used to build a flow definition. The process of building a flow consists of the following steps:
|
||||
* <ol>
|
||||
* <li>Initialize this builder, creating the initial flow definition, by calling {@link #init(FlowBuilderContext)}.
|
||||
* <li>Call {@link #buildVariables()} to create any variables of the flow and add them to the flow definition.
|
||||
* <li>Call {@link #buildInputMapper()} to create and set the input mapper for the flow.
|
||||
* <li>Call {@link #buildStartActions()} to create and add any start actions to the flow.
|
||||
* <li>Call {@link #buildStates()} to create the states of the flow and add them to the flow definition.
|
||||
* <li>Call {@link #buildGlobalTransitions()} to create any transitions shared by all states of the flow and add them to
|
||||
* the flow definition.
|
||||
* <li>Call {@link #buildEndActions()} to create and add any end actions to the flow.
|
||||
* <li>Call {@link #buildOutputMapper()} to create and set the output mapper for the flow.
|
||||
* <li>Call {@link #buildExceptionHandlers()} to create the exception handlers of the flow and add them to the flow
|
||||
* definition.
|
||||
* <li>Call {@link #getFlow()} to return the fully-built {@link Flow} definition.
|
||||
* <li>Dispose this builder, releasing any resources allocated during the building process by calling {@link #dispose()}.
|
||||
* </ol>
|
||||
* <p>
|
||||
* Implementations should encapsulate flow construction logic, either for a specific kind of flow, for example, an
|
||||
* <code>OrderFlowBuilder</code> built in Java code, or a generic flow builder strategy, like the
|
||||
* <code>XmlFlowBuilder</code>, for building flows from an XML-definition.
|
||||
* <p>
|
||||
* Flow builders are used by the {@link FlowAssembler}, which acts as an assembler (director). Flow Builders may be
|
||||
* reused, however, exercise caution when doing this as these objects are not thread safe. Also, for each use be sure to
|
||||
* call init, followed by the build* methods, getFlow, and dispose completely in that order.
|
||||
* <p>
|
||||
* This is a good example of the classic GoF builder pattern.
|
||||
*
|
||||
* @see Flow
|
||||
* @see FlowBuilderContext
|
||||
* @see FlowAssembler
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public interface FlowBuilder {
|
||||
|
||||
/**
|
||||
* Initialize this builder. This could cause the builder to open a stream to an externalized resource representing
|
||||
* the flow definition, for example.
|
||||
* @param context the flow builder context
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void init(FlowBuilderContext context) throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Builds any variables initialized by the flow when it starts.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void buildVariables() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Builds the input mapper responsible for mapping flow input on start.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void buildInputMapper() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Builds any start actions to execute when the flow starts.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void buildStartActions() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Builds the states of the flow.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void buildStates() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Builds any transitions shared by all states of the flow.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void buildGlobalTransitions() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Builds any end actions to execute when the flow ends.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void buildEndActions() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Builds the output mapper responsible for mapping flow output on end.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void buildOutputMapper() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Creates and adds all exception handlers to the flow built by this builder.
|
||||
* @throws FlowBuilderException an exception occurred building this flow
|
||||
*/
|
||||
void buildExceptionHandlers() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Get the fully constructed and configured Flow object. Called by the builder's assembler (director) after
|
||||
* assembly. When this method is called by the assembler, it is expected flow construction has completed and the
|
||||
* returned flow is fully configured and ready for use.
|
||||
* @throws FlowBuilderException an exception occurred building this flow
|
||||
*/
|
||||
Flow getFlow() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Shutdown the builder, releasing any resources it holds. A new flow construction process should start with another
|
||||
* call to the {@link #init(FlowBuilderContext)} method.
|
||||
* @throws FlowBuilderException an exception occurred building this flow
|
||||
*/
|
||||
void dispose() throws FlowBuilderException;
|
||||
|
||||
/**
|
||||
* As the underlying flow managed by this builder changed since the last build occurred?
|
||||
* @return true if changed, false if not
|
||||
*/
|
||||
boolean hasFlowChanged();
|
||||
|
||||
/**
|
||||
* Returns a string describing the location of the flow resource; the logical location where the source code can be
|
||||
* found. Used for informational purposes.
|
||||
* @return the flow resource string
|
||||
*/
|
||||
String getFlowResourceString();
|
||||
|
||||
}
|
||||
@@ -1,45 +1,45 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.builder;
|
||||
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
|
||||
/**
|
||||
* Exception thrown to indicate a problem while building a flow.
|
||||
*
|
||||
* @see FlowBuilder
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class FlowBuilderException extends FlowException {
|
||||
|
||||
/**
|
||||
* Create a new flow builder exception.
|
||||
* @param message descriptive message
|
||||
*/
|
||||
public FlowBuilderException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new flow builder exception.
|
||||
* @param message descriptive message
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public FlowBuilderException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.builder;
|
||||
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
|
||||
/**
|
||||
* Exception thrown to indicate a problem while building a flow.
|
||||
*
|
||||
* @see FlowBuilder
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class FlowBuilderException extends FlowException {
|
||||
|
||||
/**
|
||||
* Create a new flow builder exception.
|
||||
* @param message descriptive message
|
||||
*/
|
||||
public FlowBuilderException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new flow builder exception.
|
||||
* @param message descriptive message
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public FlowBuilderException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -1,114 +1,114 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.builder.model;
|
||||
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
|
||||
import org.springframework.webflow.engine.builder.FlowArtifactFactory;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderContext;
|
||||
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
|
||||
import org.springframework.webflow.validation.ValidationHintResolver;
|
||||
|
||||
/**
|
||||
* A builder context that delegates to a flow-local bean factory for builder services. Such builder services override
|
||||
* the services of the external "parent" context.
|
||||
* @author Keith Donald
|
||||
*/
|
||||
class LocalFlowBuilderContext implements FlowBuilderContext {
|
||||
|
||||
private FlowBuilderContext parent;
|
||||
|
||||
private ApplicationContext localFlowContext;
|
||||
|
||||
public LocalFlowBuilderContext(FlowBuilderContext parent, GenericApplicationContext localFlowContext) {
|
||||
this.parent = parent;
|
||||
this.localFlowContext = localFlowContext;
|
||||
}
|
||||
|
||||
public ApplicationContext getApplicationContext() {
|
||||
return localFlowContext;
|
||||
}
|
||||
|
||||
public String getFlowId() {
|
||||
return parent.getFlowId();
|
||||
}
|
||||
|
||||
public AttributeMap<Object> getFlowAttributes() {
|
||||
return parent.getFlowAttributes();
|
||||
}
|
||||
|
||||
public FlowDefinitionLocator getFlowDefinitionLocator() {
|
||||
if (localFlowContext.containsLocalBean("flowRegistry")) {
|
||||
return localFlowContext.getBean("flowRegistry", FlowDefinitionLocator.class);
|
||||
} else {
|
||||
return parent.getFlowDefinitionLocator();
|
||||
}
|
||||
}
|
||||
|
||||
public FlowArtifactFactory getFlowArtifactFactory() {
|
||||
if (localFlowContext.containsLocalBean("flowArtifactFactory")) {
|
||||
return localFlowContext.getBean("flowArtifactFactory", FlowArtifactFactory.class);
|
||||
} else {
|
||||
return parent.getFlowArtifactFactory();
|
||||
}
|
||||
}
|
||||
|
||||
public ConversionService getConversionService() {
|
||||
if (localFlowContext.containsLocalBean("conversionService")) {
|
||||
return localFlowContext.getBean("conversionService", ConversionService.class);
|
||||
} else {
|
||||
return parent.getConversionService();
|
||||
}
|
||||
}
|
||||
|
||||
public ViewFactoryCreator getViewFactoryCreator() {
|
||||
if (localFlowContext.containsLocalBean("viewFactoryCreator")) {
|
||||
return localFlowContext.getBean("viewFactoryCreator", ViewFactoryCreator.class);
|
||||
} else {
|
||||
return parent.getViewFactoryCreator();
|
||||
}
|
||||
}
|
||||
|
||||
public ExpressionParser getExpressionParser() {
|
||||
if (localFlowContext.containsLocalBean("expressionParser")) {
|
||||
return localFlowContext.getBean("expressionParser", ExpressionParser.class);
|
||||
} else {
|
||||
return parent.getExpressionParser();
|
||||
}
|
||||
}
|
||||
|
||||
public Validator getValidator() {
|
||||
if (localFlowContext.containsLocalBean("validator")) {
|
||||
return localFlowContext.getBean("validator", Validator.class);
|
||||
} else {
|
||||
return parent.getValidator();
|
||||
}
|
||||
}
|
||||
|
||||
public ValidationHintResolver getValidationHintResolver() {
|
||||
if (localFlowContext.containsLocalBean("validationHintResolver")) {
|
||||
return localFlowContext.getBean("validationHintResolver", ValidationHintResolver.class);
|
||||
} else {
|
||||
return parent.getValidationHintResolver();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.builder.model;
|
||||
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
|
||||
import org.springframework.webflow.engine.builder.FlowArtifactFactory;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderContext;
|
||||
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
|
||||
import org.springframework.webflow.validation.ValidationHintResolver;
|
||||
|
||||
/**
|
||||
* A builder context that delegates to a flow-local bean factory for builder services. Such builder services override
|
||||
* the services of the external "parent" context.
|
||||
* @author Keith Donald
|
||||
*/
|
||||
class LocalFlowBuilderContext implements FlowBuilderContext {
|
||||
|
||||
private FlowBuilderContext parent;
|
||||
|
||||
private ApplicationContext localFlowContext;
|
||||
|
||||
public LocalFlowBuilderContext(FlowBuilderContext parent, GenericApplicationContext localFlowContext) {
|
||||
this.parent = parent;
|
||||
this.localFlowContext = localFlowContext;
|
||||
}
|
||||
|
||||
public ApplicationContext getApplicationContext() {
|
||||
return localFlowContext;
|
||||
}
|
||||
|
||||
public String getFlowId() {
|
||||
return parent.getFlowId();
|
||||
}
|
||||
|
||||
public AttributeMap<Object> getFlowAttributes() {
|
||||
return parent.getFlowAttributes();
|
||||
}
|
||||
|
||||
public FlowDefinitionLocator getFlowDefinitionLocator() {
|
||||
if (localFlowContext.containsLocalBean("flowRegistry")) {
|
||||
return localFlowContext.getBean("flowRegistry", FlowDefinitionLocator.class);
|
||||
} else {
|
||||
return parent.getFlowDefinitionLocator();
|
||||
}
|
||||
}
|
||||
|
||||
public FlowArtifactFactory getFlowArtifactFactory() {
|
||||
if (localFlowContext.containsLocalBean("flowArtifactFactory")) {
|
||||
return localFlowContext.getBean("flowArtifactFactory", FlowArtifactFactory.class);
|
||||
} else {
|
||||
return parent.getFlowArtifactFactory();
|
||||
}
|
||||
}
|
||||
|
||||
public ConversionService getConversionService() {
|
||||
if (localFlowContext.containsLocalBean("conversionService")) {
|
||||
return localFlowContext.getBean("conversionService", ConversionService.class);
|
||||
} else {
|
||||
return parent.getConversionService();
|
||||
}
|
||||
}
|
||||
|
||||
public ViewFactoryCreator getViewFactoryCreator() {
|
||||
if (localFlowContext.containsLocalBean("viewFactoryCreator")) {
|
||||
return localFlowContext.getBean("viewFactoryCreator", ViewFactoryCreator.class);
|
||||
} else {
|
||||
return parent.getViewFactoryCreator();
|
||||
}
|
||||
}
|
||||
|
||||
public ExpressionParser getExpressionParser() {
|
||||
if (localFlowContext.containsLocalBean("expressionParser")) {
|
||||
return localFlowContext.getBean("expressionParser", ExpressionParser.class);
|
||||
} else {
|
||||
return parent.getExpressionParser();
|
||||
}
|
||||
}
|
||||
|
||||
public Validator getValidator() {
|
||||
if (localFlowContext.containsLocalBean("validator")) {
|
||||
return localFlowContext.getBean("validator", Validator.class);
|
||||
} else {
|
||||
return parent.getValidator();
|
||||
}
|
||||
}
|
||||
|
||||
public ValidationHintResolver getValidationHintResolver() {
|
||||
if (localFlowContext.containsLocalBean("validationHintResolver")) {
|
||||
return localFlowContext.getBean("validationHintResolver", ValidationHintResolver.class);
|
||||
} else {
|
||||
return parent.getValidationHintResolver();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,123 +1,123 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.builder.support;
|
||||
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.engine.Flow;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilder;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderContext;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Abstract base implementation of a flow builder defining common functionality needed by most concrete flow builder
|
||||
* implementations. This class implements all optional parts of the FlowBuilder process as no-op methods. Subclasses are
|
||||
* only required to implement {@link #buildStates()}.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public abstract class AbstractFlowBuilder implements FlowBuilder {
|
||||
|
||||
/**
|
||||
* The <code>Flow</code> built by this builder.
|
||||
*/
|
||||
private Flow flow;
|
||||
|
||||
/**
|
||||
* The flow builder context providing access to services needed to build the flow.
|
||||
*/
|
||||
private FlowBuilderContext context;
|
||||
|
||||
public void init(FlowBuilderContext context) throws FlowBuilderException {
|
||||
this.context = context;
|
||||
doInit();
|
||||
flow = createFlow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flow builder initialization hook. Does nothing by default. May be overridden by subclasses.
|
||||
*/
|
||||
protected void doInit() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that initially creates the flow implementation during flow builder initialization. Simply
|
||||
* delegates to the configured flow artifact factory by default.
|
||||
* @return the flow instance, initially created but not yet built
|
||||
*/
|
||||
protected Flow createFlow() {
|
||||
String id = getContext().getFlowId();
|
||||
AttributeMap<Object> attributes = getContext().getFlowAttributes();
|
||||
return getContext().getFlowArtifactFactory().createFlow(id, attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this flow builder's context.
|
||||
* @return the flow builder context
|
||||
*/
|
||||
protected FlowBuilderContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public void buildVariables() throws FlowBuilderException {
|
||||
}
|
||||
|
||||
public void buildInputMapper() throws FlowBuilderException {
|
||||
}
|
||||
|
||||
public void buildStartActions() throws FlowBuilderException {
|
||||
}
|
||||
|
||||
public abstract void buildStates() throws FlowBuilderException;
|
||||
|
||||
public void buildGlobalTransitions() throws FlowBuilderException {
|
||||
}
|
||||
|
||||
public void buildEndActions() throws FlowBuilderException {
|
||||
}
|
||||
|
||||
public void buildOutputMapper() throws FlowBuilderException {
|
||||
}
|
||||
|
||||
public void buildExceptionHandlers() throws FlowBuilderException {
|
||||
}
|
||||
|
||||
public Flow getFlow() throws FlowBuilderException {
|
||||
return flow;
|
||||
}
|
||||
|
||||
public void dispose() throws FlowBuilderException {
|
||||
flow = null;
|
||||
doDispose();
|
||||
}
|
||||
|
||||
public boolean hasFlowChanged() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getFlowResourceString() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flow builder destruction hook. Does nothing by default. May be overridden by subclasses.
|
||||
*/
|
||||
protected void doDispose() {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.builder.support;
|
||||
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.engine.Flow;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilder;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderContext;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderException;
|
||||
|
||||
/**
|
||||
* Abstract base implementation of a flow builder defining common functionality needed by most concrete flow builder
|
||||
* implementations. This class implements all optional parts of the FlowBuilder process as no-op methods. Subclasses are
|
||||
* only required to implement {@link #buildStates()}.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public abstract class AbstractFlowBuilder implements FlowBuilder {
|
||||
|
||||
/**
|
||||
* The <code>Flow</code> built by this builder.
|
||||
*/
|
||||
private Flow flow;
|
||||
|
||||
/**
|
||||
* The flow builder context providing access to services needed to build the flow.
|
||||
*/
|
||||
private FlowBuilderContext context;
|
||||
|
||||
public void init(FlowBuilderContext context) throws FlowBuilderException {
|
||||
this.context = context;
|
||||
doInit();
|
||||
flow = createFlow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flow builder initialization hook. Does nothing by default. May be overridden by subclasses.
|
||||
*/
|
||||
protected void doInit() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method that initially creates the flow implementation during flow builder initialization. Simply
|
||||
* delegates to the configured flow artifact factory by default.
|
||||
* @return the flow instance, initially created but not yet built
|
||||
*/
|
||||
protected Flow createFlow() {
|
||||
String id = getContext().getFlowId();
|
||||
AttributeMap<Object> attributes = getContext().getFlowAttributes();
|
||||
return getContext().getFlowArtifactFactory().createFlow(id, attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this flow builder's context.
|
||||
* @return the flow builder context
|
||||
*/
|
||||
protected FlowBuilderContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public void buildVariables() throws FlowBuilderException {
|
||||
}
|
||||
|
||||
public void buildInputMapper() throws FlowBuilderException {
|
||||
}
|
||||
|
||||
public void buildStartActions() throws FlowBuilderException {
|
||||
}
|
||||
|
||||
public abstract void buildStates() throws FlowBuilderException;
|
||||
|
||||
public void buildGlobalTransitions() throws FlowBuilderException {
|
||||
}
|
||||
|
||||
public void buildEndActions() throws FlowBuilderException {
|
||||
}
|
||||
|
||||
public void buildOutputMapper() throws FlowBuilderException {
|
||||
}
|
||||
|
||||
public void buildExceptionHandlers() throws FlowBuilderException {
|
||||
}
|
||||
|
||||
public Flow getFlow() throws FlowBuilderException {
|
||||
return flow;
|
||||
}
|
||||
|
||||
public void dispose() throws FlowBuilderException {
|
||||
flow = null;
|
||||
doDispose();
|
||||
}
|
||||
|
||||
public boolean hasFlowChanged() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getFlowResourceString() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flow builder destruction hook. Does nothing by default. May be overridden by subclasses.
|
||||
*/
|
||||
protected void doDispose() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,77 +1,77 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.builder.support;
|
||||
|
||||
import org.springframework.binding.convert.converters.Converter;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.support.FluentParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.webflow.engine.TargetStateResolver;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderContext;
|
||||
import org.springframework.webflow.engine.support.DefaultTargetStateResolver;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* Converter that takes an encoded string representation and produces a corresponding {@link TargetStateResolver}
|
||||
* object.
|
||||
* <p>
|
||||
* This converter supports the following encoded forms:
|
||||
* <ul>
|
||||
* <li>"stateId" - will result in a TargetStateResolver that always resolves the same state.</li>
|
||||
* <li>"${stateIdExpression} - will result in a TargetStateResolver that resolves the target state by evaluating an
|
||||
* expression against the request context. The resolved value can be a target state identifier or a custom
|
||||
* TargetStateResolver to delegate to.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
class TextToTargetStateResolver implements Converter {
|
||||
|
||||
/**
|
||||
* Context for flow builder services.
|
||||
*/
|
||||
private FlowBuilderContext flowBuilderContext;
|
||||
|
||||
/**
|
||||
* Create a new converter that converts strings to transition target state resolver objects. The given conversion
|
||||
* service will be used to do all necessary internal conversion (e.g. parsing expression strings).
|
||||
*/
|
||||
public TextToTargetStateResolver(FlowBuilderContext flowBuilderContext) {
|
||||
this.flowBuilderContext = flowBuilderContext;
|
||||
}
|
||||
|
||||
public Class<?> getSourceClass() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
public Class<?> getTargetClass() {
|
||||
return TargetStateResolver.class;
|
||||
}
|
||||
|
||||
public Object convertSourceToTargetClass(Object source, Class<?> targetClass) throws Exception {
|
||||
String targetStateId = (String) source;
|
||||
if (!StringUtils.hasText(targetStateId)) {
|
||||
return null;
|
||||
}
|
||||
ExpressionParser parser = flowBuilderContext.getExpressionParser();
|
||||
Expression expression = parser.parseExpression(targetStateId,
|
||||
new FluentParserContext().template().evaluate(RequestContext.class).expectResult(String.class));
|
||||
return new DefaultTargetStateResolver(expression);
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.builder.support;
|
||||
|
||||
import org.springframework.binding.convert.converters.Converter;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.support.FluentParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.webflow.engine.TargetStateResolver;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderContext;
|
||||
import org.springframework.webflow.engine.support.DefaultTargetStateResolver;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* Converter that takes an encoded string representation and produces a corresponding {@link TargetStateResolver}
|
||||
* object.
|
||||
* <p>
|
||||
* This converter supports the following encoded forms:
|
||||
* <ul>
|
||||
* <li>"stateId" - will result in a TargetStateResolver that always resolves the same state.</li>
|
||||
* <li>"${stateIdExpression} - will result in a TargetStateResolver that resolves the target state by evaluating an
|
||||
* expression against the request context. The resolved value can be a target state identifier or a custom
|
||||
* TargetStateResolver to delegate to.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
class TextToTargetStateResolver implements Converter {
|
||||
|
||||
/**
|
||||
* Context for flow builder services.
|
||||
*/
|
||||
private FlowBuilderContext flowBuilderContext;
|
||||
|
||||
/**
|
||||
* Create a new converter that converts strings to transition target state resolver objects. The given conversion
|
||||
* service will be used to do all necessary internal conversion (e.g. parsing expression strings).
|
||||
*/
|
||||
public TextToTargetStateResolver(FlowBuilderContext flowBuilderContext) {
|
||||
this.flowBuilderContext = flowBuilderContext;
|
||||
}
|
||||
|
||||
public Class<?> getSourceClass() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
public Class<?> getTargetClass() {
|
||||
return TargetStateResolver.class;
|
||||
}
|
||||
|
||||
public Object convertSourceToTargetClass(Object source, Class<?> targetClass) throws Exception {
|
||||
String targetStateId = (String) source;
|
||||
if (!StringUtils.hasText(targetStateId)) {
|
||||
return null;
|
||||
}
|
||||
ExpressionParser parser = flowBuilderContext.getExpressionParser();
|
||||
Expression expression = parser.parseExpression(targetStateId,
|
||||
new FluentParserContext().template().evaluate(RequestContext.class).expectResult(String.class));
|
||||
return new DefaultTargetStateResolver(expression);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,95 +1,95 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.builder.support;
|
||||
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.convert.converters.Converter;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.support.FluentParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.webflow.engine.TransitionCriteria;
|
||||
import org.springframework.webflow.engine.WildcardTransitionCriteria;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderContext;
|
||||
import org.springframework.webflow.engine.support.DefaultTransitionCriteria;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* Converter that takes an encoded string representation and produces a corresponding <code>TransitionCriteria</code>
|
||||
* object.
|
||||
* <p>
|
||||
* This converter supports the following encoded forms:
|
||||
* <ul>
|
||||
* <li>"*" - will result in a TransitionCriteria object that matches on everything.</li>
|
||||
* <li>"eventId" - will result in a TransitionCriteria object that matches given event id.</li>
|
||||
* <li>"${...}" - will result in a TransitionCriteria object that evaluates given condition, expressed as an expression.
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @see org.springframework.webflow.engine.TransitionCriteria
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
class TextToTransitionCriteria implements Converter {
|
||||
|
||||
/**
|
||||
* Context for flow builder services.
|
||||
*/
|
||||
private FlowBuilderContext flowBuilderContext;
|
||||
|
||||
/**
|
||||
* Create a new converter that converts strings to transition criteria objects. Custom transition criteria will be
|
||||
* looked up using given service locator.
|
||||
*/
|
||||
public TextToTransitionCriteria(FlowBuilderContext flowBuilderContext) {
|
||||
this.flowBuilderContext = flowBuilderContext;
|
||||
}
|
||||
|
||||
public Class<?> getSourceClass() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
public Class<?> getTargetClass() {
|
||||
return TransitionCriteria.class;
|
||||
}
|
||||
|
||||
public Object convertSourceToTargetClass(Object source, Class<?> targetClass) {
|
||||
String encodedCriteria = (String) source;
|
||||
ExpressionParser parser = flowBuilderContext.getExpressionParser();
|
||||
if (!StringUtils.hasText(encodedCriteria)
|
||||
|| WildcardTransitionCriteria.WILDCARD_EVENT_ID.equals(encodedCriteria)) {
|
||||
return WildcardTransitionCriteria.INSTANCE;
|
||||
} else {
|
||||
return createBooleanExpressionTransitionCriteria(encodedCriteria, parser);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook method subclasses can override to return a specialized expression evaluating transition criteria
|
||||
* implementation.
|
||||
* @param encodedCriteria the encoded transition criteria expression
|
||||
* @param parser the parser that should parse the expression
|
||||
* @return the transition criteria object
|
||||
* @throws ConversionExecutionException when something goes wrong
|
||||
*/
|
||||
protected TransitionCriteria createBooleanExpressionTransitionCriteria(String encodedCriteria,
|
||||
ExpressionParser parser) throws ConversionExecutionException {
|
||||
Expression expression = parser.parseExpression(encodedCriteria,
|
||||
new FluentParserContext().template().evaluate(RequestContext.class));
|
||||
return new DefaultTransitionCriteria(expression);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.builder.support;
|
||||
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.convert.converters.Converter;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.support.FluentParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.webflow.engine.TransitionCriteria;
|
||||
import org.springframework.webflow.engine.WildcardTransitionCriteria;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderContext;
|
||||
import org.springframework.webflow.engine.support.DefaultTransitionCriteria;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* Converter that takes an encoded string representation and produces a corresponding <code>TransitionCriteria</code>
|
||||
* object.
|
||||
* <p>
|
||||
* This converter supports the following encoded forms:
|
||||
* <ul>
|
||||
* <li>"*" - will result in a TransitionCriteria object that matches on everything.</li>
|
||||
* <li>"eventId" - will result in a TransitionCriteria object that matches given event id.</li>
|
||||
* <li>"${...}" - will result in a TransitionCriteria object that evaluates given condition, expressed as an expression.
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @see org.springframework.webflow.engine.TransitionCriteria
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
class TextToTransitionCriteria implements Converter {
|
||||
|
||||
/**
|
||||
* Context for flow builder services.
|
||||
*/
|
||||
private FlowBuilderContext flowBuilderContext;
|
||||
|
||||
/**
|
||||
* Create a new converter that converts strings to transition criteria objects. Custom transition criteria will be
|
||||
* looked up using given service locator.
|
||||
*/
|
||||
public TextToTransitionCriteria(FlowBuilderContext flowBuilderContext) {
|
||||
this.flowBuilderContext = flowBuilderContext;
|
||||
}
|
||||
|
||||
public Class<?> getSourceClass() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
public Class<?> getTargetClass() {
|
||||
return TransitionCriteria.class;
|
||||
}
|
||||
|
||||
public Object convertSourceToTargetClass(Object source, Class<?> targetClass) {
|
||||
String encodedCriteria = (String) source;
|
||||
ExpressionParser parser = flowBuilderContext.getExpressionParser();
|
||||
if (!StringUtils.hasText(encodedCriteria)
|
||||
|| WildcardTransitionCriteria.WILDCARD_EVENT_ID.equals(encodedCriteria)) {
|
||||
return WildcardTransitionCriteria.INSTANCE;
|
||||
} else {
|
||||
return createBooleanExpressionTransitionCriteria(encodedCriteria, parser);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook method subclasses can override to return a specialized expression evaluating transition criteria
|
||||
* implementation.
|
||||
* @param encodedCriteria the encoded transition criteria expression
|
||||
* @param parser the parser that should parse the expression
|
||||
* @return the transition criteria object
|
||||
* @throws ConversionExecutionException when something goes wrong
|
||||
*/
|
||||
protected TransitionCriteria createBooleanExpressionTransitionCriteria(String encodedCriteria,
|
||||
ExpressionParser parser) throws ConversionExecutionException {
|
||||
Expression expression = parser.parseExpression(encodedCriteria,
|
||||
new FluentParserContext().template().evaluate(RequestContext.class));
|
||||
return new DefaultTransitionCriteria(expression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,173 +1,173 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.impl;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.CollectionUtils;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
|
||||
import org.springframework.webflow.engine.Flow;
|
||||
import org.springframework.webflow.execution.FlowExecution;
|
||||
import org.springframework.webflow.execution.FlowExecutionFactory;
|
||||
import org.springframework.webflow.execution.FlowExecutionKey;
|
||||
import org.springframework.webflow.execution.FlowExecutionKeyFactory;
|
||||
import org.springframework.webflow.execution.factory.FlowExecutionListenerLoader;
|
||||
import org.springframework.webflow.execution.factory.StaticFlowExecutionListenerLoader;
|
||||
|
||||
/**
|
||||
* A factory for instances of the {@link FlowExecutionImpl default flow execution} implementation.
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class FlowExecutionImplFactory implements FlowExecutionFactory {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(FlowExecutionImplFactory.class);
|
||||
|
||||
private AttributeMap<Object> executionAttributes = CollectionUtils.EMPTY_ATTRIBUTE_MAP;
|
||||
|
||||
private FlowExecutionListenerLoader executionListenerLoader = StaticFlowExecutionListenerLoader.EMPTY_INSTANCE;
|
||||
|
||||
private FlowExecutionKeyFactory executionKeyFactory = new SimpleFlowExecutionKeyFactory();
|
||||
|
||||
/**
|
||||
* Sets the attributes to apply to flow executions created by this factory. Execution attributes may affect flow
|
||||
* execution behavior.
|
||||
* @param executionAttributes flow execution system attributes
|
||||
*/
|
||||
public void setExecutionAttributes(AttributeMap<Object> executionAttributes) {
|
||||
this.executionAttributes = executionAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strategy for loading listeners that should observe executions of a flow definition. Allows full control
|
||||
* over what listeners should apply for executions of a flow definition.
|
||||
*/
|
||||
public void setExecutionListenerLoader(FlowExecutionListenerLoader executionListenerLoader) {
|
||||
this.executionListenerLoader = executionListenerLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strategy for generating flow execution keys for persistent flow executions.
|
||||
*/
|
||||
public void setExecutionKeyFactory(FlowExecutionKeyFactory executionKeyFactory) {
|
||||
this.executionKeyFactory = executionKeyFactory;
|
||||
}
|
||||
|
||||
public FlowExecution createFlowExecution(FlowDefinition flowDefinition) {
|
||||
Assert.isInstanceOf(Flow.class, flowDefinition, "FlowDefinition is of the wrong type: ");
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Creating new execution of '" + flowDefinition.getId() + "'");
|
||||
}
|
||||
FlowExecutionImpl execution = new FlowExecutionImpl((Flow) flowDefinition);
|
||||
execution.setAttributes(executionAttributes);
|
||||
execution.setListeners(executionListenerLoader.getListeners(execution.getDefinition()));
|
||||
execution.setKeyFactory(executionKeyFactory);
|
||||
return execution;
|
||||
}
|
||||
|
||||
public FlowExecution restoreFlowExecution(FlowExecution flowExecution, FlowDefinition flowDefinition,
|
||||
FlowExecutionKey flowExecutionKey, MutableAttributeMap<Object> conversationScope,
|
||||
FlowDefinitionLocator subflowDefinitionLocator) {
|
||||
Assert.isInstanceOf(FlowExecutionImpl.class, flowExecution, "FlowExecution is of the wrong type: ");
|
||||
Assert.isInstanceOf(Flow.class, flowDefinition, "FlowDefinition is of the wrong type: ");
|
||||
FlowExecutionImpl execution = (FlowExecutionImpl) flowExecution;
|
||||
Flow flow = (Flow) flowDefinition;
|
||||
execution.setFlow(flow);
|
||||
if (execution.hasSessions()) {
|
||||
FlowSessionImpl rootSession = execution.getRootSession();
|
||||
rootSession.setFlow(flow);
|
||||
rootSession.setState(flow.getStateInstance(rootSession.getStateId()));
|
||||
if (execution.hasSubflowSessions()) {
|
||||
for (Iterator<FlowSessionImpl> it = execution.getSubflowSessionIterator(); it.hasNext();) {
|
||||
FlowSessionImpl subflowSession = it.next();
|
||||
Flow subflowDef = (Flow) subflowDefinitionLocator.getFlowDefinition(subflowSession.getFlowId());
|
||||
subflowSession.setFlow(subflowDef);
|
||||
subflowSession.setState(subflowDef.getStateInstance(subflowSession.getStateId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
execution.setKey(flowExecutionKey);
|
||||
if (conversationScope == null) {
|
||||
conversationScope = new LocalAttributeMap<>();
|
||||
}
|
||||
execution.setConversationScope(conversationScope);
|
||||
execution.setAttributes(executionAttributes);
|
||||
execution.setListeners(executionListenerLoader.getListeners(execution.getDefinition()));
|
||||
execution.setKeyFactory(executionKeyFactory);
|
||||
return execution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple key factory suitable for standalone usage and testing. Not expected to be used in a web environment.
|
||||
*/
|
||||
private static class SimpleFlowExecutionKeyFactory implements FlowExecutionKeyFactory {
|
||||
|
||||
private int sequence;
|
||||
|
||||
public FlowExecutionKey getKey(FlowExecution execution) {
|
||||
if (execution.getKey() == null) {
|
||||
return new SimpleFlowExecutionKey(nextSequence());
|
||||
} else {
|
||||
// keep the same key
|
||||
return execution.getKey();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllFlowExecutionSnapshots(FlowExecution execution) {
|
||||
}
|
||||
|
||||
public void removeFlowExecutionSnapshot(FlowExecution execution) {
|
||||
}
|
||||
|
||||
public void updateFlowExecutionSnapshot(FlowExecution execution) {
|
||||
}
|
||||
|
||||
private synchronized int nextSequence() {
|
||||
return ++sequence;
|
||||
}
|
||||
|
||||
private static class SimpleFlowExecutionKey extends FlowExecutionKey {
|
||||
|
||||
private int value;
|
||||
|
||||
public SimpleFlowExecutionKey(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof SimpleFlowExecutionKey)) {
|
||||
SimpleFlowExecutionKey key = (SimpleFlowExecutionKey) o;
|
||||
return value == key.value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.impl;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.CollectionUtils;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
|
||||
import org.springframework.webflow.engine.Flow;
|
||||
import org.springframework.webflow.execution.FlowExecution;
|
||||
import org.springframework.webflow.execution.FlowExecutionFactory;
|
||||
import org.springframework.webflow.execution.FlowExecutionKey;
|
||||
import org.springframework.webflow.execution.FlowExecutionKeyFactory;
|
||||
import org.springframework.webflow.execution.factory.FlowExecutionListenerLoader;
|
||||
import org.springframework.webflow.execution.factory.StaticFlowExecutionListenerLoader;
|
||||
|
||||
/**
|
||||
* A factory for instances of the {@link FlowExecutionImpl default flow execution} implementation.
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class FlowExecutionImplFactory implements FlowExecutionFactory {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(FlowExecutionImplFactory.class);
|
||||
|
||||
private AttributeMap<Object> executionAttributes = CollectionUtils.EMPTY_ATTRIBUTE_MAP;
|
||||
|
||||
private FlowExecutionListenerLoader executionListenerLoader = StaticFlowExecutionListenerLoader.EMPTY_INSTANCE;
|
||||
|
||||
private FlowExecutionKeyFactory executionKeyFactory = new SimpleFlowExecutionKeyFactory();
|
||||
|
||||
/**
|
||||
* Sets the attributes to apply to flow executions created by this factory. Execution attributes may affect flow
|
||||
* execution behavior.
|
||||
* @param executionAttributes flow execution system attributes
|
||||
*/
|
||||
public void setExecutionAttributes(AttributeMap<Object> executionAttributes) {
|
||||
this.executionAttributes = executionAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strategy for loading listeners that should observe executions of a flow definition. Allows full control
|
||||
* over what listeners should apply for executions of a flow definition.
|
||||
*/
|
||||
public void setExecutionListenerLoader(FlowExecutionListenerLoader executionListenerLoader) {
|
||||
this.executionListenerLoader = executionListenerLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strategy for generating flow execution keys for persistent flow executions.
|
||||
*/
|
||||
public void setExecutionKeyFactory(FlowExecutionKeyFactory executionKeyFactory) {
|
||||
this.executionKeyFactory = executionKeyFactory;
|
||||
}
|
||||
|
||||
public FlowExecution createFlowExecution(FlowDefinition flowDefinition) {
|
||||
Assert.isInstanceOf(Flow.class, flowDefinition, "FlowDefinition is of the wrong type: ");
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Creating new execution of '" + flowDefinition.getId() + "'");
|
||||
}
|
||||
FlowExecutionImpl execution = new FlowExecutionImpl((Flow) flowDefinition);
|
||||
execution.setAttributes(executionAttributes);
|
||||
execution.setListeners(executionListenerLoader.getListeners(execution.getDefinition()));
|
||||
execution.setKeyFactory(executionKeyFactory);
|
||||
return execution;
|
||||
}
|
||||
|
||||
public FlowExecution restoreFlowExecution(FlowExecution flowExecution, FlowDefinition flowDefinition,
|
||||
FlowExecutionKey flowExecutionKey, MutableAttributeMap<Object> conversationScope,
|
||||
FlowDefinitionLocator subflowDefinitionLocator) {
|
||||
Assert.isInstanceOf(FlowExecutionImpl.class, flowExecution, "FlowExecution is of the wrong type: ");
|
||||
Assert.isInstanceOf(Flow.class, flowDefinition, "FlowDefinition is of the wrong type: ");
|
||||
FlowExecutionImpl execution = (FlowExecutionImpl) flowExecution;
|
||||
Flow flow = (Flow) flowDefinition;
|
||||
execution.setFlow(flow);
|
||||
if (execution.hasSessions()) {
|
||||
FlowSessionImpl rootSession = execution.getRootSession();
|
||||
rootSession.setFlow(flow);
|
||||
rootSession.setState(flow.getStateInstance(rootSession.getStateId()));
|
||||
if (execution.hasSubflowSessions()) {
|
||||
for (Iterator<FlowSessionImpl> it = execution.getSubflowSessionIterator(); it.hasNext();) {
|
||||
FlowSessionImpl subflowSession = it.next();
|
||||
Flow subflowDef = (Flow) subflowDefinitionLocator.getFlowDefinition(subflowSession.getFlowId());
|
||||
subflowSession.setFlow(subflowDef);
|
||||
subflowSession.setState(subflowDef.getStateInstance(subflowSession.getStateId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
execution.setKey(flowExecutionKey);
|
||||
if (conversationScope == null) {
|
||||
conversationScope = new LocalAttributeMap<>();
|
||||
}
|
||||
execution.setConversationScope(conversationScope);
|
||||
execution.setAttributes(executionAttributes);
|
||||
execution.setListeners(executionListenerLoader.getListeners(execution.getDefinition()));
|
||||
execution.setKeyFactory(executionKeyFactory);
|
||||
return execution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple key factory suitable for standalone usage and testing. Not expected to be used in a web environment.
|
||||
*/
|
||||
private static class SimpleFlowExecutionKeyFactory implements FlowExecutionKeyFactory {
|
||||
|
||||
private int sequence;
|
||||
|
||||
public FlowExecutionKey getKey(FlowExecution execution) {
|
||||
if (execution.getKey() == null) {
|
||||
return new SimpleFlowExecutionKey(nextSequence());
|
||||
} else {
|
||||
// keep the same key
|
||||
return execution.getKey();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllFlowExecutionSnapshots(FlowExecution execution) {
|
||||
}
|
||||
|
||||
public void removeFlowExecutionSnapshot(FlowExecution execution) {
|
||||
}
|
||||
|
||||
public void updateFlowExecutionSnapshot(FlowExecution execution) {
|
||||
}
|
||||
|
||||
private synchronized int nextSequence() {
|
||||
return ++sequence;
|
||||
}
|
||||
|
||||
private static class SimpleFlowExecutionKey extends FlowExecutionKey {
|
||||
|
||||
private int value;
|
||||
|
||||
public SimpleFlowExecutionKey(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof SimpleFlowExecutionKey)) {
|
||||
SimpleFlowExecutionKey key = (SimpleFlowExecutionKey) o;
|
||||
return value == key.value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,102 +1,102 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.model.builder;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelHolder;
|
||||
|
||||
/**
|
||||
* A flow model holder that can detect changes on an underlying flow model resource and refresh that resource
|
||||
* automatically.
|
||||
* <p>
|
||||
* This class is thread-safe.
|
||||
* <p>
|
||||
* Note that this {@link FlowModel} holder uses a {@link FlowModelBuilder}.
|
||||
*
|
||||
* @see FlowModel
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class DefaultFlowModelHolder implements FlowModelHolder {
|
||||
|
||||
private FlowModel flowModel;
|
||||
|
||||
private FlowModelBuilder flowModelBuilder;
|
||||
|
||||
private boolean assembling;
|
||||
|
||||
/**
|
||||
* Creates a new refreshable flow model holder that uses the configured assembler (GOF director) to drive flow
|
||||
* assembly, on initial use and on any resource change or refresh.
|
||||
* @param flowModelBuilder the flow model builder to use
|
||||
*/
|
||||
public DefaultFlowModelHolder(FlowModelBuilder flowModelBuilder) {
|
||||
Assert.notNull(flowModelBuilder, "The flow model builder is required");
|
||||
this.flowModelBuilder = flowModelBuilder;
|
||||
}
|
||||
|
||||
public synchronized FlowModel getFlowModel() {
|
||||
if (assembling) {
|
||||
// must return early assembly result for when a flow calls itself recursively
|
||||
return flowModelBuilder.getFlowModel();
|
||||
}
|
||||
if (flowModel == null) {
|
||||
assembleFlowModel();
|
||||
} else {
|
||||
if (flowModelBuilder.hasFlowModelResourceChanged()) {
|
||||
assembleFlowModel();
|
||||
}
|
||||
}
|
||||
return flowModel;
|
||||
}
|
||||
|
||||
public Resource getFlowModelResource() {
|
||||
return flowModelBuilder.getFlowModelResource();
|
||||
}
|
||||
|
||||
public boolean hasFlowModelChanged() {
|
||||
return flowModelBuilder.hasFlowModelResourceChanged();
|
||||
}
|
||||
|
||||
public synchronized void refresh() {
|
||||
assembleFlowModel();
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private void assembleFlowModel() throws FlowModelBuilderException {
|
||||
try {
|
||||
assembling = true;
|
||||
flowModelBuilder.init();
|
||||
flowModelBuilder.build();
|
||||
flowModel = flowModelBuilder.getFlowModel();
|
||||
} finally {
|
||||
try {
|
||||
flowModelBuilder.dispose();
|
||||
} finally {
|
||||
assembling = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("flowModelBuilder", flowModelBuilder).toString();
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.model.builder;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelHolder;
|
||||
|
||||
/**
|
||||
* A flow model holder that can detect changes on an underlying flow model resource and refresh that resource
|
||||
* automatically.
|
||||
* <p>
|
||||
* This class is thread-safe.
|
||||
* <p>
|
||||
* Note that this {@link FlowModel} holder uses a {@link FlowModelBuilder}.
|
||||
*
|
||||
* @see FlowModel
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class DefaultFlowModelHolder implements FlowModelHolder {
|
||||
|
||||
private FlowModel flowModel;
|
||||
|
||||
private FlowModelBuilder flowModelBuilder;
|
||||
|
||||
private boolean assembling;
|
||||
|
||||
/**
|
||||
* Creates a new refreshable flow model holder that uses the configured assembler (GOF director) to drive flow
|
||||
* assembly, on initial use and on any resource change or refresh.
|
||||
* @param flowModelBuilder the flow model builder to use
|
||||
*/
|
||||
public DefaultFlowModelHolder(FlowModelBuilder flowModelBuilder) {
|
||||
Assert.notNull(flowModelBuilder, "The flow model builder is required");
|
||||
this.flowModelBuilder = flowModelBuilder;
|
||||
}
|
||||
|
||||
public synchronized FlowModel getFlowModel() {
|
||||
if (assembling) {
|
||||
// must return early assembly result for when a flow calls itself recursively
|
||||
return flowModelBuilder.getFlowModel();
|
||||
}
|
||||
if (flowModel == null) {
|
||||
assembleFlowModel();
|
||||
} else {
|
||||
if (flowModelBuilder.hasFlowModelResourceChanged()) {
|
||||
assembleFlowModel();
|
||||
}
|
||||
}
|
||||
return flowModel;
|
||||
}
|
||||
|
||||
public Resource getFlowModelResource() {
|
||||
return flowModelBuilder.getFlowModelResource();
|
||||
}
|
||||
|
||||
public boolean hasFlowModelChanged() {
|
||||
return flowModelBuilder.hasFlowModelResourceChanged();
|
||||
}
|
||||
|
||||
public synchronized void refresh() {
|
||||
assembleFlowModel();
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private void assembleFlowModel() throws FlowModelBuilderException {
|
||||
try {
|
||||
assembling = true;
|
||||
flowModelBuilder.init();
|
||||
flowModelBuilder.build();
|
||||
flowModel = flowModelBuilder.getFlowModel();
|
||||
} finally {
|
||||
try {
|
||||
flowModelBuilder.dispose();
|
||||
} finally {
|
||||
assembling = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("flowModelBuilder", flowModelBuilder).toString();
|
||||
}
|
||||
}
|
||||
@@ -1,85 +1,85 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.model.builder;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
|
||||
/**
|
||||
* Builder interface used to build a flow model. The process of building a flow model consists of the following steps:
|
||||
* <ol>
|
||||
* <li>Initialize this builder by calling {@link #init()}.
|
||||
* <li>Call {@link #build()} to create the flow model.
|
||||
* <li>Call {@link #getFlowModel()} to return the fully-built {@link FlowModel} model.
|
||||
* <li>Dispose this builder, releasing any resources allocated during the building process by calling {@link #dispose()}.
|
||||
* </ol>
|
||||
* <p>
|
||||
* Implementations should encapsulate flow construction logic, either for a specific kind of flow, for example, an
|
||||
* <code>XmlFlowModelBuilder</code>, for building flows from an XML-definition.
|
||||
* <p>
|
||||
* This is a good example of the classic GoF builder pattern.
|
||||
*
|
||||
* @see FlowModel
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public interface FlowModelBuilder {
|
||||
|
||||
/**
|
||||
* Initialize this builder. This could cause the builder to open a stream to an externalized resource representing
|
||||
* the flow definition, for example.
|
||||
* @throws FlowModelBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void init() throws FlowModelBuilderException;
|
||||
|
||||
/**
|
||||
* Builds any variables initialized by the flow when it starts.
|
||||
* @throws FlowModelBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void build() throws FlowModelBuilderException;
|
||||
|
||||
/**
|
||||
* Get the fully constructed flow model. Called by the builder's assembler (director) after assembly. When this
|
||||
* method is called by the assembler, it is expected flow construction has completed and the returned flow model is
|
||||
* ready for use.
|
||||
* @throws FlowModelBuilderException an exception occurred building this flow
|
||||
*/
|
||||
FlowModel getFlowModel() throws FlowModelBuilderException;
|
||||
|
||||
/**
|
||||
* Shutdown the builder, releasing any resources it holds. A new flow construction process should start with another
|
||||
* call to the {@link #init()} method.
|
||||
* @throws FlowModelBuilderException an exception occurred disposing this flow
|
||||
*/
|
||||
void dispose() throws FlowModelBuilderException;
|
||||
|
||||
/**
|
||||
* Get the underlying flow model resource accessed to build this flow model. Returns null if this builder does not
|
||||
* construct the flow model from a resource.
|
||||
* @return the flow model resource
|
||||
*/
|
||||
Resource getFlowModelResource();
|
||||
|
||||
/**
|
||||
* Returns true if the underlying flow model resource has changed since the last call to {@link #init()}. Always
|
||||
* returns false if the flow model is not build from a resource.
|
||||
* @return true if the resource backing the flow model has changed
|
||||
*/
|
||||
boolean hasFlowModelResourceChanged();
|
||||
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.model.builder;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
|
||||
/**
|
||||
* Builder interface used to build a flow model. The process of building a flow model consists of the following steps:
|
||||
* <ol>
|
||||
* <li>Initialize this builder by calling {@link #init()}.
|
||||
* <li>Call {@link #build()} to create the flow model.
|
||||
* <li>Call {@link #getFlowModel()} to return the fully-built {@link FlowModel} model.
|
||||
* <li>Dispose this builder, releasing any resources allocated during the building process by calling {@link #dispose()}.
|
||||
* </ol>
|
||||
* <p>
|
||||
* Implementations should encapsulate flow construction logic, either for a specific kind of flow, for example, an
|
||||
* <code>XmlFlowModelBuilder</code>, for building flows from an XML-definition.
|
||||
* <p>
|
||||
* This is a good example of the classic GoF builder pattern.
|
||||
*
|
||||
* @see FlowModel
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public interface FlowModelBuilder {
|
||||
|
||||
/**
|
||||
* Initialize this builder. This could cause the builder to open a stream to an externalized resource representing
|
||||
* the flow definition, for example.
|
||||
* @throws FlowModelBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void init() throws FlowModelBuilderException;
|
||||
|
||||
/**
|
||||
* Builds any variables initialized by the flow when it starts.
|
||||
* @throws FlowModelBuilderException an exception occurred building the flow
|
||||
*/
|
||||
void build() throws FlowModelBuilderException;
|
||||
|
||||
/**
|
||||
* Get the fully constructed flow model. Called by the builder's assembler (director) after assembly. When this
|
||||
* method is called by the assembler, it is expected flow construction has completed and the returned flow model is
|
||||
* ready for use.
|
||||
* @throws FlowModelBuilderException an exception occurred building this flow
|
||||
*/
|
||||
FlowModel getFlowModel() throws FlowModelBuilderException;
|
||||
|
||||
/**
|
||||
* Shutdown the builder, releasing any resources it holds. A new flow construction process should start with another
|
||||
* call to the {@link #init()} method.
|
||||
* @throws FlowModelBuilderException an exception occurred disposing this flow
|
||||
*/
|
||||
void dispose() throws FlowModelBuilderException;
|
||||
|
||||
/**
|
||||
* Get the underlying flow model resource accessed to build this flow model. Returns null if this builder does not
|
||||
* construct the flow model from a resource.
|
||||
* @return the flow model resource
|
||||
*/
|
||||
Resource getFlowModelResource();
|
||||
|
||||
/**
|
||||
* Returns true if the underlying flow model resource has changed since the last call to {@link #init()}. Always
|
||||
* returns false if the flow model is not build from a resource.
|
||||
* @return true if the resource backing the flow model has changed
|
||||
*/
|
||||
boolean hasFlowModelResourceChanged();
|
||||
|
||||
}
|
||||
@@ -1,46 +1,46 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.model.builder;
|
||||
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
|
||||
/**
|
||||
* Exception thrown to indicate a problem while building a flow model.
|
||||
*
|
||||
* @see FlowModelBuilder
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class FlowModelBuilderException extends FlowException {
|
||||
|
||||
/**
|
||||
* Create a new flow model builder exception.
|
||||
* @param message descriptive message
|
||||
*/
|
||||
public FlowModelBuilderException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new flow model builder exception.
|
||||
* @param message descriptive message
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public FlowModelBuilderException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.model.builder;
|
||||
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
|
||||
/**
|
||||
* Exception thrown to indicate a problem while building a flow model.
|
||||
*
|
||||
* @see FlowModelBuilder
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class FlowModelBuilderException extends FlowException {
|
||||
|
||||
/**
|
||||
* Create a new flow model builder exception.
|
||||
* @param message descriptive message
|
||||
*/
|
||||
public FlowModelBuilderException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new flow model builder exception.
|
||||
* @param message descriptive message
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public FlowModelBuilderException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -1,42 +1,42 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.model.builder.xml;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* A generic strategy interface encapsulating the logic to load an XML-based document.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface DocumentLoader {
|
||||
|
||||
/**
|
||||
* Load the XML-based document from the external resource.
|
||||
* @param resource the document resource
|
||||
* @return the loaded (parsed) document
|
||||
* @throws IOException an exception occured accessing the resource input stream
|
||||
* @throws ParserConfigurationException an exception occured building the document parser
|
||||
* @throws SAXException a error occured during document parsing
|
||||
*/
|
||||
Document loadDocument(Resource resource) throws IOException, ParserConfigurationException, SAXException;
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.model.builder.xml;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* A generic strategy interface encapsulating the logic to load an XML-based document.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface DocumentLoader {
|
||||
|
||||
/**
|
||||
* Load the XML-based document from the external resource.
|
||||
* @param resource the document resource
|
||||
* @return the loaded (parsed) document
|
||||
* @throws IOException an exception occured accessing the resource input stream
|
||||
* @throws ParserConfigurationException an exception occured building the document parser
|
||||
* @throws SAXException a error occured during document parsing
|
||||
*/
|
||||
Document loadDocument(Resource resource) throws IOException, ParserConfigurationException, SAXException;
|
||||
}
|
||||
@@ -1,74 +1,74 @@
|
||||
/*
|
||||
* Copyright 2004-2018 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
|
||||
*
|
||||
* https://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.model.builder.xml;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* EntityResolver implementation for the Spring Web Flow XML Schema. This will load the XSD from the classpath.
|
||||
* <p>
|
||||
* The xmlns of the XSD expected to be resolved:
|
||||
*
|
||||
* <pre>
|
||||
* <?xml version="1.0" encoding="UTF-8"?>
|
||||
* <flow xmlns="http://www.springframework.org/schema/webflow"
|
||||
* xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
* xsi:schemaLocation="http://www.springframework.org/schema/webflow
|
||||
* http://www.springframework.org/schema/webflow/spring-webflow.xsd">
|
||||
* </pre>
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
* @author Ben Hale
|
||||
*/
|
||||
class WebFlowEntityResolver implements EntityResolver {
|
||||
|
||||
private static final String SPRING_WEBFLOW_XSD = "spring-webflow.xsd";
|
||||
|
||||
private static final String[] WEBFLOW_VERSIONS = new String[] { "spring-webflow-2.4", "spring-webflow-2.0" };
|
||||
|
||||
|
||||
public InputSource resolveEntity(String publicId, String systemId) {
|
||||
if (systemId != null && systemId.contains(SPRING_WEBFLOW_XSD)) {
|
||||
return createInputSource(publicId, systemId, SPRING_WEBFLOW_XSD);
|
||||
}
|
||||
for (String element : WEBFLOW_VERSIONS) {
|
||||
if (systemId != null && systemId.indexOf(element) > systemId.lastIndexOf("/")) {
|
||||
return createInputSource(publicId, systemId, SPRING_WEBFLOW_XSD);
|
||||
}
|
||||
}
|
||||
// let the parser handle it
|
||||
return null;
|
||||
}
|
||||
|
||||
private InputSource createInputSource(String publicId, String systemId, String fileName) {
|
||||
try {
|
||||
Resource resource = new ClassPathResource(fileName, getClass());
|
||||
InputSource source = new InputSource(resource.getInputStream());
|
||||
source.setPublicId(publicId);
|
||||
source.setSystemId(systemId);
|
||||
return source;
|
||||
} catch (IOException ex) {
|
||||
// fall through below
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2018 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
|
||||
*
|
||||
* https://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.model.builder.xml;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* EntityResolver implementation for the Spring Web Flow XML Schema. This will load the XSD from the classpath.
|
||||
* <p>
|
||||
* The xmlns of the XSD expected to be resolved:
|
||||
*
|
||||
* <pre>
|
||||
* <?xml version="1.0" encoding="UTF-8"?>
|
||||
* <flow xmlns="http://www.springframework.org/schema/webflow"
|
||||
* xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
* xsi:schemaLocation="http://www.springframework.org/schema/webflow
|
||||
* http://www.springframework.org/schema/webflow/spring-webflow.xsd">
|
||||
* </pre>
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
* @author Ben Hale
|
||||
*/
|
||||
class WebFlowEntityResolver implements EntityResolver {
|
||||
|
||||
private static final String SPRING_WEBFLOW_XSD = "spring-webflow.xsd";
|
||||
|
||||
private static final String[] WEBFLOW_VERSIONS = new String[] { "spring-webflow-2.4", "spring-webflow-2.0" };
|
||||
|
||||
|
||||
public InputSource resolveEntity(String publicId, String systemId) {
|
||||
if (systemId != null && systemId.contains(SPRING_WEBFLOW_XSD)) {
|
||||
return createInputSource(publicId, systemId, SPRING_WEBFLOW_XSD);
|
||||
}
|
||||
for (String element : WEBFLOW_VERSIONS) {
|
||||
if (systemId != null && systemId.indexOf(element) > systemId.lastIndexOf("/")) {
|
||||
return createInputSource(publicId, systemId, SPRING_WEBFLOW_XSD);
|
||||
}
|
||||
}
|
||||
// let the parser handle it
|
||||
return null;
|
||||
}
|
||||
|
||||
private InputSource createInputSource(String publicId, String systemId, String fileName) {
|
||||
try {
|
||||
Resource resource = new ClassPathResource(fileName, getClass());
|
||||
InputSource source = new InputSource(resource.getInputStream());
|
||||
source.setPublicId(publicId);
|
||||
source.setSystemId(systemId);
|
||||
return source;
|
||||
} catch (IOException ex) {
|
||||
// fall through below
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,55 +1,55 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.model.registry;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
|
||||
/**
|
||||
* A holder holding a reference to a Flow model. Provides a layer of indirection, enabling things like "hot-reloadable"
|
||||
* flow models.
|
||||
*
|
||||
* @see FlowModelRegistry#registerFlowModel(String, FlowModelHolder)
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public interface FlowModelHolder {
|
||||
|
||||
/**
|
||||
* Returns the flow model held by this holder. Calling this method the first time may trigger flow model assembly.
|
||||
*/
|
||||
FlowModel getFlowModel();
|
||||
|
||||
/**
|
||||
* Has the underlying flow model changed since it was last accessed via a call to {@link #getFlowModel()}.
|
||||
* @return true if yes, false if not
|
||||
*/
|
||||
boolean hasFlowModelChanged();
|
||||
|
||||
/**
|
||||
* Returns the underlying resource defining the flow model.
|
||||
* @return the flow model resource
|
||||
*/
|
||||
Resource getFlowModelResource();
|
||||
|
||||
/**
|
||||
* Refresh the flow model held by this holder. Calling this method typically triggers flow re-assembly, which may
|
||||
* include a refresh from an externalized resource such as a file.
|
||||
*/
|
||||
void refresh();
|
||||
|
||||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* https://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.model.registry;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
|
||||
/**
|
||||
* A holder holding a reference to a Flow model. Provides a layer of indirection, enabling things like "hot-reloadable"
|
||||
* flow models.
|
||||
*
|
||||
* @see FlowModelRegistry#registerFlowModel(String, FlowModelHolder)
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public interface FlowModelHolder {
|
||||
|
||||
/**
|
||||
* Returns the flow model held by this holder. Calling this method the first time may trigger flow model assembly.
|
||||
*/
|
||||
FlowModel getFlowModel();
|
||||
|
||||
/**
|
||||
* Has the underlying flow model changed since it was last accessed via a call to {@link #getFlowModel()}.
|
||||
* @return true if yes, false if not
|
||||
*/
|
||||
boolean hasFlowModelChanged();
|
||||
|
||||
/**
|
||||
* Returns the underlying resource defining the flow model.
|
||||
* @return the flow model resource
|
||||
*/
|
||||
Resource getFlowModelResource();
|
||||
|
||||
/**
|
||||
* Refresh the flow model held by this holder. Calling this method typically triggers flow re-assembly, which may
|
||||
* include a refresh from an externalized resource such as a file.
|
||||
*/
|
||||
void refresh();
|
||||
|
||||
}
|
||||
@@ -1,36 +1,36 @@
|
||||
/*
|
||||
* Copyright 2004-2015 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
|
||||
*
|
||||
* https://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.model.registry;
|
||||
|
||||
/**
|
||||
* A companion to {@link FlowModelLocator} for access to the FlowModelHolder
|
||||
* wrapping the FlowModel.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 2.4.2
|
||||
*/
|
||||
public interface FlowModelHolderLocator {
|
||||
|
||||
/**
|
||||
* Lookup the FlowModelHolder with the specified id.
|
||||
* @param id the flow model identifier
|
||||
* @return the flow model holder
|
||||
* @throws NoSuchFlowModelException when the flow model with the specified
|
||||
* id does not exist
|
||||
*/
|
||||
FlowModelHolder getFlowModelHolder(String id) throws NoSuchFlowModelException;
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2015 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
|
||||
*
|
||||
* https://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.model.registry;
|
||||
|
||||
/**
|
||||
* A companion to {@link FlowModelLocator} for access to the FlowModelHolder
|
||||
* wrapping the FlowModel.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 2.4.2
|
||||
*/
|
||||
public interface FlowModelHolderLocator {
|
||||
|
||||
/**
|
||||
* Lookup the FlowModelHolder with the specified id.
|
||||
* @param id the flow model identifier
|
||||
* @return the flow model holder
|
||||
* @throws NoSuchFlowModelException when the flow model with the specified
|
||||
* id does not exist
|
||||
*/
|
||||
FlowModelHolder getFlowModelHolder(String id) throws NoSuchFlowModelException;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.model.registry;
|
||||
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
|
||||
/**
|
||||
* A runtime service locator interface for retrieving flow definitions by <code>id</code>. Flow locators are needed by
|
||||
* flow executors at runtime to retrieve flow models to support loading flow definitions.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public interface FlowModelLocator {
|
||||
|
||||
/**
|
||||
* Lookup the flow model with the specified id.
|
||||
* @param id the flow model identifier
|
||||
* @return the flow mode
|
||||
* @throws NoSuchFlowModelException when the flow model with the specified id does not exist
|
||||
*/
|
||||
FlowModel getFlowModel(String id) throws NoSuchFlowModelException;
|
||||
}
|
||||
/*
|
||||
* Copyright 2004-2012 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
|
||||
*
|
||||
* https://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.model.registry;
|
||||
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
|
||||
/**
|
||||
* A runtime service locator interface for retrieving flow definitions by <code>id</code>. Flow locators are needed by
|
||||
* flow executors at runtime to retrieve flow models to support loading flow definitions.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public interface FlowModelLocator {
|
||||
|
||||
/**
|
||||
* Lookup the flow model with the specified id.
|
||||
* @param id the flow model identifier
|
||||
* @return the flow mode
|
||||
* @throws NoSuchFlowModelException when the flow model with the specified id does not exist
|
||||
*/
|
||||
FlowModel getFlowModel(String id) throws NoSuchFlowModelException;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user