It's all about the answers!

Ask a question

RAM Custom Policy: How to find approvers and their vote?


Angela Borchard (701120) | asked Dec 05 '12, 4:17 a.m.
edited Feb 27 '13, 5:10 p.m.

Hello,

I need to write a custom policy to do the following:

1. Identify who the approvers are (User Groups and/or Users) and

2. If any users are added as approvers directly, then they must approve.

3. If any groups are added as approvers, then at least 1 member from each approving group must have approved. (ie not all approvers within the group need to approve - only 1 needs to approve.
 
(Note the approvers are not standard for each asset and are typically a group defined within a community - ie APPROVER GROUP 1, APPROVER GROUP 2  but may also be an individual user (Joe Smith). Therefore the asset owner will add the reviewers and approvers.

For example:

Approvers

- Joe Smith

- Group A [Approvers]

- Group B [Approvers]

Then Joe must approve and 1 person from Group A Approvers and 1 person from Group B Approvers must approve.

Can you please advise how to do this via the API?

Approvers

I have been exploring the API as follows:

Lifecycle lifecycle = asset.getLifecycle().getValue();Set <Authorization> auth = lifecycle.getReviewBoardMembers();

StateConfiguration stateConfig = LifecycleUtilities.getStateConfiguration(lifecycle, asset.getState());

ReviewConfiguration revConfig = stateConfig.getReviewConfiguration();

//if (revConfig == null) {

//revConfig = new ReviewConfiguration();

//}

Set <Reviewer> reviewers = stateConfig.getReviewers();

Reviewer r1;

r1.isVoteAllowed();

RAMAsset asset2;

RAMVote [] ramVote = asset2.getCurrentStateHistory().getVotes();

ramVote[0].getVoteChoice();

Thanks,

-Angela

3 answers



permanent link
Gili Mendel (1.8k56) | answered Mar 06 '13, 11:19 a.m.
JAZZ DEVELOPER
Looking at the code above, there is a minor glitch, where as it will require EVERYONE in the group to approve, in order  for the policy to to return success.  I fixed/cleaned up the code below -- simple change. 

I had a simple configuration: two reviewers, two groups, policy to run on actions and updates, and a criteria for the policy to return success before moving to the next stage.   (you can optionally run this policy on a timer)





As you can see ... as reviewer voted, policy worked properly








 public Result test()
  {
      Result status = new Result(this);
      status.setReturnCode(Result.ERROR);
     
      PolicyContext policyContext = this.getPolicyContext();
      RAMAsset asset = policyContext.getRAMAsset();
     
      if (isAssetApproved(asset, status))
      {
         status.setMessage("Approval creteria has been met");
         status.setReturnCode(Result.SUCCESS);
      }
      else
      {   
         status.setMessage("Approval creteria has NOT been met");
      }
     
      return status;
   }
  
  
  
   /*  An asset is approved when the following occurs:
    *      - If any USERS are allocated as approvers, then all users MUST approve.
    *      - If any GROUPS are allocated as approvers, then at least 1 member from each group MUST approve.
    */
   private boolean isAssetApproved(RAMAsset asset, Result status)
   {
      boolean assetApproved = true;
      Lifecycle lifecycle = null;
      ClosableIterator<IUserInformation> userGroupIter = null;
     
      try
      {
         Method getLifecycleMethod = asset.getClass().getDeclaredMethod("getLifecycle");
         getLifecycleMethod.setAccessible(true);
         lifecycle = (Lifecycle)getLifecycleMethod.invoke(asset);
      } catch(NoSuchMethodException e) {
         System.out.println("Exception: \n" + e.toString());
      } catch (IllegalArgumentException e) {
         System.out.println("Exception: \n" + e.toString());
      } catch (IllegalAccessException e) {
         System.out.println("Exception: \n" + e.toString());
      } catch (InvocationTargetException e) {
         System.out.println("Exception: \n" + e.toString());
      }
      
      StateConfiguration stateConfig = LifecycleUtilities.getStateConfiguration(lifecycle, asset.getState().getIdentifier());
     
      Set<String> approvingUsers = new HashSet<String>();
     
      for(RAMVote vote : asset.getCurrentStateHistory().getVotes())
      {
         if(VoteChoice.APPROVE.equals(vote.getVoteChoice()))
         {
            approvingUsers.add(vote.getUser().getUid());
         }
      }
     
      for (Reviewer reviewer : stateConfig.getReviewers())
      {
         if(reviewer.isVoteAllowed())
         {
            if(reviewer.getUser() != null)
            {
               if(!approvingUsers.contains(reviewer.getUser().getValue().getIdentifier()))
               {
                  assetApproved = false;
                  status.addDetail(new ResultDetail(Result.ERROR,
                                   "<font color=red>Reviewer\t["+reviewer.getUser().getValue().getName()+"] have not approved yet</font>"));
               }
               else
                  status.addDetail(new ResultDetail(Result.SUCCESS,
                                   "Reviewer\t["+reviewer.getUser().getValue().getName()+"] approved"));
            }
            else if(reviewer.getUserGroup() != null)
            {
               String groupId = JAXBLinksUtil.getUserGroupIdentifier(reviewer.getUserGroup().getHref());
               UserGroupInstance userGroup = null;
               try
               {
                  userGroup = SecurityManager.getManager().getUserGroup(Integer.parseInt(groupId));
               } catch (NumberFormatException e) {
                  System.out.println("Exception: \n" + e.toString());
               } catch (Exception e) {
                  System.out.println("Exception: \n" + e.toString());
               }
                  
               try
               {
                  userGroupIter = userGroup.getAllUsers(UserGroupInstance.START_WITH_FIRST_USER);
                  int approvals = 0;
                  for(IUserInformation user : userGroupIter)
                     if(approvingUsers.contains(user.getUid()))
                            approvals++;
                 
                  if (approvals < APPROVAL_GROUP_MIN) {
                      assetApproved = false;
                      status.addDetail(new ResultDetail(Result.ERROR,
                                      "<font color=red>Group\t["+userGroup.getName()+"] did not met creteria with "+approvals+" approvals</font>"));
                  }
                  else
                      status.addDetail(new ResultDetail(Result.SUCCESS,
                                      "Group\t["+userGroup.getName()+"] met approval creteria"));
                           
               }
               finally
               {
                  if(userGroupIter != null)
                  {
                     userGroupIter.close();
                  }
               }
            }   
         }
      }       
      return assetApproved;
   }


permanent link
Angela Borchard (701120) | answered Feb 27 '13, 5:12 p.m.

Hi All,

Thank you for the information. I have incorporated the code into a policy and a policy governor (which I have emailed to Sheehan Anderson).

The policy doesnt seem to be working as required.

Can you please assist?

Thanks,

-Angela


Comments
Gili Mendel commented Mar 04 '13, 1:33 p.m.
JAZZ DEVELOPER

... if you provide more info, we may be able to help guide you on this.
what specifically is not working for you?


permanent link
Sheehan Anderson (1.2k4) | answered Dec 06 '12, 2:47 p.m.
JAZZ DEVELOPER
edited Dec 06 '12, 2:51 p.m.
Here's the test method of a policy to verify that all aprovers (both individuals and users in groups) have approved.  To make it compile you'll need to include the com.ibm.ram.repository.jar file available on the server in the <install dir>\IBM\WebSphere\AppServer\profiles\AppSrv01\installedApps\<cell>\RAM1WebApplication.ear\com.ibm.ram.repository.web.war\WEB-INF\lib directory.

public Result test() {
		RAMAsset asset = getPolicyContext().getRAMAsset();
		Lifecycle lifecycle = null;
		try {
			Method getLifecycleMethod = asset.getClass().getDeclaredMethod("getLifecycle");
			getLifecycleMethod.setAccessible(true);
			lifecycle = (Lifecycle)getLifecycleMethod.invoke(asset);
		} catch(NoSuchMethodException e) {
			handleError(e);
		} catch (IllegalArgumentException e) {
			handleError(e);
		} catch (IllegalAccessException e) {
			handleError(e);
		} catch (InvocationTargetException e) {
			handleError(e);
		}
		StateConfiguration stateConfig = LifecycleUtilities.getStateConfiguration(lifecycle, asset.getState().getIdentifier());
		Set approvingUsers = new HashSet();
		for(RAMVote vote : asset.getCurrentStateHistory().getVotes()) {
			if(VoteChoice.APPROVE.equals(vote.getVoteChoice())) {
				approvingUsers.add(vote.getUser().getUid());
			}
		}
		Result result = new Result(this);
		result.setReturnCode(Result.SUCCESS);
		for (Reviewer reviewer : stateConfig.getReviewers()) {
			if(reviewer.isVoteAllowed()) {
				if(reviewer.getUser() != null) {
					if(!approvingUsers.contains(reviewer.getUser().getValue().getIdentifier())) {
						result.setReturnCode(Result.ERROR);
						break;
					}
				} else if(reviewer.getUserGroup() != null) {
					String groupId = JAXBLinksUtil.getUserGroupIdentifier(reviewer.getUserGroup().getHref());
					UserGroupInstance userGroup = null;
					try {
						userGroup = SecurityManager.getManager().getUserGroup(Integer.parseInt(groupId));
					} catch (NumberFormatException e) {
						handleError(e);
					} catch (UserGroupNotFoundException e) {
						handleError(e);
					}
					ClosableIterator userGroupIter = null;
					try {
						userGroupIter = userGroup.getAllUsers(UserGroupInstance.START_WITH_FIRST_USER);
					for(IUserInformation user : userGroupIter) {
						if(!approvingUsers.contains(user.getUid())) {
							result.setReturnCode(Result.ERROR);
							break;
						}
					}
					} finally {
						if(userGroupIter != null) {
							userGroupIter.close();
						}
					}
				}
				
			}
		}
		
		return result;
		
	}

Comments
Rich Kulp commented Dec 11 '12, 10:32 a.m.
FORUM MODERATOR / JAZZ DEVELOPER

You will need com.ibm.ram.repository.jar file ONLY for compiling. Do not include it when installing the policy into RAM. It is already there and you will cause yourself grief.

Your answer


Register or to post your answer.


Dashboards and work items are no longer publicly available, so some links may be invalid. We now provide similar information through other means. Learn more here.