Mercurial > hg > LGDataverses
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetVersionServiceBean.java Tue Sep 08 17:00:21 2015 +0200 @@ -0,0 +1,599 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package edu.harvard.iq.dataverse; + +import edu.harvard.iq.dataverse.DatasetVersion.VersionState; +import edu.harvard.iq.dataverse.settings.SettingsServiceBean; +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.ejb.EJB; +import javax.ejb.EJBException; +import javax.ejb.Stateless; +import javax.inject.Named; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import javax.persistence.TypedQuery; + + +/** + * + * @author skraffmiller + */ +@Stateless +@Named +public class DatasetVersionServiceBean implements java.io.Serializable { + + private static final Logger logger = Logger.getLogger(DatasetVersionServiceBean.class.getCanonicalName()); + + @EJB + DatasetServiceBean datasetService; + + @EJB + SettingsServiceBean settingsService; + + @PersistenceContext(unitName = "VDCNet-ejbPU") + private EntityManager em; + + /** + * Response to a successful request from the DatasetPage + * + * Used to help display messages in the cases when: + * (1) A specific dataset version (including a DRAFT) is requested + * (2) A different dataset is returned b/c the first one doesn't exist + * + * Simple example: "DRAFT" requested but no longer exists b/c it + * was published and is now version "1.0" + */ + public class RetrieveDatasetVersionResponse{ + + private DatasetVersion datasetVersionForResponse; + private boolean wasSpecificVersionRequested = false; + private boolean didSpecificVersionMatch = false; + private String actualVersion = null; + private String requestedVersion = null; + + public RetrieveDatasetVersionResponse(DatasetVersion datasetVersion, String requestedVersion){ + if (datasetVersion == null){ + throw new IllegalArgumentException("datasetVersion cannot be null"); + } + //logger.fine("RetrieveDatasetVersionResponse: datasetVersion: " + datasetVersion.getSemanticVersion() + " requestedVersion: " + requestedVersion); + //logger.fine("chosenVersion id: " + datasetVersion.getId() + " getFriendlyVersionNumber: " + datasetVersion.getFriendlyVersionNumber()); + this.datasetVersionForResponse = datasetVersion; + + this.actualVersion = datasetVersion.getSemanticVersion(); + this.requestedVersion = requestedVersion; + this.checkVersion(); + } + + + public String getDifferentVersionMessage(){ + + if (this.wasSpecificVersionRequested && !this.didSpecificVersionMatch){ + String userMsg; + if (DatasetVersionServiceBean.this.isVersionAskingForDraft(this.requestedVersion)){ + userMsg = "The \"DRAFT\" version was not found."; + }else{ + userMsg = "Version \"" + this.requestedVersion + "\" was not found."; + } + + if (DatasetVersionServiceBean.this.isVersionAskingForDraft(this.actualVersion)){ + userMsg += " This is the \"DRAFT\" version."; + }else{ + userMsg += " This is version \"" + this.actualVersion + "\"."; + } + + return userMsg; + } + return null; + } + + private void checkVersion(){ + if (actualVersion==null){ // this shouldn't happen + return; + } + //logger.fine("check version. requested: " + this.requestedVersion + " returned: " + actualVersion); + // This may often be the case if version is not specified + // + if (requestedVersion == null || requestedVersion.equals("")){ + this.wasSpecificVersionRequested = false; + return; + } + + this.wasSpecificVersionRequested = true; + + if (this.requestedVersion.equalsIgnoreCase(actualVersion)){ + this.didSpecificVersionMatch = true; + }else{ + this.didSpecificVersionMatch = false; // redundant, already the default + } + + } + + public boolean wasRequestedVersionRetrieved(){ + if (this.wasSpecificVersionRequested && !this.didSpecificVersionMatch){ + return false; + } + return true; + } + + + public DatasetVersion getDatasetVersion(){ + return this.datasetVersionForResponse; + } + } // end RetrieveDatasetVersionResponse + + public DatasetVersion find(Object pk) { + return (DatasetVersion) em.find(DatasetVersion.class, pk); + } + + public DatasetVersion findByFriendlyVersionNumber(Long datasetId, String friendlyVersionNumber) { + + Long majorVersionNumber = null; + Long minorVersionNumber = null; + + String[] versions = friendlyVersionNumber.split("\\."); + try { + if (versions.length == 1) { + majorVersionNumber = Long.parseLong(versions[0]); + } else if (versions.length == 2) { + majorVersionNumber = Long.parseLong(versions[0]); + minorVersionNumber = Long.parseLong(versions[1]); + } else { + return null; + } + } catch (NumberFormatException n) { + return null; + } + + if (majorVersionNumber != null && minorVersionNumber != null) { + String queryStr = "SELECT v from DatasetVersion v where v.dataset.id = :datasetId and v.versionNumber= :majorVersionNumber and v.minorVersionNumber= :minorVersionNumber"; + DatasetVersion foundDatasetVersion = null; + try { + Query query = em.createQuery(queryStr); + query.setParameter("datasetId", datasetId); + query.setParameter("majorVersionNumber", majorVersionNumber); + query.setParameter("minorVersionNumber", minorVersionNumber); + foundDatasetVersion = (DatasetVersion) query.getSingleResult(); + } catch (javax.persistence.NoResultException e) { + logger.warning("no ds version found: " + datasetId + " " + friendlyVersionNumber); + // DO nothing, just return null. + } + return foundDatasetVersion; + + } + + if (majorVersionNumber == null && minorVersionNumber == null) { + + return null; + + } + + if (majorVersionNumber != null && minorVersionNumber == null) { + + try { + TypedQuery<DatasetVersion> typedQuery = em.createQuery("SELECT v from DatasetVersion v where v.dataset.id = :datasetId and v.versionNumber= :majorVersionNumber", DatasetVersion.class); + typedQuery.setParameter("datasetId", datasetId); + typedQuery.setParameter("majorVersionNumber", majorVersionNumber); + DatasetVersion retVal = null; + List<DatasetVersion> versionsList = typedQuery.getResultList(); + for (DatasetVersion dsvTest : versionsList) { + if (retVal == null) { + retVal = dsvTest; + } else { + if (retVal.getMinorVersionNumber().intValue() < dsvTest.getMinorVersionNumber().intValue()) { + retVal = dsvTest; + } + } + } + + return retVal; + + } catch (javax.persistence.NoResultException e) { + logger.warning("no ds version found: " + datasetId + " " + friendlyVersionNumber); + // DO nothing, just return null. + } + + } + + return null; + } + + /** + * Parse a Persistent Id and return as 3 strings. + * + * Example: 1.0, 1.1. 3.4, etc. + * + * @param version + * @return Long[] with [ major_version, minor_version ] + * - either or both may be null + */ + public Long[] parseVersionNumber(String version){ + if (version == null){ + return null; + } + + Long majorVersion; + Long minorVersion = null; + + String[] vparts = version.split("\\."); + if (vparts.length == 1){ + try{ + majorVersion = Long.parseLong(vparts[0]); + }catch (NumberFormatException n) { + return null; + } + }else if (vparts.length == 2){ + try{ + majorVersion = Long.parseLong(vparts[0]); + minorVersion = Long.parseLong(vparts[1]); + }catch (NumberFormatException n) { + return null; + } + }else{ + return null; + } + + Long versionNumbers[] = { majorVersion, minorVersion }; + + return versionNumbers; + } + + + + private void msg(String s){ + //logger.fine(s); + } + + /** + * Does the version identifier in the URL ask for a "DRAFT"? + * + * @param version + * @return boolean + */ + private boolean isVersionAskingForDraft(String version){ + + if (version == null){ + return false; + } + + return version.toUpperCase().equals(VersionState.DRAFT.toString()); + } + + private String getDatasetVersionBasicQuery(String identifierClause, String extraClause){ + + if (identifierClause == null){ + return null; + } + + if (extraClause == null){ + extraClause = ""; + } + + String queryStr = "SELECT dv.* FROM DatasetVersion dv"; + queryStr += " INNER JOIN Dataset ds"; + queryStr += " ON dv.dataset_id=ds.id"; + queryStr += identifierClause; // either persistentId or id + queryStr += extraClause; // may be an empty string + queryStr += " ORDER BY versionNumber DESC, minorVersionNumber DESC"; + queryStr += " LIMIT 1;"; + + return queryStr; + + } + + + /** + * Query to return the last Released DatasetVersion by Persistent ID + * + * @param identifierClause - query clause to retrieve via DatasetVersion.Id or DatasetVersion.persistentId + * @return String fullQuery + */ + private String getLatestReleasedDatasetVersionQuery(String identifierClause){ + + if (identifierClause == null){ + return null; + } + String releasedClause = " AND dv.versionstate = '" + VersionState.RELEASED.toString() + "'"; + + return getDatasetVersionBasicQuery(identifierClause, releasedClause); + + } + + /** + * Query to return a DatasetVersion by Specific Version + * + * @param identifierClause - query clause to retrieve via DatasetVersion.Id or DatasetVersion.persistentId + * @return String fullQuery + */ + private String getNumericDatasetVersionQueryByIdentifier(String identifierClause, Long majorVersion, Long minorVersion){ + + if (identifierClause == null){ + return null; + } + String extraQueryClause = ""; + + + // For an exact version: retrieve either RELEASED or DEACCESSIONED + // + if (majorVersion != null && minorVersion != null){ + extraQueryClause += " AND dv.versionNumber= " + majorVersion; + extraQueryClause += " AND dv.minorVersionNumber= " + minorVersion; + extraQueryClause += " AND (dv.versionstate = '" + VersionState.RELEASED.toString() + "' or dv.versionstate = '" + VersionState.DEACCESSIONED.toString() + "')"; + } else { + // Last released major version + // + extraQueryClause += " AND dv.versionNumber= " + majorVersion; + extraQueryClause += " AND dv.versionstate = '" + VersionState.RELEASED.toString() + "'"; + } + + return getDatasetVersionBasicQuery(identifierClause, extraQueryClause); + + } + + /** + * Query to return a Draft DatasetVersion by Persistent ID + * + * @param identifierClause - query clause to retrieve via DatasetVersion.Id or DatasetVersion.persistentId + * @return String fullQuery + */ + private String getDraftDatasetVersionQuery(String identifierClause){ + + if (identifierClause == null){ + return null; + } + String draftClause = " AND dv.versionstate = '" + VersionState.DRAFT.toString() + "'"; + + return getDatasetVersionBasicQuery(identifierClause, draftClause); + + } + + /** + * Query to return a DEACCESSIONED DatasetVersion by Persistent ID + * + * @param identifierClause - query clause to retrieve via DatasetVersion.Id or DatasetVersion.persistentId + * @return String fullQuery + */ + private String getDeaccessionedDatasetVersionQuery(String identifierClause){ + + if (identifierClause == null){ + return null; + } + String draftClause = " AND dv.versionstate = '" + VersionState.DEACCESSIONED.toString() + "'"; + + return getDatasetVersionBasicQuery(identifierClause, draftClause); + + } + + + + + /** + * Execute a query to return DatasetVersion + * + * @param queryString + * @return + */ + private DatasetVersion getDatasetVersionByQuery(String queryString){ + msg("getDatasetVersionByQuery queryString: " + queryString); + if (queryString == null){ + return null; + } + + // Inexact check to see if one of the selected tables is DATASETVERSION + // + if (!queryString.toUpperCase().contains("FROM DATASETVERSION")){ + throw new IllegalArgumentException("This query does not select from the table DATASETVERSION"); + } + + try{ + Query query = em.createNativeQuery(queryString, DatasetVersion.class); + DatasetVersion ds = (DatasetVersion) query.getSingleResult(); + + msg("Found: " + ds); + return ds; + + } catch (javax.persistence.NoResultException e) { + msg("DatasetVersion not found: " + queryString); + logger.log(Level.FINE, "DatasetVersion not found: {0}", queryString); + return null; + } catch (EJBException e) { + logger.log(Level.WARNING, "EJBException exception: {0}", e.getMessage()); + return null; + } + } // end getDatasetVersionByQuery + + + + + public DatasetVersion retrieveDatasetVersionByIdentiferClause(String identifierClause, String version){ + + if (identifierClause == null){ + return null; + } + + DatasetVersion chosenVersion; + + /* -------------------------------------------- + (1) Scenario: User asking for a DRAFT? + - (1a) Look for draft + - (1b) Not found: Get Latest Release + - Permissions: check on DatasetPage + -------------------------------------------- */ + if (DatasetVersionServiceBean.this.isVersionAskingForDraft(version)){ + + // (1a) Try to retrieve a draft + msg("(1a) Try to retrieve a draft"); + String draftQuery = this.getDraftDatasetVersionQuery(identifierClause); + chosenVersion = this.getDatasetVersionByQuery(draftQuery); + + // Draft Exists! Return it! + msg("Draft Exists! Return it!"); + if (chosenVersion != null){ + return chosenVersion; // let DatasetPage check permissions + } + + // (1b) No draft found - check for last released + msg("(1b) No draft found - check for last released"); + String lastReleasedQuery = this.getLatestReleasedDatasetVersionQuery(identifierClause); + chosenVersion = this.getDatasetVersionByQuery(lastReleasedQuery); + + return chosenVersion; // This may be null -- let DatasetPage check + } + // END: User asking for a Draft + + /* -------------------------------------------- + (2) Scenario: Version specified + - (2a) Look for major and minor version - RELEASE OR DEACCESSIONED + - OR Look for major version - RELEASE + - (2c) Not found: look for latest released version + - (2c) Not found: look for DEACCESSIONED + - (2d) Not found: look for draft + - Permissions: check on DatasetPage + + (3) Scenario: No version specified + - Same as (2c)(2d) above + - Permissions: check on DatasetPage + -------------------------------------------- */ + Long[] versionNumbers = parseVersionNumber(version); + if (versionNumbers != null && versionNumbers.length == 2){ // At least a major version found + + // (2a) Look for major and minor version - RELEASE OR DEACCESSIONED + msg("(2a) Look for major and minor version -" + Arrays.toString(versionNumbers)); + String specificVersionQuery = this.getNumericDatasetVersionQueryByIdentifier(identifierClause, versionNumbers[0], versionNumbers[1]); + + chosenVersion = this.getDatasetVersionByQuery(specificVersionQuery); + if (chosenVersion != null){ + return chosenVersion; + } + } + + // (2b) Look for latest released version + msg("(2b) Look for latest released version"); + String latestVersionQuery = this.getLatestReleasedDatasetVersionQuery(identifierClause); + //msg("latestVersionQuery: " + latestVersionQuery); + chosenVersion = this.getDatasetVersionByQuery(latestVersionQuery); + if (chosenVersion != null){ + return chosenVersion; + } + + // (2c) Look for DEACCESSIONED + msg("(2c) Look for draft"); + String dQuery = this.getDeaccessionedDatasetVersionQuery(identifierClause); + //msg("draftQuery: " + draftQuery); + chosenVersion = this.getDatasetVersionByQuery(dQuery); + if (chosenVersion != null){ + return chosenVersion; + } + + // (2d) Look for draft + msg("(2d) Look for draft"); + String draftQuery = this.getDraftDatasetVersionQuery(identifierClause); + //msg("draftQuery: " + draftQuery); + chosenVersion = this.getDatasetVersionByQuery(draftQuery); + + return chosenVersion; // This may be null -- let DatasetPage check + + + } // end: retrieveDatasetVersionByPersistentId + + + /** + * Find a DatasetVersion using the persisentID and version string + * + * @param persistentId doi:10.5072/FK2/BYM3IW + * @param version "DRAFT", 1.0, 2, 3.4, null, etc + * @return + */ + public RetrieveDatasetVersionResponse retrieveDatasetVersionByPersistentId(String persistentId, String version){ + + msg("retrieveDatasetVersionByPersistentId: " + persistentId + " " + version); + if (persistentId==null){ + return null; + } + + /* + Parse the persistent id + */ + GlobalId parsedId; + try{ + parsedId = new GlobalId(persistentId); // [ protocol, authority, identifier] + } catch (IllegalArgumentException e){ + logger.log(Level.WARNING, "Failed to parse persistentID: {0}", persistentId); + return null; + } + + String identifierClause = " AND ds.protocol= '" + parsedId.getProtocol() + "'"; + identifierClause += " AND ds.authority = '" + parsedId.getAuthority() + "'"; + identifierClause += " AND ds.identifier = '" + parsedId.getIdentifier() + "'"; + + + DatasetVersion ds = retrieveDatasetVersionByIdentiferClause(identifierClause, version); + + if (ds != null){ + msg("retrieved dataset: " + ds.getId() + " semantic: " + ds.getSemanticVersion()); + return new RetrieveDatasetVersionResponse(ds, version); + } + + return null; + + } + + + + /** + * Find a DatasetVersion using the persisentID and version string + * + * @param datasetId + * @param version "DRAFT", 1.0, 2, 3.4, null, etc + * @return + */ + public RetrieveDatasetVersionResponse retrieveDatasetVersionById(Long datasetId, String version){ + msg("retrieveDatasetVersionById: " + datasetId + " " + version); + if (datasetId==null){ + return null; + } + + String identifierClause = " AND ds.id = " + datasetId; + + DatasetVersion ds = retrieveDatasetVersionByIdentiferClause(identifierClause, version); + + if (ds != null){ + return new RetrieveDatasetVersionResponse(ds, version); + } + + return null; + + + } // end: retrieveDatasetVersionById + + + /** + * Find a DatasetVersion using the dataset versionId + * + * @param versionId DatasetVersion id + * @return + */ + public RetrieveDatasetVersionResponse retrieveDatasetVersionByVersionId(Long versionId){ + //msg("retrieveDatasetVersionById: " + datasetId + " " + versionId); + if (versionId==null ){ + return null; + } + + // Try versionId - release state doesn't matte + // + String identifierClause = " and dv.id = " + versionId; + String retrieveSpecifiedDSVQuery = getDatasetVersionBasicQuery(identifierClause, null); + DatasetVersion chosenVersion = this.getDatasetVersionByQuery(retrieveSpecifiedDSVQuery); + if (chosenVersion != null) { + return new RetrieveDatasetVersionResponse(chosenVersion, ""); + } + return null; + } // end: retrieveDatasetVersionByVersionId + +} // end class
