/**
* Copyright 2010 Wealthfront Inc. Licensed 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 com.kaching.platform.converters;
import java.lang.reflect.Type;
import com.google.inject.TypeLiteral;
import com.kaching.platform.common.Errors;
import com.kaching.platform.common.Option;
public class Instantiators {
/* The Instantiators class is the entry point into the library and is not
* meant to be instantiated.
*/
private Instantiators() {}
/**
* Creates an instantiator for {@code klass}.
*/
public static <T> Instantiator<T> createInstantiator(
Class<T> klass, InstantiatorModule... modules) {
Errors errors = new Errors();
for (Instantiator<T> instantiator : createInstantiator(errors, klass, modules)) {
return instantiator;
}
errors.throwIfHasErrors();
// The following program should not be reachable since the factory should
// produce errors if it is unable to create an instantiator.
throw new IllegalStateException();
}
/**
* Creates an instantiator for {@code klass} if possible and aggregates errors.
* This factory method is mostly useful when instantiators are used as a piece
* in larger framework and allows errors aggregation to be done hollisticly.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static <T> Option<Instantiator<T>> createInstantiator(
Errors errors, Class<T> klass, InstantiatorModule... modules) {
// we do not want to expose the covariant option
return (Option) factoryFor(errors, klass, modules).build();
}
/**
* Creates a converter for {@code klass}.
*/
public static <T> Converter<T> createConverter(
Class<T> klass, InstantiatorModule... modules) {
return createConverterForType(klass, modules);
}
/**
* Creates a converter for {@code typeLiteral}.
*/
public static <T> Converter<T> createConverter(
TypeLiteral<T> typeLiteral, InstantiatorModule... modules) {
return createConverterForType(typeLiteral.getType(), modules);
}
private static <T> InstantiatorImplFactory<T> factoryFor(
Errors errors, Class<T> klass,
InstantiatorModule... modules) {
InstantiatorImplFactory<T> factory = InstantiatorImplFactory
.createFactory(errors, klass);
for (InstantiatorModule c : modules) {
c.configure(factory.binder());
}
return factory;
}
@SuppressWarnings("unchecked")
private static <T> Converter<T> createConverterForType(Type type,
InstantiatorModule... modules) {
return (Converter<T>) factoryFor(new Errors(), null, modules).createConverter(type).getOrThrow();
}
}