blob: 73b47de060afa1dfde074b6a9ebe10abd14cab1a [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.crunch.types;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.Map;
import org.apache.crunch.CrunchRuntimeException;
import org.apache.crunch.Pair;
import org.apache.crunch.Tuple;
import org.apache.crunch.Tuple3;
import org.apache.crunch.Tuple4;
import org.apache.crunch.TupleN;
import com.google.common.collect.Maps;
public abstract class TupleFactory<T extends Tuple> implements Serializable {
public void initialize() {
}
public abstract T makeTuple(Object... values);
private static final Map<Class, TupleFactory> customTupleFactories = Maps.newHashMap();
/**
* Get the {@link TupleFactory} for a given Tuple implementation.
*
* @param tupleClass
* The class for which the factory is to be retrieved
* @return The appropriate TupleFactory
*/
public static <T extends Tuple> TupleFactory<T> getTupleFactory(Class<T> tupleClass) {
if (tupleClass == Pair.class) {
return (TupleFactory<T>) PAIR;
} else if (tupleClass == Tuple3.class) {
return (TupleFactory<T>) TUPLE3;
} else if (tupleClass == Tuple4.class) {
return (TupleFactory<T>) TUPLE4;
} else if (tupleClass == TupleN.class) {
return (TupleFactory<T>) TUPLEN;
} else if (customTupleFactories.containsKey(tupleClass)) {
return (TupleFactory<T>) customTupleFactories.get(tupleClass);
} else {
throw new IllegalArgumentException("Can't create TupleFactory for " + tupleClass);
}
}
public static final TupleFactory<Pair> PAIR = new TupleFactory<Pair>() {
@Override
public Pair makeTuple(Object... values) {
return Pair.of(values[0], values[1]);
}
};
public static final TupleFactory<Tuple3> TUPLE3 = new TupleFactory<Tuple3>() {
@Override
public Tuple3 makeTuple(Object... values) {
return Tuple3.of(values[0], values[1], values[2]);
}
};
public static final TupleFactory<Tuple4> TUPLE4 = new TupleFactory<Tuple4>() {
@Override
public Tuple4 makeTuple(Object... values) {
return Tuple4.of(values[0], values[1], values[2], values[3]);
}
};
public static final TupleFactory<TupleN> TUPLEN = new TupleFactory<TupleN>() {
@Override
public TupleN makeTuple(Object... values) {
return new TupleN(values);
}
};
public static <T extends Tuple> TupleFactory<T> create(Class<T> clazz, Class... typeArgs) {
if (customTupleFactories.containsKey(clazz)) {
return (TupleFactory<T>) customTupleFactories.get(clazz);
}
TupleFactory<T> custom = new CustomTupleFactory<T>(clazz, typeArgs);
customTupleFactories.put(clazz, custom);
return custom;
}
private static class CustomTupleFactory<T extends Tuple> extends TupleFactory<T> {
private final Class<T> clazz;
private final Class[] typeArgs;
private transient Constructor<T> constructor;
public CustomTupleFactory(Class<T> clazz, Class[] typeArgs) {
this.clazz = clazz;
this.typeArgs = typeArgs;
}
@Override
public void initialize() {
try {
constructor = clazz.getConstructor(typeArgs);
} catch (Exception e) {
throw new CrunchRuntimeException(e);
}
}
@Override
public T makeTuple(Object... values) {
try {
return constructor.newInstance(values);
} catch (Exception e) {
throw new CrunchRuntimeException(e);
}
}
}
}