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