comparison src/main/java/edu/harvard/iq/dataverse/DatasetVersionServiceBean.java @ 10:a50cf11e5178

Rewrite LGDataverse completely upgrading to dataverse4.0
author Zoe Hong <zhong@mpiwg-berlin.mpg.de>
date Tue, 08 Sep 2015 17:00:21 +0200
parents
children
comparison
equal deleted inserted replaced
9:5926d6419569 10:a50cf11e5178
1 /*
2 * To change this license header, choose License Headers in Project Properties.
3 * To change this template file, choose Tools | Templates
4 * and open the template in the editor.
5 */
6 package edu.harvard.iq.dataverse;
7
8 import edu.harvard.iq.dataverse.DatasetVersion.VersionState;
9 import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
10 import java.util.Arrays;
11 import java.util.List;
12 import java.util.logging.Level;
13 import java.util.logging.Logger;
14 import javax.ejb.EJB;
15 import javax.ejb.EJBException;
16 import javax.ejb.Stateless;
17 import javax.inject.Named;
18 import javax.persistence.EntityManager;
19 import javax.persistence.PersistenceContext;
20 import javax.persistence.Query;
21 import javax.persistence.TypedQuery;
22
23
24 /**
25 *
26 * @author skraffmiller
27 */
28 @Stateless
29 @Named
30 public class DatasetVersionServiceBean implements java.io.Serializable {
31
32 private static final Logger logger = Logger.getLogger(DatasetVersionServiceBean.class.getCanonicalName());
33
34 @EJB
35 DatasetServiceBean datasetService;
36
37 @EJB
38 SettingsServiceBean settingsService;
39
40 @PersistenceContext(unitName = "VDCNet-ejbPU")
41 private EntityManager em;
42
43 /**
44 * Response to a successful request from the DatasetPage
45 *
46 * Used to help display messages in the cases when:
47 * (1) A specific dataset version (including a DRAFT) is requested
48 * (2) A different dataset is returned b/c the first one doesn't exist
49 *
50 * Simple example: "DRAFT" requested but no longer exists b/c it
51 * was published and is now version "1.0"
52 */
53 public class RetrieveDatasetVersionResponse{
54
55 private DatasetVersion datasetVersionForResponse;
56 private boolean wasSpecificVersionRequested = false;
57 private boolean didSpecificVersionMatch = false;
58 private String actualVersion = null;
59 private String requestedVersion = null;
60
61 public RetrieveDatasetVersionResponse(DatasetVersion datasetVersion, String requestedVersion){
62 if (datasetVersion == null){
63 throw new IllegalArgumentException("datasetVersion cannot be null");
64 }
65 //logger.fine("RetrieveDatasetVersionResponse: datasetVersion: " + datasetVersion.getSemanticVersion() + " requestedVersion: " + requestedVersion);
66 //logger.fine("chosenVersion id: " + datasetVersion.getId() + " getFriendlyVersionNumber: " + datasetVersion.getFriendlyVersionNumber());
67 this.datasetVersionForResponse = datasetVersion;
68
69 this.actualVersion = datasetVersion.getSemanticVersion();
70 this.requestedVersion = requestedVersion;
71 this.checkVersion();
72 }
73
74
75 public String getDifferentVersionMessage(){
76
77 if (this.wasSpecificVersionRequested && !this.didSpecificVersionMatch){
78 String userMsg;
79 if (DatasetVersionServiceBean.this.isVersionAskingForDraft(this.requestedVersion)){
80 userMsg = "The \"DRAFT\" version was not found.";
81 }else{
82 userMsg = "Version \"" + this.requestedVersion + "\" was not found.";
83 }
84
85 if (DatasetVersionServiceBean.this.isVersionAskingForDraft(this.actualVersion)){
86 userMsg += " This is the \"DRAFT\" version.";
87 }else{
88 userMsg += " This is version \"" + this.actualVersion + "\".";
89 }
90
91 return userMsg;
92 }
93 return null;
94 }
95
96 private void checkVersion(){
97 if (actualVersion==null){ // this shouldn't happen
98 return;
99 }
100 //logger.fine("check version. requested: " + this.requestedVersion + " returned: " + actualVersion);
101 // This may often be the case if version is not specified
102 //
103 if (requestedVersion == null || requestedVersion.equals("")){
104 this.wasSpecificVersionRequested = false;
105 return;
106 }
107
108 this.wasSpecificVersionRequested = true;
109
110 if (this.requestedVersion.equalsIgnoreCase(actualVersion)){
111 this.didSpecificVersionMatch = true;
112 }else{
113 this.didSpecificVersionMatch = false; // redundant, already the default
114 }
115
116 }
117
118 public boolean wasRequestedVersionRetrieved(){
119 if (this.wasSpecificVersionRequested && !this.didSpecificVersionMatch){
120 return false;
121 }
122 return true;
123 }
124
125
126 public DatasetVersion getDatasetVersion(){
127 return this.datasetVersionForResponse;
128 }
129 } // end RetrieveDatasetVersionResponse
130
131 public DatasetVersion find(Object pk) {
132 return (DatasetVersion) em.find(DatasetVersion.class, pk);
133 }
134
135 public DatasetVersion findByFriendlyVersionNumber(Long datasetId, String friendlyVersionNumber) {
136
137 Long majorVersionNumber = null;
138 Long minorVersionNumber = null;
139
140 String[] versions = friendlyVersionNumber.split("\\.");
141 try {
142 if (versions.length == 1) {
143 majorVersionNumber = Long.parseLong(versions[0]);
144 } else if (versions.length == 2) {
145 majorVersionNumber = Long.parseLong(versions[0]);
146 minorVersionNumber = Long.parseLong(versions[1]);
147 } else {
148 return null;
149 }
150 } catch (NumberFormatException n) {
151 return null;
152 }
153
154 if (majorVersionNumber != null && minorVersionNumber != null) {
155 String queryStr = "SELECT v from DatasetVersion v where v.dataset.id = :datasetId and v.versionNumber= :majorVersionNumber and v.minorVersionNumber= :minorVersionNumber";
156 DatasetVersion foundDatasetVersion = null;
157 try {
158 Query query = em.createQuery(queryStr);
159 query.setParameter("datasetId", datasetId);
160 query.setParameter("majorVersionNumber", majorVersionNumber);
161 query.setParameter("minorVersionNumber", minorVersionNumber);
162 foundDatasetVersion = (DatasetVersion) query.getSingleResult();
163 } catch (javax.persistence.NoResultException e) {
164 logger.warning("no ds version found: " + datasetId + " " + friendlyVersionNumber);
165 // DO nothing, just return null.
166 }
167 return foundDatasetVersion;
168
169 }
170
171 if (majorVersionNumber == null && minorVersionNumber == null) {
172
173 return null;
174
175 }
176
177 if (majorVersionNumber != null && minorVersionNumber == null) {
178
179 try {
180 TypedQuery<DatasetVersion> typedQuery = em.createQuery("SELECT v from DatasetVersion v where v.dataset.id = :datasetId and v.versionNumber= :majorVersionNumber", DatasetVersion.class);
181 typedQuery.setParameter("datasetId", datasetId);
182 typedQuery.setParameter("majorVersionNumber", majorVersionNumber);
183 DatasetVersion retVal = null;
184 List<DatasetVersion> versionsList = typedQuery.getResultList();
185 for (DatasetVersion dsvTest : versionsList) {
186 if (retVal == null) {
187 retVal = dsvTest;
188 } else {
189 if (retVal.getMinorVersionNumber().intValue() < dsvTest.getMinorVersionNumber().intValue()) {
190 retVal = dsvTest;
191 }
192 }
193 }
194
195 return retVal;
196
197 } catch (javax.persistence.NoResultException e) {
198 logger.warning("no ds version found: " + datasetId + " " + friendlyVersionNumber);
199 // DO nothing, just return null.
200 }
201
202 }
203
204 return null;
205 }
206
207 /**
208 * Parse a Persistent Id and return as 3 strings.
209 *
210 * Example: 1.0, 1.1. 3.4, etc.
211 *
212 * @param version
213 * @return Long[] with [ major_version, minor_version ]
214 * - either or both may be null
215 */
216 public Long[] parseVersionNumber(String version){
217 if (version == null){
218 return null;
219 }
220
221 Long majorVersion;
222 Long minorVersion = null;
223
224 String[] vparts = version.split("\\.");
225 if (vparts.length == 1){
226 try{
227 majorVersion = Long.parseLong(vparts[0]);
228 }catch (NumberFormatException n) {
229 return null;
230 }
231 }else if (vparts.length == 2){
232 try{
233 majorVersion = Long.parseLong(vparts[0]);
234 minorVersion = Long.parseLong(vparts[1]);
235 }catch (NumberFormatException n) {
236 return null;
237 }
238 }else{
239 return null;
240 }
241
242 Long versionNumbers[] = { majorVersion, minorVersion };
243
244 return versionNumbers;
245 }
246
247
248
249 private void msg(String s){
250 //logger.fine(s);
251 }
252
253 /**
254 * Does the version identifier in the URL ask for a "DRAFT"?
255 *
256 * @param version
257 * @return boolean
258 */
259 private boolean isVersionAskingForDraft(String version){
260
261 if (version == null){
262 return false;
263 }
264
265 return version.toUpperCase().equals(VersionState.DRAFT.toString());
266 }
267
268 private String getDatasetVersionBasicQuery(String identifierClause, String extraClause){
269
270 if (identifierClause == null){
271 return null;
272 }
273
274 if (extraClause == null){
275 extraClause = "";
276 }
277
278 String queryStr = "SELECT dv.* FROM DatasetVersion dv";
279 queryStr += " INNER JOIN Dataset ds";
280 queryStr += " ON dv.dataset_id=ds.id";
281 queryStr += identifierClause; // either persistentId or id
282 queryStr += extraClause; // may be an empty string
283 queryStr += " ORDER BY versionNumber DESC, minorVersionNumber DESC";
284 queryStr += " LIMIT 1;";
285
286 return queryStr;
287
288 }
289
290
291 /**
292 * Query to return the last Released DatasetVersion by Persistent ID
293 *
294 * @param identifierClause - query clause to retrieve via DatasetVersion.Id or DatasetVersion.persistentId
295 * @return String fullQuery
296 */
297 private String getLatestReleasedDatasetVersionQuery(String identifierClause){
298
299 if (identifierClause == null){
300 return null;
301 }
302 String releasedClause = " AND dv.versionstate = '" + VersionState.RELEASED.toString() + "'";
303
304 return getDatasetVersionBasicQuery(identifierClause, releasedClause);
305
306 }
307
308 /**
309 * Query to return a DatasetVersion by Specific Version
310 *
311 * @param identifierClause - query clause to retrieve via DatasetVersion.Id or DatasetVersion.persistentId
312 * @return String fullQuery
313 */
314 private String getNumericDatasetVersionQueryByIdentifier(String identifierClause, Long majorVersion, Long minorVersion){
315
316 if (identifierClause == null){
317 return null;
318 }
319 String extraQueryClause = "";
320
321
322 // For an exact version: retrieve either RELEASED or DEACCESSIONED
323 //
324 if (majorVersion != null && minorVersion != null){
325 extraQueryClause += " AND dv.versionNumber= " + majorVersion;
326 extraQueryClause += " AND dv.minorVersionNumber= " + minorVersion;
327 extraQueryClause += " AND (dv.versionstate = '" + VersionState.RELEASED.toString() + "' or dv.versionstate = '" + VersionState.DEACCESSIONED.toString() + "')";
328 } else {
329 // Last released major version
330 //
331 extraQueryClause += " AND dv.versionNumber= " + majorVersion;
332 extraQueryClause += " AND dv.versionstate = '" + VersionState.RELEASED.toString() + "'";
333 }
334
335 return getDatasetVersionBasicQuery(identifierClause, extraQueryClause);
336
337 }
338
339 /**
340 * Query to return a Draft DatasetVersion by Persistent ID
341 *
342 * @param identifierClause - query clause to retrieve via DatasetVersion.Id or DatasetVersion.persistentId
343 * @return String fullQuery
344 */
345 private String getDraftDatasetVersionQuery(String identifierClause){
346
347 if (identifierClause == null){
348 return null;
349 }
350 String draftClause = " AND dv.versionstate = '" + VersionState.DRAFT.toString() + "'";
351
352 return getDatasetVersionBasicQuery(identifierClause, draftClause);
353
354 }
355
356 /**
357 * Query to return a DEACCESSIONED DatasetVersion by Persistent ID
358 *
359 * @param identifierClause - query clause to retrieve via DatasetVersion.Id or DatasetVersion.persistentId
360 * @return String fullQuery
361 */
362 private String getDeaccessionedDatasetVersionQuery(String identifierClause){
363
364 if (identifierClause == null){
365 return null;
366 }
367 String draftClause = " AND dv.versionstate = '" + VersionState.DEACCESSIONED.toString() + "'";
368
369 return getDatasetVersionBasicQuery(identifierClause, draftClause);
370
371 }
372
373
374
375
376 /**
377 * Execute a query to return DatasetVersion
378 *
379 * @param queryString
380 * @return
381 */
382 private DatasetVersion getDatasetVersionByQuery(String queryString){
383 msg("getDatasetVersionByQuery queryString: " + queryString);
384 if (queryString == null){
385 return null;
386 }
387
388 // Inexact check to see if one of the selected tables is DATASETVERSION
389 //
390 if (!queryString.toUpperCase().contains("FROM DATASETVERSION")){
391 throw new IllegalArgumentException("This query does not select from the table DATASETVERSION");
392 }
393
394 try{
395 Query query = em.createNativeQuery(queryString, DatasetVersion.class);
396 DatasetVersion ds = (DatasetVersion) query.getSingleResult();
397
398 msg("Found: " + ds);
399 return ds;
400
401 } catch (javax.persistence.NoResultException e) {
402 msg("DatasetVersion not found: " + queryString);
403 logger.log(Level.FINE, "DatasetVersion not found: {0}", queryString);
404 return null;
405 } catch (EJBException e) {
406 logger.log(Level.WARNING, "EJBException exception: {0}", e.getMessage());
407 return null;
408 }
409 } // end getDatasetVersionByQuery
410
411
412
413
414 public DatasetVersion retrieveDatasetVersionByIdentiferClause(String identifierClause, String version){
415
416 if (identifierClause == null){
417 return null;
418 }
419
420 DatasetVersion chosenVersion;
421
422 /* --------------------------------------------
423 (1) Scenario: User asking for a DRAFT?
424 - (1a) Look for draft
425 - (1b) Not found: Get Latest Release
426 - Permissions: check on DatasetPage
427 -------------------------------------------- */
428 if (DatasetVersionServiceBean.this.isVersionAskingForDraft(version)){
429
430 // (1a) Try to retrieve a draft
431 msg("(1a) Try to retrieve a draft");
432 String draftQuery = this.getDraftDatasetVersionQuery(identifierClause);
433 chosenVersion = this.getDatasetVersionByQuery(draftQuery);
434
435 // Draft Exists! Return it!
436 msg("Draft Exists! Return it!");
437 if (chosenVersion != null){
438 return chosenVersion; // let DatasetPage check permissions
439 }
440
441 // (1b) No draft found - check for last released
442 msg("(1b) No draft found - check for last released");
443 String lastReleasedQuery = this.getLatestReleasedDatasetVersionQuery(identifierClause);
444 chosenVersion = this.getDatasetVersionByQuery(lastReleasedQuery);
445
446 return chosenVersion; // This may be null -- let DatasetPage check
447 }
448 // END: User asking for a Draft
449
450 /* --------------------------------------------
451 (2) Scenario: Version specified
452 - (2a) Look for major and minor version - RELEASE OR DEACCESSIONED
453 - OR Look for major version - RELEASE
454 - (2c) Not found: look for latest released version
455 - (2c) Not found: look for DEACCESSIONED
456 - (2d) Not found: look for draft
457 - Permissions: check on DatasetPage
458
459 (3) Scenario: No version specified
460 - Same as (2c)(2d) above
461 - Permissions: check on DatasetPage
462 -------------------------------------------- */
463 Long[] versionNumbers = parseVersionNumber(version);
464 if (versionNumbers != null && versionNumbers.length == 2){ // At least a major version found
465
466 // (2a) Look for major and minor version - RELEASE OR DEACCESSIONED
467 msg("(2a) Look for major and minor version -" + Arrays.toString(versionNumbers));
468 String specificVersionQuery = this.getNumericDatasetVersionQueryByIdentifier(identifierClause, versionNumbers[0], versionNumbers[1]);
469
470 chosenVersion = this.getDatasetVersionByQuery(specificVersionQuery);
471 if (chosenVersion != null){
472 return chosenVersion;
473 }
474 }
475
476 // (2b) Look for latest released version
477 msg("(2b) Look for latest released version");
478 String latestVersionQuery = this.getLatestReleasedDatasetVersionQuery(identifierClause);
479 //msg("latestVersionQuery: " + latestVersionQuery);
480 chosenVersion = this.getDatasetVersionByQuery(latestVersionQuery);
481 if (chosenVersion != null){
482 return chosenVersion;
483 }
484
485 // (2c) Look for DEACCESSIONED
486 msg("(2c) Look for draft");
487 String dQuery = this.getDeaccessionedDatasetVersionQuery(identifierClause);
488 //msg("draftQuery: " + draftQuery);
489 chosenVersion = this.getDatasetVersionByQuery(dQuery);
490 if (chosenVersion != null){
491 return chosenVersion;
492 }
493
494 // (2d) Look for draft
495 msg("(2d) Look for draft");
496 String draftQuery = this.getDraftDatasetVersionQuery(identifierClause);
497 //msg("draftQuery: " + draftQuery);
498 chosenVersion = this.getDatasetVersionByQuery(draftQuery);
499
500 return chosenVersion; // This may be null -- let DatasetPage check
501
502
503 } // end: retrieveDatasetVersionByPersistentId
504
505
506 /**
507 * Find a DatasetVersion using the persisentID and version string
508 *
509 * @param persistentId doi:10.5072/FK2/BYM3IW
510 * @param version "DRAFT", 1.0, 2, 3.4, null, etc
511 * @return
512 */
513 public RetrieveDatasetVersionResponse retrieveDatasetVersionByPersistentId(String persistentId, String version){
514
515 msg("retrieveDatasetVersionByPersistentId: " + persistentId + " " + version);
516 if (persistentId==null){
517 return null;
518 }
519
520 /*
521 Parse the persistent id
522 */
523 GlobalId parsedId;
524 try{
525 parsedId = new GlobalId(persistentId); // [ protocol, authority, identifier]
526 } catch (IllegalArgumentException e){
527 logger.log(Level.WARNING, "Failed to parse persistentID: {0}", persistentId);
528 return null;
529 }
530
531 String identifierClause = " AND ds.protocol= '" + parsedId.getProtocol() + "'";
532 identifierClause += " AND ds.authority = '" + parsedId.getAuthority() + "'";
533 identifierClause += " AND ds.identifier = '" + parsedId.getIdentifier() + "'";
534
535
536 DatasetVersion ds = retrieveDatasetVersionByIdentiferClause(identifierClause, version);
537
538 if (ds != null){
539 msg("retrieved dataset: " + ds.getId() + " semantic: " + ds.getSemanticVersion());
540 return new RetrieveDatasetVersionResponse(ds, version);
541 }
542
543 return null;
544
545 }
546
547
548
549 /**
550 * Find a DatasetVersion using the persisentID and version string
551 *
552 * @param datasetId
553 * @param version "DRAFT", 1.0, 2, 3.4, null, etc
554 * @return
555 */
556 public RetrieveDatasetVersionResponse retrieveDatasetVersionById(Long datasetId, String version){
557 msg("retrieveDatasetVersionById: " + datasetId + " " + version);
558 if (datasetId==null){
559 return null;
560 }
561
562 String identifierClause = " AND ds.id = " + datasetId;
563
564 DatasetVersion ds = retrieveDatasetVersionByIdentiferClause(identifierClause, version);
565
566 if (ds != null){
567 return new RetrieveDatasetVersionResponse(ds, version);
568 }
569
570 return null;
571
572
573 } // end: retrieveDatasetVersionById
574
575
576 /**
577 * Find a DatasetVersion using the dataset versionId
578 *
579 * @param versionId DatasetVersion id
580 * @return
581 */
582 public RetrieveDatasetVersionResponse retrieveDatasetVersionByVersionId(Long versionId){
583 //msg("retrieveDatasetVersionById: " + datasetId + " " + versionId);
584 if (versionId==null ){
585 return null;
586 }
587
588 // Try versionId - release state doesn't matte
589 //
590 String identifierClause = " and dv.id = " + versionId;
591 String retrieveSpecifiedDSVQuery = getDatasetVersionBasicQuery(identifierClause, null);
592 DatasetVersion chosenVersion = this.getDatasetVersionByQuery(retrieveSpecifiedDSVQuery);
593 if (chosenVersion != null) {
594 return new RetrieveDatasetVersionResponse(chosenVersion, "");
595 }
596 return null;
597 } // end: retrieveDatasetVersionByVersionId
598
599 } // end class