]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/icu/dev/test/util/ICUPropertyFactory.java
icu4jsrc
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / icu / dev / test / util / ICUPropertyFactory.java
1 //##header\r
2 //#if defined(FOUNDATION10) || defined(J2SE13)\r
3 //#else\r
4 /*\r
5  *******************************************************************************\r
6  * Copyright (C) 2002-2009, International Business Machines Corporation and    *\r
7  * others. All Rights Reserved.                                                *\r
8  *******************************************************************************\r
9  */\r
10 package com.ibm.icu.dev.test.util;\r
11 \r
12 import java.util.ArrayList;\r
13 import java.util.Arrays;\r
14 import java.util.Collection;\r
15 import java.util.HashMap;\r
16 import java.util.Iterator;\r
17 import java.util.List;\r
18 import java.util.Locale;\r
19 import java.util.Map;\r
20 import java.util.Set;\r
21 import java.util.TreeSet;\r
22 \r
23 import com.ibm.icu.lang.UCharacter;\r
24 import com.ibm.icu.lang.UProperty;\r
25 import com.ibm.icu.text.Normalizer;\r
26 import com.ibm.icu.text.UTF16;\r
27 import com.ibm.icu.util.VersionInfo;\r
28 \r
29 \r
30 /**\r
31  * Provides a general interface for Unicode Properties, and\r
32  * extracting sets based on those values.\r
33  * @author Davis\r
34  */\r
35 \r
36 public class ICUPropertyFactory extends UnicodeProperty.Factory {\r
37         \r
38     static class ICUProperty extends UnicodeProperty {\r
39             protected int propEnum = Integer.MIN_VALUE;\r
40             \r
41             protected ICUProperty(String propName, int propEnum) {\r
42                 setName(propName);\r
43                 this.propEnum = propEnum;\r
44                 setType(internalGetPropertyType(propEnum));\r
45             }\r
46 \r
47             boolean shownException = false;\r
48             \r
49             public String _getValue(int codePoint) {\r
50                 switch(propEnum) {\r
51                     case UProperty.AGE: String temp = UCharacter.getAge(codePoint).toString();\r
52                         if (temp.equals("0.0.0.0")) return "unassigned";\r
53                         if (temp.endsWith(".0.0")) return temp.substring(0,temp.length()-4);\r
54                         return temp;\r
55                     case UProperty.BIDI_MIRRORING_GLYPH: return UTF16.valueOf(UCharacter.getMirror(codePoint));\r
56                     case UProperty.CASE_FOLDING: return UCharacter.foldCase(UTF16.valueOf(codePoint),true);\r
57                     case UProperty.ISO_COMMENT: return UCharacter.getISOComment(codePoint);\r
58                     case UProperty.LOWERCASE_MAPPING: return UCharacter.toLowerCase(Locale.ENGLISH,UTF16.valueOf(codePoint));\r
59                     case UProperty.NAME: return UCharacter.getName(codePoint);\r
60                     case UProperty.SIMPLE_CASE_FOLDING: return UTF16.valueOf(UCharacter.foldCase(codePoint,true));\r
61                     case UProperty.SIMPLE_LOWERCASE_MAPPING: return UTF16.valueOf(UCharacter.toLowerCase(codePoint));\r
62                     case UProperty.SIMPLE_TITLECASE_MAPPING: return UTF16.valueOf(UCharacter.toTitleCase(codePoint));\r
63                     case UProperty.SIMPLE_UPPERCASE_MAPPING: return UTF16.valueOf(UCharacter.toUpperCase(codePoint));\r
64                     case UProperty.TITLECASE_MAPPING: return UCharacter.toTitleCase(Locale.ENGLISH,UTF16.valueOf(codePoint),null);\r
65                     case UProperty.UNICODE_1_NAME: return UCharacter.getName1_0(codePoint);\r
66                     case UProperty.UPPERCASE_MAPPING: return UCharacter.toUpperCase(Locale.ENGLISH,UTF16.valueOf(codePoint));\r
67                     case NFC: return Normalizer.normalize(codePoint, Normalizer.NFC);\r
68                     case NFD: return Normalizer.normalize(codePoint, Normalizer.NFD);\r
69                     case NFKC: return Normalizer.normalize(codePoint, Normalizer.NFKC);\r
70                     case NFKD: return Normalizer.normalize(codePoint, Normalizer.NFKD);\r
71                     case isNFC: return String.valueOf(Normalizer.normalize(codePoint, Normalizer.NFC).equals(UTF16.valueOf(codePoint)));\r
72                     case isNFD: return String.valueOf(Normalizer.normalize(codePoint, Normalizer.NFD).equals(UTF16.valueOf(codePoint)));\r
73                     case isNFKC: return String.valueOf(Normalizer.normalize(codePoint, Normalizer.NFKC).equals(UTF16.valueOf(codePoint)));\r
74                     case isNFKD: return String.valueOf(Normalizer.normalize(codePoint, Normalizer.NFKD).equals(UTF16.valueOf(codePoint)));\r
75                     case isLowercase: return String.valueOf(UCharacter.toLowerCase(Locale.ENGLISH,UTF16.valueOf(codePoint)).equals(UTF16.valueOf(codePoint)));\r
76                     case isUppercase: return String.valueOf(UCharacter.toUpperCase(Locale.ENGLISH,UTF16.valueOf(codePoint)).equals(UTF16.valueOf(codePoint)));\r
77                     case isTitlecase: return String.valueOf(UCharacter.toTitleCase(Locale.ENGLISH,UTF16.valueOf(codePoint),null).equals(UTF16.valueOf(codePoint)));\r
78                     case isCasefolded: return String.valueOf(UCharacter.foldCase(UTF16.valueOf(codePoint),true).equals(UTF16.valueOf(codePoint)));\r
79                     case isCased: return String.valueOf(UCharacter.toLowerCase(Locale.ENGLISH,UTF16.valueOf(codePoint)).equals(UTF16.valueOf(codePoint)));\r
80                 }\r
81                 if (propEnum < UProperty.INT_LIMIT) {\r
82                     int enumValue = -1;\r
83                     String value = null;\r
84                     try {\r
85                         enumValue = UCharacter.getIntPropertyValue(codePoint, propEnum);\r
86                         if (enumValue >= 0) value = fixedGetPropertyValueName(propEnum,enumValue, UProperty.NameChoice.LONG);\r
87                     } catch (IllegalArgumentException e) {\r
88                         if (!shownException) {\r
89                             System.out.println("Fail: " + getName() + ", " + Integer.toHexString(codePoint));\r
90                             shownException = true;\r
91                         }\r
92                     }\r
93                     return value != null ? value : String.valueOf(enumValue);\r
94                 } else if (propEnum < UProperty.DOUBLE_LIMIT) {\r
95                     double num = UCharacter.getUnicodeNumericValue(codePoint);\r
96                     if (num == UCharacter.NO_NUMERIC_VALUE) return null;\r
97                     return Double.toString(num);\r
98                     // TODO: Fix HACK -- API deficient\r
99                 }\r
100                 return null;\r
101             }\r
102 \r
103             /**\r
104              * @param valueAlias null if unused.\r
105              * @param valueEnum -1 if unused\r
106              * @param nameChoice\r
107              * @return\r
108              */\r
109             private String getFixedValueAlias(String valueAlias, int valueEnum, int nameChoice) {\r
110                 if (propEnum >= UProperty.STRING_START) {\r
111                     if (nameChoice != UProperty.NameChoice.LONG) return null;\r
112                     return "<string>";\r
113                 } else if (propEnum >= UProperty.DOUBLE_START) {\r
114                     if (nameChoice != UProperty.NameChoice.LONG) return null;\r
115                     return "<number>";\r
116                 }\r
117                 if (valueAlias != null && !valueAlias.equals("<integer>")) {\r
118                     valueEnum = fixedGetPropertyValueEnum(propEnum,valueAlias);\r
119                 }\r
120                 // because these are defined badly, there may be no normal (long) name.\r
121                 // if there is \r
122                 String result = fixedGetPropertyValueName(propEnum, valueEnum, nameChoice);\r
123                 if (result != null) return result;\r
124                 // HACK try other namechoice\r
125                 if (nameChoice == UProperty.NameChoice.LONG) {\r
126                     result = fixedGetPropertyValueName(propEnum,valueEnum, UProperty.NameChoice.SHORT);\r
127                     if (result != null) return result;\r
128                     if (propEnum == UProperty.CANONICAL_COMBINING_CLASS) return null;\r
129                     return "<integer>";\r
130                }\r
131                return null;\r
132             }\r
133 \r
134             private static int fixedGetPropertyValueEnum(int propEnum, String valueAlias) {\r
135                 try {\r
136                     return UCharacter.getPropertyValueEnum(propEnum, valueAlias);\r
137                 } catch (Exception e) {\r
138                     return Integer.parseInt(valueAlias);\r
139                 }\r
140             }\r
141     \r
142             static Map fixSkeleton = new HashMap();\r
143             private static String fixedGetPropertyValueName(int propEnum, int valueEnum, int nameChoice) {\r
144                 \r
145                 try {\r
146                     String value = UCharacter.getPropertyValueName(propEnum,valueEnum,nameChoice);\r
147                     String newValue = (String) fixSkeleton.get(value);\r
148                     if (newValue == null) {\r
149                         newValue = value;\r
150                         if (propEnum == UProperty.JOINING_GROUP) {\r
151                             newValue = newValue.toLowerCase(Locale.ENGLISH);\r
152                         } \r
153                         newValue = regularize(newValue, true);\r
154                         fixSkeleton.put(value, newValue);\r
155                     }\r
156                     return newValue;\r
157                 } catch (Exception e) {\r
158                     return null;\r
159                 }\r
160             }\r
161 \r
162             public List _getNameAliases(List result) {\r
163                 if (result == null) result = new ArrayList();\r
164                 String alias = String_Extras.get(propEnum);\r
165                 if (alias == null) alias = Binary_Extras.get(propEnum);\r
166                 if (alias != null) {\r
167                     addUnique(alias, result);\r
168                 } else {\r
169                     addUnique(getFixedPropertyName(propEnum, UProperty.NameChoice.SHORT), result);\r
170                     addUnique(getFixedPropertyName(propEnum, UProperty.NameChoice.LONG), result);\r
171                 }\r
172                 return result;\r
173             }\r
174             \r
175             public String getFixedPropertyName(int propName, int nameChoice) {\r
176                 try {\r
177                     return UCharacter.getPropertyName(propEnum, nameChoice);\r
178                 } catch (IllegalArgumentException e) {\r
179                     return null;\r
180                 }\r
181             }\r
182 \r
183             private Map cccHack = new HashMap();\r
184             boolean needCccHack = true;\r
185             \r
186             public List _getAvailableValues(List result) {\r
187                 if (result == null) result = new ArrayList();\r
188                 if (propEnum == UProperty.AGE) {\r
189                     addAllUnique(getAges(),\r
190                         result);\r
191                     return result;\r
192                 }\r
193                 if (propEnum < UProperty.INT_LIMIT) {\r
194                     if (Binary_Extras.isInRange(propEnum)) {\r
195                         propEnum = UProperty.BINARY_START; // HACK\r
196                     }\r
197                     int start = UCharacter.getIntPropertyMinValue(propEnum);\r
198                     int end = UCharacter.getIntPropertyMaxValue(propEnum);\r
199                     for (int i = start; i <= end; ++i) {\r
200                         String alias = getFixedValueAlias(null, i, UProperty.NameChoice.LONG);\r
201                         String alias2 = getFixedValueAlias(null, i, UProperty.NameChoice.SHORT);\r
202                         if (alias == null) {\r
203                             alias = alias2;\r
204                             if (alias == null && propEnum == UProperty.CANONICAL_COMBINING_CLASS) {\r
205                                 alias = String.valueOf(i);\r
206                             }\r
207                         }\r
208                         if (needCccHack && propEnum == UProperty.CANONICAL_COMBINING_CLASS) { // HACK\r
209                             cccHack.put(alias, String.valueOf(i));\r
210                         }\r
211                         //System.out.println(propertyAlias + "\t" + i + ":\t" + alias);\r
212                         addUnique(alias, result);\r
213                     }\r
214                     needCccHack = false;\r
215                 } else {\r
216                     String alias = getFixedValueAlias(null, -1,UProperty.NameChoice.LONG);\r
217                     addUnique(alias, result);\r
218                 }\r
219                 return result;\r
220             }\r
221 \r
222             static String[] AGES = null;\r
223             private String[] getAges() {\r
224                 if (AGES == null) {\r
225                   Set ages = new TreeSet();\r
226                   for (int i = 0; i < 0x10FFFF; ++i) {\r
227                     VersionInfo age = UCharacter.getAge(i);\r
228                     ages.add(age.toString());\r
229                   }\r
230                   AGES = (String[]) ages.toArray(new String[ages.size()]);\r
231                 }\r
232                 return AGES;\r
233             }\r
234 \r
235             public List _getValueAliases(String valueAlias, List result) {\r
236                 if (result == null) result = new ArrayList();\r
237                 if (propEnum == UProperty.AGE) {\r
238                     addUnique(valueAlias, result);\r
239                     return result;\r
240                 }\r
241                 if (propEnum == UProperty.CANONICAL_COMBINING_CLASS) {\r
242                     addUnique(cccHack.get(valueAlias), result); // add number\r
243                 }\r
244                 addUnique(getFixedValueAlias(valueAlias, -1, UProperty.NameChoice.SHORT), result);\r
245                 addUnique(getFixedValueAlias(valueAlias, -1, UProperty.NameChoice.LONG), result);\r
246                 return result;\r
247             }\r
248 \r
249 \r
250             /* (non-Javadoc)\r
251              * @see com.ibm.icu.dev.test.util.UnicodePropertySource#getPropertyType()\r
252              */\r
253             private int internalGetPropertyType(int prop) {\r
254                 switch(prop) {\r
255                     case UProperty.AGE: \r
256                     case UProperty.BLOCK: \r
257                     case UProperty.SCRIPT: \r
258                         return UnicodeProperty.CATALOG;\r
259                     case UProperty.ISO_COMMENT:\r
260                     case UProperty.NAME:\r
261                     case UProperty.UNICODE_1_NAME: \r
262                         return UnicodeProperty.MISC;\r
263                     case UProperty.BIDI_MIRRORING_GLYPH:\r
264                     case UProperty.CASE_FOLDING:\r
265                     case UProperty.LOWERCASE_MAPPING:\r
266                     case UProperty.SIMPLE_CASE_FOLDING: \r
267                     case UProperty.SIMPLE_LOWERCASE_MAPPING:\r
268                     case UProperty.SIMPLE_TITLECASE_MAPPING: \r
269                     case UProperty.SIMPLE_UPPERCASE_MAPPING:\r
270                     case UProperty.TITLECASE_MAPPING: \r
271                     case UProperty.UPPERCASE_MAPPING: \r
272                         return UnicodeProperty.EXTENDED_STRING;\r
273                 }\r
274                 if (prop < UProperty.BINARY_START) return UnicodeProperty.UNKNOWN;\r
275                 if (prop < UProperty.BINARY_LIMIT) return UnicodeProperty.BINARY;\r
276                 if (prop < UProperty.INT_START) return UnicodeProperty.EXTENDED_BINARY;\r
277                 if (prop < UProperty.INT_LIMIT) return UnicodeProperty.ENUMERATED;\r
278                 if (prop < UProperty.DOUBLE_START) return UnicodeProperty.EXTENDED_ENUMERATED;\r
279                 if (prop < UProperty.DOUBLE_LIMIT) return UnicodeProperty.NUMERIC;\r
280                 if (prop < UProperty.STRING_START) return UnicodeProperty.EXTENDED_NUMERIC;\r
281                 if (prop < UProperty.STRING_LIMIT) return UnicodeProperty.STRING;\r
282                 return UnicodeProperty.EXTENDED_STRING;\r
283             }\r
284 \r
285             /* (non-Javadoc)\r
286              * @see com.ibm.icu.dev.test.util.UnicodeProperty#getVersion()\r
287              */\r
288             public String _getVersion() {\r
289                 return VersionInfo.ICU_VERSION.toString();\r
290             }\r
291         }\r
292 \r
293         /*{\r
294             matchIterator = new UnicodeSetIterator(\r
295                 new UnicodeSet("[^[:Cn:]-[:Default_Ignorable_Code_Point:]]"));\r
296         }*/\r
297 \r
298 \r
299         \r
300         /*\r
301          * Other Missing Functions:\r
302             Expands_On_NFC\r
303             Expands_On_NFD\r
304             Expands_On_NFKC\r
305             Expands_On_NFKD\r
306             Composition_Exclusion\r
307             Decomposition_Mapping\r
308             FC_NFKC_Closure\r
309             ISO_Comment\r
310             NFC_Quick_Check\r
311             NFD_Quick_Check\r
312             NFKC_Quick_Check\r
313             NFKD_Quick_Check\r
314             Special_Case_Condition\r
315             Unicode_Radical_Stroke\r
316          */\r
317         \r
318          static final Names Binary_Extras = new Names(UProperty.BINARY_LIMIT,\r
319             new String[] {\r
320             "isNFC", "isNFD", "isNFKC", "isNFKD",\r
321             "isLowercase", "isUppercase", "isTitlecase", "isCasefolded", "isCased",\r
322         });\r
323 \r
324         static final Names String_Extras = new Names(UProperty.STRING_LIMIT,\r
325             new String[] {\r
326             "toNFC", "toNFD", "toNFKC", "toNKFD",\r
327         });\r
328 \r
329         static final int\r
330             isNFC = UProperty.BINARY_LIMIT,\r
331             isNFD = UProperty.BINARY_LIMIT+1,\r
332             isNFKC = UProperty.BINARY_LIMIT+2,\r
333             isNFKD = UProperty.BINARY_LIMIT+3,\r
334             isLowercase = UProperty.BINARY_LIMIT+4,\r
335             isUppercase = UProperty.BINARY_LIMIT+5,\r
336             isTitlecase = UProperty.BINARY_LIMIT+6,\r
337             isCasefolded = UProperty.BINARY_LIMIT+7,\r
338             isCased = UProperty.BINARY_LIMIT+8,\r
339 \r
340             NFC  = UProperty.STRING_LIMIT,\r
341             NFD  = UProperty.STRING_LIMIT+1,\r
342             NFKC = UProperty.STRING_LIMIT+2,\r
343             NFKD = UProperty.STRING_LIMIT+3\r
344             ;\r
345         \r
346         private ICUPropertyFactory() {\r
347             Collection c = getInternalAvailablePropertyAliases(new ArrayList());\r
348             Iterator it = c.iterator();\r
349             while (it.hasNext()) {\r
350                 add(getInternalProperty((String)it.next()));\r
351             }\r
352         }\r
353         \r
354         private static ICUPropertyFactory singleton = null;\r
355         \r
356         public static synchronized ICUPropertyFactory make() {\r
357             if (singleton != null) return singleton;\r
358             singleton = new ICUPropertyFactory();\r
359             return singleton;\r
360         }\r
361         \r
362         public List getInternalAvailablePropertyAliases(List result) {\r
363             int[][] ranges = {\r
364                 {UProperty.BINARY_START,    UProperty.BINARY_LIMIT},\r
365                 {UProperty.INT_START,       UProperty.INT_LIMIT},\r
366                 {UProperty.DOUBLE_START,    UProperty.DOUBLE_LIMIT},\r
367                 {UProperty.STRING_START,    UProperty.STRING_LIMIT},\r
368             };\r
369             for (int i = 0; i < ranges.length; ++i) {\r
370                 for (int j = ranges[i][0]; j < ranges[i][1]; ++j) {\r
371                     String alias = UCharacter.getPropertyName(j, UProperty.NameChoice.LONG);\r
372                     UnicodeProperty.addUnique(alias, result);\r
373                     if (!result.contains(alias)) result.add(alias);\r
374                 }\r
375             }\r
376             result.addAll(String_Extras.getNames());\r
377             result.addAll(Binary_Extras.getNames());\r
378             return result;\r
379         }\r
380        \r
381         public UnicodeProperty getInternalProperty(String propertyAlias) {\r
382             int propEnum;\r
383             main:\r
384             {\r
385                 int possibleItem = Binary_Extras.get(propertyAlias);\r
386                 if (possibleItem >= 0) {\r
387                     propEnum = possibleItem;\r
388                     break main;\r
389                 }\r
390                 possibleItem = String_Extras.get(propertyAlias);\r
391                 if (possibleItem >= 0) {\r
392                     propEnum = possibleItem;\r
393                     break main;\r
394                 }\r
395                 propEnum = UCharacter.getPropertyEnum(propertyAlias);\r
396             }\r
397             return new ICUProperty(propertyAlias, propEnum);\r
398         }\r
399  \r
400         /* (non-Javadoc)\r
401          * @see com.ibm.icu.dev.test.util.UnicodePropertySource#getProperty(java.lang.String)\r
402          */\r
403     // TODO file bug on getPropertyValueName for Canonical_Combining_Class  \r
404     \r
405     public static class Names {\r
406         private String[] names;\r
407         private int base;\r
408         public Names(int base, String[] names) {\r
409             this.base = base;\r
410             this.names = names;\r
411         }\r
412         public int get(String name) {\r
413             for (int i = 0; i < names.length; ++i) {\r
414                 if (name.equalsIgnoreCase(names[i])) return base + i;\r
415             }\r
416             return -1;\r
417         }\r
418         public String get(int number) {\r
419             number -= base;\r
420             if (number < 0 || names.length <= number) return null;\r
421             return names[number];\r
422         }\r
423         public boolean isInRange(int number) {\r
424             number -= base;\r
425             return (0 <= number && number < names.length);\r
426         }\r
427         public List getNames() {\r
428             return Arrays.asList(names);\r
429         }\r
430     }\r
431 }\r
432 //#endif\r