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.resource.mds;
20  
21  import fr.cnes.doi.application.DoiMdsApplication;
22  import fr.cnes.doi.application.DoiMdsApplication.API_MDS;
23  import fr.cnes.doi.client.ClientMDS;
24  import fr.cnes.doi.client.ClientMDS.DATACITE_API_RESPONSE;
25  import fr.cnes.doi.exception.ClientMdsException;
26  import fr.cnes.doi.exception.DoiServerException;
27  import fr.cnes.doi.settings.Consts;
28  import fr.cnes.doi.settings.DoiSettings;
29  import fr.cnes.doi.utils.spec.Requirement;
30  import java.util.Arrays;
31  import org.apache.logging.log4j.Level;
32  import org.restlet.data.MediaType;
33  import org.restlet.data.Method;
34  import org.restlet.data.Status;
35  import org.restlet.ext.wadl.DocumentationInfo;
36  import org.restlet.ext.wadl.MethodInfo;
37  import org.restlet.ext.wadl.ParameterStyle;
38  import org.restlet.ext.wadl.RepresentationInfo;
39  import org.restlet.representation.Representation;
40  import org.restlet.representation.StringRepresentation;
41  import org.restlet.resource.Get;
42  
43  /**
44   * DOI resource to retrieve the landing page for a given DOI.
45   *
46   * @author Jean-Christophe Malapert (jean-christophe.malapert@cnes.fr)
47   */
48  public class DoiResource extends BaseMdsResource {
49  
50      /**
51       * Function of this resource {@value #GET_DOI}.
52       */
53      public static final String GET_DOI = "Get DOI";
54  
55      /**
56       * DOI template.
57       */
58      private volatile String doiName;
59  
60      /**
61       * Init by getting the DOI name in the
62       * {@link DoiMdsApplication#DOI_TEMPLATE template URL}.
63       *
64       * @throws DoiServerException - if a problem happens
65       */
66      @Override
67      protected void doInit() throws DoiServerException {
68          super.doInit();
69          LOG.traceEntry();
70          setDescription("The resource can retrieve a DOI");
71          this.doiName = getAttributePath(DoiMdsApplication.DOI_URI);
72          LOG.debug(this.doiName);
73          LOG.traceExit();
74      }
75  
76      /**
77       * Returns the URL associated to a given DOI or no content. When the status
78       * is 200, the URL associated to a DOI is returnes. When the status is 204,
79       * the DOI is known to MDS, but is not minted (or not resolvable e.g. due to
80       * handle's latency)
81       *
82       * @return an URL or no content (DOI is known to MDS, but is not minted (or
83       * not resolvable e.g. due to handle's latency))
84       * @throws DoiServerException - if the response is not a success
85       * <ul>
86       * <li>{@link DATACITE_API_RESPONSE#DOI_NOT_FOUND}</li>
87       * <li>{@link API_MDS#DATACITE_PROBLEM}</li>
88       * <li>{@link API_MDS#DOI_VALIDATION}</li>
89       * </ul>
90       */
91      @Requirement(reqId = Requirement.DOI_SRV_070, reqName = Requirement.DOI_SRV_070_NAME)
92      @Requirement(reqId = Requirement.DOI_MONIT_020, reqName = Requirement.DOI_MONIT_020_NAME)
93      @Requirement(reqId = Requirement.DOI_INTER_070, reqName = Requirement.DOI_INTER_070_NAME)
94      @Get
95      public Representation getDoi() throws DoiServerException {
96          LOG.traceEntry();
97          final Representation result;
98          checkInput(this.doiName);
99          try {
100             final String doi = this.getDoiApp().getClient().getDoi(this.doiName);
101             if (doi == null || doi.isEmpty()) {
102                 setStatus(Status.SUCCESS_NO_CONTENT);
103             } else {
104                 setStatus(Status.SUCCESS_OK);
105             }
106             result = new StringRepresentation(doi, MediaType.TEXT_PLAIN);
107         } catch (ClientMdsException ex) {
108             if (ex.getStatus().getCode() == Status.CLIENT_ERROR_NOT_FOUND.getCode()) {
109                 throw LOG.throwing(
110                         Level.ERROR,
111                         new DoiServerException(getApplication(), DATACITE_API_RESPONSE.DOI_NOT_FOUND,
112                                 ex)
113                 );
114             } else {
115                 throw LOG.throwing(
116                         Level.ERROR,
117                         new DoiServerException(getApplication(), API_MDS.DATACITE_PROBLEM, ex)
118                 );
119             }
120         }
121         return LOG.traceExit(result);
122     }
123 
124     /**
125      * Checks if doiName is not empty and contains the institution's prefix
126      *
127      * @param doiName DOI name
128      * @throws DoiServerException 400 Bad Request if the DOI does not contain
129      * the institution suffix.
130      */
131     @Requirement(reqId = Requirement.DOI_INTER_070, reqName = Requirement.DOI_INTER_070_NAME)
132     private void checkInput(final String doiName) throws DoiServerException {
133         LOG.traceEntry("Parameter : {}", doiName);
134         if (doiName == null || doiName.isEmpty()) {
135             throw LOG.throwing(
136                     Level.ERROR,
137                     new DoiServerException(getApplication(), API_MDS.DOI_VALIDATION,
138                             "DoiName must be set.")
139             );
140         } else if (doiName.startsWith(DoiSettings.getInstance().getString(Consts.INIST_DOI))) {
141             try {
142                 ClientMDS.checkIfAllCharsAreValid(doiName);
143             } catch (IllegalArgumentException ex) {
144                 throw LOG.throwing(
145                         Level.ERROR,
146                         new DoiServerException(getApplication(), API_MDS.DOI_VALIDATION, ex)
147                 );
148             }
149         } else {
150             throw LOG.throwing(
151                     Level.ERROR,
152                     new DoiServerException(getApplication(), API_MDS.DOI_VALIDATION, "the DOI"
153                             + " prefix must contains the prefix of the institution")
154             );
155         }
156         LOG.traceExit();
157     }
158 
159     /**
160      * DOI representation
161      *
162      * @return Wadl representation for a DOI
163      */
164     @Requirement(reqId = Requirement.DOI_DOC_010, reqName = Requirement.DOI_DOC_010_NAME)
165     private RepresentationInfo doiRepresentation() {
166         final RepresentationInfo repInfo = new RepresentationInfo();
167         repInfo.setMediaType(MediaType.TEXT_PLAIN);
168         final DocumentationInfo docInfo = new DocumentationInfo();
169         docInfo.setTitle("DOI Representation");
170         docInfo.setTextContent("This request returns an URL associated with a given DOI.");
171         repInfo.setDocumentation(docInfo);
172         return repInfo;
173     }
174 
175     /**
176      * Describes the Get Method. The different representations are the
177      * followings:
178      * <ul>
179      * <li>{@link DATACITE_API_RESPONSE#SUCCESS}</li>
180      * <li>{@link DATACITE_API_RESPONSE#SUCCESS_NO_CONTENT}</li>
181      * <li>{@link API_MDS#DOI_VALIDATION}</li>
182      * <li>{@link DATACITE_API_RESPONSE#DOI_NOT_FOUND}</li>
183      * <li>{@link API_MDS#DATACITE_PROBLEM}</li>
184      * </ul>
185      *
186      * @param info Wadl description
187      */
188     @Requirement(reqId = Requirement.DOI_DOC_010, reqName = Requirement.DOI_DOC_010_NAME)
189     @Override
190     protected final void describeGet(final MethodInfo info) {
191         info.setName(Method.GET);
192         info.setDocumentation("Get the landing page related to a given DOI");
193         addRequestDocToMethod(info, Arrays.asList(
194                 createQueryParamDoc(
195                         DoiMdsApplication.DOI_TEMPLATE,
196                         ParameterStyle.TEMPLATE, "DOI name", true, "xs:string"
197                 )
198         ));
199 
200         addResponseDocToMethod(info, createResponseDoc(
201                 DATACITE_API_RESPONSE.SUCCESS.getStatus(),
202                 DATACITE_API_RESPONSE.SUCCESS.getShortMessage(),
203                 doiRepresentation())
204         );
205         addResponseDocToMethod(info, createResponseDoc(
206                 DATACITE_API_RESPONSE.SUCCESS_NO_CONTENT.getStatus(),
207                 DATACITE_API_RESPONSE.SUCCESS_NO_CONTENT.getShortMessage(),
208                 "explainRepresentationID")
209         );
210         addResponseDocToMethod(info, createResponseDoc(
211                 API_MDS.DOI_VALIDATION.getStatus(),
212                 API_MDS.DOI_VALIDATION.getShortMessage(),
213                 "explainRepresentationID")
214         );
215         addResponseDocToMethod(info, createResponseDoc(
216                 DATACITE_API_RESPONSE.DOI_NOT_FOUND.getStatus(),
217                 DATACITE_API_RESPONSE.DOI_NOT_FOUND.getShortMessage(),
218                 "explainRepresentationID")
219         );
220         addResponseDocToMethod(info, createResponseDoc(
221                 API_MDS.DATACITE_PROBLEM.getStatus(),
222                 API_MDS.DATACITE_PROBLEM.getShortMessage(),
223                 "explainRepresentationID")
224         );
225     }
226 
227 }