package mil.nga.giat.geowave.core.store.data.field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import mil.nga.giat.geowave.core.store.filter.GenericTypeResolver;
import mil.nga.giat.geowave.core.store.spi.SPIServiceRegistry;
/**
* This class has a set of convenience methods to determine the appropriate
* field reader and writer for a given field type (Class)
*
*/
public class FieldUtils
{
private static final Logger LOGGER = LoggerFactory.getLogger(FieldUtils.class);
private static Map<Class<?>, FieldReader<?>> fieldReaderRegistry = null;
private static Map<Class<?>, FieldWriter<?, ?>> fieldWriterRegistry = null;
private static synchronized Map<Class<?>, FieldReader<?>> getRegisteredFieldReaders() {
if (fieldReaderRegistry == null) {
initRegistry();
}
return fieldReaderRegistry;
}
private static synchronized Map<Class<?>, FieldWriter<?, ?>> getRegisteredFieldWriters() {
if (fieldWriterRegistry == null) {
initRegistry();
}
return fieldWriterRegistry;
}
private static synchronized void initRegistry() {
fieldReaderRegistry = new HashMap<Class<?>, FieldReader<?>>();
fieldWriterRegistry = new HashMap<Class<?>, FieldWriter<?, ?>>();
final Iterator<FieldSerializationProviderSpi> serializationProviders = new SPIServiceRegistry(
FieldSerializationProviderSpi.class).load(FieldSerializationProviderSpi.class);
while (serializationProviders.hasNext()) {
final FieldSerializationProviderSpi<?> serializationProvider = serializationProviders.next();
if (serializationProvider != null) {
final Class<?> type = GenericTypeResolver.resolveTypeArgument(
serializationProvider.getClass(),
FieldSerializationProviderSpi.class);
final FieldReader<?> reader = serializationProvider.getFieldReader();
if (reader != null) {
if (fieldReaderRegistry.containsKey(type)) {
LOGGER.warn("Field reader already registered for " + type + "; not able to add " + reader);
}
else {
fieldReaderRegistry.put(
type,
reader);
}
}
final FieldWriter<?, ?> writer = serializationProvider.getFieldWriter();
if (writer != null) {
if (fieldWriterRegistry.containsKey(type)) {
LOGGER.warn("Field writer already registered for " + type + "; not able to add " + writer);
}
else {
fieldWriterRegistry.put(
type,
writer);
}
}
}
}
}
@SuppressWarnings("unchecked")
public static <T> FieldReader<T> getDefaultReaderForClass(
final Class<T> myClass ) {
final Map<Class<?>, FieldReader<?>> internalFieldReaders = getRegisteredFieldReaders();
// try concrete class
final FieldReader<T> reader = (FieldReader<T>) internalFieldReaders.get(myClass);
if (reader != null) {
return reader;
}
// if the concrete class lookup failed, try inheritance
return (FieldReader<T>) getAssignableValueFromClassMap(
myClass,
internalFieldReaders);
}
@SuppressWarnings("unchecked")
public static <T> FieldWriter<?, T> getDefaultWriterForClass(
final Class<T> myClass ) {
final Map<Class<?>, FieldWriter<?, ?>> internalFieldWriters = getRegisteredFieldWriters();
// try concrete class
final FieldWriter<?, T> writer = (FieldWriter<?, T>) internalFieldWriters.get(myClass);
if (writer != null) {
return writer;
} // if the concrete class lookup failed, try inheritance
return (FieldWriter<?, T>) getAssignableValueFromClassMap(
myClass,
internalFieldWriters);
}
public static <T> T getAssignableValueFromClassMap(
final Class<?> myClass,
final Map<Class<?>, T> classToAssignableValueMap ) {
// loop through the map to discover the first class that is assignable
// from myClass
for (final Entry<Class<?>, T> candidate : classToAssignableValueMap.entrySet()) {
if (candidate.getKey().isAssignableFrom(
myClass)) {
return candidate.getValue();
}
}
return null;
}
public static <RowType, FieldType> FieldWriter<RowType, FieldType> getDefaultWriterForClass(
final Class<FieldType> myClass,
final FieldVisibilityHandler<RowType, Object> visibilityHandler ) {
return new BasicWriter<RowType, FieldType>(
getDefaultWriterForClass(myClass),
visibilityHandler);
}
}