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    /** 
028     * A Writable for arrays containing instances of a class. The elements of this
029     * writable must all be instances of the same class. If this writable will be
030     * the input for a Reducer, you will need to create a subclass that sets the
031     * value to be of the proper type.
032     *
033     * For example:
034     * <code>
035     * public class IntArrayWritable extends ArrayWritable {
036     *   public IntArrayWritable() { 
037     *     super(IntWritable.class); 
038     *   }  
039     * }
040     * </code>
041     */
042    @InterfaceAudience.Public
043    @InterfaceStability.Stable
044    public class ArrayWritable implements Writable {
045      private Class<? extends Writable> valueClass;
046      private Writable[] values;
047    
048      public ArrayWritable(Class<? extends Writable> valueClass) {
049        if (valueClass == null) { 
050          throw new IllegalArgumentException("null valueClass"); 
051        }    
052        this.valueClass = valueClass;
053      }
054    
055      public ArrayWritable(Class<? extends Writable> valueClass, Writable[] values) {
056        this(valueClass);
057        this.values = values;
058      }
059    
060      public ArrayWritable(String[] strings) {
061        this(UTF8.class, new Writable[strings.length]);
062        for (int i = 0; i < strings.length; i++) {
063          values[i] = new UTF8(strings[i]);
064        }
065      }
066    
067      public Class getValueClass() {
068        return valueClass;
069      }
070    
071      public String[] toStrings() {
072        String[] strings = new String[values.length];
073        for (int i = 0; i < values.length; i++) {
074          strings[i] = values[i].toString();
075        }
076        return strings;
077      }
078    
079      public Object toArray() {
080        Object result = Array.newInstance(valueClass, values.length);
081        for (int i = 0; i < values.length; i++) {
082          Array.set(result, i, values[i]);
083        }
084        return result;
085      }
086    
087      public void set(Writable[] values) { this.values = values; }
088    
089      public Writable[] get() { return values; }
090    
091      @Override
092      public void readFields(DataInput in) throws IOException {
093        values = new Writable[in.readInt()];          // construct values
094        for (int i = 0; i < values.length; i++) {
095          Writable value = WritableFactories.newInstance(valueClass);
096          value.readFields(in);                       // read a value
097          values[i] = value;                          // store it in values
098        }
099      }
100    
101      @Override
102      public void write(DataOutput out) throws IOException {
103        out.writeInt(values.length);                 // write values
104        for (int i = 0; i < values.length; i++) {
105          values[i].write(out);
106        }
107      }
108    
109    }
110