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;
022
023import java.io.DataInputStream;
024import java.io.DataOutputStream;
025import java.io.IOException;
026import java.io.InputStream;
027import java.io.OutputStream;
028import java.math.BigDecimal;
029import java.math.BigInteger;
030
031import org.apache.hadoop.conf.Configured;
032import org.apache.hadoop.io.serializer.Deserializer;
033import org.apache.hadoop.io.serializer.Serialization;
034import org.apache.hadoop.io.serializer.Serializer;
035
036/**
037 * Class BigDecimalSerialization is an implementation of Hadoop's {@link org.apache.hadoop.io.serializer.Serialization} interface for use
038 * by {@link BigDecimal} instances.
039 * <p>
040 * To use, call<br>
041 * {@code TupleSerializationProps.addSerialization(properties, BigDecimalSerialization.class.getName());}
042 *
043 * @see cascading.tuple.hadoop.TupleSerializationProps#addSerialization(java.util.Map, String)
044 */
045@SerializationToken(tokens = {125}, classNames = {"java.math.BigDecimal"})
046public class BigDecimalSerialization extends Configured implements Serialization<BigDecimal>
047  {
048  public static class BigDecimalDeserializer implements Deserializer<BigDecimal>
049    {
050    private DataInputStream in;
051
052    @Override
053    public void open( InputStream in ) throws IOException
054      {
055      if( in instanceof DataInputStream )
056        this.in = (DataInputStream) in;
057      else
058        this.in = new DataInputStream( in );
059      }
060
061    @Override
062    public BigDecimal deserialize( BigDecimal existing ) throws IOException
063      {
064      int len = in.readInt();
065      byte[] valueBytes = new byte[ len ];
066
067      in.readFully( valueBytes );
068
069      BigInteger value = new BigInteger( valueBytes );
070
071      return new BigDecimal( value, in.readInt() );
072      }
073
074    @Override
075    public void close() throws IOException
076      {
077      in.close();
078      }
079    }
080
081  public static class BigDecimalSerializer implements Serializer<BigDecimal>
082    {
083    private DataOutputStream out;
084
085    @Override
086    public void open( OutputStream out ) throws IOException
087      {
088      if( out instanceof DataOutputStream )
089        this.out = (DataOutputStream) out;
090      else
091        this.out = new DataOutputStream( out );
092      }
093
094    @Override
095    public void serialize( BigDecimal bigDecimal ) throws IOException
096      {
097      BigInteger value = bigDecimal.unscaledValue();
098      byte[] valueBytes = value.toByteArray();
099
100      out.writeInt( valueBytes.length );
101      out.write( valueBytes );
102      out.writeInt( bigDecimal.scale() );
103      }
104
105    @Override
106    public void close() throws IOException
107      {
108      out.close();
109      }
110    }
111
112  public BigDecimalSerialization()
113    {
114    }
115
116  @Override
117  public boolean accept( Class<?> c )
118    {
119    return BigDecimal.class == c;
120    }
121
122  @Override
123  public Serializer<BigDecimal> getSerializer( Class<BigDecimal> c )
124    {
125    return new BigDecimalSerializer();
126    }
127
128  @Override
129  public Deserializer<BigDecimal> getDeserializer( Class<BigDecimal> c )
130    {
131    return new BigDecimalDeserializer();
132    }
133  }