/* ObjectHandle.java This class is used to group information about objects. It is used in the QueryResult class to keep things organized, and on the client to keep track of the status of objects on the server. Created: 6 February 1998 Module By: Jonathan Abbey, jonabbey@arlut.utexas.edu ----------------------------------------------------------------------- Ganymede Directory Management System Copyright (C) 1996-2014 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.common; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import arlut.csd.JDataComponent.listHandle; /*------------------------------------------------------------------------------ class ObjectHandle ------------------------------------------------------------------------------*/ /** * <p>This immutable class is used to hold serializable label, Invid * and object status information.</p> * * <p>ObjectHandles are collected in {@link * arlut.csd.ganymede.common.QueryResult QueryResults}, which are * returned by certain query operations in {@link * arlut.csd.ganymede.server.DBQueryEngine} and by the choices() * method in the {@link arlut.csd.ganymede.server.StringDBField} and * {@link arlut.csd.ganymede.server.InvidDBField} classes.</p> * * <p>Because QueryResult is also used to return string choices from * the StringDBField.choices() method, ObjectHandles may have null * Invids, in which case they are just used for transporting * Strings.</p> */ public class ObjectHandle implements Cloneable, Externalizable { private boolean externalizing; private String label; private Invid invid; private boolean editable = false; private boolean inactive = false; private boolean expirationSet = false; private boolean removalSet = false; /* -- */ /** * Default no-arg constructor for Externalization * * When this constructor is called, readExternal() can be called to * load state into this object. After readExternal() returns, no * further modifications to this object can be made. */ public ObjectHandle() { this.externalizing = true; } public ObjectHandle(String label, Invid invid, boolean inactive, boolean expirationSet, boolean removalSet, boolean editable) { this.label = label; this.invid = invid; this.inactive = inactive; this.expirationSet = expirationSet; this.removalSet = removalSet; this.editable = editable; this.externalizing = false; } /** * Relabel copy constructor */ public ObjectHandle(ObjectHandle original, String newLabel) { this.label = newLabel; this.invid = original.invid; this.inactive = original.inactive; this.expirationSet = original.expirationSet; this.removalSet = original.removalSet; this.editable = original.editable; this.externalizing = false; } public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException ex) { } return null; // if it didn't work.. not a prob. } public final String getLabel() { return label; } public final Invid getInvid() { return invid; } public final boolean isInactive() { return inactive; } public final boolean isExpirationSet() { return expirationSet; } public final boolean isRemovalSet() { return removalSet; } public final boolean isEditable() { return editable; } /** * Various GUI components use listHandles. */ public final listHandle getListHandle() { return new listHandle(label, invid); } // externalization methods public void writeExternal(ObjectOutput out) throws IOException { byte status = 0; if (this.inactive) { status += 1; } if (this.expirationSet) { status += 2; } if (this.removalSet) { status += 4; } if (this.editable) { status += 8; } if (this.invid == null) { status += 16; } out.writeByte(status); out.writeUTF(this.label); if (this.invid != null) { this.invid.writeExternal(out); } } public void readExternal(ObjectInput in) throws IOException { if (!this.externalizing) { throw new RuntimeException("Invalid double de-externalization"); } try { byte status = in.readByte(); this.inactive = (status & 1) != 0; this.expirationSet = (status & 2) != 0; this.removalSet = (status & 4) != 0; this.editable = (status & 8) != 0; this.label = in.readUTF(); if ((status & 16) != 0) { this.invid = null; return; } Invid anInvid = new Invid(); anInvid.readExternal(in); this.invid = anInvid.intern(); } finally { this.externalizing = false; } } /** * toString() is not finalized, in case we get * wacky with subclassing. */ public String toString() { return label; } public String debugDump() { StringBuilder tmpBuf = new StringBuilder(); tmpBuf.append(label); tmpBuf.append(": "); if (editable) { tmpBuf.append("editable :"); } if (inactive) { tmpBuf.append("inactive :"); } if (expirationSet) { tmpBuf.append("expiration set :"); } if (removalSet) { tmpBuf.append("removal set :"); } return tmpBuf.toString(); } }