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.io;
020    
021    import java.io.*;
022    import java.lang.reflect.Array;
023    
024    import org.apache.hadoop.classification.InterfaceAudience;
025    import org.apache.hadoop.classification.InterfaceStability;
026    
027    /** A Writable for 2D arrays containing a matrix of instances of a class. */
028    @InterfaceAudience.Public
029    @InterfaceStability.Stable
030    public class TwoDArrayWritable implements Writable {
031      private Class valueClass;
032      private Writable[][] values;
033    
034      public TwoDArrayWritable(Class valueClass) {
035        this.valueClass = valueClass;
036      }
037    
038      public TwoDArrayWritable(Class valueClass, Writable[][] values) {
039        this(valueClass);
040        this.values = values;
041      }
042    
043      public Object toArray() {
044        int dimensions[] = {values.length, 0};
045        Object result = Array.newInstance(valueClass, dimensions);
046        for (int i = 0; i < values.length; i++) {
047          Object resultRow = Array.newInstance(valueClass, values[i].length);
048          Array.set(result, i, resultRow);
049          for (int j = 0; j < values[i].length; j++) {
050            Array.set(resultRow, j, values[i][j]);
051          }
052        }
053        return result;
054      }
055    
056      public void set(Writable[][] values) { this.values = values; }
057    
058      public Writable[][] get() { return values; }
059    
060      @Override
061      public void readFields(DataInput in) throws IOException {
062        // construct matrix
063        values = new Writable[in.readInt()][];          
064        for (int i = 0; i < values.length; i++) {
065          values[i] = new Writable[in.readInt()];
066        }
067    
068        // construct values
069        for (int i = 0; i < values.length; i++) {
070          for (int j = 0; j < values[i].length; j++) {
071            Writable value;                             // construct value
072            try {
073              value = (Writable)valueClass.newInstance();
074            } catch (InstantiationException e) {
075              throw new RuntimeException(e.toString());
076            } catch (IllegalAccessException e) {
077              throw new RuntimeException(e.toString());
078            }
079            value.readFields(in);                       // read a value
080            values[i][j] = value;                       // store it in values
081          }
082        }
083      }
084    
085      @Override
086      public void write(DataOutput out) throws IOException {
087        out.writeInt(values.length);                 // write values
088        for (int i = 0; i < values.length; i++) {
089          out.writeInt(values[i].length);
090        }
091        for (int i = 0; i < values.length; i++) {
092          for (int j = 0; j < values[i].length; j++) {
093            values[i][j].write(out);
094          }
095        }
096      }
097    }
098