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.IOException; 024import java.io.OutputStream; 025import java.util.IdentityHashMap; 026import java.util.Map; 027 028import cascading.tuple.Tuple; 029import cascading.tuple.io.IndexTuple; 030import cascading.tuple.io.TupleOutputStream; 031import cascading.tuple.io.TuplePair; 032import org.apache.hadoop.io.WritableUtils; 033 034/** 035 * 036 */ 037public class HadoopTupleOutputStream extends TupleOutputStream 038 { 039 /** Field WRITABLE_TOKEN */ 040 public static final int WRITABLE_TOKEN = 32; 041 042 private static final Map<Class, TupleElementWriter> staticTupleUnTypedElementWriters = new IdentityHashMap<>(); 043 private static final Map<Class, TupleElementWriter> staticTupleTypedElementWriters = new IdentityHashMap<>(); 044 045 static 046 { 047 // untyped 048 049 staticTupleUnTypedElementWriters.put( String.class, ( stream, element ) -> 050 { 051 WritableUtils.writeVInt( stream, 1 ); 052 WritableUtils.writeString( stream, (String) element ); 053 } ); 054 055 staticTupleUnTypedElementWriters.put( Float.class, ( stream, element ) -> 056 { 057 WritableUtils.writeVInt( stream, 2 ); 058 stream.writeFloat( (Float) element ); 059 } ); 060 061 staticTupleUnTypedElementWriters.put( Double.class, ( stream, element ) -> 062 { 063 WritableUtils.writeVInt( stream, 3 ); 064 stream.writeDouble( (Double) element ); 065 } ); 066 067 staticTupleUnTypedElementWriters.put( Integer.class, ( stream, element ) -> 068 { 069 WritableUtils.writeVInt( stream, 4 ); 070 WritableUtils.writeVInt( stream, (Integer) element ); 071 } ); 072 073 staticTupleUnTypedElementWriters.put( Long.class, ( stream, element ) -> 074 { 075 WritableUtils.writeVInt( stream, 5 ); 076 WritableUtils.writeVLong( stream, (Long) element ); 077 } ); 078 079 staticTupleUnTypedElementWriters.put( Boolean.class, ( stream, element ) -> 080 { 081 WritableUtils.writeVInt( stream, 6 ); 082 stream.writeBoolean( (Boolean) element ); 083 } ); 084 085 staticTupleUnTypedElementWriters.put( Short.class, ( stream, element ) -> 086 { 087 WritableUtils.writeVInt( stream, 7 ); 088 stream.writeShort( (Short) element ); 089 } ); 090 091 staticTupleUnTypedElementWriters.put( Tuple.class, ( stream, element ) -> 092 { 093 WritableUtils.writeVInt( stream, 8 ); 094 stream.writeTuple( (Tuple) element ); 095 } ); 096 097 staticTupleUnTypedElementWriters.put( TuplePair.class, ( stream, element ) -> 098 { 099 WritableUtils.writeVInt( stream, 9 ); 100 stream.writeTuplePair( (TuplePair) element ); 101 } ); 102 103 staticTupleUnTypedElementWriters.put( IndexTuple.class, ( stream, element ) -> 104 { 105 WritableUtils.writeVInt( stream, 10 ); 106 stream.writeIndexTuple( (IndexTuple) element ); 107 } ); 108 109 // typed 110 111 staticTupleTypedElementWriters.put( Void.class, ( stream, element ) -> 112 { 113 // do nothing 114 } ); 115 116 staticTupleTypedElementWriters.put( String.class, ( stream, element ) -> WritableUtils.writeString( stream, (String) element ) ); 117 118 staticTupleTypedElementWriters.put( Float.class, ( stream, element ) -> 119 { 120 if( element == null ) 121 { 122 stream.writeByte( 0 ); 123 return; 124 } 125 126 stream.writeByte( 1 ); 127 stream.writeFloat( (Float) element ); 128 } ); 129 130 staticTupleTypedElementWriters.put( Double.class, ( stream, element ) -> 131 { 132 if( element == null ) 133 { 134 stream.writeByte( 0 ); 135 return; 136 } 137 138 stream.writeByte( 1 ); 139 stream.writeDouble( (Double) element ); 140 } ); 141 142 staticTupleTypedElementWriters.put( Integer.class, ( stream, element ) -> 143 { 144 if( element == null ) 145 { 146 stream.writeByte( 0 ); 147 return; 148 } 149 150 stream.writeByte( 1 ); 151 WritableUtils.writeVInt( stream, (Integer) element ); 152 } ); 153 154 staticTupleTypedElementWriters.put( Long.class, ( stream, element ) -> 155 { 156 if( element == null ) 157 { 158 stream.writeByte( 0 ); 159 return; 160 } 161 162 stream.writeByte( 1 ); 163 WritableUtils.writeVLong( stream, (Long) element ); 164 } ); 165 166 staticTupleTypedElementWriters.put( Boolean.class, ( stream, element ) -> 167 { 168 if( element == null ) 169 { 170 stream.writeByte( 0 ); 171 return; 172 } 173 174 stream.writeByte( 1 ); 175 stream.writeBoolean( (Boolean) element ); 176 } ); 177 178 staticTupleTypedElementWriters.put( Short.class, ( stream, element ) -> 179 { 180 if( element == null ) 181 { 182 stream.writeByte( 0 ); 183 return; 184 } 185 186 stream.writeByte( 1 ); 187 stream.writeShort( (Short) element ); 188 } ); 189 190 staticTupleTypedElementWriters.put( Float.TYPE, ( stream, element ) -> 191 { 192 if( element == null ) 193 stream.writeFloat( 0 ); 194 else 195 stream.writeFloat( (Float) element ); 196 } ); 197 198 staticTupleTypedElementWriters.put( Double.TYPE, ( stream, element ) -> 199 { 200 if( element == null ) 201 stream.writeDouble( 0 ); 202 else 203 stream.writeDouble( (Double) element ); 204 } ); 205 206 staticTupleTypedElementWriters.put( Integer.TYPE, ( stream, element ) -> 207 { 208 if( element == null ) 209 WritableUtils.writeVInt( stream, 0 ); 210 else 211 WritableUtils.writeVInt( stream, (Integer) element ); 212 } ); 213 214 staticTupleTypedElementWriters.put( Long.TYPE, ( stream, element ) -> 215 { 216 if( element == null ) 217 WritableUtils.writeVLong( stream, 0 ); 218 else 219 WritableUtils.writeVLong( stream, (Long) element ); 220 } ); 221 222 staticTupleTypedElementWriters.put( Boolean.TYPE, ( stream, element ) -> 223 { 224 if( element == null ) 225 stream.writeBoolean( false ); 226 else 227 stream.writeBoolean( (Boolean) element ); 228 } ); 229 230 staticTupleTypedElementWriters.put( Short.TYPE, ( stream, element ) -> 231 { 232 if( element == null ) 233 stream.writeShort( 0 ); 234 else 235 stream.writeShort( (Short) element ); 236 } ); 237 238 staticTupleTypedElementWriters.put( Tuple.class, ( stream, element ) -> stream.writeTuple( (Tuple) element ) ); 239 240 staticTupleTypedElementWriters.put( TuplePair.class, ( stream, element ) -> stream.writeTuplePair( (TuplePair) element ) ); 241 242 staticTupleTypedElementWriters.put( IndexTuple.class, ( stream, element ) -> stream.writeIndexTuple( (IndexTuple) element ) ); 243 } 244 245 public static TupleElementWriter[] getWritersFor( final ElementWriter elementWriter, final Class[] keyClasses ) 246 { 247 if( keyClasses == null || keyClasses.length == 0 ) 248 return null; 249 250 TupleElementWriter[] writers = new TupleElementWriter[ keyClasses.length ]; 251 252 for( int i = 0; i < keyClasses.length; i++ ) 253 { 254 TupleElementWriter writer = staticTupleTypedElementWriters.get( keyClasses[ i ] ); 255 256 if( writer != null ) 257 { 258 writers[ i ] = writer; 259 } 260 else 261 { 262 final int index = i; 263 writers[ i ] = ( stream, element ) -> elementWriter.write( stream, keyClasses[ index ], element ); 264 } 265 } 266 267 return writers; 268 } 269 270 public HadoopTupleOutputStream( OutputStream outputStream, ElementWriter elementWriter ) 271 { 272 super( staticTupleUnTypedElementWriters, staticTupleTypedElementWriters, outputStream, elementWriter ); 273 } 274 275 @Override 276 protected void writeIntInternal( int value ) throws IOException 277 { 278 WritableUtils.writeVInt( this, value ); 279 } 280 281 public void writeIndexTuple( IndexTuple indexTuple ) throws IOException 282 { 283 writeIntInternal( indexTuple.getIndex() ); 284 writeTuple( indexTuple.getTuple() ); 285 } 286 }