001/* 002 * Copyright (c) 2007-2022 The Cascading Authors. All Rights Reserved. 003 * 004 * Project and contact information: https://cascading.wensel.net/ 005 * 006 * This file is part of the Cascading project. 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020 021package cascading.tuple.hadoop.io; 022 023import java.io.DataInputStream; 024import java.io.IOException; 025import java.io.InputStream; 026import java.util.IdentityHashMap; 027import java.util.Map; 028 029import cascading.tuple.Tuple; 030import cascading.tuple.io.IndexTuple; 031import cascading.tuple.io.TupleInputStream; 032import cascading.tuple.io.TuplePair; 033import org.apache.hadoop.io.WritableUtils; 034 035/** 036 * 037 */ 038public class HadoopTupleInputStream extends TupleInputStream 039 { 040 private static final Map<Class, TupleElementReader> staticTupleUnTypedElementReaders = new IdentityHashMap<>(); 041 private static final Map<Class, TupleElementReader> staticTupleTypedElementReaders = new IdentityHashMap<>(); 042 043 static 044 { 045 // typed 046 047 staticTupleTypedElementReaders.put( Void.class, (TupleElementReader<HadoopTupleInputStream>) stream -> null ); 048 049 staticTupleTypedElementReaders.put( String.class, (TupleElementReader<HadoopTupleInputStream>) HadoopTupleInputStream::readString ); 050 051 staticTupleTypedElementReaders.put( Float.class, (TupleElementReader<HadoopTupleInputStream>) HadoopTupleInputStream::readNullFloat ); 052 053 staticTupleTypedElementReaders.put( Double.class, (TupleElementReader<HadoopTupleInputStream>) HadoopTupleInputStream::readNullDouble ); 054 055 staticTupleTypedElementReaders.put( Integer.class, (TupleElementReader<HadoopTupleInputStream>) HadoopTupleInputStream::readNullVInt ); 056 057 staticTupleTypedElementReaders.put( Long.class, (TupleElementReader<HadoopTupleInputStream>) HadoopTupleInputStream::readNullVLong ); 058 059 staticTupleTypedElementReaders.put( Boolean.class, (TupleElementReader<HadoopTupleInputStream>) HadoopTupleInputStream::readNullBoolean ); 060 061 staticTupleTypedElementReaders.put( Short.class, (TupleElementReader<HadoopTupleInputStream>) HadoopTupleInputStream::readNullShort ); 062 063 staticTupleTypedElementReaders.put( Float.TYPE, (TupleElementReader<HadoopTupleInputStream>) DataInputStream::readFloat ); 064 065 staticTupleTypedElementReaders.put( Double.TYPE, (TupleElementReader<HadoopTupleInputStream>) DataInputStream::readDouble ); 066 067 staticTupleTypedElementReaders.put( Integer.TYPE, (TupleElementReader<HadoopTupleInputStream>) HadoopTupleInputStream::readVInt ); 068 069 staticTupleTypedElementReaders.put( Long.TYPE, (TupleElementReader<HadoopTupleInputStream>) HadoopTupleInputStream::readVLong ); 070 071 staticTupleTypedElementReaders.put( Boolean.TYPE, (TupleElementReader<HadoopTupleInputStream>) DataInputStream::readBoolean ); 072 073 staticTupleTypedElementReaders.put( Short.TYPE, (TupleElementReader<HadoopTupleInputStream>) DataInputStream::readShort ); 074 075 staticTupleTypedElementReaders.put( Tuple.class, (TupleElementReader<HadoopTupleInputStream>) TupleInputStream::readTuple ); 076 077 staticTupleTypedElementReaders.put( TuplePair.class, (TupleElementReader<HadoopTupleInputStream>) TupleInputStream::readTuplePair ); 078 079 staticTupleTypedElementReaders.put( IndexTuple.class, (TupleElementReader<HadoopTupleInputStream>) TupleInputStream::readIndexTuple ); 080 } 081 082 public static TupleElementReader[] getReadersFor( final ElementReader elementReader, final Class[] classes ) 083 { 084 if( classes == null || classes.length == 0 ) 085 return null; 086 087 TupleElementReader[] readers = new TupleElementReader[ classes.length ]; 088 089 for( int i = 0; i < classes.length; i++ ) 090 { 091 TupleElementReader reader = staticTupleTypedElementReaders.get( classes[ i ] ); 092 093 if( reader != null ) 094 { 095 readers[ i ] = reader; 096 } 097 else 098 { 099 final int index = i; 100 readers[ i ] = stream -> elementReader.read( classes[ index ], stream ); 101 } 102 } 103 104 return readers; 105 } 106 107 public HadoopTupleInputStream( InputStream inputStream, ElementReader elementReader ) 108 { 109 super( inputStream, elementReader ); 110 } 111 112 public int getNumElements() throws IOException 113 { 114 return readVInt(); 115 } 116 117 public int readToken() throws IOException 118 { 119 return readVInt(); 120 } 121 122 public Object getNextElement() throws IOException 123 { 124 return readType( readToken() ); 125 } 126 127 public IndexTuple readIndexTuple( IndexTuple tuple ) throws IOException 128 { 129 tuple.setIndex( readVInt() ); 130 tuple.setTuple( readTuple() ); 131 132 return tuple; 133 } 134 135 public Long readNullVLong() throws IOException 136 { 137 byte b = this.readByte(); 138 139 if( b == 0 ) 140 return null; 141 142 return WritableUtils.readVLong( this ); 143 } 144 145 public long readVLong() throws IOException 146 { 147 return WritableUtils.readVLong( this ); 148 } 149 150 public Integer readNullVInt() throws IOException 151 { 152 byte b = this.readByte(); 153 154 if( b == 0 ) 155 return null; 156 157 return WritableUtils.readVInt( this ); 158 } 159 160 public int readVInt() throws IOException 161 { 162 return WritableUtils.readVInt( this ); 163 } 164 165 public String readString() throws IOException 166 { 167 return WritableUtils.readString( this ); 168 } 169 170 private Short readNullShort() throws IOException 171 { 172 byte b = this.readByte(); 173 174 if( b == 0 ) 175 return null; 176 177 return readShort(); 178 } 179 180 private Object readNullBoolean() throws IOException 181 { 182 byte b = this.readByte(); 183 184 if( b == 0 ) 185 return null; 186 187 return readBoolean(); 188 } 189 190 private Object readNullDouble() throws IOException 191 { 192 byte b = this.readByte(); 193 194 if( b == 0 ) 195 return null; 196 197 return readDouble(); 198 } 199 200 private Object readNullFloat() throws IOException 201 { 202 byte b = this.readByte(); 203 204 if( b == 0 ) 205 return null; 206 207 return readFloat(); 208 } 209 210 protected final Object readType( int type ) throws IOException 211 { 212 switch( type ) 213 { 214 case 0: 215 return null; 216 case 1: 217 return readString(); 218 case 2: 219 return readFloat(); 220 case 3: 221 return readDouble(); 222 case 4: 223 return readVInt(); 224 case 5: 225 return readVLong(); 226 case 6: 227 return readBoolean(); 228 case 7: 229 return readShort(); 230 case 8: 231 return readTuple(); 232 case 9: 233 return readTuplePair(); 234 case 10: 235 return readIndexTuple(); 236 default: 237 return elementReader.read( type, this ); 238 } 239 } 240 241 public final Object readType( Class type ) throws IOException 242 { 243 if( type == Void.class ) 244 return null; 245 246 if( type == String.class ) 247 return readString(); 248 249 if( type == Float.class ) 250 return readNullFloat(); 251 if( type == Double.class ) 252 return readNullDouble(); 253 if( type == Integer.class ) 254 return readNullVInt(); 255 if( type == Long.class ) 256 return readNullVLong(); 257 if( type == Boolean.class ) 258 return readNullBoolean(); 259 if( type == Short.class ) 260 return readNullShort(); 261 262 if( type == Float.TYPE ) 263 return readFloat(); 264 if( type == Double.TYPE ) 265 return readDouble(); 266 if( type == Integer.TYPE ) 267 return readVInt(); 268 if( type == Long.TYPE ) 269 return readVLong(); 270 if( type == Boolean.TYPE ) 271 return readBoolean(); 272 if( type == Short.TYPE ) 273 return readShort(); 274 275 if( type == Tuple.class ) 276 return readTuple(); 277 if( type == TuplePair.class ) 278 return readTuplePair(); 279 if( type == IndexTuple.class ) 280 return readIndexTuple(); 281 else 282 return elementReader.read( type, this ); 283 } 284 }