View Javadoc

1   /*
2    * Copyright (C) 2017-2019 Centre National d'Etudes Spatiales (CNES).
3    *
4    * This library is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 3.0 of the License, or (at your option) any later version.
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this library; if not, write to the Free Software
16   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17   * MA 02110-1301  USA
18   */
19  package fr.cnes.doi.client;
20  
21  import com.fasterxml.jackson.databind.ObjectMapper;
22  import fr.cnes.doi.exception.ClientCrossCiteException;
23  import fr.cnes.doi.utils.spec.Requirement;
24  import java.io.IOException;
25  import java.util.List;
26  import java.util.logging.Level;
27  import org.restlet.data.Reference;
28  import org.restlet.data.Status;
29  import org.restlet.representation.Representation;
30  import org.restlet.resource.ResourceException;
31  
32  /**
33   * Client to query the citation service. This class queries
34   * <a href="https://citation.crosscite.org/">CrossCite</a>.
35   *
36   * @author Jean-Christophe Malapert (Jean-Christophe.malapert@cnes.fr)
37   */
38  @Requirement(reqId = Requirement.DOI_INTER_020, reqName = Requirement.DOI_INTER_020_NAME)
39  public class ClientCrossCiteCitation extends BaseClient {
40  
41      /**
42       * Service end point {@value #CROSS_CITE_URL}.
43       */
44      public static final String CROSS_CITE_URL = "http://citation.crosscite.org";
45  
46      /**
47       * Service end point {@value #CROSS_CITE_MOCK_URL}.
48       */
49      public static final String CROSS_CITE_MOCK_URL = "http://localhost:" + DATACITE_MOCKSERVER_PORT;
50  
51      /**
52       * URI to get styles {@value #STYLE_URI}.
53       */
54      public static final String STYLE_URI = "styles";
55  
56      /**
57       * URI to get locales {@value #LOCALE_URI}.
58       */
59      public static final String LOCALE_URI = "locales";
60  
61      /**
62       * URI to get format {@value #FORMAT_URI}.
63       */
64      public static final String FORMAT_URI = "format";
65  
66      /**
67       * Context use.
68       */
69      private final Context contextUse;
70  
71      /**
72       * Creates a client to {@value CROSS_CITE_URL} with a
73       * {@link Context#PROD prod} context and without a proxy.
74       */
75      public ClientCrossCiteCitation() {
76          super(CROSS_CITE_URL);
77          this.contextUse = Context.PROD;
78      }
79  
80      /**
81       * Creates a client to an URI related to the context.
82       *
83       * @param context context
84       */
85      public ClientCrossCiteCitation(final Context context) {
86          super(context.getCrossCiteUrl());
87          this.contextUse = context;
88      }
89  
90      /**
91       * Init the endpoint.
92       */
93      protected void init() {
94          this.getClient().setReference(new Reference(this.contextUse.getCrossCiteUrl()));
95      }
96  
97      /**
98       * Returns the response as a list of String of an URI.
99       *
100      * @param segment resource name
101      * @return the response
102      * @throws ClientCrossCiteException - if an error happens when requesting
103      * CrossCite
104      */
105     private List<String> getList(final String segment) throws ClientCrossCiteException {
106         try {
107             final Reference ref = getClient().addSegment(segment);
108             this.getClient().setReference(ref);
109             final Representation rep = this.getClient().get();
110             final Status status = this.getClient().getStatus();
111             if (status.isSuccess()) {
112                 final ObjectMapper mapper = new ObjectMapper();
113                 return mapper.readValue(rep.getStream(), List.class);
114             } else {
115                 throw new ClientCrossCiteException(status, status.getDescription());
116             }
117         } catch (IOException | ResourceException ex) {
118             throw new ClientCrossCiteException(Status.SERVER_ERROR_INTERNAL, ex.getMessage(), ex);
119         } finally {
120             this.getClient().release();
121         }
122     }
123 
124     /**
125      * Returns styles by calling {@value #STYLE_URI}.
126      *
127      * @return list of possible styles
128      * @throws fr.cnes.doi.exception.ClientCrossCiteException Will thrown an
129      * Exception when a problem happens during the request to Cross Cite
130      */
131     public List<String> getStyles() throws ClientCrossCiteException {
132         init();
133         return getList(STYLE_URI);
134     }
135 
136     /**
137      * Returns languages by calling {@value #LOCALE_URI}.
138      *
139      * @return List of possible languages
140      * @throws fr.cnes.doi.exception.ClientCrossCiteException Will thrown an
141      * Exception when a problem happens during the request to Cross Cite
142      */
143     public List<String> getLanguages() throws ClientCrossCiteException {
144         init();
145         return getList(LOCALE_URI);
146     }
147 
148     /**
149      * Returns the citation of a DOI based on the selected style and language.
150      *
151      * @param doiName DOI name
152      * @param style Selected style to format the citation
153      * @param language Selected language to format the citation
154      * @return The formatted citation
155      * @throws fr.cnes.doi.exception.ClientCrossCiteException Will thrown an
156      * Exception when a problem happens during the request to Cross Cite
157      */
158     public String getFormat(final String doiName,
159             final String style,
160             final String language) throws ClientCrossCiteException {
161         init();
162         final String result;
163         try {
164             Reference ref = this.getClient().addSegment(FORMAT_URI);
165             ref = ref.addQueryParameter("doi", doiName);
166             ref = ref.addQueryParameter("style", style);
167             ref = ref.addQueryParameter("lang", language);
168             this.getClient().setReference(ref);
169             final Representation rep = this.getClient().get();
170             final Status status = this.getClient().getStatus();
171             if (status.isSuccess()) {
172                 result = rep.getText();
173             } else {
174                 throw new ClientCrossCiteException(status, status.getDescription());
175             }
176             return result;
177         } catch (IOException ex) {
178             throw new ClientCrossCiteException(Status.SERVER_ERROR_INTERNAL, ex.getMessage(), ex);
179         } catch (ResourceException ex) {
180             throw new ClientCrossCiteException(ex.getStatus(), ex.getMessage(), ex);
181         } finally {
182             this.getClient().release();
183         }
184     }
185 
186     /**
187      * Options for each context.
188      */
189     public enum Context {
190 
191         /**
192          * Development context. This context uses the
193          * {@link #CROSS_CITE_MOCK_URL} end point with a log level sets to OFF.
194          */
195         DEV(CROSS_CITE_MOCK_URL, Level.OFF),
196         /**
197          * Post development context. This context uses the
198          * {@link #CROSS_CITE_URL} end point with a log level sets to ALL.
199          */
200         POST_DEV(CROSS_CITE_URL, Level.ALL),
201         /**
202          * Pre production context. This context uses the {@link #CROSS_CITE_URL}
203          * end point with a log level sets to FINE.
204          */
205         PRE_PROD(CROSS_CITE_URL, Level.FINE),
206         /**
207          * Production context. This context uses the {@link #CROSS_CITE_URL} end
208          * point with a log level sets to INFO.
209          */
210         PROD(CROSS_CITE_URL, Level.INFO);
211 
212         /**
213          * Level log.
214          */
215         private Level levelLog;
216 
217         /**
218          * CrossCite URL.
219          */
220         private String crossCiteUrl;
221 
222         /**
223          * Construct a development context
224          *
225          * @param dataciteUrl dataciteURL according to the context
226          * @param levelLog level log
227          */
228         Context(final String dataciteUrl,
229                 final Level levelLog) {
230             this.crossCiteUrl = dataciteUrl;
231             this.levelLog = levelLog;
232         }
233 
234         /**
235          * Returns the log level.
236          *
237          * @return the log level
238          */
239         public Level getLevelLog() {
240             return this.levelLog;
241         }
242 
243         /**
244          * Returns the service end point.
245          *
246          * @return the service end point
247          */
248         public String getCrossCiteUrl() {
249             return this.crossCiteUrl;
250         }
251 
252         /**
253          * Sets the level log for the context
254          *
255          * @param levelLog level log
256          */
257         private void setLevelLog(final Level levelLog) {
258             this.levelLog = levelLog;
259         }
260 
261         /**
262          * Sets the Cross Cite URL for the context.
263          *
264          * @param crossCiteUrl Cross Cite URL
265          */
266         private void setCrossCiteUrl(final String crossCiteUrl) {
267             this.crossCiteUrl = crossCiteUrl;
268         }
269 
270         /**
271          * Sets the level log for a given context
272          *
273          * @param context the context
274          * @param levelLog the level log
275          */
276         public static void setLevelLog(final Context context,
277                 final Level levelLog) {
278             context.setLevelLog(levelLog);
279         }
280 
281         /**
282          * Sets the Cross Cite URL for a given context
283          *
284          * @param context the context
285          * @param crossCiteUrl Cross Cite URL
286          */
287         public static void setCrossCiteUrl(final Context context,
288                 final String crossCiteUrl) {
289             context.setCrossCiteUrl(crossCiteUrl);
290         }
291 
292     }
293 }