001 // Copyright 2006-2007 Daniel Gredler
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package net.sf.beanform.prop;
016
017 import net.sf.beanform.util.StringCache;
018
019 import org.apache.hivemind.ApplicationRuntimeException;
020 import org.apache.tapestry.services.DataSqueezer;
021 import org.apache.tapestry.util.io.SqueezeAdaptor;
022
023 /**
024 * Squeezes {@link BeanProperty} objects into and out of HTML and URLs.
025 *
026 * Since many class names, property names and validator strings will be serialized
027 * to the client, but the number of distinct class names, property names and validator
028 * strings using this squeezer will usually be small, this implementation keeps small
029 * static caches of these strings and their corresponding "abbreviations", which are what
030 * is actually sent to the clients. This is extremely important, as URLs are generally
031 * <a href="http://support.microsoft.com/default.aspx?scid=KB;en-us;q208427">limited</a>
032 * to about 2,000 characters.
033 *
034 * @author Daniel Gredler
035 */
036 public class BeanPropertySqueezer implements SqueezeAdaptor {
037
038 private final static StringCache CLASSNAME_CACHE = new StringCache( 100 );
039 private final static StringCache PROPERTY_CACHE = new StringCache( 100 );
040 private final static StringCache VALIDATOR_CACHE = new StringCache( 100 );
041 private final static StringCache INPUT_CACHE = new StringCache( 10 );
042
043 private final static String PREFIX = "B";
044 private final static String DIVIDER = "_";
045
046 public String getPrefix() {
047 return PREFIX;
048 }
049
050 public Class getDataClass() {
051 return BeanProperty.class;
052 }
053
054 public String squeeze( DataSqueezer squeezer, Object data ) {
055 BeanProperty prop = (BeanProperty) data;
056 String c = CLASSNAME_CACHE.getShortVersion( prop.getOwnerClass().getName() );
057 String p = PROPERTY_CACHE.getShortVersion( prop.getName() );
058 String v = VALIDATOR_CACHE.getShortVersion( prop.getValidators() );
059 String i = INPUT_CACHE.getShortVersion( prop.getInput() );
060 return PREFIX + DIVIDER + c + DIVIDER + p + DIVIDER + v + DIVIDER + i;
061 }
062
063 public Object unsqueeze( DataSqueezer squeezer, String string ) {
064 String[] s = string.split( DIVIDER );
065 String c = CLASSNAME_CACHE.getRealVersion( s[ 1 ] );
066 String p = PROPERTY_CACHE.getRealVersion( s[ 2 ] );
067 String v = VALIDATOR_CACHE.getRealVersion( s[ 3 ] );
068 String i = INPUT_CACHE.getRealVersion( s[ 4 ] );
069 try {
070 Class clazz = Class.forName( c );
071 BeanProperty prop = new BeanProperty( clazz, p, v, i );
072 return prop;
073 }
074 catch( ClassNotFoundException e ) {
075 String msg = BeanPropertyMessages.unsqueezeClassNotFound( string, c );
076 throw new ApplicationRuntimeException( msg, e );
077 }
078 }
079
080 }