mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
Merge pull request #1479 from tdonohue/DS-3277
DS-3277 : Create new 'handle_id_seq' for handle_id column. Use 'handle_seq' to mint new handles.
This commit is contained in:
@@ -26,8 +26,8 @@ public class Handle implements ReloadableEntity<Integer> {
|
||||
|
||||
@Id
|
||||
@Column(name="handle_id")
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE ,generator="handle_seq")
|
||||
@SequenceGenerator(name="handle_seq", sequenceName="handle_seq", allocationSize = 1)
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="handle_id_seq")
|
||||
@SequenceGenerator(name="handle_id_seq", sequenceName="handle_id_seq", allocationSize = 1)
|
||||
private Integer id;
|
||||
|
||||
@Column(name = "handle", unique = true)
|
||||
@@ -57,6 +57,7 @@ public class Handle implements ReloadableEntity<Integer> {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getID() {
|
||||
return id;
|
||||
}
|
||||
@@ -91,6 +92,7 @@ public class Handle implements ReloadableEntity<Integer> {
|
||||
return resourceTypeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
@@ -105,6 +107,7 @@ public class Handle implements ReloadableEntity<Integer> {
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(id)
|
||||
|
@@ -8,20 +8,22 @@
|
||||
package org.dspace.handle;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.service.SiteService;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.handle.dao.HandleDAO;
|
||||
import org.dspace.handle.service.HandleService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Interface to the <a href="http://www.handle.net" target=_new>CNRI Handle
|
||||
* System </a>.
|
||||
@@ -46,6 +48,8 @@ public class HandleServiceImpl implements HandleService
|
||||
@Autowired(required = true)
|
||||
protected HandleDAO handleDAO;
|
||||
|
||||
@Autowired(required = true)
|
||||
protected ConfigurationService configurationService;
|
||||
|
||||
@Autowired
|
||||
protected SiteService siteService;
|
||||
@@ -66,7 +70,7 @@ public class HandleServiceImpl implements HandleService
|
||||
return null;
|
||||
}
|
||||
|
||||
String url = ConfigurationManager.getProperty("dspace.url")
|
||||
String url = configurationService.getProperty("dspace.url")
|
||||
+ "/handle/" + handle;
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
@@ -81,9 +85,9 @@ public class HandleServiceImpl implements HandleService
|
||||
public String resolveUrlToHandle(Context context, String url)
|
||||
throws SQLException
|
||||
{
|
||||
String dspaceUrl = ConfigurationManager.getProperty("dspace.url")
|
||||
String dspaceUrl = configurationService.getProperty("dspace.url")
|
||||
+ "/handle/";
|
||||
String handleResolver = ConfigurationManager.getProperty("handle.canonical.prefix");
|
||||
String handleResolver = configurationService.getProperty("handle.canonical.prefix");
|
||||
|
||||
String handle = null;
|
||||
|
||||
@@ -119,8 +123,8 @@ public class HandleServiceImpl implements HandleService
|
||||
// Let the admin define a new prefix, if not then we'll use the
|
||||
// CNRI default. This allows the admin to use "hdl:" if they want to or
|
||||
// use a locally branded prefix handle.myuni.edu.
|
||||
String handlePrefix = ConfigurationManager.getProperty("handle.canonical.prefix");
|
||||
if (handlePrefix == null || handlePrefix.length() == 0)
|
||||
String handlePrefix = configurationService.getProperty("handle.canonical.prefix");
|
||||
if (StringUtils.isBlank(handlePrefix))
|
||||
{
|
||||
handlePrefix = "http://hdl.handle.net/";
|
||||
}
|
||||
@@ -133,7 +137,7 @@ public class HandleServiceImpl implements HandleService
|
||||
throws SQLException
|
||||
{
|
||||
Handle handle = handleDAO.create(context, new Handle());
|
||||
String handleId = createId(handle.getID());
|
||||
String handleId = createId(context);
|
||||
|
||||
handle.setHandle(handleId);
|
||||
handle.setDSpaceObject(dso);
|
||||
@@ -302,8 +306,8 @@ public class HandleServiceImpl implements HandleService
|
||||
@Override
|
||||
public String getPrefix()
|
||||
{
|
||||
String prefix = ConfigurationManager.getProperty("handle.prefix");
|
||||
if (null == prefix)
|
||||
String prefix = configurationService.getProperty("handle.prefix");
|
||||
if (StringUtils.isBlank(prefix))
|
||||
{
|
||||
prefix = EXAMPLE_PREFIX; // XXX no good way to exit cleanly
|
||||
log.error("handle.prefix is not configured; using " + prefix);
|
||||
@@ -386,18 +390,22 @@ public class HandleServiceImpl implements HandleService
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new handle id. The implementation uses the PK of the RDBMS
|
||||
* Handle table.
|
||||
* Create/mint a new handle id.
|
||||
*
|
||||
* @param context DSpace Context
|
||||
* @return A new handle id
|
||||
* @exception SQLException
|
||||
* If a database error occurs
|
||||
*/
|
||||
protected String createId(int id) throws SQLException
|
||||
protected String createId(Context context) throws SQLException
|
||||
{
|
||||
// Get configured prefix
|
||||
String handlePrefix = getPrefix();
|
||||
|
||||
return handlePrefix + (handlePrefix.endsWith("/") ? "" : "/") + id;
|
||||
// Get next available suffix (as a Long, since DSpace uses an incrementing sequence)
|
||||
Long handleSuffix = handleDAO.getNextHandleSuffix(context);
|
||||
|
||||
return handlePrefix + (handlePrefix.endsWith("/") ? "" : "/") + handleSuffix.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -24,6 +24,8 @@ import java.util.List;
|
||||
*/
|
||||
public interface HandleDAO extends GenericDAO<Handle> {
|
||||
|
||||
public Long getNextHandleSuffix(Context context) throws SQLException;
|
||||
|
||||
public List<Handle> getHandlesByDSpaceObject(Context context, DSpaceObject dso) throws SQLException;
|
||||
|
||||
public Handle findByHandle(Context context, String handle)throws SQLException;
|
||||
|
@@ -7,6 +7,9 @@
|
||||
*/
|
||||
package org.dspace.handle.dao.impl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.AbstractHibernateDAO;
|
||||
@@ -15,6 +18,10 @@ import org.dspace.handle.dao.HandleDAO;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.jdbc.ReturningWork;
|
||||
import org.hibernate.service.jdbc.dialect.internal.StandardDialectResolver;
|
||||
import org.hibernate.service.jdbc.dialect.spi.DialectResolver;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
@@ -29,6 +36,9 @@ import java.util.List;
|
||||
*/
|
||||
public class HandleDAOImpl extends AbstractHibernateDAO<Handle> implements HandleDAO
|
||||
{
|
||||
// The name of the sequence used to determine next available handle
|
||||
private static final String HANDLE_SEQUENCE = "handle_seq";
|
||||
|
||||
protected HandleDAOImpl()
|
||||
{
|
||||
super();
|
||||
@@ -94,4 +104,45 @@ public class HandleDAOImpl extends AbstractHibernateDAO<Handle> implements Handl
|
||||
public int countRows(Context context) throws SQLException {
|
||||
return count(createQuery(context, "SELECT count(*) FROM Handle"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return next available value of Handle suffix (based on DB sequence).
|
||||
* @param context Current DSpace Context
|
||||
* @return next available Handle suffix (as a Long)
|
||||
* @throws SQLException if database error or sequence doesn't exist
|
||||
*/
|
||||
@Override
|
||||
public Long getNextHandleSuffix(Context context) throws SQLException
|
||||
{
|
||||
// Create a new Hibernate ReturningWork, which will return the
|
||||
// result of the next value in the Handle Sequence.
|
||||
ReturningWork<Long> nextValReturningWork = new ReturningWork<Long>() {
|
||||
@Override
|
||||
public Long execute(Connection connection) throws SQLException {
|
||||
Long nextVal = 0L;
|
||||
|
||||
// Determine what dialect we are using for this DB
|
||||
DialectResolver dialectResolver = new StandardDialectResolver();
|
||||
Dialect dialect = dialectResolver.resolveDialect(connection.getMetaData());
|
||||
|
||||
// Find the next value in our sequence (based on DB dialect)
|
||||
try (PreparedStatement preparedStatement = connection.prepareStatement(dialect.getSequenceNextValString(HANDLE_SEQUENCE)))
|
||||
{
|
||||
// Execute query and return results
|
||||
try(ResultSet resultSet = preparedStatement.executeQuery())
|
||||
{
|
||||
if(resultSet.next())
|
||||
{
|
||||
// Return result of query (from first column)
|
||||
nextVal = resultSet.getLong(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nextVal;
|
||||
}
|
||||
};
|
||||
|
||||
// Run our work, returning the next value in the sequence (see 'nextValReturningWork' above)
|
||||
return getHibernateSession(context).doReturningWork(nextValReturningWork);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,30 @@
|
||||
--
|
||||
-- The contents of this file are subject to the license and copyright
|
||||
-- detailed in the LICENSE and NOTICE files at the root of the source
|
||||
-- tree and available online at
|
||||
--
|
||||
-- http://www.dspace.org/license/
|
||||
--
|
||||
|
||||
------------------------------------------------------
|
||||
-- DS-2775 Drop unused sequences
|
||||
------------------------------------------------------
|
||||
|
||||
DROP SEQUENCE bitstream_seq;
|
||||
DROP SEQUENCE bundle2bitstream_seq;
|
||||
DROP SEQUENCE bundle_seq;
|
||||
DROP SEQUENCE collection2item_seq;
|
||||
DROP SEQUENCE collection_seq;
|
||||
DROP SEQUENCE community2collection_seq;
|
||||
DROP SEQUENCE community2community_seq;
|
||||
DROP SEQUENCE community_seq;
|
||||
DROP SEQUENCE dcvalue_seq;
|
||||
DROP SEQUENCE eperson_seq;
|
||||
DROP SEQUENCE epersongroup2eperson_seq;
|
||||
DROP SEQUENCE epersongroup2workspaceitem_seq;
|
||||
DROP SEQUENCE epersongroup_seq;
|
||||
DROP SEQUENCE group2group_seq;
|
||||
DROP SEQUENCE group2groupcache_seq;
|
||||
DROP SEQUENCE historystate_seq;
|
||||
DROP SEQUENCE item2bundle_seq;
|
||||
DROP SEQUENCE item_seq;
|
@@ -0,0 +1,15 @@
|
||||
--
|
||||
-- The contents of this file are subject to the license and copyright
|
||||
-- detailed in the LICENSE and NOTICE files at the root of the source
|
||||
-- tree and available online at
|
||||
--
|
||||
-- http://www.dspace.org/license/
|
||||
--
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
-- DS-3277 : 'handle_id' column needs its own separate sequence, so that Handles
|
||||
-- can be minted from 'handle_seq'
|
||||
----------------------------------------------------------------------------------
|
||||
-- Create a new sequence for 'handle_id' column.
|
||||
-- The role of this sequence is to simply provide a unique internal ID to the database.
|
||||
CREATE SEQUENCE handle_id_seq;
|
@@ -0,0 +1,44 @@
|
||||
--
|
||||
-- The contents of this file are subject to the license and copyright
|
||||
-- detailed in the LICENSE and NOTICE files at the root of the source
|
||||
-- tree and available online at
|
||||
--
|
||||
-- http://www.dspace.org/license/
|
||||
--
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
-- DS-3277 : 'handle_id' column needs its own separate sequence, so that Handles
|
||||
-- can be minted from 'handle_seq'
|
||||
----------------------------------------------------------------------------------
|
||||
-- Create a new sequence for 'handle_id' column.
|
||||
-- The role of this sequence is to simply provide a unique internal ID to the database.
|
||||
CREATE SEQUENCE handle_id_seq;
|
||||
-- Initialize new 'handle_id_seq' to the maximum value of 'handle_id'
|
||||
DECLARE
|
||||
curr NUMBER := 0;
|
||||
BEGIN
|
||||
SELECT max(handle_id) INTO curr FROM handle;
|
||||
|
||||
curr := curr + 1;
|
||||
|
||||
EXECUTE IMMEDIATE 'DROP SEQUENCE handle_id_seq';
|
||||
|
||||
EXECUTE IMMEDIATE 'CREATE SEQUENCE handle_id_seq START WITH ' || NVL(curr,1);
|
||||
END;
|
||||
/
|
||||
|
||||
-- Ensure the 'handle_seq' is updated to the maximum *suffix* in 'handle' column,
|
||||
-- as this sequence is used to mint new Handles.
|
||||
-- Code borrowed from update-sequences.sql and updateseq.sql
|
||||
DECLARE
|
||||
curr NUMBER := 0;
|
||||
BEGIN
|
||||
SELECT max(to_number(regexp_replace(handle, '.*/', ''), '999999999999')) INTO curr FROM handle WHERE REGEXP_LIKE(handle, '^.*/[0123456789]*$');
|
||||
|
||||
curr := curr + 1;
|
||||
|
||||
EXECUTE IMMEDIATE 'DROP SEQUENCE handle_seq';
|
||||
|
||||
EXECUTE IMMEDIATE 'CREATE SEQUENCE handle_seq START WITH ' || NVL(curr,1);
|
||||
END;
|
||||
/
|
@@ -0,0 +1,30 @@
|
||||
--
|
||||
-- The contents of this file are subject to the license and copyright
|
||||
-- detailed in the LICENSE and NOTICE files at the root of the source
|
||||
-- tree and available online at
|
||||
--
|
||||
-- http://www.dspace.org/license/
|
||||
--
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
-- DS-3277 : 'handle_id' column needs its own separate sequence, so that Handles
|
||||
-- can be minted from 'handle_seq'
|
||||
----------------------------------------------------------------------------------
|
||||
-- Create a new sequence for 'handle_id' column.
|
||||
-- The role of this sequence is to simply provide a unique internal ID to the database.
|
||||
CREATE SEQUENCE handle_id_seq;
|
||||
-- Initialize new 'handle_id_seq' to the maximum value of 'handle_id'
|
||||
SELECT setval('handle_id_seq', max(handle_id)) FROM handle;
|
||||
|
||||
-- Ensure the 'handle_seq' is updated to the maximum *suffix* in 'handle' column,
|
||||
-- as this sequence is used to mint new Handles.
|
||||
-- Code borrowed from update-sequences.sql
|
||||
SELECT setval('handle_seq',
|
||||
CAST (
|
||||
max(
|
||||
to_number(regexp_replace(handle, '.*/', ''), '999999999999')
|
||||
)
|
||||
AS BIGINT)
|
||||
)
|
||||
FROM handle
|
||||
WHERE handle SIMILAR TO '%/[0123456789]*';
|
@@ -61,7 +61,9 @@
|
||||
@updateseq.sql metadataschemaregistry_seq metadataschemaregistry metadata_schema_id ""
|
||||
@updateseq.sql harvested_collection_seq harvested_collection id ""
|
||||
@updateseq.sql harvested_item_seq harvested_item id ""
|
||||
@updateseq.sql webapp_seq webapp id ""
|
||||
@updateseq.sql webapp_seq webapp webapp_id ""
|
||||
@updateseq.sql requestitem_seq requestitem requestitem_id ""
|
||||
@updateseq.sql handle_id_seq handle handle_id ""
|
||||
|
||||
-- Handle Sequence is a special case. Since Handles minted by DSpace use the 'handle_seq',
|
||||
-- we need to ensure the next assigned handle will *always* be unique. So, 'handle_seq'
|
||||
|
@@ -60,6 +60,7 @@ SELECT setval('harvested_collection_seq', max(id)) FROM harvested_collection;
|
||||
SELECT setval('harvested_item_seq', max(id)) FROM harvested_item;
|
||||
SELECT setval('webapp_seq', max(webapp_id)) FROM webapp;
|
||||
SELECT setval('requestitem_seq', max(requestitem_id)) FROM requestitem;
|
||||
SELECT setval('handle_id_seq', max(handle_id)) FROM handle;
|
||||
|
||||
-- Handle Sequence is a special case. Since Handles minted by DSpace use the 'handle_seq',
|
||||
-- we need to ensure the next assigned handle will *always* be unique. So, 'handle_seq'
|
||||
|
Reference in New Issue
Block a user