Home | History | Annotate | Download | only in impl
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html#License
      3 /*
      4 ******************************************************************************
      5 * Copyright (C) 2007-2010, International Business Machines Corporation and   *
      6 * others. All Rights Reserved.                                               *
      7 ******************************************************************************
      8 */
      9 
     10 package com.ibm.icu.impl.duration.impl;
     11 
     12 import java.io.IOException;
     13 import java.io.Reader;
     14 import java.util.ArrayList;
     15 import java.util.List;
     16 
     17 import com.ibm.icu.lang.UCharacter;
     18 
     19 public class XMLRecordReader implements RecordReader {
     20     private Reader r;
     21 
     22     private List<String> nameStack;
     23 
     24     private boolean atTag;
     25 
     26     private String tag; // cache
     27 
     28     public XMLRecordReader(Reader r) {
     29         this.r = r;
     30         this.nameStack = new ArrayList<String>();
     31 
     32         // skip XML prologue
     33         if (getTag().startsWith("?xml")) {
     34             advance();
     35         }
     36 
     37         // skip FIRST comment
     38         if (getTag().startsWith("!--")) {
     39             advance();
     40         }
     41     }
     42 
     43     @Override
     44     public boolean open(String title) {
     45         if (getTag().equals(title)) {
     46             nameStack.add(title);
     47             advance();
     48             return true;
     49         }
     50         return false;
     51     }
     52 
     53     @Override
     54     public boolean close() {
     55         int ix = nameStack.size() - 1;
     56         String name = nameStack.get(ix);
     57         if (getTag().equals("/" + name)) {
     58             nameStack.remove(ix);
     59             advance();
     60             return true;
     61         }
     62         return false;
     63     }
     64 
     65     @Override
     66     public boolean bool(String name) {
     67         String s = string(name);
     68         if (s != null) {
     69             return "true".equals(s);
     70         }
     71         return false;
     72     }
     73 
     74     @Override
     75     public boolean[] boolArray(String name) {
     76         String[] sa = stringArray(name);
     77         if (sa != null) {
     78             boolean[] result = new boolean[sa.length];
     79             for (int i = 0; i < sa.length; ++i) {
     80                 result[i] = "true".equals(sa[i]);
     81             }
     82             return result;
     83         }
     84         return null;
     85     }
     86 
     87     @Override
     88     public char character(String name) {
     89         String s = string(name);
     90         if (s != null) {
     91             return s.charAt(0);
     92         }
     93         return '\uffff';
     94     }
     95 
     96     @Override
     97     public char[] characterArray(String name) {
     98         String[] sa = stringArray(name);
     99         if (sa != null) {
    100             char[] result = new char[sa.length];
    101             for (int i = 0; i < sa.length; ++i) {
    102                 result[i] = sa[i].charAt(0);
    103             }
    104             return result;
    105         }
    106         return null;
    107     }
    108 
    109     @Override
    110     public byte namedIndex(String name, String[] names) {
    111         String sa = string(name);
    112         if (sa != null) {
    113             for (int i = 0; i < names.length; ++i) {
    114                 if (sa.equals(names[i])) {
    115                     return (byte) i;
    116                 }
    117             }
    118         }
    119         return (byte) -1;
    120     }
    121 
    122     @Override
    123     public byte[] namedIndexArray(String name, String[] names) {
    124         String[] sa = stringArray(name);
    125         if (sa != null) {
    126             byte[] result = new byte[sa.length];
    127             loop: for (int i = 0; i < sa.length; ++i) {
    128                 String s = sa[i];
    129                 for (int j = 0; j < names.length; ++j) {
    130                     if (names[j].equals(s)) {
    131                         result[i] = (byte) j;
    132                         continue loop;
    133                     }
    134                 }
    135                 result[i] = (byte) -1;
    136             }
    137             return result;
    138         }
    139         return null;
    140     }
    141 
    142     @Override
    143     public String string(String name) {
    144         if (match(name)) {
    145             String result = readData();
    146             if (match("/" + name)) {
    147                 return result;
    148             }
    149         }
    150         return null;
    151     }
    152 
    153     @Override
    154     public String[] stringArray(String name) {
    155         if (match(name + "List")) {
    156             List<String> list = new ArrayList<String>();
    157             String s;
    158             while (null != (s = string(name))) {
    159                 if ("Null".equals(s)) {
    160                     s = null;
    161                 }
    162                 list.add(s);
    163             }
    164             if (match("/" + name + "List")) {
    165                 return list.toArray(new String[list.size()]);
    166             }
    167         }
    168         return null;
    169     }
    170 
    171     @Override
    172     public String[][] stringTable(String name) {
    173         if (match(name + "Table")) {
    174             List<String[]> list = new ArrayList<String[]>();
    175             String[] sa;
    176             while (null != (sa = stringArray(name))) {
    177                 list.add(sa);
    178             }
    179             if (match("/" + name + "Table")) {
    180                 return list.toArray(new String[list.size()][]);
    181             }
    182         }
    183         return null;
    184     }
    185 
    186     private boolean match(String target) {
    187         if (getTag().equals(target)) {
    188             // System.out.println("match '" + target + "'");
    189             advance();
    190             return true;
    191         }
    192         return false;
    193     }
    194 
    195     private String getTag() {
    196         if (tag == null) {
    197             tag = readNextTag();
    198         }
    199         return tag;
    200     }
    201 
    202     private void advance() {
    203         tag = null;
    204     }
    205 
    206     private String readData() {
    207         StringBuilder sb = new StringBuilder();
    208         boolean inWhitespace = false;
    209         // boolean inAmp = false;
    210         while (true) {
    211             int c = readChar();
    212             if (c == -1 || c == '<') {
    213                 atTag = c == '<';
    214                 break;
    215             }
    216             if (c == '&') {
    217                 c = readChar();
    218                 if (c == '#') {
    219                     StringBuilder numBuf = new StringBuilder();
    220                     int radix = 10;
    221                     c = readChar();
    222                     if (c == 'x') {
    223                         radix = 16;
    224                         c = readChar();
    225                     }
    226                     while (c != ';' && c != -1) {
    227                         numBuf.append((char) c);
    228                         c = readChar();
    229                     }
    230                     try {
    231                         int num = Integer.parseInt(numBuf.toString(), radix);
    232                         c = (char) num;
    233                     } catch (NumberFormatException ex) {
    234                         System.err.println("numbuf: " + numBuf.toString()
    235                                 + " radix: " + radix);
    236                         throw ex;
    237                     }
    238                 } else {
    239                     StringBuilder charBuf = new StringBuilder();
    240                     while (c != ';' && c != -1) {
    241                         charBuf.append((char) c);
    242                         c = readChar();
    243                     }
    244                     String charName = charBuf.toString();
    245                     if (charName.equals("lt")) {
    246                         c = '<';
    247                     } else if (charName.equals("gt")) {
    248                         c = '>';
    249                     } else if (charName.equals("quot")) {
    250                         c = '"';
    251                     } else if (charName.equals("apos")) {
    252                         c = '\'';
    253                     } else if (charName.equals("amp")) {
    254                         c = '&';
    255                     } else {
    256                         System.err.println("unrecognized character entity: '"
    257                                 + charName + "'");
    258                         continue;
    259                     }
    260                 }
    261             }
    262 
    263             if (UCharacter.isWhitespace(c)) {
    264                 if (inWhitespace) {
    265                     continue;
    266                 }
    267                 c = ' ';
    268                 inWhitespace = true;
    269             } else {
    270                 inWhitespace = false;
    271             }
    272             sb.append((char) c);
    273         }
    274         //System.err.println("read data: '" + sb.toString() + "'");
    275         return sb.toString();
    276     }
    277 
    278     private String readNextTag() {
    279         int c = '\0';
    280         while (!atTag) {
    281             c = readChar();
    282             if (c == '<' || c == -1) {
    283                 if (c == '<') {
    284                     atTag = true;
    285                 }
    286                 break;
    287             }
    288             if (!UCharacter.isWhitespace(c)) {
    289                 System.err.println("Unexpected non-whitespace character "
    290                         + Integer.toHexString(c));
    291                 break;
    292             }
    293         }
    294 
    295         if (atTag) {
    296             atTag = false;
    297             StringBuilder sb = new StringBuilder();
    298             while (true) {
    299                 c = readChar();
    300                 if (c == '>' || c == -1) {
    301                     break;
    302                 }
    303                 sb.append((char) c);
    304             }
    305             // System.err.println("read tag: '" + sb.toString() + "'");
    306             return sb.toString();
    307         }
    308         return null;
    309     }
    310 
    311     int readChar() {
    312         try {
    313             return r.read();
    314         } catch (IOException e) {
    315             // assume end of input
    316         }
    317         return -1;
    318     }
    319 }
    320