001: /*
002: * Created on Nov 29, 2005
003: */
004: package uk.org.ponder.rsf.preservation;
005:
006: import java.util.HashMap;
007: import java.util.Iterator;
008: import java.util.Map;
009:
010: import uk.org.ponder.beanutil.BeanLocator;
011: import uk.org.ponder.beanutil.BeanModelAlterer;
012: import uk.org.ponder.beanutil.WriteableBeanLocator;
013: import uk.org.ponder.rsf.components.ParameterList;
014: import uk.org.ponder.rsf.components.UIParameter;
015: import uk.org.ponder.stringutil.StringList;
016:
017: /**
018: * NB - this implementation is incomplete and a sample only.
019: *
020: * Stores token state inside the navigation URL. Note that the tokenID used here
021: * (as with clientFormTSH) is irrelevant since the state ID is implicitly
022: * specified by the client. The state is going to come back anyway, no point
023: * trying to specify it!
024: * <p>
025: * This TSH should be used with some care, since the storage it offers needs to
026: * be scoped manually - it is essentially "immortal" unless the TSH client
027: * cleans up properly.
028: * <p>
029: * Currently this TSH only knows how to store state in attributes. If you want
030: * to store it in the trunk URL, probably safer to define a new ViewParameters.
031: * <p>
032: * BETWEEN a POST REPONSE and the GET RENDERING, this state is indeed stored in
033: * the URL. However, after rendering, it is stored in a client field, as indeed
034: * any query parameters are that expect to be submitted for a POST.
035: * <p> Soon we will implement ClientFormPreservationStrategy, which will keep
036: * the information in a short-lived flow token (a la errortoken) in the gap, and
037: * then in a client form, perhaps in some form of compressed bulk.
038: * @author Antranig Basman (antranig@caret.cam.ac.uk)
039: *
040: */
041: // TODO: split this into request-scope and app-scope portions.
042: // TODO: This is actually an AutonomousStatePreservationStrategy!
043: // TODO: Can we abolish this completely?
044: public class InURLPreservationStrategy implements
045: StatePreservationStrategy {
046: private String prefix = "";
047: private Map requestmap;
048: private Map iupsspecs = new HashMap();
049: private BeanModelAlterer bma;
050: private ParameterList outgoingparams;
051:
052: public static class IUPSMapping {
053: public static final String IUPS_TERMINATOR = "|";
054: public String urlkey;
055: public String beanpath;
056:
057: public IUPSMapping(String spec) {
058: int splitpos = spec.indexOf(IUPS_TERMINATOR);
059: urlkey = spec.substring(0, splitpos);
060: beanpath = spec.substring(splitpos
061: + IUPS_TERMINATOR.length());
062: }
063: }
064:
065: /**
066: * Sets the URL prefix to be used in order to locate parameters from the
067: * request map.
068: */
069: public void setPrefix(String prefix) {
070: this .prefix = prefix;
071: }
072:
073: public void setBeanModelAlterer(BeanModelAlterer bma) {
074: this .bma = bma;
075: }
076:
077: public void setPreservingBeanSpecs(StringList specs) {
078: for (int i = 0; i < specs.size(); ++i) {
079: String spec = specs.stringAt(i);
080: IUPSMapping mapping = new IUPSMapping(spec);
081: iupsspecs.put(prefix + mapping.urlkey, mapping);
082: }
083: }
084:
085: /**
086: * Sets the parameter map for the current request. This is a map of String to
087: * String[]. It should not matter whether this is a normalized or unnormalized
088: * map, since InURLTSH parameters should be entirely orthogonal to RSF
089: * parameters.
090: */
091: public void setRequestMap(Map requestmap) {
092: this .requestmap = requestmap;
093: }
094:
095: public void setOutgoingParams(ParameterList outgoingparams) {
096: this .outgoingparams = outgoingparams;
097: }
098:
099: public int preserve(BeanLocator source, String tokenid) {
100: int preserved = 0;
101: outgoingparams.clear();
102: for (Iterator specit = iupsspecs.values().iterator(); specit
103: .hasNext();) {
104: IUPSMapping spec = (IUPSMapping) specit.next();
105: String converted = (String) bma.getFlattenedValue(
106: spec.beanpath, source, String.class, null);
107: if (converted == null)
108: continue;
109: outgoingparams.add(new UIParameter(spec.urlkey, converted));
110: ++preserved;
111: }
112: return preserved;
113: }
114:
115: public int restore(WriteableBeanLocator target, String tokenid) {
116: int restored = 0;
117: for (Iterator keyit = requestmap.keySet().iterator(); keyit
118: .hasNext();) {
119: String key = (String) keyit.next();
120: IUPSMapping spec = (IUPSMapping) iupsspecs.get(key);
121: if (spec != null) {
122: String[] value = (String[]) requestmap.get(key);
123: bma.setBeanValue(spec.beanpath, target, value, null,
124: false);
125: if (value != null) {
126: outgoingparams.add(new UIParameter(key, value[0]));
127: ++restored;
128: }
129: }
130: }
131: return restored;
132: }
133:
134: public void clear(String tokenid) {
135: outgoingparams.clear();
136: }
137:
138: }
|