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.util; 016 017 import java.util.HashMap; 018 import java.util.Map; 019 020 /** 021 * A thread-safe cache of strings that allows aliasing of long strings to smaller 022 * strings that can then be used to reverse the process. 023 * 024 * @author Daniel Gredler 025 */ 026 public class StringCache { 027 028 protected final static char[] CHARS = { 029 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 030 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 031 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; 032 033 protected int maxSize; 034 protected Map<String, String> cacheByShort; 035 protected Map<String, String> cacheByReal; 036 037 public StringCache( int maxSize ) { 038 this.maxSize = maxSize; 039 this.cacheByShort = new HashMap<String, String>( maxSize ); 040 this.cacheByReal = new HashMap<String, String>( maxSize ); 041 } 042 043 public synchronized String getShortVersion( String real ) { 044 if( this.cacheByReal.size() == this.maxSize ) return real; 045 String s; 046 if( this.cacheByReal.containsKey( real ) ) { 047 s = this.cacheByReal.get( real ); 048 } 049 else { 050 s = Character.toString( CHARS[ 0 ] ); 051 for( int i = 1; this.cacheByShort.containsKey( s ); i++ ) { 052 s = getChars( CHARS, i ); 053 } 054 this.cacheByShort.put( s, real ); 055 this.cacheByReal.put( real, s ); 056 } 057 return s; 058 } 059 060 public synchronized String getRealVersion( String shortVersion ) { 061 String real; 062 if( this.cacheByShort.containsKey( shortVersion ) ) { 063 real = this.cacheByShort.get( shortVersion ); 064 } 065 else { 066 real = shortVersion; 067 } 068 return real; 069 } 070 071 protected static String getChars( char[] chars, int index ) { 072 String s = new String(); 073 int i = index / chars.length; 074 if( i > 0 ) { 075 s = getChars( chars, i - 1 ) + s; 076 } 077 s = s + chars[ index % chars.length ]; 078 return s; 079 } 080 081 }