Hi Andy,

The same Encoder could indeed be used across multiple pages.

Some pointers:

You need to create one of these:
http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry/ValueEncoder.html
Look at the source for one of the existing implementation for ideas,
e.g. StringEncoder

I've attached an example implementation of a MapValueEncoder.java


You will then need to configure your Tap App to use your encoder e.g.

        public static void
contributeValueEncoderSource(MappedConfiguration<Class,
ValueEncoderFactory> configuration)  { 
                configuration.add(Map.class, new 
GenericValueEncoderFactory<Map>(new
MapValueEncoder())); 
        } 



You can then have activation context's that take a Map e.g.

        protected boolean onActivate(Map params) {      
          id =  params.get("id");
        }


I'm sure there is a doc page for encoders, although I cann't seem to dig
it out.


-----Original Message-----
From: Andy Buckley <andy.buck...@durham.ac.uk>
Reply-To: Tapestry users <users@tapestry.apache.org>
To: Tapestry users <users@tapestry.apache.org>
Subject: Re: T5: Passing named/structured-type params in URLs?
Date: Tue, 12 May 2009 16:07:06 +0100

Joel Halbert wrote:
> There was a jira feature request raised for named params some time ago:
> https://issues.apache.org/jira/browse/TAP5-264
> 
> 
> Andy - in the meantime, another alternative is to create a custom
> ValueEncoder for activation contexts which can encode and decode a map.
> You could then encode the map context using a scheme which uses, for
> example, underscores as delimiters, such as:
> 
> /mypage/name1_value1_name2_value2
> (i.e. /mypage/<context>)
> 
> This would allow you to access params by name from an activation
> context.
> 
> This works well enough so long as you do not care about using the
> correct http request syntax for query strings
> (?name1=value1&name2=value2).

I've ended up essentially doing this, but more manually via the
onActivate() method of the page. Can you point me at any documentation
on how to do this with a custom ValueEncoder as you've suggested, and
what the benefits would be of doing it that way? (e.g. would this make
it easy to use the same param value encoding scheme on multiple pages?)

Cheers,
Andy

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.collections.map.ListOrderedMap;
import org.apache.log4j.Logger;
import org.apache.tapestry5.ValueEncoder;

public class MapValueEncoder implements ValueEncoder {

	static final Logger log = Logger.getLogger(MapValueEncoder.class);
	
	private static final String DELIM = "_";

	@Override
	public String toClient(Object value) {
		String res = "";
		Iterator<String> it = null;
		Map<String,Object> map = (Map<String, Object>) value;
		
		if (value instanceof ListOrderedMap) {
			ListOrderedMap lomap = (ListOrderedMap) value;
			it = lomap.keyList().iterator();
			
		} else {
			it = map.keySet().iterator();
						
		}
		
		while(it.hasNext()) {
			String key = it.next();
			Object val = map.get(key);
			if (val != null) {
				if (res.length() > 0) {
					res += DELIM;
				}
				res += key + DELIM + escapeString(val.toString());	
			}
		}
		

		return res;
	}

	@Override
	public Object toValue(String clientValue) {
		String[] tokens = clientValue.split(DELIM);
		ListOrderedMap res = new ListOrderedMap();
		boolean tokIsKey = true;
		String currKey = null;
		for (int i = 0; i < tokens.length; i++) {
			String tok = tokens[i];
			if (tokIsKey) {
				currKey = tok;
				
			} else {
				res.put(currKey, descapeString(tok));
				
			}
			
			tokIsKey = !tokIsKey;
		}
		
		return res;
	}
	
	public static String escapeString(String string) {
		try {
			return URLEncoder.encode(string, "UTF-8");
			
		} catch (UnsupportedEncodingException e) {
			log.error("unable to encode : " + string, e);
			return "";
		}
	}

	public static String descapeString(String string) {
		try {
			return URLDecoder.decode(string, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			log.error("unable to descape : " + string, e);
			return "";
		}
	}
	
}

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
For additional commands, e-mail: users-h...@tapestry.apache.org

Reply via email to