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    
019    package org.apache.hadoop.record.meta;
020    
021    import java.io.IOException;
022    import java.util.*;
023    
024    import org.apache.hadoop.classification.InterfaceAudience;
025    import org.apache.hadoop.classification.InterfaceStability;
026    import org.apache.hadoop.record.RecordInput;
027    import 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
037    public 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    }