]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-361: More work on refactoring ID Service to a hierarchy of IDGeneratorParts...
authorAron Roberts <aron@socrates.berkeley.edu>
Thu, 10 Sep 2009 02:50:33 +0000 (02:50 +0000)
committerAron Roberts <aron@socrates.berkeley.edu>
Thu, 10 Sep 2009 02:50:33 +0000 (02:50 +0000)
18 files changed:
services/id/service/src/main/java/org/collectionspace/services/id/AlphabeticIDGeneratorPart.java
services/id/service/src/main/java/org/collectionspace/services/id/BaseIDGenerator.java
services/id/service/src/main/java/org/collectionspace/services/id/IDGenerator.java
services/id/service/src/main/java/org/collectionspace/services/id/IDGeneratorPart.java
services/id/service/src/main/java/org/collectionspace/services/id/IDResource.java
services/id/service/src/main/java/org/collectionspace/services/id/IDService.java
services/id/service/src/main/java/org/collectionspace/services/id/IDServiceJdbcImpl.java
services/id/service/src/main/java/org/collectionspace/services/id/NumericIDGeneratorPart.java
services/id/service/src/main/java/org/collectionspace/services/id/StringIDGeneratorPart.java
services/id/service/src/main/java/org/collectionspace/services/id/UUIDGeneratorPart.java [new file with mode: 0644]
services/id/service/src/main/java/org/collectionspace/services/id/YearIDGeneratorPart.java
services/id/service/src/test/java/org/collectionspace/services/id/test/AlphabeticIDGeneratorPartTest.java
services/id/service/src/test/java/org/collectionspace/services/id/test/IDGeneratorTest.java
services/id/service/src/test/java/org/collectionspace/services/id/test/IDServiceJdbcImplTest.java
services/id/service/src/test/java/org/collectionspace/services/id/test/NumericIDGeneratorPartTest.java
services/id/service/src/test/java/org/collectionspace/services/id/test/StringIDGeneratorPartTest.java
services/id/service/src/test/java/org/collectionspace/services/id/test/UUIDGeneratorPartTest.java [new file with mode: 0644]
services/id/service/src/test/java/org/collectionspace/services/id/test/YearIDGeneratorPartTest.java

index 9a9b59d0c533cec6d64b86bf14546029ce28c124..c29975c62f7d304196c69fbbc1d86727af5f1579 100644 (file)
  *
  * You may obtain a copy of the ECL 2.0 License at
  * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 // @TODO: Add Javadoc comments
@@ -61,7 +67,7 @@ import java.util.regex.Pattern;
  * $LastChangedRevision$
  * $LastChangedDate$
  */
-public class AlphabeticIDGeneratorPart implements IDGeneratorPart {
+public class AlphabeticIDGeneratorPart implements SequenceIDGeneratorPart {
    
     private static final char NULL_CHAR = '\u0000';
     
@@ -178,7 +184,7 @@ public class AlphabeticIDGeneratorPart implements IDGeneratorPart {
         }
 
         // Initialize the current value from the initial value.
-        this.currentValue = new Vector<Character>(this.initialValue);
+        // this.currentValue = new Vector<Character>(this.initialValue);
 
     }
 
@@ -189,7 +195,11 @@ public class AlphabeticIDGeneratorPart implements IDGeneratorPart {
 
     // Returns the current value.
     public String getCurrentID() {
-        return getIDString(this.currentValue);
+        if (this.currentValue == null || this.currentValue.size() == 0) {
+            return getIDString(this.initialValue);
+        } else {
+            return getIDString(this.currentValue);
+        }
     }
 
     // Sets the current value.
@@ -235,10 +245,10 @@ public class AlphabeticIDGeneratorPart implements IDGeneratorPart {
 
     // Reset the current value to the initial value.
     public void resetID() {
-        Collections.copy(this.currentValue, this.initialValue);
+        this.currentValue = this.initialValue;
+        // Collections.copy(this.currentValue, this.initialValue);
     }
 
-    
     // Returns the next alphabetic ID in the sequence.
     //
     // Currently, the number of characters auto-expands as the
@@ -292,25 +302,34 @@ public class AlphabeticIDGeneratorPart implements IDGeneratorPart {
         return getIDString(this.currentValue);
         
     }
-
-    // Returns a String representation of the ID, by appending
-    // the String values of each character.
-    public String getIDString(Vector<Character> v) {
-        StringBuffer sb = new StringBuffer();
-        for ( Character ch : v ) {
-            sb.append(ch.toString());
+    
+    /**
+     * Returns a new identifier.
+     */
+    @Override
+    public String newID() {
+        // If there is no current value, return the initial value
+        // and set the current value to the initial value.
+        if (this.currentValue == null || this.currentValue.size() == 0) {
+            this.currentValue = this.initialValue;
+            return getIDString(this.currentValue);
+        // Otherwise, return a new value.
+        } else {
+            return nextID();
         }
-        return sb.toString();
     }
 
-    public boolean isValidID(String value) {
-
-        if (value == null || value.equals("")) {
-            return false;
-        }
+    @Override
+    public boolean isValidID(String id) {
+    
+        if (id == null) return false;
+        // @TODO May potentially throw at least one pattern-related exception.
+        // We'll need to catch and handle this here, as well as in all
+        // derived classes and test cases that invoke validation.
 
         Pattern pattern = Pattern.compile(getRegex());
-        Matcher matcher = pattern.matcher(value);
+        Matcher matcher = pattern.matcher(id);
         if (matcher.matches()) {
             return true;
         } else {
@@ -319,15 +338,36 @@ public class AlphabeticIDGeneratorPart implements IDGeneratorPart {
         
     }
 
+    @Override
     public 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.
+        // @TODO May need to constrain the number of alphabetic 
+        // characters based on a maximum length value.
+        //
+        // Currently, this regex simply matches any sequence of one
+        // or more alphabetic characters, with no explicit constraint
+        // on length.
         String regex = 
           "(" + "[" + 
           String.valueOf(this.startChar) + "-" + String.valueOf(this.endChar) +
-          "]+" + ")";
+          "]" + "+" + ")";
         return regex;
     }
+
+    /**
+     * Returns a String representation of the ID, by concatenating
+     * the String values of each alphabetic character constituting the ID.
+     *
+     * @param   characters  The alphabetic characters constituting the ID.
+     *
+     * @return  A String representation of the ID.
+     */
+    public String getIDString(Vector<Character> characters) {
+        StringBuffer sb = new StringBuffer();
+        for ( Character ch : characters ) {
+            sb.append(ch.toString());
+        }
+        return sb.toString();
+    }
+
     
 }
index 5f1339d987c0f21755278e55c2439034dabf2cbe..fbad490f29a5efeefef987434344cae179abb82c 100644 (file)
@@ -1,8 +1,4 @@
 /**
- * BaseIDGenerator
- *
- * Models an identifier (ID), which consists of multiple IDGeneratorParts.
- *
  * This document is a part of the source code and related artifacts
  * for CollectionSpace, an open source collections management system
  * for museums and related institutions:
  * You may obtain a copy of the ECL 2.0 License at
  * https://source.collectionspace.org/collection-space/LICENSE.txt
  *
- * $LastChangedBy$
- * $LastChangedRevision$
- * $LastChangedDate$
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 // @TODO: Add Javadoc comments
@@ -36,274 +34,368 @@ import java.util.Vector;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+/**
+ * BaseIDGenerator
+ *
+ * Models an identifier (ID) generator, consisting of 
+ * multiple IDGeneratorParts.
+ *
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ */
 public class BaseIDGenerator implements IDGenerator {
 
-       private String csid = "";
-       private String uri = "";
-       private String description = "";
-       private Vector<IDGeneratorPart> parts = new Vector<IDGeneratorPart>();
-
-       final static int MAX_ID_LENGTH = 50;
-       
-       // Constructor
-       public BaseIDGenerator(String csid) {
-         if (csid != null && ! csid.equals("")) {
-           this.csid = csid;
-         }
-       }
-       
-       // Constructor
-       public BaseIDGenerator(String csid, Vector<IDGeneratorPart> partsList) {
-         if (csid != null && ! csid.equals("")) {
-           this.csid = csid;
-         }
-               if (partsList != null) {
-                       this.parts = partsList;
-               }
-       }
+    private String csid = "";
+    private String uri = "";
+    private String description = "";
+    private Vector<IDGeneratorPart> parts = new Vector<IDGeneratorPart>();
 
-       public String getCsid() {
-         return this.csid;
-  }
+    final static int MAX_ID_LENGTH = 50;
+    
+    /**
+     * Constructor.
+     *
+     * @param csid  A CollectionSpace ID (CSID) identifying this ID generator.
+     *
+     */
+    public BaseIDGenerator(String csid) {
+      if (csid != null && ! csid.equals("")) {
+        this.csid = csid;
+      }
+    }
+    
+    /**
+     * Constructor.
+     *
+     * @param csid  A CollectionSpace ID (CSID) identifying this ID generator.
+     *
+     * @param parts A collection of ID generator parts.
+     *
+     */
+    public BaseIDGenerator(String csid, Vector<IDGeneratorPart> parts) {
+        if (csid != null && ! csid.equals("")) {
+            this.csid = csid;
+        }
+        if (parts != null) {
+            this.parts = parts;
+        }
+    }
 
-       public void setURI(String uriStr) {
-    if (uriStr == null || uriStr.equals("")) {
-      return;
+    /**
+     * Returns the CollectionSpace ID (CSID) identifying this ID generator.
+     */
+    public String getCsid() {
+        return this.csid;
     }
-    // Validate that this is a legal URI.
-    try {
-      URI uri = new URI(uriStr);
-    } catch (URISyntaxException e) {
-      return;
+
+    /**
+     * Sets a URI as a second type of identifier for this ID generator,
+     * in addition to the CollectionSpace ID (CSID).
+     *
+     * @param uriStr A String representation of a URI.
+     */
+    public void setURI(String uriStr) {
+        if (uriStr == null || uriStr.equals("")) {
+            return;
+        }
+        // Validate that this is a legal URI.
+        try {
+            URI uri = new URI(uriStr);
+        } catch (URISyntaxException e) {
+            // Fail silently without setting the URI.
+            return;
+        }
+        this.uri = uriStr;
     }
-    this.uri = uriStr;
-  }
 
-       public String getURI() {
-         return this.uri;
-  }
+    /**
+     * Returns the URI, if any, that is used as a second type of
+     * identifier for this ID generator.
+     */
+    public String getURI() {
+        return this.uri;
+    }
 
-       public void setDescription(String description) {
-    if (description != null) {
-      this.description = description;
+    /**
+     * Sets an optional, human-readable description of this ID generator.
+     *
+     * @param description A human-readable description of this ID generator.
+     */
+    public void setDescription(String description) {
+        if (description != null) {
+            this.description = description;
+        }
     }
-  }
 
-       public String getDescription() {
-    return this.description;
-  }
+    /**
+     * Returns the human-readable description of this ID generator, if any.
+     */
+    public String getDescription() {
+        return this.description;
+    }
   
-       public void add(IDGeneratorPart part) {
-               if (part != null) {
-                       this.parts.add(part);
-               }
-       }
+    /**
+     * Adds a single ID generator part.
+     *
+     * @param part  An ID generator part.
+     */
+    public void add(IDGeneratorPart part) {
+        if (part != null) {
+            this.parts.add(part);
+        }
+    }
 
-       // Returns the current value of this ID.
-       public String getCurrentID() {
-               StringBuffer sb = new StringBuffer(MAX_ID_LENGTH);
-               for (IDGeneratorPart part : this.parts) {
-                       sb.append(part.getCurrentID());
-               }
-               return sb.toString();
-       }
+    /**
+     * Removes all ID generator parts.
+     */
+    public void clear() {
+        this.parts.clear();
+    }
 
-       // 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 IDGeneratorPart.
-       // * "E55-" becomes "E55-a", where the next ID component
-       //   is an incrementing alphabetic IDGeneratorPart.
-       public String getCurrentID(String value)
-               throws IllegalArgumentException {
+    @Override
+    public String getCurrentID() {
+        StringBuffer sb = new StringBuffer(MAX_ID_LENGTH);
+        for (IDGeneratorPart part : this.parts) {
+            sb.append(part.getCurrentID());
+        }
+        return sb.toString();
+    }
 
-         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 BaseIDGenerator'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 (IDGeneratorPart 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 IDGeneratorParts 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.");
-               }
+/*
+    @Override
+    public String newID() {
+        StringBuffer sb = new StringBuffer(MAX_ID_LENGTH);
+        int lastPart = parts.size() - 1;
+        int i = 0;
+        for (IDGeneratorPart part : this.parts) {
+            if (i == lastPart){
+                sb.append(part.newID());
+            } else {
+                sb.append(part.getCurrentID());
+            }
+            i++;
+        }
+        return sb.toString();
+    }
+*/
 
-               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 IDGeneratorParts.
-               IDGeneratorPart currentPart;
-               for (int i = 1; i <= matchedParts; i++) {
-                 currentPart = this.parts.get(i - 1);
-      currentPart.setCurrentID(matcher.group(i));
-               }
+    // 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 IDGeneratorPart.
+    // * "E55-" becomes "E55-a", where the next ID component
+    //   is an incrementing alphabetic IDGeneratorPart.
+    public String getCurrentID(String value)
+        throws IllegalArgumentException {
 
-               // Obtain the initial value of the next IDGeneratorPart, 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' IDGeneratorPart, 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 IDGeneratorPart.
-                       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 IDGeneratorParts, as well as on the added IDGeneratorPart
-               // 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();
+      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 BaseIDGenerator'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 (IDGeneratorPart 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 IDGeneratorParts 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.");
+        }
 
-       // Returns the next value of this ID, and sets the current value to that ID.
-       public String newID() throws IllegalStateException {
-       
-               // Obtain the last (least significant) IDGeneratorPart,
-               // 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 IDGeneratorParts
-               StringBuffer sb = new StringBuffer(MAX_ID_LENGTH);
-               for (IDGeneratorPart part : this.parts) {
-                       sb.append(part.getCurrentID());
-               }
-               
-               return sb.toString();
-               
-       }
+        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 IDGeneratorParts.
+        IDGeneratorPart currentPart;
+        for (int i = 1; i <= matchedParts; i++) {
+            currentPart = this.parts.get(i - 1);
+            currentPart.setCurrentID(matcher.group(i));
+        }
 
-       // 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 String newID(String value)
-               throws IllegalStateException, IllegalArgumentException {
+        // Obtain the initial value of the next IDGeneratorPart, 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' IDGeneratorPart, and we must catch that Exception below. 
+        int nextPartNum = matchedParts;
+        try {
+            // String initial = this.parts.get(nextPartNum).getInitialID();
+            // this.parts.get(nextPartNum).setCurrentID(initial);
+            String currentID = this.parts.get(nextPartNum).getCurrentID();
+            // Increment the number of matched parts to reflect the
+            // addition of this next IDGeneratorPart.
+            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 IDGeneratorParts, as well as on the added IDGeneratorPart
+        // 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();
 
-         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 IDGeneratorParts.
-               IDGeneratorPart currentPart;
-               for (int i = 1; i <= (matcher.groupCount() - 1); i++) {
-                 currentPart = this.parts.get(i - 1);
-      currentPart.setCurrentID(matcher.group(i));
-               }
+    }
+
+    // Returns the next value of this ID, and sets the current value to that ID.
+    @Override
+    public String newID() throws IllegalStateException {
+    
+        int lastPartNum = this.parts.size();
+        StringBuffer sb = new StringBuffer(MAX_ID_LENGTH);
+        int i = 0;
+        for (IDGeneratorPart part : this.parts) {
+               i++;
+               if (i < lastPartNum) {
+               sb.append(part.getCurrentID());
+               } else {
+                       sb.append(part.newID());
+               }
+        }
+        
+        return sb.toString();
+        
+    }
 
-               // Obtain the last (least significant) IDGeneratorPart,
-               // 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 IDGeneratorParts
-               StringBuffer sb = new StringBuffer();
-               for (IDGeneratorPart 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 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 the new value of this ID, given a
+    // supplied ID that entirely matches the pattern,
+    // and sets the current value to that ID.
+    public String newID(String value)
+        throws IllegalStateException, IllegalArgumentException {
 
-       // Returns a regular expression to validate this ID.
-       public String getRegex() {
-               StringBuffer sb = new StringBuffer();
-               for (IDGeneratorPart part : this.parts) {
-                       sb.append(part.getRegex());
-               }
-               return sb.toString();
-       }
+        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 IDGeneratorParts.
+        IDGeneratorPart currentPart;
+        for (int i = 1; i <= (matcher.groupCount() - 1); i++) {
+            currentPart = this.parts.get(i - 1);
+            currentPart.setCurrentID(matcher.group(i));
+        }
+        
+        // @TODO This code is duplicated in newID(), above,
+        // and thus we may want to refactor this.
+        int lastPartNum = this.parts.size();
+        StringBuffer sb = new StringBuffer(MAX_ID_LENGTH);
+        int i = 0;
+        for (IDGeneratorPart part : this.parts) {
+               i++;
+               if (i < lastPartNum) {
+               sb.append(part.getCurrentID());
+               } else {
+                       sb.append(part.newID());
+               }
+        }
+        
+        return sb.toString();
+        
+    }
+    
+    @Override
+    public boolean isValidID(String id) {
+        return isValidID(id, getRegex());
+    }
+
+   /**
+     * Validates a supplied ID against the format of the IDs
+     * generated by this ID generator.
+     *
+     * @param    id    An ID.
+     *
+     * @param    regex  A regular expression for validating IDs against
+     *                  a format.
+     *
+     * @return   true if the supplied ID matches the format of the
+     *           IDs generated by this ID generator;
+     *           false if it does not match that format.
+      */
+    public boolean isValidID(String id, String regex) {
+    
+        if (id == null) return false;
+        // @TODO May potentially throw at least one pattern-related exception.
+        // We'll need to catch and handle this here, as well as in all
+        // derived classes and test cases that invoke validation.
+
+        Pattern pattern = Pattern.compile(regex);
+        Matcher matcher = pattern.matcher(id);
+        if (matcher.matches()) {
+            return true;
+        } else {
+            return false;
+        }
+        
+    }
+
+    @Override
+    public String getRegex() {
+        StringBuffer sb = new StringBuffer();
+        for (IDGeneratorPart part : this.parts) {
+            sb.append(part.getRegex());
+        }
+        return sb.toString();
+    }
  
 }
index 829e6a964e2e2abd59ab472e8f1748ce7da2f9aa..b8d733f66def84595277c4d60de06fecd65ff8be 100644 (file)
  * You may obtain a copy of the ECL 2.0 License at
  * https://source.collectionspace.org/collection-space/LICENSE.txt
  *
- * $LastChangedBy$
- * $LastChangedRevision$
- * $LastChangedDate$
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
  
 package org.collectionspace.services.id;
@@ -30,18 +32,44 @@ package org.collectionspace.services.id;
 public interface IDGenerator {
 
     /**
-     * Returns a new identifier (ID).
+     * Returns a new ID.
+     *
+     * @return  A new ID.
      */
        public String newID();
 
     /**
-     * Returns a new identifier (ID), based on a supplied identifier.
+     * Returns a new ID, based on a supplied identifier.
+     *
+     * @return  A new ID.
      */
        public String newID(String id);
-
+       
     /**
-     * Returns the current identifier (ID).
+     * Returns the current ID.
+     *
+     * @return  The current ID.
      */
        public String getCurrentID();
 
+    /**
+     * Validates a supplied ID against the format of the IDs
+     * generated by this ID generator.
+     *
+     * @param    id    An ID.
+     *
+     * @return   true if the supplied ID matches the format of the
+     *           IDs generated by this ID generator;
+     *           false if it does not match that format.
+     */
+    public boolean isValidID(String id);
+
+    /**
+     * Returns a regular expression that can be used to validate the IDs
+     * generated by this ID generator. 
+     *
+     * @return  A regular expression that can be used to validate IDs.
+     */
+    public String getRegex();
+
 }
index b76a12f970b3a2d9a3a318da2ad8f24242078795..4193c4eb101f821e4a90e257e09daed8216ce808 100644 (file)
@@ -1,4 +1,4 @@
- /*    
+/**
  * This document is a part of the source code and related artifacts
  * for CollectionSpace, an open source collections management system
  * for museums and related institutions:
  *
  * You may obtain a copy of the ECL 2.0 License at
  * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
- /*    
+/**    
  * IDGeneratorPart, interface for a component part of an ID Generator.
  *
  * $LastChangedRevision$
@@ -25,27 +31,47 @@ package org.collectionspace.services.id;
 
 public interface IDGeneratorPart {
     
-       // Returns the initial value of the ID.
-       public String getInitialID();
-
-       // Gets the current value of an ID.
+    /**
+     * Returns the current value of the ID
+     * associated with this part.
+     *
+     * @return  The current value of the ID.
+     */
        public String getCurrentID();
-       
-       // Sets the current value of an ID.
-       public void setCurrentID(String value) throws IllegalArgumentException;
 
-       // Resets an ID to its initial value.
-       public void resetID();
+    /**
+     * Sets the current value of the ID
+     * associated with this part.
+     *
+     * @return  The current value of the ID.
+     */
+       public void setCurrentID(String value) throws IllegalArgumentException;
 
-       // Returns the next ID in the sequence, and sets
-       // the current value to that ID.
-       public String nextID() throws IllegalStateException;
+    /**
+     * Returns a new ID.
+     *
+     * @return  An ID.
+     */
+       public String newID();
 
-       // Validates an ID against a pattern of generated IDs.
-       public boolean isValidID(String value);
+    /**
+     * Validates a supplied ID against the format of the IDs
+     * generated by this ID generator.
+     *
+     * @param    id    An ID.
+     *
+     * @return   true if the supplied ID matches the format of the
+     *           IDs generated by this ID generator;
+     *           false if it does not match that format.
+     */
+    public boolean isValidID(String id);
 
-       // Returns a String representation of the regular expression ("regex")
-       // pattern used to validate instance values of generated IDs.  
-       public String getRegex();
+    /**
+     * Returns a regular expression that can be used to validate the IDs
+     * generated by this ID generator. 
+     *
+     * @return  A regular expression that can be used to validate IDs.
+     */
+    public String getRegex();
                
 }
index 0ad1b6f5b0aad4e5d7a9e72b2267f7bd18cffcb5..90932fbf0c9f98ff1bc3e2748de83931116e98e6 100644 (file)
  *
  * You may obtain a copy of the ECL 2.0 License at
  * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
   
 package org.collectionspace.services.id;
index ce333f3f03e61072f60c8462a6c9544a8339b4b3..c437d7c8d0fcd2461c311c0d9023211d61b34481 100644 (file)
@@ -28,44 +28,44 @@ package org.collectionspace.services.id;
  */
 public interface IDService {
 
-       // ----------------------------------------
-       // IDs
-       // ----------------------------------------
+    // ----------------------------------------
+    // IDs
+    // ----------------------------------------
 
-       // Create
+    // Create
 
-       // Read single object
-       
+    // Read single object
+    
     // Generates and returns a new ID from the specified ID generator.
     public String newID(String csid)
       throws IllegalArgumentException, IllegalStateException;
     
     // Returns the last-generated ID associated with the specified ID generator.
     public String getLastID(String csid)
-      throws IllegalArgumentException, IllegalStateException;
+        throws IllegalArgumentException, IllegalStateException;
 
-       // Read a list of objects (aka read multiple)
-       
-       // ----------------------------------------
-       // ID Generators
-       // ----------------------------------------
-       
-       // Create
-       
-         // Adds a new ID generator.
+    // Read a list of objects (aka read multiple)
+    
+    // ----------------------------------------
+    // ID Generators
+    // ----------------------------------------
+    
+    // Create
+    
+    // Adds a new ID generator.
     public void addIDGenerator(String csid, String serializedIDGenerator)
-      throws IllegalArgumentException, IllegalStateException;
-       
-         // Read single object
+        throws IllegalArgumentException, IllegalStateException;
+    
+    // Read single object
     public String getIDGenerator(String csid)
-      throws IllegalArgumentException, IllegalStateException;
-       
-       // Read a list of objects (aka read multiple)
-       
-         // Update (may need to check for changes in the ID generator structure)
+        throws IllegalArgumentException, IllegalStateException;
+    
+    // Read a list of objects (aka read multiple)
+    
+    // Update (may need to check for changes in the ID generator structure)
     public void updateIDGenerator(String csid, String serializedIDGenerator)
-      throws IllegalArgumentException, IllegalStateException;
-       
-       // Delete (possibly not permitted - deactivate instead?)
+        throws IllegalArgumentException, IllegalStateException;
+    
+    // Delete (possibly not permitted - deactivate instead?)
 
 }
index da5c69f94a754e5a4a2e9002660c3c5b159145a8..93d9ad698090180ee2f90cd7258f4255e8f31bcc 100644 (file)
  *
  * You may obtain a copy of the ECL 2.0 License at
  * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 // *IMPORTANT*
@@ -85,195 +91,194 @@ import org.slf4j.LoggerFactory;
  * Manages the storage of ID generators and persistence of their
  * current state, via a JDBC interface to an underlying database.
  *
- * $LastChangedBy$
  * $LastChangedRevision$
  * $LastChangedDate$
  */
 public class IDServiceJdbcImpl implements IDService {
 
        final Logger logger = LoggerFactory.getLogger(IDServiceJdbcImpl.class);
+       
+       final String JDBC_DRIVER_CLASSNAME = "com.mysql.jdbc.Driver";
+       final String DATABASE_NAME = "cspace";
+       final String DATABASE_URL = "jdbc:mysql://localhost:3306/" + DATABASE_NAME;
+       final String DATABASE_USERNAME = "test";
+       final String DATABASE_PASSWORD = "test";
+       final String TABLE_NAME = "id_generator";
+       
+       boolean hasPreconditions = true;
 
-  final String JDBC_DRIVER_CLASSNAME = "com.mysql.jdbc.Driver";
-  final String DATABASE_NAME = "cspace";
-  final String DATABASE_URL = "jdbc:mysql://localhost:3306/" + DATABASE_NAME;
-  final String DATABASE_USERNAME = "test";
-  final String DATABASE_PASSWORD = "test";
-  final String TABLE_NAME = "id_generator";
-  
-  boolean hasPreconditions = true;
-
-  //////////////////////////////////////////////////////////////////////
-  /**
-   * Constructor (no-argument).
-   */ 
-  public void IDServiceJdbcImpl() throws IllegalStateException {
-  
-    // @TODO Decide when and how to fail at startup, or else to correct
-    // failure conditions automatically, when preconditions are not met.
-    //
-    // Currently, errors at initialization are merely informative and
-    // result in exceptions that can be persistently logged.
-    
-    try {
-      init();
-    } catch (IllegalStateException e) {
-      throw e;
-    }
-    
-  }
-  
-  // @TODO init() is currently UNTESTED as of 2009-08-11T13:00-0700.
-
-  //////////////////////////////////////////////////////////////////////
-  /**
-   * Initializes the service.
-   *
-   * @throws  IllegalStateException if one or more of the required preconditions
-   *          for the service is not present, or is not in its required state.
-   */
-  public void init() throws IllegalStateException {
-
+       //////////////////////////////////////////////////////////////////////
+       /**
+       * Constructor (no-argument).
+       */ 
+       public void IDServiceJdbcImpl() throws IllegalStateException {
+       
+               // @TODO Decide when and how to fail at startup, or else to correct
+               // failure conditions automatically, when preconditions are not met.
+               //
+               // Currently, errors at initialization are merely informative and
+               // result in exceptions that can be persistently logged.
+       
+               try {
+                       init();
+               } catch (IllegalStateException e) {
+                       throw e;
+               }
+       
+       }
+       
+       // @TODO init() is currently UNTESTED as of 2009-08-11T13:00-0700.
+       
+    //////////////////////////////////////////////////////////////////////
+   /**
+       * Initializes the service.
+       *
+       * @throws  IllegalStateException if one or more of the required preconditions
+       *          for the service is not present, or is not in its required state.
+       */
+       public void init() throws IllegalStateException {
+       
                logger.debug("> in init");
-
-    try {
-      instantiateJdbcDriver(JDBC_DRIVER_CLASSNAME);
-    } catch (IllegalStateException e) {
-      throw e;
-    }
-    
-    try {
-      boolean hasTable = hasTable(TABLE_NAME);
-      if (! hasTable) {
-        String msg =
-          "Required table " +
-          "\'" + TABLE_NAME + "\'" +
-          " could not be found in the database.";
-                   logger.warn(msg);
-        throw new IllegalStateException(msg);
-      }
-    } catch (IllegalStateException e) {
-      throw e;
-    }
-  
-  }
-
-  //////////////////////////////////////////////////////////////////////
-  /**
-   * Creates a new instance of the specified JDBC driver class.
-   *
-   * @param   jdbcDriverClassname  The name of a JDBC driver class.
-   *
-   * @throws  IllegalStateException if a new instance of the specified
-   *          JDBC driver class cannot be created.
-   */
-  public void instantiateJdbcDriver(String jdbcDriverClassname)
-    throws IllegalStateException {
-
+       
+               try {
+                       instantiateJdbcDriver(JDBC_DRIVER_CLASSNAME);
+               } catch (IllegalStateException e) {
+                       throw e;
+               }
+               
+               try {
+                       boolean hasTable = hasTable(TABLE_NAME);
+                       if (! hasTable) {
+                       String msg =
+                               "Required table " +
+                               "\'" + TABLE_NAME + "\'" +
+                               " could not be found in the database.";
+                               logger.warn(msg);
+                       throw new IllegalStateException(msg);
+                 }
+               } catch (IllegalStateException e) {
+                       throw e;
+               }
+       
+       }
+       
+       //////////////////////////////////////////////////////////////////////
+   /**
+       * Creates a new instance of the specified JDBC driver class.
+       *
+       * @param   jdbcDriverClassname  The name of a JDBC driver class.
+       *
+       * @throws  IllegalStateException if a new instance of the specified
+       *          JDBC driver class cannot be created.
+       */
+       public void instantiateJdbcDriver(String jdbcDriverClassname)
+       throws IllegalStateException {
+       
                logger.debug("> in instantiateJdbcDriver(String)");
-  
-    try {
-      Class.forName(jdbcDriverClassname).newInstance();
-    } catch (ClassNotFoundException e) {
-      throw new IllegalStateException(
-        "Error finding JDBC driver class '" +
-        JDBC_DRIVER_CLASSNAME +
-        "' to set up database connection.");
-    } catch (InstantiationException e) {
-      throw new IllegalStateException(
-        "Error instantiating JDBC driver class '" +
-        JDBC_DRIVER_CLASSNAME +
-        "' to set up database connection.");
-    } catch (IllegalAccessException e) {
-    throw new IllegalStateException(
-      "Error accessing JDBC driver class '" +
-      JDBC_DRIVER_CLASSNAME +
-      "' to set up database connection.");
-    }
-      
-  }
-  
-  //////////////////////////////////////////////////////////////////////
-  /**
-   * Identifies whether a specified table exists in the database.
-   *
-   * @param   tablename  The name of a database table.
-   *
-   * @return  True if the specified table exists in the database;
-   *          false if the specified table does not exist in the database.
-   *
-   * @throws  IllegalStateException if an error occurs while checking for the
-   *          existence of the specified table.
-   */
-  public boolean hasTable(String tablename) throws IllegalStateException {
-
+       
+               try {
+                       Class.forName(jdbcDriverClassname).newInstance();
+               } catch (ClassNotFoundException e) {
+                       throw new IllegalStateException(
+                               "Error finding JDBC driver class '" +
+                               JDBC_DRIVER_CLASSNAME +
+                               "' to set up database connection.");
+               } catch (InstantiationException e) {
+                       throw new IllegalStateException(
+                               "Error instantiating JDBC driver class '" +
+                               JDBC_DRIVER_CLASSNAME +
+                               "' to set up database connection.");
+               } catch (IllegalAccessException e) {
+                       throw new IllegalStateException(
+                               "Error accessing JDBC driver class '" +
+                               JDBC_DRIVER_CLASSNAME +
+                               "' to set up database connection.");
+               }
+         
+       }
+       
+    //////////////////////////////////////////////////////////////////////
+   /**
+       * Identifies whether a specified table exists in the database.
+       *
+       * @param   tablename  The name of a database table.
+       *
+       * @return  True if the specified table exists in the database;
+       *          false if the specified table does not exist in the database.
+       *
+       * @throws  IllegalStateException if an error occurs while checking for the
+       *          existence of the specified table.
+       */
+       public boolean hasTable(String tablename) throws IllegalStateException {
+       
                logger.debug("> in hasTable");
-
+       
                if (tablename == null || tablename.equals("")) {
                        return false;
                }
-      
-    Connection conn = null;
-    try {
-
-      conn = getJdbcConnection();
-    
-      // Retrieve a list of tables in the current database. 
-      final String CATALOG_NAME = null;
-      final String SCHEMA_NAME_PATTERN = null;
-      final String[] TABLE_TYPES = null;
-      ResultSet tablesMatchingTableName =
-        conn.getMetaData().getTables(
-          CATALOG_NAME, SCHEMA_NAME_PATTERN, tablename, TABLE_TYPES);
-
-      // Check whether a table with the specified name is in that list. 
+         
+               Connection conn = null;
+               try {
+               
+                       conn = getJdbcConnection();
+                       
+                       // Retrieve a list of tables in the current database. 
+                       final String CATALOG_NAME = null;
+                       final String SCHEMA_NAME_PATTERN = null;
+                       final String[] TABLE_TYPES = null;
+                       ResultSet tablesMatchingTableName =
+                               conn.getMetaData().getTables(
+                                       CATALOG_NAME, SCHEMA_NAME_PATTERN, tablename, TABLE_TYPES);
+               
+                       // Check whether a table with the specified name is in that list. 
                        boolean moreRows = tablesMatchingTableName.next();
                        if (! moreRows) {
-        return false;
-      } else {
-        return true;
-      }
-
-    } catch (SQLException e) {
-      throw new IllegalStateException(
-        "Error while checking for existence of tablebase table: " + e.getMessage());
-    } finally {
-      try {
-        if (conn != null) {
-          conn.close();
-        }
-      } catch(SQLException e) {
-        // Do nothing here
-      }
-    }
-    
-  }
-        
-  //////////////////////////////////////////////////////////////////////
-  /**
-   * Generates and returns a new ID associated with a specified ID generator.
-   *
-   * This method has an intentional side-effect: it sets the
-   * current ID of that ID generator to the just-generated ID.
-   *
-   * @param  csid  An identifier for an ID generator.
-   *
-   * @return  A new ID associated with the specified ID generator.
-   *
-   * @throws  IllegalArgumentException if the provided csid is null or empty,
-   *          or if the specified ID generator can't be found.
-   *
-   * @throws  IllegalStateException if a storage-related error occurred.
-   */
+                               return false;
+                       } else {
+                               return true;
+                       }
+               
+               } catch (SQLException e) {
+                       throw new IllegalStateException(
+                               "Error while checking for existence of tablebase table: " + e.getMessage());
+               } finally {
+                       try {
+                               if (conn != null) {
+                                       conn.close();
+                               }
+                       } catch(SQLException e) {
+                               // Do nothing here
+                       }
+               }
+       
+       }
+               
+       //////////////////////////////////////////////////////////////////////
+   /**
+       * Generates and returns a new ID associated with a specified ID generator.
+       *
+       * This method has an intentional side-effect: it sets the
+       * current ID of that ID generator to the just-generated ID.
+       *
+       * @param  csid  An identifier for an ID generator.
+       *
+       * @return  A new ID associated with the specified ID generator.
+       *
+       * @throws  IllegalArgumentException if the provided csid is null or empty,
+       *          or if the specified ID generator can't be found.
+       *
+       * @throws  IllegalStateException if a storage-related error occurred.
+       */
        public String newID(String csid) throws
                IllegalArgumentException, IllegalStateException {
                
                logger.debug("> in newID");
-
-    // @TODO Where relevant, implement logic to check for ID availability,
-    // after generating a candidate ID.
-   
-    // @TODO: Add checks for authorization to perform this operation.
-
+               
+               // @TODO Where relevant, implement logic to check for ID availability,
+               // after generating a candidate ID.
+               
+               // @TODO: Add checks for authorization to perform this operation.
+               
                String newId = "";
                String lastId = "";
                
@@ -281,8 +286,8 @@ public class IDServiceJdbcImpl implements IDService {
                        throw new IllegalArgumentException(
                                "Identifier for ID generator must not be null or empty.");
                }
-
-    String serializedGenerator = "";
+               
+               String serializedGenerator = "";
                try {
                        serializedGenerator = getIDGenerator(csid);
                } catch (IllegalArgumentException e ) {
@@ -296,241 +301,245 @@ public class IDServiceJdbcImpl implements IDService {
                        throw new IllegalArgumentException(
                                "ID generator " + "\'" + csid + "\'" + " could not be found.");
                }
-
-    BaseIDGenerator generator;
-    try {
-      generator = IDGeneratorSerializer.deserialize(serializedGenerator);
-    } catch (IllegalArgumentException e) {
-           throw e;
-    }
                
+               BaseIDGenerator generator;
                try {
-
-      // Retrieve the last ID associated with this generator
-      // from persistent storage.
-      lastId = getLastID(csid);
-
-                 // If there was no last generated ID associated with this generator,
-                 // get the current ID generated by the ID generator as the 'new' ID.
-                 if (lastId == null || lastId.equals("")) {
-                   newId = generator.getCurrentID();
-
-      // Otherwise, generate a new ID, potentially based on the last ID.
-      // (This also sets the current ID of the ID generator's state
-      // to this just-generated 'new' ID.)
-                 } else {
-        newId = generator.newID(lastId);
-      }
-      
-                 // Store the 'new' ID as the last-generated ID for this generator.
-                 updateLastID(csid, newId);
-                 
-                 // Store the new state of this ID generator, reflecting that
-                 // one of its parts may possibly have had its value updated as
-                 // a result of the generation of this 'new' ID.
-                 updateIDGenerator(csid, generator);
+                       generator = IDGeneratorSerializer.deserialize(serializedGenerator);
+               } catch (IllegalArgumentException e) {
+                       throw e;
+               }
+               
+               try {
+               
+                       // Retrieve the last ID associated with this generator
+                       // from persistent storage.
+                       lastId = getLastID(csid);
+                       
+                       // If there was no last generated ID associated with this generator,
+                       // get a new ID.
+                       if (lastId == null || lastId.equals("")) {
+                               newId = generator.newID();
+                       
+                       // Otherwise, generate a new ID, potentially based on the last ID.
+                       // (This also sets the current ID of the ID generator's state
+                       // to this just-generated 'new' ID.)
+                       } else {
+                               newId = generator.newID(lastId);
+                       }
+                       
+                       // Store the 'new' ID as the last-generated ID for this generator.
+                       updateLastID(csid, newId);
+                       
+                       // Store the new state of this ID generator, reflecting that
+                       // one of its parts may possibly have had its value updated as
+                       // a result of the generation of this 'new' ID.
+                       updateIDGenerator(csid, generator);
                  
                } catch (IllegalArgumentException e ) {
-                 throw e;
+                   throw e;
                } catch (IllegalStateException e ) {
                        throw e;
                }
                
                return newId;
-
-       }
        
-  //////////////////////////////////////////////////////////////////////
-  /**
-   * Stores the last-generated ID, corresponding to a specified ID generator,
-   * into persistent storage.
-   *
-   * @param  csid     An identifier for an ID generator.
-   *
-   * @param  generator  An ID generator, including the values of its constituent parts.
-   *
-   * @param  lastId  The value of the last-generated ID associated with that ID generator.
-   *
-   * @throws  IllegalArgumentException if the requested ID generator could not be found.
-   *
-   * @throws  IllegalStateException if a storage-related error occurred.
-   */
+       }
+
+       //////////////////////////////////////////////////////////////////////
+   /**
+       * Stores the last-generated ID, corresponding to a specified ID generator,
+       * into persistent storage.
+       *
+       * @param  csid     An identifier for an ID generator.
+       *
+       * @param  generator  An ID generator, including the values of its constituent parts.
+       *
+       * @param  lastId  The value of the last-generated ID associated with that ID generator.
+       *
+       * @throws  IllegalArgumentException if the requested ID generator could not be found.
+       *
+       * @throws  IllegalStateException if a storage-related error occurred.
+       */
        public void updateLastID(String csid, String lastId)
          throws IllegalArgumentException, IllegalStateException {
-    
+       
                logger.debug("> in updateLastID");
-
-    // @TODO Where relevant, implement logic to check for ID availability,
-    // after generating a candidate ID.
-   
-    // @TODO: Add checks for authorization to perform this operation.
-
-    Connection conn = null;
-    try {
-    
-      conn = getJdbcConnection();
-      Statement stmt = conn.createStatement();
+               
+               // @TODO Where relevant, implement logic to check for ID availability,
+               // after generating a candidate ID.
+               
+               // @TODO: Add checks for authorization to perform this operation.
+               
+               Connection conn = null;
+               try {
+               
+                       conn = getJdbcConnection();
+                       Statement stmt = conn.createStatement();
                        
                        int rowsUpdated = stmt.executeUpdate(
-                         "UPDATE id_generators SET last_generated_id='" + lastId + "' WHERE id_generator_csid='" + csid + "'");
+                         "UPDATE id_generators SET last_generated_id='" + lastId +
+                         "' WHERE id_generator_csid='" + csid + "'");
                          
                        if (rowsUpdated != 1) {
-        throw new IllegalStateException(
-          "Error updating last-generated ID in the database for ID generator '" + csid + "'");
-      }
-
+                               throw new IllegalStateException(
+                                       "Error updating last-generated ID in the database for ID generator '" +
+                                       csid + "'");
+                       }
+               
                  logger.debug("> successfully updated last-generated ID: " + lastId);
-
-    } catch (SQLException e) {
-      throw new IllegalStateException("Error updating last-generated ID in the database: " + e.getMessage());
-    } finally {
-      try {
-        if (conn != null) {
-          conn.close();
-        }
-      } catch(SQLException e) {
-        // Do nothing here
-      }
-    }
-
-  }
-
-  //////////////////////////////////////////////////////////////////////
-  /**
-   * Returns the last-generated ID, corresponding to a specified ID generator,
-   * from persistent storage.
-   *
-   * @param  csid  An identifier for an ID generator.
-   *
-   * @return  The last ID generated that corresponds to the requested ID generator.
-   *
-   * @throws  IllegalArgumentException if the requested ID generator could not be found.
-   *
-   * @throws  IllegalStateException if a storage-related error occurred.
-   */
-       public String getLastID(String csid) throws IllegalArgumentException, IllegalStateException {
-
+               
+               } catch (SQLException e) {
+                       throw new IllegalStateException("Error updating last-generated ID in the database: " +
+                       e.getMessage());
+               } finally {
+                       try {
+                               if (conn != null) {
+                                       conn.close();
+                               }
+                       } catch(SQLException e) {
+                               // Do nothing here
+                       }
+               }
+       
+       }
+       
+       //////////////////////////////////////////////////////////////////////
+   /**
+       * Returns the last-generated ID, corresponding to a specified ID generator,
+       * from persistent storage.
+       *
+       * @param  csid  An identifier for an ID generator.
+       *
+       * @return  The last ID generated that corresponds to the requested ID generator.
+       *
+       * @throws  IllegalArgumentException if the requested ID generator could not be found.
+       *
+       * @throws  IllegalStateException if a storage-related error occurred.
+       */
+       public String getLastID(String csid) throws IllegalArgumentException,
+               IllegalStateException {
+       
                logger.debug("> in getLastID");
-
-    // @TODO Where relevant, implement logic to check for ID availability,
-    // after generating a candidate ID.
-   
-    // @TODO: Add checks for authorization to perform this operation.
-
-    String lastId = null;
-    Connection conn = null;
-    try {
-
-      conn = getJdbcConnection();
-      Statement stmt = conn.createStatement();
+               
+               // @TODO Where relevant, implement logic to check for ID availability,
+               // after generating a candidate ID.
+               
+               // @TODO: Add checks for authorization to perform this operation.
+               
+               String lastId = null;
+               Connection conn = null;
+               try {
+               
+                       conn = getJdbcConnection();
+                       Statement stmt = conn.createStatement();
                        
                        ResultSet rs = stmt.executeQuery(
                          "SELECT last_generated_id FROM id_generators WHERE id_generator_csid='" + csid + "'");
                          
                        boolean moreRows = rs.next();
                        if (! moreRows) {
-        throw new IllegalArgumentException(
-          "ID generator " + "\'" + csid + "\'" + " could not be found.");
-      }
-
+                       throw new IllegalArgumentException(
+                               "ID generator " + "\'" + csid + "\'" + " could not be found.");
+                       }
+               
                        lastId = rs.getString(1);
-
-                 logger.debug("> retrieved ID: " + lastId);
-
+                       logger.debug("> retrieved ID: " + lastId);
+               
                        rs.close();
-
-    } catch (SQLException e) {
-      throw new IllegalStateException("Error retrieving last ID from the database: " + e.getMessage());
-    } finally {
-      try {
-        if (conn != null) {
-          conn.close();
-        }
-      } catch(SQLException e) {
-        // Do nothing here
-      }
-    }
-
+               
+               } catch (SQLException e) {
+                       throw new IllegalStateException("Error retrieving last ID from the database: " +
+                       e.getMessage());
+               } finally {
+                       try {
+                               if (conn != null) {
+                                 conn.close();
+                               }
+                       } catch(SQLException e) {
+                               // Do nothing here
+                       }
+               }
+               
                logger.debug("> returning ID: " + lastId);
-    
-    return lastId;
-
-  }
-
-  //////////////////////////////////////////////////////////////////////
-  /**
-   * Adds a new ID generator to persistent storage.
-   *
-   * @param  csid     An identifier for an ID generator.
-   *
-   * @param  generator  An ID generator, reflecting its current state,
-   *                  including the values of its constituent parts.
-   *
-   * @throws  IllegalStateException if a storage-related error occurred.
-   */
+               
+               return lastId;
+       
+       }
+       
+       //////////////////////////////////////////////////////////////////////
+   /**
+       * Adds a new ID generator to persistent storage.
+       *
+       * @param  csid     An identifier for an ID generator.
+       *
+       * @param  generator  An ID generator, reflecting its current state,
+       *                  including the values of its constituent parts.
+       *
+       * @throws  IllegalStateException if a storage-related error occurred.
+       */
        public void addIDGenerator(String csid, BaseIDGenerator generator)
          throws IllegalArgumentException, IllegalStateException {
-    
+       
                logger.debug("> in addIDGenerator(String, BaseIDGenerator)");
-
-    // @TODO: Add checks for authorization to perform this operation.
-
-         if (generator == null) {
-           throw new IllegalArgumentException("New ID generator to add cannot be null.");
-         }
-
-    String serializedGenerator = "";
-    try {
-      serializedGenerator = IDGeneratorSerializer.serialize(generator);
-    } catch (IllegalArgumentException e) {
-           throw e;
-    }
-
+       
+               // @TODO: Add checks for authorization to perform this operation.
+               
+               if (generator == null) {
+                       throw new IllegalArgumentException("New ID generator to add cannot be null.");
+               }
+               
+               String serializedGenerator = "";
+               try {
+                       serializedGenerator = IDGeneratorSerializer.serialize(generator);
+               } catch (IllegalArgumentException e) {
+                       throw e;
+               }
+               
                try {
                        addIDGenerator(csid, serializedGenerator);
-               } catch (IllegalArgumentException e ) {
+               } catch (IllegalArgumentException e) {
                        throw e;
-               } catch (IllegalStateException e ) {
+               } catch (IllegalStateException e) {
                        throw e;
                }
-
-  }
-
-  //////////////////////////////////////////////////////////////////////
-  /**
-   * Adds a new ID generator to persistent storage, from a serialization
-   * of that generator.
-   *
-   * The serialization method recognized by this method has implementation
-   * dependencies.  Currently, this method expects serialization via XStream's
-   * out-of-the-box serializer, without custom configuration.
-   *
-   * @param  csid     An identifier for an ID generator.
-   *
-   * @param  serializedGenerator  A serialized ID generator, reflecting its current state,
-   *                            including the values of its constituent parts.
-   *
-   * @throws  IllegalStateException if a storage-related error occurred.
-   */
+       
+       }
+       
+       //////////////////////////////////////////////////////////////////////
+   /**
+       * Adds a new ID generator to persistent storage, from a serialization
+       * of that generator.
+       *
+       * The serialization method recognized by this method has implementation
+       * dependencies.  Currently, this method expects serialization via XStream's
+       * out-of-the-box serializer, without custom configuration.
+       *
+       * @param  csid     An identifier for an ID generator.
+       *
+       * @param  serializedGenerator  A serialized ID generator, reflecting its current state,
+       *                              including the values of its constituent parts.
+       *
+       * @throws  IllegalStateException if a storage-related error occurred.
+       */
        public void addIDGenerator(String csid, String serializedGenerator)
          throws IllegalArgumentException, IllegalStateException {
-    
+       
                logger.debug("> in addIDGenerator(String, String)");
-
-    // @TODO Add checks for authorization to perform this operation.
-               
+       
+               // @TODO Add checks for authorization to perform this operation.
+                       
                if (serializedGenerator == null || serializedGenerator.equals("")) {
-                 throw new IllegalArgumentException(
-             "Could not understand or parse this representation of an ID generator.");
-    }
-
-    Connection conn = null;
-    try {
-    
-      conn = getJdbcConnection();
-      Statement stmt = conn.createStatement();
-
-      // Test whether this ID generator already exists in the database.
+                       throw new IllegalArgumentException(
+                               "Could not understand or parse this representation of an ID generator.");
+               }
+               
+               Connection conn = null;
+               try {
+               
+                       conn = getJdbcConnection();
+                       Statement stmt = conn.createStatement();
+                       
+                       // Test whether this ID generator already exists in the database.
                        //
                        // @TODO This check should extend further, to other aspects of the generator,
                        // such as its URI, if any, and its structure.
@@ -541,90 +550,92 @@ public class IDServiceJdbcImpl implements IDService {
                        
                        boolean idGeneratorFound = true;
                        if (! moreRows) {
-        idGeneratorFound = false;
-      }
-                       
+                               idGeneratorFound = false;
+                       }
+                               
                        // If this ID generator already exists in the database, throw an Exception.
                        //
                        // @TODO This exception needs to convey the meaning that a conflict has
                        // occurred, so that this status can be reported to the client.
                        if (idGeneratorFound) {
-        throw new IllegalStateException(
-          "Conflict with existing generator when attempting to add new ID generator with ID '" +
-          csid +
-          "' to the database.");
-          
-                       // Otherwise, add this new ID generator, as a new record to the database.
-      } else {
-        final String SQL_STATEMENT_STRING =
-                           "INSERT INTO id_generators " +
-                           "(" +
-                             "id_generator_csid, " +
-                             "id_generator_state, " + 
-                             "last_generated_id" +
-                           ")" +
-                           " VALUES (?, ?, ?)";
-                           
-        PreparedStatement ps = conn.prepareStatement(SQL_STATEMENT_STRING);
-        ps.setString(1, csid);
-        ps.setString(2, serializedGenerator);
-        ps.setNull(3, java.sql.Types.VARCHAR);
-        
-        int rowsUpdated = ps.executeUpdate();
-        if (rowsUpdated != 1) {
-          throw new IllegalStateException(
-            "Error adding new ID generator '" + csid + "'" + " to the database.");
-        }
-        
-       } // end if (idGeneratorFound)
-
-                 logger.debug("> successfully added ID generator: " + csid);
-
-    } catch (SQLException e) {
-      throw new IllegalStateException("Error adding new ID generator to the database: " + e.getMessage());
-    } finally {
-      try {
-        if (conn != null) {
-          conn.close();
-        }
-      } catch(SQLException e) {
-        // Do nothing here
-      }
-    }
-
-  }
-
-  //////////////////////////////////////////////////////////////////////
-  /**
-   * Updates an existing ID generator in persistent storage.
-   *
-   * @param  csid     An identifier for an ID generator.
-   *
-   * @param  generator  An ID generator, reflecting its current state,
-   *                  including the values of its constituent parts.
-   *
-   * @throws  IllegalStateException if a storage-related error occurred.
-   */
+                               throw new IllegalStateException(
+                                       "Conflict with existing generator when attempting to add " +
+                                       "new ID generator with ID '" +
+                                       csid +
+                                       "' to the database.");
+                         
+                       // Otherwise, add this new ID generator, as a new record to the database.
+                       } else {
+                       
+                               final String SQL_STATEMENT_STRING =
+                                       "INSERT INTO id_generators " +
+                                       "(" +
+                                         "id_generator_csid, " +
+                                         "id_generator_state, " + 
+                                         "last_generated_id" +
+                                       ")" +
+                                       " VALUES (?, ?, ?)";
+                                       
+                               PreparedStatement ps = conn.prepareStatement(SQL_STATEMENT_STRING);
+                               ps.setString(1, csid);
+                               ps.setString(2, serializedGenerator);
+                               ps.setNull(3, java.sql.Types.VARCHAR);
+                               
+                               int rowsUpdated = ps.executeUpdate();
+                               if (rowsUpdated != 1) {
+                                       throw new IllegalStateException(
+                                               "Error adding new ID generator '" + csid + "'" + " to the database.");
+                               }
+                       
+                       } // end if (idGeneratorFound)
+                       
+                         logger.debug("> successfully added ID generator: " + csid);
+                       
+                       } catch (SQLException e) {
+                               throw new IllegalStateException("Error adding new ID generator to the database: " +
+                               e.getMessage());
+                       } finally {
+                               try {
+                                       if (conn != null) {
+                                           conn.close();
+                                       }
+                               } catch(SQLException e) {
+                                   // Do nothing here
+                               }
+                       }
+       
+       }
+       
+       //////////////////////////////////////////////////////////////////////
+       /**
+       * Updates an existing ID generator in persistent storage.
+       *
+       * @param  csid     An identifier for an ID generator.
+       *
+       * @param  generator  An ID generator, reflecting its current state,
+       *                  including the values of its constituent parts.
+       *
+       * @throws  IllegalStateException if a storage-related error occurred.
+       */
        public void updateIDGenerator(String csid, BaseIDGenerator generator)
          throws IllegalArgumentException, IllegalStateException {
-    
+       
                logger.debug("> in updateIDGenerator(String, BaseIDGenerator)");
-
-    // @TODO: Add checks for authorization to perform this operation.
-
-         if (generator == null) {
-           throw new IllegalArgumentException(
-             "ID generator provided in update operation cannot be null.");
-         }
-
-    String serializedGenerator = "";
-    try {
-      serializedGenerator = IDGeneratorSerializer.serialize(generator);
-    } catch (IllegalArgumentException e) {
-           throw e;
-    }
-
+       
+               // @TODO: Add checks for authorization to perform this operation.
+       
+               if (generator == null) {
+                       throw new IllegalArgumentException(
+                               "ID generator provided in update operation cannot be null.");
+               }
+               
+               String serializedGenerator = "";
+               try {
+                       serializedGenerator = IDGeneratorSerializer.serialize(generator);
+               } catch (IllegalArgumentException e) {
+                       throw e;
+               }
+       
                try {
                        updateIDGenerator(csid, serializedGenerator);
                } catch (IllegalArgumentException e ) {
@@ -632,262 +643,260 @@ public class IDServiceJdbcImpl implements IDService {
                } catch (IllegalStateException e ) {
                        throw e;
                }
-  }
-  
-  //////////////////////////////////////////////////////////////////////
-  /**
-   * Updates an existing ID generator in persistent storage,
-   * from a serialization of the current state of that generator.
-   *
-   * The serialization method recognized by this method has implementation
-   * dependencies.  Currently, this method expects serialization via XStream's
-   * out-of-the-box serializer, without custom configuration.
-   *
-   * @param  csid     An identifier for an ID generator.
-   *
-   * @param  serializedGenerator  A serialized ID generator, reflecting its current state,
-   *                            including the values of its constituent parts.
-   *
-   * @throws  IllegalStateException if a storage-related error occurred.
-   */
+       
+       }
+       
+       //////////////////////////////////////////////////////////////////////
+       /**
+       * Updates an existing ID generator in persistent storage,
+       * from a serialization of the current state of that generator.
+       *
+       * The serialization method recognized by this method has implementation
+       * dependencies.  Currently, this method expects serialization via XStream's
+       * out-of-the-box serializer, without custom configuration.
+       *
+       * @param  csid     An identifier for an ID generator.
+       *
+       * @param  serializedGenerator  A serialized ID generator, reflecting its current state,
+       *                            including the values of its constituent parts.
+       *
+       * @throws  IllegalStateException if a storage-related error occurred.
+       */
        public void updateIDGenerator(String csid, String serializedGenerator)
          throws IllegalArgumentException, IllegalStateException {
-    
+       
                logger.debug("> in updateIDGenerator(String, String)");
-
-    // @TODO: Add checks for authorization to perform this operation.
+       
+               // @TODO: Add checks for authorization to perform this operation.
                
                if (serializedGenerator == null || serializedGenerator.equals("")) {
                  throw new IllegalArgumentException(
-             "Could not understand or parse this representation of an ID generator.");
-    }
-
-    Connection conn = null;
-    try {
-    
-      conn = getJdbcConnection();
-      Statement stmt = conn.createStatement();
-
-      // Test whether this ID generator already exists in the database.
+                       "Could not understand or parse this representation of an ID generator.");
+               }
+       
+               Connection conn = null;
+               try {
+               
+                       conn = getJdbcConnection();
+                       Statement stmt = conn.createStatement();
+               
+                       // Test whether this ID generator already exists in the database.
                        ResultSet rs = stmt.executeQuery(
-                         "SELECT id_generator_csid FROM id_generators WHERE id_generator_csid='" + csid + "'");
-                         
+                               "SELECT id_generator_csid FROM id_generators WHERE id_generator_csid='" +
+                               csid + "'");
+                                 
                        boolean moreRows = rs.next();
-                       
+                               
                        boolean idGeneratorFound = true;
                        if (! moreRows) {
-        idGeneratorFound = false;
-      }
-                       
+                               idGeneratorFound = false;
+                       }
+                               
                        // If this ID generator already exists in the database, update its record.
                        if (idGeneratorFound) {
-
-                         final String SQL_STATEMENT_STRING =
-                           "UPDATE id_generators SET " + 
-                              "id_generator_state = ?, " + 
-                              "last_generated_id = ? " + 
-                           "WHERE id_generator_csid = ?";
-                           
-                         BaseIDGenerator generator;
-        try {
-          generator = IDGeneratorSerializer.deserialize(serializedGenerator);
-        } catch (IllegalArgumentException e) {
-          throw e;
-        }
-                   String lastId = generator.getCurrentID();
-                       
-        PreparedStatement ps = conn.prepareStatement(SQL_STATEMENT_STRING);
-        ps.setString(1, serializedGenerator);
-        ps.setString(2, lastId);
-        ps.setString(3, csid);
-                
-        int rowsUpdated = ps.executeUpdate();
-        if (rowsUpdated != 1) {
-          throw new IllegalStateException(
-            "Error updating ID generator '" + csid + "'" + " in the database.");
-        }
-        
+       
+                       final String SQL_STATEMENT_STRING =
+                                 "UPDATE id_generators SET " + 
+                                  "id_generator_state = ?, " + 
+                                  "last_generated_id = ? " + 
+                                 "WHERE id_generator_csid = ?";
+                                 
+                               BaseIDGenerator generator;
+                               try {
+                                       generator = IDGeneratorSerializer.deserialize(serializedGenerator);
+                               } catch (IllegalArgumentException e) {
+                                       throw e;
+                               }
+                               String lastId = generator.getCurrentID();
+                                       
+                               PreparedStatement ps = conn.prepareStatement(SQL_STATEMENT_STRING);
+                               ps.setString(1, serializedGenerator);
+                               ps.setString(2, lastId);
+                               ps.setString(3, csid);
+                                               
+                               int rowsUpdated = ps.executeUpdate();
+                               if (rowsUpdated != 1) {
+                                       throw new IllegalStateException(
+                                               "Error updating ID generator '" + csid + "'" + " in the database.");
+                               }
+                               
                        // Otherwise, throw an exception, which indicates that the requested
                        // ID generator was not found.
-      } else {
-        throw new IllegalArgumentException(
-          "Error updating ID generator '" + csid + "': generator could not be found in the database.");
-       
-       } // end if (idGeneratorFound)
-
-                 logger.debug("> successfully updated ID Generator: " + csid);
-
-    } catch (SQLException e) {
-      throw new IllegalStateException("Error updating ID generator in the database: " + e.getMessage());
-    } finally {
-      try {
-        if (conn != null) {
-          conn.close();
-        }
-      } catch(SQLException e) {
-        // Do nothing here
-      }
-    }
-
-  }
-
-  //////////////////////////////////////////////////////////////////////
-  /**
-   * Deletes an existing ID generator from persistent storage.
-   *
-   * @param  csid     An identifier for an ID generator.
-   *
-   * @throws  IllegalStateException if a storage-related error occurred.
-   */
+                       } else {
+                               throw new IllegalArgumentException(
+                                 "Error updating ID generator '" + csid +
+                                 "': generator could not be found in the database.");
+                       } // end if (idGeneratorFound)
+               
+                       logger.debug("> successfully updated ID Generator: " + csid);
+               
+               } catch (SQLException e) {
+                       throw new IllegalStateException(
+                               "Error updating ID generator in the database: " + e.getMessage());
+               } finally {
+                       try {
+                               if (conn != null) {
+                                       conn.close();
+                               }
+                       } catch(SQLException e) {
+                               // Do nothing here
+                       }
+               }
+       
+       }
+       
+       //////////////////////////////////////////////////////////////////////
+       /**
+       * Deletes an existing ID generator from persistent storage.
+       *
+       * @param  csid     An identifier for an ID generator.
+       *
+       * @throws  IllegalStateException if a storage-related error occurred.
+       */
        public void deleteIDGenerator(String csid)
          throws IllegalArgumentException, IllegalStateException {
-    
+       
                logger.debug("> in deleteIDGenerator");
-
-    // @TODO: Add checks for authorization to perform this operation.
-    
-    Connection conn = null;
-    try {
-    
-      conn = getJdbcConnection();
-      Statement stmt = conn.createStatement();
-
-      // Test whether this ID generator already exists in the database.
+               
+               // @TODO: Add checks for authorization to perform this operation.
+               
+               Connection conn = null;
+               try {
+               
+                       conn = getJdbcConnection();
+                       Statement stmt = conn.createStatement();
+                       
+                       // Test whether this ID generator already exists in the database.
                        ResultSet rs = stmt.executeQuery(
-                         "SELECT id_generator_csid FROM id_generators WHERE id_generator_csid='" + csid + "'");
-                         
+                         "SELECT id_generator_csid FROM id_generators WHERE id_generator_csid='" +
+                         csid + "'");
                        boolean moreRows = rs.next();
                        
                        boolean idGeneratorFound = true;
                        if (! moreRows) {
-        idGeneratorFound = false;
-      }
+                               idGeneratorFound = false;
+                       }
                        
                        // If this ID generator already exists in the database, update its record.
                        if (idGeneratorFound) {
-
-                         final String SQL_STATEMENT_STRING =
-                           "DELETE FROM id_generators WHERE id_generator_csid = ?";
-                           
-        PreparedStatement ps = conn.prepareStatement(SQL_STATEMENT_STRING);
-        ps.setString(1, csid);
-                
-        int rowsUpdated = ps.executeUpdate();
-        if (rowsUpdated != 1) {
-          throw new IllegalStateException(
-            "Error deleting ID generator '" + csid + "'" + " in the database.");
-        }
-        
+               
+                          final String SQL_STATEMENT_STRING =
+                              "DELETE FROM id_generators WHERE id_generator_csid = ?";
+                               
+                               PreparedStatement ps = conn.prepareStatement(SQL_STATEMENT_STRING);
+                               ps.setString(1, csid);
+                                               
+                               int rowsUpdated = ps.executeUpdate();
+                               if (rowsUpdated != 1) {
+                               throw new IllegalStateException(
+                                       "Error deleting ID generator '" + csid + "'" + " in the database.");
+                               }
+               
                        // Otherwise, throw an exception, which indicates that the requested
                        // ID generator was not found.
-      } else {
-        throw new IllegalArgumentException(
-          "Error deleting ID generator '" + csid + "': generator could not be found in the database.");
-       
-       } // end if (idGeneratorFound)
-
-                 logger.debug("> successfully deleted ID generator: " + csid);
-
-    } catch (SQLException e) {
-      throw new IllegalStateException("Error deleting ID generator in database: " + e.getMessage());
-    } finally {
-      try {
-        if (conn != null) {
-          conn.close();
-        }
-      } catch(SQLException e) {
-        // Do nothing here
-      }
-    }
-
-  }
-
-  //////////////////////////////////////////////////////////////////////
-  /**
-   * Opens a connection to the database and returns a JDBC Connection object.
-   *
-   * @return  A JDBC database Connection object.
-   *
-   * @throws  SQLException if a storage-related error occurred.
-   */
-  public Connection getJdbcConnection() throws SQLException {
-  
-    logger.debug("> in getJdbcConnection");
-
-    Connection conn = null;
-    try {
-    
-      conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USERNAME, DATABASE_PASSWORD);
-      
-    } catch (SQLException e) {
-      throw e;
-    }
-    
-    return conn;
-    
-  }
-
-  //////////////////////////////////////////////////////////////////////
-  /**
-   * Returns a requested ID generator from persistent storage.
-   *
-   * @param  csid  An identifier for an ID generator.
-   *
-   * @return  A serialized representation of the requested ID generator.
-   *
-   * @throws  IllegalArgumentException if the requested ID generator could not be found.
-   *
-   * @throws  IllegalStateException if a storage-related error occurred.
-   */
+                       } else {
+                               throw new IllegalArgumentException(
+                                 "Error deleting ID generator '" + csid +
+                                 "': generator could not be found in the database.");
+                       } // end if (idGeneratorFound)
+               
+                       logger.debug("> successfully deleted ID generator: " + csid);
+               
+               } catch (SQLException e) {
+                       throw new IllegalStateException(
+                               "Error deleting ID generator in database: " + e.getMessage());
+               } finally {
+                       try {
+                               if (conn != null) {
+                                       conn.close();
+                               }
+                       } catch(SQLException e) {
+                               // Do nothing here
+                       }
+               }
+       
+       }
+       
+       //////////////////////////////////////////////////////////////////////
+       /**
+       * Opens a connection to the database and returns a JDBC Connection object.
+       *
+       * @return  A JDBC database Connection object.
+       *
+       * @throws  SQLException if a storage-related error occurred.
+       */
+       public Connection getJdbcConnection() throws SQLException {
+       
+               logger.debug("> in getJdbcConnection");
+               
+               Connection conn = null;
+               try {
+                       conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USERNAME, DATABASE_PASSWORD);
+               } catch (SQLException e) {
+                       throw e;
+               }
+               return conn;
+       
+       }
+       
+       //////////////////////////////////////////////////////////////////////
+       /**
+       * Returns a requested ID generator from persistent storage.
+       *
+       * @param  csid  An identifier for an ID generator.
+       *
+       * @return  A serialized representation of the requested ID generator.
+       *
+       * @throws  IllegalArgumentException if the requested ID generator could not be found.
+       *
+       * @throws  IllegalStateException if a storage-related error occurred.
+       */
        public String getIDGenerator (String csid) throws IllegalArgumentException, IllegalStateException {
-
+       
                logger.debug("> in getIDGenerator");
-
-    String serializedGenerator = null;
-    
-    Connection conn = null;
-    try {
-    
-      conn = getJdbcConnection();
-      Statement stmt = conn.createStatement();
+               
+               String serializedGenerator = null;
+               
+               Connection conn = null;
+               try {
+               
+                       conn = getJdbcConnection();
+                       Statement stmt = conn.createStatement();
                        
                        ResultSet rs = stmt.executeQuery(
                          "SELECT id_generator_state FROM id_generators WHERE id_generator_csid='" + csid + "'");
                          
                        boolean moreRows = rs.next();
                        if (! moreRows) {
-        throw new IllegalArgumentException(
-          "ID generator with ID " +
-          "\'" + csid + "\'" +
-          " could not be found.");
-      }
-
+                               throw new IllegalArgumentException(
+                                   "ID generator with ID " +
+                                   "\'" + csid + "\'" +
+                                   " could not be found.");
+                       }
+               
                        serializedGenerator = rs.getString(1);
                        
                        rs.close();
-
-    } catch (SQLException e) {
-      throw new IllegalStateException(
-        "Error retrieving ID generator " +
-        "\'" + csid + "\'" +
-        " from database: " + e.getMessage());
-    } finally {
-      try {
-        if (conn != null) {
-          conn.close();
-        }
-      } catch(SQLException e) {
-        // Do nothing here
-      }
-    }
-    
-         logger.debug("> retrieved BaseIDGenerator: " + serializedGenerator);
-
-    return serializedGenerator;
-
-  }
-  
-}
+               
+               } catch (SQLException e) {
+                       throw new IllegalStateException(
+                               "Error retrieving ID generator " +
+                               "\'" + csid + "\'" +
+                               " from database: " + e.getMessage());
+               } finally {
+                       try {
+                               if (conn != null) {
+                                       conn.close();
+                               }
+                       } catch(SQLException e) {
+                               // Do nothing here
+                       }
+               }
+               
+               logger.debug("> retrieved BaseIDGenerator: " + serializedGenerator);
+               
+               return serializedGenerator;
+       
+               }
+         
+       }
index 6dc5ae05aa5da62328e96db17083feaa36ba84d8..8580f0de5d1a8104dd5b3833f7b1225a85439cbb 100644 (file)
  * You may obtain a copy of the ECL 2.0 License at
  * https://source.collectionspace.org/collection-space/LICENSE.txt
  *
- * $LastChangedBy$
- * $LastChangedRevision$
- * $LastChangedDate$
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 // @TODO: Add Javadoc comments
@@ -37,14 +39,15 @@ import java.util.regex.Pattern;
  * $LastChangedRevision$
  * $LastChangedDate$
  */
-public class NumericIDGeneratorPart implements IDGeneratorPart {
+public class NumericIDGeneratorPart implements SequenceIDGeneratorPart {
   
     final static private int DEFAULT_MAX_LENGTH = 6;
     private int maxLength = DEFAULT_MAX_LENGTH;
     
     final static private int DEFAULT_INITIAL_VALUE = 1;
+    final static private long CURRENT_VALUE_NOT_SET = -1;
     private long initialValue = DEFAULT_INITIAL_VALUE;
-    private long currentValue = DEFAULT_INITIAL_VALUE;
+    private long currentValue = CURRENT_VALUE_NOT_SET;
 
     // Constructor using defaults for initial value and maximum length.
     public NumericIDGeneratorPart() throws IllegalArgumentException {
@@ -73,7 +76,7 @@ public class NumericIDGeneratorPart implements IDGeneratorPart {
                 throw new IllegalArgumentException(
                     "Initial ID value should be zero (0) or greater");
             }
-            this.currentValue = l;
+            // this.currentValue = l;
             this.initialValue = l;
         } catch (NullPointerException e) {
             throw new IllegalArgumentException(
@@ -102,7 +105,11 @@ public class NumericIDGeneratorPart implements IDGeneratorPart {
     }
 
     public String getCurrentID() {
-        return Long.toString(this.currentValue);
+        if (this.currentValue == CURRENT_VALUE_NOT_SET) {
+               return Long.toString(this.initialValue);
+        } else {
+            return Long.toString(this.currentValue);
+        }
     }
 
     // Sets the current value of the ID.
@@ -123,7 +130,6 @@ public class NumericIDGeneratorPart implements IDGeneratorPart {
                     "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");
@@ -137,13 +143,13 @@ public class NumericIDGeneratorPart implements IDGeneratorPart {
         this.maxLength = DEFAULT_MAX_LENGTH;
     }
     
-    public void resetID() {
-        this.currentValue = this.initialValue;
-    }
-
     // Returns the next ID in the sequence, and sets the current value to that ID.
     public String nextID() throws IllegalStateException {
-        this.currentValue++;
+        if (this.currentValue == CURRENT_VALUE_NOT_SET) {
+                       this.currentValue = this.initialValue;
+        } else {
+               this.currentValue++;
+        }
         String nextID = Long.toString(this.currentValue);
         if (nextID.length() > this.maxLength) {
             throw new IllegalStateException(
@@ -151,15 +157,26 @@ public class NumericIDGeneratorPart implements IDGeneratorPart {
         }
         return nextID;
     }
+    /**
+    * Returns a new identifier.
+    */
+    @Override
+    public String newID() {
+        return nextID();
+    }
 
-    public boolean isValidID(String value) {
-
-        if ( value == null || value == "") {
-            return false;
-        }
+    @Override
+    public boolean isValidID(String id) {
+    
+        if (id == null) return false;
+        // @TODO May potentially throw at least one pattern-related exception.
+        // We'll need to catch and handle this here, as well as in all
+        // derived classes and test cases that invoke validation.
 
         Pattern pattern = Pattern.compile(getRegex());
-        Matcher matcher = pattern.matcher(value);
+        Matcher matcher = pattern.matcher(id);
         if (matcher.matches()) {
             return true;
         } else {
@@ -168,6 +185,7 @@ public class NumericIDGeneratorPart implements IDGeneratorPart {
         
     }
 
+    @Override
     public String getRegex() {
         String regex =
             "(" + "\\d" + "{1," + Integer.toString(this.maxLength) + "}" + ")";
index 19254a351d50e76ca5a5646a2636d77155af6b9c..435162d0a7c2563227356cfcd2d8268745900b2d 100644 (file)
  *
  * You may obtain a copy of the ECL 2.0 License at
  * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 // @TODO: Add Javadoc comments
@@ -33,7 +39,8 @@ import java.util.regex.PatternSyntaxException;
  * $LastChangedRevision$
  * $LastChangedDate$
  */
-public class StringIDGeneratorPart implements IDGeneratorPart {
+public class StringIDGeneratorPart implements IDGeneratorPart, 
+    StoredValueIDGeneratorPart {
     
     private String initialValue = null;
     private String currentValue = null;
@@ -51,10 +58,12 @@ public class StringIDGeneratorPart implements IDGeneratorPart {
 
     }
 
+    @Override
     public String getInitialID() {
         return this.initialValue;
     }
 
+    @Override
     public String getCurrentID() {
         return this.currentValue;
     }
@@ -66,23 +75,23 @@ public class StringIDGeneratorPart implements IDGeneratorPart {
         }
         this.currentValue = value;
     }
-    
-    public void resetID() {
-        // Do nothing
-    }
 
-    public String nextID() {
+    @Override
+    public String newID() {
         return this.currentValue;
-  }
-
-    public boolean isValidID(String value) {
+    }
 
-        if (value == null || value.equals("")) {
-            return false;
-        }
+    @Override
+    public boolean isValidID(String id) {
+    
+        if (id == null) return false;
+        // @TODO May potentially throw at least one pattern-related exception.
+        // We'll need to catch and handle this here, as well as in all
+        // derived classes and test cases that invoke validation.
 
         Pattern pattern = Pattern.compile(getRegex());
-        Matcher matcher = pattern.matcher(value);
+        Matcher matcher = pattern.matcher(id);
         if (matcher.matches()) {
             return true;
         } else {
@@ -91,6 +100,7 @@ public class StringIDGeneratorPart implements IDGeneratorPart {
         
     }
 
+    @Override
     public String getRegex() {
 
         String initial = this.initialValue;
diff --git a/services/id/service/src/main/java/org/collectionspace/services/id/UUIDGeneratorPart.java b/services/id/service/src/main/java/org/collectionspace/services/id/UUIDGeneratorPart.java
new file mode 100644 (file)
index 0000000..eea702d
--- /dev/null
@@ -0,0 +1,115 @@
+/**   
+ * This document is a part of the source code and related artifacts
+ * for CollectionSpace, an open source collections management system
+ * for museums and related institutions:
+ *
+ * http://www.collectionspace.org
+ * http://wiki.collectionspace.org
+ *
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.collectionspace.services.id;
+
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ * UUIDGeneratorPart
+ *
+ * Generates universally unique identifiers (UUIDs) in the Version 4 format
+ * (random or pseudorandom numbers), described at
+ * http://en.wikipedia.org/wiki/Universally_Unique_Identifier#Version_4_.28random.29
+ *
+ * $LastChangedRevision: 625 $
+ * $LastChangedDate$
+ */
+public class UUIDGeneratorPart implements IDGeneratorPart {
+    
+    String currentValue = "";
+    
+    final static String REGEX_PATTERN =
+        "(" +
+        "[a-z0-9\\-]{8}" +
+        "\\-" +
+        "[a-z0-9\\-]{4}" +
+        "\\-" +
+        "4" +
+        "[a-z0-9\\-]{3}" +
+        "\\-" +
+        "[89ab]" +
+        "[a-z0-9\\-]{3}" +
+        "\\-" +
+        "[a-z0-9\\-]{12}" +
+        ")";
+        
+    final static int UUID_LENGTH = 36;
+    
+    /**
+     * Constructor (no-argument).
+     */
+    public UUIDGeneratorPart() {
+    }
+
+    public void setCurrentID(String id) {
+        if (id == null || id.equals("") || (! isValidID(id) )) {
+            this.currentValue = newID();
+        } else {
+            this.currentValue = id;
+        }  
+    }
+
+    public String getCurrentID() {
+        if (this.currentValue == null || this.currentValue.equals("")) {
+            return newID();
+        } else {
+            return this.currentValue;
+        }
+    }
+    
+    @Override
+    public String newID() {
+        String id = UUID.randomUUID().toString();
+        this.currentValue = id;
+        return id;
+    }
+
+    @Override
+    public boolean isValidID(String id) {
+    
+        if (id == null) return false;
+        // @TODO May potentially throw at least one pattern-related exception.
+        // We'll need to catch and handle this here, as well as in all
+        // derived classes and test cases that invoke validation.
+
+        Pattern pattern = Pattern.compile(getRegex());
+        Matcher matcher = pattern.matcher(id);
+        if (matcher.matches()) {
+            return true;
+        } else {
+            return false;
+        }
+        
+    }
+    
+    @Override
+    public String getRegex() {
+        return REGEX_PATTERN;
+    }
+    
+}
index 286fa843edc063cdc48971d167cf54d7720619e7..2b0364e11f87d17bb742095f6ff7070dbefd8e67 100644 (file)
  *
  * You may obtain a copy of the ECL 2.0 License at
  * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 // @TODO: Add Javadoc comments
@@ -56,6 +62,10 @@ public class YearIDGeneratorPart implements IDGeneratorPart {
        private String initialValue = null;
        private String currentValue = null;
        
+    // NOTE: Currently hard-coded to accept only a range of
+    // four-digit Gregorian Calendar year dates.
+    final static String REGEX_PATTERN = "(\\d{4})";
+
        public YearIDGeneratorPart() throws IllegalArgumentException {
 
                String currentYear = getCurrentYear();
@@ -117,34 +127,40 @@ public class YearIDGeneratorPart implements IDGeneratorPart {
        public String nextID() {
                return this.currentValue;
     }
+    
+    @Override
+    public String newID() {
+        return getCurrentYear();
+    }
+
+    @Override
+    public boolean isValidID(String id) {
+    
+        if (id == null) return false;
+        // @TODO May potentially throw at least one pattern-related exception.
+        // We'll need to catch and handle this here, as well as in all
+        // derived classes and test cases that invoke validation.
+
+        Pattern pattern = Pattern.compile(getRegex());
+        Matcher matcher = pattern.matcher(id);
+        if (matcher.matches()) {
+            return true;
+        } else {
+            return false;
+        }
+        
+    }
+
+    @Override
+       public String getRegex() {
+               return REGEX_PATTERN;
+       }
 
        public static String getCurrentYear() {
                Calendar cal = GregorianCalendar.getInstance();
         int y = cal.get(Calendar.YEAR);
                return Integer.toString(y);
        }       
-
-       public boolean isValidID(String value) throws IllegalArgumentException {
-
-               if (value == null || value.equals("")) {
-                       return false;
-               }
-
-               Pattern pattern = Pattern.compile(getRegex());
-               Matcher matcher = pattern.matcher(value);
-               if (matcher.matches()) {
-                       return true;
-               } else {
-                       return false;
-               }
-               
-       }
-
-       public String getRegex() {
-               // NOTE: Currently hard-coded to accept only a range of
-               // four-digit Gregorian Calendar year dates.
-               String regex = "(\\d{4})";
-               return regex;
-       }
        
 }
index 751202acc7eb9be1e028862cc60e81efc2d03fbd..85e601397b6332349206805d37820aaf155fac6f 100644 (file)
  *
  * You may obtain a copy of the ECL 2.0 License at
  * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 package org.collectionspace.services.id;
@@ -30,94 +36,84 @@ import junit.framework.TestCase;
  */
 public class AlphabeticIDGeneratorPartTest extends TestCase {
 
-       IDGeneratorPart part;
+       SequenceIDGeneratorPart part;
        
        public void testNextIDLowercase() {
 
                part = new AlphabeticIDGeneratorPart("a");
-               assertEquals("b", part.nextID());
-               assertEquals("c", part.nextID());
+               assertEquals("a", part.newID());
+               assertEquals("b", part.newID());
+               assertEquals("c", part.newID());
 
                part = new AlphabeticIDGeneratorPart("x");
-               assertEquals("y", part.nextID());
-               assertEquals("z", part.nextID());
+               assertEquals("x", part.newID());
+               assertEquals("y", part.newID());
+               assertEquals("z", part.newID());
 
 }
 
-       public void testnextIDLowercase2Chars() {
+       public void testnewIDLowercase2Chars() {
 
                part = new AlphabeticIDGeneratorPart("aa");
-               assertEquals("ab", part.nextID());
-               assertEquals("ac", part.nextID());
+               assertEquals("aa", part.newID());
+               assertEquals("ab", part.newID());
+               assertEquals("ac", part.newID());
 
                part = new AlphabeticIDGeneratorPart("zx");
-               assertEquals("zy", part.nextID());
-               assertEquals("zz", part.nextID());
+               assertEquals("zx", part.newID());
+               assertEquals("zy", part.newID());
+               assertEquals("zz", part.newID());
 
        }
 
-       public void testnextIDLowercase2CharsRolloverFirst() {
+       public void testnewIDLowercase2CharsRolloverFirst() {
 
                part = new AlphabeticIDGeneratorPart("ay");
-               assertEquals("az", part.nextID());
-               assertEquals("ba", part.nextID());
-               assertEquals("bb", part.nextID());
+               assertEquals("ay", part.newID());
+               assertEquals("az", part.newID());
+               assertEquals("ba", part.newID());
+               assertEquals("bb", part.newID());
 
-  }
+    }
        
-       public void testnextIDUppercase() {
+       public void testnewIDUppercase() {
                
                part = new AlphabeticIDGeneratorPart("A", "Z", "A");
-               assertEquals("B", part.nextID());
-               assertEquals("C", part.nextID());
+               assertEquals("A", part.newID());
+               assertEquals("B", part.newID());
+               assertEquals("C", part.newID());
 
                part = new AlphabeticIDGeneratorPart("A", "Z", "X");
-               assertEquals("Y", part.nextID());
-               assertEquals("Z", part.nextID());
+               assertEquals("X", part.newID());
+               assertEquals("Y", part.newID());
+               assertEquals("Z", part.newID());
 
-}
+    }
 
-       public void testnextIDUppercase2Chars() {
+       public void testnewIDUppercase2Chars() {
 
                part = new AlphabeticIDGeneratorPart("A", "Z", "AA");
-               assertEquals("AB", part.nextID());
-               assertEquals("AC", part.nextID());
+               assertEquals("AA", part.newID());
+               assertEquals("AB", part.newID());
+               assertEquals("AC", part.newID());
 
                part = new AlphabeticIDGeneratorPart("A", "Z", "ZX");
-               assertEquals("ZY", part.nextID());
-               assertEquals("ZZ", part.nextID());
+               assertEquals("ZX", part.newID());
+               assertEquals("ZY", part.newID());
+               assertEquals("ZZ", part.newID());
                        
        }
 
-       public void testnextIDUppercase2CharsRolloverFirst() {
+       public void testnewIDUppercase2CharsRolloverFirst() {
 
                part = new AlphabeticIDGeneratorPart("A", "Z", "AY");
-               assertEquals("AZ", part.nextID());
-               assertEquals("BA", part.nextID());
-               assertEquals("BB", part.nextID());
+               assertEquals("AY", part.newID());
+               assertEquals("AZ", part.newID());
+               assertEquals("BA", part.newID());
+               assertEquals("BB", part.newID());
 
   }
-  
-       public void testresetIDLowercase() {
-               
-               part = new AlphabeticIDGeneratorPart("zx");
-               assertEquals("zy", part.nextID());
-               assertEquals("zz", part.nextID());
-               part.resetID();
-               assertEquals("zx", part.getCurrentID());
-       
-       }
 
-       public void testresetIDUppercase() {
-               
-               part = new AlphabeticIDGeneratorPart("A", "Z", "RA");
-               assertEquals("RB", part.nextID());
-               assertEquals("RC", part.nextID());
-               part.resetID();
-               assertEquals("RB", part.nextID());
-       
-       }
-       
        public void testInitialLowercase() {
                
                part = new AlphabeticIDGeneratorPart("aaa");
@@ -136,10 +132,11 @@ public class AlphabeticIDGeneratorPartTest extends TestCase {
                
                part = new AlphabeticIDGeneratorPart("aaa");
                assertEquals("aaa", part.getCurrentID());
-               assertEquals("aab", part.nextID());
-               assertEquals("aac", part.nextID());
+               assertEquals("aaa", part.newID());
+               assertEquals("aab", part.newID());
+               assertEquals("aac", part.newID());
                assertEquals("aac", part.getCurrentID());
-               assertEquals("aad", part.nextID());
+               assertEquals("aad", part.newID());
                
        }
 
@@ -147,28 +144,31 @@ public class AlphabeticIDGeneratorPartTest extends TestCase {
                
                part = new AlphabeticIDGeneratorPart("A", "Z", "A");
                assertEquals("A", part.getCurrentID());
-               assertEquals("B", part.nextID());
-               assertEquals("C", part.nextID());
+               assertEquals("A", part.newID());
+               assertEquals("B", part.newID());
+               assertEquals("C", part.newID());
                assertEquals("C", part.getCurrentID());
-               assertEquals("D", part.nextID());
+               assertEquals("D", part.newID());
                
        }       
-       
+
        public void testOverflowLowercase() {
        
-    part = new AlphabeticIDGeneratorPart("zx");
-    assertEquals("zy", part.nextID());
-    assertEquals("zz", part.nextID());
-    assertEquals("aaa", part.nextID());
+        part = new AlphabeticIDGeneratorPart("zx");
+        assertEquals("zx", part.newID());
+        assertEquals("zy", part.newID());
+        assertEquals("zz", part.newID());
+        assertEquals("aaa", part.newID());
                
        }
 
        public void testOverflowUppercase() {
        
-    part = new AlphabeticIDGeneratorPart("A", "Z", "X");
-    assertEquals("Y", part.nextID());
-    assertEquals("Z", part.nextID());
-    assertEquals("AA", part.nextID());
+        part = new AlphabeticIDGeneratorPart("A", "Z", "X");
+        assertEquals("X", part.newID());
+        assertEquals("Y", part.newID());
+        assertEquals("Z", part.newID());
+        assertEquals("AA", part.newID());
                
        }
 
index 50a484a5c139a27588cf8fefe9639f253b470798..4f3b9f0d7c6d7050109412897bb31326f40c610e 100644 (file)
@@ -1,4 +1,4 @@
-/*     
+/*    
  * This document is a part of the source code and related artifacts
  * for CollectionSpace, an open source collections management system
  * for museums and related institutions:
  *
  * You may obtain a copy of the ECL 2.0 License at
  * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 package org.collectionspace.services.id;
 
-import static org.junit.Assert.fail;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
 import java.util.Vector;
+
 import junit.framework.TestCase;
+import static org.junit.Assert.fail;
+
 
-/**    
+/**    
  * IDGeneratorTest, Test class for IDGenerator.
  *
  * $LastChangedRevision$
@@ -29,243 +39,405 @@ import junit.framework.TestCase;
  */
 public class IDGeneratorTest extends TestCase {
 
-       BaseIDGenerator generator;
-       IDGeneratorPart part;
-       
-       final static String DEFAULT_CSID = "1";
-
-       // 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 YearIDGeneratorPart("2009"));
-               parts.add(new StringIDGeneratorPart("."));
-               parts.add(new NumericIDGeneratorPart("1"));
-               parts.add(new StringIDGeneratorPart("-"));
-               parts.add(new AlphabeticIDGeneratorPart("a"));
-               generator = new BaseIDGenerator(DEFAULT_CSID, parts);
-               assertEquals("2009.1-a", generator.getCurrentID());
-                       
-       }
-
-       public void testCurrentIDViaAdd() {
-
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("1"));
-               generator.add(new StringIDGeneratorPart("-"));
-               generator.add(new AlphabeticIDGeneratorPart("a"));      
-               assertEquals("2009.1-a", generator.getCurrentID());
-
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("0"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("0"));
-               assertEquals("2009.0.0", generator.getCurrentID());
-                       
-       }
-
-       public void testCurrentIDWithPartialSuppliedID() {
-                       
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new StringIDGeneratorPart("E"));
-               generator.add(new NumericIDGeneratorPart("1"));
-               assertEquals("E1", generator.getCurrentID("E"));
-               assertEquals("E2", generator.newID());
-
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart());
-               generator.add(new StringIDGeneratorPart("."));
-               assertEquals("2009.", generator.getCurrentID("2009"));
-               assertEquals("2009.", generator.newID());
-               assertEquals("2010.", generator.getCurrentID("2010"));
-               assertEquals("2010.", generator.newID());
-
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart());
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("1"));
-               assertEquals("2009.1", generator.getCurrentID("2009."));
-               assertEquals("2009.2", generator.newID());
-
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart());
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("55"));
-               assertEquals("2010.55", generator.getCurrentID("2010."));
-               assertEquals("2010.56", generator.newID());
-
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart());
-               assertEquals("2009.1", generator.getCurrentID("2009."));
-               assertEquals("2009.2", generator.newID());
-               // Test a repeat of the last two operations.
-               assertEquals("2009.1", generator.getCurrentID("2009."));
-               assertEquals("2009.2", generator.newID());
-
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("1"));
-               generator.add(new StringIDGeneratorPart("-"));
-               generator.add(new AlphabeticIDGeneratorPart("a"));
-               assertEquals("2009.1-a", generator.getCurrentID("2009.1-"));
-               assertEquals("2009.1-b", generator.newID());
-               assertEquals("2009.3-a", generator.getCurrentID("2009.3-"));
-
-       }
-
-       public void testCurrentIDWithFullSuppliedID() {
-       
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("55"));
-               assertEquals("2009.55", generator.getCurrentID("2009.55"));
-               assertEquals("2009.56", generator.newID());
-
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("1"));
-               generator.add(new StringIDGeneratorPart("-"));
-               generator.add(new AlphabeticIDGeneratorPart("a"));
-               assertEquals("2009.1-a", generator.getCurrentID("2009.1-a"));
-               assertEquals("2009.1-b", generator.newID());
-
-       }
-
-       public void testNewID() {
-
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("1"));
-               assertEquals("2009.2", generator.newID());
-               assertEquals("2009.3", generator.newID());
-
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("1"));
-               generator.add(new StringIDGeneratorPart("-"));
-               generator.add(new AlphabeticIDGeneratorPart("a"));
-               assertEquals("2009.1-b", generator.newID());
-               assertEquals("2009.1-c", generator.newID());
-
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new StringIDGeneratorPart("T"));
-               generator.add(new NumericIDGeneratorPart("1005"));
-               assertEquals("T1006", generator.newID());
-               assertEquals("T1007", generator.newID());
-
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("1"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("1"));
-               assertEquals("2009.1.2", generator.newID());
-                       
-       }
-
-       public void testNewIDWithConstantStringID() {
-       
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("1"));
-               generator.add(new StringIDGeneratorPart("-"));
-               assertEquals("2009.1-", generator.newID());
-               assertEquals("2009.1-", generator.newID());
-
-       }
-
-       public void testNewIDWithSuppliedID() {
-       
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("1"));
-               assertEquals("2009.2", generator.newID("2009.1"));
-               assertEquals("2009.3", generator.newID("2009.2"));
-
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("1"));
-               generator.add(new StringIDGeneratorPart("-"));
-               generator.add(new AlphabeticIDGeneratorPart("a"));
-               assertEquals("2009.1-b", generator.newID("2009.1-a"));
-               assertEquals("2009.3-c", generator.newID("2009.3-b"));
-
-       }
-
-       public void testEmptyPartsListCurrentID() {
-
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               assertEquals("", generator.getCurrentID());
-                       
-       }
-
-       public void testIsValidIDYearPattern() {
-       
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-
-               assertTrue(generator.isValidID("2009"));
-               assertTrue(generator.isValidID("5555"));
-
-               assertFalse(generator.isValidID("456"));
-               assertFalse(generator.isValidID("10000"));
-               
-       }
-
-
-       public void testGetRegex() {
-       
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("1"));
-               assertEquals("(\\d{4})(\\.)(\\d{1,6})", generator.getRegex());
-       
-       }
-
-       public void testIsValidIDYearSeparatorItemPattern() {
-       
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-               generator.add(new StringIDGeneratorPart("."));
-               generator.add(new NumericIDGeneratorPart("1"));
-               
-               assertTrue(generator.isValidID("2009.1"));
-               assertTrue(generator.isValidID("5555.55"));
-
-               assertFalse(generator.isValidID("456.1"));
-               assertFalse(generator.isValidID("2009-1"));
-               assertFalse(generator.isValidID("2009.a"));
-               assertFalse(generator.isValidID("2009-a"));
-               assertFalse(generator.isValidID("non-generator conforming text"));
-
-               generator = new BaseIDGenerator(DEFAULT_CSID);
-               generator.add(new YearIDGeneratorPart("2009"));
-               generator.add(new StringIDGeneratorPart("ZZ.AND."));
-               generator.add(new NumericIDGeneratorPart("1"));
-
-               assertTrue(generator.isValidID("2009ZZ.AND.1"));
-               assertFalse(generator.isValidID("2009ZZ-AND-1"));
-       
-       }
-
-       // @TODO: Add more tests of boundary conditions, exceptions ...
+    BaseIDGenerator generator;
+    IDGeneratorPart part;
+    
+    final static String DEFAULT_CSID = "1";
+
+    // Note: tests may fail with IllegalArgumentException
+    // if any initialization of new IDParts fails
+    // due to invalid arguments passed to their constructors.
+
+    public void testEmptyPartsListCurrentID() {
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        assertEquals("", generator.getCurrentID());
+    }
+
+    public void testEmptyPartsListNewID() {
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        assertEquals("", generator.newID());
+    }
+
+    public void testCurrentIDViaVector() {
+
+        Vector parts = new Vector();
+
+        parts.clear();
+        parts.add(new AlphabeticIDGeneratorPart("a"));
+        generator = new BaseIDGenerator(DEFAULT_CSID, parts);
+        assertEquals("a", generator.getCurrentID());
+
+        parts.clear();
+        parts.add(new NumericIDGeneratorPart("1"));
+        generator = new BaseIDGenerator(DEFAULT_CSID, parts);
+        assertEquals("1", generator.getCurrentID());
+
+        parts.clear();
+        parts.add(new StringIDGeneratorPart("PREFIX"));
+        parts.add(new StringIDGeneratorPart("-"));
+        parts.add(new StringIDGeneratorPart("SUFFIX"));
+        generator = new BaseIDGenerator(DEFAULT_CSID, parts);
+        assertEquals("PREFIX-SUFFIX", generator.getCurrentID());
+
+        parts.clear();
+        parts.add(new YearIDGeneratorPart());
+        generator = new BaseIDGenerator(DEFAULT_CSID, parts);
+        assertEquals(getCurrentYear(), generator.getCurrentID());
+
+        parts.clear();
+        parts.add(new UUIDGeneratorPart());
+        generator = new BaseIDGenerator(DEFAULT_CSID, parts);
+        assertTrue(generator.getCurrentID().length() ==
+            UUIDGeneratorPart.UUID_LENGTH);
+
+        parts.clear();
+        parts.add(new YearIDGeneratorPart("2009"));
+        parts.add(new StringIDGeneratorPart("."));
+        parts.add(new NumericIDGeneratorPart("1"));
+        parts.add(new StringIDGeneratorPart("-"));
+        parts.add(new AlphabeticIDGeneratorPart("a"));
+        generator = new BaseIDGenerator(DEFAULT_CSID, parts);
+        assertEquals("2009.1-a", generator.getCurrentID());
+            
+    }
+
+    public void testCurrentIDViaAdd() {
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart("2009"));
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("1"));
+        generator.add(new StringIDGeneratorPart("-"));
+        generator.add(new AlphabeticIDGeneratorPart("a"));    
+        assertEquals("2009.1-a", generator.getCurrentID());
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart("2009"));
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("0"));
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("0"));
+        assertEquals("2009.0.0", generator.getCurrentID());
+            
+    }
+
+    public void testCurrentIDWithPartialSuppliedID() {
+            
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new StringIDGeneratorPart("E"));
+        generator.add(new NumericIDGeneratorPart("1"));
+        assertEquals("E1", generator.getCurrentID("E"));
+        assertEquals("E1", generator.getCurrentID("E"));
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart());
+        generator.add(new StringIDGeneratorPart("."));
+        assertEquals("2009.", generator.getCurrentID("2009"));
+        assertEquals("2009.", generator.getCurrentID("2009"));
+        assertEquals("2010.", generator.getCurrentID("2010"));
+        assertEquals("2010.", generator.getCurrentID("2010"));
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart());
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("1"));
+        assertEquals("2009.1", generator.getCurrentID("2009."));
+        assertEquals("2009.1", generator.getCurrentID("2009."));
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart());
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("55"));
+        assertEquals("2010.55", generator.getCurrentID("2010."));
+        assertEquals("2010.55", generator.getCurrentID("2010."));
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart("2009"));
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart());
+        assertEquals("2009.1", generator.getCurrentID("2009."));
+        assertEquals("2009.1", generator.getCurrentID("2009."));
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart("2009"));
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("1"));
+        generator.add(new StringIDGeneratorPart("-"));
+        generator.add(new AlphabeticIDGeneratorPart("a"));
+        assertEquals("2009.1-a", generator.getCurrentID("2009.1-"));
+        assertEquals("2009.1-a", generator.getCurrentID("2009.1-"));
+        assertEquals("2009.3-a", generator.getCurrentID("2009.3-"));
+        assertEquals("2009.3-a", generator.getCurrentID("2009.3-"));
+
+    }
+
+    public void testCurrentIDWithFullSuppliedID() {
+    
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart("2009"));
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("55"));
+        assertEquals("2009.55", generator.getCurrentID("2009.55"));
+        assertEquals("2009.56", generator.newID());
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart("2009"));
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("1"));
+        generator.add(new StringIDGeneratorPart("-"));
+        generator.add(new AlphabeticIDGeneratorPart("a"));
+        assertEquals("2009.1-a", generator.getCurrentID("2009.1-a"));
+        assertEquals("2009.1-b", generator.newID());
+
+    }
+
+    public void testNewAlphabeticLowercaseID() {
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new AlphabeticIDGeneratorPart("a"));
+        assertEquals("a", generator.newID());
+        assertEquals("b", generator.newID());
+        assertEquals("c", generator.newID());
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new AlphabeticIDGeneratorPart("aa"));
+        assertEquals("aa", generator.newID());
+        assertEquals("ab", generator.newID());
+        assertEquals("ac", generator.newID());
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new AlphabeticIDGeneratorPart("az"));
+        assertEquals("az", generator.newID());
+        assertEquals("ba", generator.newID());
+        assertEquals("bb", generator.newID());
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new AlphabeticIDGeneratorPart("a"));
+        generator.add(new AlphabeticIDGeneratorPart("yy"));
+        assertEquals("ayy", generator.newID());
+        assertEquals("ayz", generator.newID());
+        assertEquals("aza", generator.newID());
+    }
+
+    public void testNewAlphabeticUppercaseID() {
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new AlphabeticIDGeneratorPart("A", "Z", "A"));
+        assertEquals("A", generator.newID());
+        assertEquals("B", generator.newID());
+        assertEquals("C", generator.newID());
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new AlphabeticIDGeneratorPart("A", "Z", "AA"));
+        assertEquals("AA", generator.newID());
+        assertEquals("AB", generator.newID());
+        assertEquals("AC", generator.newID());
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new AlphabeticIDGeneratorPart("A", "Z", "AZ"));
+        assertEquals("AZ", generator.newID());
+        assertEquals("BA", generator.newID());
+        assertEquals("BB", generator.newID());
+        
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new AlphabeticIDGeneratorPart("A", "Z", "A"));
+        generator.add(new AlphabeticIDGeneratorPart("A", "Z", "YY"));
+        assertEquals("AYY", generator.newID());
+        assertEquals("AYZ", generator.newID());
+        assertEquals("AZA", generator.newID());
+    }
+
+    public void testNewStringID() {
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new StringIDGeneratorPart("PREFIX"));
+        assertEquals("PREFIX", generator.newID());
+        assertEquals("PREFIX", generator.newID());
+        assertEquals("PREFIX", generator.newID());
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new AlphabeticIDGeneratorPart("A", "Z", "AA"));
+        assertEquals("AA", generator.newID());
+        assertEquals("AB", generator.newID());
+        assertEquals("AC", generator.newID());
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new AlphabeticIDGeneratorPart("A", "Z", "AZ"));
+        assertEquals("AZ", generator.newID());
+        assertEquals("BA", generator.newID());
+        assertEquals("BB", generator.newID());
+    }
+
+    public void testNewUUID() {
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new UUIDGeneratorPart());
+        String firstID = generator.newID();
+        String secondID = generator.newID();
+        String thirdID = generator.newID();
+        assertTrue(firstID.length() == UUIDGeneratorPart.UUID_LENGTH);
+        assertTrue(secondID.length() == UUIDGeneratorPart.UUID_LENGTH);
+        assertTrue(thirdID.length() == UUIDGeneratorPart.UUID_LENGTH);
+        assertTrue(firstID.compareTo(secondID) != 0);
+        assertTrue(firstID.compareTo(thirdID) != 0);
+        assertTrue(secondID.compareTo(thirdID) != 0);
+    }
+
+    public void testNewID() {
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new NumericIDGeneratorPart("1"));
+        assertEquals("1", generator.newID());
+        assertEquals("2", generator.newID());
+        assertEquals("3", generator.newID());
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart());
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("1"));
+        assertEquals(getCurrentYear() + ".1", generator.newID());
+        assertEquals(getCurrentYear() + ".2", generator.newID());
+        assertEquals(getCurrentYear() + ".3", generator.newID());
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart());
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("1"));
+        generator.add(new StringIDGeneratorPart("-"));
+        generator.add(new AlphabeticIDGeneratorPart("a"));
+        assertEquals(getCurrentYear() + ".1-a", generator.newID());
+        assertEquals(getCurrentYear() + ".1-b", generator.newID());
+        assertEquals(getCurrentYear() + ".1-c", generator.newID());
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new StringIDGeneratorPart("T"));
+        generator.add(new NumericIDGeneratorPart("1005"));
+        assertEquals("T1005", generator.newID());
+        assertEquals("T1006", generator.newID());
+        assertEquals("T1007", generator.newID());
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart());
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("1"));
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("1"));
+        assertEquals(getCurrentYear() + ".1.1", generator.newID());
+        assertEquals(getCurrentYear() + ".1.2", generator.newID());
+        assertEquals(getCurrentYear() + ".1.3", generator.newID());
+            
+    }
+
+    public void testNewIDWithTrailingConstantStringID() {
+    
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart());
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("1"));
+        generator.add(new StringIDGeneratorPart("-"));
+        assertEquals(getCurrentYear() + ".1-", generator.newID());
+        assertEquals(getCurrentYear() + ".1-", generator.newID());
+
+    }
+
+    public void testNewIDWithSuppliedID() {
+    
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart("2009"));
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("1"));
+        assertEquals("2009.1", generator.newID("2009.1"));
+        assertEquals("2009.2", generator.newID());
+        assertEquals("2009.3", generator.newID());
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart("2009"));
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("1"));
+        generator.add(new StringIDGeneratorPart("-"));
+        generator.add(new AlphabeticIDGeneratorPart("a"));
+        assertEquals("2009.1-a", generator.newID("2009.1-a"));
+        assertEquals("2009.1-b", generator.newID());
+        assertEquals("2009.1-c", generator.newID());
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart("2009"));
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("3"));
+        generator.add(new StringIDGeneratorPart("-"));
+        generator.add(new AlphabeticIDGeneratorPart("b"));        
+        assertEquals("2009.3-b", generator.newID("2009.3-b"));
+        assertEquals("2009.3-c", generator.newID());
+        assertEquals("2009.3-d", generator.newID());
+
+    }
+
+    public void testValidUUID() {
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new UUIDGeneratorPart());
+
+        assertTrue(generator.isValidID("4c9395a8-1669-41f9-806c-920d86e40912"));
+
+        // Invalid character in 15th position (should be '4').
+        assertFalse(generator.isValidID("4c9395a8-1669-31f9-806c-920d86e40912"));
+        // Invalid character in 20th position (should be '8', '9', 'a', or 'b').
+        assertFalse(generator.isValidID("4c9395a8-1669-41f9-106c-920d86e40912"));
+        assertFalse(generator.isValidID(null));
+        assertFalse(generator.isValidID(""));
+        assertFalse(generator.isValidID("not a UUID"));
+        assertFalse(generator.isValidID("12345"));
+    }
+
+    public void testValidYearID() {
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart());
+
+        assertTrue(generator.isValidID("2009"));
+        assertTrue(generator.isValidID("5555"));
+
+        assertFalse(generator.isValidID("456"));
+        assertFalse(generator.isValidID("10000"));
+    }
+
+
+    public void testGetRegex() {
+    
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart("2009"));
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("1"));
+        assertEquals("(\\d{4})(\\.)(\\d{1,6})", generator.getRegex());
+    
+    }
+
+    public void testIsValidIDYearSeparatorItemPattern() {
+    
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart("2009"));
+        generator.add(new StringIDGeneratorPart("."));
+        generator.add(new NumericIDGeneratorPart("1"));
+        
+        assertTrue(generator.isValidID("2009.1"));
+        assertTrue(generator.isValidID("5555.55"));
+
+        assertFalse(generator.isValidID("456.1"));
+        assertFalse(generator.isValidID("2009-1"));
+        assertFalse(generator.isValidID("2009.a"));
+        assertFalse(generator.isValidID("2009-a"));
+        assertFalse(generator.isValidID("non-generator conforming text"));
+
+        generator = new BaseIDGenerator(DEFAULT_CSID);
+        generator.add(new YearIDGeneratorPart("2009"));
+        generator.add(new StringIDGeneratorPart("ZZ.AND."));
+        generator.add(new NumericIDGeneratorPart("1"));
+
+        assertTrue(generator.isValidID("2009ZZ.AND.1"));
+        assertFalse(generator.isValidID("2009ZZ-AND-1"));
+    
+    }
+
+    public static String getCurrentYear() {
+        Calendar cal = GregorianCalendar.getInstance();
+        int y = cal.get(Calendar.YEAR);
+        return Integer.toString(y);
+    }    
+
+    // @TODO: Add more tests of boundary conditions, exceptions ...
  
 }
index 62635263060524b39ad653631ebda68da84340bf..1576429fa17ab6f582e6ef4412c4c72694170176 100644 (file)
  *
  * You may obtain a copy of the ECL 2.0 License at
  * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 package org.collectionspace.services.id.test;
@@ -43,6 +49,9 @@ public class IDServiceJdbcImplTest {
     
     final static String TABLE_NAME = "id_generators";
     final static String DEFAULT_CSID = "TEST-1";
+    
+    final static String CURRENT_YEAR = YearIDGeneratorPart.getCurrentYear();
+
 
     @Test
     public void hasRequiredDatabaseTable() {
@@ -55,19 +64,24 @@ public class IDServiceJdbcImplTest {
 
     @Test(dependsOnMethods = {"hasRequiredDatabaseTable"})
     public void addIDGenerator() {
+        try {
+            jdbc.deleteIDGenerator(DEFAULT_CSID);
+        } catch (Exception e) {
+               // Fail silently; this is guard code.
+        }
         jdbc.addIDGenerator(DEFAULT_CSID, getSpectrumEntryNumberGenerator());
     }
 
-    @Test(dependsOnMethods = {"addIDGenerator"})
+    @Test(dependsOnMethods = {"hasRequiredDatabaseTable", "addIDGenerator"})
     public void readIDGenerator() {
 
         serializedGenerator = jdbc.getIDGenerator(DEFAULT_CSID);
         generator = IDGeneratorSerializer.deserialize(serializedGenerator);
-        Assert.assertEquals(DEFAULT_CSID, generator.getCsid());
+        Assert.assertEquals(generator.getCsid(), DEFAULT_CSID);
         
     }
 
-    @Test(dependsOnMethods = {"addIDGenerator"})
+    @Test(dependsOnMethods = {"hasRequiredDatabaseTable", "addIDGenerator", "readIDGenerator"})
     public void updateIDGenerator() {
 
         final String NEW_DESCRIPTION = "new description";
@@ -84,53 +98,54 @@ public class IDServiceJdbcImplTest {
         serializedGenerator = jdbc.getIDGenerator(DEFAULT_CSID);
         generator = IDGeneratorSerializer.deserialize(serializedGenerator);
         
-        Assert.assertEquals(NEW_DESCRIPTION, generator.getDescription());
+        Assert.assertEquals(generator.getDescription(), NEW_DESCRIPTION);
         
     }
 
-    @Test(dependsOnMethods = {"addIDGenerator", "readIDGenerator"})
+    @Test(dependsOnMethods = {"hasRequiredDatabaseTable", "addIDGenerator",
+       "readIDGenerator", "updateIDGenerator"})
     public void deleteIDGenerator() {
         jdbc.deleteIDGenerator(DEFAULT_CSID);
     }
+
  
-    @Test(dependsOnMethods = {"addIDGenerator", "deleteIDGenerator"})
+    @Test(dependsOnMethods = {"hasRequiredDatabaseTable", "addIDGenerator", "readIDGenerator", 
+       "updateIDGenerator", "deleteIDGenerator"})
         public void newIDValidPattern() {
-        
-        csid = DEFAULT_CSID;
-        
+                
         try {
-            jdbc.deleteIDGenerator(csid);
+            jdbc.deleteIDGenerator(DEFAULT_CSID);
         } catch (Exception e) {
-            // do nothing
+               // Fail silently; this is guard code.
         }
-        
-        jdbc.addIDGenerator(csid, getSpectrumEntryNumberGenerator());
 
-        Assert.assertEquals("E1", service.newID(csid));
-        Assert.assertEquals("E2", service.newID(csid));
-        Assert.assertEquals("E3", service.newID(csid));
+        jdbc.addIDGenerator(DEFAULT_CSID, getSpectrumEntryNumberGenerator());
+
+        Assert.assertEquals(service.newID(DEFAULT_CSID), "E1");
+        Assert.assertEquals(service.newID(DEFAULT_CSID), "E2");
+        Assert.assertEquals(service.newID(DEFAULT_CSID), "E3");
         
         try {
-            jdbc.deleteIDGenerator(csid);
+            jdbc.deleteIDGenerator(DEFAULT_CSID);
         } catch (Exception e) {
-            // do nothing
+            Assert.fail("Could not delete ID generator '" + DEFAULT_CSID + "'.");
         }
         
-        jdbc.addIDGenerator(csid, getChinAccessionNumberGenerator());
+        jdbc.addIDGenerator(DEFAULT_CSID, getChinAccessionNumberGenerator());
 
-        String currentYear = YearIDGeneratorPart.getCurrentYear();
-        Assert.assertEquals(currentYear + ".1.1", service.newID(csid));
-        Assert.assertEquals(currentYear + ".1.2", service.newID(csid));
-        Assert.assertEquals(currentYear + ".1.3", service.newID(csid));
+        Assert.assertEquals(service.newID(DEFAULT_CSID), CURRENT_YEAR + ".1.1");
+        Assert.assertEquals(service.newID(DEFAULT_CSID), CURRENT_YEAR + ".1.2");
+        Assert.assertEquals(service.newID(DEFAULT_CSID), CURRENT_YEAR + ".1.3");
 
         try {
-            jdbc.deleteIDGenerator(csid);
+            jdbc.deleteIDGenerator(DEFAULT_CSID);
         } catch (Exception e) {
-            // do nothing
+            Assert.fail("Could not delete ID generator '" + DEFAULT_CSID + "'.");
         }
 
     }
 
+
     // This test requires that:
     // 1. The ID Service is running and accessible to this test; and
     // 2. There is no ID generator retrievable through that service
index 9ecb44c92ed477a83536ebf5d0d88d59a4447bdd..eb51afa1b3203b403cf909bd2921c10eaa55a9c8 100644 (file)
  *
  * You may obtain a copy of the ECL 2.0 License at
  * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 package org.collectionspace.services.id;
@@ -34,32 +40,37 @@ import junit.framework.TestCase;
  */
 public class NumericIDGeneratorPartTest extends TestCase {
 
-    IDGeneratorPart part;
+    SequenceIDGeneratorPart part;
 
-    public void testNextID() {
+    public void testNewID() {
 
         part = new NumericIDGeneratorPart("0");        
-        assertEquals("1", part.nextID());
-        assertEquals("2", part.nextID());
-        assertEquals("3", part.nextID());
+        assertEquals("0", part.newID());
+        assertEquals("1", part.newID());
+        assertEquals("2", part.newID());
+        assertEquals("3", part.newID());
     
         part = new NumericIDGeneratorPart("25");
-        assertEquals("26", part.nextID());
-        assertEquals("27", part.nextID());
-        assertEquals("28", part.nextID());
+        assertEquals("25", part.newID());
+        assertEquals("26", part.newID());
+        assertEquals("27", part.newID());
+        assertEquals("28", part.newID());
         
         part = new NumericIDGeneratorPart();
-        assertEquals("2", part.nextID());
+        assertEquals("1", part.newID());
+        assertEquals("2", part.newID());
+        assertEquals("3", part.newID());
             
     }
 
-    public void testNextIDOverflow() {
+    public void testNewIDOverflow() {
 
         try {
             part = new NumericIDGeneratorPart("997", "3");        
-            assertEquals("998", part.nextID());
-            assertEquals("999", part.nextID());
-            assertEquals("1000", part.nextID());
+            assertEquals("997", part.newID());
+            assertEquals("998", part.newID());
+            assertEquals("999", part.newID());
+            assertEquals("1000", part.newID());
             fail("Should have thrown IllegalStateException here");
         } catch (IllegalStateException expected) {
             // This Exception should be thrown, and thus the test should pass.
@@ -68,9 +79,10 @@ public class NumericIDGeneratorPartTest extends TestCase {
         // Tests default MAX_LENGTH value of 6 decimal places
         try {
             part = new NumericIDGeneratorPart("999997");        
-            assertEquals("999998", part.nextID());
-            assertEquals("999999", part.nextID());
-            assertEquals("1000000", part.nextID());
+            assertEquals("999997", part.newID());
+            assertEquals("999998", part.newID());
+            assertEquals("999999", part.newID());
+            assertEquals("1000000", part.newID());
             fail("Should have thrown IllegalStateException here");
         } catch (IllegalStateException expected) {
             // This Exception should be thrown, and thus the test should pass.
@@ -78,17 +90,6 @@ public class NumericIDGeneratorPartTest extends TestCase {
             
     }
 
-    public void testResetID() {
-    
-        part = new NumericIDGeneratorPart("25");
-        assertEquals("26", part.nextID());
-        assertEquals("27", part.nextID());
-        assertEquals("28", part.nextID());
-        part.resetID();
-        assertEquals("26", part.nextID());
-            
-    }
-
     public void testInitialID() {
 
         part = new NumericIDGeneratorPart("0");
@@ -103,16 +104,17 @@ public class NumericIDGeneratorPartTest extends TestCase {
 
         part = new NumericIDGeneratorPart("0");
         assertEquals("0", part.getCurrentID());
-        assertEquals("1", part.nextID());
-        assertEquals("2", part.nextID());
+        assertEquals("0", part.newID());
+        assertEquals("1", part.newID());
+        assertEquals("2", part.newID());
         assertEquals("2", part.getCurrentID());
-        assertEquals("3", part.nextID());
+        assertEquals("3", part.newID());
 
         part = new NumericIDGeneratorPart("25");
         assertEquals("25", part.getCurrentID());
         
     }
-    
+
     public void testNullInitialValue() {
     
         try {
index 41eae683221cecd6f740e8651231a6218377cd03..a13db7ab5914b2971fb708677a6f02d1522a3a23 100644 (file)
  *
  * You may obtain a copy of the ECL 2.0 License at
  * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 package org.collectionspace.services.id;
@@ -30,26 +36,28 @@ import junit.framework.TestCase;
  */
 public class StringIDGeneratorPartTest extends TestCase {
 
-       IDGeneratorPart part;
+       StoredValueIDGeneratorPart part;
 
-       public void testNextID() {
+       public void testnewID() {
 
                part = new StringIDGeneratorPart("E");          
-               assertEquals("E", part.nextID());       
+               assertEquals("E", part.newID());        
                
                part = new StringIDGeneratorPart("XYZ");                
-               assertEquals("XYZ", part.nextID());             
+               assertEquals("XYZ", part.newID());              
                
        }
 
+/*
        public void testresetID() {
        
                part = new StringIDGeneratorPart(".");
-               assertEquals(".", part.nextID());
+               assertEquals(".", part.newID());
                part.resetID();
-               assertEquals(".", part.nextID());
+               assertEquals(".", part.newID());
                        
        }
+*/
 
        public void testInitialID() {
                part = new StringIDGeneratorPart("-");
diff --git a/services/id/service/src/test/java/org/collectionspace/services/id/test/UUIDGeneratorPartTest.java b/services/id/service/src/test/java/org/collectionspace/services/id/test/UUIDGeneratorPartTest.java
new file mode 100644 (file)
index 0000000..2ab2116
--- /dev/null
@@ -0,0 +1,77 @@
+/*    
+ * This document is a part of the source code and related artifacts
+ * for CollectionSpace, an open source collections management system
+ * for museums and related institutions:
+ *
+ * http://www.collectionspace.org
+ * http://wiki.collectionspace.org
+ *
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.collectionspace.services.id;
+
+import static org.junit.Assert.fail;
+import junit.framework.TestCase;
+
+/**
+ * UUIDGeneratorPartTest
+ *
+ * Test class for UUIDGeneratorPart.
+ *
+ * $LastChangedRevision: 625 $
+ * $LastChangedDate$
+ */
+public class UUIDGeneratorPartTest extends TestCase {
+
+    IDGeneratorPart part;
+    
+    public void testnewID() {
+
+        part = new UUIDGeneratorPart(); 
+        
+        String firstID = part.newID();
+        String secondID = part.newID();
+        String thirdID = part.newID();
+
+        assertTrue(firstID.length() == UUIDGeneratorPart.UUID_LENGTH);
+        assertTrue(secondID.length() == UUIDGeneratorPart.UUID_LENGTH);
+        assertTrue(thirdID.length() == UUIDGeneratorPart.UUID_LENGTH);
+        
+        assertTrue(firstID.compareTo(secondID) != 0);
+        assertTrue(firstID.compareTo(thirdID) != 0);
+        assertTrue(secondID.compareTo(thirdID) != 0);
+             
+    }
+
+    public void testIsValidID() {
+    
+        part = new UUIDGeneratorPart();
+        assertTrue(part.isValidID("2d5ef3cc-bfb2-4383-a4c6-35645cd5dd81"));
+
+        part = new UUIDGeneratorPart();
+        assertFalse(part.isValidID("foo"));
+
+        part = new UUIDGeneratorPart();
+        assertFalse(part.isValidID(null));
+
+        part = new UUIDGeneratorPart();
+        assertFalse(part.isValidID(""));
+    
+    }    
+    
+    // @TODO: Add more tests of boundary conditions, exceptions ...
+}
index 37a0495a398f4855d7f3a38b0d93add44db72cc7..41ae11b1ab022ff9feb5142dc3e0ad83906ed9b1 100644 (file)
  *
  * You may obtain a copy of the ECL 2.0 License at
  * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 package org.collectionspace.services.id;
@@ -41,6 +47,7 @@ public class YearIDGeneratorPartTest extends TestCase {
         return Integer.toString(y);
     }
 
+/*
     public void testCurrentID() {
 
         part = new YearIDGeneratorPart();
@@ -80,30 +87,43 @@ public class YearIDGeneratorPartTest extends TestCase {
         }
 
   }
-    
-    public void testNextID() {
+*/ 
+
+/*
+    public void testnewID() {
     
         part = new YearIDGeneratorPart("1999");        
-        assertEquals("1999", part.nextID());        
+        assertEquals("1999", part.newID());        
+        
+    }
+*/
+
+    public void testnewID() {
+    
+        part = new YearIDGeneratorPart();        
+        assertEquals(getCurrentYear(), part.newID());        
         
     }
 
+/*
     public void testresetID() {
     
         part = new YearIDGeneratorPart("1999");
-        assertEquals("1999", part.nextID());
+        assertEquals("1999", part.newID());
         part.resetID();
         assertEquals("1999", part.getCurrentID());
             
     }
+*/
 
+/*
     public void testInitialID() {
     
         part = new YearIDGeneratorPart("1999");
         assertEquals("1999", part.getInitialID());
         
     }
-
+*/
 
     public void testNullInitialValue() {