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 18 package org.apache.commons.id.serial; 19 20 import org.apache.commons.id.AbstractStringIdentifierGenerator; 21 22 import java.io.Serializable; 23 24 /** 25 * <code>AlphanumericGenerator</code> is an identifier generator 26 * that generates an incrementing number in base 36 as a String 27 * object. 28 * 29 * <p>All generated ids have the same length (padding with 0's on the left), 30 * which is determined by the <code>size</code> parameter passed to the constructor.<p> 31 * 32 * <p>The <code>wrap</code> property determines whether or not the sequence wraps 33 * when it reaches the largest value that can be represented in <code>size</code> 34 * base 36 digits. If <code>wrap</code> is false and the the maximum representable 35 * value is exceeded, an IllegalStateException is thrown</p> 36 * 37 * @author Commons-Id team 38 * @version $Id: AlphanumericGenerator.java 480488 2006-11-29 08:57:26Z bayard $ 39 */ 40 public class AlphanumericGenerator extends AbstractStringIdentifierGenerator implements Serializable { 41 42 /** 43 * <code>serialVersionUID</code> is the serializable UID for the binary version of the class. 44 */ 45 private static final long serialVersionUID = 20060120L; 46 47 /** 48 * Should the counter wrap. 49 */ 50 private boolean wrapping = true; 51 52 /** 53 * The counter. 54 */ 55 private char[] count = null; 56 57 /** 58 * 'z' char 59 */ 60 private static final char Z_CHAR = 'z'; 61 62 /** 63 * '9' char 64 */ 65 private static final char NINE_CHAR = '9'; 66 67 /** 68 * Constructor with a default size for the alphanumeric identifier. 69 * 70 * @param wrap should the factory wrap when it reaches the maximum 71 * long value (or throw an exception) 72 */ 73 public AlphanumericGenerator(boolean wrap) { 74 this(wrap, DEFAULT_ALPHANUMERIC_IDENTIFIER_SIZE); 75 } 76 77 /** 78 * Constructor. 79 * 80 * @param wrap should the factory wrap when it reaches the maximum 81 * long value (or throw an exception) 82 * @param size the size of the identifier 83 */ 84 public AlphanumericGenerator(boolean wrap, int size) { 85 super(); 86 this.wrapping = wrap; 87 if (size < 1) { 88 throw new IllegalArgumentException("The size must be at least one"); 89 } 90 this.count = new char[size]; 91 for (int i = 0; i < size; i++) { 92 count[i] = '0'; // zero 93 } 94 } 95 96 /** 97 * Construct with a counter, that will start at the specified 98 * alphanumeric value.</p> 99 * 100 * @param wrap should the factory wrap when it reaches the maximum 101 * value (or throw an exception) 102 * @param initialValue the initial value to start at 103 */ 104 public AlphanumericGenerator(boolean wrap, String initialValue) { 105 super(); 106 this.wrapping = wrap; 107 this.count = initialValue.toCharArray(); 108 109 for (int i = 0; i < this.count.length; i++) { 110 char ch = this.count[i]; 111 if (ch >= '0' && ch <= '9') continue; 112 if (ch >= 'a' && ch <= 'z') continue; 113 114 throw new IllegalArgumentException( 115 "character " + this.count[i] + " is not valid"); 116 } 117 } 118 119 public long maxLength() { 120 return this.count.length; 121 } 122 123 public long minLength() { 124 return this.count.length; 125 } 126 127 /** 128 * Getter for property wrap. 129 * 130 * @return <code>true</code> if this generator is set up to wrap. 131 * 132 */ 133 public boolean isWrap() { 134 return wrapping; 135 } 136 137 /** 138 * Sets the wrap property. 139 * 140 * @param wrap value for the wrap property 141 * 142 */ 143 public void setWrap(boolean wrap) { 144 this.wrapping = wrap; 145 } 146 147 /** 148 * Returns the (constant) size of the strings generated by this generator. 149 * 150 * @return the size of generated identifiers 151 */ 152 public int getSize() { 153 return this.count.length; 154 } 155 156 public synchronized String nextStringIdentifier() { 157 for (int i = count.length - 1; i >= 0; i--) { 158 switch (count[i]) { 159 case Z_CHAR: // z 160 if (i == 0 && !wrapping) { 161 throw new IllegalStateException 162 ("The maximum number of identifiers has been reached"); 163 } 164 count[i] = '0'; 165 break; 166 167 case NINE_CHAR: // 9 168 count[i] = 'a'; 169 i = -1; 170 break; 171 172 default: 173 count[i]++; 174 i = -1; 175 break; 176 } 177 } 178 return new String(count); 179 } 180 }