{"id":101,"date":"2008-03-11T19:02:31","date_gmt":"2008-03-11T19:02:31","guid":{"rendered":"https:\/\/www.wapshere.com\/missmiis\/?p=101"},"modified":"2009-04-05T07:58:15","modified_gmt":"2009-04-05T07:58:15","slug":"advanced-attribute-flow-rules","status":"publish","type":"post","link":"https:\/\/www.wapshere.com\/missmiis\/advanced-attribute-flow-rules","title":{"rendered":"Advanced Attribute Flow Rules"},"content":{"rendered":"<p>Today I will introduce the simplest coding element in ILM &#8211; advanced attribute flows.<\/p>\n<p>Direct attribute flows can be done with no code, but they&#8217;re not all that interesting &#8211; all you can do is flow one value directly to another, or apply a constant value. To manipulate values, or to use the values of several incoming attributes, you need to write extension code.<\/p>\n<p><!--more--><\/p>\n<h4>Import or Export?<\/h4>\n<p>Advanced flow rules can only produce a single attribute value, but they can take multiple attributes as input. They will be either:<\/p>\n<ul>\n<li><strong>Import Flow Rules<\/strong> where multiple CS attributes are used to produce a single metaverse attribute; or<\/li>\n<li><strong>Export Flow Rules<\/strong> where multiple metaverse attributes are used to produce a single CS attribute.<\/li>\n<\/ul>\n<p>If you&#8217;re doing any type of data clean-up with your flow rules it is usually best to do this as an Import, so that only the nice, clean data gets into your metaverse.<\/p>\n<h4>Configure the flow rule in your MA<\/h4>\n<p>On the Attribute Flow page, choose the input and output attributes. Don&#8217;t worry that you haven&#8217;t written the code yet, or that you may need to change the input attributes later.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.wapshere.com\/images\/ma-advanced-flow.gif\" alt=\"\" \/><\/p>\n<p>Click on <strong>New<\/strong>. A new form pops up asking you to give the flow rule a name (you will use this name in your code).<\/p>\n<p>Now I never use the default name. It is ugly, unweildy, and explicitly mentions the attributes involved &#8211; which I will no doubt need to change later. So I adopt the simple convention of &#8220;import&#8221; or &#8220;export&#8221; followed by the name of the attribute on the output end.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.wapshere.com\/images\/ma-flowrulename.gif\" alt=\"\" \/><\/p>\n<h4>Create the MA Extension<\/h4>\n<p>If you haven&#8217;t already done so, create an extension project for this MA. If you followed the step above, ILM will have filled in a name for the extension dll on the Configure Extensions page.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.wapshere.com\/images\/ma-extn-name.gif\" alt=\"\" \/><\/p>\n<blockquote><p>On the &#8220;Run this rules extension in a seperate process&#8221; option &#8211; leave it unticked for now. You can change it later (if you need to for performance reasons), but the dll <em>must<\/em> run in the same process as the ILM server if you want to debug from Visual Studio. And if you&#8217;re just starting out with this you will want to debug.<\/p><\/blockquote>\n<p>In Identity Manager, click your MA and choose Create Extension. Use the same name as specified in your MA, as in the picture above.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.wapshere.com\/images\/ma_create_extn.gif\" alt=\"\" width=\"539\" height=\"238\" \/><\/p>\n<h4>Open the Project<\/h4>\n<p>I introduced the subject of Visual Studio in <a href=\"https:\/\/www.wapshere.com\/missmiis\/?p=102\">yesterday&#8217;s post<\/a>, and mentioned how I like to create an ILM Solution to keep track of all my projects. So, assuming you&#8217;ve done this, add your new project into the solution now.<\/p>\n<p>Otherwise just open the project on it&#8217;s own. It doesn&#8217;t have to be in a solution.<\/p>\n<p>One of the nice things about these projects is that they are already configured to compile to the Extensions folder. They also have any flow rules you&#8217;ve just configured helpfully inserted for you so you&#8217;ll know where to add your code. This is why it&#8217;s a great idea to configure some rules before creating the project.<\/p>\n<p>As I mentioned <a href=\"https:\/\/www.wapshere.com\/missmiis\/?p=102\">yesterday<\/a> though, you will need to change the class name:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.wapshere.com\/images\/maextn-class.gif\" border=\"0\" alt=\"\" width=\"406\" height=\"134\" \/><\/p>\n<h4>MapAttributesForImport\/Export<\/h4>\n<p>Now you can start to enter your flow rule code.<\/p>\n<ul>\n<li>Import flows go into <strong>Sub MapAttributesForImport<\/strong>;<\/li>\n<li>Export flow rules go into <strong>Sub MapAttributesForExport<\/strong>.<\/li>\n<\/ul>\n<p>The code takes the form of a simple Case statement, where the possible values are those flow rule names you set in the MA.<\/p>\n<p>\u00c2\u00a0<\/p>\n<p>Select Case FlowRuleName<\/p>\n<p>\u00c2\u00a0 Case &#8220;exportInfo&#8221;<\/p>\n<p>\u00c2\u00a0 <em>&lt;code&gt;<\/em><\/p>\n<p>\u00c2\u00a0 Case &#8220;exportDisplayName&#8221;<\/p>\n<p>\u00c2\u00a0 <em>&lt;code&gt;<\/em><\/p>\n<p>End Select<\/p>\n<h4>And the rules themselves?<\/h4>\n<p>The following will get you started writing a flow rule:<\/p>\n<ul>\n<li>mventry refers to the metaverse object,<\/li>\n<li>csentry refers to the connector space object,<\/li>\n<li>mventry(&#8220;<em>attribute<\/em>&#8220;).IsPresent tests that <em>attribute<\/em> has a value on the metaverse object,<\/li>\n<li>csentry(&#8220;<em>attribute<\/em>&#8220;).Value sets or returns the value of <em>attribute<\/em> on the CS object.<\/li>\n<\/ul>\n<p>Here&#8217;s an example of a group of export flow rules which set the Exchange mailbox quota in AD\/Exchange 2003. The &#8220;MailQuota&#8221;, &#8220;WarningPercent&#8221; and &#8220;BlockMailPercent&#8221; values have previously been imported into the metaverse from a management database. Note I am using IntegerValue rather than Value in the sums.<\/p>\n<p>\u00c2\u00a0<br \/>\n<code>Select Case FlowRuleName<br \/>\n\u00c2\u00a0 Case \"exportMDBUseDefaults\"<br \/>\n\u00c2\u00a0 \u00c2\u00a0 'Objects: Person -&gt; User<br \/>\n\u00c2\u00a0 'Description: MDBUserDefault is FALSE if MailQuota is set, otherwise TRUE<br \/>\n\u00c2\u00a0 'Attributes: MailQuota, inExchange<br \/>\n\u00c2\u00a0 \u00c2\u00a0 If mventry(\"inExchange\").Value = \"Yes\" Then<br \/>\n\u00c2\u00a0 \u00c2\u00a0 If mventry(\"MailQuota\").IsPresent Then<br \/>\n\u00c2\u00a0 \u00c2\u00a0 csentry(\"mDBUseDefaults\").Value = False<br \/>\n\u00c2\u00a0 \u00c2\u00a0 Else<br \/>\n\u00c2\u00a0 \u00c2\u00a0 csentry(\"mDBUseDefaults\").Value = True<br \/>\n\u00c2\u00a0 \u00c2\u00a0 End If<br \/>\n\u00c2\u00a0 \u00c2\u00a0 End If\u00c2\u00a0<br \/>\n\u00c2\u00a0 Case \"exportMDBStorageQuota\"<br \/>\n\u00c2\u00a0 \u00c2\u00a0 'Objects: Person -&gt; User<br \/>\n\u00c2\u00a0 \u00c2\u00a0 'Description: Convert WarningPercent to a KB value<br \/>\n\u00c2\u00a0 \u00c2\u00a0 'Attributes: MailQuota, WarningPercent, inExchange<br \/>\n\u00c2\u00a0 If mventry(\"inExchange\").Value = \"Yes\" Then<br \/>\n\u00c2\u00a0 \u00c2\u00a0 If mventry(\"MailQuota\").IsPresent Then<br \/>\n\u00c2\u00a0 \u00c2\u00a0 Dim x As Decimal = mventry(\"MailQuota\").IntegerValue * (mventry(\"WarningPercent\").IntegerValue \/ 100)<br \/>\n\u00c2\u00a0 \u00c2\u00a0 csentry(\"mDBStorageQuota\").IntegerValue = x.Round(x, 0)<br \/>\n\u00c2\u00a0 \u00c2\u00a0 End If<br \/>\n\u00c2\u00a0 \u00c2\u00a0 End If\u00c2\u00a0<br \/>\n\u00c2\u00a0 Case \"exportMDBOverHardQuotaLimit\"<br \/>\n\u00c2\u00a0 \u00c2\u00a0 'Objects: Person -&gt; User<br \/>\n\u00c2\u00a0 \u00c2\u00a0 'Description: Convert BlockMailPercent to a KB value<br \/>\n\u00c2\u00a0 \u00c2\u00a0 'Attributes: MailQuota, BlockMailPercent, inExchange<br \/>\n\u00c2\u00a0 If mventry(\"inExchange\").Value = \"Yes\" Then<br \/>\n\u00c2\u00a0 \u00c2\u00a0 If mventry(\"MailQuota\").IsPresent Then<br \/>\n\u00c2\u00a0 \u00c2\u00a0 Dim x As Decimal = mventry(\"MailQuota\").IntegerValue * (mventry(\"BlockMailPercent\").IntegerValue \/ 100)<br \/>\n\u00c2\u00a0 \u00c2\u00a0 csentry(\"mDBOverHardQuotaLimit\").IntegerValue = x.Round(x, 0)<br \/>\n\u00c2\u00a0 \u00c2\u00a0 End If<br \/>\n\u00c2\u00a0 \u00c2\u00a0 End If<br \/>\nEnd Select\u00c2\u00a0<br \/>\n<\/code><\/p>\n<h4>Compile and Test<\/h4>\n<p>Build your project. As I said before it should compile directly into the Extensions folder, where ILM will find it.<\/p>\n<p>Now you can test your new rule by running a Full Sync on the MA. More to come on <a href=\"https:\/\/www.wapshere.com\/missmiis\/?p=103\">debugging<\/a>&#8230;<\/p>\n<p>\u00c2\u00a0<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today I will introduce the simplest coding element in ILM &#8211; advanced attribute flows. Direct attribute flows can be done with no code, but they&#8217;re not all that interesting &#8211; all you can do is flow one value directly to another, or apply a constant value. To manipulate values, or to use the values of&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[34,28,19,30],"tags":[],"class_list":["post-101","post","type-post","status-publish","format-standard","hentry","category-ilm2007","category-miis2003","category-newbie","category-vbnet"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pkp1o-1D","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/posts\/101","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/comments?post=101"}],"version-history":[{"count":1,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/posts\/101\/revisions"}],"predecessor-version":[{"id":453,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/posts\/101\/revisions\/453"}],"wp:attachment":[{"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/media?parent=101"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/categories?post=101"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wapshere.com\/missmiis\/wp-json\/wp\/v2\/tags?post=101"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}