001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.hadoop.record;
020
021import java.io.IOException;
022import java.util.TreeMap;
023import java.util.ArrayList;
024import java.io.PrintStream;
025import java.io.OutputStream;
026import java.io.UnsupportedEncodingException;
027import java.util.Stack;
028
029import org.apache.hadoop.classification.InterfaceAudience;
030import org.apache.hadoop.classification.InterfaceStability;
031
032/**
033 * XML Serializer.
034 * 
035 * @deprecated Replaced by <a href="https://hadoop.apache.org/avro/">Avro</a>.
036 */
037@Deprecated
038@InterfaceAudience.Public
039@InterfaceStability.Stable
040public class XmlRecordOutput implements RecordOutput {
041
042  private PrintStream stream;
043    
044  private int indent = 0;
045    
046  private Stack<String> compoundStack;
047    
048  private void putIndent() {
049    StringBuilder sb = new StringBuilder("");
050    for (int idx = 0; idx < indent; idx++) {
051      sb.append("  ");
052    }
053    stream.print(sb.toString());
054  }
055    
056  private void addIndent() {
057    indent++;
058  }
059    
060  private void closeIndent() {
061    indent--;
062  }
063    
064  private void printBeginEnvelope(String tag) {
065    if (!compoundStack.empty()) {
066      String s = compoundStack.peek();
067      if ("struct".equals(s)) {
068        putIndent();
069        stream.print("<member>\n");
070        addIndent();
071        putIndent();
072        stream.print("<name>"+tag+"</name>\n");
073        putIndent();
074        stream.print("<value>");
075      } else if ("vector".equals(s)) {
076        stream.print("<value>");
077      } else if ("map".equals(s)) {
078        stream.print("<value>");
079      }
080    } else {
081      stream.print("<value>");
082    }
083  }
084    
085  private void printEndEnvelope(String tag) {
086    if (!compoundStack.empty()) {
087      String s = compoundStack.peek();
088      if ("struct".equals(s)) {
089        stream.print("</value>\n");
090        closeIndent();
091        putIndent();
092        stream.print("</member>\n");
093      } else if ("vector".equals(s)) {
094        stream.print("</value>\n");
095      } else if ("map".equals(s)) {
096        stream.print("</value>\n");
097      }
098    } else {
099      stream.print("</value>\n");
100    }
101  }
102    
103  private void insideVector(String tag) {
104    printBeginEnvelope(tag);
105    compoundStack.push("vector");
106  }
107    
108  private void outsideVector(String tag) throws IOException {
109    String s = compoundStack.pop();
110    if (!"vector".equals(s)) {
111      throw new IOException("Error serializing vector.");
112    }
113    printEndEnvelope(tag);
114  }
115    
116  private void insideMap(String tag) {
117    printBeginEnvelope(tag);
118    compoundStack.push("map");
119  }
120    
121  private void outsideMap(String tag) throws IOException {
122    String s = compoundStack.pop();
123    if (!"map".equals(s)) {
124      throw new IOException("Error serializing map.");
125    }
126    printEndEnvelope(tag);
127  }
128    
129  private void insideRecord(String tag) {
130    printBeginEnvelope(tag);
131    compoundStack.push("struct");
132  }
133    
134  private void outsideRecord(String tag) throws IOException {
135    String s = compoundStack.pop();
136    if (!"struct".equals(s)) {
137      throw new IOException("Error serializing record.");
138    }
139    printEndEnvelope(tag);
140  }
141    
142  /** Creates a new instance of XmlRecordOutput */
143  public XmlRecordOutput(OutputStream out) {
144    try {
145      stream = new PrintStream(out, true, "UTF-8");
146      compoundStack = new Stack<String>();
147    } catch (UnsupportedEncodingException ex) {
148      throw new RuntimeException(ex);
149    }
150  }
151    
152  public void writeByte(byte b, String tag) throws IOException {
153    printBeginEnvelope(tag);
154    stream.print("<ex:i1>");
155    stream.print(Byte.toString(b));
156    stream.print("</ex:i1>");
157    printEndEnvelope(tag);
158  }
159    
160  public void writeBool(boolean b, String tag) throws IOException {
161    printBeginEnvelope(tag);
162    stream.print("<boolean>");
163    stream.print(b ? "1" : "0");
164    stream.print("</boolean>");
165    printEndEnvelope(tag);
166  }
167    
168  public void writeInt(int i, String tag) throws IOException {
169    printBeginEnvelope(tag);
170    stream.print("<i4>");
171    stream.print(Integer.toString(i));
172    stream.print("</i4>");
173    printEndEnvelope(tag);
174  }
175    
176  public void writeLong(long l, String tag) throws IOException {
177    printBeginEnvelope(tag);
178    stream.print("<ex:i8>");
179    stream.print(Long.toString(l));
180    stream.print("</ex:i8>");
181    printEndEnvelope(tag);
182  }
183    
184  public void writeFloat(float f, String tag) throws IOException {
185    printBeginEnvelope(tag);
186    stream.print("<ex:float>");
187    stream.print(Float.toString(f));
188    stream.print("</ex:float>");
189    printEndEnvelope(tag);
190  }
191    
192  public void writeDouble(double d, String tag) throws IOException {
193    printBeginEnvelope(tag);
194    stream.print("<double>");
195    stream.print(Double.toString(d));
196    stream.print("</double>");
197    printEndEnvelope(tag);
198  }
199    
200  public void writeString(String s, String tag) throws IOException {
201    printBeginEnvelope(tag);
202    stream.print("<string>");
203    stream.print(Utils.toXMLString(s));
204    stream.print("</string>");
205    printEndEnvelope(tag);
206  }
207    
208  public void writeBuffer(Buffer buf, String tag)
209    throws IOException {
210    printBeginEnvelope(tag);
211    stream.print("<string>");
212    stream.print(Utils.toXMLBuffer(buf));
213    stream.print("</string>");
214    printEndEnvelope(tag);
215  }
216    
217  public void startRecord(Record r, String tag) throws IOException {
218    insideRecord(tag);
219    stream.print("<struct>\n");
220    addIndent();
221  }
222    
223  public void endRecord(Record r, String tag) throws IOException {
224    closeIndent();
225    putIndent();
226    stream.print("</struct>");
227    outsideRecord(tag);
228  }
229    
230  public void startVector(ArrayList v, String tag) throws IOException {
231    insideVector(tag);
232    stream.print("<array>\n");
233    addIndent();
234  }
235    
236  public void endVector(ArrayList v, String tag) throws IOException {
237    closeIndent();
238    putIndent();
239    stream.print("</array>");
240    outsideVector(tag);
241  }
242    
243  public void startMap(TreeMap v, String tag) throws IOException {
244    insideMap(tag);
245    stream.print("<array>\n");
246    addIndent();
247  }
248    
249  public void endMap(TreeMap v, String tag) throws IOException {
250    closeIndent();
251    putIndent();
252    stream.print("</array>");
253    outsideMap(tag);
254  }
255
256}