001/** 002 * Copyright 2005-2018 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.edl.impl.components; 017 018import java.io.StringWriter; 019import java.util.Collections; 020import java.util.HashMap; 021import java.util.Map; 022import java.util.Properties; 023import java.util.StringTokenizer; 024 025import javax.xml.transform.Transformer; 026import javax.xml.transform.TransformerConfigurationException; 027import javax.xml.transform.TransformerException; 028import javax.xml.transform.TransformerFactory; 029import javax.xml.transform.dom.DOMSource; 030import javax.xml.transform.stream.StreamResult; 031import javax.xml.xpath.XPath; 032import javax.xml.xpath.XPathExpressionException; 033 034import org.apache.commons.lang.StringUtils; 035import org.apache.log4j.Logger; 036import org.kuali.rice.core.api.CoreApiServiceLocator; 037import org.kuali.rice.core.api.util.xml.XmlJotter; 038import org.kuali.rice.edl.impl.EDLContext; 039import org.kuali.rice.edl.impl.EDLModelComponent; 040import org.kuali.rice.kew.api.WorkflowRuntimeException; 041import org.kuali.rice.krad.util.KRADConstants; 042import org.kuali.rice.krad.util.UrlFactory; 043import org.w3c.dom.Document; 044import org.w3c.dom.Element; 045 046public class PerformLookupComponent implements EDLModelComponent { 047 048 private static final Logger LOG = Logger.getLogger(PerformLookupComponent.class); 049 050 @Override 051 public void updateDOM(Document dom, Element configElement, EDLContext edlContext) { 052 String userAction = edlContext.getUserAction().getAction(); 053 if (userAction != null && userAction.startsWith("performLookup")) { 054 edlContext.setRedirectUrl(constructRedirectUrl(dom, configElement, edlContext)); 055 } 056 } 057 058 protected String constructRedirectUrl(Document dom, Element configElement, EDLContext edlContext) { 059 StringBuilder buf = new StringBuilder(30); 060 buf.append(CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString( 061 KRADConstants.APPLICATION_URL_KEY)); 062 buf.append("/kr/").append(KRADConstants.LOOKUP_ACTION); 063 064 Properties parameters = new Properties(); 065 parameters.put(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, getBusinessObjectClassName(dom, configElement, edlContext)); 066 parameters.put(KRADConstants.DOC_FORM_KEY, edlContext.getUserSession().addObjectWithGeneratedKey(convertDocumentToSerializable(dom))); 067 parameters.put(KRADConstants.RETURN_LOCATION_PARAMETER, constructReturnUrl(dom, configElement, edlContext)); 068 parameters.putAll(getLookupParameters(dom, configElement, edlContext)); 069 parameters.put(KRADConstants.CONVERSION_FIELDS_PARAMETER, getFieldConversions(dom, configElement, edlContext)); 070 071 String url = UrlFactory.parameterizeUrl(buf.toString(), parameters); 072 073 return url; 074 } 075 076 protected String getBusinessObjectClassName(Document dom, Element configElement, EDLContext edlContext) { 077 String userAction = edlContext.getUserAction().getAction(); 078 String lookupField = StringUtils.substringAfter(userAction, "."); 079 if (StringUtils.isBlank(lookupField)) { 080 LOG.error("Cannot find lookup field parameters definition for field " + lookupField); 081 return null; 082 } 083 084 XPath xPath = edlContext.getXpath(); 085 try { 086 String businessObjectClassName = xPath.evaluate("//fieldDef[@name='" + lookupField + "']/lookup/businessObjectClassName", dom); 087 return businessObjectClassName; 088 } catch (XPathExpressionException e) { 089 throw new WorkflowRuntimeException(e); 090 } 091 } 092 093 protected String getFieldConversions(Document dom, Element configElement, EDLContext edlContext) { 094 String userAction = edlContext.getUserAction().getAction(); 095 String lookupField = StringUtils.substringAfter(userAction, "."); 096 if (StringUtils.isBlank(lookupField)) { 097 LOG.error("Cannot find lookup field parameters definition for field " + lookupField); 098 return null; 099 } 100 101 XPath xPath = edlContext.getXpath(); 102 try { 103 String lookupParameters = xPath.evaluate("//fieldDef[@name='" + lookupField + "']/lookup/fieldConversions", dom); 104 return lookupParameters; 105 } catch (XPathExpressionException e) { 106 throw new WorkflowRuntimeException(e); 107 } 108 } 109 110 protected Map<String, String> getLookupParameters(Document dom, Element configElement, EDLContext edlContext) { 111 String lookupParameterDefinition = retrieveLookupParametersString(dom, configElement, edlContext); 112 if (StringUtils.isBlank(lookupParameterDefinition)) { 113 return Collections.emptyMap(); 114 } 115 StringTokenizer tok = new StringTokenizer(lookupParameterDefinition, ","); 116 Map<String, String> lookupParameters = new HashMap<String, String>(); 117 118 // where all of the field values are stored 119 Element currentVersion = VersioningPreprocessor.findCurrentVersion(dom); 120 121 while (tok.hasMoreTokens()) { 122 String parameterDefinition = tok.nextToken(); 123 int colonInd = parameterDefinition.indexOf(':'); 124 if (colonInd == -1) { 125 throw new WorkflowRuntimeException("Lookup definition string improperly formatted " + lookupParameterDefinition); 126 } 127 128 String parameterName = parameterDefinition.substring(colonInd + 1); 129 String parameterValuePropertyName = parameterDefinition.substring(0, colonInd); 130 131 XPath xPath = edlContext.getXpath(); 132 try { 133 String parameterValue = xPath.evaluate("//field[@name='" + parameterValuePropertyName + "']/value", currentVersion); 134 if (LOG.isDebugEnabled()) { 135 LOG.debug(XmlJotter.jotNode(currentVersion, true)); 136 } 137 if (StringUtils.isNotBlank(parameterValue)) { 138 lookupParameters.put(parameterName, parameterValue); 139 } 140 } catch (XPathExpressionException e) { 141 throw new WorkflowRuntimeException(e); 142 } 143 } 144 return lookupParameters; 145 } 146 147 protected String retrieveLookupParametersString(Document dom, Element configElement, EDLContext edlContext) { 148 String userAction = edlContext.getUserAction().getAction(); 149 String lookupField = StringUtils.substringAfter(userAction, "."); 150 if (StringUtils.isBlank(lookupField)) { 151 LOG.error("Cannot find lookup field parameters definition for field " + lookupField); 152 return null; 153 } 154 155 XPath xPath = edlContext.getXpath(); 156 try { 157 String lookupParameters = xPath.evaluate("//fieldDef[@name='" + lookupField + "']/lookup/lookupParameters", dom); 158 return lookupParameters; 159 } catch (XPathExpressionException e) { 160 throw new WorkflowRuntimeException(e); 161 } 162 } 163 164 protected String constructReturnUrl(Document dom, Element configElement, EDLContext edlContext) { 165 StringBuilder baseUrl = new StringBuilder(30); 166 baseUrl.append(CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString( 167 KRADConstants.APPLICATION_URL_KEY)); 168 baseUrl.append("/kew/EDocLite"); 169 170 Properties parameters = new Properties(); 171 172 String url = UrlFactory.parameterizeUrl(baseUrl.toString(), parameters); 173 return url; 174 } 175 176 protected String convertDocumentToSerializable(Document document) { 177 try { 178 DOMSource domSource = new DOMSource(document); 179 StringWriter writer = new StringWriter(); 180 StreamResult result = new StreamResult(writer); 181 TransformerFactory tf = TransformerFactory.newInstance(); 182 Transformer transformer = tf.newTransformer(); 183 transformer.transform(domSource, result); 184 return writer.toString(); 185 } catch (TransformerException e) { 186 throw new WorkflowRuntimeException("Caught exception transforming document into string for session serialization", e); 187 } 188 } 189}