public void TestSyncDelta() { ConnectorObjectBuilder objbuilder = new ConnectorObjectBuilder(); objbuilder.SetName("myname"); objbuilder.SetUid("myuid"); objbuilder.AddAttribute(CreateTestAttribute()); ConnectorObject obj = objbuilder.Build(); SyncDeltaBuilder builder = new SyncDeltaBuilder(); builder.DeltaType = (SyncDeltaType.DELETE); builder.Token = (new SyncToken("mytoken")); builder.Uid = (new Uid("myuid")); builder.Object = (obj); SyncDelta v1 = builder.Build(); SyncDelta v2 = CreateTestNormalizer().NormalizeSyncDelta(v1); builder = new SyncDeltaBuilder(); builder.DeltaType = (SyncDeltaType.DELETE); builder.Token = (new SyncToken("mytoken")); builder.Uid = (new Uid("myuid")); objbuilder = new ConnectorObjectBuilder(); objbuilder.SetName("myname"); objbuilder.SetUid("myuid"); objbuilder.AddAttribute(CreateNormalizedTestAttribute()); builder.Object = objbuilder.Build(); SyncDelta expected = builder.Build(); Assert.AreEqual(expected, v2); Assert.IsFalse(expected.Equals(v1)); }
public void TestSyncDelta() { ConnectorObjectBuilder bld = new ConnectorObjectBuilder(); bld.SetUid("foo"); bld.SetName("name"); SyncDeltaBuilder builder = new SyncDeltaBuilder(); builder.PreviousUid = (new Uid("mypreviousuid")); builder.Uid = (new Uid("myuid")); builder.DeltaType = (SyncDeltaType.CREATE_OR_UPDATE); builder.Token = (new SyncToken("mytoken")); builder.Object = (bld.Build()); SyncDelta v1 = builder.Build(); SyncDelta v2 = (SyncDelta)CloneObject(v1); Assert.AreEqual(new Uid("mypreviousuid"), v2.PreviousUid); Assert.AreEqual(new Uid("foo"), v2.Uid); Assert.AreEqual(new SyncToken("mytoken"), v2.Token); Assert.AreEqual(SyncDeltaType.CREATE_OR_UPDATE, v2.DeltaType); Assert.AreEqual(v1, v2); builder = new SyncDeltaBuilder(); builder.DeltaType = SyncDeltaType.DELETE; builder.Token = new SyncToken("mytoken"); builder.ObjectClass = ObjectClass.ACCOUNT; builder.Uid = new Uid("foo"); v1 = builder.Build(); v2 = (SyncDelta)CloneObject(v1); Assert.AreEqual(ObjectClass.ACCOUNT, v2.ObjectClass); Assert.AreEqual(new Uid("foo"), v2.Uid); Assert.AreEqual(new SyncToken("mytoken"), v2.Token); Assert.AreEqual(SyncDeltaType.DELETE, v2.DeltaType); Assert.AreEqual(v1, v2); }
/// <summary> /// Process the Hashtable result and convert it to a SyncDelta object /// ready to be processed by the sync handler /// </summary> /// <remarks> /// The result Hashtable must follow a specific format and contain the following key/value: /// /// "Token": (Object) token object (could be Integer, Date, String), [!! could be null] /// "DeltaType": (String) ("CREATE|UPDATE|CREATE_OR_UPDATE"|"DELETE"), /// "Uid": (String) uid (uid of the entry), /// "PreviousUid": (String) previous uid (This is for rename ops), /// "Object": Hashtable(String,List) of attributes name/values describing the object /// "ObjectClass": (String) must be set if Operation = DELETE and Object = null /// </remarks> /// <param name="result"></param> /// <returns></returns> public Object Process(Hashtable result) { var syncbld = new SyncDeltaBuilder(); var cobld = new ConnectorObjectBuilder(); Uid uid; // SyncToken // Mandatory here if (result.ContainsKey(SyncTokenKeyName)) { syncbld.Token = result[SyncTokenKeyName] == null ? new SyncToken(0L) : new SyncToken(result[SyncTokenKeyName]); } else throw new ArgumentException("SyncToken is missing in Sync result"); // SyncDelta // Mandatory here if (isValidKeyAndValue(result,DeltaTypeKeyName)) { var op = result[DeltaTypeKeyName]; if (SyncDeltaType.CREATE.ToString().Equals(op as String, StringComparison.OrdinalIgnoreCase)) syncbld.DeltaType = SyncDeltaType.CREATE; else if (SyncDeltaType.UPDATE.ToString().Equals(op as String, StringComparison.OrdinalIgnoreCase)) syncbld.DeltaType = SyncDeltaType.UPDATE; else if (SyncDeltaType.DELETE.ToString().Equals(op as String, StringComparison.OrdinalIgnoreCase)) syncbld.DeltaType = SyncDeltaType.DELETE; else if (SyncDeltaType.CREATE_OR_UPDATE.ToString().Equals(op as String, StringComparison.OrdinalIgnoreCase)) syncbld.DeltaType = SyncDeltaType.CREATE_OR_UPDATE; else throw new ArgumentException("Unrecognized DeltaType in Sync result"); } else throw new ArgumentException("DeltaType is missing in Sync result"); // Uid // Mandatory if (isValidKeyAndValue(result, UidKeyName)) { var value = result[UidKeyName]; if (value is String) { uid = new Uid(value as String); } else if (value is Uid) { uid = value as Uid; } else { throw new ArgumentException("Unrecognized Uid in Sync result"); } syncbld.Uid = uid; cobld.SetUid(uid); } else { throw new ArgumentException("Uid is missing in Sync result"); } // PreviousUid // Not valid if DELETE if (isValidKeyAndValue(result, PreviousUidKeyName)) { var value = result[PreviousUidKeyName]; Uid previousUid; if (value is String) { previousUid = new Uid(value as String); } else if (value is Uid) { previousUid = value as Uid; } else { throw new ArgumentException("Unrecognized PreviousUid in Sync result"); } syncbld.PreviousUid = previousUid; } if (syncbld.PreviousUid != null && syncbld.DeltaType == SyncDeltaType.DELETE) { throw new ArgumentException("PreviousUid can only be specified for Create or Update."); } // Connector object // Mandatory unless DELETE if (result.ContainsKey(ConnectorObjectKeyName) && result[ConnectorObjectKeyName] is Hashtable) { var attrs = result[ConnectorObjectKeyName] as Hashtable; if (!attrs.ContainsKey(Name.NAME)) throw new ArgumentException("The Object must contain a Name"); foreach (DictionaryEntry attr in attrs) { var attrName = attr.Key as String; var attrValue = attr.Value; if (Name.NAME.Equals(attrName)) cobld.SetName(attrValue as String); else if (Uid.NAME.Equals((attrName))) { if (!uid.GetUidValue().Equals(attrValue)) throw new ArgumentException("Uid from Object is different than Uid from Sync result"); } else if (OperationalAttributes.ENABLE_NAME.Equals((attrName))) cobld.AddAttribute(ConnectorAttributeBuilder.BuildEnabled(attr.Value is bool && (bool) attr.Value)); else { if (attrValue == null) { cobld.AddAttribute(ConnectorAttributeBuilder.Build(attrName)); } else if (attrValue.GetType() == typeof(Object[]) || attrValue.GetType() == typeof(System.Collections.ICollection)) { var list = new Collection<object>(); foreach (var val in (ICollection)attrValue) { list.Add(FrameworkUtil.IsSupportedAttributeType(val.GetType()) ? val : val.ToString()); } cobld.AddAttribute(ConnectorAttributeBuilder.Build(attrName, list)); } else { cobld.AddAttribute(ConnectorAttributeBuilder.Build(attrName, attrValue)); } } } cobld.ObjectClass = _objectClass; syncbld.Object = cobld.Build(); } // If operation is DELETE and the ConnectorObject is null, // we need to set the ObjectClass at the SyncDelta level else if ((SyncDeltaType.DELETE == syncbld.DeltaType) && isValidKeyAndValue(result, ObjectClassKeyName)) { var objclass = result[ObjectClassKeyName]; if (objclass is ObjectClass) { syncbld.ObjectClass = objclass as ObjectClass; } else if (objclass is String) { syncbld.ObjectClass = new ObjectClass(objclass as String); } else { throw new ArgumentException("Unrecognized ObjectClass in Sync result"); } } else { throw new ArgumentException("Object is missing in Sync result"); } return _handler.Handle(syncbld.Build()); }