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  @Override
076  void write(RecordOutput rout, String tag) throws IOException {
077    rout.writeByte(typeVal, tag);
078    writeRest(rout, tag);
079  }
080
081  /* 
082   * Writes rest of the struct (excluding type value).
083   * As an optimization, this method is directly called by RTI 
084   * for the top level record so that we don't write out the byte
085   * indicating that this is a struct (since top level records are
086   * always structs).
087   */
088  void writeRest(RecordOutput rout, String tag) throws IOException {
089    rout.writeInt(typeInfos.size(), tag);
090    for (FieldTypeInfo ti : typeInfos) {
091      ti.write(rout, tag);
092    }
093  }
094
095  /* 
096   * deserialize ourselves. Called by RTI. 
097   */
098  void read(RecordInput rin, String tag) throws IOException {
099    // number of elements
100    int numElems = rin.readInt(tag);
101    for (int i=0; i<numElems; i++) {
102      typeInfos.add(genericReadTypeInfo(rin, tag));
103    }
104  }
105  
106  // generic reader: reads the next TypeInfo object from stream and returns it
107  private FieldTypeInfo genericReadTypeInfo(RecordInput rin, String tag) throws IOException {
108    String fieldName = rin.readString(tag);
109    TypeID id = genericReadTypeID(rin, tag);
110    return new FieldTypeInfo(fieldName, id);
111  }
112  
113  // generic reader: reads the next TypeID object from stream and returns it
114  private TypeID genericReadTypeID(RecordInput rin, String tag) throws IOException {
115    byte typeVal = rin.readByte(tag);
116    switch (typeVal) {
117    case TypeID.RIOType.BOOL: 
118      return TypeID.BoolTypeID;
119    case TypeID.RIOType.BUFFER: 
120      return TypeID.BufferTypeID;
121    case TypeID.RIOType.BYTE:
122      return TypeID.ByteTypeID;
123    case TypeID.RIOType.DOUBLE:
124      return TypeID.DoubleTypeID;
125    case TypeID.RIOType.FLOAT:
126      return TypeID.FloatTypeID;
127    case TypeID.RIOType.INT: 
128      return TypeID.IntTypeID;
129    case TypeID.RIOType.LONG:
130      return TypeID.LongTypeID;
131    case TypeID.RIOType.MAP:
132    {
133      TypeID tIDKey = genericReadTypeID(rin, tag);
134      TypeID tIDValue = genericReadTypeID(rin, tag);
135      return new MapTypeID(tIDKey, tIDValue);
136    }
137    case TypeID.RIOType.STRING: 
138      return TypeID.StringTypeID;
139    case TypeID.RIOType.STRUCT: 
140    {
141      StructTypeID stID = new StructTypeID();
142      int numElems = rin.readInt(tag);
143      for (int i=0; i<numElems; i++) {
144        stID.add(genericReadTypeInfo(rin, tag));
145      }
146      return stID;
147    }
148    case TypeID.RIOType.VECTOR: 
149    {
150      TypeID tID = genericReadTypeID(rin, tag);
151      return new VectorTypeID(tID);
152    }
153    default:
154      // shouldn't be here
155      throw new IOException("Unknown type read");
156    }
157  }
158  
159  @Override
160  public boolean equals(Object o) {
161    return super.equals(o);
162  }
163  
164  @Override
165  public int hashCode() { return super.hashCode(); }
166}