001/***************************************************************************** 002 * Copyright by The HDF Group. * 003 * Copyright by the Board of Trustees of the University of Illinois. * 004 * All rights reserved. * 005 * * 006 * This file is part of the HDF Java Products distribution. * 007 * The full copyright notice, including terms governing use, modification, * 008 * and redistribution, is contained in the files COPYING and Copyright.html. * 009 * COPYING can be found at the root of the source code distribution tree. * 010 * Or, see http://hdfgroup.org/products/hdf-java/doc/Copyright.html. * 011 * If you do not have access to either file, you may request a copy from * 012 * help@hdfgroup.org. * 013 ****************************************************************************/ 014 015package hdf.object; 016 017/** 018 * A CompoundDS is a dataset with compound datatype. 019 * <p> 020 * A compound datatype is an aggregation of one or more datatypes. Each member 021 * of a compound type has a name which is unique within that type, and a 022 * datatype of that member in a compound datum. Compound datatype can be nested, 023 * i.e. members of compound datatype can be some other compound datatype. 024 * <p> 025 * For more details on compound datatype, 026 * see <b> <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a> </b> 027 * <p> 028 * Since Java cannot handle C-structured compound data, data in compound dataset 029 * is loaded in to an Java List. Each element of the list is a data array that 030 * corresponds to a compound field. The data is read/written by compound field. 031 * <p> 032 * For example, if compound dataset "comp" has the following nested structure, 033 * and memeber datatypes 034 * 035 * <pre> 036 * comp --> m01 (int) 037 * comp --> m02 (float) 038 * comp --> nest1 --> m11 (char) 039 * comp --> nest1 --> m12 (String) 040 * comp --> nest1 --> nest2 --> m21 (long) 041 * comp --> nest1 --> nest2 --> m22 (double) 042 * </pre> 043 * 044 * The data object is an Java list of six arrays: {int[], float[], char[], 045 * Stirng[], long[] and double[]}. 046 * 047 * 048 * @version 1.1 9/4/2007 049 * @author Peter X. Cao 050 */ 051public abstract class CompoundDS extends Dataset { 052 /** 053 * 054 */ 055 private static final long serialVersionUID = -4880399929644095662L; 056 057 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CompoundDS.class); 058 059 /** 060 * A single character to separate the names of nested compound fields. An 061 * extended ASCII character, 0x95, is used to avoid common characters in 062 * compound names. 063 */ 064 public static final String separator = "\u0095"; 065 066 /** 067 * The number of members of the compound dataset. 068 */ 069 protected int numberOfMembers; 070 071 /** 072 * The names of members of the compound dataset. 073 */ 074 protected String[] memberNames; 075 076 /** 077 * Returns array containing the total number of elements of the members of 078 * compound. 079 * <p> 080 * For example, a compound dataset COMP has members of A, B and C as 081 * 082 * <pre> 083 * COMP { 084 * int A; 085 * float B[5]; 086 * double C[2][3]; 087 * } 088 * </pre> 089 * 090 * memberOrders is an integer array of {1, 5, 6} to indicate that member A 091 * has one element, member B has 5 elements, and member C has 6 elements. 092 */ 093 protected int[] memberOrders; 094 095 /** 096 * The dimension sizes of each member. 097 * <p> 098 * The i-th element of the Object[] is an integer array (int[]) that 099 * contains the dimension sizes of the i-th member. 100 */ 101 protected Object[] memberDims; 102 103 /** 104 * The datatypes of compound members. 105 */ 106 protected Datatype[] memberTypes; 107 108 /** 109 * The array to store flags to indicate if a member of compound dataset is 110 * selected for read/write. 111 * <p> 112 * If a member is selected, the read/write will perform on the member. 113 * Applications such as HDFView will only display the selected members of 114 * the compound dataset. 115 * 116 * <pre> 117 * For example, if a compound dataset has four members 118 * String[] memberNames = {"X", "Y", "Z", "TIME"}; 119 * and 120 * boolean[] isMemberSelected = {true, false, false, true}; 121 * members "X" and "TIME" are selected for read and write. 122 * </pre> 123 */ 124 protected boolean[] isMemberSelected; 125 126 /** 127 * Constructs a CompoundDS object with given file, dataset name and path. 128 * <p> 129 * The dataset object represents an existing dataset in the file. For 130 * example, new H5CompoundDS(file, "dset1", "/g0/") constructs a dataset 131 * object that corresponds to the dataset,"dset1", at group "/g0/". 132 * <p> 133 * This object is usually constructed at FileFormat.open(), which loads the 134 * file structure and object informatoin into tree structure (TreeNode). It 135 * is rarely used elsewhere. 136 * 137 * @param theFile 138 * the file that contains the dataset. 139 * @param name 140 * the name of the CompoundDS, e.g. "compDS". 141 * @param path 142 * the path of the CompoundDS, e.g. "/g1". 143 */ 144 public CompoundDS(FileFormat theFile, String name, String path) { 145 this(theFile, name, path, null); 146 } 147 148 /** 149 * @deprecated Not for public use in the future.<br> 150 * Using {@link #CompoundDS(FileFormat, String, String)} 151 * 152 * @param theFile 153 * the file that contains the dataset. 154 * @param name 155 * the name of the CompoundDS, e.g. "compDS". 156 * @param path 157 * the path of the CompoundDS, e.g. "/g1". 158 * @param oid 159 * the oid of the CompoundDS. 160 */ 161 @Deprecated 162 public CompoundDS(FileFormat theFile, String name, String path, long[] oid) { 163 super(theFile, name, path, oid); 164 165 numberOfMembers = 0; 166 memberNames = null; 167 isMemberSelected = null; 168 memberTypes = null; 169 } 170 171 /** 172 * Returns the number of members of the compound dataset. 173 * 174 * @return the number of members of the compound dataset. 175 */ 176 public final int getMemberCount() { 177 return numberOfMembers; 178 } 179 180 /** 181 * Returns the number of selected members of the compound dataset. 182 * 183 * Selected members are the compound fields which are selected for 184 * read/write. 185 * <p> 186 * For example, in a compound datatype of {int A, float B, char[] C}, users 187 * can choose to retrieve only {A, C} from dataset. In this case, 188 * getSelectedMemberCount() returns two. 189 * 190 * @return the number of selected members. 191 */ 192 public final int getSelectedMemberCount() { 193 int count = 0; 194 195 if (isMemberSelected != null) { 196 for (int i = 0; i < isMemberSelected.length; i++) { 197 if (isMemberSelected[i]) { 198 count++; 199 } 200 } 201 } 202 log.trace("count of selected members={}", count); 203 204 return count; 205 } 206 207 /** 208 * Returns the names of the members of the compound dataset. The names of 209 * compound members are stored in an array of Strings. 210 * <p> 211 * For example, for a compound datatype of {int A, float B, char[] C} 212 * getMemberNames() returns ["A", "B", "C"}. 213 * 214 * @return the names of compound members. 215 */ 216 public final String[] getMemberNames() { 217 return memberNames; 218 } 219 220 /** 221 * Checks if a member of compound is selected for read/write. 222 * 223 * @param idx 224 * the index of compound member. 225 * 226 * @return true if the i-th memeber is selected; otherwise returns false. 227 */ 228 public final boolean isMemberSelected(int idx) { 229 if ((isMemberSelected != null) && (isMemberSelected.length > idx)) { 230 return isMemberSelected[idx]; 231 } 232 else { 233 return false; 234 } 235 } 236 237 /** 238 * Selects the i-th member for read/write. 239 * 240 * @param idx 241 * the index of compound member. 242 */ 243 public final void selectMember(int idx) { 244 if ((isMemberSelected != null) && (isMemberSelected.length > idx)) { 245 isMemberSelected[idx] = true; 246 } 247 } 248 249 /** 250 * Selects/deselects all members. 251 * 252 * @param isSelected 253 * The indicator to select or deselect all members. If true, all 254 * members are selected for read/write. If false, no member is 255 * selected for read/write. 256 */ 257 public final void setMemberSelection(boolean isSelected) { 258 if (isMemberSelected == null) { 259 return; 260 } 261 262 for (int i = 0; i < isMemberSelected.length; i++) { 263 isMemberSelected[i] = isSelected; 264 } 265 } 266 267 /** 268 * Returns array containing the total number of elements of the members of 269 * compound. 270 * <p> 271 * For example, a compound dataset COMP has members of A, B and C as 272 * 273 * <pre> 274 * COMP { 275 * int A; 276 * float B[5]; 277 * double C[2][3]; 278 * } 279 * </pre> 280 * 281 * getMemberOrders() will return an integer array of {1, 5, 6} to indicate 282 * that member A has one element, member B has 5 elements, and member C has 283 * 6 elements. 284 * 285 * @return the array containing the total number of elements of the members 286 * of compound. 287 */ 288 public final int[] getMemberOrders() { 289 return memberOrders; 290 } 291 292 /** 293 * Returns array containing the total number of elements of the elected 294 * members of compound. 295 * 296 * <p> 297 * For example, a compound dataset COMP has members of A, B and C as 298 * 299 * <pre> 300 * COMP { 301 * int A; 302 * float B[5]; 303 * double C[2][3]; 304 * } 305 * </pre> 306 * 307 * If A and B are selected, getSelectedMemberOrders() returns an array of 308 * {1, 5} 309 * 310 * @return array containing the total number of elements of the selected 311 * members of compound. 312 */ 313 public final int[] getSelectedMemberOrders() { 314 if (isMemberSelected == null) { 315 return memberOrders; 316 } 317 318 int idx = 0; 319 int[] orders = new int[getSelectedMemberCount()]; 320 for (int i = 0; i < isMemberSelected.length; i++) { 321 if (isMemberSelected[i]) { 322 orders[idx++] = memberOrders[i]; 323 } 324 } 325 326 return orders; 327 } 328 329 /** 330 * Returns the dimension sizes of of the i-th member. 331 * <p> 332 * For example, a compound dataset COMP has members of A, B and C as 333 * 334 * <pre> 335 * COMP { 336 * int A; 337 * float B[5]; 338 * double C[2][3]; 339 * } 340 * </pre> 341 * 342 * getMemberDims(2) returns an array of {2, 3}, while getMemberDims(1) 343 * returns an array of {5}, getMemberDims(0) returns null. 344 * 345 * @param i the i-th member 346 * 347 * @return the dimension sizes of of the i-th member, null if the compound 348 * member is not an array. 349 */ 350 public final int[] getMemberDims(int i) { 351 if (memberDims == null) { 352 return null; 353 } 354 return (int[]) memberDims[i]; 355 } 356 357 /** 358 * Returns an array of datatype objects of compound members. 359 * <p> 360 * Each member of a compound dataset has its own datatype. The datatype of a 361 * member can be atomic or other compound datatype (nested compound). 362 * Sub-classes set up the datatype objects at init(). 363 * <p> 364 * 365 * @return the array of datatype objects of the compound members. 366 */ 367 public final Datatype[] getMemberTypes() { 368 return memberTypes; 369 } 370 371 /** 372 * Returns an array of datatype objects of selected compound members. 373 * 374 * @return an array of datatype objects of selected compound members. 375 */ 376 public final Datatype[] getSelectedMemberTypes() { 377 if (isMemberSelected == null) { 378 return memberTypes; 379 } 380 381 int idx = 0; 382 Datatype[] types = new Datatype[getSelectedMemberCount()]; 383 for (int i = 0; i < isMemberSelected.length; i++) { 384 if (isMemberSelected[i]) { 385 types[idx++] = memberTypes[i]; 386 } 387 } 388 389 return types; 390 } 391 392 /** 393 * @deprecated Not implemented for compound dataset. 394 */ 395 @Deprecated 396 @Override 397 public Dataset copy(Group pgroup, String name, long[] dims, Object data) 398 throws Exception { 399 throw new UnsupportedOperationException( 400 "Writing a subset of a compound dataset to a new dataset is not implemented."); 401 } 402 403}