/**
- * IDResource
- *
- * Resource class to handle requests to the ID Service.
- *
* This document is a part of the source code and related artifacts
* for CollectionSpace, an open source collections management system
* for museums and related institutions:
* You may obtain a copy of the ECL 2.0 License at
* https://source.collectionspace.org/collection-space/LICENSE.txt
*
- * Based on work by Richard Millet and Sanjay Dalal.
- *
- * $LastChangedBy$
- * $LastChangedRevision$
- * $LastChangedDate$
+ * Based in part on work by Richard Millet and Sanjay Dalal.
*/
package org.collectionspace.services.id;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
+import javax.ws.rs.POST;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.slf4j.LoggerFactory;
// Set the base path component for URLs that access this service.
-@Path("/ids")
+@Path("/idgenerators")
// Identify the default MIME media types consumed and produced by this service.
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
+/**
+ * IDResource
+ *
+ * Resource class to handle requests to the ID Service.
+ *
+ * $LastChangedBy$
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ */
public class IDResource {
final Logger logger = LoggerFactory.getLogger(IDResource.class);
//////////////////////////////////////////////////////////////////////
/**
- * Returns the next available ID associated with a specified ID pattern.
- *
- * @param csid An identifier for an ID pattern.
+ * Generates and returns a new ID, from the specified ID generator.
*
- * @return The next available ID associated with the specified ID pattern.
- *
- * @TODO: We're currently using simple integer IDs to identify ID patterns
- * in this initial iteration.
+ * @param csid An identifier for an ID generator.
*
- * To uniquely identify ID patterns in production, we'll need to handle
- * both CollectionSpace IDs (csids) - a form of UUIDs/GUIDs - and some
- * other form of identifier to be determined, such as URLs or URNs.
+ * @return A new ID from the specified ID generator.
*/
- @GET
- // @TODO: Temporary during early testing.
- // To be changed to a POST request, and most likely to a different URL.
- // E.g. /idpatterns/{identifier}/ids
- @Path("/next/patterns/{csid}")
- // @TODO: Temporary during testing; to be changed to return XML
+ @POST
+ @Path("/{csid}/ids")
@Produces("text/plain")
- public Response getNextID(@PathParam("csid") String csid) {
+ public Response newID(@PathParam("csid") String csid) {
- logger.debug("> in getNextID(String)");
+ logger.debug("> in newID(String)");
+
+ // @TODO The JavaDoc description reflects an as-yet-to-be-carried out
+ // refactoring, in which the highest object type in the ID service
+ // is that of an IDGenerator, some or all of which may be composed
+ // of IDParts. Some IDGenerators generate IDs based on patterns,
+ // which may be composed in part of incrementing numeric or alphabetic
+ // components, while others may not (e.g. UUIDs, web services-based
+ // responses).
+
+ // @TODO We're currently using simple integer IDs to identify ID generators
+ // in this initial iteration.
+ //
+ // To uniquely identify ID generators in production, we'll need to handle
+ // both CollectionSpace IDs (csids) - a form of UUIDs/GUIDs - and some
+ // other form of identifier to be determined, such as URLs or URNs.
+
+ // @TODO We're currently returning IDs in plain text. Identify whether
+ // there is a requirement to return an XML representation, and/or any
+ // other representations.
- // Unless the 'response' variable is explicitly initialized here, the
- // compiler gives the error: "variable response might not have been initialized."
+ // Unless the 'response' variable is explicitly initialized here,
+ // the compiler gives the error: "variable response might not have
+ // been initialized."
Response response = null;
response = response.ok().build();
- String nextId = "";
+ String newId = "";
try {
- // Retrieve the next ID for the requested pattern,
+ // Obtain a new ID from the specified ID generator,
// and return it in the entity body of the response.
- nextId = service.nextID(csid);
+ newId = service.newID(csid);
- if (nextId == null || nextId.equals("")) {
+ if (newId == null || newId.equals("")) {
response = Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("ID Service returned null or empty ID").type(MediaType.TEXT_PLAIN).build();
return response;
}
response = Response.status(Response.Status.OK)
- .entity(nextId).type(MediaType.TEXT_PLAIN).build();
+ .entity(newId).type(MediaType.TEXT_PLAIN).build();
- // @TODO: Return an XML-based error results format with the
+ // @TODO Return an XML-based error results format with the
// responses below.
- // @TODO: An IllegalStateException often indicates an overflow
+ // @TODO An IllegalStateException often indicates an overflow
// of an IDPart. Consider whether returning a 400 Bad Request
// status code is still warranted, or whether returning some other
// status would be more appropriate.
+
} catch (IllegalStateException ise) {
response = Response.status(Response.Status.BAD_REQUEST)
.entity(ise.getMessage()).type(MediaType.TEXT_PLAIN).build();
/**
- * IDService
- *
- * Interface for the methods of the ID Service.
- *
* This document is a part of the source code and related artifacts
* for CollectionSpace, an open source collections management system
* for museums and related institutions:
*
* You may obtain a copy of the ECL 2.0 License at
* https://source.collectionspace.org/collection-space/LICENSE.txt
+ */
+
+package org.collectionspace.services.id;
+
+/**
+ * IDService
*
- * Based on work by Richard Millet and Sanjay Dalal.
+ * Interface for the ID Service.
*
* $LastChangedBy$
* $LastChangedRevision$
* $LastChangedDate$
*/
-
-package org.collectionspace.services.id;
-
public interface IDService {
// ----------------------------------------
// Read single object
- // Returns the next ID associated with a specified ID pattern.
- public String nextID(String csid)
+ // Generates and returns a new ID from the specified ID generator.
+ public String newID(String csid)
throws IllegalArgumentException, IllegalStateException;
- // Returns the last generated ID associated with a specified ID pattern.
+ // Returns the last-generated ID associated with the specified ID generator.
public String getLastID(String csid)
throws IllegalArgumentException, IllegalStateException;
// ID Patterns
// ----------------------------------------
+ // @TODO Change this to IDGenerators in the next refactoring.
+
// Create
// Adds a new ID pattern.
/**
- * IDServiceJdbcImpl
- *
- * Implementation of portions of the ID Service that use JDBC
- * for persistence of IDPatterns, IDParts, and ID values.
- *
* This document is a part of the source code and related artifacts
* for CollectionSpace, an open source collections management system
* for museums and related institutions:
*
* You may obtain a copy of the ECL 2.0 License at
* https://source.collectionspace.org/collection-space/LICENSE.txt
- *
- * Based on work by Richard Millet and Sanjay Dalal.
- *
- * $LastChangedBy$
- * $LastChangedRevision$
- * $LastChangedDate$
*/
// @TODO: Revise exception handling to return custom Exceptions,
// a new IDPattern and returning its next ID. As a result,
// the generated IDs may well duplicate other, previously-generated IDs.
//
-// When we start storing IDPatterns and IDs in a database, the
+// When we start storing ID generators and IDs in a database, the
// the current ID associated with each pattern will be stored
// and modified in a single location.
//
-// At that point, we'll also need to add code to ensure that only
-// one IDPattern object is instantiated for each stored pattern,
-// at initialization or reset time, as well as to handle concurrent
-// requests.
+// At that point, we'll also need to add code to handle concurrent requests.
// @TODO: Verify access (public, protected, or private) to service methods.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+/**
+ * IDServiceJdbcImpl
+ *
+ * Manages the storage of ID generators and persistence of their
+ * current state, via a JDBC interface to an underlying database.
+ *
+ * $LastChangedBy$
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ */
public class IDServiceJdbcImpl implements IDService {
final Logger logger = LoggerFactory.getLogger(IDServiceJdbcImpl.class);
// @TODO Get the JDBC driver classname and database URL from configuration;
// better yet, substitute Hibernate for JDBC for accessing database-managed persistence.
- //
+
// @TODO: Remove any hard-coded dependencies on MySQL.
- //
+
// @TODO: Determine how to restrict access to ID-related tables by role.
+
final String JDBC_DRIVER_CLASSNAME = "com.mysql.jdbc.Driver";
final String DATABASE_URL = "jdbc:mysql://localhost:3306/cspace";
final String DATABASE_USERNAME = "test";
//////////////////////////////////////////////////////////////////////
/**
- * Returns the next ID associated with a specified ID pattern.
+ * Generates and returns a new ID associated with a specified ID generator.
*
* This method has an intentional side-effect: it sets the
- * current ID of that ID pattern to the just-generated ID.
+ * current ID of that ID generator to the just-generated ID.
*
- * @param csid An identifier for an ID pattern.
- *
- * @return The next ID associated with the specified ID pattern.
- *
- * @TODO: Implement logic to check for ID availability, after generating
- * a candidate ID.
+ * @param csid An identifier for an ID generator.
*
- * @TODO: We're currently using simple integer IDs to identify ID patterns
- * in this initial iteration.
- *
- * To uniquely identify ID patterns in production, we'll need to handle
- * both CollectionSpace IDs (csids) - a form of UUIDs/GUIDs - and some
- * other form of identifier to be determined, such as URLs or URNs.
- *
- * @TODO: Add checks for authorization to perform this operation.
+ * @return A new ID associated with the specified ID generator.
*/
- public String nextID(String csid) throws
+ public String newID(String csid) throws
IllegalArgumentException, IllegalStateException {
- logger.debug("> in nextID");
-
- String nextId = "";
+ logger.debug("> in newID");
+
+ // @TODO Where relevant, implement logic to check for ID availability,
+ // after generating a candidate ID.
+
+ // @TODO We're currently using simple integer IDs to identify ID patterns
+ // in this initial iteration.
+ //
+ // To uniquely identify ID patterns in production, we'll need to handle
+ // both CollectionSpace IDs (csids) - a form of UUIDs/GUIDs - and some
+ // other form of identifier to be determined, such as URLs or URNs.
+ //
+ // @TODO: Add checks for authorization to perform this operation.
+
+ String newId = "";
String lastId = "";
if (csid == null || csid.equals("")) {
lastId = getLastID(csid);
// If there was no last generated ID associated with this pattern,
- // get the current ID generated by the pattern as the 'next' ID.
+ // get the current ID generated by the ID generator as the 'new' ID.
if (lastId == null || lastId.equals("")) {
- nextId = pattern.getCurrentID();
+ newId = pattern.getCurrentID();
- // Otherwise, generate the 'next' ID for this pattern, based on the last ID.
- // (This also sets the current ID for the pattern to this just-generated 'next' ID.)
+ // Otherwise, generate a new ID, potentially based on the last ID.
+ // (This also sets the current ID of the ID generator's state
+ // to this just-generated 'new' ID.)
} else {
- nextId = pattern.nextID(lastId);
+ newId = pattern.nextID(lastId);
}
- // Store the 'next' ID as the last-generated ID for this pattern.
- updateLastID(csid, nextId);
+ // Store the 'new' ID as the last-generated ID for this pattern.
+ updateLastID(csid, newId);
- // Store the new state of this ID Pattern, reflecting that one of its
- // parts may have had its value updated as a result of the generation
- // of this 'next' ID.
+ // Store the new state of this ID generator, reflecting that
+ // one of its parts may possibly have had its value updated as
+ // a result of the generation of this 'new' ID.
updateIDPattern(csid, pattern);
} catch (IllegalArgumentException e ) {
throw e;
}
- return nextId;
+ return newId;
}