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    public static 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        public 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     * @param resourceId        The unique identifier of the resource that must also be used
097     *                          for accessing the resource, not {@code null}.
098     * @param resourceLocations The remote resource locations, not {@code null}.
099     * @param backupResource    The backup resource location in the classpath, not
100     *                          {@code null}.
101     * @param loaderListener    An (optional) LoaderListener to be registered.
102     */
103    public void registerData(String resourceId, UpdatePolicy updatePolicy,
104                             Map<String, String> properties, LoaderListener loaderListener,
105                             URI backupResource,
106                             URI... resourceLocations);
107
108    /**
109     * Programmatically registers a remote resource {@code resourceLocation},
110     * backed up by a classpath resource {@code backupResource}, reachable as
111     * {@code dataId} and (synchronously) loads the data.
112     *
113     * @param resourceId        The unique identifier of the resource that must also be used
114     *                          for accessing the resource, not {@code null}.
115     * @param resourceLocations The remote resource locations, not {@code null}.
116     * @param backupResource    The backup resource location in the classpath, not
117     *                          {@code null}.
118     * @param loaderListener    An (optional) LoaderListener to be registered.
119     */
120    public void registerAndLoadData(String resourceId, UpdatePolicy updatePolicy,
121                                    Map<String, String> properties, LoaderListener loaderListener,
122                                    URI backupResource,
123                                    URI... resourceLocations);
124
125    /**
126     * Get the {@link UpdatePolicy} in place for the given dataId.
127     *
128     * @param resourceId the resource's id, not {@code null}
129     * @return the {@link UpdatePolicy}, not {@code null}
130     * @throws IllegalArgumentException if no such dataId is available.
131     */
132    public UpdatePolicy getUpdatePolicy(String resourceId);
133
134    /**
135     * Get the update configuration for the given dataId.
136     *
137     * @param resourceId the dataId, not {@code null}
138     * @return the update configuration properties, not {@code null}
139     * @throws IllegalArgumentException if no such dataId is available.
140     */
141    public Map<String, String> getUpdateConfiguration(String resourceId);
142
143    /**
144     * Add a {@link LoaderListener} callback that is informed when a data
145     * resource was update from remote, or resetToFallback. Passing an empty String or
146     * {@code null} sa {@code dataId} allows to register a listener for all data
147     * resources registered. {@link #loadData(String)}
148     * {@link #resetData(String)}
149     *
150     * @param resourceIds The unique identifiers of the resource, not {@code null}.
151     * @param l           The listener to be added
152     * @see #removeLoaderListener(LoaderListener, String...)
153     */
154    public void addLoaderListener(LoaderListener l, String... resourceIds);
155
156    /**
157     * Remove a registered {@link LoaderListener} callback.
158     *
159     * @param resourceIds The unique identifier of the resource, not {@code null}.
160     * @param l           The listener to be removed
161     * @see #addLoaderListener(LoaderListener, String...)
162     */
163    public void removeLoaderListener(LoaderListener l, String... resourceIds);
164
165    /**
166     * Allows to check if a data resource with the given dataId is registered.
167     *
168     * @param resourceId The unique identifier of the resource, not {@code null}.
169     * @return {@code true}, if such a data resource is registered.
170     */
171    public boolean isResourceRegistered(String resourceId);
172
173    /**
174     * Get a {@link Set} of all registered data resource identifiers.
175     *
176     * @return a {@link Set} of all registered data resource identifiers, never
177     * {@code null}.
178     */
179    public Set<String> getResourceIds();
180
181    /**
182     * Access the input stream of the given data resource.
183     * <p>This method is called by the modules that depend on the given data
184     * item. The method always returns the most current data, either from the
185     * classpath or the local cache, depending which flavors are available
186     * and recently updated.</p><p>
187     * The method must be thread safe and can be accessed in parallel. Hereby it
188     * is possible that, when an intermediate update of the data by update
189     * occurs, that different input stream content is returned.
190     *
191     * @param resourceId The unique identifier of the resource, not {@code null}.
192     * @return The {@link InputStream} for reading the data.
193     * @throws IOException if a problem occurred.
194     */
195    public InputStream getData(String resourceId) throws IOException;
196
197    /**
198     * Explicitly triggers the loading of the registered data, regardless of its
199     * current {@link UpdatePolicy} configured, from the fallback/local
200     * resource.
201     *
202     * @param resourceId The unique identifier of the resource, not {@code null}.
203     * @return true if load was successful.
204     */
205    public boolean loadDataLocal(String resourceId);
206
207    /**
208     * Explicitly triggers the remote loading of the registered data, regardless
209     * of its current {@link UpdatePolicy} configured.
210     *
211     * @param resourceId The unique identifier of the resource, not {@code null}.
212     * @return true if load was successful.
213     * @throws IOException if a problem occurred.
214     */
215    public boolean loadData(String resourceId) throws IOException;
216
217    /**
218     * Explicitly asynchronously triggers the remote loading of the registered
219     * data, regardless of its current {@link UpdatePolicy} configured.
220     *
221     * @param resourceId The unique identifier of the resource, not {@code null}.
222     * @return the Future of the load task started, returns Boolean.TRUE if the
223     * load was successful (either from remote or from the fallback
224     * resource).
225     */
226    public Future<Boolean> loadDataAsync(String resourceId);
227
228    /**
229     * Explicitly triggers the resetToFallback (loading of the registered data from the
230     * classpath backup resource).
231     *
232     * @param resourceId The unique identifier of the resource, not {@code null}.
233     * @throws IOException if a problem occurred.
234     */
235    public void resetData(String resourceId) throws IOException;
236
237}