| // © 2016 and later: Unicode, Inc. and others. |
| // License & terms of use: http://www.unicode.org/copyright.html |
| /* |
| ****************************************************************************** |
| * Copyright (C) 2007-2010, International Business Machines Corporation and * |
| * others. All Rights Reserved. * |
| ****************************************************************************** |
| */ |
| |
| package com.ibm.icu.impl.duration.impl; |
| |
| import java.io.IOException; |
| import java.io.Writer; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import com.ibm.icu.lang.UCharacter; |
| |
| public class XMLRecordWriter implements RecordWriter { |
| private Writer w; |
| private List<String> nameStack; |
| |
| public XMLRecordWriter(Writer w) { |
| this.w = w; |
| this.nameStack = new ArrayList<String>(); |
| } |
| |
| @Override |
| public boolean open(String title) { |
| newline(); |
| writeString("<" + title + ">"); |
| nameStack.add(title); |
| return true; |
| } |
| |
| @Override |
| public boolean close() { |
| int ix = nameStack.size() - 1; |
| if (ix >= 0) { |
| String name = nameStack.remove(ix); |
| newline(); |
| writeString("</" + name + ">"); |
| return true; |
| } |
| return false; |
| } |
| |
| public void flush() { |
| try { |
| w.flush(); |
| } catch (IOException e) { |
| } |
| } |
| |
| @Override |
| public void bool(String name, boolean value) { |
| internalString(name, String.valueOf(value)); |
| } |
| |
| @Override |
| public void boolArray(String name, boolean[] values) { |
| if (values != null) { |
| String[] stringValues = new String[values.length]; |
| for (int i = 0; i < values.length; ++i) { |
| stringValues[i] = String.valueOf(values[i]); |
| } |
| stringArray(name, stringValues); |
| } |
| } |
| |
| private static String ctos(char value) { |
| if (value == '<') { |
| return "<"; |
| } |
| if (value == '&') { |
| return "&"; |
| } |
| return String.valueOf(value); |
| } |
| |
| @Override |
| public void character(String name, char value) { |
| if (value != '\uffff') { |
| internalString(name, ctos(value)); |
| } |
| } |
| |
| @Override |
| public void characterArray(String name, char[] values) { |
| if (values != null) { |
| String[] stringValues = new String[values.length]; |
| for (int i = 0; i < values.length; ++i) { |
| char value = values[i]; |
| if (value == '\uffff') { |
| stringValues[i] = NULL_NAME; |
| } else { |
| stringValues[i] = ctos(value); |
| } |
| } |
| internalStringArray(name, stringValues); |
| } |
| } |
| |
| @Override |
| public void namedIndex(String name, String[] names, int value) { |
| if (value >= 0) { |
| internalString(name, names[value]); |
| } |
| } |
| |
| @Override |
| public void namedIndexArray(String name, String[] names, byte[] values) { |
| if (values != null) { |
| String[] stringValues = new String[values.length]; |
| for (int i = 0; i < values.length; ++i) { |
| int value = values[i]; |
| if (value < 0) { |
| stringValues[i] = NULL_NAME; |
| } else { |
| stringValues[i] = names[value]; |
| } |
| } |
| internalStringArray(name, stringValues); |
| } |
| } |
| |
| public static String normalize(String str) { |
| if (str == null) { |
| return null; |
| } |
| StringBuilder sb = null; |
| boolean inWhitespace = false; |
| char c = '\0'; |
| boolean special = false; |
| for (int i = 0; i < str.length(); ++i) { |
| c = str.charAt(i); |
| if (UCharacter.isWhitespace(c)) { |
| if (sb == null && (inWhitespace || c != ' ')) { |
| sb = new StringBuilder(str.substring(0, i)); |
| } |
| if (inWhitespace) { |
| continue; |
| } |
| inWhitespace = true; |
| special = false; |
| c = ' '; |
| } else { |
| inWhitespace = false; |
| special = c == '<' || c == '&'; |
| if (special && sb == null) { |
| sb = new StringBuilder(str.substring(0, i)); |
| } |
| } |
| if (sb != null) { |
| if (special) { |
| sb.append(c == '<' ? "<" : "&"); |
| } else { |
| sb.append(c); |
| } |
| } |
| } |
| if (sb != null) { |
| /* |
| * if (c == ' ') { int len = sb.length(); if (len == 0) { return |
| * " "; } if (len > 1 && c == ' ') { sb.deleteCharAt(len - 1); } } |
| */ |
| return sb.toString(); |
| } |
| return str; |
| } |
| |
| private void internalString(String name, String normalizedValue) { |
| if (normalizedValue != null) { |
| newline(); |
| writeString("<" + name + ">" + normalizedValue + "</" + name + ">"); |
| } |
| } |
| |
| private void internalStringArray(String name, String[] normalizedValues) { |
| if (normalizedValues != null) { |
| push(name + "List"); |
| for (int i = 0; i < normalizedValues.length; ++i) { |
| String value = normalizedValues[i]; |
| if (value == null) { |
| value = NULL_NAME; |
| } |
| string(name, value); |
| } |
| pop(); |
| } |
| } |
| |
| @Override |
| public void string(String name, String value) { |
| internalString(name, normalize(value)); |
| } |
| |
| @Override |
| public void stringArray(String name, String[] values) { |
| if (values != null) { |
| push(name + "List"); |
| for (int i = 0; i < values.length; ++i) { |
| String value = normalize(values[i]); |
| if (value == null) { |
| value = NULL_NAME; |
| } |
| internalString(name, value); |
| } |
| pop(); |
| } |
| } |
| |
| @Override |
| public void stringTable(String name, String[][] values) { |
| if (values != null) { |
| push(name + "Table"); |
| for (int i = 0; i < values.length; ++i) { |
| String[] rowValues = values[i]; |
| if (rowValues == null) { |
| internalString(name + "List", NULL_NAME); |
| } else { |
| stringArray(name, rowValues); |
| } |
| } |
| pop(); |
| } |
| } |
| |
| private void push(String name) { |
| newline(); |
| writeString("<" + name + ">"); |
| nameStack.add(name); |
| } |
| |
| private void pop() { |
| int ix = nameStack.size() - 1; |
| String name = nameStack.remove(ix); |
| newline(); |
| writeString("</" + name + ">"); |
| } |
| |
| private void newline() { |
| writeString("\n"); |
| for (int i = 0; i < nameStack.size(); ++i) { |
| writeString(INDENT); |
| } |
| } |
| |
| private void writeString(String str) { |
| if (w != null) { |
| try { |
| w.write(str); |
| } catch (IOException e) { |
| // if there's a problem, record it and stop writing |
| System.err.println(e.getMessage()); |
| w = null; |
| } |
| } |
| } |
| |
| static final String NULL_NAME = "Null"; |
| private static final String INDENT = " "; |
| } |