/* * Copyright 2015 data Artisans GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.dataartisans.flink.cascading.types.tuplearray; import cascading.tuple.Tuple; import com.dataartisans.flink.cascading.types.tuple.NullMaskSerDeUtils; import org.apache.flink.api.common.typeutils.TypeSerializer; import org.apache.flink.core.memory.DataInputView; import org.apache.flink.core.memory.DataOutputView; import java.io.IOException; import java.util.Arrays; public class TupleArraySerializer extends TypeSerializer<Tuple[]> { private final int length; private final int fillLength; private final TypeSerializer<Tuple>[] tupleSerializers; private final boolean[] nullFields; public TupleArraySerializer(int length, TypeSerializer<Tuple>[] tupleSerializers) { this.length = length; this.fillLength = tupleSerializers.length; this.tupleSerializers = tupleSerializers; this.nullFields = new boolean[this.fillLength]; } @Override public Tuple[] createInstance() { return new Tuple[this.length]; } @Override public boolean isImmutableType() { return false; } @Override public TypeSerializer<Tuple[]> duplicate() { TypeSerializer<Tuple>[] serializerCopies = new TypeSerializer[this.fillLength]; for(int i=0; i<this.fillLength; i++) { serializerCopies[i] = this.tupleSerializers[i].duplicate(); } return new TupleArraySerializer(this.length, serializerCopies); } @Override public Tuple[] copy(Tuple[] from) { Tuple[] copy = new Tuple[this.length]; for(int i=0; i<this.fillLength; i++) { if(from[i] != null) { copy[i] = this.tupleSerializers[i].copy(from[i]); } else { copy[i] = null; } } return copy; } @Override public Tuple[] copy(Tuple[] from, Tuple[] reuse) { for(int i=0; i<this.fillLength; i++) { if(from[i] != null) { reuse[i] = this.tupleSerializers[i].copy(from[i]); } else { reuse[i] = null; } } return reuse; } @Override public int getLength() { return 0; } @Override public void serialize(Tuple[] tuples, DataOutputView target) throws IOException { // write null mask NullMaskSerDeUtils.writeNullMask(tuples, fillLength, target); for (int i = 0; i < fillLength; i++) { if(tuples[i] != null) { tupleSerializers[i].serialize(tuples[i], target); } } } @Override public Tuple[] deserialize(DataInputView source) throws IOException { // read null mask NullMaskSerDeUtils.readNullMask(this.nullFields, this.fillLength, source); // read non-null fields Tuple[] tuples = new Tuple[this.length]; for (int i = 0; i < this.fillLength; i++) { if(!this.nullFields[i]) { tuples[i] = tupleSerializers[i].deserialize(source); } } return tuples; } @Override public Tuple[] deserialize(Tuple[] reuse, DataInputView source) throws IOException { // read null mask NullMaskSerDeUtils.readNullMask(this.nullFields, this.fillLength, source); // read non-null fields for (int i = 0; i < this.fillLength; i++) { if(!this.nullFields[i]) { reuse[i] = tupleSerializers[i].deserialize(source); } else { reuse[i] = null; } } return reuse; } @Override public void copy(DataInputView source, DataOutputView target) throws IOException { // read and copy null mask NullMaskSerDeUtils.readAndCopyNullMask(nullFields, this.fillLength, source, target); // copy non-null fields for (int i = 0; i < this.fillLength; i++) { if(!this.nullFields[i]) { tupleSerializers[i].copy(source, target); } } } @Override public boolean equals(Object obj) { if (obj instanceof TupleArraySerializer) { TupleArraySerializer other = (TupleArraySerializer) obj; return other.canEqual(this) && this.length == other.length && Arrays.equals(this.tupleSerializers, other.tupleSerializers); } else { return false; } } @Override public int hashCode() { return 31 * this.length + Arrays.hashCode(this.tupleSerializers); } @Override public boolean canEqual(Object obj) { return obj instanceof TupleArraySerializer; } }