1 /**
2 * Copyright 2005-2016 The Kuali Foundation
3 *
4 * Licensed under the Educational Community License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.opensource.org/licenses/ecl2.php
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.kuali.rice.kns.workflow;
17
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Properties;
22
23 import javax.xml.xpath.XPath;
24 import javax.xml.xpath.XPathExpressionException;
25 import javax.xml.xpath.XPathFactory;
26
27 import org.apache.commons.lang.StringUtils;
28 import org.kuali.rice.kew.engine.RouteContext;
29 import org.kuali.rice.kew.rule.xmlrouting.WorkflowFunctionResolver;
30 import org.kuali.rice.kew.rule.xmlrouting.WorkflowNamespaceContext;
31 import org.kuali.rice.kns.util.FieldUtils;
32 import org.kuali.rice.kns.web.ui.Field;
33 import org.kuali.rice.kns.web.ui.Row;
34 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
35 import org.kuali.rice.krad.util.KRADConstants;
36 import org.kuali.rice.krad.util.KRADPropertyConstants;
37 import org.kuali.rice.krad.util.UrlFactory;
38 import org.w3c.dom.Document;
39
40 /**
41 * @author Kuali Rice Team (rice.collab@kuali.org)
42 *
43 * @deprecated Only used by KNS classes, no replacement.
44 */
45 @Deprecated
46 public final class WorkflowUtils {
47 private static final String XPATH_ROUTE_CONTEXT_KEY = "_xpathKey";
48 public static final String XSTREAM_SAFE_PREFIX = "wf:xstreamsafe('";
49 public static final String XSTREAM_SAFE_SUFFIX = "')";
50 public static final String XSTREAM_MATCH_ANYWHERE_PREFIX = "//";
51 public static final String XSTREAM_MATCH_RELATIVE_PREFIX = "./";
52
53 private WorkflowUtils() {
54 throw new UnsupportedOperationException("do not call");
55 }
56
57 /**
58 *
59 * This method sets up the XPath with the correct workflow namespace and resolver initialized. This ensures that the XPath
60 * statements can use required workflow functions as part of the XPath statements.
61 *
62 * @param document - document
63 * @return a fully initialized XPath instance that has access to the workflow resolver and namespace.
64 *
65 */
66 public final static XPath getXPath(Document document) {
67 XPath xpath = getXPath(RouteContext.getCurrentRouteContext());
68 xpath.setNamespaceContext(new WorkflowNamespaceContext());
69 WorkflowFunctionResolver resolver = new WorkflowFunctionResolver();
70 resolver.setXpath(xpath);
71 resolver.setRootNode(document);
72 xpath.setXPathFunctionResolver(resolver);
73 return xpath;
74 }
75
76 public final static XPath getXPath(RouteContext routeContext) {
77 if (routeContext == null) {
78 return XPathFactory.newInstance().newXPath();
79 }
80 if (!routeContext.getParameters().containsKey(XPATH_ROUTE_CONTEXT_KEY)) {
81 routeContext.getParameters().put(XPATH_ROUTE_CONTEXT_KEY, XPathFactory.newInstance().newXPath());
82 }
83 return (XPath) routeContext.getParameters().get(XPATH_ROUTE_CONTEXT_KEY);
84 }
85
86 /**
87 * This method will do a simple XPath.evaluate, while wrapping your xpathExpression with the xstreamSafe function. It assumes a
88 * String result, and will return such. If an XPathExpressionException is thrown, this will be re-thrown within a
89 * RuntimeException.
90 *
91 * @param xpath A correctly initialized XPath instance.
92 * @param xpathExpression Your XPath Expression that needs to be wrapped in an xstreamSafe wrapper and run.
93 * @param item The document contents you will be searching within.
94 * @return The string value of the xpath.evaluate().
95 */
96 public static final String xstreamSafeEval(XPath xpath, String xpathExpression, Object item) {
97 String xstreamSafeXPath = xstreamSafeXPath(xpathExpression);
98 String evalResult = "";
99 try {
100 evalResult = xpath.evaluate(xstreamSafeXPath, item);
101 }
102 catch (XPathExpressionException e) {
103 throw new RuntimeException("XPathExpressionException occurred on xpath: " + xstreamSafeXPath, e);
104 }
105 return evalResult;
106 }
107
108 /**
109 * This method wraps the passed-in XPath expression in XStream Safe wrappers, so that XStream generated reference links will be
110 * handled correctly.
111 *
112 * @param xpathExpression The XPath Expression you wish to use.
113 * @return Your XPath Expression wrapped in the XStreamSafe wrapper.
114 */
115 public static final String xstreamSafeXPath(String xpathExpression) {
116 return new StringBuilder(XSTREAM_SAFE_PREFIX).append(xpathExpression).append(XSTREAM_SAFE_SUFFIX).toString();
117 }
118
119 /**
120 * This method returns a label from the data dictionary service
121 *
122 * @param businessObjectClass - class where the label should come from
123 * @param attributeName - name of the attribute you need the label for
124 * @return the label from the data dictionary for the given Class and attributeName or null if not found
125 */
126 public static final String getBusinessObjectAttributeLabel(Class businessObjectClass, String attributeName) {
127 return KRADServiceLocatorWeb.getDataDictionaryService().getAttributeLabel(businessObjectClass, attributeName);
128 }
129
130
131 /**
132 * This method builds a workflow-lookup-screen Row of type TEXT, with no quickfinder/lookup.
133 *
134 * @param propertyClass The Class of the BO that this row is based on. For example, Account.class for accountNumber.
135 * @param boPropertyName The property name on the BO that this row is based on. For example, accountNumber for
136 * Account.accountNumber.
137 * @param workflowPropertyKey The workflow-lookup-screen property key. For example, account_nbr for Account.accountNumber. This
138 * key can be anything, but needs to be consistent with what is used for the row/field key on the java attribute, so
139 * everything links up correctly.
140 * @return A populated and ready-to-use workflow lookupable.Row.
141 */
142 public static Row buildTextRow(Class propertyClass, String boPropertyName, String workflowPropertyKey) {
143 if (propertyClass == null) {
144 throw new IllegalArgumentException("Method parameter 'propertyClass' was passed a NULL value.");
145 }
146 if (StringUtils.isBlank(boPropertyName)) {
147 throw new IllegalArgumentException("Method parameter 'boPropertyName' was passed a NULL or blank value.");
148 }
149 if (StringUtils.isBlank(workflowPropertyKey)) {
150 throw new IllegalArgumentException("Method parameter 'workflowPropertyKey' was passed a NULL or blank value.");
151 }
152 List<Field> fields = new ArrayList<Field>();
153 Field field;
154 field = FieldUtils.getPropertyField(propertyClass, boPropertyName, false);
155 fields.add(field);
156 return new Row(fields);
157 }
158
159 /**
160 * This method builds a workflow-lookup-screen Row of type TEXT, with the attached lookup icon and functionality.
161 *
162 * @param propertyClass The Class of the BO that this row is based on. For example, Account.class for accountNumber.
163 * @param boPropertyName The property name on the BO that this row is based on. For example, accountNumber for
164 * Account.accountNumber.
165 * @param workflowPropertyKey The workflow-lookup-screen property key. For example, account_nbr for Account.accountNumber. This
166 * key can be anything, but needs to be consistent with what is used for the row/field key on the java attribute, so
167 * everything links up correctly.
168 * @return A populated and ready-to-use workflow lookupable.Row, which includes both the property field and the lookup icon.
169 */
170 public static Row buildTextRowWithLookup(Class propertyClass, String boPropertyName, String workflowPropertyKey) {
171 return buildTextRowWithLookup(propertyClass, boPropertyName, workflowPropertyKey, null);
172 }
173
174 /**
175 * This method builds a workflow-lookup-screen Row of type TEXT, with the attached lookup icon and functionality.
176 *
177 * @param propertyClass The Class of the BO that this row is based on. For example, Account.class for accountNumber.
178 * @param boPropertyName The property name on the BO that this row is based on. For example, accountNumber for
179 * Account.accountNumber.
180 * @param workflowPropertyKey The workflow-lookup-screen property key. For example, account_nbr for Account.accountNumber. This
181 * key can be anything, but needs to be consistent with what is used for the row/field key on the java attribute, so
182 * everything links up correctly.
183 * @param fieldConversionsByBoPropertyName A list of extra field conversions where the key is the business object property name
184 * and the value is the workflow property key
185 * @return A populated and ready-to-use workflow lookupable.Row, which includes both the property field and the lookup icon.
186 */
187 public static Row buildTextRowWithLookup(Class propertyClass, String boPropertyName, String workflowPropertyKey, Map fieldConversionsByBoPropertyName) {
188 if (propertyClass == null) {
189 throw new IllegalArgumentException("Method parameter 'propertyClass' was passed a NULL value.");
190 }
191 if (StringUtils.isBlank(boPropertyName)) {
192 throw new IllegalArgumentException("Method parameter 'boPropertyName' was passed a NULL or blank value.");
193 }
194 if (StringUtils.isBlank(workflowPropertyKey)) {
195 throw new IllegalArgumentException("Method parameter 'workflowPropertyKey' was passed a NULL or blank value.");
196 }
197 Field field;
198 field = FieldUtils.getPropertyField(propertyClass, boPropertyName, false);
199
200 List<Field> fields = new ArrayList<Field>();
201 fields.add(field);
202 return new Row(fields);
203 }
204
205 /**
206 * This method builds a workflow-lookup-screen Row of type DROPDOWN.
207 *
208 * @param propertyClass The Class of the BO that this row is based on. For example, Account.class for accountNumber.
209 * @param boPropertyName The property name on the BO that this row is based on. For example, accountNumber for
210 * Account.accountNumber.
211 * @param workflowPropertyKey The workflow-lookup-screen property key. For example, account_nbr for Account.accountNumber. This
212 * key can be anything, but needs to be consistent with what is used for the row/field key on the java attribute, so
213 * everything links up correctly.
214 * @param optionMap The map of value, text pairs that will be used to constuct the dropdown list.
215 * @return A populated and ready-to-use workflow lookupable.Row.
216 */
217 public static Row buildDropdownRow(Class propertyClass, String boPropertyName, String workflowPropertyKey, Map<String, String> optionMap, boolean addBlankRow) {
218 if (propertyClass == null) {
219 throw new IllegalArgumentException("Method parameter 'propertyClass' was passed a NULL value.");
220 }
221 if (StringUtils.isBlank(boPropertyName)) {
222 throw new IllegalArgumentException("Method parameter 'boPropertyName' was passed a NULL or blank value.");
223 }
224 if (StringUtils.isBlank(workflowPropertyKey)) {
225 throw new IllegalArgumentException("Method parameter 'workflowPropertyKey' was passed a NULL or blank value.");
226 }
227 if (optionMap == null) {
228 throw new IllegalArgumentException("Method parameter 'optionMap' was passed a NULL value.");
229 }
230 List<Field> fields = new ArrayList<Field>();
231 Field field;
232 field = FieldUtils.getPropertyField(propertyClass, boPropertyName, false);
233 fields.add(field);
234 return new Row(fields);
235 }
236 }