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