001/**
002 * Copyright 2005-2015 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 org.apache.commons.lang.StringUtils;
019import org.apache.logging.log4j.Logger;
020import org.apache.logging.log4j.LogManager;
021import org.kuali.rice.core.api.CoreApiServiceLocator;
022import org.kuali.rice.core.api.util.xml.XmlJotter;
023import org.kuali.rice.edl.impl.EDLContext;
024import org.kuali.rice.edl.impl.EDLModelComponent;
025import org.kuali.rice.kew.api.KEWPropertyConstants;
026import org.kuali.rice.kew.api.WorkflowRuntimeException;
027import org.kuali.rice.krad.util.KRADConstants;
028import org.kuali.rice.krad.util.UrlFactory;
029import org.w3c.dom.Document;
030import org.w3c.dom.Element;
031
032import javax.xml.xpath.XPath;
033import javax.xml.xpath.XPathExpressionException;
034import java.util.Collections;
035import java.util.HashMap;
036import java.util.Map;
037import java.util.Properties;
038import java.util.StringTokenizer;
039
040public class PerformLookupComponent implements EDLModelComponent {
041
042        private static final Logger LOG = LogManager.getLogger(PerformLookupComponent.class);
043        
044        @Override
045        public void updateDOM(Document dom, Element configElement, EDLContext edlContext) {
046                String userAction = edlContext.getUserAction().getAction();
047                if (userAction != null && userAction.startsWith("performLookup")) {
048                        edlContext.setRedirectUrl(constructRedirectUrl(dom, configElement, edlContext));
049                }
050        }
051        
052        protected String constructRedirectUrl(Document dom, Element configElement, EDLContext edlContext) {
053                StringBuilder buf = new StringBuilder(30);
054                buf.append(CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString(
055                KRADConstants.APPLICATION_URL_KEY));
056                buf.append("/kr/").append(KRADConstants.LOOKUP_ACTION);
057                
058                Properties parameters = new Properties();
059                parameters.put(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, getBusinessObjectClassName(dom, configElement, edlContext));
060                parameters.put(KEWPropertyConstants.DOC_FORM_KEY, edlContext.getUserSession().addObjectWithGeneratedKey(dom));
061                parameters.put(KRADConstants.RETURN_LOCATION_PARAMETER, constructReturnUrl(dom, configElement, edlContext));
062                parameters.putAll(getLookupParameters(dom, configElement, edlContext));
063                parameters.put(KRADConstants.CONVERSION_FIELDS_PARAMETER, getFieldConversions(dom, configElement, edlContext));
064                
065                String url = UrlFactory.parameterizeUrl(buf.toString(), parameters);
066                
067                return url;
068        }
069
070        protected String getBusinessObjectClassName(Document dom, Element configElement, EDLContext edlContext) {
071                String userAction = edlContext.getUserAction().getAction();
072                String lookupField = StringUtils.substringAfter(userAction, ".");
073                if (StringUtils.isBlank(lookupField)) {
074                        LOG.error("Cannot find lookup field parameters definition for field " + lookupField);
075                        return null;
076                }
077
078        XPath xPath = edlContext.getXpath();
079        try {
080                        String businessObjectClassName = xPath.evaluate("//fieldDef[@name='" + lookupField + "']/lookup/businessObjectClassName", dom);
081                        return businessObjectClassName;
082                } catch (XPathExpressionException e) {
083                        throw new WorkflowRuntimeException(e);
084                }
085        }
086        
087        protected String getFieldConversions(Document dom, Element configElement, EDLContext edlContext) {
088                String userAction = edlContext.getUserAction().getAction();
089                String lookupField = StringUtils.substringAfter(userAction, ".");
090                if (StringUtils.isBlank(lookupField)) {
091                        LOG.error("Cannot find lookup field parameters definition for field " + lookupField);
092                        return null;
093                }
094
095        XPath xPath = edlContext.getXpath();
096        try {
097                        String lookupParameters = xPath.evaluate("//fieldDef[@name='" + lookupField + "']/lookup/fieldConversions", dom);
098                        return lookupParameters;
099                } catch (XPathExpressionException e) {
100                        throw new WorkflowRuntimeException(e);
101                }
102        }
103        
104        protected Map<String, String> getLookupParameters(Document dom, Element configElement, EDLContext edlContext) {
105                String lookupParameterDefinition = retrieveLookupParametersString(dom, configElement, edlContext);
106                if (StringUtils.isBlank(lookupParameterDefinition)) {
107                        return Collections.emptyMap();
108                }
109                StringTokenizer tok = new StringTokenizer(lookupParameterDefinition, ",");
110                Map<String, String> lookupParameters = new HashMap<String, String>();
111                
112                // where all of the field values are stored
113                Element currentVersion = VersioningPreprocessor.findCurrentVersion(dom);
114                
115                while (tok.hasMoreTokens()) {
116                        String parameterDefinition = tok.nextToken();
117                        int colonInd = parameterDefinition.indexOf(':');
118                        if (colonInd == -1) {
119                                throw new WorkflowRuntimeException("Lookup definition string improperly formatted " + lookupParameterDefinition);
120                        }
121                        
122                        String parameterName = parameterDefinition.substring(colonInd + 1);
123                        String parameterValuePropertyName = parameterDefinition.substring(0, colonInd);
124
125            XPath xPath = edlContext.getXpath();
126            try {
127                String parameterValue = xPath.evaluate("//field[@name='" + parameterValuePropertyName + "']/value", currentVersion);
128                if (LOG.isDebugEnabled()) {
129                    LOG.debug(XmlJotter.jotNode(currentVersion, true));
130                }
131                                if (StringUtils.isNotBlank(parameterValue)) {
132                                        lookupParameters.put(parameterName, parameterValue);
133                                }
134                        } catch (XPathExpressionException e) {
135                                throw new WorkflowRuntimeException(e);
136                        }
137                }
138                return lookupParameters;
139        }
140        
141        protected String retrieveLookupParametersString(Document dom, Element configElement, EDLContext edlContext) {
142                String userAction = edlContext.getUserAction().getAction();
143                String lookupField = StringUtils.substringAfter(userAction, ".");
144                if (StringUtils.isBlank(lookupField)) {
145                        LOG.error("Cannot find lookup field parameters definition for field " + lookupField);
146                        return null;
147                }
148
149        XPath xPath = edlContext.getXpath();
150        try {
151                        String lookupParameters = xPath.evaluate("//fieldDef[@name='" + lookupField + "']/lookup/lookupParameters", dom);
152                        return lookupParameters;
153                } catch (XPathExpressionException e) {
154                        throw new WorkflowRuntimeException(e);
155                }
156        }
157
158        protected String constructReturnUrl(Document dom, Element configElement, EDLContext edlContext) {
159                StringBuilder baseUrl = new StringBuilder(30);
160                baseUrl.append(CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString(
161                KRADConstants.APPLICATION_URL_KEY));
162                baseUrl.append("/kew/EDocLite");
163                
164                Properties parameters = new Properties();
165                
166                String url = UrlFactory.parameterizeUrl(baseUrl.toString(), parameters);
167                return url;
168        }
169}