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