|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||
java.lang.Object
|
+--arlut.csd.ganymede.DBField
|
+--arlut.csd.ganymede.InvidDBField
InvidDBField is a subclass of DBField
for the storage and handling of Invid
fields in the DBStore on the Ganymede
server.
The Ganymede client talks to InvidDBFields through the
invid_field RMI interface.
This class implements one of the most fundamental pieces of logic in the Ganymede server, the object pointer/object binding logic. Whenever the client calls setValue(), setElement(), addElement(), or deleteElement() on an InvidDBField, the object being pointed to by the Invid being set or cleared will be checked out for editing and the corresponding back pointer will be set or cleared as appropriate.
In other words, the InvidDBField logic guarantees that all objects
references in the server are symmetric. If one object points to
another via an InvidDBField, the target of that pointer will point
back, either through a field explicitly specified in the schema, or
through the server's in-memory backPointers
hash structure.
| Field Summary | |
(package private) static boolean |
debug
|
(package private) static boolean |
fixup
If fixup is true, the InvidDBField.emit() logic will deliberately exclude from the ganymede.db file any ownership links pointing to the supergash owner group, and any ownership links embodied in the supergash owner group. |
private arlut.csd.ganymede.QueryResult |
qr
We'll cache the choiceList from our parent in case we're doing a large vector add/delete. |
| Fields inherited from class arlut.csd.ganymede.DBField |
fieldcode, owner, value |
| Constructor Summary | |
(package private) |
InvidDBField(arlut.csd.ganymede.DBObject owner,
java.io.DataInput in,
arlut.csd.ganymede.DBObjectBaseField definition)
Receive constructor. |
(package private) |
InvidDBField(arlut.csd.ganymede.DBObject owner,
arlut.csd.ganymede.DBObjectBaseField definition)
No-value constructor. |
|
InvidDBField(arlut.csd.ganymede.DBObject owner,
arlut.csd.ganymede.InvidDBField field)
Copy constructor. |
|
InvidDBField(arlut.csd.ganymede.DBObject owner,
arlut.csd.ganymede.Invid value,
arlut.csd.ganymede.DBObjectBaseField definition)
Scalar value constructor. |
|
InvidDBField(arlut.csd.ganymede.DBObject owner,
java.util.Vector values,
arlut.csd.ganymede.DBObjectBaseField definition)
Vector value constructor. |
| Method Summary | |
arlut.csd.ganymede.ReturnVal |
addElement(java.lang.Object value,
boolean local,
boolean noWizards)
Adds an element to the end of this field, if a vector. The Invid we are passed must refer to a valid object in the database. |
arlut.csd.ganymede.ReturnVal |
addElements(java.util.Vector submittedValues,
boolean local,
boolean noWizards,
boolean partialSuccessOk)
Adds a set of elements to the end of this field, if a vector. |
private arlut.csd.ganymede.ReturnVal |
bind(arlut.csd.ganymede.Invid oldRemote,
arlut.csd.ganymede.Invid newRemote,
boolean local)
This method is used to link the remote invid to this checked-out invid in accordance with this field's defined symmetry constraints. |
arlut.csd.ganymede.QueryResult |
choices()
Returns a StringBuffer encoded list of acceptable invid values for this field. |
arlut.csd.ganymede.QueryResult |
choices(boolean applyFilter)
Returns a StringBuffer encoded list of acceptable invid values for this field. |
java.lang.Object |
choicesKey()
This method returns a key that can be used by the client to cache the value returned by choices(). |
void |
cleanup()
This method is intended to be called when this field is being checked into the database. |
java.lang.Object |
clone()
|
arlut.csd.ganymede.ReturnVal |
createNewEmbedded()
Creates and adds a new embedded object in this field, if it is an edit-in-place vector. |
arlut.csd.ganymede.ReturnVal |
createNewEmbedded(boolean local)
Creates and adds a new embedded object in this field, if it is an edit-in-place vector. |
arlut.csd.ganymede.ReturnVal |
deleteElement(int index,
boolean local,
boolean noWizards)
Deletes an element of this field, if a vector. The object pointed to by the Invid in the element to be deleted will be checked out of the database and its pointer to us cleared. Returns null on success, non-null on failure. If non-null is returned, the ReturnVal object will include a dialog specification that the client can use to display the error condition. |
arlut.csd.ganymede.ReturnVal |
deleteElements(java.util.Vector valuesToDelete,
boolean local,
boolean noWizards)
Removes a set of elements from this field, if a vector. |
(package private) arlut.csd.ganymede.ReturnVal |
dissolve(arlut.csd.ganymede.Invid oldInvid,
boolean local)
This method is used to effect the remote side of an unbind operation. |
(package private) void |
emit(java.io.DataOutput out)
This method is used to write the contents of this field to the Ganymede.db file and/or to the Journal file. |
void |
emitInvidXML(arlut.csd.ganymede.XMLDumpContext xmlOut,
arlut.csd.ganymede.Invid invid,
boolean asEmbedded)
This method writes out an Invid in XML form to a Ganymede XML data dump stream. |
(package private) void |
emitXML(arlut.csd.ganymede.XMLDumpContext xmlOut)
This method is used when the database is being dumped, to write out this field to disk. |
arlut.csd.ganymede.QueryResult |
encodedValues()
Returns a QueryResult encoded list of the current values stored in this field. |
private arlut.csd.ganymede.ReturnVal |
establish(arlut.csd.ganymede.Invid newInvid,
boolean local)
This method is used to effect the remote side of an bind operation. An InvidDBField being manipulated with the standard editing accessors (setValue, addElement, deleteElement, setElement) will call this method on another InvidDBField in order to link a pair of symmetrically bound InvidDBFields. This method will return false if the binding could not be performed for some reason. This method is private, and is not to be called by any code outside of this class. |
boolean |
excludeSelected(arlut.csd.ganymede.db_field x)
This method returns true if this invid field should not show any choices that are currently selected in field x, where x is another field in this db_object. |
arlut.csd.ganymede.DBField |
getCopy(arlut.csd.ganymede.DBObject newOwner)
This method is used to return a copy of this field, with the field's owner set to newOwner. |
java.lang.String |
getDiffString(arlut.csd.ganymede.DBField orig)
Returns a String representing the change in value between this field and orig. |
java.lang.String |
getEncodingString()
OK, this is a bit vague.. |
private java.lang.String |
getRemoteLabel(arlut.csd.ganymede.GanymedeSession gsession,
arlut.csd.ganymede.Invid invid,
boolean forceOriginal)
This method returns the label of an object referenced by an invid held in this field. |
short |
getTargetBase()
Return the object type that this invid field is constrained to point to, if set |
arlut.csd.ganymede.DBObjectBase |
getTargetBaseDef()
Returns an actual reference to the object type targeted by this invid field, or null if no specific object type is targeted. |
short |
getTargetField()
Return the numeric id code for the field that this invid field is set to point to, if any. |
arlut.csd.ganymede.DBObjectBaseField |
getTargetFieldDef()
Returns an actual reference to the field definition targeted by this invid field, or null if no specific field type is targeted. |
java.lang.String |
getValueString()
This method returns a text encoded value for this InvidDBField without checking permissions. |
boolean |
limited()
Returns true if this invid field may only point to objects of a particular type. |
boolean |
mustChoose()
Returns true if the only valid values for this invid field are in the QueryRersult returned by choices(). |
(package private) void |
receive(java.io.DataInput in,
arlut.csd.ganymede.DBObjectBaseField definition)
This method is used to read the contents of this field from the Ganymede.db file and/or from the Journal file. |
arlut.csd.ganymede.ReturnVal |
setElement(int index,
java.lang.Object value,
boolean local,
boolean noWizards)
Sets the value of an element of this field, if a vector. The Invid we are passed must refer to a valid object in the database. |
arlut.csd.ganymede.ReturnVal |
setValue(java.lang.Object value,
boolean local,
boolean noWizards)
Sets the value of this field, if a scalar. The Invid we are passed must refer to a valid object in the database. |
(package private) boolean |
test(arlut.csd.ganymede.DBSession session,
java.lang.String objectName)
This method tests to see if the invid's held in this InvidDBField are properly back-referenced. |
private arlut.csd.ganymede.ReturnVal |
unbind(arlut.csd.ganymede.Invid remote,
boolean local)
This method is used to unlink this field from the specified remote invid in accordance with this field's defined symmetry constraints. |
arlut.csd.ganymede.Invid |
value()
|
arlut.csd.ganymede.Invid |
value(int index)
|
arlut.csd.ganymede.ReturnVal |
verifyNewValue(java.lang.Object o)
Overridable method to verify that an object submitted to this field has an appropriate value. |
arlut.csd.ganymede.ReturnVal |
verifyNewValue(java.lang.Object o,
boolean local)
|
boolean |
verifyTypeMatch(java.lang.Object o)
Overridable method to determine whether an Object submitted to this field is of an appropriate type. |
| Methods inherited from class java.lang.Object |
finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
| Methods inherited from interface arlut.csd.ganymede.db_field |
addElement, addElements, containsElement, deleteAllElements, deleteElement, deleteElement, deleteElements, getComment, getElement, getFieldInfo, getFieldTemplate, getID, getName, getType, getTypeDesc, getValue, getValues, isBuiltIn, isDefined, isEditable, isEditInPlace, isVector, isVisible, setElement, setValue, size |
| Field Detail |
static final boolean debug
static final boolean fixup
private arlut.csd.ganymede.QueryResult qr
We'll cache the choiceList from our parent in case we're doing a large vector add/delete. Any time we change our value/values actually contained in this field, we'll null this out.
Note that having this here costs us 4 bytes RAM for every InvidDBField held in the Ganymede server's database, but without it we'll have an extraordinarily painful time doing mass adds/deletes.
| Constructor Detail |
InvidDBField(arlut.csd.ganymede.DBObject owner,
java.io.DataInput in,
arlut.csd.ganymede.DBObjectBaseField definition)
throws java.io.IOException
InvidDBField(arlut.csd.ganymede.DBObject owner,
arlut.csd.ganymede.DBObjectBaseField definition)
No-value constructor. Allows the construction of a
'non-initialized' field, for use where the
DBObjectBase
definition indicates that a given field may be present,
but for which no value has been stored in the
DBStore.
Used to provide the client a template for 'creating' this field if so desired.
public InvidDBField(arlut.csd.ganymede.DBObject owner,
arlut.csd.ganymede.InvidDBField field)
public InvidDBField(arlut.csd.ganymede.DBObject owner,
arlut.csd.ganymede.Invid value,
arlut.csd.ganymede.DBObjectBaseField definition)
public InvidDBField(arlut.csd.ganymede.DBObject owner,
java.util.Vector values,
arlut.csd.ganymede.DBObjectBaseField definition)
| Method Detail |
public arlut.csd.ganymede.DBField getCopy(arlut.csd.ganymede.DBObject newOwner)
This method is used to return a copy of this field, with the field's owner set to newOwner.
getCopy in class DBFieldpublic java.lang.Object clone()
clone in class java.lang.Object
void emit(java.io.DataOutput out)
throws java.io.IOException
emit in class DBFieldjava.io.IOException
void receive(java.io.DataInput in,
arlut.csd.ganymede.DBObjectBaseField definition)
throws java.io.IOException
receive in class DBFieldjava.io.IOException
void emitXML(arlut.csd.ganymede.XMLDumpContext xmlOut)
throws java.io.IOException
This method is used when the database is being dumped, to write out this field to disk. It is mated with receiveXML().
emitXML in class DBFieldjava.io.IOException
public void emitInvidXML(arlut.csd.ganymede.XMLDumpContext xmlOut,
arlut.csd.ganymede.Invid invid,
boolean asEmbedded)
throws java.io.IOException
This method writes out an Invid in XML form to a Ganymede XML data dump stream.
Whenever Ganymede writes out an Invid to an XML data dump, it uses an <invid> element with two attributes, type and id. type is the name of the object type that the invid points to, and id is an identifying label for the target object.
When it can, emitInvidXML() will use a human-readable label for the id attribute. This can only be done, however, in those cases where the object in question has a designated label field and in which that label field is guaranteed to have a unique value through the use of a DBNameSpace. If emitInvidXML() cannot guarantee that the label will be unique, it will write out the target object's type-specific object number
If the target invid has a unique label, the label of the object will be written out in the 'id' attribute of the invid element. If not, the 'id' attribute will be omitted and the target element will be identified by its numeric object id, using the 'num' attribute.
All this is a bit different if this InvidDBField is an edit-in-place field. In that case, emitInvidXML will simply write out the embedded object, in place of an invid element.
java.io.IOExceptionpublic void cleanup()
This method is intended to be called when this field is being checked into the database. Subclasses of DBField will override this method to clean up data that is cached for speed during editing.
cleanup in class DBFieldpublic arlut.csd.ganymede.Invid value()
public arlut.csd.ganymede.Invid value(int index)
public java.lang.String getValueString()
This method returns a text encoded value for this InvidDBField without checking permissions.
This method avoids checking permissions because it is used on
the server side only and because it is involved in the
getLabel()
logic for DBObject,
which is invoked from GanymedeSession's
getPerm()
method.
If this method checked permissions and the getPerm() method failed for some reason and tried to report the failure using object.getLabel(), as it does at present, the server could get into an infinite loop.
getValueString in interface db_fieldgetValueString in class DBField
private java.lang.String getRemoteLabel(arlut.csd.ganymede.GanymedeSession gsession,
arlut.csd.ganymede.Invid invid,
boolean forceOriginal)
This method returns the label of an object referenced by an
invid held in this field. If the remote object referenced by the
invid argument is currently being deleted, we'll try to get the
label from the state of that object as it existed at the start of
the current transaction. This is to allow us to do proper
logging of the values deleted from this field in the case of the
string generated by DBEditObject.diff() during transaction logging.
If forceOriginal is set to true, getRemoteLabel will always try to retrieve the remote object's original label, even if the remote object has not been deleted by the active transaction.
public java.lang.String getEncodingString()
OK, this is a bit vague.. getEncodingString() is used by the new dump system to allow all fields to be properly sorted in the client's query result table.. a real reversible encoding of an invid field would *not* be the getValueString() results, but getValueString() is what we want in the dump result table, so we'll do that here for now.
getEncodingString in interface db_fieldgetEncodingString in class DBFielddb_fieldpublic java.lang.String getDiffString(arlut.csd.ganymede.DBField orig)
Returns a String representing the change in value between this field and orig. This String is intended for logging and email, not for any sort of programmatic activity. The format of the generated string is not defined, but is intended to be suitable for inclusion in a log entry and in an email message.
If there is no change in the field, null will be returned.
getDiffString in class DBField
private final arlut.csd.ganymede.ReturnVal bind(arlut.csd.ganymede.Invid oldRemote,
arlut.csd.ganymede.Invid newRemote,
boolean local)
This method is used to link the remote invid to this checked-out invid in accordance with this field's defined symmetry constraints.
This method will extract the objects referenced by the old and new remote parameters, and will cause the appropriate invid dbfields in them to be updated to reflect the change in link status. If either operation can not be completed, bind will return the system to its pre-bind status and return false. One or both of the specified remote objects may remain checked out in the current editset until the transaction is committed or released.
It is an error for newRemote to be null; if you wish to undo an existing binding, use the unbind() method call. oldRemote may be null if this currently holds no value, or if this is a vector field and newRemote is being added.
This method should only be called from synchronized methods within InvidDBField.
This method is private, and is not to be called by any code outside of this class.
oldRemote - the old invid to be replacednewRemote - the new invid to be linkedlocal - if true, this operation will be performed without regard
to permissions limitations.
unbind(arlut.csd.ganymede.Invid, boolean)
private final arlut.csd.ganymede.ReturnVal unbind(arlut.csd.ganymede.Invid remote,
boolean local)
This method is used to unlink this field from the specified remote invid in accordance with this field's defined symmetry constraints.
This method is private, and is not to be called by any code outside of this class.
remote - An invid for an object to be checked out and unlinkedlocal - if true, this operation will be performed without regard
to permissions limitations.
final arlut.csd.ganymede.ReturnVal dissolve(arlut.csd.ganymede.Invid oldInvid,
boolean local)
This method is used to effect the remote side of an unbind operation.
An InvidDBField being manipulated with the standard editing accessors (setValue, addElement, deleteElement, setElement) will call this method on another InvidDBField in order to unlink a pair of symmetrically bound InvidDBFields.
This method will return false if the unbinding could not be performed for some reason.
This method is private, and is not to be called by any code outside of this class.
oldInvid - The invid to be unlinked from this field. If this
field is not linked to the invid specified, nothing will happen.local - if true, this operation will be performed without regard
to permissions limitations.
private final arlut.csd.ganymede.ReturnVal establish(arlut.csd.ganymede.Invid newInvid,
boolean local)
newInvid - The invid to be linked to this field.local - if true, this operation will be performed without regard
to permissions limitations.
boolean test(arlut.csd.ganymede.DBSession session,
java.lang.String objectName)
public arlut.csd.ganymede.ReturnVal setValue(java.lang.Object value,
boolean local,
boolean noWizards)
setValue in class DBFieldvalue - the value to set this field to, and Invidlocal - if true, this operation will be performed without regard
to permissions limitations.noWizards - If true, wizards will be skippedDBSession
public arlut.csd.ganymede.ReturnVal setElement(int index,
java.lang.Object value,
boolean local,
boolean noWizards)
setElement in class DBFieldindex - The index of the element in this field to change.value - The value to put into this vector.local - if true, this operation will be performed without regard
to permissions limitations.noWizards - If true, wizards will be skippedDBSession
public arlut.csd.ganymede.ReturnVal addElement(java.lang.Object value,
boolean local,
boolean noWizards)
addElement in class DBFieldvalue - The value to put into this vector.local - if true, this operation will be performed without regard
to permissions limitations.noWizards - If true, wizards will be skipped
public arlut.csd.ganymede.ReturnVal addElements(java.util.Vector submittedValues,
boolean local,
boolean noWizards,
boolean partialSuccessOk)
Adds a set of elements to the end of this field, if a vector. Using addElements() to add a sequence of items to a field may be many times more efficient than calling addElement() repeatedly, as addElements() can do a single server checkpoint before attempting to add all the values.
The Invid we are passed must refer to a valid object in the database. The remote object will be checked out for editing and a backpointer will placed in it. If this field previously held a pointer to another object, that other object will be checked out and its pointer to us cleared.
It is an error to call this method on an edit in place vector, or on a scalar field. An IllegalArgumentException will be thrown in these cases.
Server-side method only
The ReturnVal object returned encodes success or failure, and may optionally pass back a dialog.
addElements in class DBFieldsubmittedValues - Values to be addedlocal - If true, permissions checking will be skippednoWizards - If true, wizards will be skippedpartialSuccessOk - If true, addElements will add any values that
it can, even if some values are refused by the server logic. Any
values that are skipped will be reported in a dialog passed back
in the returned ReturnValpublic arlut.csd.ganymede.ReturnVal createNewEmbedded()
Creates and adds a new embedded object in this field, if it is an edit-in-place vector.
Returns a ReturnVal which
conveys a success or failure result. If the createNewEmbedded()
call was successful, the ReturnVal will contain
Invid and db_object, which can be retrieved
using the ReturnVal getInvid()
and getObject()
methods..
createNewEmbedded in interface invid_fieldinvid_fieldpublic arlut.csd.ganymede.ReturnVal createNewEmbedded(boolean local)
Creates and adds a new embedded object in this field, if it is an edit-in-place vector.
Returns a ReturnVal which
conveys a success or failure result. If the createNewEmbedded()
call was successful, the ReturnVal will contain
Invid and db_object, which can be retrieved
using the ReturnVal getInvid()
and getObject()
methods..
local - If true, we don't check permission to edit this
field before creating the new object.public short getTargetBase()
Return the object type that this invid field is constrained to point to, if set
-1 means there is no restriction on target type.
-2 means there is no restriction on target type, but there is a specified symmetric field.
getTargetBase in interface invid_fieldinvid_fieldpublic arlut.csd.ganymede.DBObjectBase getTargetBaseDef()
Returns an actual reference to the object type targeted by this invid field, or null if no specific object type is targeted.
public short getTargetField()
Return the numeric id code for the field that this invid field is set to point to, if any. If -1 is returned, this invid field does not point to a specific field, and so has no symmetric relationship.
public arlut.csd.ganymede.DBObjectBaseField getTargetFieldDef()
Returns an actual reference to the field definition targeted by this invid field, or null if no specific field type is targeted.
public arlut.csd.ganymede.ReturnVal deleteElement(int index,
boolean local,
boolean noWizards)
deleteElement in class DBField
public arlut.csd.ganymede.ReturnVal deleteElements(java.util.Vector valuesToDelete,
boolean local,
boolean noWizards)
Removes a set of elements from this field, if a vector. Using deleteElements() to remove a sequence of items from a field may be many times more efficient than calling deleteElement() repeatedly, as removeElements() can do a single server checkpoint before attempting to remove all the values.
The ReturnVal object returned encodes success or failure, and may optionally pass back a dialog.
Server-side method only
deleteElements in class DBFieldpublic boolean limited()
limited in interface invid_fieldinvid_fieldpublic arlut.csd.ganymede.QueryResult encodedValues()
encodedValues in interface invid_fieldinvid_fieldpublic boolean excludeSelected(arlut.csd.ganymede.db_field x)
excludeSelected in interface invid_fieldpublic boolean mustChoose()
mustChoose in interface invid_fieldinvid_fieldpublic arlut.csd.ganymede.QueryResult choices()
choices in interface invid_fieldinvid_fieldpublic arlut.csd.ganymede.QueryResult choices(boolean applyFilter)
choices in interface invid_fieldinvid_fieldpublic java.lang.Object choicesKey()
This method returns a key that can be used by the client to cache the value returned by choices(). If the client already has the key cached on the client side, it can provide the choice list from its cache rather than calling choices() on this object again.
If there is no caching key, this method will return null.
choicesKey in interface invid_fieldpublic boolean verifyTypeMatch(java.lang.Object o)
DBField
verifyTypeMatch in class DBFieldpublic arlut.csd.ganymede.ReturnVal verifyNewValue(java.lang.Object o)
DBField
verifyNewValue in class DBField
public arlut.csd.ganymede.ReturnVal verifyNewValue(java.lang.Object o,
boolean local)
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||