Home | History | Annotate | Download | only in stringprep
      1 /* GENERATED SOURCE. DO NOT MODIFY. */
      2 //  2016 and later: Unicode, Inc. and others.
      3 // License & terms of use: http://www.unicode.org/copyright.html#License
      4 /*
      5  *******************************************************************************
      6  * Copyright (C) 2003-2010, International Business Machines Corporation and    *
      7  * others. All Rights Reserved.                                                *
      8  *******************************************************************************
      9 */
     10 package android.icu.dev.test.stringprep;
     11 
     12 
     13 import java.lang.reflect.InvocationTargetException;
     14 import java.lang.reflect.Method;
     15 
     16 import android.icu.impl.ICUResourceBundle;
     17 import android.icu.lang.UCharacter;
     18 import android.icu.lang.UCharacterDirection;
     19 import android.icu.text.StringPrepParseException;
     20 import android.icu.text.UCharacterIterator;
     21 import android.icu.text.UnicodeSet;
     22 import android.icu.testsharding.MainTestShard;
     23 
     24 /**
     25  * @author ram
     26  *
     27  * To change the template for this generated type comment go to
     28  * Window>Preferences>Java>Code Generation>Code and Comments
     29  */
     30 @MainTestShard
     31 public class NamePrepTransform {
     32 
     33     private static final NamePrepTransform transform = new NamePrepTransform();
     34 
     35     private UnicodeSet labelSeparatorSet;
     36     private UnicodeSet prohibitedSet;
     37     private UnicodeSet unassignedSet;
     38     private MapTransform mapTransform;
     39     public static final int NONE = 0;
     40     public static final int ALLOW_UNASSIGNED = 1;
     41 
     42     private NamePrepTransform(){
     43         // load the resource bundle
     44         ICUResourceBundle bundle = (ICUResourceBundle)ICUResourceBundle.getBundleInstance("android/icu/dev/data/testdata","idna_rules", NamePrepTransform.class.getClassLoader(), true);
     45         String  mapRules      = bundle.getString("MapNoNormalization");
     46         mapRules             += bundle.getString("MapNFKC");
     47         // disable
     48         mapTransform          = new MapTransform("CaseMap", mapRules, 0 /*Transliterator.FORWARD*/);
     49         labelSeparatorSet     = new UnicodeSet(bundle.getString("LabelSeparatorSet"));
     50         prohibitedSet         = new UnicodeSet(bundle.getString("ProhibitedSet"));
     51         unassignedSet         = new UnicodeSet(bundle.getString("UnassignedSet"));
     52     }
     53 
     54     public static final NamePrepTransform getInstance(){
     55         return transform;
     56     }
     57     public static boolean isLabelSeparator(int ch){
     58         return transform.labelSeparatorSet.contains(ch);
     59     }
     60 
     61      /*
     62        1) Map -- For each character in the input, check if it has a mapping
     63           and, if so, replace it with its mapping.
     64 
     65        2) Normalize -- Possibly normalize the result of step 1 using Unicode
     66           normalization.
     67 
     68        3) Prohibit -- Check for any characters that are not allowed in the
     69           output.  If any are found, return an error.
     70 
     71        4) Check bidi -- Possibly check for right-to-left characters, and if
     72           any are found, make sure that the whole string satisfies the
     73           requirements for bidirectional strings.  If the string does not
     74           satisfy the requirements for bidirectional strings, return an
     75           error.
     76           [Unicode3.2] defines several bidirectional categories; each character
     77            has one bidirectional category assigned to it.  For the purposes of
     78            the requirements below, an "RandALCat character" is a character that
     79            has Unicode bidirectional categories "R" or "AL"; an "LCat character"
     80            is a character that has Unicode bidirectional category "L".  Note
     81 
     82 
     83            that there are many characters which fall in neither of the above
     84            definitions; Latin digits (<U+0030> through <U+0039>) are examples of
     85            this because they have bidirectional category "EN".
     86 
     87            In any profile that specifies bidirectional character handling, all
     88            three of the following requirements MUST be met:
     89 
     90            1) The characters in section 5.8 MUST be prohibited.
     91 
     92            2) If a string contains any RandALCat character, the string MUST NOT
     93               contain any LCat character.
     94 
     95            3) If a string contains any RandALCat character, a RandALCat
     96               character MUST be the first character of the string, and a
     97               RandALCat character MUST be the last character of the string.
     98     */
     99 
    100     public boolean isReady() {
    101         return mapTransform.isReady();
    102     }
    103 
    104     public StringBuffer prepare(UCharacterIterator src,
    105                                        int options)
    106                                        throws StringPrepParseException{
    107              return prepare(src.getText(),options);
    108     }
    109 
    110     private String map ( String src, int options)
    111                                 throws StringPrepParseException{
    112         // map
    113         boolean allowUnassigned =  ((options & ALLOW_UNASSIGNED)>0);
    114         // disable test
    115         String caseMapOut = mapTransform.transliterate(src);
    116         UCharacterIterator iter = UCharacterIterator.getInstance(caseMapOut);
    117         int ch;
    118         while((ch=iter.nextCodePoint())!=UCharacterIterator.DONE){
    119             if(transform.unassignedSet.contains(ch)==true && allowUnassigned ==false){
    120                 throw new StringPrepParseException("An unassigned code point was found in the input",
    121                                          StringPrepParseException.UNASSIGNED_ERROR);
    122             }
    123         }
    124         return caseMapOut;
    125     }
    126     public StringBuffer prepare(String src,int options)
    127                                    throws StringPrepParseException{
    128 
    129         int ch;
    130         String mapOut = map(src,options);
    131         UCharacterIterator iter = UCharacterIterator.getInstance(mapOut);
    132 
    133         int direction=UCharacterDirection.CHAR_DIRECTION_COUNT,
    134             firstCharDir=UCharacterDirection.CHAR_DIRECTION_COUNT;
    135         int rtlPos=-1, ltrPos=-1;
    136         boolean rightToLeft=false, leftToRight=false;
    137 
    138         while((ch=iter.nextCodePoint())!= UCharacterIterator.DONE){
    139 
    140 
    141             if(transform.prohibitedSet.contains(ch)==true && ch!=0x0020){
    142                 throw new StringPrepParseException("A prohibited code point was found in the input",
    143                                          StringPrepParseException.PROHIBITED_ERROR,
    144                                          iter.getText(),iter.getIndex());
    145             }
    146 
    147             direction = UCharacter.getDirection(ch);
    148             if(firstCharDir == UCharacterDirection.CHAR_DIRECTION_COUNT){
    149                 firstCharDir = direction;
    150             }
    151             if(direction == UCharacterDirection.LEFT_TO_RIGHT){
    152                 leftToRight = true;
    153                 ltrPos = iter.getIndex()-1;
    154             }
    155             if(direction == UCharacterDirection.RIGHT_TO_LEFT || direction == UCharacterDirection.RIGHT_TO_LEFT_ARABIC){
    156                 rightToLeft = true;
    157                 rtlPos = iter.getIndex()-1;
    158             }
    159         }
    160 
    161         // satisfy 2
    162         if( leftToRight == true && rightToLeft == true){
    163             throw new StringPrepParseException("The input does not conform to the rules for BiDi code points.",
    164                                      StringPrepParseException.CHECK_BIDI_ERROR,iter.getText(),(rtlPos>ltrPos) ? rtlPos : ltrPos);
    165         }
    166 
    167         //satisfy 3
    168         if( rightToLeft == true &&
    169             !((firstCharDir == UCharacterDirection.RIGHT_TO_LEFT || firstCharDir == UCharacterDirection.RIGHT_TO_LEFT_ARABIC) &&
    170             (direction == UCharacterDirection.RIGHT_TO_LEFT || direction == UCharacterDirection.RIGHT_TO_LEFT_ARABIC))
    171            ){
    172             throw new StringPrepParseException("The input does not conform to the rules for BiDi code points.",
    173                                       StringPrepParseException.CHECK_BIDI_ERROR,iter.getText(),(rtlPos>ltrPos) ? rtlPos : ltrPos);
    174         }
    175 
    176         return new StringBuffer(mapOut);
    177 
    178     }
    179 
    180     private static class MapTransform {
    181         private Object translitInstance;
    182         private Method translitMethod;
    183         private boolean isReady;
    184 
    185         MapTransform(String id, String rule, int direction) {
    186             isReady = initialize(id, rule, direction);
    187         }
    188 
    189         boolean initialize(String id, String rule, int direction) {
    190             try {
    191                 Class cls = Class.forName("android.icu.text.Transliterator");
    192                 Method createMethod = cls.getMethod("createFromRules", String.class, String.class, Integer.TYPE);
    193                 translitInstance = createMethod.invoke(null, id, rule, Integer.valueOf(direction));
    194                 translitMethod = cls.getMethod("transliterate", String.class);
    195             } catch (Throwable e) {
    196                 return false;
    197             }
    198             return true;
    199         }
    200 
    201         boolean isReady() {
    202             return isReady;
    203         }
    204 
    205         String transliterate(String text) {
    206             if (!isReady) {
    207                 throw new IllegalStateException("Transliterator is not ready");
    208             }
    209             String result = null;
    210             try {
    211                 result = (String)translitMethod.invoke(translitInstance, text);
    212             } catch (InvocationTargetException ite) {
    213                 throw new RuntimeException(ite);
    214             } catch (IllegalAccessException iae) {
    215                 throw new RuntimeException(iae);
    216             }
    217             return result;
    218         }
    219     }
    220 }
    221