private void SubmitConnectorObject(String result, ResultsHandler handler) { ConnectorObjectBuilder cob = new ConnectorObjectBuilder(); String[] resultSplit = result.Split(new char[] { '$' }); ICollection <ConnectorAttribute> attrs = new List <ConnectorAttribute>(); foreach (String str in resultSplit) { ConnectorAttributeBuilder cab = new ConnectorAttributeBuilder(); cab.AddValue(str.Split(new char[] { ':' })[1]); if (str.StartsWith("Name")) { cob.SetName(Name.NAME); cob.SetUid(str.Split(new char[] { ':' })[1]); cab.Name = Name.NAME; } else { cab.Name = str.Split(new char[] { ':' })[0]; } attrs.Add(cab.Build()); } cob.AddAttributes(attrs); handler(cob.Build()); }
public void TestDictionaryIntegerAttribute() { Dictionary <object, object> map = new Dictionary <object, object>(); map[1] = "NOK"; ConnectorAttributeBuilder bld = new ConnectorAttributeBuilder(); bld.AddValue(map); }
/// <summary> /// Renames the connector attribute to new name /// </summary> /// <param name="cattribute">ConnectorAttribute to be renamed</param> /// <param name="newName">New attribute name</param> /// <returns>Renamed ConnectorAttribute</returns> /// <exception cref="ArgumentNullException">If some of the params is null</exception> internal static ConnectorAttribute RenameAttribute(ConnectorAttribute cattribute, string newName) { Assertions.NullCheck(cattribute, "cattribute"); Assertions.NullCheck(newName, "newName"); var attBuilder = new ConnectorAttributeBuilder(); attBuilder.AddValue(cattribute.Value); attBuilder.Name = newName; return(attBuilder.Build()); }
/// <summary> /// Renames the connector attribute to new name; transforms value by keeping Common Name only /// </summary> /// <param name="cattribute">ConnectorAttribute to be renamed</param> /// <param name="newName">New attribute name</param> /// <returns>Renamed and transformed ConnectorAttribute</returns> /// <exception cref="ArgumentNullException">If some of the params is null</exception> internal static ConnectorAttribute ExtractCommonName(ConnectorAttribute cattribute, string newName) { Assertions.NullCheck(cattribute, "cattribute"); Assertions.NullCheck(newName, "newName"); var attBuilder = new ConnectorAttributeBuilder(); if (cattribute.Value != null) { ICollection <object> convertedValues = new List <object>(); foreach (object oldValue in cattribute.Value) { if (oldValue != null) // should be always the case { convertedValues.Add(ExtractCommonName(oldValue.ToString())); } } attBuilder.AddValue(convertedValues); } attBuilder.Name = newName; return(attBuilder.Build()); }
// creates a collection of attributes that correspond to the original ones, but resolves ADD/DELETE using existing values of psuser public ICollection <ConnectorAttribute> DetermineNewAttributeValues(UpdateOpContext context, ConnectorObject originalObject) { if (context.UpdateType == UpdateType.REPLACE) { // TODO check multivaluedness and updateability (as below) return(new List <ConnectorAttribute>(context.Attributes)); } else { Boolean add; if (context.UpdateType == UpdateType.ADD) { add = true; } else if (context.UpdateType == UpdateType.DELETE) { add = false; } else { throw new ArgumentException("Unsupported update type: " + context.UpdateType); } Schema schema = null; ICollection <ConnectorAttribute> rv = new List <ConnectorAttribute>(context.Attributes.Count); foreach (ConnectorAttribute attribute in context.Attributes) { ConnectorAttribute originalAttribute = originalObject.GetAttributeByName(attribute.Name); IList <object> newValues = originalAttribute != null && originalAttribute.Value != null ? new List <object>(originalAttribute.Value) : new List <object>(); Boolean changed = false; if (attribute.Value != null) { foreach (object item in attribute.Value) { if (add) { if (newValues.Contains(item)) { LOG.Warn("Trying to add value from " + attribute.Name + " that is already there: " + item); } else { newValues.Add(item); changed = true; } } else { if (!newValues.Contains(item)) { LOG.Warn("Trying to remove value from " + attribute.Name + " that is not there: " + item); } else { newValues.Remove(item); changed = true; } } } } if (changed) { ConnectorAttributeBuilder b = new ConnectorAttributeBuilder(); b.Name = attribute.Name; b.AddValue(newValues); ConnectorAttribute modified = b.Build(); if (schema == null) { ExchangeConnector connector = (ExchangeConnector)context.Connector; schema = connector.Schema(); } ObjectClassInfo oci = schema.FindObjectClassInfo(context.ObjectClass.Type); if (oci == null) { throw new InvalidOperationException("No object class info for " + context.ObjectClass.Type + " in the schema"); } var cai = ConnectorAttributeInfoUtil.Find(attribute.Name, oci.ConnectorAttributeInfos); if (cai == null) { throw new InvalidOperationException("No connector attribute info for " + context.ObjectClass.Type + " in the schema"); } if (!cai.IsUpdateable) { throw new ConnectorSecurityException("Attempt to update a non-updateable attribute (" + attribute.Name + "): " + CollectionUtil.Dump(newValues)); } if (newValues.Count > 1 && !cai.IsMultiValued) { throw new InvalidAttributeValueException("More than one value in a single-valued attribute (" + attribute.Name + "): " + CollectionUtil.Dump(newValues)); } rv.Add(modified); } } return(rv); } }
/// <summary> /// DeduplicatesEmailAddresses. /// - on REPLACE (i.e. update/replace or create) the situation is easy: we just remove duplicate entries (SMTP:x & smtp:x result in SMTP:x) /// - on DELETE we currently do nothing /// - on ADD we have one additional rule: /// "If we are adding SMTP:x, we first convert all SMTP:y in existing records to smtp:y because we see the intent of having x to be a new primary" /// /// </summary> /// <param name="context"></param> /// <param name="attributes">these are attributes to be set (already resolved if we have update of type ADD or DELETE)</param> /// <returns></returns> private ICollection <ConnectorAttribute> DeduplicateEmailAddresses(CreateUpdateOpContext context, ICollection <ConnectorAttribute> attributes) { // trivial cases if (context is UpdateOpContext && ((UpdateOpContext)context).UpdateType == UpdateType.DELETE) { return(attributes); } ConnectorAttribute attribute = ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttEmailAddresses, attributes); if (attribute == null || attribute.Value == null) { return(attributes); // missing or empty EmailAddresses - nothing to deduplicate } ConnectorAttribute attributeDelta = ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttEmailAddresses, context.Attributes); if (attributeDelta == null || attributeDelta.Value == null) { return(attributes); // missing or empty changed EmailAddresses - nothing to deduplicate } // now the main part IList <string> valuesToDeduplicate = new List <string>(); foreach (object o in attribute.Value) { if (o != null) { valuesToDeduplicate.Add(o.ToString()); } } bool changed = false; // special rule: if ADD with SMTP:, let us change all other "SMTP:x" to "smtp:x" Boolean isUpdateAdd = context is UpdateOpContext && ((UpdateOpContext)context).UpdateType == UpdateType.ADD; if (isUpdateAdd) { string newPrimary = null; foreach (object o in attributeDelta.Value) { if (((string)o).StartsWith("SMTP:")) { newPrimary = (string)o; break; } } if (newPrimary != null) { foreach (string address in new List <string>(valuesToDeduplicate)) // to eliminate concurrent access { if (address.StartsWith("SMTP:") && !address.Equals(newPrimary)) { string replacement = "smtp:" + address.Substring(5); LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Changing duplicate primary-candidate address {0} to {1}", address, replacement); valuesToDeduplicate.Remove(address); valuesToDeduplicate.Add(replacement); changed = true; } } } } IDictionary <string, string> values = new Dictionary <string, string>(); // normalized->most-recent-original e.g. SMTP:[email protected] -> SMTP:[email protected] (if primary is present) foreach (object v in valuesToDeduplicate) { string address = (string)v; string normalized = address.ToUpper(); if (values.ContainsKey(normalized)) { changed = true; string existing = values[normalized]; if (address.StartsWith("SMTP:") && existing.StartsWith("smtp:")) { LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Removing redundant address {0}, keeping {1}", existing, address); values[normalized] = address; } else { LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Removing redundant address {0}, keeping {1}", address, existing); } } else { values.Add(normalized, address); } } if (changed) { ConnectorAttributeBuilder cab = new ConnectorAttributeBuilder(); cab.Name = ExchangeConnectorAttributes.AttEmailAddresses; foreach (string value in values.Values) { cab.AddValue(value); } ICollection <ConnectorAttribute> rv = new List <ConnectorAttribute>(attributes); // the original is (sometimes) a read-only collection rv.Remove(attribute); rv.Add(cab.Build()); return(rv); } else { return(attributes); } }