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 https://support.hdfgroup.org/products/licenses.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 017import java.util.Iterator; 018import java.util.LinkedList; 019import java.util.List; 020import java.util.Queue; 021import java.util.Stack; 022import java.util.Vector; 023 024/** 025 * Group is an abstract class. Current implementing classes are the H4Group and 026 * H5Group. This class includes general information of a group object such as 027 * members of a group and common operations on groups. 028 * <p> 029 * Members of a group may include other groups, datasets or links. 030 * 031 * @version 1.1 9/4/2007 032 * @author Peter X. Cao 033 */ 034public abstract class Group extends HObject implements MetaDataContainer { 035 036 private static final long serialVersionUID = 3913174542591568052L; 037 038 /** 039 * The list of members (Groups and Datasets) of this group in memory. 040 */ 041 private List<HObject> memberList; 042 043 /** 044 * The parent group where this group is located. The parent of the root 045 * group is null. 046 */ 047 protected Group parent; 048 049 /** 050 * Total number of members of this group in file. 051 */ 052 protected int nMembersInFile; 053 054 public static final int LINK_TYPE_HARD = 0; 055 056 public static final int LINK_TYPE_SOFT = 1; 057 058 public static final int LINK_TYPE_EXTERNAL = 64; 059 060 public static final int CRT_ORDER_TRACKED = 1; 061 062 public static final int CRT_ORDER_INDEXED = 2; 063 064 065 /** 066 * Constructs an instance of the group with specific name, path and parent 067 * group. An HDF data object must have a name. The path is the group path 068 * starting from the root. The parent group is the group where this group is 069 * located. 070 * <p> 071 * For example, in H5Group(h5file, "grp", "/groups/", pgroup), "grp" is the 072 * name of the group, "/groups/" is the group path of the group, and pgroup 073 * is the group where "grp" is located. 074 * 075 * @param theFile 076 * the file containing the group. 077 * @param grpName 078 * the name of this group, e.g. "grp01". 079 * @param grpPath 080 * the full path of this group, e.g. "/groups/". 081 * @param grpParent 082 * the parent of this group. 083 */ 084 public Group(FileFormat theFile, String grpName, String grpPath, Group grpParent) { 085 this(theFile, grpName, grpPath, grpParent, null); 086 } 087 088 /** 089 * @deprecated Not for public use in the future.<br> 090 * Using {@link #Group(FileFormat, String, String, Group)} 091 * 092 * @param theFile 093 * the file containing the group. 094 * @param grpName 095 * the name of this group, e.g. "grp01". 096 * @param grpPath 097 * the full path of this group, e.g. "/groups/". 098 * @param grpParent 099 * the parent of this group. 100 * @param oid 101 * the oid of this group. 102 */ 103 @Deprecated 104 public Group(FileFormat theFile, String grpName, String grpPath, Group grpParent, long[] oid) { 105 super(theFile, grpName, grpPath, oid); 106 107 this.parent = grpParent; 108 } 109 110 /** 111 * Clears up member list and other resources in memory for the group. Since 112 * the destructor will clear memory space, the function is usually not 113 * needed. 114 */ 115 public void clear() { 116 if (memberList != null) { 117 ((Vector<HObject>) memberList).setSize(0); 118 } 119 } 120 121 /** 122 * Adds an object to the member list of this group in memory. 123 * 124 * @param object 125 * the HObject to be added to the member list. 126 */ 127 public void addToMemberList(HObject object) { 128 if (memberList == null) { 129 int size = Math.min(getNumberOfMembersInFile(), this 130 .getFileFormat().getMaxMembers()); 131 memberList = new Vector<HObject>(size + 5); 132 } 133 134 if ((object != null) && !memberList.contains(object)) { 135 memberList.add(object); 136 } 137 } 138 139 /** 140 * Removes an object from the member list of this group in memory. 141 * 142 * @param object 143 * the HObject (Group or Dataset) to be removed from the member 144 * list. 145 */ 146 public void removeFromMemberList(HObject object) { 147 if (memberList != null) { 148 memberList.remove(object); 149 } 150 } 151 152 /** 153 * Returns the list of members of this group. The list is an java.util.List 154 * containing HObjects. 155 * 156 * @return the list of members of this group. 157 */ 158 public List<HObject> getMemberList() { 159 FileFormat theFile = this.getFileFormat(); 160 161 if ((memberList == null) && (theFile != null)) { 162 int size = Math.min(getNumberOfMembersInFile(), this 163 .getFileFormat().getMaxMembers()); 164 memberList = new Vector<HObject>(size + 5); // avoid infinite loop search for groups without members 165 166 // find the memberList from the file by checking the group path and 167 // name. group may be created out of the structure tree 168 // (H4/5File.loadTree()). 169 try { 170 theFile.open(); 171 } // load the file structure; 172 catch (Exception ex) { 173 ; 174 } 175 176 HObject root = theFile.getRootObject(); 177 if (root == null) return memberList; 178 179 Iterator<HObject> it = ((Group) root).depthFirstMemberList().iterator(); 180 Group g = null; 181 Object uObj = null; 182 while (it.hasNext()) { 183 uObj = it.next(); 184 185 if (uObj instanceof Group) { 186 g = (Group) uObj; 187 if (g.getPath() != null) // add this check to get rid of null exception 188 { 189 if ((this.isRoot() && g.isRoot()) 190 || (this.getPath().equals(g.getPath()) && 191 g.getName().endsWith(this.getName()))) { 192 memberList = g.getMemberList(); 193 break; 194 } 195 } 196 } 197 } 198 } 199 200 return memberList; 201 } 202 203 /** 204 * @return the members of this Group in breadth-first order. 205 */ 206 public List<HObject> breadthFirstMemberList() { 207 Vector<HObject> members = new Vector<HObject>(); 208 Queue<HObject> queue = new LinkedList<HObject>(); 209 HObject currentObj = this; 210 211 queue.addAll(((Group) currentObj).getMemberList()); 212 213 while(!queue.isEmpty()) { 214 currentObj = queue.remove(); 215 members.add(currentObj); 216 217 if(currentObj instanceof Group && ((Group) currentObj).getNumberOfMembersInFile() > 0) { 218 queue.addAll(((Group) currentObj).getMemberList()); 219 } 220 } 221 222 return members; 223 } 224 225 /** 226 * @return the members of this Group in depth-first order. 227 */ 228 public List<HObject> depthFirstMemberList() { 229 Vector<HObject> members = new Vector<HObject>(); 230 Stack<HObject> stack = new Stack<HObject>(); 231 HObject currentObj = this; 232 233 // Push elements onto the stack in reverse order 234 List<HObject> list = ((Group) currentObj).getMemberList(); 235 for(int i = list.size() - 1; i >= 0; i--) { 236 stack.push(list.get(i)); 237 } 238 239 while(!stack.empty()) { 240 currentObj = stack.pop(); 241 members.add(currentObj); 242 243 if(currentObj instanceof Group && ((Group) currentObj).getNumberOfMembersInFile() > 0) { 244 list = ((Group) currentObj).getMemberList(); 245 for(int i = list.size() - 1; i >= 0; i--) { 246 stack.push(list.get(i)); 247 } 248 } 249 } 250 251 return members; 252 } 253 254 /** 255 * Sets the name of the group. 256 * <p> 257 * setName (String newName) changes the name of the group in memory and 258 * file. 259 * <p> 260 * setName() updates the path in memory for all the objects that are under 261 * the group with the new name. 262 * 263 * @param newName 264 * The new name of the group. 265 * 266 * @throws Exception if the name can not be set 267 */ 268 @Override 269 public void setName(String newName) throws Exception { 270 super.setName(newName); 271 272 if (memberList != null) { 273 int n = memberList.size(); 274 HObject theObj = null; 275 for (int i = 0; i < n; i++) { 276 theObj = memberList.get(i); 277 theObj.setPath(this.getPath() + newName + HObject.separator); 278 } 279 } 280 } 281 282 /** @return the parent group. */ 283 public final Group getParent() { 284 return parent; 285 } 286 287 /** 288 * Checks if it is a root group. 289 * 290 * @return true if the group is a root group; otherwise, returns false. 291 */ 292 public final boolean isRoot() { 293 return (parent == null); 294 } 295 296 /** 297 * Returns the total number of members of this group in file. 298 * 299 * Current Java applications such as HDFView cannot handle files with large 300 * numbers of objects (1,000,000 or more objects) due to JVM memory 301 * limitation. The max_members is used so that applications such as HDFView 302 * will load up to <i>max_members</i> number of objects. If the number of 303 * objects in file is larger than <i>max_members</i>, only 304 * <i>max_members</i> are loaded in memory. 305 * <p> 306 * getNumberOfMembersInFile() returns the number of objects in this group. 307 * The number of objects in memory is obtained by getMemberList().size(). 308 * 309 * @return Total number of members of this group in the file. 310 */ 311 public int getNumberOfMembersInFile() { 312 return nMembersInFile; 313 } 314 315 /** 316 * Get the HObject at the specified index in this Group's member list. 317 * @param idx The index of the HObject to get. 318 * @return The HObject at the specified index. 319 */ 320 public HObject getMember(int idx) { 321 if(memberList.size() <= 0 || idx >= memberList.size()) return null; 322 323 return memberList.get(idx); 324 } 325}