1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 package org.apache.giraph.utils;
20
21 import java.io.DataInput;
22 import java.io.DataOutput;
23 import java.io.IOException;
24 import java.util.ArrayList;
25
26 import org.apache.hadoop.conf.Configurable;
27 import org.apache.hadoop.conf.Configuration;
28 import org.apache.hadoop.io.Writable;
29 import org.apache.hadoop.util.ReflectionUtils;
30
31 /**
32 * A Writable for ListArray containing instances of a class.
33 *
34 * @param <M> Message data
35 */
36 public abstract class ArrayListWritable<M extends Writable> extends ArrayList<M>
37 implements Writable, Configurable {
38 /** Defining a layout version for a serializable class. */
39 private static final long serialVersionUID = 1L;
40 /** Used for instantiation */
41 private Class<M> refClass = null;
42
43 /** Configuration */
44 private Configuration conf;
45
46 /**
47 * Using the default constructor requires that the user implement
48 * setClass(), guaranteed to be invoked prior to instantiation in
49 * readFields()
50 */
51 public ArrayListWritable() {
52 }
53
54 /**
55 * Constructor with another {@link ArrayListWritable}.
56 *
57 * @param arrayListWritable Array list to be used internally.
58 */
59 public ArrayListWritable(ArrayListWritable<M> arrayListWritable) {
60 super(arrayListWritable);
61 }
62
63 /**
64 * This constructor allows setting the refClass during construction.
65 *
66 * @param refClass internal type class
67 */
68 public ArrayListWritable(Class<M> refClass) {
69 super();
70 this.refClass = refClass;
71 }
72
73 /**
74 * This is a one-time operation to set the class type
75 *
76 * @param refClass internal type class
77 */
78 public void setClass(Class<M> refClass) {
79 if (this.refClass != null) {
80 throw new RuntimeException(
81 "setClass: refClass is already set to " +
82 this.refClass.getName());
83 }
84 this.refClass = refClass;
85 }
86
87 /**
88 * Subclasses must set the class type appropriately and can use
89 * setClass(Class<M> refClass) to do it.
90 */
91 public abstract void setClass();
92
93 @Override
94 public void readFields(DataInput in) throws IOException {
95 if (this.refClass == null) {
96 setClass();
97 }
98
99 clear(); // clear list before storing values
100 int numValues = in.readInt(); // read number of values
101 ensureCapacity(numValues);
102 for (int i = 0; i < numValues; i++) {
103 M value = ReflectionUtils.newInstance(refClass, conf);
104 value.readFields(in); // read a value
105 add(value); // store it in values
106 }
107 }
108
109 @Override
110 public void write(DataOutput out) throws IOException {
111 int numValues = size();
112 out.writeInt(numValues); // write number of values
113 for (int i = 0; i < numValues; i++) {
114 get(i).write(out);
115 }
116 }
117
118 @Override
119 public final Configuration getConf() {
120 return conf;
121 }
122
123 @Override
124 public final void setConf(Configuration conf) {
125 this.conf = conf;
126 }
127 }