/*
 * 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.jclouds;

import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.containsPattern;
import static com.google.common.base.Predicates.instanceOf;
import static com.google.common.base.Predicates.not;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Iterables.addAll;
import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.newArrayListWithCapacity;
import static com.google.common.collect.Maps.filterKeys;
import static com.google.common.util.concurrent.MoreExecutors.newDirectExecutorService;
import static org.jclouds.Constants.PROPERTY_API;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_BUILD_VERSION;
import static org.jclouds.Constants.PROPERTY_CREDENTIAL;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.Constants.PROPERTY_IDENTITY;
import static org.jclouds.Constants.PROPERTY_ISO3166_CODES;
import static org.jclouds.Constants.PROPERTY_PROVIDER;
import static org.jclouds.reflect.Reflection2.typeToken;
import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
import static org.jclouds.util.Throwables2.propagateAuthorizationOrOriginalException;

import java.io.Closeable;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;

import org.jclouds.apis.ApiMetadata;
import org.jclouds.apis.Apis;
import org.jclouds.concurrent.SingleThreaded;
import org.jclouds.concurrent.config.ConfiguresExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.config.BindApiContextWithWildcardExtendsExplicitAndRawType;
import org.jclouds.config.BindNameToContext;
import org.jclouds.domain.Credentials;
import org.jclouds.events.config.ConfiguresEventBus;
import org.jclouds.events.config.EventBusModule;
import org.jclouds.functions.ExpandProperties;
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.lifecycle.config.LifeCycleModule;
import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.providers.Providers;
import org.jclouds.providers.config.BindProviderMetadataContextAndCredentials;
import org.jclouds.providers.internal.UpdateProviderMetadataFromProperties;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.ConfiguresCredentialStore;
import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.HttpApiMetadata;
import org.jclouds.rest.HttpClient;
import org.jclouds.rest.config.CredentialStoreModule;
import org.jclouds.rest.config.HttpApiModule;
import org.jclouds.rest.config.RestModule;
import org.jclouds.rest.internal.InvokeHttpMethod;
import org.jclouds.util.TypeTokenUtils;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.reflect.TypeToken;
import com.google.common.util.concurrent.ExecutionList;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Stage;
import com.google.inject.TypeLiteral;

/**
 * Creates {@link Context} or {@link Injector} configured to an api and
 * endpoint. Alternatively, this can be used to make a portable {@link View} of
 * that api.
 * 
 * <br/>
 * ex. to build a {@code Api} on a particular endpoint using the typed
 * interface
 * 
 * <pre>
 * api = ContextBuilder.newBuilder(new NovaApiMetadata())
 *                     .endpoint("http://10.10.10.10:5000/v2.0")
 *                     .credentials(user, pass)
 *                     .buildApi(NovaApi.class);
 * </pre>
 * 
 * <br/>
 * ex. to build a {@link View} of a particular backend context, looked up by
 * key.
 * 
 * <pre>
 * context = ContextBuilder.newBuilder("aws-s3")
 *                         .credentials(apikey, secret)
 *                         .buildView(BlobStoreContext.class);
 * </pre>
 * 
 * <h4>Assumptions</h4>
 * 
 * Threadsafe objects will be bound as singletons to the Injector or Context
 * provided.
 * <p/>
 * If no <code>Module</code>s are specified, the default
 * {@link JDKLoggingModule logging} and
 * {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be
 * installed.
 * 
 * @see Context
 * @see View
 * @see ApiMetadata
 * @see ProviderMetadata
 */
public class ContextBuilder {

   private static final Stage GUICE_STAGE = Stage.PRODUCTION;

   /**
    * looks up a provider or api with the given id
    * 
    * @param providerOrApi
    *           id of the provider or api
    * @return means to build a context to that provider
    * @throws NoSuchElementException
    *            if the id was not configured.
    */
   public static ContextBuilder newBuilder(String providerOrApi) throws NoSuchElementException {
      try {
         try {
            return ContextBuilder.newBuilder(Providers.withId(providerOrApi));
         } catch (NoSuchElementException e) {
            return ContextBuilder.newBuilder(Apis.withId(providerOrApi));
         }
      } catch (NoSuchElementException e) {
         Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
         builder.putAll("providers", transform(Providers.all(), Providers.idFunction()));
         builder.putAll("apis", transform(Apis.all(), Apis.idFunction()));
         throw new NoSuchElementException(String.format("key [%s] not in the list of providers or apis: %s",
                  providerOrApi, builder.build()));
      }
   }

   public static ContextBuilder newBuilder(ApiMetadata apiMetadata) {
      try {
         return new ContextBuilder(apiMetadata);
      } catch (Exception e) {
         return propagateAuthorizationOrOriginalException(e);
      }
   }

   public static ContextBuilder newBuilder(ProviderMetadata providerMetadata) {
      try {
         return new ContextBuilder(providerMetadata);
      } catch (Exception e) {
         return propagateAuthorizationOrOriginalException(e);
      }
   }

   protected Optional<String> name = Optional.absent();
   protected Optional<ProviderMetadata> providerMetadata = Optional.absent();
   protected final String providerId;
   protected Optional<String> endpoint = Optional.absent();
   protected Optional<String> identity = Optional.absent();
   protected Optional<Supplier<Credentials>> credentialsSupplierOption = Optional.absent();
   @Nullable
   protected String credential;
   protected ApiMetadata apiMetadata;
   protected String apiVersion;
   protected String buildVersion;
   protected Optional<Properties> overrides = Optional.absent();
   protected List<Module> modules = newArrayListWithCapacity(3);

   @Override
   public String toString() {
      return toStringHelper("").add("providerMetadata", providerMetadata).add("apiMetadata", apiMetadata).toString();
   }

   protected ContextBuilder(ProviderMetadata providerMetadata) {
      this(providerMetadata, checkNotNull(providerMetadata, "providerMetadata").getApiMetadata());
   }

   protected ContextBuilder(@Nullable ProviderMetadata providerMetadata, ApiMetadata apiMetadata) {
      this.apiMetadata = checkNotNull(apiMetadata, "apiMetadata");
      if (providerMetadata != null) {
         this.providerMetadata = Optional.of(providerMetadata);
         this.endpoint = Optional.of(providerMetadata.getEndpoint());
         this.providerId = providerMetadata.getId();
      } else {
         this.endpoint = apiMetadata.getDefaultEndpoint();
         this.providerId = apiMetadata.getId();
      }
      this.identity = apiMetadata.getDefaultIdentity();
      this.credential = apiMetadata.getDefaultCredential().orNull();
      this.apiVersion = apiMetadata.getVersion();
      this.buildVersion = apiMetadata.getBuildVersion().or("");
   }

   public ContextBuilder(ApiMetadata apiMetadata) {
      this(null, apiMetadata);
   }

   public ContextBuilder name(String name) {
     this.name = Optional.of(checkNotNull(name, "name"));
     return this;
   }

   /**
    * returns the current login credentials. jclouds will not cache this value. Use this when you need to change
    * credentials at runtime.
    */
   public ContextBuilder credentialsSupplier(Supplier<Credentials> credentialsSupplier) {
      this.credentialsSupplierOption = Optional.of(checkNotNull(credentialsSupplier, "credentialsSupplier"));
      return this;
   }
   
   /**
    * constant value of the cloud identity and credential.
    * 
    * @param credential (optional depending on {@link ApiMetadata#getCredentialName()}
    */
   public ContextBuilder credentials(String identity, @Nullable String credential) {
      this.identity = Optional.of(checkNotNull(identity, "identity"));
      this.credential = credential;
      return this;
   }

   public ContextBuilder endpoint(String endpoint) {
      this.endpoint = Optional.of(checkNotNull(endpoint, "endpoint"));
      return this;
   }

   public ContextBuilder apiVersion(String apiVersion) {
      this.apiVersion = checkNotNull(apiVersion, "apiVersion");
      return this;
   }

   public ContextBuilder buildVersion(String buildVersion) {
      this.buildVersion = checkNotNull(buildVersion, "buildVersion");
      return this;
   }

   public ContextBuilder modules(Iterable<? extends Module> modules) {
      addAll(this.modules, checkNotNull(modules, "modules"));
      return this;
   }

   public ContextBuilder overrides(Properties overrides) {
      this.overrides = Optional.of(checkNotNull(overrides, "overrides"));
      return this;
   }

   public static String searchPropertiesForProviderScopedProperty(Properties mutable, String prov, String key) throws NoSuchElementException {
      try {
         return find(newArrayList(mutable.getProperty(prov + "." + key), mutable.getProperty("jclouds." + key)),
                  notNull());
      } catch (NoSuchElementException e) {
         throw new NoSuchElementException(String.format("property %s.%s not present in properties: %s", prov, key, mutable.keySet()));
      } finally {
         mutable.remove(prov + "." + key);
         mutable.remove("jclouds." + key);
      }
   }

   public Injector buildInjector() {

      Properties unexpanded = currentStateToUnexpandedProperties();

      Set<String> keysToResolve = ImmutableSet.of(PROPERTY_IDENTITY, PROPERTY_CREDENTIAL, PROPERTY_ENDPOINT,
            PROPERTY_API, PROPERTY_API_VERSION, PROPERTY_BUILD_VERSION);

      Set<String> optionalKeys;
      if (credentialsSupplierOption.isPresent()) {
         optionalKeys = ImmutableSet.of(PROPERTY_IDENTITY, PROPERTY_CREDENTIAL);
      } else if (!apiMetadata.getCredentialName().isPresent()) {
         optionalKeys = ImmutableSet.of(PROPERTY_CREDENTIAL);
      } else {
         optionalKeys = ImmutableSet.of();
      }

      Properties resolved = resolveProperties(unexpanded, providerId, keysToResolve, optionalKeys);

      Properties expanded = new ExpandProperties().apply(resolved);

      Supplier<Credentials> credentialsSupplier = buildCredentialsSupplier(expanded);

      ProviderMetadata providerMetadata = new UpdateProviderMetadataFromProperties(apiMetadata, this.providerMetadata)
            .apply(expanded);

      // We use either the specified name (optional) or a hash of provider/api, endpoint, api version & identity. Hash
      // is used to be something readable.
      return buildInjector(name.or(String.valueOf(Objects.hashCode(providerMetadata.getId(),
            providerMetadata.getEndpoint(), providerMetadata.getApiMetadata().getVersion(), credentialsSupplier))),
            providerMetadata, credentialsSupplier, modules);
   }

   protected Supplier<Credentials> buildCredentialsSupplier(Properties expanded) {
      Credentials creds = new Credentials(getAndRemove(expanded, PROPERTY_IDENTITY), getAndRemove(expanded,
            PROPERTY_CREDENTIAL));

      Supplier<Credentials> credentialsSupplier;
      if (credentialsSupplierOption.isPresent()) {
         credentialsSupplier = credentialsSupplierOption.get();
      } else {
         credentialsSupplier = Suppliers.ofInstance(creds);
      }
      return credentialsSupplier;
   }

   private static String getAndRemove(Properties expanded, String key) {
      try {
         return expanded.getProperty(key);
      } finally {
         expanded.remove(key);
      }
   }
   
   private Properties currentStateToUnexpandedProperties() {
      Properties defaults = new Properties();
      putAllAsString(apiMetadata.getDefaultProperties(), defaults);
      defaults.setProperty(PROPERTY_PROVIDER, providerId);
      if (providerMetadata.isPresent()) {
         putAllAsString(providerMetadata.get().getDefaultProperties(), defaults);
         defaults.setProperty(PROPERTY_ISO3166_CODES, Joiner.on(',').join(providerMetadata.get().getIso3166Codes()));
      }
      if (endpoint.isPresent())
         defaults.setProperty(PROPERTY_ENDPOINT, endpoint.get());
      defaults.setProperty(PROPERTY_API, apiMetadata.getName());
      defaults.setProperty(PROPERTY_API_VERSION, apiVersion);
      defaults.setProperty(PROPERTY_BUILD_VERSION, buildVersion);
      if (identity.isPresent())
         defaults.setProperty(PROPERTY_IDENTITY, identity.get());
      if (credential != null)
         defaults.setProperty(PROPERTY_CREDENTIAL, credential);
      if (overrides.isPresent())
         putAllAsString(overrides.get(), defaults);
      putAllAsString(propertiesPrefixedWithJcloudsApiOrProviderId(getSystemProperties(), apiMetadata.getId(), providerId), defaults);
      return defaults;
   }

   private static void putAllAsString(Map<?, ?> source, Properties target) {
      for (Map.Entry<?, ?> entry : source.entrySet()) {
         target.setProperty(entry.getKey().toString(), entry.getValue().toString());
      }
   }

   @VisibleForTesting
   protected Properties getSystemProperties() {
      return System.getProperties();
   }

   public static Injector buildInjector(String name, ProviderMetadata providerMetadata, Supplier<Credentials> creds, List<Module> inputModules) {
      List<Module> modules = newArrayList();
      modules.addAll(inputModules);
      boolean apiModuleSpecifiedByUser = apiModulePresent(inputModules);
      Iterable<Module> defaultModules = ifSpecifiedByUserDontIncludeDefaultApiModule(
               providerMetadata.getApiMetadata(), apiModuleSpecifiedByUser);
      addAll(modules, defaultModules);
      addClientModuleIfNotPresent(providerMetadata.getApiMetadata(), modules);
      addRestContextBinding(providerMetadata.getApiMetadata(), modules);
      addLoggingModuleIfNotPresent(modules);
      addHttpModuleIfNeededAndNotPresent(modules);
      addExecutorServiceIfNotPresent(modules);
      addEventBusIfNotPresent(modules);
      addCredentialStoreIfNotPresent(modules);
      modules.add(new LifeCycleModule());
      modules.add(new BindProviderMetadataContextAndCredentials(providerMetadata, creds));
      modules.add(new BindNameToContext(name));
      Injector returnVal = Guice.createInjector(GUICE_STAGE, modules);
      returnVal.getInstance(ExecutionList.class).execute();
      return returnVal;
   }

   static Properties resolveProperties(Properties mutable, String providerId, Set<String> keys, Set<String> optionalKeys) throws NoSuchElementException {
      for (String key : keys) {
         String scopedProperty = Iterables.get(Splitter.on('.').split(key), 1);
         try {
            mutable.setProperty(key, searchPropertiesForProviderScopedProperty(mutable, providerId, scopedProperty));
         } catch (NoSuchElementException e) {
            if (!optionalKeys.contains(key))
               throw e;
         }
      }
      return mutable;
   }

   static void addRestContextBinding(ApiMetadata apiMetadata, List<Module> modules) {
      if (apiMetadata instanceof HttpApiMetadata) {
         try {
            modules
                  .add(new BindApiContextWithWildcardExtendsExplicitAndRawType(HttpApiMetadata.class.cast(apiMetadata)));
         } catch (IllegalArgumentException ignored) {

         }
      }
   }

   static Iterable<Module> ifSpecifiedByUserDontIncludeDefaultApiModule(ApiMetadata apiMetadata,
            boolean restModuleSpecifiedByUser) {
      Iterable<Module> defaultModules = transform(apiMetadata.getDefaultModules(),
               new Function<Class<? extends Module>, Module>() {

                  @Override
                  public Module apply(Class<? extends Module> arg0) {
                     try {
                        return arg0.getConstructor().newInstance();
                     } catch (InstantiationException e) {
                        throw propagate(e);
                     } catch (IllegalAccessException e) {
                        throw propagate(e);
                     } catch (InvocationTargetException e) {
                        throw propagate(e);
                     } catch (NoSuchMethodException e) {
                        throw propagate(e);
                     }
                  }

               });
      if (restModuleSpecifiedByUser)
         defaultModules = filter(defaultModules, not(configuresApi));
      return defaultModules;
   }

   @SuppressWarnings( { "unchecked" })
   static Map<String, Object> propertiesPrefixedWithJcloudsApiOrProviderId(Properties properties, String apiId,
            String providerId) {
      return filterKeys(Map.class.cast(properties), containsPattern("^(jclouds|" + providerId + "|" + apiId + ").*"));
   }

   @VisibleForTesting
   static void addLoggingModuleIfNotPresent(List<Module> modules) {
      if (!any(modules, instanceOf(LoggingModule.class)))
         modules.add(new JDKLoggingModule());
   }

   @VisibleForTesting
   static void addHttpModuleIfNeededAndNotPresent(List<Module> modules) {
      if (nothingConfiguresAnHttpService(modules))
         modules.add(new JavaUrlHttpCommandExecutorServiceModule());
   }

   static boolean nothingConfiguresAnHttpService(List<Module> modules) {
      return !any(modules, new Predicate<Module>() {
         public boolean apply(Module input) {
            return input.getClass().isAnnotationPresent(ConfiguresHttpCommandExecutorService.class);
         }

      });
   }

   @VisibleForTesting
   static void addClientModuleIfNotPresent(ApiMetadata apiMetadata, List<Module> modules) {
      if (!apiModulePresent(modules)) {
         addClientModule(apiMetadata, modules);
      }
   }
   private static boolean apiModulePresent(List<Module> modules) {
      return any(modules, configuresApi);
   }

   private static Predicate<Module> configuresApi = new Predicate<Module>() {
      public boolean apply(Module input) {
         return input.getClass().isAnnotationPresent(ConfiguresHttpApi.class);
      }

   };

   @SuppressWarnings({ "unchecked", "rawtypes" })
   static void addClientModule(ApiMetadata apiMetadata, List<Module> modules) {
      // TODO: move this up
      if (apiMetadata instanceof HttpApiMetadata) {
         HttpApiMetadata api = HttpApiMetadata.class.cast(apiMetadata);
         modules.add(new HttpApiModule(api.getApi()));
      } else {
         modules.add(new RestModule());
         // Minimally bind HttpClient so that Utils works.
         modules.add(new AbstractModule() {
            @Override public void configure() {
               bind(new TypeLiteral<Function<Invocation, Object>>() {
               }).to(InvokeHttpMethod.class);
               bindHttpApi(binder(), HttpClient.class);
            }
         });
      }
   }

   @VisibleForTesting
   static void addEventBusIfNotPresent(List<Module> modules) {
      if (!any(modules, new Predicate<Module>() {
         public boolean apply(Module input) {
            return input.getClass().isAnnotationPresent(ConfiguresEventBus.class);
         }
      }

      )) {
         modules.add(new EventBusModule());
      }
   }

   @VisibleForTesting
   static void addExecutorServiceIfNotPresent(List<Module> modules) {
      if (!any(modules, new Predicate<Module>() {
         public boolean apply(Module input) {
            return input.getClass().isAnnotationPresent(ConfiguresExecutorService.class);
         }
      }

      )) {
         if (any(modules, new Predicate<Module>() {
            public boolean apply(Module input) {
               return input.getClass().isAnnotationPresent(SingleThreaded.class);
            }
         })) {
            modules.add(new ExecutorServiceModule(newDirectExecutorService()));
         } else {
            modules.add(new ExecutorServiceModule());
         }
      }
   }

   @VisibleForTesting
   static void addCredentialStoreIfNotPresent(List<Module> modules) {
      if (!any(modules, new Predicate<Module>() {
         public boolean apply(Module input) {
            return input.getClass().isAnnotationPresent(ConfiguresCredentialStore.class);
         }
      }

      )) {
         modules.add(new CredentialStoreModule());
      }

   }

   /**
    * Builds the base context for this api. Note that this may be of type {@link Closer}, if nothing
    * else was configured via {@link ApiMetadata#getContext()}. Typically, the type returned is
    * {@link ApiContext}
    * 
    * @see ApiMetadata#getContext()
    * @see #build(TypeToken)
    */
   @SuppressWarnings("unchecked")
   public <C extends Context> C build() {
      return (C) build(apiMetadata.getContext());
   }

   /**
    * @see #buildView(Class)
    */
   public <V extends View> V build(Class<V> viewType) {
     return buildView(checkNotNull(viewType, "viewType"));
   }

   /**
    * @see #buildView(TypeToken)
    */
   public <V extends View> V buildView(Class<V> viewType) {
     return buildView(typeToken(viewType));
   }
   
   /**
    * this will build any {@link ApiMetadata#getViews() view} supported by the ApiMetadata.
    * 
    * ex. {@code builder.build(BlobStoreContext.class) } will work, if {@code TypeToken<BlobStore>}
    * is a configured {@link ApiMetadata#getViews() view} of this api.
    * 
    */
   @SuppressWarnings("unchecked")
   public <V extends View> V buildView(TypeToken<V> viewType) {
      TypeToken<V> returnType;
      try {
         returnType = (TypeToken<V>) Apis.findView(apiMetadata, checkNotNull(viewType, "viewType"));
      } catch (NoSuchElementException e) {
         throw new IllegalArgumentException(String.format(
                  "api %s not wrappable as %s; context: %s, views: %s", apiMetadata,
                  viewType, apiMetadata.getContext(), apiMetadata.getViews()));
      }
      return (V) buildInjector().getInstance(Key.get(TypeLiteral.get(returnType.getType())));
   }

   /**
    * this will build the {@link ApiMetadata#getContext() context} supported by the current ApiMetadata.
    */
   @SuppressWarnings("unchecked")
   public <C extends Context> C build(TypeToken<C> contextType) {
      TypeToken<C> returnType = null;
      if (TypeTokenUtils.isSupertypeOf(contextType, apiMetadata.getContext()))
         returnType = (TypeToken<C>) apiMetadata.getContext();
      else
         throw new IllegalArgumentException(String.format("api %s not assignable from %s; context: %s", apiMetadata,
                  contextType, apiMetadata.getContext()));
      return (C) buildInjector().getInstance(Key.get(TypeLiteral.get(returnType.getType())));
   }

   /**
    * This will return the top-level interface for the api or provider.
    * 
    * Ex. 
    * <pre>
    * api = ContextBuilder.newBuilder("openstack-nova")
    *                     ... 
    *                     .buildApi(NovaApi.class);
    *</pre>
    */
   public <A extends Closeable> A buildApi(Class<A> api) {
      return buildApi(typeToken(api));
   }

   /**
    * like {@link #buildApi(Class)} but permits a type-token for convenience.
    */
   @SuppressWarnings("unchecked")
   public <A extends Closeable> A buildApi(TypeToken<A> apiType) {
      return (A) buildInjector().getInstance(Key.get(TypeLiteral.get(apiType.getType())));
   }

   public ApiMetadata getApiMetadata() {
      return apiMetadata;
   }
}
