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 }