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.kns.workflow.attribute;
017
018import net.sf.cglib.proxy.Enhancer;
019import net.sf.cglib.proxy.InvocationHandler;
020import org.kuali.rice.core.web.format.BooleanFormatter;
021import org.kuali.rice.krad.bo.BusinessObject;
022import org.kuali.rice.krad.util.ObjectUtils;
023
024import java.lang.reflect.Method;
025import java.util.HashMap;
026
027/**
028 * This class provides access to the properties of business objects returned as search results by the WorkflowLookupableImpl.
029 * 
030 * 
031 * @see org.kuali.rice.kew.attribute.WorkflowLookupableImpl
032 * @deprecated This will go away once workflow supports simple url integration for custom attribute lookups.
033 */
034@Deprecated
035public class WorkflowLookupableInvocationHandler implements InvocationHandler {
036    private BusinessObject proxiedBusinessObject;
037    private ClassLoader classLoader;
038
039    private String returnUrl;
040
041    /**
042     * Constructs a WorkflowLookupableInvocationHandler.java.
043     * 
044     * @param proxiedBusinessObject The BusinessObject that this instance is providing access to.
045     */
046    public WorkflowLookupableInvocationHandler(BusinessObject proxiedBusinessObject, ClassLoader classLoader) {
047        this.proxiedBusinessObject = proxiedBusinessObject;
048        this.classLoader = classLoader;
049    }
050
051    /**
052     * Constructs a WorkflowLookupableInvocationHandler.java.
053     * 
054     * @param proxiedBusinessObject The BusinessObject that this instance is providing access to.
055     * @param returnUrl The returnUrl String for selection of a result from the UI
056     */
057    public WorkflowLookupableInvocationHandler(BusinessObject proxiedBusinessObject, String returnUrl, ClassLoader classLoader) {
058        this.proxiedBusinessObject = proxiedBusinessObject;
059        this.returnUrl = returnUrl;
060        this.classLoader = classLoader;
061    }
062
063    /**
064     * This method intercepts "getReturnUrl" and returns this objects returnUrl attribute. It proxies access to nested
065     * BusinessObjects to ensure that the application plugin classloader is used to resolve OJB proxies. And, it translates booleans
066     * for the UI, using the BooleanFormatter.
067     * 
068     * @see net.sf.cglib.proxy.InvocationHandler#invoke(java.lang.Object proxy, java.lang.reflect.Method method, java.lang.Object[]
069     *      args)
070     * 
071     */
072    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
073        ClassLoader oldClassloader = Thread.currentThread().getContextClassLoader();
074        try {
075            Thread.currentThread().setContextClassLoader(classLoader);
076            if ("getReturnUrl".equals(method.getName())) {
077                return returnUrl;
078            }
079            else if ("getWorkflowLookupableResult".equals(method.getName())) {
080                return Enhancer.create(HashMap.class, new Class[] { WorkflowLookupableResult.class }, this);
081            }
082            else if ("get".equals(method.getName())) {
083                Object propertyValue = ObjectUtils.getNestedValue(proxiedBusinessObject, args[0].toString());
084                if (propertyValue instanceof BusinessObject) {
085                    return Enhancer.create(propertyValue.getClass(), new WorkflowLookupableInvocationHandler((BusinessObject) propertyValue, classLoader));
086                }
087                else {
088                    if (propertyValue instanceof Boolean) {
089                        return new BooleanFormatter().format(propertyValue);
090                    }
091                    return propertyValue;
092                }
093            }
094            else {
095                return method.invoke(proxiedBusinessObject, args);
096            }
097        }
098        catch (Exception e) {
099            throw (e.getCause() != null ? e.getCause() : e);
100        }
101        finally {
102            Thread.currentThread().setContextClassLoader(oldClassloader);
103        }
104    }
105}