Novell Identity Manager has a number of very powerful verbs, nouns, and tokens. One that I use a lot, but drives me mad on a regular basis is ParseDN.
Watch out for known limitations, as described at: http://www.novell.com/communities/node/4337/ parsedn-token-identity-manager-and-some-its-limitations.
ParseDN is pretty powerful and cool, but as described in the article above, it can only do what it can with the available data. (The issue above relates to LDAP naming, when the data about whether each node is a CN=, OU=, C=, DC=, or the like is not available. If it is not in the attribute you are using the token on, it cannot, alas, magically figure it out for you. I had so hoped it would somehow magically calculate the full LDAP DN, but that was not to be.)
The thing is, the help in Designer (at least last I looked in the 3.0 beta 1 build) tries to explain the token, but could really use some better examples. Thus I thought I would try and provide some of the most common ones I use.
All my examples are going to work with DN's in the format Identity Manager uses internally. That is, a DN that would look like \ACME-TREE\LAB\USERS\ACTIVE\BSMITH. In this example, the LDAP name might be CN=BSMITH,OU=ACTIVE,OU=USERS,O=LAB,T=ACME-TREE or somesuch. But for now, I will use the backslash format to explain it. The root most node, regardless of how you look at (IDM internal, or LDAP) is the ACME-TREE node, since it is closest to the root of the tree. (Ok, so it IS actually the tree name, hard to get closer to root than that, right?).
Leaf most node is the one farthest from the root, in our examples BSMITH (or CN=BSMITH in LDAP namespace).
The most common issue I use ParseDN for is changing the length of the DN. Usually I want to do one of three things. Chop off the tree name (root most node), chop off the BSMITH node (leaf most node) to get the parent container of the object, or just get the name of the object, without any of the path.
You have two controls, Start and Length.
Start is pretty easy. A start value of zero (0) means start at the beginning of the DN, which is root most. Where it gets kind of interesting, is working the other way, -1 means start at the leaf most node. So -2 would be start one node from the leaf most end.
Length is easy at first, a positive integer means go that number of nodes.
Negative one (-1), means go to the end of the nodes (leaf most). Negative 2 (-2) means go to one node before the leaf most node.
For the examples above, I would set the following values:
Chop off tree name:
Start: 1 (skip the first node)
Length: -1 (go to the end)
\ACME-TREE\LAB\USERS\ACTIVE\BSMITH would become \LAB\USERS\ACTIVE\BSMITH
Chop off last node: (Get the parent container)
Start: 0 (start at the beginning)
Length: -2 (go to one before the end)
\ACME-TREE\LAB\USERS\ACTIVE\BSMITH would become \ACME-TREE\LAB\USERS\ACTIVE\
Get the name of the object:
\ACME-TREE\LAB\USERS\ACTIVE\BSMITH would become BSMITH
It is worth noting that the Source DN() token and the Destination DN() token in Argument Builder both have the ability to specify these length and start values in a similar fashion. What ParseDN brings to the table that is additional, is conversion between formats (source, destination, LDAP (with the limits noted above), and others that you can define)
One trick to be careful of that I have noticed, is that trying to combine length changes in one move, can be fraught with peril. That is, trying to get the middle set of nodes can be tricky.
In principle to get the middle bits of a DN path, i.e. the part without the end node and without the tree name, you should be able to:
But in practice I have had a hard time doing this. What I mean by that is, it just does not work reliably. I am not sure why exactly. What I found works the best when you run into an issue like this one is to chop of the end (leaf most) node first, either as part of the Source DN token, (which as I mentioned above can do some of ParseDN's cool stuff) with a length of -1 and a start of 1, and the nest that under a ParseDN token to chop off the tree name.
Often I have the value of the DN stored as string in some other attribute, or it is coming from an object that is not actually the current operational object, or from somewhere else, where I cannot use the Source DN or Destination DN tokens.
One common example of that would be from the XPATH of -dn from the results of a query for an object as is discussed in the middle of this article at: http://www.novell.com/communities/node/4833/some-thoughts-xpath-novell-identity-manager
The issue is that if you want to use the Query token to find the a user in either the source or destination data store, that while it is quite powerful, there is no direct way to get the distinguished name of the object you are looking for. You would think, based on Argument Builders interface, that you could Query for the SourceDN token, but alas that does not work. In fact, the attribute you would want to return is called DN, but it is not a real attribute in the usual sense, so you cannot return it directly.
Instead what you need to do is query for the object you want, as appropriate, and get a nodeset value back. Part of the reason it is not so simple to do is that you could end up with a single or multiple results. In any case, you need to then use an XPATH expression of -dn to get the value out. The most common way is to set a local variable, as a nodeset. The value set into the local variable is a Query token for the object you are looking for. Then in the next action, set a local variable of type string, equal to the XPATH expression. Something like the following rule:
<do-set-local-variable name="SOURCE-DN" scope="policy">
<token-text xml:space="preserve">Object Class</token-text>
<do-set-local-variable name="SOURCE-DN" scope="policy">
In this example, we generate a Query against the source datasource (so depending on your channel (subscriber or publisher) it could be either eDirectory of the application, for a user with the current value of workforceID.
I like to scope things so that we only search from the container I know users are stored in, in this case defined by a Global Configuration Variable called eDirUserContainer. I really like scoping my searches, since sometimes the trees can be very large, and unconstrained searches can do a lot of extra work.
Now one of the tricks is ask for the return of an attribute you know will ALWAY be there on an object, If you think about it, Object Class is implicitly a mandatory attribute. Actually it is an explicitly mandatory attribute of the Top class, which every object class in the tree inherits from. Anyway, every object in the tree has Object Class defined, even if it is set to Unknown. Of course, in this case, you could probably also ask it to return the attribute you searched on, workforceID since if it is found, it must have it by definition.
Then once we have it set, note that the first SOURCE-DN is set as a nodeset variable, not a string, we use a second set local variable action to set the same variable name SOURCE-DN as a string, to the XPATH of $SOURCE-DN/@src-dn The $SOURCE-DN is how you represent the variable (with a leading dollar sign ($)) and then in the context of that variable get the attribute (the at sign (@)) src-dn.
If you need to ParseDN this to LDAP syntax, then you probably want to grab the attribute @qualified-src-dn instead which would look more like CN=BSMITH.OU=ACTIVE.OU=USERS.O=LAB.T=ACME-TREE. Which as discussed above can be ParseDN'ed into real LDAP syntax (which alas means mostly swapping periods with commas.)
If you have an expectation of returning more than one value in your search (I hope not for workforceID, one hopes that is unique in your tree), then you should probably iterate through the values returned inside a for-each loop, and get the value of each object returned. Otherwise you will only get the value from the first one, which may or may not be the one you want. You can always test to see how many values got returned by using an XPATH of something like count($SOURCE-DN) to get the number of nodes in the returned document, and if it is greater than 1, you may have a problem.
Whoever thought getting the distinguished name of an object could be so complex? (Wait till you try and get the DN of an object very soon after a move operation happened, and then see how much fun that can be! You often get two values returned, the old and the new, depending on when you query it).