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.CoreApiServiceLocator;
021    import org.kuali.rice.core.api.util.xml.XmlJotter;
022    import org.kuali.rice.edl.impl.EDLContext;
023    import org.kuali.rice.edl.impl.EDLModelComponent;
024    import org.kuali.rice.kew.api.KEWPropertyConstants;
025    import org.kuali.rice.kew.api.WorkflowRuntimeException;
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 java.util.Collections;
034    import java.util.HashMap;
035    import java.util.Map;
036    import java.util.Properties;
037    import java.util.StringTokenizer;
038    
039    public 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    }