blob: 4ce6928b84bd0831e31a1042a117ee7a6907c701 [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.tajo.storage.fragment;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.protobuf.ByteString;
import org.apache.hadoop.conf.Configuration;
import org.apache.tajo.annotation.ThreadSafe;
import org.apache.tajo.exception.TajoInternalError;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.List;
import java.util.Map;
import static org.apache.tajo.catalog.proto.CatalogProtos.FragmentProto;
@ThreadSafe
public class FragmentConvertor {
/**
* Cache of fragment classes
*/
protected static final Map<String, Class<? extends Fragment>> CACHED_FRAGMENT_CLASSES = Maps.newConcurrentMap();
/**
* Cache of constructors for each class.
*/
private static final Map<Class<?>, Constructor<?>> CONSTRUCTOR_CACHE = Maps.newConcurrentMap();
/**
* default parameter for all constructors
*/
private static final Class<?>[] DEFAULT_FRAGMENT_PARAMS = { ByteString.class };
public static Class<? extends Fragment> getFragmentClass(Configuration conf, String dataFormat) {
Class<? extends Fragment> fragmentClass = CACHED_FRAGMENT_CLASSES.get(dataFormat.toLowerCase());
if (fragmentClass == null) {
fragmentClass = conf.getClass(
String.format("tajo.storage.fragment.%s.class", dataFormat.toLowerCase()), null, Fragment.class);
CACHED_FRAGMENT_CLASSES.put(dataFormat.toLowerCase(), fragmentClass);
}
if (fragmentClass == null) {
throw new TajoInternalError("No such a fragment for " + dataFormat.toLowerCase());
}
return fragmentClass;
}
public static <T extends Fragment> T convert(Class<T> clazz, FragmentProto fragment) {
T result;
try {
Constructor<T> constructor = (Constructor<T>) CONSTRUCTOR_CACHE.get(clazz);
if (constructor == null) {
constructor = clazz.getDeclaredConstructor(DEFAULT_FRAGMENT_PARAMS);
constructor.setAccessible(true);
CONSTRUCTOR_CACHE.put(clazz, constructor);
}
result = constructor.newInstance(new Object[]{fragment.getContents()});
} catch (Throwable e) {
throw new TajoInternalError(e);
}
return result;
}
public static <T extends Fragment> T convert(Configuration conf, FragmentProto fragment) {
Class<T> fragmentClass = (Class<T>) getFragmentClass(conf, fragment.getDataFormat().toLowerCase());
if (fragmentClass == null) {
throw new TajoInternalError("No such a fragment class for " + fragment.getDataFormat());
}
return convert(fragmentClass, fragment);
}
public static <T extends Fragment> List<T> convert(Class<T> clazz, FragmentProto...fragments)
throws IOException {
List<T> list = Lists.newArrayList();
if (fragments == null) {
return list;
}
for (FragmentProto proto : fragments) {
list.add(convert(clazz, proto));
}
return list;
}
public static <T extends Fragment> List<T> convert(Configuration conf, FragmentProto...fragments) {
List<T> list = Lists.newArrayList();
if (fragments == null) {
return list;
}
for (FragmentProto proto : fragments) {
list.add((T) convert(conf, proto));
}
return list;
}
public static List<FragmentProto> toFragmentProtoList(Fragment... fragments) {
List<FragmentProto> list = Lists.newArrayList();
if (fragments == null) {
return list;
}
for (Fragment fragment : fragments) {
list.add(fragment.getProto());
}
return list;
}
public static FragmentProto [] toFragmentProtoArray(Fragment... fragments) {
List<FragmentProto> list = toFragmentProtoList(fragments);
return list.toArray(new FragmentProto[list.size()]);
}
}