public void TestSchema() { OperationOptionInfo opInfo = new OperationOptionInfo("name", typeof(int?)); ObjectClassInfoBuilder bld = new ObjectClassInfoBuilder(); bld.ObjectType = ObjectClass.ACCOUNT_NAME; ObjectClassInfo info = bld.Build(); ICollection <ObjectClassInfo> temp = CollectionUtil.NewSet(info); IDictionary <SafeType <APIOperation>, ICollection <ObjectClassInfo> > map = new Dictionary <SafeType <APIOperation>, ICollection <ObjectClassInfo> >(); map[SafeType <APIOperation> .Get <CreateApiOp>()] = temp; ICollection <OperationOptionInfo> temp2 = CollectionUtil.NewSet(opInfo); IDictionary <SafeType <APIOperation>, ICollection <OperationOptionInfo> > map2 = new Dictionary <SafeType <APIOperation>, ICollection <OperationOptionInfo> >(); map2[SafeType <APIOperation> .Get <CreateApiOp>()] = temp2; Schema v1 = new Schema(CollectionUtil.NewSet(info), CollectionUtil.NewSet(opInfo), map, map2); Schema v2 = (Schema)CloneObject(v1); Assert.AreEqual(v1, v2); Assert.AreEqual(info, v2.ObjectClassInfo.First()); Assert.AreEqual(1, v2.SupportedObjectClassesByOperation.Count); Assert.AreEqual(1, v2.SupportedOptionsByOperation.Count); Assert.AreEqual(1, v2.OperationOptionInfo.Count); }
internal ConnectorObject CreateConnectorObject(ExchangeConnector connector, PSObject psobject, ObjectClass objectClass) { ConnectorObjectBuilder builder = new ConnectorObjectBuilder(); string guid = (string)psobject.Properties["guid"].Value.ToString(); string name = (string)psobject.Properties["name"].Value; builder.SetUid(new Uid(guid)); builder.SetName(new Name(name)); ObjectClassInfo ocinfo = connector.GetSchema().FindObjectClassInfo(objectClass.GetObjectClassValue()); IDictionary <string, PSPropertyInfo> properties = psobject.Properties.ToDictionary(psinfo => psinfo.Name); LOG.Trace("Building connector object with UID = {0} and Name = {1}", guid, name); foreach (ConnectorAttributeInfo cai in ocinfo.ConnectorAttributeInfos) { if (cai.IsReadable && properties.ContainsKey(cai.Name)) { object value = properties[cai.Name].Value; LOG.Trace(" - attribute {0} = {1}", cai.Name, value); if (value is PSObject) { var ps = value as PSObject; value = ps.BaseObject; LOG.Trace(" - attribute {0} UNWRAPPED = {1} ({2})", cai.Name, value, value.GetType()); } builder.AddAttribute(cai.Name, CommonUtils.ConvertToSupportedForm(cai, value)); } } return(builder.Build()); }
/// <summary> /// Gets the object class info for specified object class, used for schema building /// </summary> /// <param name="oc">ObjectClass to get info for</param> /// <returns>ObjectClass' ObjectClassInfo</returns> protected override ObjectClassInfo GetObjectClassInfo(ObjectClass oc) { ObjectClassInfo ret = CollectionUtil.GetValue(this.mapOcInfo, oc, null) ?? base.GetObjectClassInfo(oc); Assertions.NullCheck(ret, "ret"); return(ret); }
private static void Merge(IDictionary <ObjectClass, ObjectClassInfo> target, IDictionary <ObjectClass, ObjectClassInfo> source) { foreach (ObjectClass oc in source.Keys) { ObjectClassInfo sourceOCI = source[oc]; if (!target.ContainsKey(oc)) { ObjectClassInfoBuilder builder = new ObjectClassInfoBuilder(); builder.ObjectType = sourceOCI.ObjectType; builder.IsContainer = sourceOCI.IsContainer; builder.AddAllAttributeInfo(sourceOCI.ConnectorAttributeInfos); ObjectClassInfo targetOCI = builder.Build(); LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Adding object class info {0}", targetOCI.ObjectType); target.Add(oc, targetOCI); } else { ObjectClassInfo targetOCI = target[oc]; if (!targetOCI.ObjectType.Equals(sourceOCI.ObjectType)) { throw new ArgumentException("Incompatible ObjectType for object class " + oc); } if (targetOCI.IsContainer != sourceOCI.IsContainer) { throw new ArgumentException("Incompatible Container flag for object class " + oc); } ObjectClassInfoBuilder builder = new ObjectClassInfoBuilder(); builder.ObjectType = targetOCI.ObjectType; builder.IsContainer = targetOCI.IsContainer; builder.AddAllAttributeInfo(targetOCI.ConnectorAttributeInfos); foreach (ConnectorAttributeInfo info in sourceOCI.ConnectorAttributeInfos) { if (info.Is(Name.NAME)) { // The __NAME__ attribute is a special one and has to be provided on each object class. // So, even if we just want to extend an object class with a few attributes, we have to provide // artificial __NAME__ attribute there. When merging, we simply skip it. continue; } foreach (ConnectorAttributeInfo existingInfo in targetOCI.ConnectorAttributeInfos) { if (existingInfo.Is(info.Name)) { throw new ArgumentException("Attempted to redefine attribute " + info.Name); } } LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Adding connector attribute info {0}:{1}", info.Name, info.ValueType); builder.AddAttributeInfo(info); } ObjectClassInfo targetRebuilt = builder.Build(); LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Replacing object class info {0}", targetOCI.ObjectType); target.Remove(oc); target.Add(oc, targetRebuilt); } } }
/// <summary> /// Gets the object class info for specified object class, used for schema building /// </summary> /// <param name="oc">ObjectClass to get info for</param> /// <returns>ObjectClass' ObjectClassInfo</returns> protected override ObjectClassInfo GetObjectClassInfo(ObjectClass oc) { // get the object class from base ObjectClassInfo oinfo = base.GetObjectClassInfo(oc); // add additional attributes for ACCOUNT if (oc.Is(ObjectClass.ACCOUNT_NAME)) { var classInfoBuilder = new ObjectClassInfoBuilder { IsContainer = oinfo.IsContainer, ObjectType = oinfo.ObjectType }; classInfoBuilder.AddAllAttributeInfo(oinfo.ConnectorAttributeInfos); classInfoBuilder.AddAttributeInfo(AttInfoDatabase); classInfoBuilder.AddAttributeInfo(AttInfoRecipientType); classInfoBuilder.AddAttributeInfo(AttInfoExternalMail); oinfo = classInfoBuilder.Build(); } // return return(oinfo); }
public void TestObjectClassInfo() { ConnectorAttributeInfoBuilder builder = new ConnectorAttributeInfoBuilder(); builder.Name = ("foo"); builder.ValueType = (typeof(String)); builder.Required = (true); builder.Readable = (true); builder.Updateable = (true); builder.MultiValued = (true); ObjectClassInfoBuilder obld = new ObjectClassInfoBuilder(); obld.ObjectType = ObjectClass.ACCOUNT_NAME; obld.IsContainer = true; obld.AddAttributeInfo(builder.Build()); ObjectClassInfo v1 = obld.Build(); ObjectClassInfo v2 = (ObjectClassInfo)CloneObject(v1); Assert.AreEqual(v1, v2); Assert.IsTrue(v2.IsContainer); }
public static Schema BuildSchema(Connector connector, GetSupportedObjectClassesDelegate getSupportedObjectClassesDelegate, GetObjectClassInfoDelegate getObjectClassInfoDelegate, GetSupportedOperationsDelegate getSupportedOperationsDelegate, GetUnSupportedOperationsDelegate getUnSupportedOperationsDelegate) { SchemaBuilder schemaBuilder = new SchemaBuilder(SafeType <Connector> .Get(connector)); //iterate through supported object classes foreach (ObjectClass oc in getSupportedObjectClassesDelegate()) { ObjectClassInfo ocInfo = getObjectClassInfoDelegate(oc); Assertions.NullCheck(ocInfo, "ocInfo"); //add object class to schema schemaBuilder.DefineObjectClass(ocInfo); //add supported operations IList <SafeType <SPIOperation> > supportedOps = getSupportedOperationsDelegate(oc); if (supportedOps != null) { foreach (SafeType <SPIOperation> op in supportedOps) { schemaBuilder.AddSupportedObjectClass(op, ocInfo); } } //remove unsupported operatons IList <SafeType <SPIOperation> > unSupportedOps = getUnSupportedOperationsDelegate(oc); if (unSupportedOps != null) { foreach (SafeType <SPIOperation> op in unSupportedOps) { schemaBuilder.RemoveSupportedObjectClass(op, ocInfo); } } } LOG.Debug("Finished retrieving schema"); return(schemaBuilder.Build()); }
public static IDictionary <ObjectClass, ICollection <string> > GetAttributesReturnedByDefault( GetSupportedObjectClassesDelegate getSupportedObjectClassesDelegate, GetObjectClassInfoDelegate getObjectClassInfoDelegate) { var attributesReturnedByDefault = new Dictionary <ObjectClass, ICollection <string> >(); //iterate through supported object classes foreach (ObjectClass oc in getSupportedObjectClassesDelegate()) { ObjectClassInfo ocInfo = getObjectClassInfoDelegate(oc); Assertions.NullCheck(ocInfo, "ocInfo"); //populate the list of default attributes to get attributesReturnedByDefault.Add(oc, new HashSet <string>()); foreach (ConnectorAttributeInfo caInfo in ocInfo.ConnectorAttributeInfos) { if (caInfo.IsReturnedByDefault) { attributesReturnedByDefault[oc].Add(caInfo.Name); } } } return(attributesReturnedByDefault); }
// 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); } }