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 }