Perl best practices part 2: getting Properties

Last week, we explored how to use ElectricCommander properties to ease and speed up your step development. This week, we will build on last week function InvokeCommander().

sub getP()

Accessing a property value in ElectricCommander is easy and straightforward. You have several options:

  • Standard substitution: $[/path/to/my/property]. The problem is if the property does not exit, the step fail even before it start.
  • You can use the special Javascript property $[/javascript] but I found the syntax a little confusing.
  • And finally you can use the API $ec->getProperty(“/path/to/my/property”) but again the step will fail if the property does not exist, this time at run time.

But now we have this awesome function InvokeCommander() on which we can build to get our property and manage error cases gracefully. So with one of my colleagues, Mike Westerhof, we came up with getP() which is basically $ec->getProperty(), returning either the property value or undef in case of error.

As you can see in the code below, it’s a simple encapsulation with InvokeCommander() and some basic error management.

#######################################################################
#
# Return property value or undef in case of error (non existing)
#
#######################################################################
sub getP
{
  my $prop=shift;

  my($success, $xPath, $errMsg, $errCode)=
          InvokeCommander(“SuppressLog IgnoreError”,
                          “getProperty”,
                         $prop);
  return undef if ($success != 1);
  my $val= $xPath->findvalue(“//value”);
  return($val);
}

To use it simply invoke:

$value=getP(“/path/to/my/property”);

sub getPS()

Of course, once you have single property covered, you need to start thinking about a bunch of them, either as a set of properties on an object or as a simple PropertySheet. Fortunately, we can group some two cases in one call using the path option for getProperties(). The other question is of course about depth. Do you want to get only the top level properties or work you way down in nested PropertySheets?

So again with Mike’s help, we wrote getPS(). Our main discussion was around what data structure to use and we finally decided on using Hash references. We agreed it’s not necessarily the easiest structure but it’s efficient and fairly explicit. If you’re going to learn Perl, you’ll definitively need this tool in your arsenal anyway.

So here is an example on how to use getPS()  to get the properties associated with an artifact version. I wrote it for a customer (a large toy manufacturer) who asked for it on the day I coded getPS. Talk about great timing!

#
# The second argument is a Boolean to recurse or not
# getPS() returns a Hash reference
#
my $propertyHashRef = getPS(“/artifactVersions/$group:$key:$version”, 0);

#
# Loop on the Hash keys
#
foreach my $name (keys($propertyHashRef)) {
  print “Property: $namen”;
   print “Value ” . $propertyHashRef->{“$name”} . “n”;
}

Here is another example with recursivity this time. When a nested PropertySheet is found in getPS(), a new Hash is created and the reference is associated with its name (the key) instead of a “normal” value. So when we explore the returned Hash reference, we need to test if the entry is a Hash or a “normal” entry.

For greater visibility, the indentation is increased at each sub-level when printing the results (if you’re not a Perl specialist, the ‘x’ operator is the replicator -in our case, we “multiply” two spaces by the depth level to create indentation)

$[/projects/EC-Admin/scripts/perlHeaderJSON]
$[/projects/EC-Admin/scripts/perlLibJSON]

my $propertyHashRef = getPS(“/server/ec_ui”, 1);
displayNestedPS($propertyHashRef, 0);

sub displayNestedPS()
{
  my $Href=shift;         # Hash reference
  my $depth=shift;      # Depth level (for indentation)

  foreach my $name (keys($Href)) {
    printf(“sProperty: sn”, ”  ” x $depth, $name);
    # testing for a nested PS
    if (ref($Href->{“$name”}) eq ‘HASH’) {
      displayNestedPS($Href->{“$name”}, $depth+1);
    } else {
      # normal property
      printf(“sValue: s n”, ”  ” x $depth, $Href->{“$name”});
    }
  }
}

Conclusion

We looked at how to build on top of InvokeCommander() with two very common needs. Those 2 functions are part of the EC-Admin project (version 1.3.3) and can be found on our GitHub Commander repository at https://github.com/electriccommunity/electriccommander/tree/master/EC-Admin.

My goal is to grow this library of functions to make it more useful for our customers so if you have any ideas or needs, please leave me a comment below or contact me directly by email.

Laurent Rochette

Laurent Rochette is a Professional Service Engineer with Electric Cloud. He trains customers on our products and help them with deployments and consulting to enable them to use our products effectively. Prior to joining Electric Cloud, Laurent served as an IT Architect at Mentor Graphics. Laurent holds a Master degree in Computer Science from the Grenoble Polytechnic Institute (INPG) in France.

By continuing to browse or by dismissing this alert you agree to the storing of first- and third-party cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts. See privacy policy.