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 }