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  @Override
153  public void writeByte(byte b, String tag) throws IOException {
154    printBeginEnvelope(tag);
155    stream.print("<ex:i1>");
156    stream.print(Byte.toString(b));
157    stream.print("</ex:i1>");
158    printEndEnvelope(tag);
159  }
160    
161  @Override
162  public void writeBool(boolean b, String tag) throws IOException {
163    printBeginEnvelope(tag);
164    stream.print("<boolean>");
165    stream.print(b ? "1" : "0");
166    stream.print("</boolean>");
167    printEndEnvelope(tag);
168  }
169    
170  @Override
171  public void writeInt(int i, String tag) throws IOException {
172    printBeginEnvelope(tag);
173    stream.print("<i4>");
174    stream.print(Integer.toString(i));
175    stream.print("</i4>");
176    printEndEnvelope(tag);
177  }
178    
179  @Override
180  public void writeLong(long l, String tag) throws IOException {
181    printBeginEnvelope(tag);
182    stream.print("<ex:i8>");
183    stream.print(Long.toString(l));
184    stream.print("</ex:i8>");
185    printEndEnvelope(tag);
186  }
187    
188  @Override
189  public void writeFloat(float f, String tag) throws IOException {
190    printBeginEnvelope(tag);
191    stream.print("<ex:float>");
192    stream.print(Float.toString(f));
193    stream.print("</ex:float>");
194    printEndEnvelope(tag);
195  }
196    
197  @Override
198  public void writeDouble(double d, String tag) throws IOException {
199    printBeginEnvelope(tag);
200    stream.print("<double>");
201    stream.print(Double.toString(d));
202    stream.print("</double>");
203    printEndEnvelope(tag);
204  }
205    
206  @Override
207  public void writeString(String s, String tag) throws IOException {
208    printBeginEnvelope(tag);
209    stream.print("<string>");
210    stream.print(Utils.toXMLString(s));
211    stream.print("</string>");
212    printEndEnvelope(tag);
213  }
214    
215  @Override
216  public void writeBuffer(Buffer buf, String tag)
217    throws IOException {
218    printBeginEnvelope(tag);
219    stream.print("<string>");
220    stream.print(Utils.toXMLBuffer(buf));
221    stream.print("</string>");
222    printEndEnvelope(tag);
223  }
224    
225  @Override
226  public void startRecord(Record r, String tag) throws IOException {
227    insideRecord(tag);
228    stream.print("<struct>\n");
229    addIndent();
230  }
231    
232  @Override
233  public void endRecord(Record r, String tag) throws IOException {
234    closeIndent();
235    putIndent();
236    stream.print("</struct>");
237    outsideRecord(tag);
238  }
239    
240  @Override
241  public void startVector(ArrayList v, String tag) throws IOException {
242    insideVector(tag);
243    stream.print("<array>\n");
244    addIndent();
245  }
246    
247  @Override
248  public void endVector(ArrayList v, String tag) throws IOException {
249    closeIndent();
250    putIndent();
251    stream.print("</array>");
252    outsideVector(tag);
253  }
254    
255  @Override
256  public void startMap(TreeMap v, String tag) throws IOException {
257    insideMap(tag);
258    stream.print("<array>\n");
259    addIndent();
260  }
261    
262  @Override
263  public void endMap(TreeMap v, String tag) throws IOException {
264    closeIndent();
265    putIndent();
266    stream.print("</array>");
267    outsideMap(tag);
268  }
269
270}