Coverage report

  %line %branch
org.apache.torque.om.ComboKey
78% 
88% 

 1  
 package org.apache.torque.om;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.util.ArrayList;
 23  
 import org.apache.commons.lang.ObjectUtils;
 24  
 
 25  
 /**
 26  
  * This class can be used as an ObjectKey to uniquely identify an
 27  
  * object within an application where the key consists of multiple
 28  
  * entities (such a String[] representing a multi-column primary key).
 29  
  *
 30  
  * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
 31  
  * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
 32  
  * @author <a href="mailto:drfish@cox.net">J. Russell Smyth</a>
 33  
  * @version $Id: ComboKey.java 473821 2006-11-11 22:37:25Z tv $
 34  
  */
 35  
 public class ComboKey extends ObjectKey
 36  
 {
 37  
     /**
 38  
      * Serial version
 39  
      */
 40  
     private static final long serialVersionUID = -264927663211141894L;
 41  
 
 42  
     // might want to shift these to TR.props
 43  
 
 44  
     /** The single character used to separate key values in a string. */
 45  
     public static final char SEPARATOR = ':';
 46  
 
 47  
     /** The single character used to separate key values in a string. */
 48  
     public static final String SEPARATOR_STRING = ":";
 49  
 
 50  
     /** The array of the keys */
 51  
     private SimpleKey[] key;
 52  
 
 53  
     /**
 54  
      * Creates an ComboKey whose internal representation will be
 55  
      * set later, through a set method
 56  
      */
 57  
     public ComboKey()
 58  0
     {
 59  0
     }
 60  
 
 61  
     /**
 62  
      * Creates a ComboKey whose internal representation is an
 63  
      * array of SimpleKeys.
 64  
      *
 65  
      * @param keys the key values
 66  
      */
 67  48
     public ComboKey(SimpleKey[] keys)
 68  1056
     {
 69  1104
         setValue(keys);
 70  1104
     }
 71  
 
 72  
     /**
 73  
      * Sets the internal representation to a String array.
 74  
      *
 75  
      * @param keys the key values
 76  
      * @see #toString()
 77  
      */
 78  3
     public ComboKey(String keys)
 79  66
     {
 80  69
         setValue(keys);
 81  69
     }
 82  
 
 83  
     /**
 84  
      * Sets the internal representation using a SimpleKey array.
 85  
      *
 86  
      * @param keys the key values
 87  
      */
 88  
     public void setValue(SimpleKey[] keys)
 89  
     {
 90  1104
         this.key = keys;
 91  1104
     }
 92  
 
 93  
     /**
 94  
      * Sets the internal representation using a String of the
 95  
      * form produced by the toString method.
 96  
      *
 97  
      * @param keys the key values
 98  
      */
 99  
     public void setValue(String keys)
 100  
     {
 101  69
         int startPtr = 0;
 102  69
         int indexOfSep = keys.indexOf(SEPARATOR);
 103  69
         ArrayList tmpKeys = new ArrayList();
 104  233
         while (indexOfSep != -1)
 105  
         {
 106  161
             if (indexOfSep == startPtr)
 107  
             {
 108  23
                 tmpKeys.add(null);
 109  22
             }
 110  
             else
 111  
             {
 112  138
                 char keyType = keys.class="keyword">charAt(startPtr);
 113  138
                 String keyString = keys.substring(startPtr + 1, indexOfSep);
 114  
 
 115  138
                 SimpleKey newKey = null;
 116  138
                 switch(keyType)
 117  
                 {
 118  
                     case 'N':
 119  23
                         newKey = new NumberKey(keyString);
 120  23
                         break;
 121  
                     case 'S':
 122  92
                         newKey = new StringKey(keyString);
 123  92
                         break;
 124  
                     case 'D':
 125  
                         try
 126  
                         {
 127  23
                             newKey = new DateKey(keyString);
 128  
                         }
 129  0
                         catch (NumberFormatException nfe)
 130  
                         {
 131  0
                             newKey = new DateKey();
 132  22
                         }
 133  0
                         break;
 134  
                     default:
 135  
                         // unextepcted key type
 136  
                 }
 137  138
                 tmpKeys.add(newKey);
 138  
             }
 139  161
             startPtr = indexOfSep + 1;
 140  161
             indexOfSep = keys.indexOf(SEPARATOR, startPtr);
 141  154
         }
 142  
 
 143  69
         this.key = new SimpleKey[tmpKeys.size()];
 144  230
         for (int i = 0; i < this.key.length; i++)
 145  
         {
 146  161
             this.key[i] = (SimpleKey) tmpKeys.get(i);
 147  
         }
 148  69
     }
 149  
 
 150  
     /**
 151  
      * Sets the internal representation using a ComboKey.
 152  
      *
 153  
      * @param keys the key values
 154  
      */
 155  
     public void setValue(ComboKey keys)
 156  
     {
 157  0
         setValue((SimpleKey[]) keys.getValue());
 158  0
     }
 159  
 
 160  
     /**
 161  
      * Get the underlying object.
 162  
      *
 163  
      * @return the underlying object
 164  
      */
 165  
     public Object getValue()
 166  
     {
 167  184
         return key;
 168  
     }
 169  
 
 170  
     /**
 171  
      * This method will return true if the conditions for a looseEquals
 172  
      * are met and in addition no parts of the keys are null.
 173  
      *
 174  
      * @param keyObj the comparison value
 175  
      * @return whether the two objects are equal
 176  
      */
 177  
     public boolean equals(Object keyObj)
 178  
     {
 179  161
         boolean isEqual = false;
 180  
 
 181  161
         if (key != null)
 182  
         {
 183  
             // check that all keys are not null
 184  161
             isEqual = true;
 185  161
             SimpleKey[] keys = key;
 186  506
             for (int i = 0; i < keys.length && isEqual; i++)
 187  
             {
 188  345
                 isEqual &= keys[i] != null && keys[i].getValue() != class="keyword">null;
 189  
             }
 190  
 
 191  161
             isEqual &= looseEquals(keyObj);
 192  
         }
 193  
 
 194  161
         return isEqual;
 195  
     }
 196  
 
 197  
     /**
 198  
      * keyObj is equal to this ComboKey if keyObj is a ComboKey, String,
 199  
      * ObjectKey[], or String[] that contains the same information this key
 200  
      * contains.
 201  
      * For example A String[] might be equal to this key, if this key was
 202  
      * instantiated with a String[] and the arrays contain equal Strings.
 203  
      * Another example, would be if keyObj is an ComboKey that was
 204  
      * instantiated with a ObjectKey[] and this ComboKey was instantiated with
 205  
      * a String[], but the ObjectKeys in the ObjectKey[] were instantiated
 206  
      * with Strings that equal the Strings in this KeyObject's String[]
 207  
      * This method is not as strict as the equals method which does not
 208  
      * allow any null keys parts, while the internal key may not be null
 209  
      * portions may be, and the two object will be considered equal if
 210  
      * their null portions match.
 211  
      *
 212  
      * @param keyObj the comparison value
 213  
      * @return whether the two objects are equal
 214  
      */
 215  
     public boolean looseEquals(Object keyObj)
 216  
     {
 217  207
         boolean isEqual = false;
 218  
 
 219  207
         if (key != null)
 220  
         {
 221  
             // Checks  a compound key (ObjectKey[] or String[]
 222  
             // based) with the delimited String created by the
 223  
             // toString() method.  Slightly expensive, but should be less
 224  
             // than parsing the String into its constituents.
 225  207
             if (keyObj instanceof String)
 226  
             {
 227  0
                 isEqual = toString().equals(keyObj);
 228  0
             }
 229  
             // check against a ObjectKey. Two keys are equal, if their
 230  
             // internal keys equivalent.
 231  207
             else if (keyObj instanceof ComboKey)
 232  
             {
 233  184
                 SimpleKey[] obj = (SimpleKey[])
 234  8
                     ((ComboKey) keyObj).getValue();
 235  
 
 236  184
                 SimpleKey[] keys1 = key;
 237  184
                 SimpleKey[] keys2 = obj;
 238  184
                 isEqual = keys1.length == keys2.length;
 239  575
                 for (int i = 0; i < keys1.length && isEqual; i++)
 240  
                 {
 241  391
                     isEqual &= ObjectUtils.equals(keys1[i], keys2[i]);
 242  
                 }
 243  176
             }
 244  23
             else if (keyObj instanceof SimpleKey[])
 245  
             {
 246  0
                 SimpleKey[] keys1 = key;
 247  0
                 SimpleKey[] keys2 = (SimpleKey[]) keyObj;
 248  0
                 isEqual = keys1.length == keys2.length;
 249  0
                 for (int i = 0; i < keys1.length && isEqual; i++)
 250  
                 {
 251  0
                     isEqual &= ObjectUtils.equals(keys1[i], keys2[i]);
 252  
                 }
 253  
             }
 254  
         }
 255  207
         return isEqual;
 256  
     }
 257  
 
 258  
     /**
 259  
      *
 260  
      * @param sb the StringBuffer to append
 261  
      * @see #toString()
 262  
      */
 263  
     public void appendTo(StringBuffer sb)
 264  
     {
 265  115
         if (key != null)
 266  
         {
 267  115
             SimpleKey[] keys = key;
 268  391
             for (int i = 0; i < keys.length; i++)
 269  
             {
 270  276
                 if (keys[i] != null)
 271  
                 {
 272  230
                     if (keys[i] instanceof StringKey)
 273  
                     {
 274  161
                         sb.append("S");
 275  154
                     }
 276  69
                     else if (keys[i] instanceof NumberKey)
 277  
                     {
 278  46
                         sb.append("N");
 279  44
                     }
 280  23
                     else if (keys[i] instanceof DateKey)
 281  
                     {
 282  23
                         sb.append("D");
 283  22
                     }
 284  
                     else
 285  
                     {
 286  
                         // unknown type
 287  0
                         sb.append("U");
 288  
                     }
 289  230
                     keys[i].appendTo(sb);
 290  
                 }
 291  
                 // MUST BE ADDED AFTER EACH KEY, IN CASE OF NULL KEY!
 292  276
                 sb.append(SEPARATOR);
 293  
             }
 294  
         }
 295  115
     }
 296  
 
 297  
     /**
 298  
      * if the underlying key array is not null and the first element is
 299  
      * not null this method returns the hashcode of the first element
 300  
      * in the key.  Otherwise calls ObjectKey.hashCode()
 301  
      *
 302  
      * @return an <code>int</code> value
 303  
      */
 304  
     public int hashCode()
 305  
     {
 306  0
         if (key == null)
 307  
         {
 308  0
             return super.hashCode();
 309  
         }
 310  
 
 311  0
         SimpleKey sk = key[0];
 312  0
         if (sk == null)
 313  
         {
 314  0
             return super.hashCode();
 315  
         }
 316  
 
 317  0
         return sk.hashCode();
 318  
     }
 319  
 
 320  
     /**
 321  
      * A String that may consist of one section or multiple sections
 322  
      * separated by a colon. <br/>
 323  
      * Each Key is represented by <code>[type N|S|D][value][:]</code>. <p/>
 324  
      * Example: <br/>
 325  
      * the ComboKey(StringKey("key1"), NumberKey(2)) is represented as
 326  
      * <code><b>Skey1:N2:</b></code>
 327  
      *
 328  
      * @return a String representation
 329  
      */
 330  
     public String toString()
 331  
     {
 332  92
         StringBuffer sbuf = new StringBuffer();
 333  92
         appendTo(sbuf);
 334  92
         return sbuf.toString();
 335  
     }
 336  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.