From: Aron Roberts Date: Thu, 25 Jun 2009 03:17:22 +0000 (+0000) Subject: CSPACE-245: Initiated work on ID Service, via a shell project cloned from CollectionO... X-Git-Url: https://git.aero2k.de/?a=commitdiff_plain;h=1cf5d5cabd0ca83cb641ddc14f5838227a2879b9;p=tmp%2Fjakarta-migration.git CSPACE-245: Initiated work on ID Service, via a shell project cloned from CollectionObject. The vast majority of the project is currently commented out, and Client library dir was removed for now. Unit tests of POJOs currently succeed, and a rudimentary central Resource class can be compiled. The current IDPattern class will need to be refactored to split code from data. --- diff --git a/services/id/3rdparty/nuxeo-platform-cs-id/build.properties b/services/id/3rdparty/nuxeo-platform-cs-id/build.properties new file mode 100644 index 000000000..908e58f29 --- /dev/null +++ b/services/id/3rdparty/nuxeo-platform-cs-id/build.properties @@ -0,0 +1,15 @@ +# Example for Windows +# jboss.dir=c:/dev/jboss-4.2.3.GA +# Example for Unix +jboss.dir=/usr/local/jboss + +# Which JBoss server config to use +jboss.config=default + +# nuxeo deployment +jboss.nuxeo.ear.dir=${jboss.dir}/server/${jboss.config}/deploy/nuxeo.ear + + +# additional command line parameters for mvn commands +# e.g. to work offline: +#mvn.opts=-o diff --git a/services/id/3rdparty/nuxeo-platform-cs-id/build.xml b/services/id/3rdparty/nuxeo-platform-cs-id/build.xml new file mode 100644 index 000000000..d4e3b266c --- /dev/null +++ b/services/id/3rdparty/nuxeo-platform-cs-id/build.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/services/id/3rdparty/nuxeo-platform-cs-id/pom.xml b/services/id/3rdparty/nuxeo-platform-cs-id/pom.xml new file mode 100644 index 000000000..15cfd8db0 --- /dev/null +++ b/services/id/3rdparty/nuxeo-platform-cs-id/pom.xml @@ -0,0 +1,35 @@ + + 4.0.0 + + + org.nuxeo.ecm.platform + nuxeo-platform-parent + 5.2-SNAPSHOT + + + nuxeo-platform-cs-id + jar + nuxeo-platform-cs-id + + ID Nuxeo document type + + + 5.2-SNAPSHOT + 1.5-SNAPSHOT + + + + org.nuxeo.ecm.core + nuxeo-core-schema + ${nuxeo.version.1.5} + + + org.nuxeo.ecm.platform + nuxeo-platform-types-core + ${nuxeo.version.5.2} + + + + diff --git a/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/META-INF/MANIFEST.MF b/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 000000000..72874b4c1 --- /dev/null +++ b/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1,22 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 1 +Bundle-Name: NuxeoCS +Bundle-SymbolicName: org.collectionspace.collectionobject;singleton:=true +Bundle-Version: 1.0.0 +Bundle-Localization: plugin +Bundle-Vendor: Nuxeo +Require-Bundle: org.nuxeo.runtime, + org.nuxeo.ecm.core.api, + org.nuxeo.ecm.core, + org.nuxeo.ecm.core.api, + org.nuxeo.ecm.platform.types.api, + org.nuxeo.ecm.platform.versioning.api, + org.nuxeo.ecm.platform.ui, + org.nuxeo.ecm.platform.forms.layout.client, + org.nuxeo.ecm.platform.publishing.api, + org.nuxeo.ecm.platform.ws +Provide-Package: org.collectionspace.collectionobject +Nuxeo-Component: OSGI-INF/core-types-contrib.xml, + OSGI-INF/ecm-types-contrib.xml, + OSGI-INF/layouts-contrib.xml + diff --git a/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/OSGI-INF/core-types-contrib.xml b/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/OSGI-INF/core-types-contrib.xml new file mode 100644 index 000000000..72aa5ef19 --- /dev/null +++ b/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/OSGI-INF/core-types-contrib.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/OSGI-INF/deployment-fragment.xml b/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/OSGI-INF/deployment-fragment.xml new file mode 100644 index 000000000..88b94ffd1 --- /dev/null +++ b/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/OSGI-INF/deployment-fragment.xml @@ -0,0 +1,408 @@ + + + + + + ${bundle.fileName} + + + + + nuxeo.war + /nuxeo + + + + + + + + + + + + Seam Context Filter + /ws/FileManageWS + + + + Seam Context Filter + /DocumentManagerWS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #{currentServerLocation.name}/#{currentTabAction.label} + + + + Create new document in #{currentDocument.name} + + + + Create new document in #{currentDocument.name} + + + + breadcrumb=command.user_dashboard + + + + breadcrumb=command.manageMembers + + + + breadcrumb=command.manageMembers + + + + breadcrumb=title.vocabularies + + + + breadcrumb=command.advancedSearch + + + + + + en + en_GB + en_US + fr + de + es + it + ar + ru + ja + vn + + + messages + + + + config/addWorkspace.jpdl.xml + + + + + + generic_error_page + /generic_error_page.xhtml + + + + + generic_message_page + /generic_message_page.xhtml + + + + + home + /nxstartup.xhtml + + + + + user_login + /login.xhtml + + + + + user_logout + /logout.xhtml + + + + + view_servers + /view_servers.xhtml + + + + + + + view_domains + /view_domains.xhtml + + + + + select_document_type + /select_document_type.xhtml + + + + + create_document + /create_document.xhtml + + + + + edit_document + /edit_document.xhtml + + + + + view_documents + /view_documents.xhtml + + + + + create_file + /create_file.xhtml + + + + + create_workspace_wizard + /createWorkspaceWizard.xhtml + + + + + send_email + /document_email.xhtml + + + + + + view_workspaces + /view_workspaces.xhtml + + + + + + create_domain + /create_domain.xhtml + + + + + + edit_domain + /edit_domain.xhtml + + + + + + create_workspace + /create_workspace.xhtml + + + + + + edit_workspace + /edit_workspace.xhtml + + + + + + + members_management + /members_management.xhtml + + + + + view_users + /view_users.xhtml + + + + + view_many_users + /view_many_users.xhtml + + + + + edit_user + /edit_user.xhtml + + + + + edit_user_password + /edit_user_password.xhtml + + + + + view_user + /view_user.xhtml + + + + + create_user + /create_user.xhtml + + + + + view_groups + /view_groups.xhtml + + + + + view_group + /view_group.xhtml + + + + + edit_group + /edit_group.xhtml + + + + + create_group + /create_group.xhtml + + + + + view_vocabularies + /view_vocabularies.xhtml + + + + + view_vocabulary + /view_vocabulary.xhtml + + + + + + + search_form + /search/search_form.xhtml + + + + + search_results_nxql + /search/search_results_nxql.xhtml + + + + + search_results_advanced + + /search/search_results_advanced.xhtml + + + + + + search_results_simple + /search/search_results_simple.xhtml + + + + + + + clipboard + /incl/clipboard.xhtml + + + + + user_dashboard + /user_dashboard.xhtml + + + + + select_workspace_template + /select_workspace_template.xhtml + + + + + pdf_generation_error + /pdf_generation_error.xhtml + + + + + mass_edit + /massedit_documents.xhtml + + + + + mass_edit_confirm + /massedit_documents_preview.xhtml + + + + + + diff --git a/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/OSGI-INF/ecm-types-contrib.xml b/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/OSGI-INF/ecm-types-contrib.xml new file mode 100644 index 000000000..541251f1e --- /dev/null +++ b/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/OSGI-INF/ecm-types-contrib.xml @@ -0,0 +1,28 @@ + + + + + + + view_documents + + + heading + collectionobject + + + + + + CollectionObject + + + + + + CollectionObject + + + + + diff --git a/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/OSGI-INF/layouts-contrib.xml b/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/OSGI-INF/layouts-contrib.xml new file mode 100644 index 000000000..ee35a77d4 --- /dev/null +++ b/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/OSGI-INF/layouts-contrib.xml @@ -0,0 +1,129 @@ + + + + + + + + + + + + objectNumber + otherNumber + briefDescription + comments + distFeatures + objectName + responsibleDept + title + + + + + + + true + + objectNumber + + + dataInputText + + + + + + + + true + + otherNumber + + + dataInputText + + + + + + + + true + + briefDescription + + + dataInputText + + + + + + + + true + + comments + + + dataInputText + + + + + + + + true + + distFeatures + + + dataInputText + + + + + + + + true + + objectName + + + dataInputText + + + + + + + + true + + responsibleDept + + + dataInputText + + + + + + + + true + + title + + + dataInputText + + + + + + diff --git a/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/schemas/id.xsd b/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/schemas/id.xsd new file mode 100644 index 000000000..7c6e1c255 --- /dev/null +++ b/services/id/3rdparty/nuxeo-platform-cs-id/src/main/resources/schemas/id.xsd @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/services/id/3rdparty/pom.xml b/services/id/3rdparty/pom.xml new file mode 100644 index 000000000..b4e1485c1 --- /dev/null +++ b/services/id/3rdparty/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + + org.collectionspace.services.collectionobject + org.collectionspace.services + 1.0 + + + org.collectionspace.services.collectionobject.3rdparty + pom + services.collectionobject.3rdparty + + 3rd party build for collectionobject service + + + diff --git a/services/id/build.properties b/services/id/build.properties new file mode 100644 index 000000000..908e58f29 --- /dev/null +++ b/services/id/build.properties @@ -0,0 +1,15 @@ +# Example for Windows +# jboss.dir=c:/dev/jboss-4.2.3.GA +# Example for Unix +jboss.dir=/usr/local/jboss + +# Which JBoss server config to use +jboss.config=default + +# nuxeo deployment +jboss.nuxeo.ear.dir=${jboss.dir}/server/${jboss.config}/deploy/nuxeo.ear + + +# additional command line parameters for mvn commands +# e.g. to work offline: +#mvn.opts=-o diff --git a/services/id/jaxb/build.properties b/services/id/jaxb/build.properties new file mode 100644 index 000000000..908e58f29 --- /dev/null +++ b/services/id/jaxb/build.properties @@ -0,0 +1,15 @@ +# Example for Windows +# jboss.dir=c:/dev/jboss-4.2.3.GA +# Example for Unix +jboss.dir=/usr/local/jboss + +# Which JBoss server config to use +jboss.config=default + +# nuxeo deployment +jboss.nuxeo.ear.dir=${jboss.dir}/server/${jboss.config}/deploy/nuxeo.ear + + +# additional command line parameters for mvn commands +# e.g. to work offline: +#mvn.opts=-o diff --git a/services/id/jaxb/pom.xml b/services/id/jaxb/pom.xml new file mode 100644 index 000000000..222f54132 --- /dev/null +++ b/services/id/jaxb/pom.xml @@ -0,0 +1,101 @@ + + + + + org.collectionspace.services.id + org.collectionspace.services + 1.0 + + + 4.0.0 + org.collectionspace.services + org.collectionspace.services.idpattern.jaxb + 1.0 + services.id.jaxb + + + + com.sun.xml.bind + jaxb-impl + 2.0.2 + + + org.jvnet.jaxb2-commons + property-listener-injector + 1.0 + + + org.jvnet.jaxb2_commons + runtime + 0.4.1.4 + + + + collectionspace-services-idpattern-jaxb + install + + + org.jvnet.jaxb2.maven2 + maven-jaxb2-plugin + + + + generate + + + + + + + javax.activation + activation + 1.1 + + + com.sun.xml.bind + jaxb-impl + 2.1.2 + + + + + -XtoString + -Xinject-listener-code + + + + + + + org.jvnet.jaxb2_commons + + basic + 0.4.1 + + + + org.jvnet.jaxb2-commons + + + property-listener-injector + + 1.0 + + + + + + + maven-compiler-plugin + 2.0.2 + + 1.5 + 1.5 + + + + + diff --git a/services/id/jaxb/src/main/java/org/collectionspace/services/IDJAXBSchema.java b/services/id/jaxb/src/main/java/org/collectionspace/services/IDJAXBSchema.java new file mode 100644 index 000000000..bb797fbb4 --- /dev/null +++ b/services/id/jaxb/src/main/java/org/collectionspace/services/IDJAXBSchema.java @@ -0,0 +1,25 @@ + /* + * ID + * + * Schema for an identifier (ID). + * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +package org.collectionspace.services; + +public interface IDJAXBSchema { + final static String ID = "id"; +} + + diff --git a/services/id/jaxb/src/main/java/org/collectionspace/services/IDListItemJAXBSchema.java b/services/id/jaxb/src/main/java/org/collectionspace/services/IDListItemJAXBSchema.java new file mode 100644 index 000000000..91125f806 --- /dev/null +++ b/services/id/jaxb/src/main/java/org/collectionspace/services/IDListItemJAXBSchema.java @@ -0,0 +1,5 @@ +package org.collectionspace.services; + +public interface IDListItemJAXBSchema { + final static String ID = "id"; +} diff --git a/services/id/jaxb/src/main/java/org/collectionspace/services/IDPatternJAXBSchema.java b/services/id/jaxb/src/main/java/org/collectionspace/services/IDPatternJAXBSchema.java new file mode 100644 index 000000000..58f7b3020 --- /dev/null +++ b/services/id/jaxb/src/main/java/org/collectionspace/services/IDPatternJAXBSchema.java @@ -0,0 +1,28 @@ + /* + * IDPattern + * + * Models an identifier (ID), which consists of multiple IDParts. + * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +package org.collectionspace.services; + +public interface IDPatternJAXBSchema { + final static String ID_PATTERN_NAME = "idPatternName"; + final static String CSID = "csid"; + final static String URI = "uri"; + // Insert other fields here, corresponding to the schema declarations in id.xsd. +} + + diff --git a/services/id/jaxb/src/main/java/org/collectionspace/services/IDPatternListItemJAXBSchema.java b/services/id/jaxb/src/main/java/org/collectionspace/services/IDPatternListItemJAXBSchema.java new file mode 100644 index 000000000..7c958b8a1 --- /dev/null +++ b/services/id/jaxb/src/main/java/org/collectionspace/services/IDPatternListItemJAXBSchema.java @@ -0,0 +1,8 @@ +package org.collectionspace.services; + +public interface IDPatternListItemJAXBSchema { + final static String ID_PATTERN_NAME = "idPatternName"; + final static String CSID = "csid"; + final static String URI = "uri"; + // Insert other fields here, corresponding to the schema declarations in id.xsd. +} diff --git a/services/id/jaxb/src/main/resources/id.xsd b/services/id/jaxb/src/main/resources/id.xsd new file mode 100644 index 000000000..7c6e1c255 --- /dev/null +++ b/services/id/jaxb/src/main/resources/id.xsd @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/services/id/pom.xml b/services/id/pom.xml new file mode 100644 index 000000000..dc4de61f3 --- /dev/null +++ b/services/id/pom.xml @@ -0,0 +1,62 @@ + + + + org.collectionspace.services.main + org.collectionspace.services + 1.0 + + 4.0.0 + org.collectionspace.services + 1.0 + org.collectionspace.services.id + pom + services.id + + + 5.2-SNAPSHOT + 1.5-SNAPSHOT + + + + + service + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + org.apache.maven.plugins + maven-site-plugin + + /usr/bin/unzip -o > err.txt + + + + org.apache.maven.plugins + maven-war-plugin + 2.0.1 + + WEB-INF/lib/*.jar + + + true + + + + + + + + + diff --git a/services/id/service/pom.xml b/services/id/service/pom.xml new file mode 100644 index 000000000..e16cf8893 --- /dev/null +++ b/services/id/service/pom.xml @@ -0,0 +1,136 @@ + + + + + org.collectionspace.services.id + org.collectionspace.services + 1.0 + + + 4.0.0 + org.collectionspace.services + org.collectionspace.services.id.service + jar + 1.0 + services.id.service + + + + org.collectionspace.services + org.collectionspace.services.common + 1.0 + + + + junit + junit + 4.1 + test + + + org.testng + testng + 5.6 + + + + + + + + javax.security + jaas + 1.0.01 + provided + + + + dom4j + dom4j + 1.6.1 + provided + + + + + + org.jboss.resteasy + resteasy-jaxrs + 1.0.2.GA + + + tjws + webserver + + + + + org.jboss.resteasy + resteasy-jaxb-provider + 1.0.2.GA + + + org.jboss.resteasy + resteasy-multipart-provider + 1.0.2.GA + + + + + + org.nuxeo.ecm.core + nuxeo-core-api + ${nuxeo.version.1.5} + + + jboss-remoting + jboss + + + + + + org.restlet + org.restlet + 1.0.7 + + + com.noelios.restlet + com.noelios.restlet.ext.httpclient + 1.0.7 + + + com.noelios.restlet + com.noelios.restlet + 1.0.7 + + + + + + collectionspace-services-commonobject + + + org.codehaus.mojo + jboss-maven-plugin + + ${jboss.dir} + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + diff --git a/services/id/service/src/main/java/org/collectionspace/services/IDResource.java b/services/id/service/src/main/java/org/collectionspace/services/IDResource.java new file mode 100644 index 000000000..dfc5be286 --- /dev/null +++ b/services/id/service/src/main/java/org/collectionspace/services/IDResource.java @@ -0,0 +1,295 @@ +/* + * IDResource + * + * Resource class to handle requests to the ID Service. + * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * 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. + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + + package org.collectionspace.services; + +import java.util.Iterator; +import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.DELETE; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.PathParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; + +import org.collectionspace.services.IDService; +import org.collectionspace.services.id.*; +// import org.collectionspace.services.id.IDPatternList.*; +// import org.collectionspace.services.IDJAXBSchema; + +import org.dom4j.Document; +import org.dom4j.Element; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Path("/idpatterns") // Think long and hard about this ... +@Consumes("application/xml") +@Produces("application/xml") +public class IDResource { + + final Logger logger = LoggerFactory.getLogger(IDResource.class); + + // This should be a DI wired by a container like Spring, Seam, or EJB3 + // final static CollectionObjectService service = new CollectionObjectServiceNuxeoImpl(); + + public IDResource() { + // do nothing + } + + // Retrieve the next ID + @GET + @Path("/{csid}/ids/next") + @Produces("text/plain") + public String getCollectionObject(@PathParam("csid") String csid) { + return "foo"; // placeholder + } + +/* + @GET + public CollectionObjectList getCollectionObjectList(@Context UriInfo ui) { + CollectionObjectList p = new CollectionObjectList(); + try { + Document document = service.getCollectionObjectList(); + Element root = document.getRootElement(); + + // debug + System.err.println(document.asXML()); + + List list = p + .getCollectionObjectListItem(); + for (Iterator i = root.elementIterator(); i.hasNext();) { + Element element = (Element) i.next(); + // debug + System.err.println(); + element.asXML(); + + // set the CollectionObject list item entity elements + CollectionObjectListItem pli = new CollectionObjectListItem(); + pli.setObjectNumber(element.attributeValue("title")); + pli.setUri(element.attributeValue("url")); + pli.setCsid(element.attributeValue("id")); + list.add(pli); + } + + } catch (Exception e) { + e.printStackTrace(); + } + + return p; + } + + @POST + public Response createCollectionObject(CollectionObject co) { + + String csid = null; + try { + + Document document = service.postCollectionObject(co); + Element root = document.getRootElement(); + for (Iterator i = root.elementIterator(); i.hasNext();) { + Element element = (Element) i.next(); + if ("docRef".equals(element.getName())) { + csid = (String) element.getData(); + co.setCsid(csid); + } + } + } catch (Exception e) { + Response response = Response.status(Response.Status.NOT_FOUND) + .entity("Create failed").type("text/plain").build(); + throw new WebApplicationException(response); + } + + verbose("createCollectionObject: ", co); + UriBuilder path = UriBuilder + .fromResource(CollectionObjectResource.class); + path.path("" + csid); + Response response = Response.created(path.build()).build(); + + return response; + } + + @GET + @Path("{csid}") + public CollectionObject getCollectionObject(@PathParam("csid") String csid) { + + CollectionObject co = null; + try { + Document document = service.getCollectionObject(csid); + Element root = document.getRootElement(); + co = new CollectionObject(); + + // TODO: recognize schema thru namespace uri + // Namespace ns = new Namespace("collectionobject", + // "http://collectionspace.org/collectionobject"); + + Iterator siter = root.elementIterator("schema"); + while (siter.hasNext()) { + + Element schemaElement = siter.next(); + System.err + .println("CollectionObject.getCollectionObject() called."); + + // TODO: recognize schema thru namespace uri + if (CollectionObjectService.CO_SCHEMA_NAME.equals(schemaElement.attribute("name") + .getValue())) { + Element ele = schemaElement + .element(CollectionObjectJAXBSchema.OBJECT_NUMBER); + if (ele != null) { + co.setObjectNumber((String) ele.getData()); + } + ele = schemaElement + .element(CollectionObjectJAXBSchema.OTHER_NUMBER); + if (ele != null) { + co.setOtherNumber((String) ele.getData()); + } + ele = schemaElement + .element(CollectionObjectJAXBSchema.BRIEF_DESCRIPTION); + if (ele != null) { + co.setBriefDescription((String) ele.getData()); + } + ele = schemaElement + .element(CollectionObjectJAXBSchema.COMMENTS); + if (ele != null) { + co.setComments((String) ele.getData()); + } + ele = schemaElement + .element(CollectionObjectJAXBSchema.DIST_FEATURES); + if (ele != null) { + co.setDistFeatures((String) ele.getData()); + } + ele = schemaElement + .element(CollectionObjectJAXBSchema.OBJECT_NAME); + if (ele != null) { + co.setObjectName((String) ele.getData()); + } + ele = schemaElement + .element(CollectionObjectJAXBSchema.RESPONSIBLE_DEPT); + if (ele != null) { + co.setResponsibleDept((String) ele.getData()); + } + ele = schemaElement + .element(CollectionObjectJAXBSchema.TITLE); + if (ele != null) { + co.setTitle((String) ele.getData()); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + Response response = Response.status( + Response.Status.INTERNAL_SERVER_ERROR).entity("Get failed") + .type("text/plain").build(); + throw new WebApplicationException(response); + } + if (co == null) { + Response response = Response.status(Response.Status.NOT_FOUND) + .entity( + "Get failed, the requested CollectionObject CSID:" + + csid + ": was not found.").type( + "text/plain").build(); + throw new WebApplicationException(response); + } + verbose("getCollectionObject: ", co); + + return co; + } + + @PUT + @Path("{csid}") + public CollectionObject updateCollectionObject( + @PathParam("csid") String csid, CollectionObject theUpdate) { + + verbose("updateCollectionObject with input: ", theUpdate); + + String status = null; + try { + + Document document = service.putCollectionObject(csid, theUpdate); + Element root = document.getRootElement(); + for (Iterator i = root.elementIterator(); i.hasNext();) { + Element element = (Element) i.next(); + if ("docRef".equals(element.getName())) { + status = (String) element.getData(); + verbose("updateCollectionObject response: " + status); + } + } + } catch (Exception e) { + // FIXME: NOT_FOUND? + Response response = Response.status(Response.Status.NOT_FOUND) + .entity("Update failed ").type("text/plain").build(); + throw new WebApplicationException(response); + } + + return theUpdate; + } + + @DELETE + @Path("{csid}") + public void deleteCollectionObject(@PathParam("csid") String csid) { + + verbose("deleteCollectionObject with csid=" + csid); + try { + + Document document = service.deleteCollectionObject(csid); + Element root = document.getRootElement(); + for (Iterator i = root.elementIterator(); i.hasNext();) { + Element element = (Element) i.next(); + if ("docRef".equals(element.getName())) { + String status = (String) element.getData(); + verbose("deleteCollectionObjectt response: " + status); + } + } + } catch (Exception e) { + // FIXME: NOT_FOUND? + Response response = Response.status(Response.Status.NOT_FOUND) + .entity("Delete failed ").type("text/plain").build(); + throw new WebApplicationException(response); + } + + } + +*/ + + private void verbose(String msg, IDPattern idPattern) { + try { + verbose(msg); + JAXBContext jc = JAXBContext.newInstance(IDPattern.class); + Marshaller m = jc.createMarshaller(); + m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + m.marshal(idPattern, System.out); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void verbose(String msg) { + System.out.println("IDResource. " + msg); + } + +} diff --git a/services/id/service/src/main/java/org/collectionspace/services/IDService.java b/services/id/service/src/main/java/org/collectionspace/services/IDService.java new file mode 100644 index 000000000..903ccd6b2 --- /dev/null +++ b/services/id/service/src/main/java/org/collectionspace/services/IDService.java @@ -0,0 +1,56 @@ +/* + * IDService + * + * Interface for the methods of the ID Service. + * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * 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. + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +package org.collectionspace.services; + +import java.io.IOException; +import org.dom4j.Document; +import org.dom4j.DocumentException; + +import org.collectionspace.services.id.*; +import org.collectionspace.services.id.IDServiceNuxeoImpl; + +public interface IDService { + + public final static String ID_SCHEMA_NAME = "id"; // Note to self: Where is this used? + +/* + // Create + Document postCollectionObject(CollectionObject co) + throws DocumentException, IOException; + + // Read single object + Document getCollectionObject(String csid) throws DocumentException, + IOException; + + // Read a list of objects + Document getCollectionObjectList() throws DocumentException, IOException; + + // Update + Document putCollectionObject(String csid, CollectionObject theUpdate) + throws DocumentException, IOException; + + // Delete + Document deleteCollectionObject(String csid) throws DocumentException, + IOException; + +*/ + +} diff --git a/services/id/service/src/main/java/org/collectionspace/services/IDServiceNuxeoImpl.java b/services/id/service/src/main/java/org/collectionspace/services/IDServiceNuxeoImpl.java new file mode 100644 index 000000000..feea99c02 --- /dev/null +++ b/services/id/service/src/main/java/org/collectionspace/services/IDServiceNuxeoImpl.java @@ -0,0 +1,221 @@ +/* + * IDServiceNuxeoImpl + * + * Implementation of Nuxeo-specific portions of the ID Service, + * such as storing and retrieving documents from the Nuxeo repository. + * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * 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. + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +package org.collectionspace.services.id; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +// import org.collectionspace.services.nuxeo.NuxeoRESTClient; +// import org.collectionspace.services.nuxeo.CollectionSpaceServiceNuxeoImpl; +import org.collectionspace.services.id.*; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.io.SAXReader; +// import org.restlet.resource.Representation; + +public class IDServiceNuxeoImpl { // implements IDService { + + // Placeholder constructor. + public void IDServiceNuxeoImpl() { + } + +/* + + // May need doctypes, schema names for both ID Patterns and IDs + + final static String ID_NUXEO_DOCTYPE = "CollectionObject"; + final static String ID_NUXEO_SCHEMA_NAME = "collectionobject"; + final static String ID_NUXEO_DC_TITLE = "CollectionSpace-CollectionObject"; + + // replace WORKSPACE_UID for resource workspace + static String CS_COLLECTIONOBJECT_WORKSPACE_UID = "e4a8e3d4-0954-4c10-963a-cc4ed09d5112"; + + public Document deleteCollectionObject(String csid) + throws DocumentException, IOException { + + NuxeoRESTClient nxClient = getClient(); + List pathParams = new ArrayList(); + Map queryParams = new HashMap(); + + pathParams.add("default"); + pathParams.add(csid); + pathParams.add("deleteDocumentRestlet"); + Representation res = nxClient.get(pathParams, queryParams); + SAXReader reader = new SAXReader(); + Document document = reader.read(res.getStream()); + + return document; + } + + public Document getCollectionObject(String csid) throws DocumentException, + IOException { + List pathParams = new ArrayList(); + Map queryParams = new HashMap(); + + pathParams.add("default"); + pathParams.add(csid); + pathParams.add("export"); + queryParams.put("format", "XML"); + + NuxeoRESTClient nxClient = getClient(); + Representation res = nxClient.get(pathParams, queryParams); + + SAXReader reader = new SAXReader(); + Document document = reader.read(res.getStream()); + + return document; + } + + public Document getCollectionObjectList() throws DocumentException, + IOException { + Document result = null; + + NuxeoRESTClient nxClient = getClient(); + List pathParams = new ArrayList(); + Map queryParams = new HashMap(); + pathParams = Arrays.asList("default", + CS_COLLECTIONOBJECT_WORKSPACE_UID, "browse"); + Representation res = nxClient.get(pathParams, queryParams); + SAXReader reader = new SAXReader(); + result = reader.read(res.getStream()); + + return result; + } + + public Document postCollectionObject(CollectionObject co) + throws DocumentException, IOException { + NuxeoRESTClient nxClient = getClient(); + + List pathParams = new ArrayList(); + Map queryParams = new HashMap(); + pathParams.add("default"); + pathParams.add(CS_COLLECTIONOBJECT_WORKSPACE_UID); + pathParams.add("createDocument"); + queryParams.put("docType", CO_NUXEO_DOCTYPE); + + // a default title for the Dublin Core schema + queryParams.put("dublincore:title", CO_NUXEO_DC_TITLE); + + // CollectionObject core values + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.OBJECT_NUMBER, co + .getObjectNumber()); + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.OTHER_NUMBER, co.getOtherNumber()); + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.BRIEF_DESCRIPTION, co + .getBriefDescription()); + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.COMMENTS, co.getComments()); + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.DIST_FEATURES, co + .getDistFeatures()); + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.OBJECT_NAME, co.getObjectName()); + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.RESPONSIBLE_DEPT, co + .getResponsibleDept()); + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.TITLE, co.getTitle()); + + ByteArrayInputStream bais = new ByteArrayInputStream(new byte[0]); + Representation res = nxClient.post(pathParams, queryParams, bais); + + SAXReader reader = new SAXReader(); + Document document = reader.read(res.getStream()); + + return document; + } + + public Document putCollectionObject(String csid, CollectionObject theUpdate) + throws DocumentException, IOException { + List pathParams = new ArrayList(); + Map queryParams = new HashMap(); + pathParams.add("default"); + pathParams.add(csid); + pathParams.add("updateDocumentRestlet"); + + // todo: intelligent merge needed + if (theUpdate.getObjectNumber() != null) { + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.OBJECT_NUMBER, theUpdate + .getObjectNumber()); + } + + if (theUpdate.getOtherNumber() != null) { + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.OTHER_NUMBER, theUpdate + .getOtherNumber()); + } + + if (theUpdate.getBriefDescription() != null) { + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.BRIEF_DESCRIPTION, theUpdate + .getBriefDescription()); + } + + if (theUpdate.getComments() != null) { + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.COMMENTS, theUpdate + .getComments()); + } + + if (theUpdate.getDistFeatures() != null) { + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.DIST_FEATURES, theUpdate + .getDistFeatures()); + } + + if (theUpdate.getObjectName() != null) { + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.OBJECT_NAME, theUpdate + .getObjectName()); + } + + if (theUpdate.getResponsibleDept() != null) { + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.RESPONSIBLE_DEPT, theUpdate + .getResponsibleDept()); + } + + if (theUpdate.getTitle() != null) { + queryParams.put(CO_NUXEO_SCHEMA_NAME + ":" + + CollectionObjectJAXBSchema.TITLE, theUpdate.getTitle()); + } + + NuxeoRESTClient nxClient = getClient(); + Representation res = nxClient.get(pathParams, queryParams); + SAXReader reader = new SAXReader(); + Document document = reader.read(res.getStream()); + + return document; + } + +*/ + +} diff --git a/services/id/service/src/main/java/org/collectionspace/services/id/AlphabeticIDGenerator.java b/services/id/service/src/main/java/org/collectionspace/services/id/AlphabeticIDGenerator.java new file mode 100644 index 000000000..21f268cc7 --- /dev/null +++ b/services/id/service/src/main/java/org/collectionspace/services/id/AlphabeticIDGenerator.java @@ -0,0 +1,319 @@ +/* + * AlphabeticIDGenerator + * + *

An identifier generator that generates an incrementing alphabetic ID + * from any sequence of characters, as a String object.

+ * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +// @TODO: Add Javadoc comments + +// @TODO: When auto expanding, we'll need to set a maximum length to which the +// generated IDs can grow, likely as an additional parameter to be +// passed to a constructor, with a default value hard-coded in the class. + +// @TODO: Consider handling escaped characters or sequences which represent Unicode +// code points, both in the start and end characters of the sequence, and in the initial value. +// (Example: '\u0072' for the USASCII 'r' character; see +// http://www.fileformat.info/info/unicode/char/0072/index.htm) +// +// Ideally, we should read these in free-text patterns, alongside unescaped characters, +// but in practice we may wish to require some structured form for arguments +// containing such characters. +// +// Some initial research on this: +// http://www.velocityreviews.com/forums/t367758-unescaping-unicode-code-points-in-a-java-string.html +// We might also look into the (protected) source code for java.util.Properties.load() +// which reads escaped Unicode values. +// +// Note also that, if the goal is to cycle through a sequence of alphabetic identifiers, +// such as the sequence of characters used in a particular human language, it may or may not +// be the case that any contiguous Unicode code point sequence reflects such a character sequence. + +// NOTE: This class currently hard-codes the assumption that the values in +// alphabetic identifiers are ordered in significance from left-to-right; +// that is, the most significant value appears in the left-most position. + +package org.collectionspace.services.id; + +import java.util.Collections; +import java.util.Vector; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class AlphabeticIDGenerator implements IDGenerator { + + private static final char NULL_CHAR = '\u0000'; + + private static final String DEFAULT_START_CHAR = "a"; + private static final String DEFAULT_END_CHAR = "z"; + private static final String DEFAULT_INITIAL_VALUE = "a"; + + private char startChar = NULL_CHAR; + private char endChar = NULL_CHAR; + + private Vector initialValue = new Vector(); + private Vector currentValue = new Vector(); + + // Constructor using defaults for character sequence and initial value. + // + // If no start and end characters are provided for the alphabetic character + // sequence, default to an 'a-z' sequence, representing the lowercase alphabetic + // characters in the USASCII character set (within Java's internal + // Unicode UTF-16 representation). + // + // Additionally defaults to an initial value of "a". + public AlphabeticIDGenerator() throws IllegalArgumentException { + + this(DEFAULT_START_CHAR, DEFAULT_END_CHAR, DEFAULT_INITIAL_VALUE); + + } + + // Constructor using defaults for character sequence. + // + // If no start and end characters are provided for the alphabetic character + // sequence, default to an 'a-z' sequence, representing the lowercase alphabetic + // characters in the USASCII character set (within Java's internal + // Unicode UTF-16 representation). + public AlphabeticIDGenerator(String initial) throws IllegalArgumentException { + + this(DEFAULT_START_CHAR, DEFAULT_END_CHAR, initial); + + } + + // Constructor. + public AlphabeticIDGenerator(String sequenceStart, String sequenceEnd, String initial) + throws IllegalArgumentException { + + // Validate and store the start character in the character sequence. + + if (sequenceStart == null || sequenceStart.equals("")) { + throw new IllegalArgumentException( + "Start character in the character sequence must not be null or empty"); + } + + if (sequenceStart.length() == 1) { + this.startChar = sequenceStart.charAt(0); + } else if (false) { + // Handle representations of Unicode code points here + } else { + throw new IllegalArgumentException( + "Start character must be one character in length"); + // "Start character must be one character in length or a Unicode value such as '\u0000'"); + } + + // Validate and store the end character in the character sequence. + + if (sequenceEnd == null || sequenceEnd.equals("")) { + throw new IllegalArgumentException( + "End character in the character sequence must not be null or empty"); + } + + if (sequenceEnd.length() == 1) { + this.endChar = sequenceEnd.charAt(0); + } else if (false) { + // Handle representations of Unicode code points here + } else { + throw new IllegalArgumentException( + "End character must be one character in length"); + // "End character must be one character in length or a Unicode value such as '\u0000'"); + } + + if (this.endChar <= this.startChar) { + throw new IllegalArgumentException( + "End (last) character in the character sequence must be greater than the start character"); + } + + // Validate and store the initial value of this identifier. + + if (initial == null || initial.equals("")) { + throw new IllegalArgumentException("Initial value must not be null or empty"); + } + + // @TODO: Add a check for maximum length of the initial value here. + + // Store the chars in the initial value as Characters in a Vector, + // validating each character to identify whether it falls within + // the provided sequence. + // + // (Since we're performing casts from char to Character, we can't just + // use Arrays.asList() to copy the initial array to a Vector.) + char[] chars = initial.toCharArray(); + char ch; + for (int i = 0; i < chars.length; i++) { + + // If the character falls within the provided sequence, copy it to the Vector. + ch = chars[i]; + if (ch >= this.startChar && ch <= this.endChar) { + this.initialValue.add(new Character(ch)); + // Otherwise, we've detected a character not in the sequence. + } else { + throw new IllegalArgumentException("character " + "\'" + ch + "\'" + " is not valid"); + } + + } + + // Initialize the current value from the initial value. + this.currentValue = new Vector(this.initialValue); + + } + + // Returns the initial value. + public synchronized String getInitialID() { + return getIDString(this.initialValue); + } + + // Returns the current value. + public synchronized String getCurrentID() { + return getIDString(this.currentValue); + } + + // Sets the current value. + public synchronized void setCurrentID(String value) throws IllegalArgumentException { + + // @TODO Much of this code is copied from the main constructor, + // and may be ripe for refactoring. + + if (value == null || value.equals("")) { + throw new IllegalArgumentException("Initial value must not be null or empty"); + } + + // @TODO: Add a check for maximum length of the value here. + + // Store the chars in the value as Characters in a Vector, + // validating each character to identify whether it falls within + // the provided sequence. + // + // (Since we're performing casts from char to Character, we can't just + // use Arrays.asList() to copy the initial array to a Vector.) + char[] chars = value.toCharArray(); + char ch; + Vector v = new Vector(); + for (int i = 0; i < chars.length; i++) { + + // If the character falls within the range bounded by the start and end + // characters, copy it to the Vector. + ch = chars[i]; + if (ch >= this.startChar && ch <= this.endChar) { + v.add(new Character(ch)); + // Otherwise, we've detected a character not in the sequence. + } else { + throw new IllegalArgumentException("character " + "\'" + ch + "\'" + " is not valid"); + } + + } + + // Set the current value. + this.currentValue = new Vector(v); + + } + + // Reset the current value to the initial value. + public synchronized void resetID() { + Collections.copy(this.currentValue, this.initialValue); + } + + + // Returns the next alphabetic ID in the sequence. + // + // Currently, the number of characters auto-expands as the + // value of the most significant character rolls over. + // E.g. a call to getNextID(), where the current ID is "z", + // auto-expands to "aa", and "ZZ" auto-expands to "AAA". + // + // See the TODOs at the top of this class for additional + // functionality that needs to be implemented. + public synchronized String nextID() { + + // Get next values for each character, from right to left + // (least significant to most significant). + boolean expandIdentifier = false; + int size = this.currentValue.size(); + char ch; + for (int i = (size - 1); i >= 0; i--) { + + ch = this.currentValue.get(i).charValue(); + + // When we reach the maximum value for any character, + // 'roll over' to the minimum value in our character range. + if (ch == this.endChar) { + this.currentValue.set(i, Character.valueOf(this.startChar)); + // If this rollover occurs in the most significant value, + // set a flag to later expand the size of the identifier. + // + // @TODO: Set another flag to enable or disable this behavior, + // as well as a mechanism for setting the maximum expansion permitted. + if (i == 0) { + expandIdentifier = true; + } + // When we reach the most significant character whose value + // doesn't roll over, increment that character and exit the loop. + } else { + ch++; + this.currentValue.set(i, Character.valueOf(ch)); + i = -1; + break; + } + + } + + // If we are expanding the size of the identifier, insert a new + // value at the most significant (leftmost) character position, + // sliding other values to the right. + if (expandIdentifier) { + this.currentValue.add(0, Character.valueOf(this.startChar)); + } + + return getIDString(this.currentValue); + + } + + // Returns a String representation of the ID, by appending + // the String values of each character. + public synchronized String getIDString(Vector v) { + StringBuffer sb = new StringBuffer(); + for ( Character ch : v ) { + sb.append(ch.toString()); + } + return sb.toString(); + } + + public synchronized boolean isValidID(String value) throws IllegalArgumentException { + + if ( value == null || value == "") { + throw new IllegalArgumentException("ID to validate must not be null or empty"); + } + + Pattern pattern = Pattern.compile(getRegex()); + Matcher matcher = pattern.matcher(value); + if (matcher.matches()) { + return true; + } else { + return false; + } + + } + + public synchronized String getRegex() { + // @TODO: May need to constrain the number of alphabetic characters based + // on a maximum value, TBA. Currently, this regex simply matches sequences + // of one or more characters. + String regex = + "(" + "[" + + String.valueOf(this.startChar) + "-" + String.valueOf(this.endChar) + + "]+" + ")"; + return regex; + } +} diff --git a/services/id/service/src/main/java/org/collectionspace/services/id/AlphabeticIDPart.java b/services/id/service/src/main/java/org/collectionspace/services/id/AlphabeticIDPart.java new file mode 100644 index 000000000..61cd834bc --- /dev/null +++ b/services/id/service/src/main/java/org/collectionspace/services/id/AlphabeticIDPart.java @@ -0,0 +1,37 @@ + /* + * AlphabeticIDPart + * + * Models a part of an identifier (ID) whose values are an alphabetic series. + * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +// @TODO: Add Javadoc comments + +package org.collectionspace.services.id; + +public class AlphabeticIDPart extends IDPart { + + public AlphabeticIDPart() { + super(new AlphabeticIDGenerator()); + }; + + public AlphabeticIDPart(String baseVal) { + super(new AlphabeticIDGenerator(baseVal)); + }; + + public AlphabeticIDPart(String startVal, String endVal, String baseVal) { + super(new AlphabeticIDGenerator(startVal, endVal, baseVal)); + }; + +} diff --git a/services/id/service/src/main/java/org/collectionspace/services/id/IDGenerator.java b/services/id/service/src/main/java/org/collectionspace/services/id/IDGenerator.java new file mode 100644 index 000000000..0963894ee --- /dev/null +++ b/services/id/service/src/main/java/org/collectionspace/services/id/IDGenerator.java @@ -0,0 +1,50 @@ + /* + * IDGenerator + * + * Interface for a generator class that returns IDs. + * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +// @TODO: Consider making this class, or a class that implements +// this interface, abstract, in part because we're duplicating code +// in isValidID() in multiple Generator subclasses. + +package org.collectionspace.services.id; + +public interface IDGenerator { + + // Returns the initial value of the ID. + public String getInitialID(); + + // Gets the current value of an ID. + public String getCurrentID(); + + // Sets the current value of an ID. + public void setCurrentID(String value); + + // Resets an ID to its initial value. + public void resetID(); + + // Returns the next ID in the sequence, and sets + // the current value to that ID. + public String nextID(); + + // Validates an ID against a pattern of generated IDs. + public boolean isValidID(String value); + + // Returns a String representation of the regular expression ("regex") + // pattern used to validate instance values of generated IDs. + public String getRegex(); + +} diff --git a/services/id/service/src/main/java/org/collectionspace/services/id/IDPart.java b/services/id/service/src/main/java/org/collectionspace/services/id/IDPart.java new file mode 100644 index 000000000..7c24676fa --- /dev/null +++ b/services/id/service/src/main/java/org/collectionspace/services/id/IDPart.java @@ -0,0 +1,85 @@ + /* + * IDPart + * + *

Models a part of an identifier (ID).

+ * + *

Some representative examples of data that can be + * managed within IDParts include:

+ * + *
    + *
  • Incrementing numeric or alphabetic values
  • + *
  • Date values
  • + *
  • Static separators
  • + *
+ * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 291 $ + * $Date: 2009-06-24 11:48:28 -0700 (Wed, 24 Jun 2009) $ + */ + +// @TODO: Add Javadoc comments + +package org.collectionspace.services.id; + +public abstract class IDPart { + + // A generator for the types of IDs that are generated by this part. + // This generator is passed in at construction time. + protected IDGenerator generator; + + // Constructor + public IDPart(IDGenerator idGenerator) throws IllegalArgumentException { + this.generator = idGenerator; + } + + // Returns the initial value of the ID associated with this IDPart. + public synchronized String getInitialID() { + return generator.getInitialID(); + } + + // Returns the current value of the ID associated with this IDPart. + public synchronized String getCurrentID() { + return generator.getCurrentID(); + } + + // Sets the current value of the ID associated with this IDPart. + public synchronized void setCurrentID(String value) { + generator.setCurrentID(value); + } + + // Resets the ID associated with this IDPart to its initial value. + public synchronized void resetID() { + generator.resetID(); + } + + // Returns the next ID in the sequence, and sets the current value + // of the ID associated with this IDPart to that next ID. + public synchronized String nextID() throws IllegalStateException { + return generator.nextID(); + } + + // Validates a supplied ID against the pattern of this IDPart. + // + // Some IDParts may offer generic validation, + // while others may offer per-instance valiadation + // based on the values, series, etc. that are + // stored within those parts. + public synchronized boolean isValidID(String value) throws IllegalArgumentException { + return generator.isValidID(value); + } + + // Returns a String representation of the regular expression ("regex") + // pattern used to validate instance values of this IDPart. + public synchronized String getRegex() { + return generator.getRegex(); + } + +} diff --git a/services/id/service/src/main/java/org/collectionspace/services/id/IDPattern.java b/services/id/service/src/main/java/org/collectionspace/services/id/IDPattern.java new file mode 100644 index 000000000..7b848c1e7 --- /dev/null +++ b/services/id/service/src/main/java/org/collectionspace/services/id/IDPattern.java @@ -0,0 +1,261 @@ + /* + * IDPattern + * + *

Models an identifier (ID), which consists of multiple IDParts.

+ * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +// @TODO: Add Javadoc comments + +// @TODO: Catch Exceptions thrown by IDPart, then +// reflect this in the corresponding IDPatternTest class. + +package org.collectionspace.services.id; + +import java.util.Vector; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class IDPattern { + + final static int MAX_ID_LENGTH = 50; + + private Vector parts = new Vector(); + + // Constructor + public IDPattern() { + } + + // Constructor + public IDPattern(Vector partsList) { + if (partsList != null) { + this.parts = partsList; + } + } + + public void add(IDPart part) { + if (part != null) { + this.parts.add(part); + } + } + + // Returns the current value of this ID. + public synchronized String getCurrentID() { + StringBuffer sb = new StringBuffer(MAX_ID_LENGTH); + for (IDPart part : this.parts) { + sb.append(part.getCurrentID()); + } + return sb.toString(); + } + + // Returns the current value of this ID, given a + // supplied ID that partly matches the pattern. + // + // If the supplied ID fully matches the pattern, + // will return the supplied ID. + // + // However, if the supplied ID is a partial ID, which + // partly "stem-matches" the pattern but does not + // ully match the pattern, will return the partial ID with + // its next ID component appended. The next ID component + // will be set to its initial value. + // + // Examples: + // * 2009.5." becomes "2009.5.1", in a case where the + // next ID component is an incrementing numeric IDPart. + // * "E55-" becomes "E55-a", where the next ID component + // is an incrementing alphabetic IDPart. + public synchronized String getCurrentID(String value) + throws IllegalArgumentException { + + if (value == null) return value; + + // Try ever-larger stem matches against the supplied value, + // by incrementally appending each part's regex, until no + // (more) matches are found. + // + // In so doing, build a subset of this IDPattern's regex + // that fully matches the supplied value. + Pattern pattern = null; + Matcher matcher = null; + int matchedParts = 0; + StringBuffer regexToTry = new StringBuffer(); + StringBuffer regex = new StringBuffer(); + for (IDPart partToTryMatching : this.parts) { + regexToTry.append(partToTryMatching.getRegex()); + pattern = Pattern.compile(regexToTry.toString()); + matcher = pattern.matcher(value); + // If a stem match was found on the current regex, + // store a count of matched IDParts and the regex pattern + // that has matched to this point. + if (matcher.lookingAt()) { + matchedParts++; + regex.append(partToTryMatching.getRegex()); + // Otherwise, exit the loop. + } else { + break; + } + } + + // If the supplied ID doesn't partly match the pattern, + // throw an Exception. + if (matchedParts == 0) { + throw new IllegalArgumentException("Supplied ID does not match this ID pattern."); + } + + pattern = Pattern.compile(regex.toString()); + matcher = pattern.matcher(value); + + // If the supplied ID doesn't match the pattern built above, + // throw an Exception. (This error condition should likely + // never be reached, but it's here as a guard.) + if (! matcher.matches()) { + throw new IllegalArgumentException("Supplied ID does not match this ID pattern."); + } + + // Otherwise, if the supplied ID matches the pattern, + // split the ID into its components and store those + // values in each of the pattern's IDParts. + IDPart currentPart; + for (int i = 1; i <= matchedParts; i++) { + currentPart = this.parts.get(i - 1); + currentPart.setCurrentID(matcher.group(i)); + } + + // Obtain the initial value of the next IDPart, and + // set the current value of that part to its initial value. + // + // If the supplied ID fully matches the pattern, there will + // be no 'next' IDPart, and we must catch that Exception below. + int nextPartNum = matchedParts; + try { + String initial = this.parts.get(nextPartNum).getInitialID(); + this.parts.get(nextPartNum).setCurrentID(initial); + // Increment the number of matched parts to reflect the + // addition of this next IDPart. + matchedParts++; + } catch (ArrayIndexOutOfBoundsException e ) { + // Do nothing here; we simply won't increment + // the number of matched parts, used in the loop below. + } + + // Call the getCurrentID() method on each of the + // supplied IDParts, as well as on the added IDPart + // whose initial value was just obtained, if any. + StringBuffer sb = new StringBuffer(); + for (int i = 1; i <= matchedParts; i++) { + sb.append(this.parts.get(i - 1).getCurrentID()); + } + + return sb.toString(); + + } + + // Returns the next value of this ID, and sets the current value to that ID. + public synchronized String nextID() throws IllegalStateException { + + // Obtain the last (least significant) IDPart, + // and call its nextID() method, which will + // concurrently set the current value of that ID + // to the next ID. + int lastPartNum = this.parts.size() - 1; + this.parts.get(lastPartNum).nextID(); + + // Then call the getCurrentID() method on all of the IDParts + StringBuffer sb = new StringBuffer(MAX_ID_LENGTH); + for (IDPart part : this.parts) { + sb.append(part.getCurrentID()); + } + + return sb.toString(); + + } + + // Returns the next value of this ID, given a + // supplied ID that entirely matches the pattern, + // and sets the current value to that ID. + public synchronized String nextID(String value) + throws IllegalStateException, IllegalArgumentException { + + if (value == null) { + throw new IllegalArgumentException("Supplied ID cannot be null."); + } + + Pattern pattern = Pattern.compile(getRegex()); + Matcher matcher = pattern.matcher(value); + + // If the supplied ID doesn't entirely match the pattern, + // throw an Exception. + if (! matcher.matches()) { + throw new IllegalArgumentException("Supplied ID does not match this ID pattern."); + } + + // Otherwise, if the supplied ID entirely matches the pattern, + // split the ID into its components and store those values in + // each of the pattern's IDParts. + IDPart currentPart; + for (int i = 1; i <= (matcher.groupCount() - 1); i++) { + currentPart = this.parts.get(i - 1); + currentPart.setCurrentID(matcher.group(i)); + } + + // Obtain the last (least significant) IDPart, + // and call its nextID() method, which will + // concurrently set the current value of that ID + // to the next ID. + // + // @TODO: This code is duplicated in nextID(), above, + // and thus we may want to refactor this. + int lastPartNum = this.parts.size() - 1; + this.parts.get(lastPartNum).nextID(); + + // Then call the getCurrentID() method on all of the IDParts + StringBuffer sb = new StringBuffer(); + for (IDPart part : this.parts) { + sb.append(part.getCurrentID()); + } + + return sb.toString(); + + } + + // Validates a provided ID against the pattern. + // + // @TODO May potentially throw at least one pattern-related exception; + // we'll need to catch and handle this. + public synchronized boolean isValidID(String value) { + + if (value == null) return false; + + Pattern pattern = Pattern.compile(getRegex()); + Matcher matcher = pattern.matcher(value); + if (matcher.matches()) { + return true; + } else { + return false; + } + + } + + // Returns a regular expression to validate this ID. + public synchronized String getRegex() { + StringBuffer sb = new StringBuffer(); + for (IDPart part : this.parts) { + sb.append(part.getRegex()); + } + return sb.toString(); + } + +} diff --git a/services/id/service/src/main/java/org/collectionspace/services/id/NumericIDGenerator.java b/services/id/service/src/main/java/org/collectionspace/services/id/NumericIDGenerator.java new file mode 100644 index 000000000..4d4f7206b --- /dev/null +++ b/services/id/service/src/main/java/org/collectionspace/services/id/NumericIDGenerator.java @@ -0,0 +1,139 @@ +/* + * NumericIDGenerator + * + *

An identifier generator that generates an incrementing ID as a + * series of numeric values, beginning from an initial value.

+ * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +// @TODO: Add Javadoc comments + +// @TODO: Need to set and enforce maximum value. + +package org.collectionspace.services.id; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class NumericIDGenerator implements IDGenerator { + + final static private int DEFAULT_MAX_LENGTH = 6; + private int maxLength = DEFAULT_MAX_LENGTH; + + final static private int DEFAULT_INITIAL_VALUE = 1; + private long initialValue = DEFAULT_INITIAL_VALUE; + private long currentValue = DEFAULT_INITIAL_VALUE; + + // Constructor using defaults for initial value and maximum length. + public NumericIDGenerator() throws IllegalArgumentException { + this(Integer.toString(DEFAULT_INITIAL_VALUE), Integer.toString(DEFAULT_MAX_LENGTH)); + } + + // Constructor using default maximum length. + public NumericIDGenerator(String initialValue) throws IllegalArgumentException { + this(initialValue, Integer.toString(DEFAULT_MAX_LENGTH)); + } + + // Constructor. + public NumericIDGenerator(String initialValue, String maxLength) + throws IllegalArgumentException { + + try { + long l = Long.parseLong(initialValue.trim()); + if ( l < 0 ) { + throw new IllegalArgumentException("Initial ID value should be zero (0) or greater"); + } + this.currentValue = l; + this.initialValue = l; + } catch (NullPointerException e) { + throw new IllegalArgumentException("Initial ID value should not be null"); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Initial ID value must be parseable as a number"); + } + + try { + this.maxLength = Integer.parseInt(maxLength); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Maximum ID length must be parseable as a number"); + } + + } + + public synchronized String getInitialID() { + return Long.toString(this.initialValue); + } + + public synchronized String getCurrentID() { + return Long.toString(this.currentValue); + } + + // Sets the current value of the ID. + public synchronized void setCurrentID(String value) throws IllegalArgumentException { + + // @TODO Much of this code is copied from the main constructor, + // and may be ripe for refactoring. + try { + long l = Long.parseLong(value.trim()); + if ( l < 0 ) { + throw new IllegalArgumentException("Initial ID value should be zero (0) or greater"); + } + this.currentValue = l; + this.initialValue = l; + } catch (NullPointerException e) { + throw new IllegalArgumentException("ID value should not be null"); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("ID value must be parseable as a number"); + } + + // @TODO An expedient; we may need to check the String length of the + // provided ID and calculate a maximum length here. + this.maxLength = DEFAULT_MAX_LENGTH; + } + + public synchronized void resetID() { + this.currentValue = this.initialValue; + } + + // Returns the next ID in the sequence, and sets the current value to that ID. + public synchronized String nextID() throws IllegalStateException { + this.currentValue++; + String nextID = Long.toString(this.currentValue); + if (nextID.length() > this.maxLength) { + throw new IllegalStateException("Next ID cannot exceed maximum length"); + } + return nextID; + } + + public synchronized boolean isValidID(String value) { + + if ( value == null || value == "") { + return false; + } + + Pattern pattern = Pattern.compile(getRegex()); + Matcher matcher = pattern.matcher(value); + if (matcher.matches()) { + return true; + } else { + return false; + } + + } + + public synchronized String getRegex() { + String regex = "(" + "\\d" + "{1," + Integer.toString(this.maxLength) + "}" + ")"; + return regex; + } + +} diff --git a/services/id/service/src/main/java/org/collectionspace/services/id/NumericIDPart.java b/services/id/service/src/main/java/org/collectionspace/services/id/NumericIDPart.java new file mode 100644 index 000000000..78977e85f --- /dev/null +++ b/services/id/service/src/main/java/org/collectionspace/services/id/NumericIDPart.java @@ -0,0 +1,42 @@ + /* + * NumericIDPart + * + * Models a part of an identifier (ID) whose values come from an + * incrementing numeric series, with those values represented as + * String objects. + * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +// @TODO: Add Javadoc comments + +package org.collectionspace.services.id; + +public class NumericIDPart extends IDPart { + + public NumericIDPart() throws IllegalArgumentException { + super(new NumericIDGenerator()); + }; + + // Store the appropriate Numeric ID generator and the base value for this part. + public NumericIDPart(String baseVal) throws IllegalArgumentException { + super(new NumericIDGenerator(baseVal)); + }; + + // Store the appropriate Numeric ID generator, and the base value + // and maximum length for this part. + public NumericIDPart(String baseVal, String maxLength) throws IllegalArgumentException { + super(new NumericIDGenerator(baseVal, maxLength)); + }; + +} diff --git a/services/id/service/src/main/java/org/collectionspace/services/id/StringIDGenerator.java b/services/id/service/src/main/java/org/collectionspace/services/id/StringIDGenerator.java new file mode 100644 index 000000000..e2c2a391e --- /dev/null +++ b/services/id/service/src/main/java/org/collectionspace/services/id/StringIDGenerator.java @@ -0,0 +1,103 @@ +/* + * StringIDGenerator + * + *

An identifier generator that stores and returns a static String.

+ * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +// @TODO: Add Javadoc comments + +// @TODO: Need to set and enforce maximum String length. + +package org.collectionspace.services.id; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +public class StringIDGenerator implements IDGenerator { + + private String initialValue = null; + private String currentValue = null; + + public StringIDGenerator(String initialValue) throws IllegalArgumentException { + + if ( initialValue == null || initialValue == "") { + throw new IllegalArgumentException("Initial ID value must not be null or empty"); + } + + this.initialValue = initialValue; + this.currentValue = initialValue; + + } + + public synchronized String getInitialID() { + return this.initialValue; + } + + public synchronized String getCurrentID() { + return this.currentValue; + } + + public synchronized void setCurrentID(String value) throws IllegalArgumentException { + if ( initialValue == null || initialValue == "") { + throw new IllegalArgumentException("ID value must not be null or empty"); + } + this.currentValue = value; + } + + public synchronized void resetID() { + // Do nothing + } + + public synchronized String nextID() { + return this.currentValue; + } + + public synchronized boolean isValidID(String value) throws IllegalArgumentException { + + if ( value == null || value == "") { + throw new IllegalArgumentException("ID to validate must not be null or empty"); + } + + Pattern pattern = Pattern.compile(getRegex()); + Matcher matcher = pattern.matcher(value); + if (matcher.matches()) { + return true; + } else { + return false; + } + + } + + public synchronized String getRegex() { + + String initial = this.initialValue; + + // Escape or otherwise modify various characters that have + // significance in regular expressions. + // + // @TODO Test these thoroughly, add processing of more + // special characters as needed. + + // Escape un-escaped period/full stop characters. + Pattern pattern = Pattern.compile("([^\\\\]{0,1})\\."); + Matcher matcher = pattern.matcher(initial); + String escapedInitial = matcher.replaceAll("$1\\\\."); + + String regex = "(" + escapedInitial + ")"; + return regex; + } + +} diff --git a/services/id/service/src/main/java/org/collectionspace/services/id/StringIDPart.java b/services/id/service/src/main/java/org/collectionspace/services/id/StringIDPart.java new file mode 100644 index 000000000..16ae17420 --- /dev/null +++ b/services/id/service/src/main/java/org/collectionspace/services/id/StringIDPart.java @@ -0,0 +1,29 @@ + /* + * StringIDGenerator + * + * Models a part of an identifier (ID) whose values are an alphabetic series. + * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +// @TODO: Add Javadoc comments + +package org.collectionspace.services.id; + +public class StringIDPart extends IDPart { + + public StringIDPart(String baseVal) { + super(new StringIDGenerator(baseVal)); + }; + +} diff --git a/services/id/service/src/main/java/org/collectionspace/services/id/YearIDGenerator.java b/services/id/service/src/main/java/org/collectionspace/services/id/YearIDGenerator.java new file mode 100644 index 000000000..915783511 --- /dev/null +++ b/services/id/service/src/main/java/org/collectionspace/services/id/YearIDGenerator.java @@ -0,0 +1,141 @@ +/* + * YearIDGenerator + * + *

An identifier generator that stores and returns the current year + * as a String object.

+ * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +// @TODO: Add Javadoc comments + +// @TODO: Need to understand and reflect time zone issues; +// what happens when a year rollover occurs: +// - In the time zone of the end user. +// - In the time zone of the museum or other institution. +// - In the time zone of the physical server where the code is hosted. + +// NOTE: This class currently hard-codes the assumption that the +// Gregorian Calendar system is in use. +// +// We may wish to use the Joda-Time framework if handling of +// additional calendar systems is needed, or additional treatment +// of time zones is warranted: +// http://joda-time.sourceforge.net/ +// +// There may also be a need to have a structured set of date-time +// classes related to identifier generation. + +package org.collectionspace.services.id; + +import java.util.Calendar; +import java.util.GregorianCalendar; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class YearIDGenerator implements IDGenerator { + + private String initialValue = null; + private String currentValue = null; + + public YearIDGenerator() throws IllegalArgumentException { + + String currentYear = getCurrentYear(); + this.initialValue = currentYear; + this.currentValue = currentYear; + + } + + public YearIDGenerator(String initialValue) throws IllegalArgumentException { + + if ( initialValue == null || initialValue == "") { + throw new IllegalArgumentException("Initial ID value must not be null or empty"); + } + + // @TODO: Add regex-based validation here, by calling isValidID(). + // Consider implications for Internationalization when doing so. + + this.initialValue = initialValue; + this.currentValue = initialValue; + + } + + public synchronized String getInitialID() { + return this.initialValue; + } + + public synchronized String getCurrentID() { + return this.currentValue; + } + + // Sets the current value. + public synchronized void setCurrentID(String value) throws IllegalArgumentException { + + // @TODO This code is copied from the main constructor, + // and thus there may be an opportunity for refactoring. + + if ( value == null || value == "") { + throw new IllegalArgumentException("ID value must not be null or empty"); + } + + // @TODO: Add regex-based validation here, by calling isValidID(). + // Consider implications for Internationalization when doing so. + + this.currentValue = value; + + } + + public synchronized void resetID() { + this.currentValue = this.initialValue; + } + + // @TODO: We'll need to decide what a "next" ID means in the context of: + // - An initially supplied value. + // - A year value that has not changed from its previous value. + // - A year value that has changed, as a result of a rollover + // to a new instant in time. + public synchronized String nextID() { + return this.currentValue; + } + + public String getCurrentYear() { + Calendar cal = GregorianCalendar.getInstance(); + int y = cal.get(Calendar.YEAR); + return Integer.toString(y); + } + + public synchronized boolean isValidID(String value) throws IllegalArgumentException { + + if ( value == null || value == "") { + throw new IllegalArgumentException("ID to validate must not be null or empty"); + } + + Pattern pattern = Pattern.compile(getRegex()); + Matcher matcher = pattern.matcher(value); + if (matcher.matches()) { + return true; + } else { + return false; + } + + } + + public synchronized String getRegex() { + // NOTE: Currently hard-coded to accept only a range of + // four-digit Gregorian Calendar year dates. + String regex = "(\\d{4})"; + return regex; + } + +} diff --git a/services/id/service/src/main/java/org/collectionspace/services/id/YearIDPart.java b/services/id/service/src/main/java/org/collectionspace/services/id/YearIDPart.java new file mode 100644 index 000000000..f0d7ede9d --- /dev/null +++ b/services/id/service/src/main/java/org/collectionspace/services/id/YearIDPart.java @@ -0,0 +1,34 @@ + /* + * YearIDGenerator + * + * Models a part of an identifier (ID) whose value is the current year + * or a supplied year. + * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +// @TODO: Add Javadoc comments + +package org.collectionspace.services.id; + +public class YearIDPart extends IDPart { + + public YearIDPart() { + super(new YearIDGenerator()); + }; + + public YearIDPart(String baseVal) { + super(new YearIDGenerator(baseVal)); + }; + +} diff --git a/services/id/service/src/test/java/org/collectionspace/services/IDServiceTest.java b/services/id/service/src/test/java/org/collectionspace/services/IDServiceTest.java new file mode 100644 index 000000000..9a69a486f --- /dev/null +++ b/services/id/service/src/test/java/org/collectionspace/services/IDServiceTest.java @@ -0,0 +1,10 @@ +package org.collectionspace.services.test; + +//import org.collectionspace.services.id.Id; +//import org.collectionspace.services.id.IdList; +//import org.collectionspace.services.id.IdPattern; +//import org.collectionspace.services.id.IdPatternList; + +public class IDServiceTest { + //empty +} diff --git a/services/id/service/src/test/java/org/collectionspace/services/id/AlphabeticIDPartTest.java b/services/id/service/src/test/java/org/collectionspace/services/id/AlphabeticIDPartTest.java new file mode 100644 index 000000000..5b85ad55a --- /dev/null +++ b/services/id/service/src/test/java/org/collectionspace/services/id/AlphabeticIDPartTest.java @@ -0,0 +1,248 @@ +/* + * AlphabeticIDPartTest + * + * Test class for AlphabeticIDPart. + * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +package org.collectionspace.services.id; + +import static org.junit.Assert.fail; +import junit.framework.TestCase; + +public class AlphabeticIDPartTest extends TestCase { + + IDPart part; + + public void testnextIDLowercase() { + + part = new AlphabeticIDPart("a"); + assertEquals("b", part.nextID()); + assertEquals("c", part.nextID()); + + part = new AlphabeticIDPart("x"); + assertEquals("y", part.nextID()); + assertEquals("z", part.nextID()); + +} + + public void testnextIDLowercase2Chars() { + + part = new AlphabeticIDPart("aa"); + assertEquals("ab", part.nextID()); + assertEquals("ac", part.nextID()); + + part = new AlphabeticIDPart("zx"); + assertEquals("zy", part.nextID()); + assertEquals("zz", part.nextID()); + + } + + public void testnextIDLowercase2CharsRolloverFirst() { + + part = new AlphabeticIDPart("ay"); + assertEquals("az", part.nextID()); + assertEquals("ba", part.nextID()); + assertEquals("bb", part.nextID()); + + } + + public void testnextIDUppercase() { + + part = new AlphabeticIDPart("A", "Z", "A"); + assertEquals("B", part.nextID()); + assertEquals("C", part.nextID()); + + part = new AlphabeticIDPart("A", "Z", "X"); + assertEquals("Y", part.nextID()); + assertEquals("Z", part.nextID()); + +} + + public void testnextIDUppercase2Chars() { + + part = new AlphabeticIDPart("A", "Z", "AA"); + assertEquals("AB", part.nextID()); + assertEquals("AC", part.nextID()); + + part = new AlphabeticIDPart("A", "Z", "ZX"); + assertEquals("ZY", part.nextID()); + assertEquals("ZZ", part.nextID()); + + } + + public void testnextIDUppercase2CharsRolloverFirst() { + + part = new AlphabeticIDPart("A", "Z", "AY"); + assertEquals("AZ", part.nextID()); + assertEquals("BA", part.nextID()); + assertEquals("BB", part.nextID()); + + } + + public void testresetIDLowercase() { + + part = new AlphabeticIDPart("zx"); + assertEquals("zy", part.nextID()); + assertEquals("zz", part.nextID()); + part.resetID(); + assertEquals("zx", part.getCurrentID()); + + } + + public void testresetIDUppercase() { + + part = new AlphabeticIDPart("A", "Z", "RA"); + assertEquals("RB", part.nextID()); + assertEquals("RC", part.nextID()); + part.resetID(); + assertEquals("RB", part.nextID()); + + } + + public void testInitialLowercase() { + + part = new AlphabeticIDPart("aaa"); + assertEquals("aaa", part.getInitialID()); + + } + + public void testInitialUppercase() { + + part = new AlphabeticIDPart("A", "Z", "AZ"); + assertEquals("AZ", part.getInitialID()); + + } + + public void testCurrentLowercase() { + + part = new AlphabeticIDPart("aaa"); + assertEquals("aaa", part.getCurrentID()); + assertEquals("aab", part.nextID()); + assertEquals("aac", part.nextID()); + assertEquals("aac", part.getCurrentID()); + assertEquals("aad", part.nextID()); + + } + + public void testCurrentUppercase() { + + part = new AlphabeticIDPart("A", "Z", "A"); + assertEquals("A", part.getCurrentID()); + assertEquals("B", part.nextID()); + assertEquals("C", part.nextID()); + assertEquals("C", part.getCurrentID()); + assertEquals("D", part.nextID()); + + } + + public void testOverflowLowercase() { + + part = new AlphabeticIDPart("zx"); + assertEquals("zy", part.nextID()); + assertEquals("zz", part.nextID()); + assertEquals("aaa", part.nextID()); + + } + + public void testOverflowUppercase() { + + part = new AlphabeticIDPart("A", "Z", "X"); + assertEquals("Y", part.nextID()); + assertEquals("Z", part.nextID()); + assertEquals("AA", part.nextID()); + + } + + public void testNonAlphabeticInitialValue() { + try { + part = new AlphabeticIDPart("&*432"); + fail("Should have thrown IllegalArgumentException here"); + } catch (IllegalArgumentException expected) { + // This Exception should be thrown, and thus the test should pass. + } + } + + public void testNullInitialValue() { + try { + part = new AlphabeticIDPart(null); + fail("Should have thrown IllegalArgumentException here"); + } catch (IllegalArgumentException expected) { + // This Exception should be thrown, and thus the test should pass. + } + } + + public void testEmptyStringInitialValue() { + try { + part = new AlphabeticIDPart(""); + fail("Should have thrown IllegalArgumentException here"); + } catch (IllegalArgumentException expected) { + // This Exception should be thrown, and thus the test should pass. + } + } + + public void testAllSpaceCharsInitialValue() { + try { + part = new AlphabeticIDPart(" "); + fail("Should have thrown IllegalArgumentException here"); + } catch (IllegalArgumentException expected) { + // This Exception should be thrown, and thus the test should pass. + } + } + + public void testIsValidIDDefaultSeries() { + + part = new AlphabeticIDPart(); + + assertTrue(part.isValidID("a")); + assertTrue(part.isValidID("z")); + + assertFalse(part.isValidID("A")); + assertFalse(part.isValidID("123")); + + } + + public void testIsValidIDConstrainedLowerCaseSeries() { + + part = new AlphabeticIDPart("a", "f", "a"); + + assertTrue(part.isValidID("a")); + assertTrue(part.isValidID("b")); + assertTrue(part.isValidID("f")); + + assertFalse(part.isValidID("g")); + assertFalse(part.isValidID("z")); + assertFalse(part.isValidID("A")); + assertFalse(part.isValidID("123")); + + } + + public void testIsValidIDConstrainedUppercaseSeries() { + + part = new AlphabeticIDPart("A", "F", "A"); + + assertTrue(part.isValidID("A")); + assertTrue(part.isValidID("B")); + assertTrue(part.isValidID("F")); + + assertFalse(part.isValidID("G")); + assertFalse(part.isValidID("Z")); + assertFalse(part.isValidID("a")); + assertFalse(part.isValidID("123")); + + } + + // @TODO: Add more tests of boundary conditions, exceptions ... + +} diff --git a/services/id/service/src/test/java/org/collectionspace/services/id/IDPatternTest.java b/services/id/service/src/test/java/org/collectionspace/services/id/IDPatternTest.java new file mode 100644 index 000000000..e89653522 --- /dev/null +++ b/services/id/service/src/test/java/org/collectionspace/services/id/IDPatternTest.java @@ -0,0 +1,250 @@ +/* + * IDPatternTest + * + * Test class for IDPattern. + * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +package org.collectionspace.services.id; + +import static org.junit.Assert.fail; +import java.util.Vector; +import junit.framework.TestCase; + +public class IDPatternTest extends TestCase { + + IDPattern pattern; + IDPart part; + + // Note: tests may fail with IllegalArgumentException + // if any initialization of new IDParts fails + // due to invalid arguments passed to their constructors. + + public void testCurrentIDViaVector() { + + Vector parts = new Vector(); + parts.add(new YearIDPart("2009")); + parts.add(new StringIDPart(".")); + parts.add(new NumericIDPart("1")); + parts.add(new StringIDPart("-")); + parts.add(new AlphabeticIDPart("a")); + pattern = new IDPattern(parts); + assertEquals("2009.1-a", pattern.getCurrentID()); + + } + + public void testCurrentIDViaAdd() { + + pattern = new IDPattern(); + pattern.add(new YearIDPart("2009")); + pattern.add(new StringIDPart(".")); + pattern.add(new NumericIDPart("1")); + pattern.add(new StringIDPart("-")); + pattern.add(new AlphabeticIDPart("a")); + assertEquals("2009.1-a", pattern.getCurrentID()); + + } + + public void testCurrentIDWithPartialSuppliedID() { + + // @TODO: Temporary for testing: ascertain regex patterns + + pattern = new IDPattern(); + pattern.add(new StringIDPart("E")); + pattern.add(new NumericIDPart("1")); + assertEquals("E1", pattern.getCurrentID("E")); + assertEquals("E2", pattern.nextID()); + + pattern = new IDPattern(); + pattern.add(new YearIDPart()); + pattern.add(new StringIDPart(".")); + assertEquals("2009.", pattern.getCurrentID("2009")); + assertEquals("2009.", pattern.nextID()); + assertEquals("2010.", pattern.getCurrentID("2010")); + assertEquals("2010.", pattern.nextID()); + + pattern = new IDPattern(); + pattern.add(new YearIDPart()); + pattern.add(new StringIDPart(".")); + pattern.add(new NumericIDPart("1")); + assertEquals("2009.1", pattern.getCurrentID("2009.")); + assertEquals("2009.2", pattern.nextID()); + + pattern = new IDPattern(); + pattern.add(new YearIDPart()); + pattern.add(new StringIDPart(".")); + pattern.add(new NumericIDPart("55")); + assertEquals("2010.55", pattern.getCurrentID("2010.")); + assertEquals("2010.56", pattern.nextID()); + + pattern = new IDPattern(); + pattern.add(new YearIDPart("2009")); + pattern.add(new StringIDPart(".")); + pattern.add(new NumericIDPart()); + assertEquals("2009.1", pattern.getCurrentID("2009.")); + assertEquals("2009.2", pattern.nextID()); + // Test a repeat of the last two operations. + assertEquals("2009.1", pattern.getCurrentID("2009.")); + assertEquals("2009.2", pattern.nextID()); + + pattern = new IDPattern(); + pattern.add(new YearIDPart("2009")); + pattern.add(new StringIDPart(".")); + pattern.add(new NumericIDPart("1")); + pattern.add(new StringIDPart("-")); + pattern.add(new AlphabeticIDPart("a")); + assertEquals("2009.1-a", pattern.getCurrentID("2009.1-")); + assertEquals("2009.1-b", pattern.nextID()); + assertEquals("2009.3-a", pattern.getCurrentID("2009.3-")); + + } + + public void testCurrentIDWithFullSuppliedID() { + + pattern = new IDPattern(); + pattern.add(new YearIDPart("2009")); + pattern.add(new StringIDPart(".")); + pattern.add(new NumericIDPart("55")); + assertEquals("2009.55", pattern.getCurrentID("2009.55")); + assertEquals("2009.56", pattern.nextID()); + + pattern = new IDPattern(); + pattern.add(new YearIDPart("2009")); + pattern.add(new StringIDPart(".")); + pattern.add(new NumericIDPart("1")); + pattern.add(new StringIDPart("-")); + pattern.add(new AlphabeticIDPart("a")); + assertEquals("2009.1-a", pattern.getCurrentID("2009.1-a")); + assertEquals("2009.1-b", pattern.nextID()); + + } + + public void testNextID() { + + pattern = new IDPattern(); + pattern.add(new YearIDPart("2009")); + pattern.add(new StringIDPart(".")); + pattern.add(new NumericIDPart("1")); + assertEquals("2009.2", pattern.nextID()); + assertEquals("2009.3", pattern.nextID()); + + pattern = new IDPattern(); + pattern.add(new YearIDPart("2009")); + pattern.add(new StringIDPart(".")); + pattern.add(new NumericIDPart("1")); + pattern.add(new StringIDPart("-")); + pattern.add(new AlphabeticIDPart("a")); + assertEquals("2009.1-b", pattern.nextID()); + assertEquals("2009.1-c", pattern.nextID()); + + pattern = new IDPattern(); + pattern.add(new StringIDPart("T")); + pattern.add(new NumericIDPart("1005")); + assertEquals("T1006", pattern.nextID()); + assertEquals("T1007", pattern.nextID()); + + } + + public void testNextIDWithConstantStringID() { + + pattern = new IDPattern(); + pattern.add(new YearIDPart("2009")); + pattern.add(new StringIDPart(".")); + pattern.add(new NumericIDPart("1")); + pattern.add(new StringIDPart("-")); + assertEquals("2009.1-", pattern.nextID()); + assertEquals("2009.1-", pattern.nextID()); + + } + + public void testNextIDWithSuppliedID() { + + pattern = new IDPattern(); + pattern.add(new YearIDPart("2009")); + pattern.add(new StringIDPart(".")); + pattern.add(new NumericIDPart("1")); + assertEquals("2009.2", pattern.nextID("2009.1")); + assertEquals("2009.3", pattern.nextID("2009.2")); + + pattern = new IDPattern(); + pattern.add(new YearIDPart("2009")); + pattern.add(new StringIDPart(".")); + pattern.add(new NumericIDPart("1")); + pattern.add(new StringIDPart("-")); + pattern.add(new AlphabeticIDPart("a")); + assertEquals("2009.1-b", pattern.nextID("2009.1-a")); + assertEquals("2009.3-c", pattern.nextID("2009.3-b")); + + } + + public void testEmptyPartsListCurrentID() { + + pattern = new IDPattern(); + assertEquals("", pattern.getCurrentID()); + + } + + public void testIsValidIDYearPattern() { + + pattern = new IDPattern(); + pattern.add(new YearIDPart("2009")); + + assertTrue(pattern.isValidID("2009")); + assertTrue(pattern.isValidID("5555")); + + assertFalse(pattern.isValidID("456")); + assertFalse(pattern.isValidID("10000")); + + } + + + public void testGetRegex() { + + pattern = new IDPattern(); + pattern.add(new YearIDPart("2009")); + pattern.add(new StringIDPart(".")); + pattern.add(new NumericIDPart("1")); + assertEquals("(\\d{4})(\\.)(\\d{1,6})", pattern.getRegex()); + + } + + public void testIsValidIDYearSeparatorItemPattern() { + + pattern = new IDPattern(); + pattern.add(new YearIDPart("2009")); + pattern.add(new StringIDPart(".")); + pattern.add(new NumericIDPart("1")); + + assertTrue(pattern.isValidID("2009.1")); + assertTrue(pattern.isValidID("5555.55")); + + assertFalse(pattern.isValidID("456.1")); + assertFalse(pattern.isValidID("2009-1")); + assertFalse(pattern.isValidID("2009.a")); + assertFalse(pattern.isValidID("2009-a")); + assertFalse(pattern.isValidID("non-pattern conforming text")); + + pattern = new IDPattern(); + pattern.add(new YearIDPart("2009")); + pattern.add(new StringIDPart("ZZ.AND.")); + pattern.add(new NumericIDPart("1")); + + assertTrue(pattern.isValidID("2009ZZ.AND.1")); + assertFalse(pattern.isValidID("2009ZZ-AND-1")); + + } + + // @TODO: Add more tests of boundary conditions, exceptions ... + +} diff --git a/services/id/service/src/test/java/org/collectionspace/services/id/NumericIDPartTest.java b/services/id/service/src/test/java/org/collectionspace/services/id/NumericIDPartTest.java new file mode 100644 index 000000000..0708300bb --- /dev/null +++ b/services/id/service/src/test/java/org/collectionspace/services/id/NumericIDPartTest.java @@ -0,0 +1,165 @@ +/* + * NumericIDPartTest + * + * Test class for NumericIDPart. + * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +package org.collectionspace.services.id; + +import static org.junit.Assert.fail; +import junit.framework.TestCase; + +public class NumericIDPartTest extends TestCase { + + IDPart part; + + public void testNextID() { + + part = new NumericIDPart("0"); + assertEquals("1", part.nextID()); + assertEquals("2", part.nextID()); + assertEquals("3", part.nextID()); + + part = new NumericIDPart("25"); + assertEquals("26", part.nextID()); + assertEquals("27", part.nextID()); + assertEquals("28", part.nextID()); + + } + + public void testNextIDOverflow() { + + try { + part = new NumericIDPart("997", "3"); + assertEquals("998", part.nextID()); + assertEquals("999", part.nextID()); + assertEquals("1000", part.nextID()); + fail("Should have thrown IllegalStateException here"); + } catch (IllegalStateException expected) { + // This Exception should be thrown, and thus the test should pass. + } + + // Tests default MAX_LENGTH value of 6 decimal places + try { + part = new NumericIDPart("999997"); + assertEquals("999998", part.nextID()); + assertEquals("999999", part.nextID()); + assertEquals("1000000", part.nextID()); + fail("Should have thrown IllegalStateException here"); + } catch (IllegalStateException expected) { + // This Exception should be thrown, and thus the test should pass. + } + + } + + public void testresetID() { + + part = new NumericIDPart("25"); + assertEquals("26", part.nextID()); + assertEquals("27", part.nextID()); + assertEquals("28", part.nextID()); + part.resetID(); + assertEquals("26", part.nextID()); + + } + + public void testInitialID() { + + part = new NumericIDPart("0"); + assertEquals("0", part.getInitialID()); + + part = new NumericIDPart("25"); + assertEquals("25", part.getInitialID()); + + } + + public void testCurrentID() { + + part = new NumericIDPart("0"); + assertEquals("0", part.getCurrentID()); + assertEquals("1", part.nextID()); + assertEquals("2", part.nextID()); + assertEquals("2", part.getCurrentID()); + assertEquals("3", part.nextID()); + + part = new NumericIDPart("25"); + assertEquals("25", part.getCurrentID()); + + } + + public void testNullInitialValue() { + + try { + part = new NumericIDPart(null); + fail("Should have thrown IllegalArgumentException here"); + } catch (IllegalArgumentException expected) { + // This Exception should be thrown, and thus the test should pass. + } + + } + + public void testNonLongParseableInitialValue() { + + try { + part = new NumericIDPart("not a long parseable value"); + fail("Should have thrown IllegalArgumentException here"); + } catch (IllegalArgumentException expected) { + // This Exception should be thrown, and thus the test should pass. + } + + } + + public void testNonLongParseableMaxLength() { + + try { + part = new NumericIDPart("1", "not an int parseable value"); + fail("Should have thrown IllegalArgumentException here"); + } catch (IllegalArgumentException expected) { + // This Exception should be thrown, and thus the test should pass. + } + + } + + public void testIsValidID() { + + part = new NumericIDPart("1"); + assertTrue(part.isValidID("1")); + + part = new NumericIDPart("1"); + assertTrue(part.isValidID("123")); + + part = new NumericIDPart("1"); + assertTrue(part.isValidID("123456")); + + part = new NumericIDPart("1"); + assertFalse(part.isValidID("1234567")); + + part = new NumericIDPart("1", "3"); + assertTrue(part.isValidID("123")); + + part = new NumericIDPart("1", "3"); + assertFalse(part.isValidID("1234")); + + part = new NumericIDPart("1"); + assertFalse(part.isValidID("not a parseable long")); + + part = new NumericIDPart("1", "3"); + assertFalse(part.isValidID("not a parseable long")); + + } + + // @TODO: Add more tests of boundary conditions, exceptions ... + +} diff --git a/services/id/service/src/test/java/org/collectionspace/services/id/StringIDPartTest.java b/services/id/service/src/test/java/org/collectionspace/services/id/StringIDPartTest.java new file mode 100644 index 000000000..dd3a7a928 --- /dev/null +++ b/services/id/service/src/test/java/org/collectionspace/services/id/StringIDPartTest.java @@ -0,0 +1,110 @@ +/* + * StringIDPartTest + * + * Test class for StringIDPart. + * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +package org.collectionspace.services.id; + +import static org.junit.Assert.fail; +import junit.framework.TestCase; + +public class StringIDPartTest extends TestCase { + + IDPart part; + + public void testNextID() { + part = new StringIDPart("XYZ"); + assertEquals("XYZ", part.nextID()); + } + + public void testresetID() { + + part = new StringIDPart("."); + assertEquals(".", part.nextID()); + part.resetID(); + assertEquals(".", part.nextID()); + + } + + public void testInitialID() { + part = new StringIDPart("-"); + assertEquals("-", part.getInitialID()); + } + + public void testCurrentID() { + part = new StringIDPart("- -"); + assertEquals("- -", part.getCurrentID()); + } + + public void testNullInitialValue() { + + try { + part = new StringIDPart(null); + fail("Should have thrown IllegalArgumentException here"); + } catch (IllegalArgumentException expected) { + // This Exception should be thrown, and thus the test should pass. + } + + } + + public void testEmptyInitialValue() { + + try { + part = new StringIDPart(""); + fail("Should have thrown IllegalArgumentException here"); + } catch (IllegalArgumentException expected) { + // This Exception should be thrown, and thus the test should pass. + } + + } + + public void testIsValidID() { + + part = new StringIDPart("-"); + assertTrue(part.isValidID("-")); + + part = new StringIDPart("-"); + assertFalse(part.isValidID("--")); + + // Test chars with special meaning in regexes. + part = new StringIDPart("."); + assertTrue(part.isValidID(".")); + + part = new StringIDPart("TE"); + assertTrue(part.isValidID("TE")); + + part = new StringIDPart("TE"); + assertFalse(part.isValidID("T")); + + part = new StringIDPart("T"); + assertFalse(part.isValidID("TE")); + + } + + public void testNullValidationValue() { + + try { + part = new StringIDPart("-"); + assertFalse(part.isValidID(null)); + fail("Should have thrown IllegalArgumentException here"); + } catch (IllegalArgumentException expected) { + // This Exception should be thrown, and thus the test should pass. + } + + } + // @TODO: Add more tests of boundary conditions, exceptions ... + +} diff --git a/services/id/service/src/test/java/org/collectionspace/services/id/YearIDPartTest.java b/services/id/service/src/test/java/org/collectionspace/services/id/YearIDPartTest.java new file mode 100644 index 000000000..12b5d85f3 --- /dev/null +++ b/services/id/service/src/test/java/org/collectionspace/services/id/YearIDPartTest.java @@ -0,0 +1,121 @@ +/* + * YearIDPartTest + * + * Test class for YearIDPart. + * + * Copyright 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * @author $Author: aron $ + * @version $Revision: 267 $ + * $Date: 2009-06-19 19:03:38 -0700 (Fri, 19 Jun 2009) $ + */ + +package org.collectionspace.services.id; + +import static org.junit.Assert.fail; +import java.util.Calendar; +import java.util.GregorianCalendar; +import junit.framework.TestCase; + +public class YearIDPartTest extends TestCase { + + IDPart part; + String year = "1999"; + + public String getCurrentYear() { + Calendar cal = GregorianCalendar.getInstance(); + int y = cal.get(Calendar.YEAR); + return Integer.toString(y); + } + + public void testCurrentID() { + + part = new YearIDPart(); + assertEquals(getCurrentYear(), part.getCurrentID()); + + part = new YearIDPart(year); + assertEquals(year, part.getCurrentID()); + + } + + +/* + public void testNextID() { + part = new YearIDPart("XYZ"); + assertEquals("XYZ", part.nextID()); + } + + public void testresetID() { + + part = new YearIDPart("."); + assertEquals(".", part.nextID()); + part.resetID(); + assertEquals(".", part.nextID()); + + } + + public void testInitialID() { + part = new YearIDPart("-"); + assertEquals("-", part.getInitialID()); + } + +*/ + + public void testNullInitialValue() { + + try { + part = new YearIDPart(null); + fail("Should have thrown IllegalArgumentException here"); + } catch (IllegalArgumentException expected) { + // This Exception should be thrown, and thus the test should pass. + } + + } + + public void testEmptyInitialValue() { + + try { + part = new YearIDPart(""); + fail("Should have thrown IllegalArgumentException here"); + } catch (IllegalArgumentException expected) { + // This Exception should be thrown, and thus the test should pass. + } + + } + + public void testIsValidID() { + + part = new YearIDPart(); + assertTrue(part.isValidID("2009")); + + part = new YearIDPart(); + assertFalse(part.isValidID("839")); + + part = new YearIDPart(); + assertFalse(part.isValidID("10100")); + + part = new YearIDPart(); + assertFalse(part.isValidID("non-numeric value")); + + } + + public void testNullValidationValue() { + + try { + part = new YearIDPart(); + assertFalse(part.isValidID(null)); + fail("Should have thrown IllegalArgumentException here"); + } catch (IllegalArgumentException expected) { + // This Exception should be thrown, and thus the test should pass. + } + + } + // @TODO: Add more tests of boundary conditions, exceptions ... + +} diff --git a/services/id/service/src/test/resources/log4j.xml b/services/id/service/src/test/resources/log4j.xml new file mode 100644 index 000000000..52121cb83 --- /dev/null +++ b/services/id/service/src/test/resources/log4j.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +