View Javadoc

1   /**
2    * 
3    */
4   package org.kuali.student.lum.workflow.qualifierresolver;
5   
6   import java.util.ArrayList;
7   import java.util.HashSet;
8   import java.util.List;
9   import java.util.Set;
10  
11  import javax.xml.namespace.QName;
12  import javax.xml.xpath.XPath;
13  import javax.xml.xpath.XPathConstants;
14  import javax.xml.xpath.XPathExpressionException;
15  
16  import org.apache.commons.lang.StringUtils;
17  import org.kuali.rice.core.resourceloader.GlobalResourceLoader;
18  import org.kuali.rice.kew.engine.RouteContext;
19  import org.kuali.rice.kew.engine.node.RouteNodeUtils;
20  import org.kuali.rice.kew.role.QualifierResolver;
21  import org.kuali.rice.kew.rule.xmlrouting.XPathHelper;
22  import org.kuali.rice.kew.util.KEWConstants;
23  import org.kuali.rice.kew.util.XmlHelper;
24  import org.kuali.rice.kim.bo.types.dto.AttributeSet;
25  import org.kuali.rice.student.bo.KualiStudentKimAttributes;
26  import org.kuali.student.common.search.dto.SearchParam;
27  import org.kuali.student.common.search.dto.SearchRequest;
28  import org.kuali.student.common.search.dto.SearchResult;
29  import org.kuali.student.common.search.dto.SearchResultCell;
30  import org.kuali.student.common.search.dto.SearchResultRow;
31  import org.kuali.student.core.organization.service.OrganizationService;
32  import org.w3c.dom.Document;
33  import org.w3c.dom.Element;
34  import org.w3c.dom.Node;
35  import org.w3c.dom.NodeList;
36  
37  /**
38   * An abstract base class that consolidates convenience methods for using the {@link OrganizationService} class.
39   * 
40   */
41  public abstract class AbstractOrganizationServiceQualifierResolver implements QualifierResolver {
42      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AbstractOrganizationServiceQualifierResolver.class);
43      
44      protected static final String DOCUMENT_CONTENT_XML_DEFAULT_ORG_ID_KEY = "orgId";
45      protected static final String DOCUMENT_CONTENT_XML_ORG_ID_KEY = "organizationIdDocumentContentKey";
46  
47      // below string MUST match
48      // org.kuali.student.common.assembly.transform.ProposalWorkflowFilter.DOCUMENT_CONTENT_XML_ROOT_ELEMENT_NAME constant
49      public static final String DOCUMENT_CONTENT_XML_ROOT_ELEMENT_NAME = "info";
50  
51      public static final String KUALI_ORG_TYPE_CURRICULUM_PARENT = "kuali.org.CurriculumParent";
52      public static final String KUALI_ORG_HIERARCHY_CURRICULUM  = "kuali.org.hierarchy.Curriculum";
53      public static final String KUALI_ORG_DEPARTMENT               = "kuali.org.Department";
54      public static final String KUALI_ORG_COLLEGE                  = "kuali.org.College";
55      public static final String KUALI_ORG_COC                      = "kuali.org.COC";
56      public static final String KUALI_ORG_DIVISION                 = "kuali.org.Division";
57      public static final String KUALI_ORG_PROGRAM                  = "kuali.org.Program";
58  
59      private OrganizationService organizationService;
60  
61      protected OrganizationService getOrganizationService() {
62          if (null == organizationService) {
63              organizationService = (OrganizationService) GlobalResourceLoader.getService(new QName("http://student.kuali.org/wsdl/organization", "OrganizationService"));
64          }
65          return organizationService;
66      }
67  
68      protected void setOrganizationService(OrganizationService orgSvc) {
69          organizationService = orgSvc;
70      }
71  
72      /**
73       * Method to fetch the organization ids from the KEW document content XML
74       * 
75       * @param context
76       *            - RouteContext class that holds data about the current document's routing and data
77       * @return A list of organization ids that are listed in the XML (may have duplicates if duplicates are allowed by
78       *         KS code)
79       */
80      protected Set<String> getOrganizationIdsFromDocumentContent(RouteContext context) {
81          String baseXpathExpression = "/" + KEWConstants.DOCUMENT_CONTENT_ELEMENT + "/" + KEWConstants.APPLICATION_CONTENT_ELEMENT + "/" + DOCUMENT_CONTENT_XML_ROOT_ELEMENT_NAME;
82          String orgXpathExpression = "./" + getOrganizationIdDocumentContentFieldKey(context);
83          Document xmlContent = context.getDocumentContent().getDocument();
84          XPath xPath = XPathHelper.newXPath();
85          try {
86              NodeList baseElements = (NodeList) xPath.evaluate(baseXpathExpression, xmlContent, XPathConstants.NODESET);
87              if (LOG.isDebugEnabled()) {
88                  LOG.debug("Found " + baseElements.getLength() + " baseElements to parse for AttributeSets using document XML:");
89                  XmlHelper.printDocumentStructure(xmlContent);
90              }
91              Set<String> distinctiveOrganizationIds = new HashSet<String>();
92              for (int i = 0; i < baseElements.getLength(); i++) {
93                  Node baseNode = baseElements.item(i);
94                  NodeList attributes = (NodeList) xPath.evaluate(orgXpathExpression, baseNode, XPathConstants.NODESET);
95                  for (int j = 0; j < attributes.getLength(); j++) {
96                      Element attributeElement = (Element) attributes.item(j);
97                      distinctiveOrganizationIds.add(attributeElement.getTextContent());
98                  }
99              }
100             return distinctiveOrganizationIds;
101         } catch (XPathExpressionException e) {
102             throw new RuntimeException("Encountered an issue executing XPath.", e);
103         }
104     }
105 
106     protected String getOrganizationIdDocumentContentFieldKey(RouteContext context) {
107         String organizationIdFieldKey = RouteNodeUtils.getValueOfCustomProperty(context.getNodeInstance().getRouteNode(), DOCUMENT_CONTENT_XML_ORG_ID_KEY);
108         if (StringUtils.isBlank(organizationIdFieldKey)) {
109             LOG.info("Cannot find element '" + DOCUMENT_CONTENT_XML_ORG_ID_KEY + "' on Route Node XML configuration. Will use default value of '" + DOCUMENT_CONTENT_XML_DEFAULT_ORG_ID_KEY + "'.");
110             organizationIdFieldKey = DOCUMENT_CONTENT_XML_DEFAULT_ORG_ID_KEY;
111         }
112         return organizationIdFieldKey;
113     }
114 
115     protected List<SearchResultRow> relatedOrgsFromOrgId(String orgId, String relationType, String relatedOrgType) {
116         List<SearchResultRow> results = null;
117         if (null != orgId) {
118             List<SearchParam> queryParamValues = new ArrayList<SearchParam>(2);
119             SearchParam qpRelType = new SearchParam();
120             qpRelType.setKey("org.queryParam.relationType");
121             qpRelType.setValue(relationType);
122             queryParamValues.add(qpRelType);
123 
124             SearchParam qpOrgId = new SearchParam();
125             qpOrgId.setKey("org.queryParam.orgId");
126             qpOrgId.setValue(orgId);
127             queryParamValues.add(qpOrgId);
128 
129             SearchParam qpRelOrgType = new SearchParam();
130             qpRelOrgType.setKey("org.queryParam.relatedOrgType");
131             qpRelOrgType.setValue(relatedOrgType);
132             queryParamValues.add(qpRelOrgType);
133 
134             SearchRequest searchRequest = new SearchRequest();
135             searchRequest.setSearchKey("org.search.orgQuickViewByRelationTypeRelatedOrgTypeOrgId");
136             searchRequest.setParams(queryParamValues);
137             try {
138                 SearchResult result = getOrganizationService().search(searchRequest);
139                 results = result.getRows();
140             } catch (Exception e) {
141                 LOG.error("Error calling org service");
142                 throw new RuntimeException(e);
143             }
144         }
145         return results;
146     }
147     
148     /*
149      *  Add attributes for derived role and adhoc routing participants to the results
150      */
151     protected List<AttributeSet> attributeSetFromSearchResult(List<SearchResultRow> results, String orgIdKey) {
152         List<AttributeSet> returnAttrSetList = new ArrayList<AttributeSet>();
153         if (results != null) {
154             for (SearchResultRow result : results) {
155                 AttributeSet attributeSet = new AttributeSet();
156                 String resolvedOrgId = "";
157                 String resolvedOrgShortName = "";
158                 for (SearchResultCell resultCell : result.getCells()) {
159                     if ("org.resultColumn.orgId".equals(resultCell.getKey())) {
160                         resolvedOrgId = resultCell.getValue();
161                     } else if ("org.resultColumn.orgShortName".equals(resultCell.getKey())) {
162                         resolvedOrgShortName = resultCell.getValue();
163                     }
164                 }
165                 if (orgIdKey != null) {
166                     attributeSet.put(orgIdKey, resolvedOrgId);
167                 }
168                 attributeSet.put(KualiStudentKimAttributes.QUALIFICATION_ORG_ID, resolvedOrgId);
169                 returnAttrSetList.add(attributeSet);
170             }
171         }
172         return returnAttrSetList;
173     }
174 
175 }