code: <T> T build(ConfigurationProvider<T> configurationProvider)
      {
          requireNonNull(configurationProvider, "configurationProvider");
          registerConfigurationProvider(configurationProvider, Optional.empty());
  
          // check for a prebuilt instance
          T instance = getCachedInstance(configurationProvider);
          if (instance != null) {
              return instance;
          }
  
          ConfigurationBinding<T> configurationBinding = configurationProvider.getConfigurationBinding();
          ConfigurationHolder<T> holder = build(configurationBinding.getConfigClass(), configurationBinding.getPrefix(), getConfigDefaults(configurationBinding.getKey()));
          instance = holder.getInstance();
  
          // inform caller about warnings
          if (warningsMonitor != null) {
              for (Message message : holder.getProblems().getWarnings()) {
                  warningsMonitor.onWarning(message.toString());
              }
          }
  
          // add to instance cache
          T existingValue = putCachedInstance(configurationProvider, instance);
          // if key was already associated with a value, there was a
          // creation race and we lost. Just use the winners' instance;
          if (existingValue != null) {
              return existingValue;
          }
          return instance;
      }
docs: This is used by the configuration provider