≡ Menu

Critical Conditions

Share the knowledge

As I’ve covered in previous posts covering the basics of Teamcenter’s Conditions and discussing how to use Conditions in your ITK, I’ve been playing around with Conditions in Teamcenter lately and have generally found them to be useful and promising. But not everything has been wine and roses. There are some warts, some deficiencies, and some straight up errors with how they work. I feel that I would be remiss if I did not spend some time discussing the problems and pitfalls I’ve found.

WARNING: Don’t redefine parameter type

I could go into a long story about how I managed to cause a lot of grief for our admin, but I’ll cut to the chase: Once you define a condition, don’t go changing the parameter type. For example, if you create and deploy a Condition that works on Items, don’t change it to ItemRevision later. There is a known bug and that change will not be deployed to the server. The BMIDE will not tell you that there is any problem and you’ll appear to be able to deploy the change, but it won’t actually take. You’re better off either deleting the condition and then re-defining it, Or creating a new condition with a different name.

They’re tempting to overuse

This not a problem with Conditions, per se but with over-eager developers. Once you start using conditions, particularly within ITK, you may find yourself using them for every condition you need to check. If you’re not careful you could end up with a whole lot of very trivial Condition objects in the database, many of which might even be unused. There is only one “namespace” for conditions, and it is easy to clutter it up. So try to use some judgement and common sense about it.

If it’d take you two lines of code to do the same check as what the condition will give you, you’re probably better off using the ITK. You should also consider if the check involves any business logic or not. For example, you can probably create a Condition to check if a revision is an assembly or not. But the definition of assembly isn’t really something that depends on your business logic and it’s something easily enough to determine strictly with ITK. On the other hand, checking if an object has one of a particular set of release statuses to determine if it’s valid for some operation is dependent on your business logic and is conceivably something that could change over time, so for that I would give consideration to using a Condition.

Signature restrictions

Probably the first frustration that users experience is that the hooks in the BMIDE to use Conditions have very specific signatures. Usually the BMIDE will only let you use Conditions that take the UserSession object as input. This means that most Conditions used to configure the BMIDE can only check things like the current Group, Role, or Project of the user. For example, if you want to check if the current user has membership in ProjectX, even though they’re not logged into it right now, you can’t. You’d have to find some other way of checking for group membership.

Can’t Check for unset values

Another snag I ran into is that you can’t test for unset attribute values unless they’re a reference to another Business Object, i.e. tag_t references. In database SQL terms I want to test if any attribute IS NULL or IS NOT NULL. For example, say I had a Drawing item with a string attribute, checker_name, and an initial value of NULL. I might want to define a condition to determine if a checker has been assigned yet or not,

hasChecker(DrawingRevision d) := 
    d.checker_name != NULL # Error!

Unfortunately this isn’t possible because the BMIDE complains that the types don’t match. NULL can currently only be compared to object references (i.e. tag_t attributes), but checker in this example is a string attribute. Since NULL is a valid value in the underlying database tables, we should be able to test for it.

One note: I could test d.checker_name != "", but an empty string is not the same thing as NULL.

Few Functions

There are only three functions that you can use to manipulate the values you’re examining and apparently there’s no way for customers to add their own. The three functions provided are INLIST, which allows you to search for a value in a list, and ToUpper and ToLower, which transform a string value into upper or lowercase. It certainly didn’t take me long to come up with several functions that I wish I had or could define myself, for example:

  • Length(string or list)– return the number of characters in a string or elements in a list. 

    Example: Check if an string property has a minimum number of characters

    minimumLength(Workspace Object obj) := 
        Function::Length(obj.object_name) > 5 
        # Error: No such Length function exists

    Example: Check if an object has multiple statuses

    hasMultipleStatuses(WorkspaceObject obj) := 
        Function::Length(obj.release_status_list) > 1
  • ANY(Condition, list) – return true if the condition is true for anyvalue in the list 

    Example: Check if any revision of an item has multiple statuses

    hasRevWithMultipleStatuses(Item item) := 
        Function::Any(Condition::hasMultipleStatuses, 
                      item.item_revision_list)
  • ALL(Condition, list) – return True if the condition is true for allvalues in the list.
    Example:
    Check if all revisions of an item have multiple statuses

    allRevsHaveMultipleStatuses(Item item) := 
        Function::All(Condition::hasMultipleStatuses, 
                      item.item_revision_list) 
                      # Error - no such function

No access to Constants

Conditions can’t access Global or Business Object Constants. I had hoped to create a Business Object Constant, valid_statuses, which defined a list of status names. Then I wanted to test if an object had a valid status by defining a condition something like,

hasValidStatus(WorkspaceObject o) := 
    Function::INLIST(o.last_release_status, 
                     o.valid_statuses)

Where valid_statuses is the value of the Business Object Constant. It seems that your options are to either explicitly list the statuses in your condition definition,

hasValidStatus(WorkspaceObject o) := 
    o.last_release_status=”StatusA” 
    OR 
    o.last_release_status=”StatusB”

Or, to define an Business Object Operation and then use that in your condition,

hasValidStatus(WorkspaceObject o) := 
    o.hasValidStatus()

This is the approach used by the Foundation Condition isOtherSideLatestMature which invokes the isLatestRevisionMature() operation which evidently looks up the MaturityStatuses constant.

No “Dynamic Casting”

If you’re checking a revision object you can use the items_tag to get back to the parent Item and evaluate its properties.

# test if revision has the same name as it's parent item: 
hasItemsName(ItemRevision revision) := 
    revision.object_name = revision.items_tag.object_name

Now, you might expect, or at least I would, that If I had my own custom Item Type with its own custom attribute, that I could do the same thing for my custom Item type’s properties:

myRevHasSamePropertyAsItem(MyItemRevision my_revision) := 
    my_revision.my_rev_attribute = 
        my_revision.items_tag.my_item_attribute # Error!

As it turns out, items_tag cannot access properties defined on subtypes of Item. The reason is simple enough: items_tag is defined as a property of ItemRevision which refers to an object of type Item. So even though there’s no way for the items_tag of a MyItemRevision object to refer to anything but MyItem, you’re limited to accessing the properties defined for the base type, Item, and there isn’t any way to “cast” (to borrow a programming term) the reference to its proper type.

Small Beer: Minor, but Annoying Issues

In my examples above I used line breaks and # comments to clarify my examples. Neither is actually possible in real conditions, however. Line breaks will get you an error from the BMIDE and there is no such thing as a comment in the condition definition.

I won’t cry in my beer over it, but it is annoying.

Conclusions

This wraps up the series on Conditions for now. I hope the information will be useful. Have you tried using Conditions for anything yet? What have you found, good, bad or indifferent, about them? Please share you experiences with us.


Related Posts

[related_posts]

  • Narasimha

    Scott,

    Some concepts were bouncers to me,the way you analyzed and pointed out the flaws is commendable.

    I will comment once I do some hands-on on the above topics.

    After new changemangement has been introduced,I always used to try to create ECR and ECN with wrong users and again used to correct it after referring to conditions in BMIDE.

    After referring to your post and referring to sample in gtac I have used Conditions API and now if I supply username,password and group in my standalone ITK.I can get to know who can and who cannot create PR,ECR and ECN.It saved some of my time :-)

    Regards,
    Narasimha

  • Bob Donovan

    Hi, Thanks for sharing some great ideas.  

    Some of your examples and text is cut off on the right side of the text area. Can you fix this so that we can read the missing text?

    Bob Donovan

    • http://plmdojo.com Scott Pigman

      Bob, thanks for bringing that to my attention; I truly appreciate it. The formatting should be fixed now. It looked fine when I first published it but I made some changes to the theme I’m using awhile back and that’s probably when the page got screwed up.

  • Raj

    The condition engine in Tc Enterprise was more powerful than this

    • http://plmdojo.com/ Scott Pigman

      Could you give some examples?

Optimization WordPress Plugins & Solutions by W3 EDGE