|
|||||||||||||||||||
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover | |||||||||||||||||||
Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
DataSqueezerImpl.java | 86.1% | 84.6% | 81.8% | 84.8% |
|
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;
|
|
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
|
|
27 |
* particular uses involving HTTP URLs and Cookies.
|
|
28 |
*
|
|
29 |
* @author Howard Lewis Ship
|
|
30 |
*/
|
|
31 |
|
|
32 |
public class DataSqueezerImpl implements DataSqueezer |
|
33 |
{ |
|
34 |
private static final String 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
|
|
44 |
* unsqueezing. Each adaptor is identified by a single ASCII character, in
|
|
45 |
* the range of 33 ('!') to 122 (the letter 'z'). The offset into this table
|
|
46 |
* is the character minus 33.
|
|
47 |
*/
|
|
48 |
|
|
49 |
private ISqueezeAdaptor[] _adaptorByPrefix = new ISqueezeAdaptor[ARRAY_SIZE]; |
|
50 |
|
|
51 |
/**
|
|
52 |
* AdaptorRegistry cache of adaptors.
|
|
53 |
*/
|
|
54 |
|
|
55 |
private StrategyRegistry _adaptors = new StrategyRegistryImpl(); |
|
56 |
|
|
57 |
/**
|
|
58 |
* Resource resolver used to deserialize classes.
|
|
59 |
*/
|
|
60 |
|
|
61 |
private ClassResolver _resolver;
|
|
62 |
|
|
63 |
/**
|
|
64 |
* Creates a new squeezer with the default set of adaptors.
|
|
65 |
*/
|
|
66 |
|
|
67 | 33 |
public DataSqueezerImpl(ClassResolver resolver)
|
68 |
{ |
|
69 | 33 |
this(resolver, null); |
70 |
} |
|
71 |
|
|
72 |
/**
|
|
73 |
* Creates a new data squeezer, which will have the default set of adaptors,
|
|
74 |
* and may add additional adaptors.
|
|
75 |
*
|
|
76 |
* @param adaptors
|
|
77 |
* an optional list of adaptors that will be registered to the
|
|
78 |
* data squeezer (it may be null or empty)
|
|
79 |
*/
|
|
80 |
|
|
81 | 34 |
public DataSqueezerImpl(ClassResolver resolver, ISqueezeAdaptor[] adaptors)
|
82 |
{ |
|
83 | 34 |
_resolver = resolver; |
84 |
|
|
85 | 34 |
registerDefaultAdaptors(); |
86 |
|
|
87 | 34 |
if (adaptors != null) |
88 | 1 |
for (int i = 0; i < adaptors.length; i++) |
89 | 1 |
adaptors[i].register(this);
|
90 |
} |
|
91 |
|
|
92 | 34 |
private void registerDefaultAdaptors() |
93 |
{ |
|
94 | 34 |
new CharacterAdaptor().register(this); |
95 | 34 |
new StringAdaptor().register(this); |
96 | 34 |
new IntegerAdaptor().register(this); |
97 | 34 |
new DoubleAdaptor().register(this); |
98 | 34 |
new ByteAdaptor().register(this); |
99 | 34 |
new FloatAdaptor().register(this); |
100 | 34 |
new LongAdaptor().register(this); |
101 | 34 |
new ShortAdaptor().register(this); |
102 | 34 |
new BooleanAdaptor().register(this); |
103 | 34 |
new SerializableAdaptor().register(this); |
104 | 34 |
new ComponentAddressAdaptor().register(this); |
105 | 34 |
new EnumAdaptor().register(this); |
106 |
} |
|
107 |
|
|
108 |
/**
|
|
109 |
* Registers the adaptor with one or more single-character prefixes.
|
|
110 |
*
|
|
111 |
* @param prefix
|
|
112 |
* one or more characters, each of which will be a prefix for the
|
|
113 |
* adaptor.
|
|
114 |
* @param dataClass
|
|
115 |
* the class (or interface) which can be encoded by the adaptor.
|
|
116 |
* @param adaptor
|
|
117 |
* the adaptor which to be registered.
|
|
118 |
*/
|
|
119 |
|
|
120 | 414 |
public synchronized void register(String prefix, Class dataClass, ISqueezeAdaptor adaptor) |
121 |
{ |
|
122 | 414 |
int prefixLength = prefix.length();
|
123 | 414 |
int offset;
|
124 |
|
|
125 | 414 |
if (prefixLength < 1)
|
126 | 1 |
throw new IllegalArgumentException(Tapestry.getMessage("DataSqueezer.short-prefix")); |
127 |
|
|
128 | 413 |
if (dataClass == null) |
129 | 1 |
throw new IllegalArgumentException(Tapestry.getMessage("DataSqueezer.null-class")); |
130 |
|
|
131 | 412 |
if (adaptor == null) |
132 | 1 |
throw new IllegalArgumentException(Tapestry.getMessage("DataSqueezer.null-adaptor")); |
133 |
|
|
134 | 411 |
for (int i = 0; i < prefixLength; i++) |
135 |
{ |
|
136 | 785 |
char ch = prefix.charAt(i);
|
137 |
|
|
138 | 785 |
if (ch < '!' | ch > 'z')
|
139 | 1 |
throw new IllegalArgumentException(Tapestry.getMessage("DataSqueezer.prefix-out-of-range")); |
140 |
|
|
141 | 784 |
offset = ch - FIRST_ADAPTOR_OFFSET; |
142 |
|
|
143 | 784 |
if (_adaptorByPrefix[offset] != null) |
144 | 1 |
throw new IllegalArgumentException(Tapestry.format("DataSqueezer.adaptor-prefix-taken", prefix |
145 |
.substring(i, i))); |
|
146 |
|
|
147 | 783 |
_adaptorByPrefix[offset] = adaptor; |
148 |
|
|
149 |
} |
|
150 |
|
|
151 | 409 |
_adaptors.register(dataClass, adaptor); |
152 |
} |
|
153 |
|
|
154 |
/**
|
|
155 |
* Squeezes the data object into a String by locating an appropriate adaptor
|
|
156 |
* that can perform the conversion. data may be null.
|
|
157 |
*/
|
|
158 |
|
|
159 | 76 |
public String squeeze(Object data) throws IOException |
160 |
{ |
|
161 | 76 |
ISqueezeAdaptor adaptor; |
162 |
|
|
163 | 76 |
if (data == null) |
164 | 2 |
return NULL_PREFIX;
|
165 |
|
|
166 | 74 |
adaptor = (ISqueezeAdaptor) _adaptors.getStrategy(data.getClass()); |
167 |
|
|
168 | 74 |
return adaptor.squeeze(this, data); |
169 |
} |
|
170 |
|
|
171 |
/**
|
|
172 |
* A convience; invokes {@link #squeeze(Object)}for each element in the
|
|
173 |
* data array. If data is null, returns null.
|
|
174 |
*/
|
|
175 |
|
|
176 | 14 |
public String[] squeeze(Object[] data) throws IOException |
177 |
{ |
|
178 | 14 |
if (data == null) |
179 | 1 |
return null; |
180 |
|
|
181 | 13 |
int length = data.length;
|
182 | 13 |
String[] result; |
183 |
|
|
184 | 13 |
result = new String[length];
|
185 |
|
|
186 | 13 |
for (int i = 0; i < length; i++) |
187 | 34 |
result[i] = squeeze(data[i]); |
188 |
|
|
189 | 13 |
return result;
|
190 |
} |
|
191 |
|
|
192 |
/**
|
|
193 |
* Unsqueezes the string. Note that in a special case, where the first
|
|
194 |
* character of the string is not a recognized prefix, it is assumed that
|
|
195 |
* the string is simply a string, and return with no change.
|
|
196 |
*/
|
|
197 |
|
|
198 | 82 |
public Object unsqueeze(String string) throws IOException |
199 |
{ |
|
200 | 82 |
ISqueezeAdaptor adaptor = null;
|
201 |
|
|
202 | 82 |
if (string.equals(NULL_PREFIX))
|
203 | 2 |
return null; |
204 |
|
|
205 | 80 |
int offset = string.charAt(0) - FIRST_ADAPTOR_OFFSET;
|
206 |
|
|
207 | 80 |
if (offset >= 0 && offset < _adaptorByPrefix.length)
|
208 | 80 |
adaptor = _adaptorByPrefix[offset]; |
209 |
|
|
210 |
// If the adaptor is not otherwise recognized, the it is simply
|
|
211 |
// an encoded String (the StringAdaptor may not have added
|
|
212 |
// a prefix).
|
|
213 |
|
|
214 | 80 |
if (adaptor == null) |
215 | 2 |
return string;
|
216 |
|
|
217 |
// Adaptor should never be null, because we always supply
|
|
218 |
// an adaptor for String
|
|
219 |
|
|
220 | 78 |
return adaptor.unsqueeze(this, string); |
221 |
} |
|
222 |
|
|
223 |
/**
|
|
224 |
* Convienience method for unsqueezing many strings (back into objects).
|
|
225 |
* <p>
|
|
226 |
* If strings is null, returns null.
|
|
227 |
*/
|
|
228 |
|
|
229 | 21 |
public Object[] unsqueeze(String[] strings) throws IOException |
230 |
{ |
|
231 | 21 |
if (strings == null) |
232 | 1 |
return null; |
233 |
|
|
234 | 20 |
int length = strings.length;
|
235 | 20 |
Object[] result; |
236 |
|
|
237 | 20 |
result = new Object[length];
|
238 |
|
|
239 | 20 |
for (int i = 0; i < length; i++) |
240 | 42 |
result[i] = unsqueeze(strings[i]); |
241 |
|
|
242 | 20 |
return result;
|
243 |
} |
|
244 |
|
|
245 |
/**
|
|
246 |
* Checks to see if a given prefix character has a registered adaptor. This
|
|
247 |
* is used by the String adaptor to determine whether it needs to put a
|
|
248 |
* prefix on its String.
|
|
249 |
*/
|
|
250 |
|
|
251 | 0 |
public boolean isPrefixRegistered(char prefix) |
252 |
{ |
|
253 | 0 |
int offset = prefix - FIRST_ADAPTOR_OFFSET;
|
254 |
|
|
255 |
// Special case for handling nulls.
|
|
256 |
|
|
257 | 0 |
if (prefix == NULL_PREFIX_CH)
|
258 | 0 |
return true; |
259 |
|
|
260 | 0 |
if (offset < 0 || offset >= _adaptorByPrefix.length)
|
261 | 0 |
return false; |
262 |
|
|
263 | 0 |
return _adaptorByPrefix[offset] != null; |
264 |
} |
|
265 |
|
|
266 | 0 |
public String toString()
|
267 |
{ |
|
268 | 0 |
StringBuffer buffer; |
269 |
|
|
270 | 0 |
buffer = new StringBuffer();
|
271 | 0 |
buffer.append("DataSqueezer[adaptors=<");
|
272 | 0 |
buffer.append(_adaptors.toString()); |
273 | 0 |
buffer.append(">]");
|
274 |
|
|
275 | 0 |
return buffer.toString();
|
276 |
} |
|
277 |
|
|
278 |
/**
|
|
279 |
* Returns the resource resolver used with this squeezer.
|
|
280 |
*
|
|
281 |
* @since 2.2
|
|
282 |
*/
|
|
283 |
|
|
284 | 3 |
public ClassResolver getResolver()
|
285 |
{ |
|
286 | 3 |
return _resolver;
|
287 |
} |
|
288 |
|
|
289 |
} |
|