// Path: src/main/java/pl/wavesoftware/eid/api/Configuration.java
// public interface Configuration {
//     /**
//      * Gets a Eid formatter
//      *
//      * @return a formatter of Eid
//      */
//     Formatter getFormatter();
// 
//     /**
//      * Gets a Eid unique ID generator
//      *
//      * @return unique ID generator
//      */
//     UniqueIdGenerator getIdGenerator();
// 
//     /**
//      * Gets a Eid validator if set. Returns null if validator wasn't configured.
//      *
//      * @return an Eid validator, or null
//      */
//     @Nullable
//     Validator getValidator();
// 
//     /**
//      * Gets a locale to be used when formatting texts. Returns null if locale
//      * isn't set.
//      *
//      * @return a locale to be used when formatting texts, or null
//      */
//     @Nullable
//     Locale getLocale();
// 
//     /**
//      * Gets a time zone to be used when formatting texts. Returns null if time
//      * zone isn't set.
//      *
//      * @return a time zone to be used when formatting texts, or null
//      */
//     @Nullable
//     TimeZone getTimeZone();
// }
// 
// Path: src/main/java/pl/wavesoftware/eid/api/ConfigurationBuilder.java
// public interface ConfigurationBuilder {
// 
//     /**
//      * Configures a unique ID generator used by Eid objects to generate unique
//      * part of Eid number.
//      *
//      * @param generator a generator of unique ID
//      * @return a self reference for ease of use
//      */
//     ConfigurationBuilder uniqueIdGenerator(UniqueIdGenerator generator);
// 
//     /**
//      * Configures a formatter to be used by Eid numbers.
//      *
//      * @param formatter a formatter to be used by Eid formatting and displaying
//      * @return a self reference for ease of use
//      */
//     ConfigurationBuilder formatter(Formatter formatter);
// 
//     /**
//      * Sets a locale to be used when formatting texts. If not set default system
//      * locale will be used (platform specific). See {@link Locale#getDefault()}.
//      *
//      * @param locale a locale to be used, if {@code null} was given default
//      *               locale will be used
//      * @return a self reference for ease of use
//      * @see Locale#getDefault()
//      */
//     ConfigurationBuilder locale(@Nullable Locale locale);
// 
//     /**
//      * Sets a time zone to be used when formatting texts. If not set, default
//      * system time zone will be used (platform specific). See
//      * {@link TimeZone#getDefault()}.
//      *
//      * @param zone a time zone to be used, if {@code null} was given default
//      *             time zone will be used
//      * @return a self reference for ease of use
//      * @see TimeZone#getDefault()
//      */
//     ConfigurationBuilder timezone(@Nullable TimeZone zone);
// 
//     /**
//      * Configures a validator that will be called on each Eid number. By
//      * default, there is no validator configured for maximum speed. Using this
//      * validator you can enforce a standardization of Eid numbers.
//      *
//      * @param validator a validator to be used, if {@code null} was given
//      *                  validator will not be used.
//      * @return a self reference for ease of use
//      */
//     ConfigurationBuilder validator(@Nullable Validator validator);
// 
//     /**
//      * Gets an object that is a future configuration, to be used to cross
//      * configure elements of the configuration.
//      * <p>
//      * It might throw exceptions if configuration isn't completed so use it
//      * only if configuration is done.
//      *
//      * @return a future configuration
//      */
//     Configuration getFutureConfiguration();
// }
// 
// Path: src/main/java/pl/wavesoftware/eid/api/ConfigurationSystem.java
// public interface ConfigurationSystem {
//     /**
//      * Get a configuration object
//      *
//      * @return a configuration object
//      */
//     Configuration getConfiguration();
// 
//     /**
//      * Configures an Eid library programmatically. Note, that method returns a
//      * configurator that can be used to restore configuration to the state
//      * before you invoke this configuration method.
//      *
//      * @param configurator a configurator to use to configure Eid library
//      * @return a reference to a configurator that can be used to restore
//      * previous configuration
//      */
//     Configurator configure(Configurator configurator);
// }
// 
// Path: src/main/java/pl/wavesoftware/eid/api/Configurator.java
// public interface Configurator {
// 
//     /**
//      * Configures an Eid configuration.
//      *
//      * @param configuration a configuration to be configured
//      */
//     void configure(ConfigurationBuilder configuration);
// }
// 
// Path: src/main/java/pl/wavesoftware/eid/api/Supplier.java
// public interface Supplier<T> {
//     /**
//      * Gets an object
//      *
//      * @return an object
//      */
//     T get();
// }


import pl.wavesoftware.eid.api.Configuration;
import pl.wavesoftware.eid.api.ConfigurationBuilder;
import pl.wavesoftware.eid.api.ConfigurationSystem;
import pl.wavesoftware.eid.api.Configurator;
import pl.wavesoftware.eid.api.Supplier;
import java.util.ServiceLoader;
        private static MutableConfiguration loadConfiguration() {
            MutableConfiguration mutableConfiguration = new ConfigurationImpl();
            new DefaultConfigurator().configure(mutableConfiguration);
            ServiceLoader<Configurator> configurators =
                ServiceLoader.load(Configurator.class);

            for (Configurator configurator : configurators) {
                configurator.configure(mutableConfiguration);
            }
            return mutableConfiguration;
        }
    }

    private static final class RestoreConfigurator
        implements Configurator {
        private final MutableConfiguration configuration;

        RestoreConfigurator(MutableConfiguration configuration) {
            this.configuration = configuration;
        }

        /*
        Suppress is for forcing nullable values to non null methods
        for copy constructor.
         */
        @SuppressWarnings("ConstantConditions")
        @Override
        public void configure(ConfigurationBuilder builder) {
            builder.formatter(configuration.getFormatter())
                .uniqueIdGenerator(configuration.getIdGenerator())
// Path: src/main/java/pl/wavesoftware/eid/api/Configuration.java
// public interface Configuration {
//     /**
//      * Gets a Eid formatter
//      *
//      * @return a formatter of Eid
//      */
//     Formatter getFormatter();
// 
//     /**
//      * Gets a Eid unique ID generator
//      *
//      * @return unique ID generator
//      */
//     UniqueIdGenerator getIdGenerator();
// 
//     /**
//      * Gets a Eid validator if set. Returns null if validator wasn't configured.
//      *
//      * @return an Eid validator, or null
//      */
//     @Nullable
//     Validator getValidator();
// 
//     /**
//      * Gets a locale to be used when formatting texts. Returns null if locale
//      * isn't set.
//      *
//      * @return a locale to be used when formatting texts, or null
//      */
//     @Nullable
//     Locale getLocale();
// 
//     /**
//      * Gets a time zone to be used when formatting texts. Returns null if time
//      * zone isn't set.
//      *
//      * @return a time zone to be used when formatting texts, or null
//      */
//     @Nullable
//     TimeZone getTimeZone();
// }
// 
// Path: src/main/java/pl/wavesoftware/eid/api/ConfigurationBuilder.java
// public interface ConfigurationBuilder {
// 
//     /**
//      * Configures a unique ID generator used by Eid objects to generate unique
//      * part of Eid number.
//      *
//      * @param generator a generator of unique ID
//      * @return a self reference for ease of use
//      */
//     ConfigurationBuilder uniqueIdGenerator(UniqueIdGenerator generator);
// 
//     /**
//      * Configures a formatter to be used by Eid numbers.
//      *
//      * @param formatter a formatter to be used by Eid formatting and displaying
//      * @return a self reference for ease of use
//      */
//     ConfigurationBuilder formatter(Formatter formatter);
// 
//     /**
//      * Sets a locale to be used when formatting texts. If not set default system
//      * locale will be used (platform specific). See {@link Locale#getDefault()}.
//      *
//      * @param locale a locale to be used, if {@code null} was given default
//      *               locale will be used
//      * @return a self reference for ease of use
//      * @see Locale#getDefault()
//      */
//     ConfigurationBuilder locale(@Nullable Locale locale);
// 
//     /**
//      * Sets a time zone to be used when formatting texts. If not set, default
//      * system time zone will be used (platform specific). See
//      * {@link TimeZone#getDefault()}.
//      *
//      * @param zone a time zone to be used, if {@code null} was given default
//      *             time zone will be used
//      * @return a self reference for ease of use
//      * @see TimeZone#getDefault()
//      */
//     ConfigurationBuilder timezone(@Nullable TimeZone zone);
// 
//     /**
//      * Configures a validator that will be called on each Eid number. By
//      * default, there is no validator configured for maximum speed. Using this
//      * validator you can enforce a standardization of Eid numbers.
//      *
//      * @param validator a validator to be used, if {@code null} was given
//      *                  validator will not be used.
//      * @return a self reference for ease of use
//      */
//     ConfigurationBuilder validator(@Nullable Validator validator);
// 
//     /**
//      * Gets an object that is a future configuration, to be used to cross
//      * configure elements of the configuration.
//      * <p>
//      * It might throw exceptions if configuration isn't completed so use it
//      * only if configuration is done.
//      *
//      * @return a future configuration
//      */
//     Configuration getFutureConfiguration();
// }
// 
// Path: src/main/java/pl/wavesoftware/eid/api/ConfigurationSystem.java
// public interface ConfigurationSystem {
//     /**
//      * Get a configuration object
//      *
//      * @return a configuration object
//      */
//     Configuration getConfiguration();
// 
//     /**
//      * Configures an Eid library programmatically. Note, that method returns a
//      * configurator that can be used to restore configuration to the state
//      * before you invoke this configuration method.
//      *
//      * @param configurator a configurator to use to configure Eid library
//      * @return a reference to a configurator that can be used to restore
//      * previous configuration
//      */
//     Configurator configure(Configurator configurator);
// }
// 
// Path: src/main/java/pl/wavesoftware/eid/api/Configurator.java
// public interface Configurator {
// 
//     /**
//      * Configures an Eid configuration.
//      *
//      * @param configuration a configuration to be configured
//      */
//     void configure(ConfigurationBuilder configuration);
// }
// 
// Path: src/main/java/pl/wavesoftware/eid/api/Supplier.java
// public interface Supplier<T> {
//     /**
//      * Gets an object
//      *
//      * @return an object
//      */
//     T get();
// }


// Path: src/main/java/pl/wavesoftware/eid/impl/ConfigurationSystemImpl.java
import pl.wavesoftware.eid.api.Configuration;
import pl.wavesoftware.eid.api.ConfigurationBuilder;
import pl.wavesoftware.eid.api.ConfigurationSystem;
import pl.wavesoftware.eid.api.Configurator;
import pl.wavesoftware.eid.api.Supplier;
import java.util.ServiceLoader;

        private static MutableConfiguration loadConfiguration() {
            MutableConfiguration mutableConfiguration = new ConfigurationImpl();
            new DefaultConfigurator().configure(mutableConfiguration);
            ServiceLoader<Configurator> configurators =
                ServiceLoader.load(Configurator.class);

            for (Configurator configurator : configurators) {
                configurator.configure(mutableConfiguration);
            }
            return mutableConfiguration;
        }
    }

    private static final class RestoreConfigurator
        implements Configurator {
        private final MutableConfiguration configuration;

        RestoreConfigurator(MutableConfiguration configuration) {
            this.configuration = configuration;
        }

        /*
        Suppress is for forcing nullable values to non null methods
        for copy constructor.
         */
        @SuppressWarnings("ConstantConditions")
        @Override
        public void configure(ConfigurationBuilder builder) {
            builder.formatter(configuration.getFormatter())
                .uniqueIdGenerator(configuration.getIdGenerator())
                .validator(configuration.getValidator())