001    /**
002     * Copyright 2005-2013 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     */
016    package org.kuali.rice.edl.impl.components;
017    
018    import org.apache.commons.lang.StringUtils;
019    import org.apache.log4j.Logger;
020    import org.kuali.rice.core.api.util.xml.XmlJotter;
021    import org.kuali.rice.edl.impl.EDLContext;
022    import org.kuali.rice.edl.impl.EDLModelComponent;
023    import org.kuali.rice.kew.api.KEWPropertyConstants;
024    import org.kuali.rice.kew.api.WorkflowRuntimeException;
025    import org.kuali.rice.krad.service.KRADServiceLocator;
026    import org.kuali.rice.krad.util.KRADConstants;
027    import org.kuali.rice.krad.util.UrlFactory;
028    import org.w3c.dom.Document;
029    import org.w3c.dom.Element;
030    
031    import javax.xml.xpath.XPath;
032    import javax.xml.xpath.XPathExpressionException;
033    import javax.xml.xpath.XPathFactory;
034    import java.util.Collections;
035    import java.util.HashMap;
036    import java.util.Map;
037    import java.util.Properties;
038    import java.util.StringTokenizer;
039    
040    public class PerformLookupComponent implements EDLModelComponent {
041    
042            private static final Logger LOG = Logger.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(KRADServiceLocator.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(KRADServiceLocator.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    }