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