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
019package org.apache.hadoop.io;
020
021import java.io.*;
022import java.lang.reflect.Array;
023
024import org.apache.hadoop.classification.InterfaceAudience;
025import 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
044public 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