001: /*
002: * Created on Nov 17, 2005
003: */
004: package uk.org.ponder.rsf.viewstate;
005:
006: import java.util.HashMap;
007: import java.util.Iterator;
008: import java.util.Map;
009:
010: import uk.org.ponder.reflect.DeepBeanCloner;
011: import uk.org.ponder.rsac.GlobalBeanAccessor;
012: import uk.org.ponder.rsf.components.ParameterList;
013: import uk.org.ponder.rsf.components.UIParameter;
014: import uk.org.ponder.stringutil.CharWrap;
015: import uk.org.ponder.stringutil.URLUtil;
016:
017: /** Utilities for converting URL parameters to and from Objects (ViewParameters),
018: * Maps, and Lists of various dizzying forms.
019: * @author Antranig Basman (amb26@ponder.org.uk)
020: *
021: */
022:
023: public class ViewParamUtil {
024: /** Returns the standard RSF "DeepBeanCloner" bound to the current thread.
025: * It is always undesirable to name beans in Java code, but this access is
026: * necessary to permit ViewParameters objects to clone themselves in contexts
027: * too small to inject this dependency.
028: */
029:
030: public static DeepBeanCloner getCloner() {
031: return (DeepBeanCloner) GlobalBeanAccessor
032: .getBean("deepBeanCloner");
033: }
034:
035: /** Converts the portion of ViewParameters that will be rendered into URL
036: * attributes into name/value pairs as a Map.
037: * @param vsh The ViewStateHandler encoding URL information
038: * @param viewparams The ViewParameters object to be encoded
039: * @return A map of String to String holding the key/value pairs.
040: */
041:
042: public static Map viewParamsToMap(ViewStateHandler vsh,
043: ViewParameters viewparams) {
044: String fullURL = vsh.getFullURL(viewparams);
045: int qpos = fullURL.indexOf('?');
046: HashMap togo = new HashMap();
047: return URLUtil.paramsToMap(fullURL.substring(qpos + 1), togo);
048: }
049:
050: /** A prefix for a ViewParameters attribute representing a "surrogate" pathinfo
051: * trunk segment. This is useful, for example when constructing a GET form which
052: * is attempting to submit against a part of the view state which has been mapped
053: * into the trunk path.
054: */
055: public static final String HIGH_PREFIX = "!";
056: /** An alternative representation of HIGH_PREFIX which will not take priority
057: * when determining the overall viewID of a param set.
058: */
059: public static final String LOW_PREFIX = "~";
060:
061: /** Convert a "surrogate" attribute name ("!0", "!1" etc) to its pathinfo index
062: * or return -1 if not recognised.
063: */
064: public static int attrToIndex(String attrname) {
065: if (attrname.startsWith(HIGH_PREFIX)
066: || attrname.startsWith(LOW_PREFIX)) {
067: try {
068: return Integer.parseInt(attrname.substring(1));
069: } catch (Exception e) {
070: return -1;
071: }
072: }
073: return -1;
074: }
075:
076: /** Returns the "surrogate attribute name" corresponding to a given pathinfo
077: * index and its priority level.
078: */
079: public static String getAttrIndex(int index, boolean highpriority) {
080: return (highpriority ? HIGH_PREFIX : LOW_PREFIX) + index;
081: }
082:
083: public static ParameterList mapToParamList(Map toconvert) {
084: ParameterList togo = new ParameterList();
085: for (Iterator keyit = toconvert.keySet().iterator(); keyit
086: .hasNext();) {
087: String key = (String) keyit.next();
088: Object value = toconvert.get(key);
089: if (value instanceof String) {
090: togo.add(new UIParameter(key, (String) value));
091: } else if (value instanceof String[]) {
092: String[] values = (String[]) value;
093: for (int i = 0; i < values.length; ++i) {
094: togo.add(new UIParameter(key, values[i]));
095: }
096: }
097: }
098: return togo;
099: }
100:
101: public static String toHTTPRequest(ViewParamsCodec vpcodec,
102: ViewParameters viewparams) {
103: RawURLState rus = vpcodec.renderViewParams(viewparams);
104: return ViewParamUtil.toHTTPRequest(rus);
105: }
106:
107: /**
108: * Returns the "mid-portion" of the URL corresponding to these parameters,
109: * i.e. /view-id/more-path-info?param1=val¶m2=val#anchor
110: */
111:
112: public static String toHTTPRequest(RawURLState rawstate) {
113: CharWrap togo = new CharWrap();
114: togo.append(rawstate.pathinfo);
115: boolean isfirst = true;
116: for (Iterator keyit = rawstate.params.keySet().iterator(); keyit
117: .hasNext();) {
118: String attrname = (String) keyit.next();
119: Object attrval = rawstate.params.get(attrname);
120: if (attrval instanceof String) {
121: URLUtil.appendAttribute(togo, isfirst, attrname,
122: (String) attrval);
123: isfirst = false;
124: } else if (attrval instanceof String[]) {
125: String[] vals = (String[]) attrval;
126: for (int j = 0; j < vals.length; ++j) {
127: URLUtil.appendAttribute(togo, isfirst, attrname,
128: vals[j]);
129: isfirst = false;
130: }
131: }
132: }
133: String anchorfield = rawstate.anchor;
134: if (rawstate.anchor != null) {
135: togo.append("#").append(anchorfield);
136: }
137: return togo.toString();
138: }
139:
140: /** Parse a "reduced URL" (as often seen in serialized component trees and
141: * the like) into a full ViewParameters object.
142: */
143:
144: public static ViewParameters parse(ViewParametersParser parser,
145: String reducedURL) {
146: int qpos = reducedURL.indexOf('?');
147: String pathinfo = qpos == -1 ? reducedURL : reducedURL
148: .substring(0, qpos);
149: HashMap params = new HashMap();
150: if (qpos != -1) {
151: URLUtil.paramsToMap(reducedURL.substring(qpos + 1), params);
152: }
153: return parser.parse(pathinfo, params);
154: }
155:
156: /** Convert an AnyViewParameters to a full URL, using the supplied ViewStateHandler
157: * in the case of a ViewParameters, or the contained URL in the case of
158: * RawViewParameters.
159: */
160: public static String getAnyFullURL(AnyViewParameters viewparams,
161: ViewStateHandler vsh) {
162: return viewparams instanceof RawViewParameters ? ((RawViewParameters) viewparams).URL
163: : vsh.getFullURL((ViewParameters) viewparams);
164: }
165: }
|