FIM 2010 R2: Metaverse Attribute Flow Precedence and dealing with Blank values


Introduction

In FIM Attribute flow precedence determines which Management agent (MA) gets priority when more than one is contributing to a field in the Metaverse. If an MA does not have a value then the value of the next one down in the priority list is used. This can become a problem if you have a MA at the top of the list who you have designated as the authoritative source for that field. So if the field is blank in the authoritative MA you want the field value exported out to the remote system to be blank even where other contributing MAs have a value. The example below uses the Middle initial field to illustrate this problem and a work around that I did.

 

Case Overview

Contoso wants to update their Active directory (AD) with data from Human Resources (HR) database. One of the fields that will flow from the HR MA to the AD MA is the middle initial field. AD already has pre-existing data that should be overwritten. Not all users in AD are managed in HR system so there is need to maintain the AD records of some users.

Contoso would like the following requirements for the synchronisation of middle initial

  1. If a value exists in HR then overwrite AD.
  2. If a value does not exists in HR then set AD value to blank.
  3. If HR is not contributing to the AD object then use the value in AD.

Solution requirement

  1. We want user data from Contoso AD projected into the FIM metaverse (MV)
  2. We want a join between HR MA connector space (CS) object and the MV object.
  3. We want to be able to identifying when an HR MA object is connected to the MV object.
  4. We want to capture the AD object Initials separate from the HR MA Initials.
  5. We want to export the initials based on Contoso?s requirements.

Solution design

We want user data from Contoso AD projected into the FIM metaverse (MV). Create a person projection rule for the AD MA

  1. We want a join between Contoso HR MA connector space (CS) object and the MV object. Create a join for a field (e.g email or employee number) in the Contoso HR MA to the MV.
  2. We want to be able to identifying when an HR MA object is connected to the MV object. Create a string field in MV for person Object called HRFeed. Add an advanced attribute flow in Contoso HR MA which will flow a constant value of ?HR? into the MV.HRFeed.
  3. We want to capture the AD object Initials separate from the HR MA Initials. In the Contoso HR MA flow the Middle Initial to MV.Middlename. In the AD MA Flow the Initials to MV.Initials
  4. We want to export the initials based on Contoso?s requirements. In the AD MA create an Advance export flow, take MV.Middlename,Initials,HRFeed flowing to CS.Initials, call the name of the flow rule ?ExportInitials?. Write C# logic in the sync engine.

Code logic

The ExportInitials flow rule.

  1. If MV.HRFeed Ispresent then HR is connected to MV object, use the MV.middlename if it is present. 
  2. If  MV.HRFeed is not Present, then HR is not connected to the MV object, use the MV.Initials if it is present. 

 

Code

MA Extension.cs

void IMASynchronization.MapAttributesForExport (string FlowRuleName, MVEntry mventry, CSEntry csentry)
        {
             switch (FlowRuleName)
            {
                 case "ExportInitials":
                    {
                        //Declare Variables
                        string mventryRegValue = "HRFeed";
                         string mventryRegMValue = "Middlename";
                         string mventryADMValue = "Initials";
                         string csmnameValue = "Initials";
                        //if there is middlename value use it
                         if (mventry[mventryRegMValue].IsPresent)
                        {
                            csentry[csmnameValue].Value = mventry[mventryRegMValue].Value;
                        }
                        Else
                       //if there is no HR connection then use the AD Initials contribution 
                       if (!mventry[mventryRegValue].IsPresent && mventry[mventryADMValue].IsPresent)
                        {
                            csentry[csmnameValue].Value = mventry[mventryADMValue].Value;
                        }                                         }
                     break; 
            }
        }