001/** 002 * DataCase -- A collection of parameters that make up a single case in a data set. 003 * 004 * Copyright (C) 2003-2025, by Joseph A. Huwaldt. All rights reserved. 005 * 006 * This library is free software; you can redistribute it and/or modify it under the terms 007 * of the GNU Lesser General Public License as published by the Free Software Foundation; 008 * either version 2 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, but WITHOUT ANY 011 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 012 * PARTICULAR PURPOSE. See the GNU Library General Public License for more details. 013 * 014 * You should have received a copy of the GNU Lesser General Public License along with 015 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - 016 * Suite 330, Boston, MA 02111-1307, USA. Or visit: http://www.gnu.org/licenses/lgpl.html 017 */ 018package jahuwaldt.js.datareader; 019 020import java.util.Collection; 021import java.util.List; 022import java.util.ListIterator; 023import javolution.context.ObjectFactory; 024import javolution.util.FastTable; 025 026/** 027 * Defines a data element called a case. A case is a collection of 028 * {@link DataParam parameters} or variables that make up a single run or test case. Any 029 * number of parameters may be added to a case, but all array type parameters in a single 030 * case must have the same number of elements. 031 * 032 * <p> Modified by: Joseph A. Huwaldt </p> 033 * 034 * @author Joseph A. Huwaldt, Date: March 5, 2003 035 * @version February 23, 2025 036 */ 037public final class DataCase extends DataElementList<DataParam> { 038 039 /** 040 * Return a case made up of any {@link DataParam parameters} found in the specified 041 * collection. Any objects that are not {@link DataParam} objects in the specified 042 * collection will be ignored. 043 * 044 * @param name The name to be assigned to this case (may not be <code>null</code>). 045 * @param params A collection that contains a set of parameters. 046 * @return A new case made up of any DataParam objects found in the specified collection. 047 * @throws ArrayIndexOutOfBoundsException if an array added to this case has a 048 * different number of elements than an array already in this case. 049 */ 050 public static DataCase valueOf(CharSequence name, Collection<?> params) throws ArrayIndexOutOfBoundsException { 051 052 DataCase aCase = DataCase.newInstance(name); 053 054 // Determine the size allowed for arrays in this case. 055 int allowedSize = 0; 056 057 for (Object obj : params) { 058 if (obj instanceof ArrayParam) { 059 060 // Check size of arrays for consistency before adding! 061 ArrayParam newArray = (ArrayParam)obj; 062 int size = newArray.size(); 063 if (allowedSize > 0) 064 if (size != allowedSize) { 065 DataCase.recycle(aCase); 066 throw new ArrayIndexOutOfBoundsException(RESOURCES.getString("arrSizeErr")); 067 } else 068 allowedSize = size; 069 070 aCase.add((DataParam)obj); 071 072 } else if (obj instanceof DataParam) { 073 aCase.add((DataParam)obj); 074 } 075 } 076 077 return aCase; 078 } 079 080 /** 081 * Replaces the parameter at the specified position in this case with the specified 082 * parameter. Null elements are ignored. 083 * 084 * @param index The index of the parameter to replace. 085 * @param element The parameter to be stored a the specified position. 086 * @return The parameter previously at the specified position in this case. 087 * @throws ArrayIndexOutOfBoundsException if an array added to this case has a 088 * different number of elements than an array already in this case. 089 */ 090 @Override 091 public DataParam set(int index, DataParam element) { 092 if (element == null) 093 return null; 094 095 if (element instanceof ArrayParam) { 096 // Determine the size allowed for arrays in this case. 097 int allowedSize = getAllowedArraySize(); 098 099 if (allowedSize > 0 && ((ArrayParam)element).size() != allowedSize) 100 throw new ArrayIndexOutOfBoundsException(RESOURCES.getString("arrSizeErr")); 101 } 102 103 return super.set(index, element); 104 } 105 106 /** 107 * Inserts the specified parameter at the specified position in this case. Shifts the 108 * parameter currently at that position (if any) and any subsequent parameters to the 109 * right (adds one to their indices). Null elements are ignored. 110 * 111 * @param index Index at which the specified parameter is to be inserted. 112 * @param element DataParam to be inserted. 113 * @throws ClassCastException if the specified element is not a DataParam type object. 114 * @throws ArrayIndexOutOfBoundsException if an array added to this case has a 115 * different number of elements than an array already in this case. 116 */ 117 @Override 118 public void add(int index, DataParam element) { 119 if (element == null) 120 return; 121 122 if (element instanceof ArrayParam) { 123 // Determine the size allowed for arrays in this case. 124 int allowedSize = getAllowedArraySize(); 125 126 if (allowedSize > 0 && ((ArrayParam)element).size() != allowedSize) 127 throw new ArrayIndexOutOfBoundsException(RESOURCES.getString("arrSizeErr")); 128 } 129 130 super.add(index, element); 131 } 132 133 /** 134 * Appends the specified list of parameters to the end of this case. Null elements are 135 * ignored. 136 * 137 * @param elements List of parameters to be inserted. 138 * @throws ArrayIndexOutOfBoundsException if an array added to this case has a 139 * different number of elements than an array already in this case. 140 */ 141 @Override 142 public void addAll(DataParam[] elements) { 143 if (elements != null) { 144 int size = elements.length; 145 for (int i = 0; i < size; ++i) { 146 DataParam param = elements[i]; 147 this.add(param); 148 } 149 } 150 } 151 152 /** 153 * Inserts the specified list of parameters at the specified position in this case. 154 * Shifts the parameter currently at that position (if any) and any subsequent 155 * parameters to the right (adds one to their indices) until all the parameters have 156 * been added. Null elements are ignored. 157 * 158 * @param index Index at which the specified list of parameters is to be inserted. 159 * @param elements List of parameters to be inserted. 160 * @throws ArrayIndexOutOfBoundsException if an array added to this case has a 161 * different number of elements than an array already in this case. 162 */ 163 @Override 164 public void addAll(int index, DataParam[] elements) { 165 if (elements != null) { 166 167 for (DataParam param : elements) { 168 this.add(index, param); 169 ++index; 170 } 171 172 } 173 } 174 175 /** 176 * Returns the size of any array in this case (since all arrays must have the same 177 * number of elements). If there are no arrays in this case, zero is returned. 178 * 179 * @return The size of any array in this case. 180 */ 181 public int getAllowedArraySize() { 182 int size = 0; 183 184 for (DataParam param : this) { 185 if (param instanceof ArrayParam) { 186 size = ((ArrayParam)param).size(); 187 break; 188 } 189 } 190 191 return size; 192 } 193 194 /** 195 * Returns a list of all the Text/Note objects in this case. If there are no text 196 * parameters, null is returned. 197 * 198 * @return A list of all the Text/Note objects in this case. 199 */ 200 public List<TextParam> getAllText() { 201 202 List<TextParam> list = FastTable.newInstance(); 203 204 // Loop over all the parameters and collect the text parameters. 205 for (DataParam param : this) { 206 if (param instanceof TextParam) 207 list.add((TextParam)param); 208 } 209 210 return list; 211 } 212 213 /** 214 * Removes all TextParam objects from this case. 215 */ 216 public void clearAllText() { 217 218 // Loop over all the parameters and delete text parameters. 219 for (ListIterator<DataParam> i = listIterator(); i.hasNext();) { 220 Object obj = i.next(); 221 if (obj instanceof TextParam) 222 i.remove(); 223 } 224 } 225 226 /** 227 * Returns a list of all the {@link ScalarParam} objects in this case. If there are no scalar 228 * parameters, null is returned. 229 * 230 * @return A list of all the ScalarParam objects in this case. 231 */ 232 public List<ScalarParam> getAllScalars() { 233 234 List<ScalarParam> list = FastTable.newInstance(); 235 236 // Loop over all the parameters and collect the scalar parameters. 237 for (DataParam param : this) { 238 if (param instanceof ScalarParam) 239 list.add((ScalarParam)param); 240 } 241 242 return list; 243 } 244 245 /** 246 * Returns a list of all the {@link ArrayParam} objects in this case. If there are no array 247 * parameters, null is returned. 248 * 249 * @return A list of all the ArrayParam objects in this case. 250 */ 251 public List<ArrayParam> getAllArrays() { 252 253 List<ArrayParam> list = FastTable.newInstance(); 254 255 // Loop over all the parameters and collect the array parameters. 256 for (DataParam param : this) { 257 if (param instanceof ArrayParam) 258 list.add((ArrayParam)param); 259 } 260 261 return list; 262 } 263 264 ////////////////////// 265 // Factory Creation // 266 ////////////////////// 267 public static DataCase newInstance(CharSequence name) { 268 DataCase o = FACTORY.object(); 269 try { 270 o.setName(name); 271 } catch (NullPointerException e) { 272 FACTORY.recycle(o); 273 throw e; 274 } 275 return o; 276 } 277 private static final ObjectFactory<DataCase> FACTORY = new ObjectFactory<DataCase>() { 278 @Override 279 protected DataCase create() { 280 return new DataCase(); 281 } 282 283 @Override 284 protected void cleanup(DataCase obj) { 285 obj.reset(); 286 } 287 }; 288 289 /** 290 * Recycles a case instance immediately (on the stack when executing in a 291 * StackContext). 292 * 293 * @param instance The case instance to recycle. 294 */ 295 public static void recycle(DataCase instance) { 296 FACTORY.recycle(instance); 297 } 298 299 /** 300 * Do not allow the default constructor to be used. 301 */ 302 private DataCase() { } 303}