/* FieldOptionMatrix.java This class stores a read-only matrix of option strings, organized by object type and field id's. Created: 25 January 2005 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.common; import java.rmi.RemoteException; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import arlut.csd.ganymede.rmi.Base; import arlut.csd.ganymede.rmi.BaseField; import arlut.csd.ganymede.server.FieldOptionDBField; /*------------------------------------------------------------------------------ class FieldOptionMatrix ------------------------------------------------------------------------------*/ /** * <p>Serializable field option matrix object, used to handle * field options for a SyncRunner.</p> * * <p>This class stores a read-only Hashtable of Strings, organized by * object type and field id's.</p> * * <p>The keys to the Hashtable are Strings that are encoded by the * static matrixEntry() methods defined in this class. I probably * could have used some sort of class object for the key, but then I * would have had to define a key() of similar complexity to the * matrixEntry() and decode methods anyway, as well as some sort of * on-disk representation for the Ganymede.db file.</p> * * <p>Here's some examples of the key encoding algorithm:</p> * * <ul> * <li><code>3::</code> - Object type 3, option for object itself</li> * <li><code>3:10</code> - Object type 3, option for field 10</li> * </ul> * * <p>FieldOptionMatrix is used on the client in the Field Option dialog, * and on the server in both * {@link arlut.csd.ganymede.server.FieldOptionDBField FieldOptionDBField} * and {@link arlut.csd.ganymede.server.SyncRunner SyncRunner}.</p> */ public class FieldOptionMatrix implements java.io.Serializable { static final boolean debug = false; // --- public Map<String, SyncPrefEnum> matrix; /* -- */ public FieldOptionMatrix() { matrix = new HashMap<String, SyncPrefEnum>(); } public FieldOptionMatrix(Map<String, SyncPrefEnum> orig) { if (orig == null) { this.matrix = new HashMap<String, SyncPrefEnum>(); } else { this.matrix = new HashMap<String, SyncPrefEnum>(orig); } } public FieldOptionMatrix(FieldOptionMatrix orig) { this.matrix = new HashMap<String, SyncPrefEnum>(orig.matrix); } /** * <p>Returns a SyncPrefEnum representing this FieldOptionMatrix's * option on the field <fieldID> in base <baseID></p> * * <p>If there is no entry in this FieldOptionMatrix for the given * field, getOption() will return null.</p> */ public SyncPrefEnum getOption(short baseID, short fieldID) { return matrix.get(matrixEntry(baseID, fieldID)); } /** * <p>Returns a SyncPrefeEnum representing this FieldOptionMatrix's * option on the base <baseID></p> */ public SyncPrefEnum getOption(short baseID) { return matrix.get(matrixEntry(baseID)); } /** * <p>Returns a SyncPrefEnum representing this FieldOptionMatrix's * option on the field <field> in base <base></p> */ public SyncPrefEnum getOption(Base base, BaseField field) { try { return getOption(base.getTypeID(), field.getID()); } catch (RemoteException ex) { throw new RuntimeException("caught remote: " + ex); } } /** * <p>Returns a SyncPrefEnum representing this FieldOptionMatrix's * option on the base <base></p> */ public SyncPrefEnum getOption(Base base) { try { return matrix.get(matrixEntry(base.getTypeID())); } catch (RemoteException ex) { throw new RuntimeException("caught remote: " + ex); } } /** * <p>Private method to generate a key for use in * our internal Hashtable, used to encode the * option for a given {@link arlut.csd.ganymede.server.DBObjectBase * DBObjectBase} and {@link arlut.csd.ganymede.server.DBObjectBaseField * DBObjectBaseField}.</p> */ private String matrixEntry(short baseID, short fieldID) { return (baseID + ":" + fieldID); } /** * <p>Private method to generate a key for use in * our internal Hashtable, used to encode the * option for a given {@link arlut.csd.ganymede.server.DBObjectBase * DBObjectBase}.</p> */ private String matrixEntry(short baseID) { return (baseID + "::"); } /** * <p>Returns true if the given String encodes the identity of * a {@link arlut.csd.ganymede.server.DBObjectBase DBObjectBase} and * not a field within a DBObjectBase.</p> */ private boolean isBase(String matrixEntry) { return (matrixEntry.indexOf("::") != -1); } /** * <p>Private helper method used to decode a hash key generated * by the matrixEntry() methods.</p> * * @return Returns the {@link arlut.csd.ganymede.server.DBObjectBase DBObjectBase} * object id encoded by the given String. */ private short entryBase(String matrixKey) { if (matrixKey.indexOf(':') == -1) { throw new IllegalArgumentException("not a valid matrixEntry"); } String baseStr = matrixKey.substring(0, matrixKey.indexOf(':')); try { return Short.parseShort(baseStr); } catch (NumberFormatException ex) { throw new RuntimeException("bad string format:" + ex); } } /** * <p>Private helper method used to decode a hash key generated * by the matrixEntry() methods.</p> * * @return Returns the * {@link arlut.csd.ganymede.server.DBObjectBaseField DBObjectBaseField} * object id encoded by the given String. */ private short entryField(String matrixKey) { if (matrixKey.indexOf(':') == -1) { throw new IllegalArgumentException("not a valid matrixEntry"); } if (isBase(matrixKey)) { throw new IllegalArgumentException("not a field matrixEntry"); } String fieldStr = matrixKey.substring(matrixKey.lastIndexOf(':')+1); try { return Short.parseShort(fieldStr); } catch (NumberFormatException ex) { throw new RuntimeException("bad string format:" + ex); } } /** * <p>Private helper method used to generate a matrixEntry() encoded String * for a single {@link arlut.csd.ganymede.server.DBObjectBase DBObjectBase} from * a matrixEntry() encoded String that also includes a field specification.</p> */ private String baseEntry(String matrixKey) { if (isBase(matrixKey)) { return matrixKey; } else { return matrixEntry(entryBase(matrixKey)); } } /** * <p>Debugging output</p> */ public String toString() { try { return FieldOptionDBField.debugdecode(matrix); } catch (Throwable ex) { return super.toString(); } } }