Ejemplo n.º 1
0
        /// <summary>
        /// Handles the ChildInitialized event of the ForEachPending ReplicatorActivity.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="ReplicatorChildEventArgs"/> instance containing the event data.</param>
        private void ForEachPending_ChildInitialized(object sender, ReplicatorChildEventArgs e)
        {
            Logger.Instance.WriteMethodEntry(EventIdentifier.UpdateLookupsForEachPendingChildInitialized, "Resource: '{0}'.", e.InstanceData);

            try
            {
                // Cast the instance data as a Guid and prepare the read resource activity
                // by assigning a resource ID for update and the attributes to be read
                Guid resource = new Guid();
                if (e.InstanceData != null)
                {
                    resource = (Guid)((Guid?)e.InstanceData);
                }

                ReadResourceActivity read = e.Activity as ReadResourceActivity;

                if (read == null)
                {
                    return;
                }

                read.ResourceId          = resource;
                read.SelectionAttributes = this.PendingRequests[resource].Select(parameter => parameter.PropertyName).ToArray();
            }
            finally
            {
                Logger.Instance.WriteMethodExit(EventIdentifier.UpdateLookupsForEachPendingChildInitialized, "Resource: '{0}'.", e.InstanceData);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Handles the ChildCompleted event of the ForEachPending ReplicatorActivity.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="ReplicatorChildEventArgs"/> instance containing the event data.</param>
        private void ForEachPending_ChildCompleted(object sender, ReplicatorChildEventArgs e)
        {
            Logger.Instance.WriteMethodEntry(EventIdentifier.UpdateLookupsForEachPendingChildCompleted, "Resource: '{0}'.", e.InstanceData);

            try
            {
                Guid resource = new Guid();
                if (e.InstanceData != null)
                {
                    resource = (Guid)((Guid?)e.InstanceData);
                }

                ReadResourceActivity read = e.Activity as ReadResourceActivity;
                if (read == null || read.Resource == null)
                {
                    return;
                }

                List <UpdateRequestParameter> changes = new List <UpdateRequestParameter>();
                foreach (UpdateRequestParameter parameter in this.PendingRequests[resource])
                {
                    // Read the current value of the attribute on the target resource
                    object currentValue = read.Resource[parameter.PropertyName];
                    if (currentValue != null)
                    {
                        // FIM inconsistently returns reference values as either UniqueIdentifiers or Guids
                        // To prevent repetitive checks, convert all UniqueIdentifiers to Guids,
                        // and any List<UniqueIdentifier> to List<Guid>
                        if (currentValue.GetType() == typeof(UniqueIdentifier))
                        {
                            currentValue = ((UniqueIdentifier)currentValue).GetGuid();
                        }
                        else if (currentValue.GetType() == typeof(List <UniqueIdentifier>))
                        {
                            List <Guid> guidList = (from id in (List <UniqueIdentifier>) currentValue select id.GetGuid()).ToList();
                            currentValue = guidList;
                        }
                    }

                    // Determine if the request represents a change based on type
                    bool change = false;
                    if (parameter.Mode == UpdateMode.Modify)
                    {
                        if (parameter.Value == null)
                        {
                            // If the new value is null, only submit the request parameter if the current value is not null
                            change = currentValue != null;
                        }
                        else if (parameter.Value.GetType().IsGenericType&& parameter.Value.GetType().GetGenericTypeDefinition() == typeof(List <>))
                        {
                            // If the new value is multi-valued, assume we are writing to a multi-valued attribute
                            // When the current value is null, simply add all new values
                            if (currentValue == null)
                            {
                                changes.AddRange(from object o in (IEnumerable)parameter.Value select new UpdateRequestParameter(parameter.PropertyName, UpdateMode.Insert, o));
                            }
                            else
                            {
                                if (!(currentValue is IEnumerable))
                                {
                                    currentValue = new object[] { currentValue };
                                }

                                // Identify all values that exist in the new list but not in the current list
                                // and submit them as insert request parameters
                                changes.AddRange(from object o in (IEnumerable)parameter.Value let contains = ((IEnumerable)currentValue).Cast <object>().Contains(o) where !contains select new UpdateRequestParameter(parameter.PropertyName, UpdateMode.Insert, o));

                                // Identify all values that exist in the current list but not in the new list
                                // and submit them as remove request parameters
                                changes.AddRange(from object o in (IEnumerable)currentValue let contains = ((IEnumerable)parameter.Value).Cast <object>().Contains(o) where !contains select new UpdateRequestParameter(parameter.PropertyName, UpdateMode.Remove, o));
                            }
                        }
                        else
                        {
                            // If the new value is not null and is single-valued,
                            // determine if it represents a change to the existing attribute value
                            if (currentValue == null)
                            {
                                change = true;
                            }
                            else
                            {
                                change = !currentValue.Equals(parameter.Value);
                            }
                        }
                    }
                    else
                    {
                        // Check if the insert or remove operation will result in a change
                        // based on the values currently in the target attribute
                        if (currentValue == null)
                        {
                            change = parameter.Mode == UpdateMode.Insert;
                        }
                        else if (parameter.Value != null && currentValue.GetType().IsGenericType&& currentValue.GetType().GetGenericTypeDefinition() == typeof(List <>))
                        {
                            bool contains = ((IEnumerable)currentValue).Cast <object>().Any(o => o.Equals(parameter.Value));

                            switch (parameter.Mode)
                            {
                            case UpdateMode.Insert:
                                change = !contains;
                                break;

                            case UpdateMode.Remove:
                                change = contains;
                                break;
                            }
                        }
                        else
                        {
                            // Current value is not null and is not multivalued or we are trying to insert or remove a null value
                            // The second possibility should have been caught earlier, while the second indicates that the calling activity has been misconfigured
                            // Let the request through so the FIM Service can throw an error if appropriate
                            change = true;
                        }
                    }

                    // If the request parameter will result in a change, add it to the change list
                    // Note that manipulation of multi-valued attributes via modify (overwrite) will have been
                    // addressed via direct insertion of request parameters to the changes collection
                    // In that scenario, change will always be false to prevent inclusion of the original request parameter
                    if (change)
                    {
                        changes.Add(parameter);
                    }
                }

                // If we have changes, add the request to the list that will be submitted
                if (changes.Count > 0)
                {
                    this.UpdateRequests.Add(resource, changes);
                }
            }
            finally
            {
                Logger.Instance.WriteMethodExit(EventIdentifier.UpdateLookupsForEachPendingChildCompleted, "Resource: '{0}'.", e.InstanceData);
            }
        }