maandag 3 september 2012

ADF 11g: ADFUtils & JSFUtils

Challenge

Having some nice utility classes to handle JSF and ADF-view related operations.

Context

JDeveloper & ADF : 11.1.1.5.0

Solution


JSFUtils

package view.util;

import java.text.SimpleDateFormat;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import java.util.Set;

import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.MethodExpression;
import javax.el.ValueExpression;

import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
import javax.faces.application.ViewHandler;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;

import javax.servlet.http.HttpServletRequest;

import oracle.adf.model.binding.DCIteratorBinding;
import oracle.adf.view.rich.component.rich.data.RichTable;

import oracle.jbo.uicli.binding.JUCtrlHierBinding;

import org.apache.myfaces.trinidad.model.CollectionModel;
import org.apache.myfaces.trinidad.model.RowKeySet;
import org.apache.myfaces.trinidad.render.ExtendedRenderKitService;
import org.apache.myfaces.trinidad.util.Service;

public final class JSFUtils {
    private static final String NO_RESOURCE_FOUND = "Missing resource: ";
    /**
     * Don't allow instantiation of this utility type class.
     * @writer Rudy De Busscher
     */
    private JSFUtils() {
    }
    /**
     * This method will handle a navigation case programmatically.
     * @param outcome
     */
    public static void handleNavigation(String outcome) {
        FacesContext ctx = JSFUtils.getFacesContext();
        ctx.getApplication().getNavigationHandler().handleNavigation(ctx, "",
                                                                     outcome);
    }
    /**
     * Method for taking a reference to a JSF binding expression and returning
     * the matching object (or creating it).
     * @param expression EL expression
     * @return Managed object
     */
    public static Object resolveExpression(String expression) {
        FacesContext facesContext = getFacesContext();
        Application app = facesContext.getApplication();
        ExpressionFactory elFactory = app.getExpressionFactory();
        ELContext elContext = facesContext.getELContext();
        ValueExpression valueExp =
            elFactory.createValueExpression(elContext, expression,
                                            Object.class);
        return valueExp.getValue(elContext);
    }
    public static String resolveRemoteUser() {
        FacesContext facesContext = getFacesContext();
        ExternalContext ectx = facesContext.getExternalContext();
        return ectx.getRemoteUser();
    }
    public static String resolveUserPrincipal() {
        FacesContext facesContext = getFacesContext();
        ExternalContext ectx = facesContext.getExternalContext();
        HttpServletRequest request = (HttpServletRequest)ectx.getRequest();
        return request.getUserPrincipal().getName();
    }
    public static Object resolveMethodExpression(String expression,
                                                 Class returnType,
                                                 Class[] argTypes,
                                                 Object[] argValues) {
        FacesContext facesContext = getFacesContext();
        Application app = facesContext.getApplication();
        ExpressionFactory elFactory = app.getExpressionFactory();
        ELContext elContext = facesContext.getELContext();
        MethodExpression methodExpression =
            elFactory.createMethodExpression(elContext, expression, returnType,
                                             argTypes);
        return methodExpression.invoke(elContext, argValues);
    }
    /**
     * Method for taking a reference to a JSF binding expression and returning
     * the matching Boolean.
     * @param expression EL expression
     * @param paTargetClass Class used to cast the result of the method.
     * @return Managed object
     */
    public static <T> T resolveExpression(String expression,
                                          Class<T> paTargetClass) {
        return (T)resolveExpression(expression);
    }
    /**
     * Convenience method for resolving a reference to a managed bean by name
     * rather than by expression.
     * @param beanName name of managed bean
     * @return Managed object
     */
    public static Object getManagedBeanValue(String beanName) {
        StringBuffer buff = new StringBuffer("#{");
        buff.append(beanName);
        buff.append('}');
        return resolveExpression(buff.toString());
    }
    /**
     * Method for setting a new object into a JSF managed bean
     * Note: will fail silently if the supplied object does
     * not match the type of the managed bean.
     * @param expression EL expression
     * @param newValue new value to set
     */
    public static void setExpressionValue(String expression, Object newValue) {
        FacesContext facesContext = getFacesContext();
        Application app = facesContext.getApplication();
        ExpressionFactory elFactory = app.getExpressionFactory();
        ELContext elContext = facesContext.getELContext();
        ValueExpression valueExp =
            elFactory.createValueExpression(elContext, expression,
                                            Object.class);
        //Check that the input newValue can be cast to the property type
        //expected by the managed bean.
        //If the managed Bean expects a primitive we rely on Auto-Unboxing
        //I could do a more comprehensive check and conversion from the object
        //to the equivilent primitive but life is too short
        Class bindClass = valueExp.getType(elContext);
        if (bindClass.isPrimitive() || bindClass.isInstance(newValue)) {
            valueExp.setValue(elContext, newValue);
        }
    }
    /**
     * Convenience method for setting the value of a managed bean by name
     * rather than by expression.
     * @param beanName name of managed bean
     * @param newValue new value to set
     */
    public static void setManagedBeanValue(String beanName, Object newValue) {
        StringBuffer buff = new StringBuffer("#{");
        buff.append(beanName);
        buff.append('}');
        setExpressionValue(buff.toString(), newValue);
    }

    /**
     * Convenience method for setting Session variables.
     * @param key object key
     * @param object value to store
     */
    public static void storeOnSession(String key, Object object) {
        FacesContext ctx = getFacesContext();
        Map sessionState = ctx.getExternalContext().getSessionMap();
        sessionState.put(key, object);
    }
    /**
     * Convenience method for getting Session variables.
     * @param key object key
     * @return session object for key
     */
    public static Object getFromSession(String key) {
        FacesContext ctx = getFacesContext();
        Map sessionState = ctx.getExternalContext().getSessionMap();
        return sessionState.get(key);
    }
    public static String getFromHeader(String key) {
        FacesContext ctx = getFacesContext();
        ExternalContext ectx = ctx.getExternalContext();
        return ectx.getRequestHeaderMap().get(key);
    }
    /**
     * Convenience method for getting Request variables.
     * @param key object key
     * @return session object for key
     */
    public static Object getFromRequest(String key) {
        FacesContext ctx = getFacesContext();
        Map sessionState = ctx.getExternalContext().getRequestMap();
        return sessionState.get(key);
    }
    /**
     * Pulls a String resource from the property bundle that
     * is defined under the application &lt;message-bundle&gt; element in
     * the faces config. Respects Locale
     * @param key string message key
     * @return Resource value or placeholder error String
     */
    public static String getStringFromBundle(String key) {
        ResourceBundle bundle = getBundle();
        return getStringSafely(bundle, key, null);
    }

    /**
     * Convenience method to construct a <code>FacesMesssage</code>
     * from a defined error key and severity
     * This assumes that the error keys follow the convention of
     * using <b>_detail</b> for the detailed part of the
     * message, otherwise the main message is returned for the
     * detail as well.
     * @param key for the error message in the resource bundle
     * @param severity severity of message
     * @return Faces Message object
     */
    public static FacesMessage getMessageFromBundle(String key,
                                                    FacesMessage.Severity severity) {
        ResourceBundle bundle = getBundle();
        String summary = getStringSafely(bundle, key, null);
        String detail = getStringSafely(bundle, key + "_detail", summary);
        FacesMessage message = new FacesMessage(summary, detail);
        message.setSeverity(severity);
        return message;
    }
    /**
     * Add JSF info message.
     * @param msg info message string
     */
    public static void addFacesInformationMessage(String msg) {
        FacesContext ctx = getFacesContext();
        FacesMessage fm =
            new FacesMessage(FacesMessage.SEVERITY_INFO, msg, "");
        ctx.addMessage(null, fm);
    }

    // Informational getters
    /**
     * Get view id of the view root.
     * @return view id of the view root
     */
    public static String getRootViewId() {
        return getFacesContext().getViewRoot().getViewId();
    }
    /**
     * Get component id of the view root.
     * @return component id of the view root
     */
    public static String getRootViewComponentId() {
        return getFacesContext().getViewRoot().getId();
    }
    /**
     * Get FacesContext.
     * @return FacesContext
     */
    public static FacesContext getFacesContext() {
        return FacesContext.getCurrentInstance();
    }
    /**
     * Internal method to pull out the correct local
     * message bundle
     */
    public static ResourceBundle getBundle() {
        FacesContext ctx = getFacesContext();
        UIViewRoot uiRoot = ctx.getViewRoot();
        Locale locale = uiRoot.getLocale();
        ClassLoader ldr = Thread.currentThread().getContextClassLoader();
        return ResourceBundle.getBundle(ctx.getApplication().getMessageBundle(),
                                        locale, ldr);
    }
    /**
     * Get an HTTP Request attribute.
     * @param name attribute name
     * @return attribute value
     */
    public static Object getRequestAttribute(String name) {
        return getFacesContext().getExternalContext().getRequestMap().get(name);
    }
    /**
     * Set an HTTP Request attribute.
     * @param name attribute name
     * @param value attribute value
     */
    public static void setRequestAttribute(String name, Object value) {
        getFacesContext().getExternalContext().getRequestMap().put(name,
                                                                   value);
    }
    /*
   * Internal method to proxy for resource keys that don't exist
   */
    private static String getStringSafely(ResourceBundle bundle, String key,
                                          String defaultValue) {
        String resource = null;
        try {
            resource = bundle.getString(key);
        } catch (MissingResourceException mrex) {
            if (defaultValue != null) {
                resource = defaultValue;
            } else {
                resource = NO_RESOURCE_FOUND + key;
            }
        }
        return resource;
    }
    /**
     * Locate an UIComponent in view root with its component id. Use a recursive way to achieve this.
     * Taken from http://www.jroller.com/page/mert?entry=how_to_find_a_uicomponent
     * @param id UIComponent id
     * @return UIComponent object
     */
    public static UIComponent findComponentInRoot(String id) {
        UIComponent component = null;
        FacesContext facesContext = FacesContext.getCurrentInstance();
        if (facesContext != null) {
            UIComponent root = facesContext.getViewRoot();
            component = findComponent(root, id);
        }
        return component;
    }
    /**
     * Locates all components.
     * @return UIComponent object
     */
    public static List<UIComponent> findAllComponentsinRoot() {
        List<UIComponent> result = new ArrayList<UIComponent>();
        FacesContext facesContext = FacesContext.getCurrentInstance();
        if (facesContext != null) {
            UIComponent root = facesContext.getViewRoot();
            result = root.getChildren();
        }
        return result;
    }
    /**
     * Locate an UIComponent from its root component.
     * Taken from http://www.jroller.com/page/mert?entry=how_to_find_a_uicomponent
     * @param base root Component (parent)
     * @param id UIComponent id
     * @return UIComponent object
     */
    public static UIComponent findComponent(UIComponent base, String id) {
        if (id.equals(base.getId())) {
            return base;
        }
        UIComponent children = null;
        UIComponent result = null;
        Iterator childrens = base.getFacetsAndChildren();
        while (childrens.hasNext() && (result == null)) {
            children = (UIComponent)childrens.next();
            if (id.equals(children.getId())) {
                result = children;
                break;
            }
            result = findComponent(children, id);
            if (result != null) {
                break;
            }
        }
        return result;
    }

    /**
     * Locate an UIComponent from a base component and looking in his parents.
     * @param base root Component
     * @param id UIComponent id to search
     * @return UIComponent object
     */
    public static UIComponent findClosestComponent(UIComponent base,
                                                   String id) {
        if (id.equals(base.getId())) {
            return base;
        }
        UIComponent child = null;
        UIComponent result = null;
        Iterator children = base.getParent().getFacetsAndChildren();
        while (children.hasNext() && (result == null)) {
            child = (UIComponent)children.next();
            result = findComponent(child, id);
        }
        if (result == null && !(base instanceof UIViewRoot)) {
            result = findClosestComponent(base.getParent(), id);
        }
        return result;
    }

    /**
     * Determines all the components that have the value specified as parameter as their id.
     * @param id
     * @return
     * @writer Rudy De Busscher
     */
    public static List<UIComponent> findComponentsInRoot(String id) {
        List<UIComponent> result = new ArrayList<UIComponent>();
        FacesContext facesContext = FacesContext.getCurrentInstance();
        if (facesContext != null) {
            UIComponent root = facesContext.getViewRoot();
            findComponents(result, root, id);
        }
        return result;
    }
    /**
     * Locate all the UIComponents from its root component.
     * @param components The list that will be populated with the found components
     * @param base root Component (parent)
     * @param id UIComponent id
     * @writer Rudy De Busscher
     */
    public static void findComponents(List<UIComponent> components,
                                      UIComponent base, String id) {
        if (id.equals(base.getId())) {
            components.add(base);
            return;
        }
        UIComponent child = null;
        Iterator children = base.getFacetsAndChildren();
        while (children.hasNext()) {
            child = (UIComponent)children.next();
            if (id.equals(child.getId())) {
                components.add(child);
                break;
            }
            findComponents(components, child, id);
        }
    }
    /**
     * Method to create a redirect URL. The assumption is that the JSF servlet mapping is
     * "faces", which is the default
     *
     * @param view the JSP or JSPX page to redirect to
     * @return a URL to redirect to
     */
    public static String getPageURL(String view) {
        FacesContext facesContext = getFacesContext();
        ExternalContext externalContext = facesContext.getExternalContext();
        String url =
            ((HttpServletRequest)externalContext.getRequest()).getRequestURL().toString();
        StringBuffer newUrlBuffer = new StringBuffer();
        newUrlBuffer.append(url.substring(0, url.lastIndexOf("faces/")));
        newUrlBuffer.append("faces");
        String targetPageUrl = view.startsWith("/") ? view : "/" + view;
        newUrlBuffer.append(targetPageUrl);
        return newUrlBuffer.toString();
    }
    /**
     * Refresh the current page.
     */
    public static void refreshCurrentPage() {
        FacesContext context = FacesContext.getCurrentInstance();
        String currentView = context.getViewRoot().getViewId();
        ViewHandler vh = context.getApplication().getViewHandler();
        UIViewRoot x = vh.createView(context, currentView);
        context.setViewRoot(x);
    }
    /**
     * Force the validation and updates model phase.  Usefull in the situation where
     * we have an ilmmediate true action but want to keep the values.
     * @param paComponent The component to validate, call it with the view root.
     * @param paContext The FacesContext
     * @writer Rudy De Busscher
     */
    public static void forceValidateAndUpdateField(UIComponent paComponent,
                                                   FacesContext paContext) {
        if (paComponent instanceof EditableValueHolder) {
            EditableValueHolder field = (EditableValueHolder)paComponent;
            paComponent.processValidators(paContext);
            field.setValid(true); // In case something went wrong, just ignore it now.
            paComponent.processUpdates(paContext);
        }
        Iterator<UIComponent> iter = paComponent.getFacetsAndChildren();
        while (iter.hasNext()) {
            UIComponent childOrFacet = iter.next();
            forceValidateAndUpdateField(childOrFacet, paContext);
        }
    }
    /**
     * Helper method to execute the an Method EL with one parameter.
     * @param expr the EL expression
     * @param paParameter
     */
    public static void invokeMethodExpression(String expr,
                                              Object paParameter) {
        invokeMethodExpression(expr, Object.class,
                               new Class[] { paParameter.getClass() },
                               new Object[] { paParameter });
    }
    /**
     * Helper method to execute the QueryListener EL for methods with a return type.
     * @param expr The method you want to execute
     * @param returnType The return type of the method
     * @param argTypes The types of the arguments
     * @param args the arguments passed to the method (must match argTypes)
     */
    public static Object invokeMethodExpression(String expr, Class returnType,
                                                Class[] argTypes,
                                                Object[] args) {
        FacesContext fc = FacesContext.getCurrentInstance();
        ELContext elctx = fc.getELContext();
        ExpressionFactory elFactory =
            fc.getApplication().getExpressionFactory();
        MethodExpression methodExpr =
            elFactory.createMethodExpression(elctx, expr, returnType,
                                             argTypes);
        return methodExpr.invoke(elctx, args);
    }
    public static Object invokeMethodExpression(String expr, Class returnType, Class argType, Object argument) {
        return invokeMethodExpression(expr, returnType, new Class[] { argType }, new Object[] { argument });
    }

    public static String resolveFromResourceBundle(String paResourceBundle,
                                                   String paKey) {
        StringBuilder expression = new StringBuilder();
        expression.append("#{adfBundle['").append(paResourceBundle).append("'].").append(paKey).append("}");
        return resolveExpression(expression.toString(), String.class);
    }
    private static final String DATEFORMATPATTERN = "dd/MM/yyyy";
    /**
     * This method will fetch a string from the resourcebundle for a specific key.
     * Afterwards it will replace all the keys from the dynamicParams map with
     * their corresponding values.
     * When the value is of type java.sql.Date, the Date will be transformed into
     * a String using the format 'DD/MM/YYYY'.
     *
     * @param paResourceBundle Path + Name of the resourceBundle
     * @param paKey The key in the resourceBundle to fetch the text
     * @param dynamicParams A map of dynamic constants to be replaced in the string of the resourcebundle
     * @return
     * @writer Filip Huysmans
     */
    public static String resolveFromResourceBundle(String paResourceBundle,
                                                   String paKey,
                                                   Map dynamicParams) {
        // Determine the string from the resource bundle
        String resourceBundleValue =
            resolveFromResourceBundle(paResourceBundle, paKey);
        // Replace the dynamic parts of the string by looping through the map
        if (dynamicParams != null && !dynamicParams.isEmpty()) {
            for (Map.Entry entry : (Set<Map.Entry>)dynamicParams.entrySet()) {
                Object value = entry.getValue();
                // Transforming the key to the exact representation in the resource bundle string
                String key = "\\{" + entry.getKey() + "\\}";
                // Handling some special cases of a date
                if (value instanceof java.sql.Date) {
                    // Format the date before putting it into the string
                    java.sql.Date newDate = (java.sql.Date)value;
                    SimpleDateFormat formatDate =
                        new SimpleDateFormat(DATEFORMATPATTERN);
                    value = formatDate.format(newDate);
                }
                // Replacing all occurances of the key with the value
                resourceBundleValue =
                        resourceBundleValue.replaceAll(key, (String)value);
            }
        }
        // Returning the result String
        return resourceBundleValue;
    }
    public static void writeJavaScriptToClient(String paScript) {
        FacesContext fctx = FacesContext.getCurrentInstance();
        ExtendedRenderKitService erks = null;
        erks =
Service.getRenderKitService(fctx, ExtendedRenderKitService.class);
        erks.addScript(fctx, paScript);
    }
    /**
     * Get the value of an EL expression.
     * @param expr
     * @return
     */
    public static Object get(String expr) {
        FacesContext fc = JSFUtils.getFacesContext();
        return fc.getApplication().evaluateExpressionGet(fc, expr,
                                                         Object.class);
    }
    /**
     * Set the a value into an EL Expression
     * @param expr
     * @param value
     */
    public static void set(String expr, String value) {
        Object valToSet = value;
        if (isELExpr(value)) {
            valToSet = get(value);
        }
        set(expr, valToSet);
    }
    /**
     * Check whether the given parameter is a valid EL Expression
     * @param o
     * @return
     */
    private static boolean isELExpr(Object o) {
        if (o instanceof String) {
            String str = (String)o;
            str = str.trim();
            return str.startsWith("#{") && str.endsWith("}");
        }
        return false;
    }
    /**
     * Set the a value into an EL Expression
     * @param expr
     * @param value
     */
    public static void set(String expr, Object value) {
        FacesContext fc = JSFUtils.getFacesContext();
        ELContext elc = fc.getELContext();
        ExpressionFactory ef = fc.getApplication().getExpressionFactory();
        ValueExpression ve = ef.createValueExpression(elc, expr, Object.class);
        ve.setValue(elc, value);
    }
    public static void addFacesMessageError(String componentId,
                                            String message) {
        FacesContext context = getFacesContext();
        context.addMessage(componentId,
                           new FacesMessage(FacesMessage.SEVERITY_ERROR, "",
                                            message));
    }
    public static void addFacesMessage(String id, FacesMessage fm) {
        JSFUtils.getFacesContext().addMessage(id, fm);
    }
    /**
     * Add JSF error message.
     * @param msg error message string
     */
    public static void addFacesErrorMessage(String msg) {
        FacesContext ctx = getFacesContext();
        FacesMessage fm =
            new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, "");
        ctx.addMessage(null, fm);
    }
    /**
     * Add JSF warning message.
     * @param msg warning message string
     */
    public static void addFacesWarningMessage(String msg) {
        FacesContext ctx = getFacesContext();
        FacesMessage fm =
            new FacesMessage(FacesMessage.SEVERITY_WARN, msg, "");
        ctx.addMessage(null, fm);
    }
    /**
     * This method will set the focus on a field in the current row from a table
     * @param table The reference to the table component
     * @param fieldId The name(=Id) of the field to focus on
     * @writer Filip Huysmans
     */
    public static void setFocusOnField(RichTable table, String fieldId) {
        // Getting the iterator from the table component
        CollectionModel cm = (CollectionModel)table.getValue();
        JUCtrlHierBinding tb = (JUCtrlHierBinding)cm.getWrappedData();
        DCIteratorBinding icd = tb.getDCIteratorBinding();
        // Take the key of the current row and set the current row active
        ArrayList lst = new ArrayList(1);
        lst.add(icd.getCurrentRow().getKey());
        table.setActiveRowKey(lst);
        // Looking for the necessary id's to create the focus call
        String tableId = table.getClientId(JSFUtils.getFacesContext());
        RowKeySet rks = table.getSelectedRowKeys();
        if (rks != null && rks.size() > 0) {
            // Only when there are rows in the table
            Object rowKey = rks.iterator().next();
            String rowId =
                table.getClientRowKeyManager().getClientRowKey(JSFUtils.getFacesContext(),
                                                               table, rowKey);
            String inputId = tableId + ":" + rowId + ":" + fieldId;
            // Creating the Javascript to put the focus on the field
            ExtendedRenderKitService service =
                Service.getRenderKitService(JSFUtils.getFacesContext(),
                                            ExtendedRenderKitService.class);
            // Adding a timeout to wait for the components to render
            service.addScript(JSFUtils.getFacesContext(),
                              "setTimeout(function(){comp = AdfPage.PAGE.findComponent('" +
                              inputId + "'); comp.focus();}, 500)");
        }
    }

    /**
     * method for removing Session variables.
     * @param
     * @writer Christophe Gobled
     */
    public static void removeFromSession(String key) {
        FacesContext ctx = getFacesContext();
        Map sessionState = ctx.getExternalContext().getSessionMap();
        sessionState.remove(key);
    }
}

ADFUtils

package view.util;

import java.util.ArrayList;
import java.util.List;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;

import oracle.adf.model.BindingContext;
import oracle.adf.model.binding.DCBindingContainer;
import oracle.adf.model.binding.DCIteratorBinding;
import oracle.adf.model.binding.DCParameter;
import oracle.adf.share.logging.ADFLogger;
import oracle.adf.view.rich.component.rich.RichPopup;
import oracle.adf.view.rich.component.rich.data.RichTable;
import oracle.adf.view.rich.context.AdfFacesContext;
import oracle.adf.view.rich.event.QueryEvent;
import oracle.adf.view.rich.model.AttributeCriterion;
import oracle.adf.view.rich.model.AttributeDescriptor;
import oracle.adf.view.rich.model.Criterion;
import oracle.adf.view.rich.model.QueryDescriptor;

import oracle.binding.AttributeBinding;
import oracle.binding.BindingContainer;
import oracle.binding.ControlBinding;
import oracle.binding.OperationBinding;

import oracle.jbo.ApplicationModule;
import oracle.jbo.Key;
import oracle.jbo.Row;
import oracle.jbo.uicli.binding.JUCtrlHierBinding;
import oracle.jbo.uicli.binding.JUCtrlHierNodeBinding;
import oracle.jbo.uicli.binding.JUCtrlValueBinding;

import org.apache.myfaces.trinidad.event.SelectionEvent;
import org.apache.myfaces.trinidad.model.CollectionModel;
import org.apache.myfaces.trinidad.model.RowKeySet;
import org.apache.myfaces.trinidad.render.ExtendedRenderKitService;
import org.apache.myfaces.trinidad.util.Service;

/**
 * A series of convenience functions for dealing with ADF Bindings.
 * Note: Updated for JDeveloper 11
 *
 * @author Duncan Mills
 * @author Steve Muench
 *
 * $Id: ADFUtils.java 141 2011-11-28 11:07:16Z HEAVEN\cgd $.
 */
public final class ADFUtils {
    private static final String NOT_FOUND = "' not found";
    public static final ADFLogger LOGGER = ADFLogger.createADFLogger(ADFUtils.class);
    /**
     * Don't allow instantiation of utility class.
     * @writer Rudy De Busscher
     */
    private ADFUtils() {
        // Don't allow instantiation of utility class.
    }
    /**
     * Get application module for an application module data control by name.
     * @param name application module data control name
     * @return ApplicationModule
     */
    public static ApplicationModule getApplicationModuleForDataControl(String name) {
        return (ApplicationModule)JSFUtils.resolveExpression("#{data." + name + ".dataProvider}");
    }

    /**
     * A convenience method for getting the value of a bound attribute in the
     * current page context programatically.
     * @param attributeName of the bound value in the pageDef
     * @return value of the attribute
     */
    public static Object getBoundAttributeValue(String attributeName) {
        return findControlBinding(attributeName).getInputValue();
    }
    /**
     * A convenience method for setting the value of a bound attribute in the
     * context of the current page.
     * @param attributeName of the bound value in the pageDef
     * @param value to set
     */
    public static void setBoundAttributeValue(String attributeName, Object value) {
        findControlBinding(attributeName).setInputValue(value);
    }
    /**
     * Returns the evaluated value of a pageDef parameter.
     * @param pageDefName reference to the page definition file of the page with the parameter
     * @param parameterName name of the pagedef parameter
     * @return evaluated value of the parameter as a String
     */
    public static Object getPageDefParameterValue(String pageDefName, String parameterName) {
        BindingContainer bindings = findBindingContainer(pageDefName);
        DCParameter param = ((DCBindingContainer)bindings).findParameter(parameterName);
        return param.getValue();
    }
    /**
     * Convenience method to find a DCControlBinding as an AttributeBinding
     * to get able to then call getInputValue() or setInputValue() on it.
     * @param bindingContainer binding container
     * @param attributeName name of the attribute binding.
     * @return the control value binding with the name passed in.
     *
     */
    public static AttributeBinding findControlBinding(BindingContainer bindingContainer, String attributeName) {
        if (attributeName != null && bindingContainer != null) {
            ControlBinding ctrlBinding = bindingContainer.getControlBinding(attributeName);
            if (ctrlBinding instanceof AttributeBinding) {
                return (AttributeBinding)ctrlBinding;
            }
        }
        return null;
    }
    /**
     * Convenience method to find a DCControlBinding as a JUCtrlValueBinding
     * to get able to then call getInputValue() or setInputValue() on it.
     * @param attributeName name of the attribute binding.
     * @return the control value binding with the name passed in.
     *
     */
    public static AttributeBinding findControlBinding(String attributeName) {
        return findControlBinding(getBindingContainer(), attributeName);
    }
    /**
     * Return the current page's binding container.
     * @return the current page's binding container
     */
    public static BindingContainer getBindingContainer() {
        return BindingContext.getCurrent().getCurrentBindingsEntry();
    }
    /**
     * Return the Binding Container as a DCBindingContainer.
     * @return current binding container as a DCBindingContainer
     */
    public static DCBindingContainer getDCBindingContainer() {
        return (DCBindingContainer)getBindingContainer();
    }
    /**
     * Get List of ADF Faces SelectItem for an iterator binding.
     *
     * Uses the value of the 'valueAttrName' attribute as the key for
     * the SelectItem key.
     *
     * @param iteratorName ADF iterator binding name
     * @param valueAttrName name of the value attribute to use
     * @param displayAttrName name of the attribute from iterator rows to display
     * @return ADF Faces SelectItem for an iterator binding
     */
    public static List<SelectItem> selectItemsForIterator(String iteratorName, String valueAttrName, String displayAttrName) {
        return selectItemsForIterator(findIterator(iteratorName), valueAttrName, displayAttrName);
    }
    /**
     * Get List of ADF Faces SelectItem for an iterator binding with description.
     *
     * Uses the value of the 'valueAttrName' attribute as the key for
     * the SelectItem key.
     *
     * @param iteratorName ADF iterator binding name
     * @param valueAttrName name of the value attribute to use
     * @param displayAttrName name of the attribute from iterator rows to display
     * @param descriptionAttrName name of the attribute to use for description
     * @return ADF Faces SelectItem for an iterator binding with description
     */
    public static List<SelectItem> selectItemsForIterator(String iteratorName, String valueAttrName, String displayAttrName, String descriptionAttrName) {
        return selectItemsForIterator(findIterator(iteratorName), valueAttrName, displayAttrName, descriptionAttrName);
    }
    /**
     * Get List of attribute values for an iterator.
     * @param iteratorName ADF iterator binding name
     * @param valueAttrName value attribute to use
     * @return List of attribute values for an iterator
     */
    public static List attributeListForIterator(String iteratorName, String valueAttrName) {
        return attributeListForIterator(findIterator(iteratorName), valueAttrName);
    }
    /**
     * Get List of Key objects for rows in an iterator.
     * @param iteratorName iterabot binding name
     * @return List of Key objects for rows
     */
    public static List<Key> keyListForIterator(String iteratorName) {
        return keyListForIterator(findIterator(iteratorName));
    }
    /**
     * Get List of Key objects for rows in an iterator.
     * @param iter iterator binding
     * @return List of Key objects for rows
     */
    public static List<Key> keyListForIterator(DCIteratorBinding iter) {
        List<Key> attributeList = new ArrayList<Key>();
        for (Row r : iter.getAllRowsInRange()) {
            attributeList.add(r.getKey());
        }
        return attributeList;
    }
    /**
     * Get List of Key objects for rows in an iterator using key attribute.
     * @param iteratorName iterator binding name
     * @param keyAttrName name of key attribute to use
     * @return List of Key objects for rows
     */
    public static List<Key> keyAttrListForIterator(String iteratorName, String keyAttrName) {
        return keyAttrListForIterator(findIterator(iteratorName), keyAttrName);
    }
    /**
     * Get List of Key objects for rows in an iterator using key attribute.
     *
     * @param iter iterator binding
     * @param keyAttrName name of key attribute to use
     * @return List of Key objects for rows
     */
    public static List<Key> keyAttrListForIterator(DCIteratorBinding iter, String keyAttrName) {
        List<Key> attributeList = new ArrayList<Key>();
        for (Row r : iter.getAllRowsInRange()) {
            attributeList.add(new Key(new Object[] { r.getAttribute(keyAttrName) }));
        }
        return attributeList;
    }
    /**
     * Get a List of attribute values for an iterator.
     *
     * @param iter iterator binding
     * @param valueAttrName name of value attribute to use
     * @return List of attribute values
     */
    public static List attributeListForIterator(DCIteratorBinding iter, String valueAttrName) {
        List attributeList = new ArrayList();
        for (Row r : iter.getAllRowsInRange()) {
            attributeList.add(r.getAttribute(valueAttrName));
        }
        return attributeList;
    }
    /**
     * Find an iterator binding in the current binding container by name.
     *
     * @param name iterator binding name
     * @return iterator binding
     */
    public static DCIteratorBinding findIterator(String name) {
        DCIteratorBinding iter = getDCBindingContainer().findIteratorBinding(name);
        if (iter == null) {
            throw new RuntimeException("Iterator '" + name + NOT_FOUND);
        }
        return iter;
    }
    /**
     * @param bindingContainer
     * @param iterator
     * @return
     */
    public static DCIteratorBinding findIterator(String bindingContainer, String iterator) {
        DCBindingContainer bindings = (DCBindingContainer)JSFUtils.resolveExpression("#{" + bindingContainer + "}");
        if (bindings == null) {
            throw new RuntimeException("Binding container '" + bindingContainer + NOT_FOUND);
        }
        DCIteratorBinding iter = bindings.findIteratorBinding(iterator);
        if (iter == null) {
            throw new RuntimeException("Iterator '" + iterator + NOT_FOUND);
        }
        return iter;
    }
    /**
     * @param name
     * @return
     */
    public static JUCtrlValueBinding findCtrlBinding(String name) {
        JUCtrlValueBinding rowBinding = (JUCtrlValueBinding)getDCBindingContainer().findCtrlBinding(name);
        if (rowBinding == null) {
            throw new RuntimeException("CtrlBinding " + name + NOT_FOUND);
        }
        return rowBinding;
    }
    /**
     * Find an operation binding in the current binding container by name.
     *
     * @param name operation binding name
     * @return operation binding
     */
    public static OperationBinding findOperation(String name) {
        OperationBinding operation = getDCBindingContainer().getOperationBinding(name);
        if (operation == null) {
            throw new RuntimeException("Operation '" + name + NOT_FOUND);
        }
        return operation;
    }
    /**
     * Find an operation binding in the current binding container by name.
     *
     * @param bindingContianer binding container name
     * @param opName operation binding name
     * @return operation binding
     */
    public static OperationBinding findOperation(String bindingContianer, String opName) {
        DCBindingContainer bindings = (DCBindingContainer)JSFUtils.resolveExpression("#{" + bindingContianer + "}");
        if (bindings == null) {
            throw new RuntimeException("Binding container '" + bindingContianer + NOT_FOUND);
        }
        OperationBinding operation = bindings.getOperationBinding(opName);
        if (operation == null) {
            throw new RuntimeException("Operation '" + opName + NOT_FOUND);
        }
        return operation;
    }
    /**
     * Get List of ADF Faces SelectItem for an iterator binding with description.
     *
     * Uses the value of the 'valueAttrName' attribute as the key for
     * the SelectItem key.
     *
     * @param iter ADF iterator binding
     * @param valueAttrName name of value attribute to use for key
     * @param displayAttrName name of the attribute from iterator rows to display
     * @param descriptionAttrName name of the attribute for description
     * @return ADF Faces SelectItem for an iterator binding with description
     */
    public static List<SelectItem> selectItemsForIterator(DCIteratorBinding iter, String valueAttrName, String displayAttrName, String descriptionAttrName) {
        List<SelectItem> selectItems = new ArrayList<SelectItem>();
        for (Row r : iter.getAllRowsInRange()) {
            selectItems.add(new SelectItem(r.getAttribute(valueAttrName), (String)r.getAttribute(displayAttrName), (String)r.getAttribute(descriptionAttrName)));
        }
        return selectItems;
    }
    /**
     * Get List of ADF Faces SelectItem for an iterator binding.
     *
     * Uses the value of the 'valueAttrName' attribute as the key for
     * the SelectItem key.
     *
     * @param iter ADF iterator binding
     * @param valueAttrName name of value attribute to use for key
     * @param displayAttrName name of the attribute from iterator rows to display
     * @return ADF Faces SelectItem for an iterator binding
     */
    public static List<SelectItem> selectItemsForIterator(DCIteratorBinding iter, String valueAttrName, String displayAttrName) {
        List<SelectItem> selectItems = new ArrayList<SelectItem>();
        for (Row r : iter.getAllRowsInRange()) {
            selectItems.add(new SelectItem(r.getAttribute(valueAttrName), (String)r.getAttribute(displayAttrName)));
        }
        return selectItems;
    }
    /**
     * Get List of ADF Faces SelectItem for an iterator binding.
     *
     * Uses the rowKey of each row as the SelectItem key.
     *
     * @param iteratorName ADF iterator binding name
     * @param displayAttrName name of the attribute from iterator rows to display
     * @return ADF Faces SelectItem for an iterator binding
     */
    public static List<SelectItem> selectItemsByKeyForIterator(String iteratorName, String displayAttrName) {
        return selectItemsByKeyForIterator(findIterator(iteratorName), displayAttrName);
    }
    /**
     * Get List of ADF Faces SelectItem for an iterator binding with discription.
     *
     * Uses the rowKey of each row as the SelectItem key.
     *
     * @param iteratorName ADF iterator binding name
     * @param displayAttrName name of the attribute from iterator rows to display
     * @param descriptionAttrName name of the attribute for description
     * @return ADF Faces SelectItem for an iterator binding with discription
     */
    public static List<SelectItem> selectItemsByKeyForIterator(String iteratorName, String displayAttrName, String descriptionAttrName) {
        return selectItemsByKeyForIterator(findIterator(iteratorName), displayAttrName, descriptionAttrName);
    }
    /**
     * Get List of ADF Faces SelectItem for an iterator binding with discription.
     *
     * Uses the rowKey of each row as the SelectItem key.
     *
     * @param iter ADF iterator binding
     * @param displayAttrName name of the attribute from iterator rows to display
     * @param descriptionAttrName name of the attribute for description
     * @return ADF Faces SelectItem for an iterator binding with discription
     */
    public static List<SelectItem> selectItemsByKeyForIterator(DCIteratorBinding iter, String displayAttrName, String descriptionAttrName) {
        List<SelectItem> selectItems = new ArrayList<SelectItem>();
        for (Row r : iter.getAllRowsInRange()) {
            selectItems.add(new SelectItem(r.getKey(), (String)r.getAttribute(displayAttrName), (String)r.getAttribute(descriptionAttrName)));
        }
        return selectItems;
    }
    /**
     * Get List of ADF Faces SelectItem for an iterator binding.
     *
     * Uses the rowKey of each row as the SelectItem key.
     *
     * @param iter ADF iterator binding
     * @param displayAttrName name of the attribute from iterator rows to display
     * @return List of ADF Faces SelectItem for an iterator binding
     */
    public static List<SelectItem> selectItemsByKeyForIterator(DCIteratorBinding iter, String displayAttrName) {
        List<SelectItem> selectItems = new ArrayList<SelectItem>();
        for (Row r : iter.getAllRowsInRange()) {
            selectItems.add(new SelectItem(r.getKey(), (String)r.getAttribute(displayAttrName)));
        }
        return selectItems;
    }
    /**
     * Find the BindingContainer for a page definition by name.
     *
     * Typically used to refer eagerly to page definition parameters. It is
     * not best practice to reference or set bindings in binding containers
     * that are not the one for the current page.
     *
     * @param pageDefName name of the page defintion XML file to use
     * @return BindingContainer ref for the named definition
     */
    private static BindingContainer findBindingContainer(String pageDefName) {
        BindingContext bctx = getDCBindingContainer().getBindingContext();
        return bctx.findBindingContainer(pageDefName);
    }
    /**
     * @param opList
     */
    public static void printOperationBindingExceptions(List opList) {
        if (opList != null && !opList.isEmpty()) {
            for (Object error : opList) {
                LOGGER.severe(error.toString());
            }
        }
    }
    /**
     * Adding an UI Component to the list of partial targets.
     * When the component is null, nothing will be done.
     * @param component
     * @writer Filip Huysmans
     */
    public static void addComponentToPartialTarget(UIComponent component) {
        if (component != null) {
            AdfFacesContext.getCurrentInstance().addPartialTarget(component);
        }
    }
    /**
     * Setting the focus (through javascript) on the current row
     * and put the focus in the field given.
     * The focus will be set after 500ms, to avoid the refresh done by PPR.
     * @param tbl Binding of the table
     * @param columnName The Id of the field that you want the focus to go to
     * @writer Filip Huysmans
     */
    public static void selectTableColumn(RichTable tbl, String columnName) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        String tableId = tbl.getClientId(facesContext);
        RowKeySet rks = tbl.getSelectedRowKeys();
        String inputId = "";
        if (rks != null && rks.size() > 0) {
            Object rowKey = rks.iterator().next();
            String rowId = tbl.getClientRowKeyManager().getClientRowKey(facesContext, tbl, rowKey);
            inputId = tableId + ":" + rowId + ":" + columnName;
        }
        ExtendedRenderKitService service = Service.getRenderKitService(facesContext, ExtendedRenderKitService.class);
        service.addScript(facesContext, "setTimeout('" + "comp = AdfPage.PAGE.findComponent(\\'" + inputId + "\\'); comp.focus();', 500)");
    }
    /**
     * Checks if the user has any search criteria specified in the AF/query search fields.
     * If not, shown an error messag. Otherwise performa the query
     * @param paQueryEvent The Query event
     * @param paOriginalADFQueryListener The ADF query listener that performs the search
     * @writer Rudy De Busscher
     */
    public static void onExecuteQueryListener(QueryEvent paQueryEvent, String paOriginalADFQueryListener) {
        QueryDescriptor qdesc = paQueryEvent.getDescriptor();
        Object val;
        AttributeDescriptor attrDescriptor;
        boolean validQuery = false;
        for (Criterion criterion : qdesc.getConjunctionCriterion().getCriterionList()) {
            attrDescriptor = ((AttributeCriterion)criterion).getAttribute();
            val = ((AttributeCriterion)criterion).getValues().get(0);
            // When Dropdown encountered, there's always a selected value: 0 for blank
            if (AttributeDescriptor.ComponentType.selectOneChoice != attrDescriptor.getComponentType()) {
                validQuery = val != null;
            } else {
                validQuery = Integer.parseInt(val.toString()) != 0;
            }
            if (validQuery) {
                break;
            }
        }
        if (validQuery) {
            JSFUtils.invokeMethodExpression(paOriginalADFQueryListener, paQueryEvent);
        } else {
            JSFUtils.addFacesErrorMessage(JSFUtils.getStringFromBundle("ERROR_QUERY_ALL_FIELD_EMPTY"));
        }
    }
    public static JUCtrlHierBinding getTreeBinding(String name) {
        //get reference to tree binding by its ID in the PageDef
        return (JUCtrlHierBinding)getBindingContainer().get(name);
    }
    /** * Synchronizes the table UI component row selection with the
     * selection in the ADF binding layer
     * @param selectionEvent event object created by the table
     * component upon row selection
     */
    public static void makeCurrent(SelectionEvent selectionEvent) {
        RichTable table = (RichTable)selectionEvent.getSource();
        //the Collection Model is the object that provides the
        //structured data
        //for the table to render
        CollectionModel tableModel = (CollectionModel)table.getValue();
        //the ADF object that implements the CollectionModel is
        //JUCtrlHierBinding. It is wrapped by the CollectionModel API
        JUCtrlHierBinding adfTableBinding = (JUCtrlHierBinding)tableModel.getWrappedData();
        //Acess the ADF iterator binding that is used with
        //ADF table binding
        DCIteratorBinding tableIteratorBinding = adfTableBinding.getDCIteratorBinding();
        //the role of this method is to synchronize the table component
        //selection with the selection in the ADF model
        Object selectedRowData = table.getSelectedRowData();
        //cast to JUCtrlHierNodeBinding, which is the ADF object that represents a row
        JUCtrlHierNodeBinding nodeBinding = (JUCtrlHierNodeBinding)selectedRowData;
        //get the row key from the node binding and set it as the current row in the iterator
        Key rwKey = nodeBinding.getRowKey();
        tableIteratorBinding.setCurrentRowWithKey(rwKey.toStringFormat(true));
    }
    /**
     * This method will create a List of SelectItems to be used in a selectonechoice or others.
     * It now only works for iterators based on the CodesLOV-view.
     * @param iteratorName
     * @return
     * @writer Filip Huysmans
     */
   /* public static List<SelectItem> createListSelectItemsFromIterator(String iteratorName) {
        List<SelectItem> returnList = new ArrayList<SelectItem>();
        // Getting the iterator with the possible values
        DCIteratorBinding stagemLOVIterator = ADFUtils.findIterator(iteratorName);
        stagemLOVIterator.setRangeSize(-1);
        Row[] allRowsInRange = stagemLOVIterator.getAllRowsInRange();
        if (allRowsInRange != null && allRowsInRange.length > 0) {
            for (Row r : allRowsInRange) {
                CodesLOVRowImpl row = (CodesLOVRowImpl)r;
                returnList.add(new SelectItem(row.getId(), row.getLabel()));
            }
        }
        return returnList;
    }

*/
    /**
     * Opens the popup passed as parameter
     * @param popup
     * @writer Chrisophe Goblet
     */
    public static void showPopup(RichPopup popup) {
        String popupId = popup.getClientId(FacesContext.getCurrentInstance());
        ExtendedRenderKitService erkService = Service.getService(FacesContext.getCurrentInstance().getRenderKit(), ExtendedRenderKitService.class);
        erkService.addScript(FacesContext.getCurrentInstance(), "var hints = {autodismissNever:true}; " + "AdfPage.PAGE.findComponent('" + popupId + "').show(hints);");
    }
    /**
     * Opens the popup passed as name
     * @param popupId the id of the popup to open
     * @writer Filip Huysmans
     */
    public static void showPopup(String popupId) {
        RichPopup popup = (RichPopup) JSFUtils.findComponentInRoot(popupId);
        popup.show(new RichPopup.PopupHints());
    }
}

Geen opmerkingen:

Een reactie posten