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.meta;
020
021import java.io.IOException;
022import java.util.*;
023
024import org.apache.hadoop.classification.InterfaceAudience;
025import org.apache.hadoop.classification.InterfaceStability;
026import org.apache.hadoop.record.RecordInput;
027import org.apache.hadoop.record.RecordOutput;
028
029/** 
030 * Represents typeID for a struct 
031 * 
032 * @deprecated Replaced by <a href="https://hadoop.apache.org/avro/">Avro</a>.
033 */
034@Deprecated
035@InterfaceAudience.Public
036@InterfaceStability.Stable
037public class StructTypeID extends TypeID {
038  private ArrayList<FieldTypeInfo> typeInfos = new ArrayList<FieldTypeInfo>();
039  
040  StructTypeID() {
041    super(RIOType.STRUCT);
042  }
043  
044  /**
045   * Create a StructTypeID based on the RecordTypeInfo of some record
046   */
047  public StructTypeID(RecordTypeInfo rti) {
048    super(RIOType.STRUCT);
049    typeInfos.addAll(rti.getFieldTypeInfos());
050  }
051
052  void add (FieldTypeInfo ti) {
053    typeInfos.add(ti);
054  }
055  
056  public Collection<FieldTypeInfo> getFieldTypeInfos() {
057    return typeInfos;
058  }
059  
060  /* 
061   * return the StructTypeiD, if any, of the given field 
062   */
063  StructTypeID findStruct(String name) {
064    // walk through the list, searching. Not the most efficient way, but this
065    // in intended to be used rarely, so we keep it simple. 
066    // As an optimization, we can keep a hashmap of record name to its RTI, for later.
067    for (FieldTypeInfo ti : typeInfos) {
068      if ((0 == ti.getFieldID().compareTo(name)) && (ti.getTypeID().getTypeVal() == RIOType.STRUCT)) {
069        return (StructTypeID) ti.getTypeID();
070      }
071    }
072    return null;
073  }
074  
075  void write(RecordOutput rout, String tag) throws IOException {
076    rout.writeByte(typeVal, tag);
077    writeRest(rout, tag);
078  }
079
080  /* 
081   * Writes rest of the struct (excluding type value).
082   * As an optimization, this method is directly called by RTI 
083   * for the top level record so that we don't write out the byte
084   * indicating that this is a struct (since top level records are
085   * always structs).
086   */
087  void writeRest(RecordOutput rout, String tag) throws IOException {
088    rout.writeInt(typeInfos.size(), tag);
089    for (FieldTypeInfo ti : typeInfos) {
090      ti.write(rout, tag);
091    }
092  }
093
094  /* 
095   * deserialize ourselves. Called by RTI. 
096   */
097  void read(RecordInput rin, String tag) throws IOException {
098    // number of elements
099    int numElems = rin.readInt(tag);
100    for (int i=0; i<numElems; i++) {
101      typeInfos.add(genericReadTypeInfo(rin, tag));
102    }
103  }
104  
105  // generic reader: reads the next TypeInfo object from stream and returns it
106  private FieldTypeInfo genericReadTypeInfo(RecordInput rin, String tag) throws IOException {
107    String fieldName = rin.readString(tag);
108    TypeID id = genericReadTypeID(rin, tag);
109    return new FieldTypeInfo(fieldName, id);
110  }
111  
112  // generic reader: reads the next TypeID object from stream and returns it
113  private TypeID genericReadTypeID(RecordInput rin, String tag) throws IOException {
114    byte typeVal = rin.readByte(tag);
115    switch (typeVal) {
116    case TypeID.RIOType.BOOL: 
117      return TypeID.BoolTypeID;
118    case TypeID.RIOType.BUFFER: 
119      return TypeID.BufferTypeID;
120    case TypeID.RIOType.BYTE:
121      return TypeID.ByteTypeID;
122    case TypeID.RIOType.DOUBLE:
123      return TypeID.DoubleTypeID;
124    case TypeID.RIOType.FLOAT:
125      return TypeID.FloatTypeID;
126    case TypeID.RIOType.INT: 
127      return TypeID.IntTypeID;
128    case TypeID.RIOType.LONG:
129      return TypeID.LongTypeID;
130    case TypeID.RIOType.MAP:
131    {
132      TypeID tIDKey = genericReadTypeID(rin, tag);
133      TypeID tIDValue = genericReadTypeID(rin, tag);
134      return new MapTypeID(tIDKey, tIDValue);
135    }
136    case TypeID.RIOType.STRING: 
137      return TypeID.StringTypeID;
138    case TypeID.RIOType.STRUCT: 
139    {
140      StructTypeID stID = new StructTypeID();
141      int numElems = rin.readInt(tag);
142      for (int i=0; i<numElems; i++) {
143        stID.add(genericReadTypeInfo(rin, tag));
144      }
145      return stID;
146    }
147    case TypeID.RIOType.VECTOR: 
148    {
149      TypeID tID = genericReadTypeID(rin, tag);
150      return new VectorTypeID(tID);
151    }
152    default:
153      // shouldn't be here
154      throw new IOException("Unknown type read");
155    }
156  }
157  
158  public boolean equals(Object o) {
159    return super.equals(o);
160  }
161  
162  public int hashCode() { return super.hashCode(); }
163}