package org.realityforge.arez.api2;

final class ArezConfig
{
  private static final Provider c_provider = createProvider();

  private ArezConfig()
  {
  }

  static boolean verboseErrorMessages()
  {
    return getProvider().verboseErrorMessages();
  }

  static boolean checkInvariants()
  {
    return getProvider().checkInvariants();
  }

  static boolean enableNames()
  {
    return getProvider().enableNames();
  }

  static Provider getProvider()
  {
    return c_provider;
  }

  private static Provider createProvider()
  {
    final boolean verboseErrorMessages = "true".equals( System.getProperty( "arez.verbose_error_messages", "false" ) );
    final boolean checkInvariants = "true".equals( System.getProperty( "arez.check_invariants", "false" ) );
    final boolean enableNames = "true".equals( System.getProperty( "arez.enable_names", "false" ) );
    return System.getProperty( "arez.dynamic_provider", "false" ).equals( "true" ) ?
           new DynamicProvider( verboseErrorMessages, checkInvariants, enableNames ) :
           new StaticProvider( verboseErrorMessages, checkInvariants, enableNames );
  }

  private interface Provider
  {
    boolean verboseErrorMessages();

    boolean checkInvariants();

    boolean enableNames();
  }

  static final class DynamicProvider
    implements Provider
  {
    private boolean _verboseErrorMessages;
    private boolean _checkInvariants;
    private boolean _enableNames;

    DynamicProvider( final boolean verboseErrorMessages,
                     final boolean checkInvariants,
                     final boolean enableNames )
    {
      _verboseErrorMessages = verboseErrorMessages;
      _checkInvariants = checkInvariants;
      _enableNames = enableNames;
    }

    void setVerboseErrorMessages( final boolean verboseErrorMessages )
    {
      _verboseErrorMessages = verboseErrorMessages;
    }

    void setCheckInvariants( final boolean checkInvariants )
    {
      _checkInvariants = checkInvariants;
    }

    void setEnableNames( final boolean enableNames )
    {
      _enableNames = enableNames;
    }

    @Override
    public boolean verboseErrorMessages()
    {
      return _verboseErrorMessages;
    }

    @Override
    public boolean checkInvariants()
    {
      return _checkInvariants;
    }

    @Override
    public boolean enableNames()
    {
      return _enableNames;
    }
  }

  private static final class StaticProvider
    implements Provider
  {
    private final boolean _verboseErrorMessages;
    private final boolean _checkInvariants;
    private final boolean _enableNames;

    StaticProvider( final boolean verboseErrorMessages,
                    final boolean checkInvariants,
                    final boolean enableNames )
    {
      _verboseErrorMessages = verboseErrorMessages;
      _checkInvariants = checkInvariants;
      _enableNames = enableNames;
    }

    @Override
    public boolean verboseErrorMessages()
    {
      return _verboseErrorMessages;
    }

    @Override
    public boolean checkInvariants()
    {
      return _checkInvariants;
    }

    @Override
    public boolean enableNames()
    {
      return _enableNames;
    }
  }
}

@@ -30,16 +30,138 @@
 .api2;%0A%0A
+import org.jetbrains.annotations.TestOnly;%0A%0A/**%0A * Location of all compile time configuration settings for framework.%0A */%0A
 final cl
@@ -1248,139 +1248,580 @@
 %0A%0A  
-private interface Provider%0A  %7B%0A    boolean verboseErrorMessages();%0A%0A    boolean checkInvariants();%0A%0A    boolean enableNames();%0A  %7D%0A
+/**%0A   * Abstraction used to provide configuration settings for Arez system.%0A   * This abstraction is used to allow converting configuration to compile time%0A   * constants during GWT and/or closure compiler phases and thus allow elimination of%0A   * code during production variants of the runtime.%0A   */%0A  private interface Provider%0A  %7B%0A    boolean verboseErrorMessages();%0A%0A    boolean checkInvariants();%0A%0A    boolean enableNames();%0A  %7D%0A%0A  /**%0A   * A provider implementation that allows changing of values at runtime.%0A   * Only really used during testing.%0A   */%0A  @TestOnly
 %0A  s
@@ -2936,24 +2936,264 @@
 %0A    %7D%0A  %7D%0A%0A
+  /**%0A   * The normal provider implementation for statically defining properties.%0A   * Properties do not change at runtime and can be used by GWT and closure compiler%0A   * to set values at compile time and eliminate dead/unused code.%0A   */%0A
   private st

Add some basic documentation