KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mckoi > database > TStringType


1 /**
2  * com.mckoi.database.TStringType 26 Jul 2002
3  *
4  * Mckoi SQL Database ( http://www.mckoi.com/database )
5  * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * Version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License Version 2 for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * Version 2 along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  * Change Log:
21  *
22  *
23  */

24
25 package com.mckoi.database;
26
27 import java.util.Locale JavaDoc;
28 import java.text.Collator JavaDoc;
29 import com.mckoi.database.global.StringAccessor;
30 import java.io.Reader JavaDoc;
31 import java.io.IOException JavaDoc;
32
33 /**
34  * An implementation of TType for a String.
35  *
36  * @author Tobias Downer
37  */

38
39 public final class TStringType extends TType {
40
41   static final long serialVersionUID = -4189752898050725908L;
42
43   /**
44    * The maximum allowed size for the string.
45    */

46   private int max_size;
47   
48   /**
49    * The locale of the string.
50    */

51   private Locale JavaDoc locale;
52
53   /**
54    * The strength of the collator for this string (as defined in
55    * java.text.Collator).
56    */

57   private int strength;
58   
59   /**
60    * The decomposition mode of the collator for this string type (as defined in
61    * java.text.Collator).
62    */

63   private int decomposition;
64
65   /**
66    * The Collator object for this type, created when we first compare objects.
67    */

68   private transient Collator JavaDoc collator;
69
70   /**
71    * Constructs a type with the given sql_type value, the maximum size,
72    * and the locale of the string. Note that the 'sql_type' MUST be a string
73    * SQL type.
74    * <p>
75    * Note that a string type may be constructed with a NULL locale which
76    * means strings are compared lexicographically.
77    */

78   public TStringType(int sql_type, int max_size, Locale JavaDoc locale,
79                      int strength, int decomposition) {
80     super(sql_type);
81     this.max_size = max_size;
82     this.strength = strength;
83     this.decomposition = decomposition;
84     this.locale = locale;
85   }
86
87   /**
88    * Constructs a type with the given sql_type value, the maximum size,
89    * and the locale of the string. Note that the 'sql_type' MUST be a string
90    * SQL type.
91    * <p>
92    * Note that a string type may be constructed with a NULL locale which
93    * means strings are compared lexicographically. The string locale is
94    * formated as [2 char language][2 char country][rest is variant]. For
95    * example, US english would be 'enUS', French would be 'fr' and Germany
96    * would be 'deDE'.
97    */

98   public TStringType(int sql_type, int max_size, String JavaDoc locale_str,
99                      int strength, int decomposition) {
100     super(sql_type);
101     this.max_size = max_size;
102     this.strength = strength;
103     this.decomposition = decomposition;
104
105     if (locale_str != null && locale_str.length() >= 2) {
106       String JavaDoc language = locale_str.substring(0, 2);
107       String JavaDoc country = "";
108       String JavaDoc variant = "";
109       if (locale_str.length() > 2) {
110         country = locale_str.substring(2, 4);
111         if (locale_str.length() > 4) {
112           variant = locale_str.substring(4);
113         }
114       }
115       locale = new Locale JavaDoc(language, country, variant);
116     }
117
118   }
119
120   /**
121    * Constructor without strength and decomposition that sets to default
122    * levels.
123    */

124   public TStringType(int sql_type, int max_size, String JavaDoc locale_str) {
125     this(sql_type, max_size, locale_str, -1, -1);
126   }
127   
128
129
130
131   /**
132    * Returns the maximum size of the string (-1 is don't care).
133    */

134   public int getMaximumSize() {
135     return max_size;
136   }
137
138   /**
139    * Returns the strength of this string type as defined in java.text.Collator.
140    */

141   public int getStrength() {
142     return strength;
143   }
144   
145   /**
146    * Returns the decomposition of this string type as defined in
147    * java.text.Collator.
148    */

149   public int getDecomposition() {
150     return decomposition;
151   }
152   
153   /**
154    * Returns the locale of the string.
155    */

156   public Locale JavaDoc getLocale() {
157     return locale;
158   }
159
160   /**
161    * Returns the locale information as a formatted string.
162    * <p>
163    * Note that a string type may be constructed with a NULL locale which
164    * means strings are compared lexicographically. The string locale is
165    * formated as [2 char language][2 char country][rest is variant]. For
166    * example, US english would be 'enUS', French would be 'fr' and Germany
167    * would be 'deDE'.
168    */

169   public String JavaDoc getLocaleString() {
170     if (locale == null) {
171       return "";
172     }
173     else {
174       StringBuffer JavaDoc locale_str = new StringBuffer JavaDoc();
175       locale_str.append(locale.getLanguage());
176       locale_str.append(locale.getCountry());
177       locale_str.append(locale.getVariant());
178       return new String JavaDoc(locale_str);
179     }
180   }
181
182   /**
183    * An implementation of a lexicographical compareTo operation on a
184    * StringAccessor object. This uses the Reader object to compare the strings
185    * over a stream if the size is such that it is more efficient to do so.
186    */

187   private int lexicographicalOrder(StringAccessor str1, StringAccessor str2) {
188     // If both strings are small use the 'toString' method to compare the
189
// strings. This saves the overhead of having to store very large string
190
// objects in memory for all comparisons.
191
long str1_size = str1.length();
192     long str2_size = str2.length();
193     if (str1_size < 32 * 1024 &&
194         str2_size < 32 * 1024) {
195       return str1.toString().compareTo(str2.toString());
196     }
197
198     // The minimum size
199
long size = Math.min(str1_size, str2_size);
200     Reader JavaDoc r1 = str1.getReader();
201     Reader JavaDoc r2 = str2.getReader();
202     try {
203       try {
204         while (size > 0) {
205           int c1 = r1.read();
206           int c2 = r2.read();
207           if (c1 != c2) {
208             return c1 - c2;
209           }
210           --size;
211         }
212         // They compare equally up to the limit, so now compare sizes,
213
if (str1_size > str2_size) {
214           // If str1 is larger
215
return 1;
216         }
217         else if (str1_size < str2_size) {
218           // If str1 is smaller
219
return -1;
220         }
221         // Must be equal
222
return 0;
223       }
224       finally {
225         r1.close();
226         r2.close();
227       }
228     }
229     catch (IOException JavaDoc e) {
230       throw new RuntimeException JavaDoc("IO Error: " + e.getMessage());
231     }
232
233   }
234   
235   /**
236    * Returns the java.text.Collator object for this string type. This collator
237    * is used to compare strings of this locale.
238    * <p>
239    * This method is synchronized because a side effect of this method is to
240    * store the collator object instance in a local variable.
241    */

242   private synchronized Collator JavaDoc getCollator() {
243     if (collator != null) {
244       return collator;
245     }
246     else {
247       // NOTE: Even if we are creating a lot of these objects, it shouldn't
248
// be too bad on memory usage because Collator.getInstance caches
249
// collation information behind the scenes.
250
collator = Collator.getInstance(locale);
251       int strength = getStrength();
252       int decomposition = getStrength();
253       if (strength >= 0) {
254         collator.setStrength(strength);
255       }
256       if (decomposition >= 0) {
257         collator.setDecomposition(decomposition);
258       }
259       return collator;
260     }
261   }
262   
263   // ---------- Overwritten from TType ----------
264

265   /**
266    * For strings, the locale must be the same for the types to be comparable.
267    * If the locale is not the same then they are not comparable. Note that
268    * strings with a locale of null can be compared with any other locale. So
269    * this will only return false if both types have different (but defined)
270    * locales.
271    */

272   public boolean comparableTypes(TType type) {
273     // Are we comparing with another string type?
274
if (type instanceof TStringType) {
275       TStringType s_type = (TStringType) type;
276       // If either locale is null return true
277
if (getLocale() == null || s_type.getLocale() == null) {
278         return true;
279       }
280       // If the locales are the same return true
281
return getLocale().equals(s_type.getLocale());
282     }
283     return false;
284   }
285
286   public int compareObs(Object JavaDoc ob1, Object JavaDoc ob2) {
287     if (ob1 == ob2) {
288       return 0;
289     }
290     // If lexicographical ordering,
291
if (locale == null) {
292       return lexicographicalOrder((StringAccessor) ob1, (StringAccessor) ob2);
293 // return ob1.toString().compareTo(ob2.toString());
294
}
295     else {
296       return getCollator().compare(ob1.toString(), ob2.toString());
297     }
298   }
299
300   public int calculateApproximateMemoryUse(Object JavaDoc ob) {
301     if (ob != null) {
302       return (((StringAccessor) ob).length() * 2) + 24;
303     }
304     else {
305       return 32;
306     }
307   }
308
309   public Class JavaDoc javaClass() {
310     return StringAccessor.class;
311   }
312
313 }
314
Popular Tags