001package jmri.spi;
002
003import java.util.Collection;
004import java.util.List;
005import javax.annotation.Nonnull;
006import jmri.profile.Profile;
007import jmri.util.prefs.InitializationException;
008
009/**
010 * An API for Java Service Providers that manage preferences within JMRI. It is
011 * strongly recommended that PreferencesManagers use
012 * {@link jmri.util.prefs.JmriConfigurationProvider} or
013 * {@link jmri.util.prefs.JmriPreferencesProvider} to store preferences.
014 * <p>
015 * PreferencesManagers must provide a default public constructor, but must also
016 * not perform any initialization until
017 * {@link #initialize(jmri.profile.Profile)} is called as the PreferencesManager
018 * may be constructed before the {@link jmri.profile.Profile} is known.
019 * <p>
020 * {@link jmri.util.prefs.AbstractPreferencesManager} provides an abstract
021 * implementation that is ready to extend.
022 *
023 * @see jmri.util.prefs.AbstractPreferencesManager
024 * @author Randall Wood 2015, 2019
025 */
026public interface PreferencesManager extends JmriServiceProviderInterface {
027
028    /**
029     * Initialize the PreferencesManager with preferences associated with the
030     * provided Profile.
031     * <p>
032     * Implementing classes should throw an InitializationException with a user
033     * readable localized message, since it most likely be displayed to the
034     * user. Implementing classes will still want to ensure that
035     * {@link #isInitialized(jmri.profile.Profile)} or
036     * {@link #isInitializedWithExceptions(jmri.profile.Profile)} return true if
037     * throwing an InitializationException to ensure that the provider is not
038     * repeatedly initialized.
039     *
040     * @param profile the configuration profile used for this initialization;
041     *                may be null to initialize for this user regardless of
042     *                profile
043     * @throws InitializationException if the user needs to be notified of an
044     *                                 issue that prevents regular use of the
045     *                                 application
046     */
047    void initialize(Profile profile) throws InitializationException;
048
049    /**
050     * Test if the PreferencesManager is initialized without errors for the
051     * provided Profile. Note that although both this method and
052     * {@link #isInitializedWithExceptions(jmri.profile.Profile)} can be false,
053     * if isInitializedWithExceptions(Profile) returns true, this method must
054     * return false.
055     *
056     * @param profile the configuration profile to test against; may be null to
057     *                test for exceptions thrown when initializing for this user
058     *                regardless of profile
059     * @return true if the provider is initialized without exceptions
060     */
061    boolean isInitialized(Profile profile);
062
063    /**
064     * Test if the PreferencesManager is initialized, but threw an
065     * {@link InitializationException} during initialization, for the provided
066     * Profile. Note that although both this method and
067     * {@link #isInitialized(jmri.profile.Profile)} can be false, if
068     * isInitialized(Profile) returns true, this method must return false.
069     *
070     * @param profile the configuration profile to test against; may be null to
071     *                test for exceptions thrown when initializing for this user
072     *                regardless of profile
073     * @return true if the provide is initialized with exceptions
074     */
075    boolean isInitializedWithExceptions(Profile profile);
076
077    /**
078     * Get the set of exceptions thrown during initialization for the provided
079     * Profile.
080     *
081     * @param profile the configuration profile to test against; may be null to
082     *                test for exceptions thrown when initializing for this user
083     *                regardless of profile
084     * @return A list of exceptions. If there are no exceptions, return an empty
085     *         set instead of null.
086     */
087    @Nonnull
088    List<Exception> getInitializationExceptions(Profile profile);
089
090    /**
091     * Get the set of PreferencesManagers that must be initialized prior to
092     * initializing this PreferencesManager. It is generally preferable to
093     * require an Interface or an abstract Class instead of a concrete Class,
094     * since that allows all (or any) concrete implementations of the required
095     * class to be initialized to provide required services for the requiring
096     * PreferencesManager instance.
097     * <p>
098     * Note that for any set of PreferencesManagers with the same requirements,
099     * or with a circular dependency between each other, the order in which the
100     * PreferencesManagers in that set are initialized should be considered
101     * non-deterministic.
102     *
103     * @return A set or list of classes. If there are no dependencies, return an
104     *         empty set instead of null.
105     */
106    @Nonnull
107    Collection<Class<? extends PreferencesManager>> getRequires();
108
109    /**
110     * Get the set of Classes that this PreferencesManager can be registered as
111     * a provider of in the {@link jmri.InstanceManager}.
112     *
113     * @return A set or list of classes. If this PreferencesManager provides an
114     *         instance of no other Interfaces or abstract Classes than
115     *         PreferencesManager, return an empty set instead of null.
116     */
117    @Nonnull
118    Iterable<Class<?>> getProvides();
119
120    /**
121     * Save the preferences that this provider manages for the provided Profile.
122     *
123     * @param profile the profile associated with the preferences to save; may
124     *                be null to save preferences that apply to the current user
125     *                regardless of profile
126     */
127    void savePreferences(Profile profile);
128
129}