/** * This DBObjectDeltaRec constructor is used to generate a delta record that records the * difference between two objects for the Ganymede journal */ public DBObjectDeltaRec(DBObject oldObj, DBObject newObj) { if (oldObj == null || newObj == null) { throw new IllegalArgumentException( "Got a null object parameter" + ((oldObj == null) ? " old " : "") + ((newObj == null) ? " new " : "")); } if (!oldObj.getInvid().equals(newObj.getInvid())) { throw new IllegalArgumentException("Old and New object id's don't match"); } /* - */ this.invid = oldObj.getInvid(); DBObjectBase objectBase = oldObj.getBase(); DBField origField, currentField; /* -- */ // algorithm: iterate over base.getFieldsInFieldOrder() to find // all fields possibly contained in the object.. for each field, // check to see if the value has changed. if so, create a // fieldDeltaRec for it. // note that we're counting on objectBase.sortedFields not being // changed while we're iterating here.. this is an ok assumption, // since only the loader and the schema editor will trigger changes // in sortedFields. if (debug) { System.err.println( "Entering deltarec creation for objects " + oldObj.getLabel() + " and " + newObj.getLabel()); } for (DBObjectBaseField fieldDef : objectBase.getFieldsInFieldOrder()) { if (debug) { System.err.println("Comparing field " + fieldDef.getName()); } origField = (DBField) oldObj.getField(fieldDef.getID()); currentField = (DBField) newObj.getField(fieldDef.getID()); if ((origField == null || !origField.isDefined()) && (currentField == null || !currentField.isDefined())) { // no change.. was null/undefined, still is. continue; } if (currentField == null || !currentField.isDefined()) { // lost this field fieldRecs.addElement(new fieldDeltaRec(fieldDef.getID(), null)); continue; } if (origField == null || !origField.isDefined()) { // we gained this field fieldRecs.addElement(new fieldDeltaRec(fieldDef.getID(), currentField)); continue; } if (currentField.equals(origField)) { // no changes, we don't need to write this one out. continue; } // at this point, we know we need to write out a change // record.. the only question now is whether it is for a // scalar or a vector. if (!fieldDef.isArray()) { // got a scalar.. save this field entire to write out // when we emit to the journal fieldRecs.addElement(new fieldDeltaRec(fieldDef.getID(), currentField)); continue; } // it's a vector.. use the DBField.getVectorDiff() method // to generate a vector diff. fieldRecs.addElement(currentField.getVectorDiff(origField)); } }
/** * This method takes an object in its original state, and returns a new copy of the object with * the changes embodied in this DBObjectDeltaRec applied to it. */ public DBObject applyDelta(DBObject original) { if (!original.getInvid().equals(invid)) { throw new IllegalArgumentException("Error, object identity mismatch"); } /* - */ DBObject copy; fieldDeltaRec fieldRec; Object value; /* -- */ copy = new DBObject(original, null); // now process the fieldDeltaRec's. for (int i = 0; i < fieldRecs.size(); i++) { fieldRec = (fieldDeltaRec) fieldRecs.elementAt(i); // are we clearing this field? if (!fieldRec.vector && fieldRec.scalarValue == null) { copy.clearField(fieldRec.fieldcode); continue; } // are we doing a replace or add? if (!fieldRec.vector) { fieldRec.scalarValue.setOwner(copy); if (copy.getField(fieldRec.fieldcode) != null) { copy.replaceField(fieldRec.scalarValue); } else { copy.addField(fieldRec.scalarValue); } continue; } // ok, we must be doing a vector mod // remember that we are intentionally bypassing the DBField's // add/remove logic, as we assume that this DBObjectDeltaRec // was generated as a result of a properly checked operation. // Also, since we know that only string, invid, and IP fields // can be vectors, we don't have to worry about the password // and permission matrix special-case logic. DBField field = copy.retrieveField(fieldRec.fieldcode); if (fieldRec.addValues != null) { for (int j = 0; j < fieldRec.addValues.size(); j++) { value = fieldRec.addValues.elementAt(j); if (value instanceof IPwrap) { value = ((IPwrap) value).address; } field.getVectVal().addElement(value); } } if (fieldRec.delValues != null) { for (int j = 0; j < fieldRec.delValues.size(); j++) { value = fieldRec.delValues.elementAt(j); if (value instanceof IPwrap) { value = ((IPwrap) value).address; } field.getVectVal().removeElement(value); } } } return copy; }