001/**
002 * Copyright (c) 2012, 2014, Credit Suisse (Anatole Tresch), Werner Keil and others by the @author tag.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016package org.javamoney.moneta.spi;
017
018import java.io.IOException;
019import java.io.InputStream;
020import java.net.URI;
021import java.util.Map;
022import java.util.Set;
023import java.util.concurrent.Future;
024
025/**
026 * This interface defines an updatable/reloadable data cache for providing data
027 * sources that are updatable by any remote {@link URI}s. Initial version are
028 * loaded from the classpath, or other fallback URL.
029 * <p>
030 * This class is used for managing/updating/reloading of data sources, e.g. data
031 * streams for exchange rates, additional currency data, historical currency
032 * data and so on.
033 * <p>
034 * Note: this class is implementation specific and not part of the official
035 * JSR's API.
036 *
037 * @author Anatole Tresch
038 */
039public interface LoaderService {
040
041    /**
042     * Platform RI: The update policy defines how and when the
043     * {@link LoaderService} tries to update the local cache with newest version of
044     * the registered data resources, accessing the configured remote
045     * {@link URI}s. By default no remote connections are done (
046     * {@link UpdatePolicy#NEVER} ).
047     *
048     * @author Anatole Tresch
049     */
050    public enum UpdatePolicy {
051        /**
052         * The resource will never be updated from remote, only the fallback URL
053         * will be evaluated.
054         */
055        NEVER,
056        /**
057         * The resource will be loaded automatically from remote only once on
058         * startup.
059         */
060        ONSTARTUP,
061        /**
062         * The resource will be loaded automatically from remote only once, when
063         * accessed the first time.
064         */
065        LAZY,
066        /**
067         * The resource should be regularly reloaded based on a schedule.
068         */
069        SCHEDULED
070    }
071
072    /**
073     * Callback that can be registered to be informed, when a data item was
074     * loaded/updated or resetToFallback.
075     *
076     * @author Anatole Tresch
077     * @see #resetData(String)
078     * @see #loadData(String)
079     */
080    interface LoaderListener {
081        /**
082         * Callback called from the {@link LoaderService}, when new data was
083         * read for a given data item.
084         *
085         * @param resourceId the resource id
086         * @param is         the input stream for accessing the data
087         */
088        void newDataLoaded(String resourceId, InputStream is);
089    }
090
091    /**
092     * Programmatically registers a remote resource {@code resourceLocation},
093     * backed up by a classpath resource {@code backupResource}, reachable as
094     * {@code dataId}.
095     *
096     *resourceId        The unique identifier of the resource that must also be used
097     *                          for accessing the resource, not {@code null}.
098     *resourceLocations The remote resource locations, not {@code null}.
099     *backupResource    The backup resource location in the classpath, not
100     *                          {@code null}.
101     *loaderListener    An (optional) LoaderListener to be registered.
102     */
103    void registerData(LoadDataInformation loadDataInformation);
104
105    /**
106     * Programmatically registers a remote resource {@code resourceLocation},
107     * backed up by a classpath resource {@code backupResource}, reachable as
108     * {@code dataId} and (synchronously) loads the data.
109     *
110     *resourceId        The unique identifier of the resource that must also be used
111     *                          for accessing the resource, not {@code null}.
112     * resourceLocations The remote resource locations, not {@code null}.
113     *backupResource    The backup resource location in the classpath, not
114     *                          {@code null}.
115     *loaderListener    An (optional) LoaderListener to be registered.
116     */
117    void registerAndLoadData(LoadDataInformation loadDataInformation);
118
119    @Deprecated
120    void registerAndLoadData(String resourceId, UpdatePolicy updatePolicy,
121                             Map<String, String> properties, LoaderListener loaderListener,
122                             URI backupResource,
123                             URI... resourceLocations);
124
125    @Deprecated
126    void registerData(String resourceId, UpdatePolicy updatePolicy,
127                      Map<String, String> properties, LoaderListener loaderListener,
128                      URI backupResource,
129                      URI... resourceLocations);
130
131    /**
132     * Get the {@link UpdatePolicy} in place for the given dataId.
133     *
134     * @param resourceId the resource's id, not {@code null}
135     * @return the {@link UpdatePolicy}, not {@code null}
136     * @throws IllegalArgumentException if no such dataId is available.
137     */
138    UpdatePolicy getUpdatePolicy(String resourceId);
139
140    /**
141     * Get the update configuration for the given dataId.
142     *
143     * @param resourceId the dataId, not {@code null}
144     * @return the update configuration properties, not {@code null}
145     * @throws IllegalArgumentException if no such dataId is available.
146     */
147    Map<String, String> getUpdateConfiguration(String resourceId);
148
149    /**
150     * Add a {@link LoaderListener} callback that is informed when a data
151     * resource was update from remote, or resetToFallback. Passing an empty String or
152     * {@code null} sa {@code dataId} allows to register a listener for all data
153     * resources registered. {@link #loadData(String)}
154     * {@link #resetData(String)}
155     *
156     * @param resourceIds The unique identifiers of the resource, not {@code null}.
157     * @param l           The listener to be added
158     * @see #removeLoaderListener(LoaderListener, String...)
159     */
160    void addLoaderListener(LoaderListener l, String... resourceIds);
161
162    /**
163     * Remove a registered {@link LoaderListener} callback.
164     *
165     * @param resourceIds The unique identifier of the resource, not {@code null}.
166     * @param l           The listener to be removed
167     * @see #addLoaderListener(LoaderListener, String...)
168     */
169    void removeLoaderListener(LoaderListener l, String... resourceIds);
170
171    /**
172     * Allows to check if a data resource with the given dataId is registered.
173     *
174     * @param resourceId The unique identifier of the resource, not {@code null}.
175     * @return {@code true}, if such a data resource is registered.
176     */
177    boolean isResourceRegistered(String resourceId);
178
179    /**
180     * Get a {@link Set} of all registered data resource identifiers.
181     *
182     * @return a {@link Set} of all registered data resource identifiers, never
183     * {@code null}.
184     */
185    Set<String> getResourceIds();
186
187    /**
188     * Access the input stream of the given data resource.
189     * <p>This method is called by the modules that depend on the given data
190     * item. The method always returns the most current data, either from the
191     * classpath or the local cache, depending which flavors are available
192     * and recently updated.</p><p>
193     * The method must be thread safe and can be accessed in parallel. Hereby it
194     * is possible that, when an intermediate update of the data by update
195     * occurs, that different input stream content is returned.
196     *
197     * @param resourceId The unique identifier of the resource, not {@code null}.
198     * @return The {@link InputStream} for reading the data.
199     * @throws IOException if a problem occurred.
200     */
201    InputStream getData(String resourceId) throws IOException;
202
203    /**
204     * Explicitly triggers the loading of the registered data, regardless of its
205     * current {@link UpdatePolicy} configured, from the fallback/local
206     * resource.
207     *
208     * @param resourceId The unique identifier of the resource, not {@code null}.
209     * @return true if load was successful.
210     */
211    boolean loadDataLocal(String resourceId);
212
213    /**
214     * Explicitly triggers the remote loading of the registered data, regardless
215     * of its current {@link UpdatePolicy} configured.
216     *
217     * @param resourceId The unique identifier of the resource, not {@code null}.
218     * @return true if load was successful.
219     * @throws IOException if a problem occurred.
220     */
221    boolean loadData(String resourceId) throws IOException;
222
223    /**
224     * Explicitly asynchronously triggers the remote loading of the registered
225     * data, regardless of its current {@link UpdatePolicy} configured.
226     *
227     * @param resourceId The unique identifier of the resource, not {@code null}.
228     * @return the Future of the load task started, returns Boolean.TRUE if the
229     * load was successful (either from remote or from the fallback
230     * resource).
231     */
232    Future<Boolean> loadDataAsync(String resourceId);
233
234    /**
235     * Explicitly triggers the resetToFallback (loading of the registered data from the
236     * classpath backup resource).
237     *
238     * @param resourceId The unique identifier of the resource, not {@code null}.
239     * @throws IOException if a problem occurred.
240     */
241    void resetData(String resourceId) throws IOException;
242
243}