1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ******************************************************************************* 5 * Copyright (C) 2012-2013, International Business Machines Corporation and * 6 * others. All Rights Reserved. * 7 ******************************************************************************* 8 */ 9 package com.ibm.icu.dev.tool.currency; 10 11 import java.io.File; 12 import java.io.FileInputStream; 13 import java.io.IOException; 14 import java.util.Collection; 15 import java.util.LinkedList; 16 17 import javax.xml.parsers.ParserConfigurationException; 18 import javax.xml.parsers.SAXParser; 19 import javax.xml.parsers.SAXParserFactory; 20 21 import org.xml.sax.Attributes; 22 import org.xml.sax.SAXException; 23 import org.xml.sax.helpers.DefaultHandler; 24 25 import com.ibm.icu.dev.tool.currency.CurrencyDataEntry.Builder; 26 27 /** 28 * Parser for ISO 4217 data file in XML format distributed by SIX Interbank Clearing 29 * (The ISO 4217 maintenance agency). 30 */ 31 public class CurrencyDataParser { 32 parse(File dataFile, boolean historic)33 public static Collection<CurrencyDataEntry> parse(File dataFile, boolean historic) throws IOException { 34 Collection<CurrencyDataEntry> result = null; 35 try { 36 SAXParserFactory factory = SAXParserFactory.newInstance(); 37 SAXParser parser; 38 parser = factory.newSAXParser(); 39 Handler handler = new Handler(historic); 40 parser.parse(new FileInputStream(dataFile), handler); 41 result = handler.getParsedISOCurrencies(); 42 } catch (SAXException e) { 43 throw new RuntimeException(e); 44 } catch (ParserConfigurationException e) { 45 throw new RuntimeException(e); 46 } 47 return result; 48 } 49 50 private static class Handler extends DefaultHandler { 51 private enum ElementType { 52 ENTITY("CtryNm"), 53 CURRENCY("CcyNm"), 54 ALPHABETIC_CODE("Ccy"), 55 NUMERIC_CODE("CcyNbr"), 56 MINOR_UNIT("CcyMnrUnts"), 57 WITHDRAWAL_DATE("WthdrwlDt"), 58 REMARK("Remark"), // obsolete 59 OTHER("Other"); // place holder 60 61 private String elemName; 62 ElementType(String elemName)63 ElementType(String elemName) { 64 this.elemName = elemName; 65 } 66 forName(String name)67 public static ElementType forName(String name) { 68 for (ElementType type : values()) { 69 if (type.elemName.equals(name)) { 70 return type; 71 } 72 } 73 return OTHER; 74 } 75 }; 76 77 Collection<CurrencyDataEntry> isoCurrencies = new LinkedList<CurrencyDataEntry>(); 78 ElementType elem = ElementType.OTHER; 79 Builder currBld = new Builder(); 80 81 private final boolean historic; 82 private final String currElemName; 83 Handler(boolean historic)84 public Handler(boolean historic) { 85 this.historic = historic; 86 currElemName = historic ? "HstrcCcyNtry" : "CcyNtry"; 87 } 88 getParsedISOCurrencies()89 public Collection<CurrencyDataEntry> getParsedISOCurrencies() { 90 return isoCurrencies; 91 } 92 startElement(String uri, String localName, String qName, Attributes attributes)93 public void startElement(String uri, String localName, String qName, Attributes attributes) { 94 if (qName.equals(currElemName)) { 95 currBld.reset(); 96 elem = ElementType.OTHER; 97 } else { 98 try { 99 elem = ElementType.forName(qName); 100 } catch (IllegalArgumentException e) { 101 elem = ElementType.OTHER; 102 } 103 } 104 } 105 endElement(String uri, String localName, String qName)106 public void endElement(String uri, String localName, String qName) { 107 // emit a currency data 108 if (qName.equals(currElemName)) { 109 if (historic) { 110 currBld.setHistoric(); 111 } 112 isoCurrencies.add(currBld.build()); 113 currBld.reset(); 114 } 115 elem = ElementType.OTHER; 116 } 117 characters(char[] ch, int start, int length)118 public void characters(char[] ch, int start, int length) { 119 switch (elem) { 120 case ENTITY: 121 currBld.setEntity(new String(ch, start, length).trim()); 122 break; 123 case CURRENCY: 124 currBld.setCurrency(new String(ch, start, length).trim()); 125 break; 126 case ALPHABETIC_CODE: 127 currBld.setAlphabeticCode(new String(ch, start, length).trim()); 128 break; 129 case NUMERIC_CODE: 130 currBld.setNumericCode(new String(ch, start, length).trim()); 131 break; 132 case MINOR_UNIT: 133 currBld.setMinorUnit(new String(ch, start, length).trim()); 134 break; 135 case WITHDRAWAL_DATE: 136 currBld.setWithdrawalDate(new String(ch, start, length).trim()); 137 break; 138 case REMARK: 139 currBld.setRemark(new String(ch, start, length).trim()); 140 break; 141 default: 142 // NOOP 143 break; 144 } 145 } 146 } 147 } 148