1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.rule;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.jdom.Document;
20 import org.jdom.Element;
21 import org.kuali.rice.core.api.util.xml.XmlHelper;
22 import org.kuali.rice.kew.api.WorkflowRuntimeException;
23 import org.kuali.rice.kew.doctype.bo.DocumentType;
24 import org.kuali.rice.kew.doctype.service.DocumentTypeService;
25 import org.kuali.rice.kew.exception.WorkflowServiceErrorImpl;
26 import org.kuali.rice.kew.routeheader.DocumentContent;
27 import org.kuali.rice.kew.rule.xmlrouting.XPathHelper;
28 import org.kuali.rice.kew.service.KEWServiceLocator;
29 import org.kuali.rice.kns.web.ui.Field;
30 import org.kuali.rice.kns.web.ui.Row;
31
32 import javax.xml.xpath.XPath;
33 import javax.xml.xpath.XPathExpressionException;
34 import java.io.StringReader;
35 import java.util.ArrayList;
36 import java.util.Collection;
37 import java.util.Iterator;
38 import java.util.List;
39 import java.util.Map;
40
41
42
43
44
45
46
47
48 public class RuleRoutingAttribute implements WorkflowRuleAttribute {
49
50 private static final long serialVersionUID = -8884711461398770563L;
51
52 private static final String DOC_TYPE_NAME_PROPERTY = "docTypeFullName";
53 private static final String DOC_TYPE_NAME_KEY = "docTypeFullName";
54
55 private static final String LOOKUPABLE_CLASS = "org.kuali.rice.kew.doctype.bo.DocumentType";
56 private static final String DOC_TYPE_NAME_LABEL = "Document type name";
57
58 private static final String DOC_TYPE_NAME_XPATH = "//newMaintainableObject/businessObject/docTypeName";
59 private static final String DOC_TYPE_NAME_DEL_XPATH = "//newMaintainableObject/businessObject/delegationRuleBaseValues/docTypeName";
60
61 private String doctypeName;
62 private List<Row> rows;
63 private boolean required;
64
65 public RuleRoutingAttribute(String docTypeName) {
66 this();
67 setDoctypeName(docTypeName);
68 }
69
70 public RuleRoutingAttribute() {
71 buildRows();
72 }
73
74 private void buildRows() {
75 rows = new ArrayList<Row>();
76
77 List<Field> fields = new ArrayList<Field>();
78 fields.add(new Field(DOC_TYPE_NAME_LABEL, "", Field.TEXT, false, DOC_TYPE_NAME_PROPERTY, "", false, false, null, LOOKUPABLE_CLASS));
79
80 rows.add(new Row(fields));
81 }
82
83 public boolean isMatch(DocumentContent docContent, List ruleExtensions) {
84 setDoctypeName(getRuleDocumentTypeFromRuleExtensions(ruleExtensions));
85 DocumentTypeService service = (DocumentTypeService) KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE);
86
87 try {
88 String docTypeName = getDocTypNameFromXML(docContent);
89 if (docTypeName.equals(getDoctypeName())) {
90 return true;
91 }
92 DocumentType documentType = service.findByName(docTypeName);
93 while (documentType != null && documentType.getParentDocType() != null) {
94 documentType = documentType.getParentDocType();
95 if(documentType.getName().equals(getDoctypeName())){
96 return true;
97 }
98 }
99 } catch (XPathExpressionException e) {
100 throw new WorkflowRuntimeException(e);
101 }
102
103
104 if (ruleExtensions.isEmpty()) {
105 return true;
106 }
107 return false;
108 }
109
110 protected String getRuleDocumentTypeFromRuleExtensions(List ruleExtensions) {
111 for (Iterator extensionsIterator = ruleExtensions.iterator(); extensionsIterator.hasNext();) {
112 RuleExtensionBo extension = (RuleExtensionBo) extensionsIterator.next();
113 if (extension.getRuleTemplateAttribute().getRuleAttribute().getResourceDescriptor().equals(getClass().getName())) {
114 for (Iterator valuesIterator = extension.getExtensionValues().iterator(); valuesIterator.hasNext();) {
115 RuleExtensionValue extensionValue = (RuleExtensionValue) valuesIterator.next();
116 String key = extensionValue.getKey();
117 String value = extensionValue.getValue();
118 if (key.equals(DOC_TYPE_NAME_KEY)) {
119 return value;
120 }
121 }
122 }
123 }
124 return null;
125 }
126
127 public List getRuleRows() {
128 return rows;
129 }
130
131 public List getRoutingDataRows() {
132 return rows;
133 }
134
135 public String getDocContent() {
136 if (!org.apache.commons.lang.StringUtils.isEmpty(getDoctypeName())) {
137 return "<ruleRouting><doctype>" + getDoctypeName() + "</doctype></ruleRouting>";
138 } else {
139 return "";
140 }
141 }
142
143
144 private String getDocTypNameFromXML(DocumentContent docContent) throws XPathExpressionException {
145 XPath xPath = XPathHelper.newXPath();
146 String docTypeName = xPath.evaluate(DOC_TYPE_NAME_XPATH, docContent.getDocument());
147
148 if (StringUtils.isBlank(docTypeName)) {
149 docTypeName = xPath.evaluate(DOC_TYPE_NAME_DEL_XPATH, docContent.getDocument());
150
151 if (StringUtils.isBlank(docTypeName)) {
152 throw new WorkflowRuntimeException("Could not locate Document Type Name on the document: " +
153 docContent.getRouteContext().getDocument().getDocumentId());
154 }
155 }
156 return docTypeName;
157 }
158
159
160 public List<RuleRoutingAttribute> parseDocContent(DocumentContent docContent) {
161 try {
162 Document doc2 = (Document) XmlHelper.buildJDocument(new StringReader(docContent.getDocContent()));
163
164 List<RuleRoutingAttribute> doctypeAttributes = new ArrayList<RuleRoutingAttribute>();
165 Collection<Element> ruleRoutings = XmlHelper.findElements(doc2.getRootElement(), "docTypeName");
166 List<String> usedDTs = new ArrayList<String>();
167 for (Iterator<Element> iter = ruleRoutings.iterator(); iter.hasNext();) {
168 Element ruleRoutingElement = (Element) iter.next();
169
170
171 Element docTypeElement = ruleRoutingElement;
172 String elTxt = docTypeElement.getText();
173 if (docTypeElement != null && !usedDTs.contains(elTxt)) {
174 usedDTs.add(elTxt);
175 doctypeAttributes.add(new RuleRoutingAttribute(elTxt));
176 }
177 }
178
179 return doctypeAttributes;
180 } catch (Exception e) {
181 throw new RuntimeException(e);
182 }
183 }
184
185 public List getRuleExtensionValues() {
186 List extensions = new ArrayList();
187
188 if (!org.apache.commons.lang.StringUtils.isEmpty(getDoctypeName())) {
189 RuleExtensionValue extension = new RuleExtensionValue();
190 extension.setKey(DOC_TYPE_NAME_KEY);
191 extension.setValue(getDoctypeName());
192 extensions.add(extension);
193 }
194
195 return extensions;
196 }
197
198 public List validateRoutingData(Map paramMap) {
199 List errors = new ArrayList();
200 setDoctypeName((String) paramMap.get(DOC_TYPE_NAME_PROPERTY));
201 if (isRequired() && org.apache.commons.lang.StringUtils.isEmpty(getDoctypeName())) {
202 errors.add(new WorkflowServiceErrorImpl("doc type is not valid.", "routetemplate.ruleroutingattribute.doctype.invalid"));
203 }
204
205 if (!org.apache.commons.lang.StringUtils.isEmpty(getDoctypeName())) {
206 DocumentTypeService service = (DocumentTypeService) KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE);
207 DocumentType documentType = service.findByName(getDoctypeName());
208 if (documentType == null) {
209 errors.add(new WorkflowServiceErrorImpl("doc type is not valid", "routetemplate.ruleroutingattribute.doctype.invalid"));
210 }
211 }
212 return errors;
213 }
214
215 public List validateRuleData(Map paramMap) {
216 return validateRoutingData(paramMap);
217 }
218
219 public String getDoctypeName() {
220 return this.doctypeName;
221 }
222
223 public void setDoctypeName(String docTypeName) {
224 this.doctypeName = docTypeName;
225 }
226
227 public void setRequired(boolean required) {
228 this.required = required;
229 }
230
231 public boolean isRequired() {
232 return required;
233 }
234 }