/* objectList.java This class is used to keep track of a list of objects from the server, storing various pieces of information about the objects, including their expiration/removal/inactive status, their current state in the client, and more. Created: 6 February 1998 Module By: Jonathan Abbey, jonabbey@arlut.utexas.edu ----------------------------------------------------------------------- Ganymede Directory Management System Copyright (C) 1996 - 2013 The University of Texas at Austin Ganymede is a registered trademark of The University of Texas at Austin Contact information Author Email: ganymede_author@arlut.utexas.edu Email mailing list: ganymede@arlut.utexas.edu US Mail: Computer Science Division Applied Research Laboratories The University of Texas at Austin PO Box 8029, Austin TX 78713-8029 Telephone: (512) 835-3200 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package arlut.csd.ganymede.client; import java.util.Comparator; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import arlut.csd.JDataComponent.listHandle; import arlut.csd.Util.VecQuickSort; import arlut.csd.Util.VecSortInsert; import arlut.csd.ganymede.common.Invid; import arlut.csd.ganymede.common.ObjectHandle; import arlut.csd.ganymede.common.QueryResult; /*------------------------------------------------------------------------------ class objectList ------------------------------------------------------------------------------*/ /** * <p>This class is used to keep track of a list of {@link * arlut.csd.ganymede.common.ObjectHandle ObjectHandle} objects from * the server, storing various pieces of information about the * objects, including their expiration/removal/inactive status, their * current label, and more.</p> * * @author Jonathan Abbey */ public class objectList { final static boolean debug = false; static Comparator comparator = new Comparator() { public int compare(Object o_a, Object o_b) { ObjectHandle a, b; a = (ObjectHandle) o_a; b = (ObjectHandle) o_b; int comp = 0; comp = a.getLabel().compareToIgnoreCase(b.getLabel()); if (comp < 0) { return -1; } else if (comp > 0) { return 1; } else { return 0; } } }; VecSortInsert inserter; private Vector<ObjectHandle> handles; boolean sorted = false; private Vector<ObjectHandle> activeHandles; private Hashtable<Invid, ObjectHandle> invids; boolean activeSorted = false; boolean containsNonEditable = false; /* -- */ public objectList(QueryResult result) { ObjectHandle handle; /* -- */ invids = new Hashtable<Invid, ObjectHandle>(); if (result == null) { handles = new Vector<ObjectHandle>(); } else { handles = result.getHandles(); // pre-sorted } sorted = true; activeHandles = (Vector<ObjectHandle>) handles.clone(); // quickly dup the vector of handles activeSorted = true; // now, count down from top of activeHandles vector, removing // any inactive objects for (int i = activeHandles.size() - 1; i >= 0; i--) { handle = activeHandles.get(i); invids.put(handle.getInvid(), handle); if (!handle.isEditable()) { containsNonEditable = true; } if (handle.isInactive()) { activeHandles.remove(i); if (debug) { System.err.println("objectList constructor: handle " + handle.debugDump() + " is inactive"); } } else if (debug) { System.err.println("objectList constructor: handle " + handle.debugDump() + " is not inactive"); } } // create inserter = new VecSortInsert(comparator); } /** * This method returns true if this list contains any non-editable * handles. */ public boolean containsNonEditable() { return containsNonEditable; } /** * This method is used to augment an object list with non-editables. */ public synchronized void augmentListWithNonEditables(QueryResult result) { if (containsNonEditable) { throw new IllegalArgumentException("already contains non-editables"); } if (result == null) { return; } for (ObjectHandle handle: result.getHandles()) { // we only want to add a handle if we don't have the // invid in place already if (getObjectHandle(handle.getInvid()) == null) { if (!handle.isEditable()) { containsNonEditable = true; } addObjectHandle(handle); } } } /** * <p>This method returns a sorted Vector of listHandles. The * vector is essentially a read-out of the current state of the * objectList, and will not track any future changes to this * objectList.</p> * * @param includeInactives if false, the list returned will not * include entries for any inactive objects */ public Vector<listHandle> getListHandles(boolean includeInactives) { return getListHandles(includeInactives, false); } /** * <p>This method returns a sorted Vector of listHandles. The * vector is essentially a read-out of the current state of the * objectList, and will not track any future changes to this * objectList.</p> * * @param includeInactives if false, the list returned will not * include entries for any inactive objects * * @param includeNonEditables if false, the list returned will not * include entries for any non-editable objects */ public synchronized Vector<listHandle> getListHandles(boolean includeInactives, boolean includeNonEditables) { Vector<listHandle> results = null; /* -- */ if (includeInactives) { results = new Vector<listHandle>(handles.size()); for (ObjectHandle handle: handles) { if (includeNonEditables || handle.isEditable()) { results.add(handle.getListHandle()); } } } else { results = new Vector<listHandle>(activeHandles.size()); for (ObjectHandle handle: activeHandles) { if (includeNonEditables || handle.isEditable()) { results.add(handle.getListHandle()); } } } return results; } /** * <p>This method returns a sorted Vector of object labels. The * vector is essentially a read-out of the current state of the * objectList, and will not track any future changes to this * objectList.</p> * * @param includeInactives if false, the list returned will not * include entries for any inactive objects */ public Vector<String> getLabels(boolean includeInactives) { return getLabels(includeInactives, false); } /** * <p>This method returns a sorted Vector of object labels. The * vector is essentially a read-out of the current state of the * objectList, and will not track any future changes to this * objectList.</p> * * @param includeInactives if false, the list returned will not * include entries for any inactive objects * * @param includeNonEditables if false, the list returned will not * include entries for any non-editable objects */ public synchronized Vector<String> getLabels(boolean includeInactives, boolean includeNonEditables) { Vector<String> results = null; /* -- */ if (includeInactives) { results = new Vector<String>(handles.size()); for (ObjectHandle handle: handles) { if (includeNonEditables || handle.isEditable()) { results.add(handle.getLabel()); } } } else { results = new Vector<String>(activeHandles.size()); for (ObjectHandle handle: activeHandles) { if (includeNonEditables || handle.isEditable()) { results.add(handle.getLabel()); } } } return results; } /** * <p>This method returns a sorted copy of an object handles * vector.</p> * * <p>No adds or deletes to the returned vector will be reflected in * this objectList, but any changes to the status of the individual * ObjectHandle's will be reflected in the objectList.</p> */ public Vector<ObjectHandle> getObjectHandles(boolean includeInactives) { return getObjectHandles(includeInactives, false); } /** * <p>This method returns a sorted copy of an object handles * vector.</p> * * <p>No adds or deletes to the returned vector will be reflected in * this objectList, but any changes to the status of the individual * ObjectHandle's will be reflected in the objectList.</p> */ public synchronized Vector<ObjectHandle> getObjectHandles(boolean includeInactives, boolean includeNonEditables) { if (includeNonEditables || !containsNonEditable) { if (includeInactives) { return (Vector<ObjectHandle>) handles.clone(); } else { return (Vector<ObjectHandle>) activeHandles.clone(); } } else { Vector<ObjectHandle> result = new Vector<ObjectHandle>(); if (includeInactives) { for (ObjectHandle handle: handles) { if (handle.isEditable()) { result.add(handle); } } } else { for (ObjectHandle handle: activeHandles) { if (handle.isEditable()) { result.add(handle); } } } return result; } } /** * <p>This method relabels an object handle in this list.</p> * * <p>Use this method rather than changing an object handle * reference got by getObjectHandle() in order to let objectList * maintain sort order.</p> */ public synchronized void relabelObject(Invid invid, String newLabel) { ObjectHandle handle = removeInvid(invid); if (handle == null) { return; // throw exception? } handle = new ObjectHandle(handle, newLabel); addObjectHandle(handle); } /** * <p>This method adds an object handle to this list, quickly, in * sorted order.</p> */ public synchronized void addObjectHandle(ObjectHandle handle) { inserter.insert(handles, handle); if (!handle.isInactive()) { inserter.insert(activeHandles, handle); } } /** * <p>This method returns a live reference to the object handle * corresponding to invid, or null if none such is in this object * list.</p> */ public ObjectHandle getObjectHandle(Invid invid) { return invids.get(invid); } /** * <p>This method removes object handles matching the given invid * from the object list.</p> * * <p>This isn't the fastest operation, but hopefully won't be too * bad.</p> * * @return The handle removed, or null if it wasn't found. */ public synchronized ObjectHandle removeInvid(Invid invid) { ObjectHandle handle = invids.remove(invid); if (handle == null) { return null; } handles.remove(handle); activeHandles.remove(handle); return handle; } public synchronized String toString() { StringBuilder tempBuf = new StringBuilder(); for (ObjectHandle handle: handles) { tempBuf.append(handle); tempBuf.append("\n"); } return tempBuf.toString(); } // *** // // Private methods // // *** private void sortHandles() { if (!sorted) { (new VecQuickSort(handles, comparator)).sort(); sorted = true; } if (!activeSorted) { (new VecQuickSort(activeHandles, comparator)).sort(); activeSorted = true; } } }