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