KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tapestry > util > io > DataSqueezerImpl


1 // Copyright 2004, 2005 The Apache Software Foundation
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15 package org.apache.tapestry.util.io;
16
17 import java.io.IOException JavaDoc;
18
19 import org.apache.hivemind.ClassResolver;
20 import org.apache.hivemind.lib.util.StrategyRegistry;
21 import org.apache.hivemind.lib.util.StrategyRegistryImpl;
22 import org.apache.tapestry.Tapestry;
23 import org.apache.tapestry.services.DataSqueezer;
24
25 /**
26  * A class used to convert arbitrary objects to Strings and back. This has particular uses involving
27  * HTTP URLs and Cookies.
28  *
29  * @author Howard Lewis Ship
30  */

31
32 public class DataSqueezerImpl implements DataSqueezer
33 {
34     private static final String JavaDoc NULL_PREFIX = "X";
35
36     private static final char NULL_PREFIX_CH = 'X';
37
38     private static final int ARRAY_SIZE = 90;
39
40     private static final int FIRST_ADAPTOR_OFFSET = 33;
41
42     /**
43      * An array of adaptors; this is used as a cheap lookup-table when unsqueezing. Each adaptor is
44      * identified by a single ASCII character, in the range of 33 ('!') to 122 (the letter 'z'). The
45      * offset into this table is the character minus 33.
46      */

47
48     private ISqueezeAdaptor[] _adaptorByPrefix = new ISqueezeAdaptor[ARRAY_SIZE];
49
50     /**
51      * AdaptorRegistry cache of adaptors.
52      */

53
54     private StrategyRegistry _adaptors = new StrategyRegistryImpl();
55
56     /**
57      * Resource resolver used to deserialize classes.
58      */

59
60     private ClassResolver _resolver;
61
62     /**
63      * Creates a new squeezer with the default set of adaptors.
64      */

65
66     public DataSqueezerImpl(ClassResolver resolver)
67     {
68         this(resolver, null);
69     }
70
71     /**
72      * Creates a new data squeezer, which will have the default set of adaptors, and may add
73      * additional adaptors.
74      *
75      * @param adaptors
76      * an optional list of adaptors that will be registered to the data squeezer (it may
77      * be null or empty)
78      */

79
80     public DataSqueezerImpl(ClassResolver resolver, ISqueezeAdaptor[] adaptors)
81     {
82         _resolver = resolver;
83
84         registerDefaultAdaptors();
85
86         if (adaptors != null)
87             for (int i = 0; i < adaptors.length; i++)
88                 adaptors[i].register(this);
89     }
90
91     private void registerDefaultAdaptors()
92     {
93         new CharacterAdaptor().register(this);
94         new StringAdaptor().register(this);
95         new IntegerAdaptor().register(this);
96         new DoubleAdaptor().register(this);
97         new ByteAdaptor().register(this);
98         new FloatAdaptor().register(this);
99         new LongAdaptor().register(this);
100         new ShortAdaptor().register(this);
101         new BooleanAdaptor().register(this);
102         new SerializableAdaptor().register(this);
103         new ComponentAddressAdaptor().register(this);
104     }
105
106     /**
107      * Registers the adaptor with one or more single-character prefixes.
108      *
109      * @param prefix
110      * one or more characters, each of which will be a prefix for the adaptor.
111      * @param dataClass
112      * the class (or interface) which can be encoded by the adaptor.
113      * @param adaptor
114      * the adaptor which to be registered.
115      */

116
117     public synchronized void register(String JavaDoc prefix, Class JavaDoc dataClass, ISqueezeAdaptor adaptor)
118     {
119         int prefixLength = prefix.length();
120         int offset;
121
122         if (prefixLength < 1)
123             throw new IllegalArgumentException JavaDoc(Tapestry.getMessage("DataSqueezer.short-prefix"));
124
125         if (dataClass == null)
126             throw new IllegalArgumentException JavaDoc(Tapestry.getMessage("DataSqueezer.null-class"));
127
128         if (adaptor == null)
129             throw new IllegalArgumentException JavaDoc(Tapestry.getMessage("DataSqueezer.null-adaptor"));
130
131         for (int i = 0; i < prefixLength; i++)
132         {
133             char ch = prefix.charAt(i);
134
135             if (ch < '!' | ch > 'z')
136                 throw new IllegalArgumentException JavaDoc(Tapestry
137                         .getMessage("DataSqueezer.prefix-out-of-range"));
138
139             offset = ch - FIRST_ADAPTOR_OFFSET;
140
141             if (_adaptorByPrefix[offset] != null)
142                 throw new IllegalArgumentException JavaDoc(Tapestry.format(
143                         "DataSqueezer.adaptor-prefix-taken",
144                         prefix.substring(i, i)));
145
146             _adaptorByPrefix[offset] = adaptor;
147
148         }
149
150         _adaptors.register(dataClass, adaptor);
151     }
152
153     /**
154      * Squeezes the data object into a String by locating an appropriate adaptor that can perform
155      * the conversion. data may be null.
156      */

157
158     public String JavaDoc squeeze(Object JavaDoc data) throws IOException JavaDoc
159     {
160         ISqueezeAdaptor adaptor;
161
162         if (data == null)
163             return NULL_PREFIX;
164
165         adaptor = (ISqueezeAdaptor) _adaptors.getStrategy(data.getClass());
166
167         return adaptor.squeeze(this, data);
168     }
169
170     /**
171      * A convience; invokes {@link #squeeze(Object)}for each element in the data array. If data is
172      * null, returns null.
173      */

174
175     public String JavaDoc[] squeeze(Object JavaDoc[] data) throws IOException JavaDoc
176     {
177         if (data == null)
178             return null;
179
180         int length = data.length;
181         String JavaDoc[] result;
182
183         result = new String JavaDoc[length];
184
185         for (int i = 0; i < length; i++)
186             result[i] = squeeze(data[i]);
187
188         return result;
189     }
190
191     /**
192      * Unsqueezes the string. Note that in a special case, where the first character of the string
193      * is not a recognized prefix, it is assumed that the string is simply a string, and return with
194      * no change.
195      */

196
197     public Object JavaDoc unsqueeze(String JavaDoc string) throws IOException JavaDoc
198     {
199         ISqueezeAdaptor adaptor = null;
200
201         if (string.equals(NULL_PREFIX))
202             return null;
203
204         int offset = string.charAt(0) - FIRST_ADAPTOR_OFFSET;
205
206         if (offset >= 0 && offset < _adaptorByPrefix.length)
207             adaptor = _adaptorByPrefix[offset];
208
209         // If the adaptor is not otherwise recognized, the it is simply
210
// an encoded String (the StringAdaptor may not have added
211
// a prefix).
212

213         if (adaptor == null)
214             return string;
215
216         // Adaptor should never be null, because we always supply
217
// an adaptor for String
218

219         return adaptor.unsqueeze(this, string);
220     }
221
222     /**
223      * Convienience method for unsqueezing many strings (back into objects).
224      * <p>
225      * If strings is null, returns null.
226      */

227
228     public Object JavaDoc[] unsqueeze(String JavaDoc[] strings) throws IOException JavaDoc
229     {
230         if (strings == null)
231             return null;
232
233         int length = strings.length;
234         Object JavaDoc[] result;
235
236         result = new Object JavaDoc[length];
237
238         for (int i = 0; i < length; i++)
239             result[i] = unsqueeze(strings[i]);
240
241         return result;
242     }
243
244     /**
245      * Checks to see if a given prefix character has a registered adaptor. This is used by the
246      * String adaptor to determine whether it needs to put a prefix on its String.
247      */

248
249     public boolean isPrefixRegistered(char prefix)
250     {
251         int offset = prefix - FIRST_ADAPTOR_OFFSET;
252
253         // Special case for handling nulls.
254

255         if (prefix == NULL_PREFIX_CH)
256             return true;
257
258         if (offset < 0 || offset >= _adaptorByPrefix.length)
259             return false;
260
261         return _adaptorByPrefix[offset] != null;
262     }
263
264     public String JavaDoc toString()
265     {
266         StringBuffer JavaDoc buffer;
267
268         buffer = new StringBuffer JavaDoc();
269         buffer.append("DataSqueezer[adaptors=<");
270         buffer.append(_adaptors.toString());
271         buffer.append(">]");
272
273         return buffer.toString();
274     }
275
276     /**
277      * Returns the resource resolver used with this squeezer.
278      *
279      * @since 2.2
280      */

281
282     public ClassResolver getResolver()
283     {
284         return _resolver;
285     }
286
287 }
Popular Tags