View Javadoc
1 package org.apache.torque.om; 2 3 /* ==================================================================== 4 * The Apache Software License, Version 1.1 5 * 6 * Copyright (c) 2001-2003 The Apache Software Foundation. All rights 7 * reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The end-user documentation included with the redistribution, 22 * if any, must include the following acknowledgment: 23 * "This product includes software developed by the 24 * Apache Software Foundation (http://www.apache.org/)." 25 * Alternately, this acknowledgment may appear in the software itself, 26 * if and wherever such third-party acknowledgments normally appear. 27 * 28 * 4. The names "Apache" and "Apache Software Foundation" and 29 * "Apache Turbine" must not be used to endorse or promote products 30 * derived from this software without prior written permission. For 31 * written permission, please contact apache@apache.org. 32 * 33 * 5. Products derived from this software may not be called "Apache", 34 * "Apache Turbine", nor may "Apache" appear in their name, without 35 * prior written permission of the Apache Software Foundation. 36 * 37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 * ==================================================================== 50 * 51 * This software consists of voluntary contributions made by many 52 * individuals on behalf of the Apache Software Foundation. For more 53 * information on the Apache Software Foundation, please see 54 * <http://www.apache.org/>. 55 */ 56 57 import java.util.ArrayList; 58 import org.apache.commons.lang.ObjectUtils; 59 60 /*** 61 * This class can be used as an ObjectKey to uniquely identify an 62 * object within an application where the key consists of multiple 63 * entities (such a String[] representing a multi-column primary key). 64 * 65 * @author <a href="mailto:jmcnally@collab.net">John McNally</a> 66 * @author <a href="mailto:dlr@collab.net">Daniel Rall</a> 67 * @author <a href="mailto:drfish@cox.net">J. Russell Smyth</a> 68 * @version $Id: ComboKey.java,v 1.14 2003/08/25 21:42:40 mpoeschl Exp $ 69 */ 70 public class ComboKey extends ObjectKey 71 { 72 // might want to shift these to TR.props 73 74 /*** The single character used to separate key values in a string. */ 75 public static final char SEPARATOR = ':'; 76 77 /*** The single character used to separate key values in a string. */ 78 public static final String SEPARATOR_STRING = ":"; 79 80 /*** The array of the keys */ 81 private SimpleKey[] key; 82 83 /*** 84 * Creates an ComboKey whose internal representation will be 85 * set later, through a set method 86 */ 87 public ComboKey() 88 { 89 } 90 91 /*** 92 * Creates a ComboKey whose internal representation is an 93 * array of SimpleKeys. 94 * 95 * @param keys the key values 96 */ 97 public ComboKey(SimpleKey[] keys) 98 { 99 setValue(keys); 100 } 101 102 /*** 103 * Sets the internal representation to a String array. 104 * 105 * @param keys the key values 106 * @see #toString() 107 */ 108 public ComboKey(String keys) 109 { 110 setValue(keys); 111 } 112 113 /*** 114 * Sets the internal representation using a SimpleKey array. 115 * 116 * @param keys the key values 117 */ 118 public void setValue(SimpleKey[] keys) 119 { 120 this.key = keys; 121 } 122 123 /*** 124 * Sets the internal representation using a String of the 125 * form produced by the toString method. 126 * 127 * @param keys the key values 128 */ 129 public void setValue(String keys) 130 { 131 int startPtr = 0; 132 int indexOfSep = keys.indexOf(SEPARATOR); 133 ArrayList tmpKeys = new ArrayList(); 134 while (indexOfSep != -1) 135 { 136 if (indexOfSep == startPtr) 137 { 138 tmpKeys.add(null); 139 } 140 else 141 { 142 char keyType = keys.charAt(startPtr); 143 String keyString = keys.substring(startPtr + 1, indexOfSep); 144 145 SimpleKey newKey = null; 146 switch(keyType) 147 { 148 case 'N': 149 newKey = new NumberKey(keyString); 150 break; 151 case 'S': 152 newKey = new StringKey(keyString); 153 break; 154 case 'D': 155 try 156 { 157 newKey = new DateKey(keyString); 158 } 159 catch (NumberFormatException nfe) 160 { 161 newKey = new DateKey(); 162 } 163 break; 164 default: 165 // unextepcted key type 166 } 167 tmpKeys.add(newKey); 168 } 169 startPtr = indexOfSep + 1; 170 indexOfSep = keys.indexOf(SEPARATOR, startPtr); 171 } 172 173 this.key = new SimpleKey[tmpKeys.size()]; 174 for (int i = 0; i < this.key.length; i++) 175 { 176 this.key[i] = (SimpleKey) tmpKeys.get(i); 177 } 178 } 179 180 /*** 181 * Sets the internal representation using a ComboKey. 182 * 183 * @param keys the key values 184 */ 185 public void setValue(ComboKey keys) 186 { 187 setValue((SimpleKey[]) keys.getValue()); 188 } 189 190 /*** 191 * Get the underlying object. 192 * 193 * @return the underlying object 194 */ 195 public Object getValue() 196 { 197 return key; 198 } 199 200 /*** 201 * This method will return true if the conditions for a looseEquals 202 * are met and in addition no parts of the keys are null. 203 * 204 * @param keyObj the comparison value 205 * @return whether the two objects are equal 206 */ 207 public boolean equals(Object keyObj) 208 { 209 boolean isEqual = false; 210 211 if (key != null) 212 { 213 // check that all keys are not null 214 isEqual = true; 215 SimpleKey[] keys = key; 216 for (int i = 0; i < keys.length && isEqual; i++) 217 { 218 isEqual &= keys[i] != null && keys[i].getValue() != null; 219 } 220 221 isEqual &= looseEquals(keyObj); 222 } 223 224 return isEqual; 225 } 226 227 /*** 228 * keyObj is equal to this ComboKey if keyObj is a ComboKey, String, 229 * ObjectKey[], or String[] that contains the same information this key 230 * contains. 231 * For example A String[] might be equal to this key, if this key was 232 * instantiated with a String[] and the arrays contain equal Strings. 233 * Another example, would be if keyObj is an ComboKey that was 234 * instantiated with a ObjectKey[] and this ComboKey was instantiated with 235 * a String[], but the ObjectKeys in the ObjectKey[] were instantiated 236 * with Strings that equal the Strings in this KeyObject's String[] 237 * This method is not as strict as the equals method which does not 238 * allow any null keys parts, while the internal key may not be null 239 * portions may be, and the two object will be considered equal if 240 * their null portions match. 241 * 242 * @param keyObj the comparison value 243 * @return whether the two objects are equal 244 */ 245 public boolean looseEquals(Object keyObj) 246 { 247 boolean isEqual = false; 248 249 if (key != null) 250 { 251 // Checks a compound key (ObjectKey[] or String[] 252 // based) with the delimited String created by the 253 // toString() method. Slightly expensive, but should be less 254 // than parsing the String into its constituents. 255 if (keyObj instanceof String) 256 { 257 isEqual = toString().equals(keyObj); 258 } 259 // check against a ObjectKey. Two keys are equal, if their 260 // internal keys equivalent. 261 else if (keyObj instanceof ComboKey) 262 { 263 SimpleKey[] obj = (SimpleKey[]) 264 ((ComboKey) keyObj).getValue(); 265 266 SimpleKey[] keys1 = key; 267 SimpleKey[] keys2 = obj; 268 isEqual = keys1.length == keys2.length; 269 for (int i = 0; i < keys1.length && isEqual; i++) 270 { 271 isEqual &= ObjectUtils.equals(keys1[i], keys2[i]); 272 } 273 } 274 else if (keyObj instanceof SimpleKey[]) 275 { 276 SimpleKey[] keys1 = key; 277 SimpleKey[] keys2 = (SimpleKey[]) keyObj; 278 isEqual = keys1.length == keys2.length; 279 for (int i = 0; i < keys1.length && isEqual; i++) 280 { 281 isEqual &= ObjectUtils.equals(keys1[i], keys2[i]); 282 } 283 } 284 } 285 return isEqual; 286 } 287 288 /*** 289 * 290 * @param sb the StringBuffer to append 291 * @see #toString() 292 */ 293 public void appendTo(StringBuffer sb) 294 { 295 if (key != null) 296 { 297 SimpleKey[] keys = key; 298 for (int i = 0; i < keys.length; i++) 299 { 300 if (keys[i] != null) 301 { 302 if (keys[i] instanceof StringKey) 303 { 304 sb.append("S"); 305 } 306 else if (keys[i] instanceof NumberKey) 307 { 308 sb.append("N"); 309 } 310 else if (keys[i] instanceof DateKey) 311 { 312 sb.append("D"); 313 } 314 else 315 { 316 // unknown type 317 sb.append("U"); 318 } 319 keys[i].appendTo(sb); 320 } 321 // MUST BE ADDED AFTER EACH KEY, IN CASE OF NULL KEY! 322 sb.append(SEPARATOR); 323 } 324 } 325 } 326 327 /*** 328 * if the underlying key array is not null and the first element is 329 * not null this method returns the hashcode of the first element 330 * in the key. Otherwise calls ObjectKey.hashCode() 331 * 332 * @return an <code>int</code> value 333 */ 334 public int hashCode() 335 { 336 if (key == null) 337 { 338 return super.hashCode(); 339 } 340 341 SimpleKey sk = key[0]; 342 if (sk == null) 343 { 344 return super.hashCode(); 345 } 346 347 return sk.hashCode(); 348 } 349 350 /*** 351 * A String that may consist of one section or multiple sections 352 * separated by a colon. <br/> 353 * Each Key is represented by <code>[type N|S|D][value][:]</code>. <p/> 354 * Example: <br/> 355 * the ComboKey(StringKey("key1"), NumberKey(2)) is represented as 356 * <code><b>Skey1:N2:</b></code> 357 * 358 * @return a String representation 359 */ 360 public String toString() 361 { 362 StringBuffer sbuf = new StringBuffer(); 363 appendTo(sbuf); 364 return sbuf.toString(); 365 } 366 }

This page was automatically generated by Maven