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 * <p>
030 * 
031 * @version 1.1 9/4/2007
032 * @author Peter X. Cao
033 */
034public abstract class Group extends HObject {
035
036    /**
037     * 
038     */
039    private static final long serialVersionUID = 3913174542591568052L;
040
041    /**
042     * The list of members (Groups and Datasets) of this group in memory.
043     */
044    private List<HObject> memberList;
045
046    /**
047     * The parent group where this group is located. The parent of the root
048     * group is null.
049     */
050    protected Group parent;
051
052    /**
053     * Total number of (Groups and Datasets) of this group in file.
054     */
055    protected int nMembersInFile;
056    
057    public static final int LINK_TYPE_HARD = 0;
058    
059    public static final int LINK_TYPE_SOFT = 1;
060    
061    public static final int LINK_TYPE_EXTERNAL = 64;
062    
063    public static final int CRT_ORDER_TRACKED = 1;
064    
065    public static final int CRT_ORDER_INDEXED = 2;
066    
067
068    /**
069     * Constructs an instance of the group with specific name, path and parent
070     * group. An HDF data object must have a name. The path is the group path
071     * starting from the root. The parent group is the group where this group is
072     * located.
073     * <p>
074     * For example, in H5Group(h5file, "grp", "/groups/", pgroup), "grp" is the
075     * name of the group, "/groups/" is the group path of the group, and pgroup
076     * the group where "grp" is located.
077     * 
078     * @param theFile
079     *            the file which containing the group.
080     * @param name
081     *            the name of this group, e.g. "grp01".
082     * @param path
083     *            the full path of this group, e.g. "/groups/".
084     * @param parent
085     *            the parent of this group.
086     */
087    public Group(FileFormat theFile, String name, String path, Group parent) {
088        this(theFile, name, path, parent, null);
089    }
090
091    /**
092     * @deprecated Not for public use in the future.<br>
093     *             Using {@link #Group(FileFormat, String, String, Group)}
094     */
095    @Deprecated
096    public Group(FileFormat theFile, String name, String path, Group parent,
097            long[] oid) {
098        super(theFile, name, path, oid);
099
100        this.parent = parent;
101    }
102
103    /**
104     * Clears up member list and other resources in memory for the group. Since
105     * the destructor will clear memory space, the function is usually not
106     * needed.
107     */
108    public void clear() {
109        if (memberList != null) {
110            ((Vector<HObject>) memberList).setSize(0);
111        }
112    }
113
114    /**
115     * Adds an object to the member list of this group in memory.
116     * <p>
117     * 
118     * @param object
119     *            the HObject (Group or Dataset) to be added to the member list.
120     */
121    public void addToMemberList(HObject object) {
122        if (memberList == null) {
123            int size = Math.min(getNumberOfMembersInFile(), this
124                    .getFileFormat().getMaxMembers());
125            memberList = new Vector<HObject>(size + 5);
126        }
127
128        if ((object != null) && !memberList.contains(object)) {
129            memberList.add(object);
130        }
131    }
132
133    /**
134     * Removes an object from the member list of this group in memory.
135     * <p>
136     * 
137     * @param object
138     *            the HObject (Group or Dataset) to be removed from the member
139     *            list.
140     */
141    public void removeFromMemberList(HObject object) {
142        if (memberList != null) {
143            memberList.remove(object);
144        }
145    }
146
147    /**
148     * Returns the list of members of this group. The list is an java.awt.List
149     * containing Groups and Datasets.
150     * 
151     * @return the list of members of this group.
152     */
153    public List<HObject> getMemberList() {
154        FileFormat theFile = this.getFileFormat();
155        String thePath = this.getPath();
156        String theName = this.getName();
157
158        if ((memberList == null) && (theFile != null)) {
159            int size = Math.min(getNumberOfMembersInFile(), this
160                    .getFileFormat().getMaxMembers());
161            memberList = new Vector<HObject>(size + 5); // avoid infinite loop search for
162                                               // groups without member
163
164            // find the memberList from the file by check the group path and
165            // name
166            // 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
176                    .getRootNode();
177
178            if (root == null) {
179                return memberList;
180            }
181
182            Enumeration<?> emu = root.depthFirstEnumeration();
183
184            Group g = null;
185            Object uObj = null;
186            while (emu.hasMoreElements()) {
187                uObj = ((DefaultMutableTreeNode) emu.nextElement())
188                        .getUserObject();
189                if (uObj instanceof Group) {
190                    g = (Group) uObj;
191                    if (g.getPath() != null) // add this check to get rid of
192                                             // null exception
193                    {
194                        if ((this.isRoot() && g.isRoot())
195                                || (thePath.equals(g.getPath()) && g.getName()
196                                        .endsWith(theName))) {
197                            memberList = g.getMemberList();
198                            break;
199                        }
200                    }
201                }
202            }
203        }
204
205        return memberList;
206    }
207
208    /**
209     * Sets the name of the group.
210     * <p>
211     * setName (String newName) changes the name of the group in memory and
212     * file.
213     * <p>
214     * setName() updates the path in memory for all the objects that are under
215     * the group with the new name.
216     * 
217     * @param newName
218     *            The new name of the group.
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    /** Returns 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 application 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}