Package com.scooterframework.web.controller

Source Code of com.scooterframework.web.controller.ActionContext$Cycle

/*
*   This software is distributed under the terms of the FSF
*   Gnu Lesser General Public License (see lgpl.txt).
*
*   This program is distributed WITHOUT ANY WARRANTY. See the
*   GNU General Public License for more details.
*/
package com.scooterframework.web.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import com.scooterframework.admin.Constants;
import com.scooterframework.common.util.Converters;
import com.scooterframework.common.util.CurrentThreadCache;
import com.scooterframework.common.util.Message;
import com.scooterframework.common.util.StringUtil;

/**
* <p>
* ActionContext class holds context data in different scopes.
* </p>
*
* <p>
* There are six supported scopes: thread, parameter, request, session, context
* and global. The first scope supports data held in current thread, the next
* four scopes map to the corresponding scopes in Servlet and JSP for web
* environment. The global scope provides a place for the whole application to
* access data that can be used for all users in a static way.
* </p>
*
* @author (Fei) John Chen
*/
public abstract class ActionContext {
   
    private static final String LOCALE_KEY = Constants.CURRENT_LOCALE;
   
    //key to the flash message
    public static final String KEY_FLASH_MESSAGE = "KEY_FLASH_MESSAGE";
   
    /**
     * String constant for thread scope.
     */
    public static final String SCOPE_THREAD = "thread";
   
    /**
     * String constant for parameter scope.
     */
    public static final String SCOPE_PARAMETER = "parameter";
   
    /**
     * String constant for request scope.
     */
    public static final String SCOPE_REQUEST = "request";
   
    /**
     * String constant for session scope.
     */
    public static final String SCOPE_SESSION = "session";
   
    /**
     * String constant for context scope.
     */
    public static final String SCOPE_CONTEXT = "context";
   
    /**
     * String constant for global scope.
     */
    public static final String SCOPE_GLOBAL = "global";
   
    /**
     * Global data map.
     */
    private static Map<String, Object> globalData = new HashMap<String, Object>();

    public ActionContext() {
    }

    /**
     * <p>Gets data in parameter scope as a map.</p>
     *
     * <p>Return guaranteed: An empty map will be returned if there is no data.</p>
     *
     * @return Map
     */
    public abstract Map<String, Object> getParameterDataAsMap();
   
    /**
     * <p>Gets data in request scope as a map.</p>
     *
     * <p>Return guaranteed: An empty map will be returned if there is no data.</p>
     *
     * @return Map
     */
    public abstract Map<String, Object> getRequestDataAsMap();
   
    /**
     * <p>Gets data in both parameter scope and request scope as a map.</p>
     *
     * <p>Return guaranteed: An empty map will be returned if there is no data.</p>
     *
     * @return Map
     */
    public Map<String, Object> getAllRequestDataAsMap() {
        Map<String, Object> pm = getParameterDataAsMap();
        Map<String, Object> rm = getRequestDataAsMap();
       
        if (pm == null) pm = new HashMap<String, Object>();
       
        if (rm != null) pm.putAll(rm);
        return pm;
    }

    /**
     * <p>Gets data in parameter scope as a map. Only those keys with a specific
     * keyPrefix will be processed.</p>
     *
     * <p>Return guaranteed: An empty map will be returned if there is no data.</p>
     *
     * @return Map
     */
    public Map<String, Object> getParameterDataAsMap(String keyPrefix) {
        Map<String, Object> m = getParameterDataAsMap();
        if (keyPrefix == null || "".equals(keyPrefix)) return m;
       
        Map<String, Object> m2 = new HashMap<String, Object>();
        for (Map.Entry<String, Object> entry : m.entrySet()) {
            String key = entry.getKey();
            if (key != null && key.startsWith(keyPrefix)) {
                String key2 = key.substring(keyPrefix.length());
                m2.put(key2, entry.getValue());
            }
        }
        return m2;
    }

    /**
     * <p>Gets data in request scope as a map. Only those keys with a specific
     * keyPrefix will be processed.</p>
     *
     * <p>Return guaranteed: An empty map will be returned if there is no data.</p>
     *
     * @return Map
     */
    public Map<String, Object> getRequestDataAsMap(String keyPrefix) {
        Map<String, Object> m = getRequestDataAsMap();
        if (keyPrefix == null || "".equals(keyPrefix)) return m;
       
        Map<String, Object> m2 = new HashMap<String, Object>();
        for (Map.Entry<String, Object> entry : m.entrySet()) {
            String key = entry.getKey();
            if (key != null && key.startsWith(keyPrefix)) {
                String key2 = key.substring(keyPrefix.length());
                m2.put(key2, m.get(key));
            }
        }
        return m2;
    }
   
    /**
     * <p>Gets data in both parameter scope and request scope as a map. Only those
     * keys with a specific keyPrefix will be processed.</p>
     *
     * <p>Return guaranteed: An empty map will be returned if there is no data.</p>
     *
     * @return Map
     */
    public Map<String, Object> getAllRequestDataAsMap(String keyPrefix) {
        Map<String, Object> pm = getParameterDataAsMap(keyPrefix);
        Map<String, Object> rm = getRequestDataAsMap(keyPrefix);
       
        if (pm == null) pm = new HashMap<String, Object>();
       
        if (rm != null) pm.putAll(rm);
        return pm;
    }
   
    /**
     * <p>Gets data in session scope as a map.</p>
     *
     * <p>Return guaranteed: An empty map will be returned if there is no data.</p>
     *
     * @return Map
     */
    public abstract Map<String, Object> getSessionDataAsMap();
   
    /**
     * Gets data in context scope as a map.
     *
     * @return Map
     */
    public abstract Map<String, Object> getContextDataAsMap();
   
    /**
     * Gets data in global scope as a map.
     *
     * @return Map
     */
    public static Map<String, Object> getGlobalDataAsMap() {
        return globalData;
    }
   
    /**
     * <p>Gets data represented by the key from the thread scope.</p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.</p>
     *
     * @param key
     * @return Object
     */
    public static Object getFromThreadData(String key) {
        return CurrentThreadCache.get(key);
    }
   
    /**
     * <p>Gets data represented by the key from the parameter scope.</p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.</p>
     *
     * @param key
     * @return Object
     */
    public abstract Object getFromParameterData(String key);
   
    /**
     * <p>Gets data represented by the key from the parameter scope. Ignore the
     * case of the key string.</p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.</p>
     *
     * @param key
     * @return Object
     */
    public Object getFromParameterDataIgnoreCase(String key) {
      if (key == null) return null;
     
        Object tmp = null;
        Map<String, Object> m = getParameterDataAsMap();
        if (m == null) return null;
       
        for (Map.Entry<String, Object> entry : m.entrySet()) {
            String name = entry.getKey();
            if (name.equalsIgnoreCase(key)) {
                tmp = entry.getValue();
                break;
            }
        }
        return tmp;
    }
   
    /**
     * <p>Gets data represented by the key from the request scope.</p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.</p>
     *
     * @param key
     * @return Object
     */
    public abstract Object getFromRequestData(String key);
   
    /**
     * <p>Gets data represented by the key from the session scope.</p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.</p>
     *
     * @param key
     * @return Object
     */
    public abstract Object getFromSessionData(String key);
   
    /**
     * <p>Gets data represented by the key from the context scope.</p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.</p>
     *
     * @param key
     * @return Object
     */
    public abstract Object getFromContextData(String key);
   
    /**
     * <p>Gets data represented by the key from the global scope.</p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.</p>
     *
     * @param key
     * @return Object
     */
    public static Object getFromGlobalData(String key) {
        return getGlobalDataAsMap().get(key);
    }
   
    /**
     * Gets the first message represented by the type from the flash.
     *
     * @param type
     * @return String
     */
    public String getFirstFlashMessage(String type) {
        FlashMessage fm = (FlashMessage)getFromRequestData(KEY_FLASH_MESSAGE);
        return (fm != null)?fm.getFirst(type):"";
    }
   
    /**
     * Gets the latest message represented by the type from the flash.
     *
     * @param type
     * @return String
     */
    public String getLatestFlashMessage(String type) {
        FlashMessage fm = (FlashMessage)getFromRequestData(KEY_FLASH_MESSAGE);
        return (fm != null)?fm.getLast(type):"";
    }
   
    /**
     * Gets all messages represented by the type from the flash.
     *
     * @param type flash message type
     * @return list of messages
     */
    public List<Message> getAllFlashMessages(String type) {
        FlashMessage fm = (FlashMessage)getFromRequestData(KEY_FLASH_MESSAGE);
        return (fm != null)?fm.getAll(type):null;
    }
   
    /**
     *  <p>Gets data represented by the key from the first scope it is found in
     * parameter scope and request scope.</p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.</p>
     *
     * @param key
     * @return Object
     */
    public Object getFromAllRequestData(String key) {
        Object o = getFromParameterData(key);
        if (o == null) {
            o = getFromRequestData(key);
        }
        return o;
    }
   
    /**
     * <p>Gets data represented by the key from the first scope it is found.</p>
     *
     * <p>
     * There are six supported scopes: thread, parameter, request, session, context
     * and global. The first scope supports data held in current thread, the next
     * four scopes map to the corresponding scopes in Servlet and JSP for web
     * environment. The global scope provides a place for the whole application to
     * access data that can be used for all users in a static way.
     * </p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.<p>
     *
     * @param key
     * @return Object
     */
    public Object get(String key) {
        Object o = getFromThreadData(key);
        if (o == null) {
            o = getFromParameterData(key);
            if (o == null) {
                o = getFromRequestData(key);
                if (o == null) {
                    o = getFromSessionData(key);
                    if (o == null) {
                        o = getFromContextData(key);
                        if (o == null) {
                            o = getFromGlobalData(key);
                        }
                    }
                }
            }
        }
        return o;
    }
   
    /**
     * <p>Gets data represented by the key from the specific scope.</p>
     *
     * <p>
     * There are six supported scopes: thread, parameter, request, session, context
     * and global. The first scope supports data held in current thread, the next
     * four scopes map to the corresponding scopes in Servlet and JSP for web
     * environment. The global scope provides a place for the whole application to
     * access data that can be used for all users in a static way.
     * </p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.</p>
     *
     * @param key
     * @return Object
     */
    public Object get(String key, String scope) {
        Object o = null;
        if (SCOPE_THREAD.equals(scope)) {
            o = getFromThreadData(key);
        }
        else if (SCOPE_PARAMETER.equals(scope)) {
            o = getFromParameterData(key);
        }
        else if (SCOPE_REQUEST.equals(scope)) {
            o = getFromRequestData(key);
        }
        else if (SCOPE_SESSION.equals(scope)) {
            o = getFromSessionData(key);
        }
        else if (SCOPE_CONTEXT.equals(scope)) {
            o = getFromContextData(key);
        }
        else if (SCOPE_GLOBAL.equals(scope)) {
            o = getFromGlobalData(key);
        }
        else {
            throw new IllegalArgumentException("Undefined scope: " + scope + ".");
        }
        return o;
    }
   
    /**
     * <p>Removes data represented by the key from all scopes except the
     * parameter scope. There is no servlet API that can remove data from
     * parameter scope.</p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.</p>
     *
     * @param key
     */
    public void remove(String key) {
        removeFromThreadData(key);
        removeFromRequestData(key);
        removeFromSessionData(key);
        removeFromContextData(key);
        removeFromGlobalData(key);
    }
   
    /**
     * <p>Removes data represented by the key from thread scope.</p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.</p>
     *
     * @param key
     */
    public static void removeFromThreadData(String key) {
        CurrentThreadCache.clear(key);
    }
   
    /**
     * <p>Removes data represented by the key from request scope.</p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.</p>
     *
     * @param key
     */
    public abstract void removeFromRequestData(String key);
   
    /**
     * <p>Removes data represented by the key from session scope.</p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.</p>
     *
     * @param key
     */
    public abstract void removeFromSessionData(String key);
   
    /**
     * <p>Removes data represented by the key from context scope.</p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.</p>
     *
     * @param key
     */
    public abstract void removeFromContextData(String key);
   
    /**
     * <p>Removes data represented by the key from global scope.</p>
     *
     * <p>Note: The result of this method is sensitive to the case of key string.</p>
     *
     * @param key
     */
    public static void removeFromGlobalData(String key) {
        getGlobalDataAsMap().remove(key);
    }
   
    /**
     * Removes all data represented by the key from session scope.
     */
    public abstract void removeAllSessionData();
   
    /**
     * Stores the object represented by the key to thread scope.
     *
     * @param key String
     * @param value Object
     */
    public static void storeToThread(String key, Object value) {
        CurrentThreadCache.set(key, value);
    }
   
    /**
     * Stores the object represented by the key to request scope.
     *
     * @param key String
     * @param value Object
     */
    public abstract void storeToRequest(String key, Object value);
   
    /**
     * Stores the object represented by the key to session scope.
     *
     * @param key String
     * @param value Object
     */
    public abstract void storeToSession(String key, Object value);
   
    /**
     * Stores the object represented by the key to context scope.
     *
     * @param key String
     * @param object Object
     */
    public abstract void storeToContext(String key, Object object);
   
    /**
     * Stores the object represented by the key to global scope.
     *
     * @param key String
     * @param value Object
     */
    public static void storeToGlobal(String key, Object value) {
        getGlobalDataAsMap().put(key, value);
    }
   
    /**
     * Sets message for a type.
     */
    public void setFlashMessage(String type, String message) {
        setFlashMessage(type, new Message(message));
    }
   
    /**
     * Sets message for a type.
     */
    public void setFlashMessage(String type, Message message) {
        FlashMessage fm = (FlashMessage)getFromSessionData(KEY_FLASH_MESSAGE);
        if (fm == null) {
            fm = new FlashMessage();
            storeToSession(KEY_FLASH_MESSAGE, fm);
        }
        fm.addMessage(type, message);
       
        //set to request too
        FlashMessage fm2 = (FlashMessage)getFromRequestData(KEY_FLASH_MESSAGE);
        if (fm2 == null) {
            storeToRequest(KEY_FLASH_MESSAGE, fm);
        }
        else {
            fm2.addMessage(type, message);
        }
    }
   
    /**
     * Removes FlashMessage data from session and stores it in the
     * incoming request.
     */
    public void resetFlashMessage() {
        FlashMessage fm = (FlashMessage)getFromSessionData(KEY_FLASH_MESSAGE);
        if (fm != null) {
            storeToRequest(KEY_FLASH_MESSAGE, fm);
            removeFromSessionData(KEY_FLASH_MESSAGE);
        }
    }
   
    /**
     * Returns errors as Map.
     *
     * @return Map of error
     */
    public Map<String, Object> getErrorAsMap() {
        return errors;
    }
   
    /**
     * Sets a map of error to error map.
     *
     * @param errors Map
     */
    public void setErrors(Map<String, Object> errors) {
      if (errors != null) this.errors.putAll(errors);
    }
   
    /**
     * Gets an error object represented by a key to error map.
     *
     * @param key The key to the error object.
     * @return error Object
     */
    public Object getError(String key) {
        return errors.get(key);
    }
   
    /**
     * Sets an error object represented by a key to error map.
     *
     * @param error An error object.
     */
    public void setError(String key, Object error) {
        errors.put(key, error);
    }
   
    /**
     * Errors map.
     */
    protected Map<String, Object> errors = new HashMap<String, Object>();
   
   
    /**
     * <p>Retrieves a map of primary key and values.</p>
     *
     * <p>The result map is restricted to those keys in the input with a specific
     * prefix.</p>
     *
     * @param keyPrefix a prefix string.
     * @param pkNames an array of primary key names.
     * @return map Map of primary key data.
     */
    public Map<String, Object> retrievePrimaryKeyDataMapFromRequest(String keyPrefix, String[] pkNames) {
        if (pkNames == null || pkNames.length == 0) return new HashMap<String, Object>();
        if (keyPrefix == null) keyPrefix = "";
       
        Map<String, Object> hm = new HashMap<String, Object>();
        Map<String, Object> dataMap = getAllRequestDataAsMap(keyPrefix);
        if (dataMap == null) return hm;
       
        for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
            String key = entry.getKey();
            if (key != null && StringUtil.isStringInArray(key, pkNames, true)) hm.put(key.toLowerCase(), entry.getValue());
        }
       
        return hm;
    }
   
    /**
     * Retrieves a map of primary key and values.
     *
     * @param pkNames an array of primary key names.
     * @return map Map of primary key data.
     */
    public Map<String, Object> retrievePrimaryKeyDataMapFromRequest(String[] pkNames) {
        return retrievePrimaryKeyDataMapFromRequest("", pkNames);
    }
   
    /**
     * Checks if the value of a field is required.
     *
     * @param name name of a request parameter.
     * @return true if required
     */
    public boolean isRequiredField(String name) {
        boolean require = false;
        String value = (String)get(name);
        if ("on".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value)) require = true;
        return require;
    }
   
    /**
     * <p>Returns Locale object from the first scope it is found. If no locale
     * object is found, <tt>Locale.getDefault()</tt> is returned. </p>
     *
     * <p>
     * There are six supported scopes: thread, parameter, request, session, context
     * and global. The first scope supports data held in current thread, the next
     * four scopes map to the corresponding scopes in Servlet and JSP for web
     * environment. The global scope provides a place for the whole application to
     * access data that can be used for all users in a static way.
     * </p>
     *
     * @return Locale for the scope
     */
    public Locale getLocale() {
        Locale l = (Locale)get(LOCALE_KEY);
        if (l == null) {
            l = Locale.getDefault();
        }
        return l;
    }
   
    /**
     * Returns Locale of a scope. If no locale object is found, <tt>Locale.getDefault()</tt>
     * is returned.
     *
     * @param scope the specific scope
     * @return Locale for the scope
     */
    public Locale getLocale(String scope) {
        return (Locale)get(LOCALE_KEY, scope);
    }
   
    /**
     * Stores locale object in a scope. The scope is either <tt>request</tt> or
     * <tt>session</tt> or <tt>context</tt> or <tt>global</tt>.
     *
     * @param locale
     * @param scope
     */
    public void setLocale(Locale locale, String scope) {
        if (SCOPE_REQUEST.equals(scope)) {
            storeToRequest(LOCALE_KEY, locale);
        }
        else if (SCOPE_SESSION.equals(scope)) {
            storeToSession(LOCALE_KEY, locale);
        }
        else if (SCOPE_CONTEXT.equals(scope)) {
            storeToContext(LOCALE_KEY, locale);
        }
        else if (SCOPE_GLOBAL.equals(scope)) {
            storeToGlobal(LOCALE_KEY, locale);
        }
        else {
            throw new IllegalArgumentException("Unsupported scope value for storing locale object: " + scope + ".");
        }
    }
   
    /**
     * Sets locale object to be used by a single user request.
     * @param locale
     */
    public void setRequestLocale(Locale locale) {
        setLocale(locale, SCOPE_REQUEST);
    }
   
    /**
     * Sets locale object to be used by a single user session.
     *
     * @param locale
     */
    public void setSessionLocale(Locale locale) {
        setLocale(locale, SCOPE_SESSION);
    }
   
    /**
     * Sets locale object to be used by all users.
     *
     * @param locale
     */
    public static void setGlobalLocale(Locale locale) {
        storeToGlobal(LOCALE_KEY, locale);
    }
   
    /**
     * Gets a locale object that can be used by all users.
     */
    public static Locale getGlobalLocale() {
        return (Locale)getFromGlobalData(LOCALE_KEY);
    }
   
    /**
     * Returns an item from a list of items.
     *
     * Examples:
     * <pre>
     *      class=<%=W.cycle("odd, even")%>
     *      -- use "red" class for odd rows and "blue" class for even rows.
     * </pre>
     *
     * @param items list of items to be cycled
     * @return an item value
     */
    public String cycle(String items) {
        return cycle(items, items);
    }
   
    /**
     * Returns an item from a list of items. The <tt>items</tt> string may
     * contain several items separated by comma.
     *
     * @param items list of items to be cycled
     * @param name the cycle name
     * @return an item value
     */
    public String cycle(String items, String name) {
        if (items == null || "".equals(items)) return "";
       
        Cycle c = (Cycle)getCycleFromCycleMap(name);
        if (c == null) {
            c = new Cycle(items);
            setCycleToCycleMap(name, c);
        }
       
        //in case the same cycle name is used somewhere else but with a
        //different list of items to cycle through which may cause something
        //like IndexOutOfBound exception
        if (!items.equals(c.cycleStrings)) {
            c.setItems(items);
        }
       
        return c.getValue();
    }
   
    /**
     * Returns current item in the named cycle.
     *
     * @param name  name of the cycle
     * @return current item in the named cycle.
     */
    public String currentCycle(String name) {
        Cycle c = (Cycle)getCycleFromCycleMap(name);
        return (c != null)?c.getCurrentValue():"";
    }
   
    /**
     * Resets the cycle
     *
     * @param name cycle's name
     */
    public void resetCycle(String name) {
        Cycle c = (Cycle)getCycleFromCycleMap(name);
        if (c != null) c.resetPointer();
    }
   
    /**
     * Returns a named cycle from cycle map.
     *
     * @param name
     * @return cycle object
     */
    abstract protected Object getCycleFromCycleMap(String name);
   
    /**
     * Sets a named cycle in cycle map.
     *
     * @param name
     * @param cycle
     */
    abstract protected void setCycleToCycleMap(String name, Object cycle);
   
    private static class Cycle {
        public Cycle(String items) {
            cycleStrings = items;
            setItems(items);
            currentIndex = 0;
        }
       
        void setItems(String items) {
            itemsList = Converters.convertStringToList(items);
            totalSize = itemsList.size();
        }
       
        String getValue() {
            int pointer = getPointer();
            if (pointer == -1) return "";
            latestItem = itemsList.get(pointer);
           
            return latestItem;
        }
       
        String getCurrentValue() {
            return latestItem;
        }
       
        private int getPointer() {
            if (totalSize == 0) return -1; //nothing to cycle
           
            int pointer = currentIndex;
           
            //move to next item
            incrementPointer(currentIndex);
           
            return pointer;
        }
       
        void resetPointer() {
            currentIndex = 0;
        }
       
        private void incrementPointer(int index) {
            currentIndex = index + 1;
            if (currentIndex >= totalSize) {
                resetPointer();
            }
        }
       
        private String cycleStrings = "";
        private List<String> itemsList = null;
        private int currentIndex = 0;
        private String latestItem = "";
        private int totalSize = 0;
    }
}
TOP

Related Classes of com.scooterframework.web.controller.ActionContext$Cycle

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.