View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.id.serial;
18  
19  import org.apache.commons.id.AbstractStringIdentifierGenerator;
20  
21  /**
22   * <code>PrefixedLeftPaddedNumericGenerator</code> is an Identifier Generator
23   * that generates a left-padded incrementing number with a prefix as a String object.
24   *
25   * <p>All generated ids have the same length (prefixed and padded with 0's
26   * on the left), which is determined by the <code>size</code> parameter passed
27   * to the constructor.<p>
28   *
29   * <p>The <code>wrap</code> property determines whether or not the sequence wraps
30   * when it reaches the largest value that can be represented in <code>size</code>
31   * base 10 digits. If <code>wrap</code> is false and the the maximum representable
32   * value is exceeded, an {@link IllegalStateException} is thrown.</p>
33   *
34   * @author Commons-Id team
35   * @version $Id$
36   */
37  public class PrefixedLeftPaddedNumericGenerator extends AbstractStringIdentifierGenerator {
38  
39      /** Prefix. */
40      private final String prefix;
41  
42      /** Should the counter wrap. */
43      private boolean wrap = true;
44  
45      /** The counter. */
46      private char[] count = null;
47  
48      /** '9' char. */
49      private static final char NINE_CHAR = '9';
50  
51  
52      /**
53       * Create a new prefixed left-padded numeric generator with the specified prefix.
54       *
55       * @param prefix prefix, must not be null or empty
56       * @param wrap should the factory wrap when it reaches the maximum
57       *  value that can be represented in <code>size</code> base 10 digits
58       *  (or throw an exception)
59       * @param size the size of the identifier, including prefix length
60       * @throws IllegalArgumentException if size less prefix length is not at least one
61       * @throws NullPointerException if prefix is <code>null</code>
62       */
63      public PrefixedLeftPaddedNumericGenerator(String prefix, boolean wrap, int size) {
64          super();
65  
66          if (prefix == null) {
67              throw new NullPointerException("prefix must not be null");
68          }
69          if (size < 1) {
70              throw new IllegalArgumentException("size must be at least one");
71          }
72          if (size <= prefix.length()) {
73              throw new IllegalArgumentException("size less prefix length must be at least one");
74          }
75          this.wrap = wrap;
76          this.prefix = prefix;
77  
78          int countLength = size - prefix.length();
79          this.count = new char[countLength];
80          for (int i = 0; i < countLength; i++) {
81              count[i] = '0';
82          }
83      }
84  
85  
86      /**
87       * Return the prefix for this prefixed numeric generator.
88       *
89       * @return the prefix for this prefixed numeric generator
90       */
91      public String getPrefix() {
92          return prefix;
93      }
94  
95      public long maxLength() {
96          return this.count.length + prefix.length();
97      }
98  
99      public long minLength() {
100         return this.count.length + prefix.length();
101     }
102 
103     /**
104      * Returns the (constant) size of the strings generated by this generator.
105      *
106      * @return the size of generated identifiers
107      */
108     public int getSize() {
109         return this.count.length + prefix.length();
110     }
111 
112     /**
113      * Getter for property wrap.
114      *
115      * @return <code>true</code> if this generator is set up to wrap
116      */
117     public boolean isWrap() {
118         return wrap;
119     }
120 
121     /**
122      * Setter for property wrap.
123      *
124      * @param wrap should the factory wrap when it reaches the maximum
125      *  value that can be represented in <code>size</code> base 10 digits
126      *  (or throw an exception)
127      */
128     public void setWrap(boolean wrap) {
129         this.wrap = wrap;
130     }
131 
132     public String nextStringIdentifier() {
133         for (int i = count.length - 1; i >= 0; i--) {
134             switch (count[i]) {
135                 case NINE_CHAR:  // 9
136                     count[i] = '0';
137                     if (i == 0 && !wrap) {
138                         throw new IllegalStateException
139                         ("The maximum number of identifiers has been reached");
140                     }
141                     break;
142 
143                 default:
144                     count[i]++;
145                     i = -1;
146                     break;
147             }
148         }
149 
150         StringBuffer sb = new StringBuffer(prefix);
151         sb.append(count);
152         return sb.toString();
153     }
154 }