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