001: /*
002: * Created on Oct 25, 2004
003: */
004: package uk.org.ponder.rsf.viewstate;
005:
006: import uk.org.ponder.reflect.DeepBeanCloner;
007:
008: /**
009: * An RSF ViewParameters is a rule for extracting the relevant fields from a URL
010: * (or similar spec) that specify the content of a view and representing them in
011: * a typesafe way as an object. Users will more frequently extend the more
012: * convenient class {@link SimpleViewParameters}. The actual work of parsing is
013: * done by the more stateful bean ViewParametersParser.
014: * <p/>Every ViewParameters class must be default-constructible.
015: * <p/>
016: * The base class abstracting common functionality for specifying a view state
017: * of a web application, independent of any particular application or url
018: * mapping technology. In order to get generate a complete external URL, you
019: * must use one of the methods of
020: * {@link uk.org.ponder.rsf.viewstate.ViewStateHandler}.
021: *
022: * @author Antranig Basman (antranig@caret.cam.ac.uk)
023: *
024: */
025: // for example:
026: // http://localhost:8080/FlowTalkServlet/faces/threaded-message?targetID=3mdugroBVjhPPTubjQkjAQjG
027: // |-----------------------------------------||---------------|
028: // base url view id
029: // in fact, since we only ever have ONE view id, in fact we could simply
030: // omit baseurl!!
031: public abstract class ViewParameters implements AnyViewParameters {
032: /** The special prefix which is used in {@link #getParseSpec()} to represent
033: * a part of URL state which will be placed in the URL trunk rather than
034: * an attribute. For example, the {{@link #viewID} itself is commonly mapped
035: * to <code>@0</code> indicating it is the first path segment in the "pathInfo"
036: * section of the URL.
037: */
038: public static final String TRUNK_PARSE_PREFIX = "@";
039:
040: /**
041: * Returns a "parse specification" suitable for mapping this ViewParameters
042: * onto a URL.</p>
043: * This is a comma-separated list of field specifications. Each field specification
044: * takes the form of the name of an URL attribute, optionally followed by the
045: * colon character : and an EL path into this ViewParameters object onto which
046: * the attribute should be mapped. Instead of a URL attribute, URL pathinfo
047: * segments can be specified by providing strings of the form <code>@0</code>,
048: * <code>@1</code>, etc.
049: * </p>If users derive from
050: * {@link SimpleViewParameters} and do not override this method, a default
051: * parse specification will be inferred which maps all defined properties
052: * onto similarly-named URL attributes.
053: *
054: * @return A string representing a URL parse specification
055: */
056:
057: public abstract String getParseSpec();
058:
059: /** Return a field which will be used to form the "anchor" text in the URL
060: * state - in HTTP, this typically follows the URL body with a <code>#</code>
061: * character. */
062: public String getAnchorField() {
063: return null;
064: }
065:
066: // Note that copying does not copy the error token! All command links
067: // take the original request, and all non-command links should not share
068: // error state.
069: /*****************************************************************************
070: * See {@link #copyBase(DeepBeanCloner)} below. Uses a ThreadLocal call to
071: * acquire the standard DeepBeanCloner bound to the current thread - necessary
072: * since ViewParameters objects are cloned in all sorts of lightweight
073: * contexts. Use the method below by preference if at all possible.
074: ****************************************************************************/
075: public ViewParameters copyBase() {
076: return copyBase(ViewParamUtil.getCloner());
077: }
078:
079: /** For the AnyViewParameters interface **/
080: public AnyViewParameters copy() {
081: return copyBase();
082: }
083:
084: /**
085: * Make a "deep clone" of this ViewParameters object, representing the "same"
086: * view state but sharing no Object state with this object. To enable this to
087: * work automatically, all extra members from derived classes must be POJO
088: * beans or peas. See {@link DeepBeanCloner} for explanation of the algorithm
089: * used. Use this method if the performance or architecture impact of the
090: * no-args method bothers you.
091: */
092: public ViewParameters copyBase(DeepBeanCloner cloner) {
093: return (ViewParameters) cloner.cloneBean(this , cloneexceptions);
094: }
095:
096: /**
097: * The primary key identifying this view - this is generally used as a key not
098: * only to view templates, component producers, but also into flow states.
099: * This field is always set.
100: */
101: public String viewID;
102:
103: /** The following public fields define RSF housekeeping information, and should
104: * not generally be read or written by user code.
105: * <p/>
106: * A globally unique key identifying view-specific state that is held on the
107: * server, restorable in the form of a request-scope bean container. Need not
108: * be set.
109: */
110: public String flowtoken;
111: /**
112: * This field is set in the case of an error arising from user-submitted data,
113: * in which case the data is being returned for correction. Not generally set.
114: */
115: public String errortoken;
116:
117: /**
118: * This field is set indicating that this view is a redirect from a level-1
119: * rendering error. Any further errors will be treated as fatal, to avoid a
120: * redirect loop. Usually not set.
121: */
122: public String errorredirect;
123: /**
124: * This field is set indicating that this view is a "terminal flow view",
125: * representing the summary to the user of a multi-request state (flow). Some,
126: * none or all of the request state accumulated during the flow may be
127: * available to render this view, most likely in a more rapidly-expiring cache
128: * (default is to use the same TokenStateHolder as the error state). It is
129: * only valid to set this field if flowtoken is also set.
130: */
131: public String endflow;
132:
133: /** This field is set indicating that this view will be rendered in
134: * "debug mode" - full RSF IDs will be allocated to every rendered element,
135: * and omitted elements will be highlighted in place.
136: */
137: public String debugrender;
138:
139: public static final String BASE_PARSE_SPEC = "flowtoken, endflow, errortoken, errorredirect, debugrender, @0:viewID";
140:
141: /**
142: * "Ephemeral" fields of ViewParameters state that will not propagate by
143: * default.
144: */
145: public static final String[] cloneexceptions = new String[] {
146: "flowtoken", "errortoken", "endflow", "parseSpec",
147: "anchorField" };
148:
149: /** Pea proxying method */
150: public AnyViewParameters get() {
151: return this;
152: }
153: }
|