Traversing the ArchestrA Object inheritance tree with GRAccess

by Klaus Graefensteiner 18. September 2008 05:01

Introduction

In this blog post I am describing how to recursively apply an operation to all instances of a template and the derived templates of this given template. In this case I am bumping up the configuration version number of each of the directly and indirectly derived instance objects by performing a Checkout, Save and Checkin operation.

Munich Transportation Tree

Figure 1: Munich Transportation Tree

 

Source code listing

This is the complete listing of the Program.cs file. This file compiles to a console application that can be controlled by a set of parameters. The listing describes the list of parameters.
   1: using System;
   2: using System.Collections.Generic;
   3: //GRAccess
   4: using ArchestrA.GRAccess;
   5:  
   6:  
   7: namespace ValidatePlus
   8: {
   9:     class Program
  10:     {
  11:         private static GRAccessAppClass GR;
  12:         private static IGalaxies Galaxies;
  13:         private static IGalaxy G;
  14:         private static ICommandResult CR;
  15:  
  16:  
  17:         static void Main(string[] args)
  18:         {
  19:             #region Command Line Argument Parsing
  20:  
  21:             //("ValidatePlus Usage:");
  22:             //("+++++++++++++++++++++");
  23:  
  24:             //("   g=<Galaxy Name>");
  25:             //("   gr=<GR Server Node>");
  26:             //("   u=<User Name>");
  27:             //("   pw=<Password>");
  28:             //("   tn=<Template Name>. Templates start with '$'!");
  29:             //("   r=<Is recursive? true or false?>");
  30:             //("   -> The order of the parameters doesn't matter!");
  31:             //("   -> There must be 6 parameters!");
  32:             //("   -> Use empty space characters to separate parameter=value pairs!");
  33:             //("   -> Don't use commas or semi-colon to separate parameter=value pairs!");
  34:             //("   -> The parameter=value pairs can't be longer than 254 characters!");
  35:             //("   -> The parameter specifier can't be longer than 3 characters!");
  36:  
  37:             //("   Example:");
  38:             //("   ValidatePlus gr=localhost g=Casino u=Administrator pw=ww tn=$AbstractComputerTemplate r=true");
  39:  
  40:             //Initialize dictionary
  41:             Dictionary<string, string> CmdParams = new Dictionary<string, string>(5);
  42:  
  43:             CmdParams.Add("gr", Environment.MachineName);
  44:             CmdParams.Add("g", "");
  45:             CmdParams.Add("u", "");
  46:             CmdParams.Add("pw", "");
  47:             CmdParams.Add("tn", "");
  48:             CmdParams.Add("r", "");
  49:  
  50:  
  51:             if (args.GetLength(0) != CmdParams.Count)
  52:             {
  53:                 PrintHelp();
  54:                 return;
  55:             }
  56:             foreach (string s in args)
  57:             {
  58:                 if (s.Length > 255)
  59:                 {
  60:                     PrintHelp();
  61:                     return;
  62:                 }
  63:  
  64:                 if (s.IndexOf('=') > 3)
  65:                 {
  66:                     PrintHelp();
  67:                     return;
  68:                 }
  69:  
  70:                 if (s.Split('=').GetLength(0) != 2)
  71:                 {
  72:                     PrintHelp();
  73:                     return;
  74:                 }
  75:                 try
  76:                 {
  77:                     string temp = CmdParams[(s.Split('='))[0]];
  78:                 }
  79:                 catch
  80:                 {
  81:                     PrintHelp();
  82:                     return;
  83:                 }
  84:  
  85:                 CmdParams[(s.Split('='))[0]] = ((s.Split('='))[1]);
  86:             }
  87:  
  88:             if (0 == String.Compare(CmdParams["gr"], "localhost", true))
  89:             {
  90:                 CmdParams["gr"] = Environment.MachineName;
  91:             }
  92:  
  93:             string GRMachineName = CmdParams["gr"];
  94:             string GalaxyName = CmdParams["g"];
  95:             string UserName = CmdParams["u"];
  96:             string Password = CmdParams["pw"];
  97:  
  98:             string TemplateName = CmdParams["tn"];
  99:             string Recursive = CmdParams["r"];
 100:             bool IsRecursive;
 101:  
 102:             if (Recursive.ToLower().Equals("true"))
 103:             {
 104:                 IsRecursive = true;
 105:             }
 106:             else if (Recursive.ToLower().Equals("false"))
 107:             {
 108:                 IsRecursive = false;
 109:             }
 110:             else
 111:             {
 112:                 PrintHelp();
 113:                 return;
 114:             }
 115:  
 116:             #endregion
 117:  
 118:             GR = new GRAccessAppClass();
 119:  
 120:             Galaxies = GR.QueryGalaxies(GRMachineName);
 121:  
 122:             if (Galaxies == null || GR.CommandResult.Successful == false)
 123:             {
 124:                 Console.Out.WriteLine(GR.CommandResult.Text + " : " + GR.CommandResult.CustomMessage);
 125:                 return;
 126:             }
 127:  
 128:             G = Galaxies[GalaxyName];
 129:  
 130:             if (G == null)
 131:             {
 132:                 Console.Out.WriteLine("Galaxy {0} not found on server {1}!", GalaxyName, GRMachineName);
 133:                 return;
 134:             }
 135:  
 136:             G.Login(UserName, Password);
 137:             CR = GR.CommandResult;
 138:             if (!CR.Successful)
 139:             {
 140:                 Console.Out.WriteLine("Login Galaxy Failed: " + CR.Text + " : " + CR.CustomMessage);
 141:                 return;
 142:             }
 143:             Console.Out.WriteLine("Login Galaxy Successful!");
 144:  
 145:             if(IsRecursive)
 146:             {
 147:                 GetDerivedTemplates(TemplateName);
 148:             }
 149:             else
 150:             {
 151:                 ValidateObjects(TemplateName);
 152:             }
 153:             
 154:             
 155:             Console.Out.WriteLine(TemplateName + " has been successfully validated!");
 156:             G.Logout();
 157:             
 158:         }
 159:  
 160:         #region Helper Methods
 161:  
 162:         static void GetDerivedTemplates(string templateName)
 163:         {
 164:             Console.Out.WriteLine(string.Format("Getting child objects from Template: {0}",
 165:                                                        templateName)); 
 166:  
 167:             IgObjects Templates = G.QueryObjects(EgObjectIsTemplateOrInstance.gObjectIsTemplate,
 168:                    EConditionType.derivedOrInstantiatedFrom, templateName,
 169:                    EMatch.MatchCondition);
 170:  
 171:             CR = G.CommandResult;
 172:             if (!CR.Successful)
 173:             {
 174:                 Console.Out.WriteLine(string.Format("QueryTemplates Failed for Template {0}: {1} - {2}",
 175:                                                            templateName, CR.Text, CR.CustomMessage));
 176:                 return;
 177:             }
 178:  
 179:             foreach(ITemplate template in Templates)
 180:             {
 181:                 GetDerivedTemplates(template.Tagname);
 182:             }
 183:             ValidateObjects(templateName);
 184:  
 185:         }
 186:  
 187:         static void ValidateObjects(string templateName)
 188:         {
 189:  
 190:             IgObjects Objects = G.QueryObjects(EgObjectIsTemplateOrInstance.gObjectIsInstance,
 191:                                            EConditionType.derivedOrInstantiatedFrom, templateName,
 192:                                            EMatch.MatchCondition);
 193:  
 194:             CR = G.CommandResult;
 195:             if (!CR.Successful)
 196:             {
 197:                 Console.Out.WriteLine(string.Format("QueryObjects Failed for Template {0}: {1} - {2}",
 198:                                                            templateName, CR.Text, CR.CustomMessage));
 199:                 return;
 200:             }
 201:  
 202:             if (Objects.count == 0)
 203:             {
 204:                 Console.Out.WriteLine(string.Format("No instances found for Template: {0}", templateName));
 205:  
 206:             }
 207:  
 208:             foreach (IgObject o in Objects)
 209:             {
 210:  
 211:                 Console.Out.Write(string.Format("{0}", o.Tagname));
 212:  
 213:                 Console.Out.Write(" -> CheckOut");
 214:                 o.CheckOut();
 215:                 CR = G.CommandResult;
 216:                 if (!CR.Successful)
 217:                 {
 218:                     Console.Out.WriteLine(string.Format("Checkout Failed for Instance {0}: {1} - {2}",
 219:                                                                o.Tagname, CR.Text, CR.CustomMessage));
 220:                 }
 221:  
 222:                 Console.Out.Write(" -> Save");
 223:                 o.Save();
 224:                 CR = G.CommandResult;
 225:                 if (!CR.Successful)
 226:                 {
 227:                     Console.Out.WriteLine(string.Format("Save Failed for Instance {0}: {1} - {2}",
 228:                                                                o.Tagname, CR.Text, CR.CustomMessage));
 229:                 }
 230:  
 231:                 Console.Out.Write(" -> CheckIn\n");
 232:                 o.CheckIn("ValidatePlus");
 233:                 CR = G.CommandResult;
 234:                 if (!CR.Successful)
 235:                 {
 236:                     Console.Out.WriteLine(string.Format("Checkin Failed for Instance {0}: {1} - {2}",
 237:                                                                o.Tagname, CR.Text, CR.CustomMessage));
 238:                 }
 239:             }
 240:         }
 241:         
 242:         static void PrintHelp()
 243:         {
 244:             Console.WriteLine("ValidatePlus Usage:");
 245:             Console.WriteLine("+++++++++++++++++++++");
 246:  
 247:             Console.WriteLine("   g=<Galaxy Name>");
 248:             Console.WriteLine("   gr=<GR Server Node>");
 249:             Console.WriteLine("   u=<User Name>");
 250:             Console.WriteLine("   pw=<Password>");
 251:             Console.WriteLine("   tn=<Template Name>. Templates start with '$'!");
 252:             Console.WriteLine("   r=true for recursion or r=false otherwise");
 253:             Console.WriteLine("   -> The order of the parameters doesn't matter!");
 254:             Console.WriteLine("   -> There must be 6 parameters!");
 255:             Console.WriteLine("   -> Use empty space characters to separate parameter=value pairs!");
 256:             Console.WriteLine("   -> Don't use commas or semi-colon to separate parameter=value pairs!");
 257:             Console.WriteLine("   -> The parameter=value pairs can't be longer than 254 characters!");
 258:             Console.WriteLine("   -> The parameter specifier can't be longer than 3 characters!");
 259:  
 260:             Console.WriteLine("   Example:");
 261:             Console.WriteLine("   ValidatePlus gr=localhost g=Casino u=Administrator pw=ww tn=$AbstractComputerTemplate r=true");
 262:         }
 263:         #endregion
 264:     }
 265: }

Design notes

There are three key points to get the task at hand accomplished using GRAccess.

Finding the child instances of a given template tagname

Call the function QueryObjects and look for instances that are derived from a given template tagname.
   1: IgObjects Objects = G.QueryObjects(EgObjectIsTemplateOrInstance.gObjectIsInstance,
   2:                                EConditionType.derivedOrInstantiatedFrom, templateName,
   3:                                EMatch.MatchCondition);

Finding the child templates of a given template tagname

This time call QueryObjects and look for templates that are derived from a given template tagname.
   1: IgObjects Templates = G.QueryObjects(EgObjectIsTemplateOrInstance.gObjectIsTemplate,
   2:        EConditionType.derivedOrInstantiatedFrom, templateName,
   3:        EMatch.MatchCondition);

Factoring out the code block that gets called recursively

Because templates can have derived templates, which themselves can have derived templates, it makes sense to factor out the query for templates in a method that can be called by itself recursively.
   1: static void GetDerivedTemplates(string templateName)
   2: {
   3:     Console.Out.WriteLine(string.Format("Getting child objects from Template: {0}",
   4:                                                templateName)); 
   5:  
   6:     IgObjects Templates = G.QueryObjects(EgObjectIsTemplateOrInstance.gObjectIsTemplate,
   7:            EConditionType.derivedOrInstantiatedFrom, templateName,
   8:            EMatch.MatchCondition);
   9:  
  10:     CR = G.CommandResult;
  11:     if (!CR.Successful)
  12:     {
  13:         Console.Out.WriteLine(string.Format("QueryTemplates Failed for Template {0}: {1} - {2}",
  14:                                                    templateName, CR.Text, CR.CustomMessage));
  15:         return;
  16:     }
  17:  
  18:     foreach(ITemplate template in Templates)
  19:     {
  20:         GetDerivedTemplates(template.Tagname);
  21:     }
  22:     ValidateObjects(templateName);
  23:  
  24: }

Test run

Compiling the program

Run the following command on the command prompt to compile the ValidatePlus.exe program. Remember that you need to reference ArchestrA.GRAccess.dll.

   1: csc /out:ValidatePlus.exe program.cs /r:"C:\Program Files\Common Files\
   2: ArchestrA\ArchestrA.GRAccess.dll"

Usage example

   1: ValidatePlus gr=localhost g=Casino u=Administrator pw=ww tn=$AbstractComputerTemplate r=true
   2:  

Example input and output

The following graphics show an example inheritance tree in the IDE and the output that the traversal of this tree generated.

Example Derivation Tree

Figure 2: Sample derivation tree in the IDE

 

Output generated by traversing the example derivation tree

Figure 3: Output generated by sample derivation tree traversal

Download

The source code for this sample can be downloaded here: ValidatePlus.zip

Ausblick

Traversing the ArchestrA Object inheritance tree is a common GRAccess programming task. The procedure described in this post can easily be modified to also travers the Model or the Deployment tree. All you need to do is to modify the QueryObjects() parameters to switch to a particular view.

Tags:

C# | GRAccess Toolkit | WAS | Wonderware

Comments are closed

About Klaus Graefensteiner

I like the programming of machines.

Add to Google Reader or Homepage

LinkedIn FacebookTwitter View Klaus Graefensteiner's profile on Technorati
Klaus Graefensteiner

Klaus Graefensteiner
works as Developer In Test and is founder of the PowerShell Unit Testing Framework PSUnit. More...

Open Source Projects

PSUnit is a Unit Testing framwork for PowerShell. It is designed for simplicity and hosted by Codeplex.
BlogShell is The tool for lazy developers who like to automate the composition of blog content during the writing of a blog post. It is hosted by CodePlex.

Administration

About

Powered by:
BlogEngine.Net
Version: 1.6.1.0

License:
Creative Commons License

Copyright:
© Copyright 2012, Klaus Graefensteiner.

Disclaimer:
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

Theme design:
This blog theme was designed and is copyrighted 2012 by Klaus Graefensteiner

Rendertime:
Page rendered at 5/17/2012 2:56:07 PM (PST Pacific Standard Time UTC DST -7)