/*
 * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
 *
 * The contents of this file are subject to the CCM Public
 * License (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the
 * License at http://www.redhat.com/licenses/ccmpl.html.
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language
 * governing rights and limitations under the License.
 *
 */
package com.arsdigita.cms.ui;


import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.PaginationModelBuilder;
import com.arsdigita.bebop.Paginator;
import com.arsdigita.bebop.RequestLocal;
import com.arsdigita.bebop.SimpleComponent;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.ChangeEvent;
import com.arsdigita.bebop.event.ChangeListener;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.Image;
import com.arsdigita.cms.CMS;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.ContentSection;
import com.arsdigita.cms.ContentType;
import com.arsdigita.cms.Folder;
import com.arsdigita.cms.ui.authoring.CreationSelector;
import com.arsdigita.cms.ui.folder.FolderSelectionModel;
import com.arsdigita.cms.util.SecurityConstants;
import com.arsdigita.cms.workflow.CMSTask;
import com.arsdigita.domain.DataObjectNotFoundException;
import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.kernel.Kernel;
import com.arsdigita.kernel.Party;
import com.arsdigita.kernel.User;
import com.arsdigita.kernel.permissions.PermissionManager;
import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.kernel.permissions.UniversalPermissionDescriptor;
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
import com.arsdigita.persistence.CompoundFilter;
import com.arsdigita.persistence.DataQuery;
import com.arsdigita.persistence.Filter;
import com.arsdigita.persistence.FilterFactory;
import com.arsdigita.persistence.OID;
import com.arsdigita.persistence.SessionManager;
import com.arsdigita.util.Assert;
import com.arsdigita.util.StringUtils;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.RedirectSignal;
import com.arsdigita.web.Web;
import com.arsdigita.workflow.simple.Engine;
import com.arsdigita.workflow.simple.Workflow;
import com.arsdigita.xml.Element;
import com.arsdigita.cms.util.GlobalizationUtil;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Iterator;
import javax.servlet.ServletException;

import org.apache.log4j.Logger;

public class TasksPanel extends CMSContainer {

    public static final String versionId = "$Id: //cms/dev/src/com/arsdigita/cms/ui/TasksPanel.java#21 $ by $Author: dennis $, $DateTime: 2004/04/07 16:07:11 $";

    private static Logger s_log =
        Logger.getLogger(TasksPanel.class);

    // The default number of rows to show
    private static final int DEFAULT_MAX_ROWS = 15;

    // Number of tasks to show
    private final int m_maxRows;

    private TaskList m_taskList;
    private ActionLink m_viewAllLink;
    private ActionLink m_viewShortLink;
    private Paginator m_paginator;
    private ActionLink m_viewLockLink,m_viewUnlockLink,m_viewAllLockLink;
    private Label m_viewLockLabel,m_viewUnlockLabel,m_viewAllLockLabel;
    private Label m_actionLabel;
    private StringParameter m_sortDirectionParam;
    private StringParameter m_sortTypeParam;
    private StringParameter m_lockFilterParam;

    // control link variable
    private static final String ACTION = "taskAction";
    private static final String SORT_ACTION_DOWN = "sortActionUp";
    private static final String SORT_ACTION_UP = "sortActionDown";

    public static final String LOCK_FILTER_TYPE = "lockFilterType";
    public static final String SORT_TYPE = "sortType";
    public static final String SORT_DIRECTION = "sortDirection";
    public static final String SORT_USER = "user";
    public static final String SORT_TITLE = "title";
    public static final String SORT_DATE = "date";
    public static final String SORT_STATUS = "status";

    // IMAGES
    public static final String UP_ARROW_IMAGE = "/assets/gray-triangle-up.gif";
    public static final String DOWN_ARROW_IMAGE = "/assets/gray-triangle-down.gif";

    // CREATION PANE CONSTANTS
    private Label m_selectorLabel;
    private CreationSelector m_selector;
    private ContentSectionContainer m_sections;
    private ACSObjectSelectionModel m_sectionSel;
    private ACSObjectSelectionModel m_typeSel;
    private RootFolderSelectionModel m_folderSel;
    private BoxPanel m_creationPane;

    /**
     * Constructs a new task panel that shows no more than 15
     * enabled tasks by default.
     **/
    public TasksPanel(ACSObjectSelectionModel typeModel,
                      ACSObjectSelectionModel sectionModel) {
        this(DEFAULT_MAX_ROWS,typeModel,sectionModel);
    }

    /**
     * Constructs a new task panel that shows no more than maxRows
     * enabled tasks by default.
     *
     * @param maxRows the maximum number of rows to show by default
     *
     * @pre maxRows != null
     **/
    public TasksPanel(int maxRows,ACSObjectSelectionModel typeModel,
                      ACSObjectSelectionModel sectionModel) {
        super();
        m_maxRows = maxRows;
	
        m_typeSel = typeModel;
        m_sectionSel = sectionModel;

        m_sortDirectionParam = new StringParameter(SORT_DIRECTION);
        m_sortTypeParam = new StringParameter(SORT_TYPE);
        m_lockFilterParam = new StringParameter(LOCK_FILTER_TYPE);
        addComponents();
    }


    /**
     * Adds the components to this tasks panel
     **/
    protected void addComponents() {
        m_creationPane = new BoxPanel(BoxPanel.VERTICAL);
	
        // A label that says "Create $content_type in $section"
        m_selectorLabel = new Label(new PrintListener() {
                public void prepare(PrintEvent e) {
                    PageState s = e.getPageState();
                    Label t = (Label)e.getTarget();
		    
                    ContentType type = (ContentType) m_typeSel.getSelectedObject(s);
                    ContentSection sec =
                        (ContentSection) m_sectionSel.getSelectedObject(s);
		    
                    StringBuffer buf = new StringBuffer(GlobalizationUtil.globalize("cms.ui.create").localize() + " ");
                    buf.append(type.getLabel());
                    buf.append(" in ");
                    buf.append(sec.getName());
		    
                    t.setLabel(buf.toString());
                    t.setFontWeight(Label.BOLD);
                    t.setClassAttr("creationLabel");
                }
            });
        m_selectorLabel.setClassAttr("creationLabel");
        m_creationPane.add(m_selectorLabel);
	
        m_folderSel = new RootFolderSelectionModel(m_sectionSel);
        m_selector = new CreationSelector(m_typeSel, m_folderSel);
        m_creationPane.add(m_selector);
	
        m_creationPane.setClassAttr("itemCreationPane");
        add(m_creationPane);
	
        // The section list UIx
        m_sections = new ContentSectionContainer(m_typeSel, m_sectionSel);
        add(m_sections);
	
        // When a new type is selected, show the creation UI.
        // When the selection is cleared, return to section list
        m_typeSel.addChangeListener(new ChangeListener() {
                public void stateChanged(ChangeEvent e) {
                    PageState s = e.getPageState();
                    boolean isSelected = m_typeSel.isSelected(s);
		    
                    m_sections.setVisible(s, !isSelected);
                    m_creationPane.setVisible(s, isSelected);
                }
            });
       	
        m_viewLockLink = new ActionLink(new Label(GlobalizationUtil.globalize("cms.ui.workflow.task.view_locked")));
        m_viewLockLink.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    PageState ps = e.getPageState();
                    ps.setValue(m_lockFilterParam, "lock");
                }
            });

        m_viewUnlockLink = new ActionLink(new Label(GlobalizationUtil.globalize("cms.ui.workflow.task.view_unlocked")));
        m_viewUnlockLink.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    PageState ps = e.getPageState();
                    ps.setValue(m_lockFilterParam, "unlock");
                }
            });

        m_viewAllLockLink = new ActionLink(new Label(GlobalizationUtil.globalize("cms.ui.workflow.task.view_all")));
        m_viewAllLockLink.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    PageState ps = e.getPageState();
                    ps.setValue(m_lockFilterParam, "all");
                }
            });

        m_viewLockLabel = new Label(GlobalizationUtil.globalize("cms.ui.workflow.task.view_locked"));
        m_viewLockLabel.setFontWeight(Label.BOLD);
        m_viewUnlockLabel = new Label(GlobalizationUtil.globalize("cms.ui.workflow.task.view_unlocked"));
        m_viewUnlockLabel.setFontWeight(Label.BOLD);
        m_viewAllLockLabel = new Label(GlobalizationUtil.globalize("cms.ui.workflow.task.view_all"));
        m_viewAllLockLabel.setFontWeight(Label.BOLD);

        add(new Label("<br />",false));
        add(m_viewLockLink);
        add(m_viewLockLabel);
        add(new Label("&nbsp;",false));
        add(m_viewUnlockLink);
        add(m_viewUnlockLabel);
        add(new Label("&nbsp;",false));
        add(m_viewAllLockLink);
        add(m_viewAllLockLabel);
        add(new Label("<br />",false));
        add(new Label("<br />",false));
    
        add(getTasksList());
        add(getPaginator());

        m_actionLabel = new Label(GlobalizationUtil.globalize("cms.ui.action"));
        m_actionLabel.setClassAttr("action");
    }

    public void register(Page p) {
        super.register(p);

        p.setVisibleDefault(m_creationPane, false);
        p.addComponentStateParam(this, m_folderSel.getStateParameter());

        p.addGlobalStateParam(m_lockFilterParam);
        p.addGlobalStateParam(m_sortTypeParam);
        p.addGlobalStateParam(m_sortDirectionParam);

        p.setVisibleDefault(m_viewLockLabel, false);
        p.setVisibleDefault(m_viewUnlockLabel, false);
        p.setVisibleDefault(m_viewAllLockLink, false);

        p.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    final PageState state = e.getPageState();

                    String lockFilterType = getLockFilterType(state);

                    if ( lockFilterType.equals("lock") ) {
                        m_viewLockLabel.setVisible(state,true);
                        m_viewLockLink.setVisible(state,false);
                        m_viewUnlockLabel.setVisible(state,false);
                        m_viewUnlockLink.setVisible(state,true);
                        m_viewAllLockLabel.setVisible(state,false);
                        m_viewAllLockLink.setVisible(state,true);
                    } else if ( lockFilterType.equals("unlock") ) {
                        m_viewLockLabel.setVisible(state,false);
                        m_viewLockLink.setVisible(state,true);
                        m_viewUnlockLabel.setVisible(state,true);
                        m_viewUnlockLink.setVisible(state,false);
                        m_viewAllLockLabel.setVisible(state,false);
                        m_viewAllLockLink.setVisible(state,true);
                    } else {
                        m_viewLockLabel.setVisible(state,false);
                        m_viewLockLink.setVisible(state,true);
                        m_viewUnlockLabel.setVisible(state,false);
                        m_viewUnlockLink.setVisible(state,true);
                        m_viewAllLockLabel.setVisible(state,true);
                        m_viewAllLockLink.setVisible(state,false);
                    }
                }
            });
    }
    
    public void reset(PageState state) {
        m_typeSel.clearSelection(state);
        m_sectionSel.clearSelection(state);
    }
    
    protected Paginator getPaginator() {
        if (m_paginator == null) {
            m_paginator = new Paginator(new TasksPaginationModelBuilder(), 
                                        m_maxRows);
        }
        return m_paginator;
    }


    /**
     * Returns the bebop List component to display the tasks
     **/
    private TaskList getTasksList() {
        if (m_taskList == null) {
            m_taskList = new TaskList(true);
        }
        return m_taskList;
    }

    /**
     * Returns the number of enabled tasks for the specified user.
     **/
    protected int numberTasksForUser(PageState state) {
        return m_taskList.size(state);
    }

    protected String getSortType(PageState state) {
        String sortType = (String)state.getValue(m_sortTypeParam);
        if ( sortType == null ) {
            sortType = SORT_DATE;
        }
        return sortType;
    }

    protected String getSortDirection(PageState state) {
        String sortDirection = (String)state.getValue(m_sortDirectionParam);
        if ( sortDirection == null ) {
            sortDirection = SORT_ACTION_UP;
        }
        return sortDirection;
    }

    protected String getLockFilterType(PageState state) {
        String lockFilterType = (String)state.getValue(m_lockFilterParam);
        if ( lockFilterType == null || lockFilterType.equals("") ) {
            lockFilterType = "";
        }
        return lockFilterType;
    }

    /*
     * Adds filters to the task query
     */
    protected void addQueryFilters(DataQuery query,Party party,PageState state){
        query.setParameter("userId", party.getID());

	    FilterFactory ff = query.getFilterFactory();

        // TODO: remove this hard coding of "Author", "Edit", and "Deploy"
	    CompoundFilter authorFilter = ff.and();
	    authorFilter.addFilter(ff.equals("taskType","Author"));
	    authorFilter.addFilter(getTaskFilter("Author", party, ff));

	    CompoundFilter approveFilter = ff.and();
	    approveFilter.addFilter(ff.equals("taskType","Edit"));
	    approveFilter.addFilter(getTaskFilter("Edit", party, ff));

	    CompoundFilter deployFilter = ff.and();
	    deployFilter.addFilter(ff.equals("taskType","Deploy"));
	    deployFilter.addFilter(getTaskFilter("Deploy", party, ff));

	    CompoundFilter permissionFilter = ff.or();
	    permissionFilter.addFilter(authorFilter);
	    permissionFilter.addFilter(approveFilter);
	    permissionFilter.addFilter(deployFilter);

	    query.addFilter(permissionFilter);

	    String lockFilterType = getLockFilterType(state);
	    if ( lockFilterType.equals("lock") ) {
            query.addEqualsFilter("isLocked","t");
            query.addEqualsFilter("status","1");
	    } else if ( lockFilterType.equals("unlock") ) {
            query.addEqualsFilter("isLocked","f");
	    }
    }

    private static class RootFolderSelectionModel
        extends FolderSelectionModel {
        ACSObjectSelectionModel m_sectionSel;

        public RootFolderSelectionModel(ACSObjectSelectionModel sectionSel) {
            super("f");
            m_sectionSel = sectionSel;
        }

        protected BigDecimal getRootFolderID(PageState s) {
            ContentSection sec = (ContentSection) m_sectionSel.getSelectedObject(s);
            Assert.assertNotNull(sec);

           User user = Web.getContext().getUser();
            if ( user != null ) {
                Folder folder = Folder.getUserHomeFolder(user,sec);
                if ( folder != null ) {
                    return folder.getID();
                }
            }
            return sec.getRootFolder().getID();
        }
    }

    private class TasksPaginationModelBuilder implements PaginationModelBuilder {
        public int getTotalSize(Paginator paginator,
                                PageState state) {
            return numberTasksForUser(state);
        }

        public boolean isVisible(PageState state) {
            return numberTasksForUser(state) > m_maxRows;
        }
    }

    private class TaskList extends SimpleComponent {

        private final static String QUERY_NAME =
            "com.arsdigita.cms.workflow.getEnabledUserTasks";

        private boolean m_paginate = false;

        public TaskList(boolean paginate) {
            m_paginate = paginate;
        }

        private DataQuery makeQuery(PageState state) {
            User user = (User)Kernel.getContext().getParty();

            DataQuery query = SessionManager.getSession().retrieveQuery
                ("com.arsdigita.cms.workflow.getEnabledUserTasks");
            addQueryFilters(query,user,state);

            return query;
        }

        public int size(PageState ps) {
            return ((Long) m_taskCount.get(ps)).intValue();
        }

        private RequestLocal m_taskCount = new RequestLocal() {
            public Object initialValue(PageState state) {
                DataQuery query = makeQuery(state);
                return new Long(query.size());
            }
        };

        public void generateXML(PageState state,
                                Element parent) {
            Element content = parent.newChildElement("cms:tasksPanel", CMS.CMS_XML_NS);
            exportAttributes(content);

            DataQuery query = makeQuery(state);

            String lockFilterType = getLockFilterType(state);
            content.addAttribute("lockFilterType",lockFilterType);

            if (m_paginate) {
                query.setRange(new Integer(m_paginator.getFirst(state)),
                               new Integer(m_paginator.getLast(state) + 1));
            }

            String sortKey = getSortType(state);
            String sortDirection = getSortDirection(state);
            String sortPostfix = " asc";
            if (sortDirection.equals(SORT_ACTION_DOWN)) {
                sortPostfix = " desc";
            }
            
            if ( sortKey.equals(SORT_TITLE) ) {
                query.setOrder("lower(pageTitle) " + sortPostfix + 
                               ", lower(status) asc, dueDate desc");
            } else if ( sortKey.equals(SORT_DATE) ) {
                query.setOrder("dueDate " + sortPostfix + 
                               ", lower(status) asc, lower(pageTitle) asc");
            } else if ( sortKey.equals(SORT_USER) ) {
                query.setOrder("lockingUserID " + sortPostfix +
                               ", lower(status) asc, dueDate desc, " + 
                               " lower(pageTitle) asc");
            } else if ( sortKey.equals(SORT_STATUS) ) {
                query.setOrder("lower(status) " + sortPostfix +
                               ", dueDate desc, " + 
                               " lower(pageTitle) asc");

	    }
	    
            HashMap sections = new HashMap();

            while (query.next()) {
                BigDecimal sectionID = (BigDecimal)query.get("sectionID");
                String sectionPath = (String)sections.get(sectionID);
                if (sectionPath == null) {
                    try {
                        ContentSection section = (ContentSection)DomainObjectFactory
                            .newInstance(new OID(ContentSection.BASE_DATA_OBJECT_TYPE,
                                                 sectionID));
                        sectionPath = section.getPath();
                    } catch (DataObjectNotFoundException ex) {
                        throw new UncheckedWrapperException("cannot find content section", ex);
                    }
                    sections.put(sectionID, sectionPath);
                }

                Element task = content.newChildElement("cms:tasksPanelTask", CMS.CMS_XML_NS);

                BigDecimal itemID = (BigDecimal)query.get("itemID");
                String taskType = (String)query.get("taskType");
                
                task.addAttribute("taskID", query.get("taskID").toString());
                task.addAttribute("processID", query.get("processID").toString());
                task.addAttribute("taskLabel", (String)query.get("taskLabel"));
                task.addAttribute("taskDescription", (String)query.get("taskDescription"));

                String isLocked = (String)query.get("isLocked");
                task.addAttribute("isLocked", isLocked);
                if (query.get("dueDate") != null) {
                    java.util.Date d = (java.util.Date)query.get("dueDate");
                    SimpleDateFormat df = new SimpleDateFormat("EEE, MMM d, yyyy");

                    task.addAttribute("dueDate", df.format(d));
                }

                task.addAttribute("itemID", itemID.toString());
                task.addAttribute("sectionID", query.get("sectionID").toString());
                task.addAttribute("sectionPath", sectionPath);
                task.addAttribute("pageName", (String)query.get("pageName"));
                task.addAttribute("pageTitle", (String)query.get("pageTitle"));

                BigDecimal lockingUserID = (BigDecimal)query.get("lockingUserID");
                if (lockingUserID != null) {
                    task.addAttribute("lockingUserID", lockingUserID.toString());
                    if ( !"f".equals(isLocked) ) {
                        User lockingUser = User.retrieve(lockingUserID);
                        if ( lockingUser != null ) {
                            task.addAttribute("assignee",lockingUser.getDisplayName());
                        }
                    }
                }
                task.addAttribute("taskType", taskType);
                task.addAttribute("taskTypeClass", (String)query.get("taskTypeClass"));
                task.addAttribute("status", query.get("status").toString());

                // control event for locking a task
                try {
                    state.setControlEvent(this, ACTION, itemID.toString());
                    task.addAttribute("actionURL", state.stateAsURL());
                    state.clearControlEvent();
                } catch (java.io.IOException ex) {
                    s_log.warn("Error: " + ex.getMessage());
                }

                if ("Deploy".equals(taskType)) {
                    task.addAttribute("editTabNumber", String.valueOf(ContentItemPage.PUBLISHING_TAB));
                } else {
                    task.addAttribute("editTabNumber", String.valueOf(ContentItemPage.AUTHORING_TAB));
                }
            }

            m_actionLabel.generateXML(state, content);

            String[][] sortableHeaders = 
                {{SORT_TITLE, "cms.ui.workflow.task.item_title"},
                 {SORT_DATE, "cms.tasks.ui.due_date"},
                 {SORT_STATUS, "cms.tasks.ui.status_no_colon"},
                 {SORT_USER, "cms.ui.workflow.task.locking_user"}};
            for (int i=0;i<sortableHeaders.length;i++) {
                String header = sortableHeaders[i][0];
                String labelKey = sortableHeaders[i][1];
                if (sortDirection.equals(SORT_ACTION_UP) && header.equals(sortKey)) {
                    state.setControlEvent(this, SORT_ACTION_DOWN, header);
                } else {
                    state.setControlEvent(this, SORT_ACTION_UP, header);
                }
                SimpleContainer container = new SimpleContainer();
                container.add(new Label(GlobalizationUtil.globalize(labelKey)));
                if (header.equals(sortKey)) {
                    String imageURLStub = null;
                    if (SORT_ACTION_UP.equals(sortDirection)) {
                        imageURLStub = UP_ARROW_IMAGE;
                    } else {
                        imageURLStub = DOWN_ARROW_IMAGE;
                    }
                    Image image = new Image(imageURLStub);
                    image.setBorder("0");
                    container.add(image);
                }

                ControlLink link = new ControlLink(container);
                link.setClassAttr(header);
                link.generateXML(state, content);
                state.clearControlEvent();
            }
        }


        public void respond(PageState state) throws ServletException {
            String key = state.getControlEventName();
            String value = state.getControlEventValue();
            if (ACTION.equals(key)) {
                BigDecimal itemID = new BigDecimal(value);
		
                try {
                    ContentItem item = new ContentItem(itemID);
                    Workflow wf = Workflow.getObjectWorkflow(item);
                    int tabNumber = ContentItemPage.AUTHORING_TAB;
                    String sectionPath = item.getContentSection().getPath();

                    if ( wf != null ) {
                        User user = Web.getContext().getUser();
                        Engine engine = Engine.getInstance();
                        Iterator i = engine.getEnabledTasks(user, wf.getID()).iterator();
                        if (i.hasNext()) {
                            CMSTask task = (CMSTask) i.next();
                            BigDecimal taskType = task.getTaskType();

                            if ( taskType.equals(CMSTask.DEPLOY) ) {
                                tabNumber = ContentItemPage.PUBLISHING_TAB;
                            } else {
                                // see if item is locked; if not, lock
                                if ( !task.isLocked() ) {
                                    task.lock(user);
                                }
                            }
                        }
                    }
			
                    String redirectURL = Web.getConfig().getDispatcherServletPath() + sectionPath + "/admin/item.jsp?item_id=" + itemID + "&set_tab=" + tabNumber;
                    throw new RedirectSignal(redirectURL,true);
                } catch (DataObjectNotFoundException ex) {
                    throw new ServletException("Unknown content ID" + itemID);
                }
            } else if ( SORT_ACTION_UP.equals(key) || SORT_ACTION_DOWN.equals(key)) {
                state.setValue(m_sortTypeParam, value);
                if (SORT_ACTION_DOWN.equals(key)) {
                    state.setValue(m_sortDirectionParam, SORT_ACTION_DOWN);
                } else {
                    state.setValue(m_sortDirectionParam, SORT_ACTION_UP);
                }
            } else {
                throw new ServletException("Unknown control event: " + key);
            }
        }
    }    

    private static Filter getTaskFilter(String taskType, Party party, FilterFactory factory) {
        PrivilegeDescriptor privilege;
        String queryName;
        String queryType;
        OID partyOID = party.getOID();
        if ( taskType.equals("Deploy") ) {
            queryType = "deploy";
            privilege = new PrivilegeDescriptor(SecurityConstants.CMS_PUBLISH);
        } else {
            queryType = "edit";
            privilege = new PrivilegeDescriptor(SecurityConstants.CMS_EDIT_ITEM);
        }

	return PermissionService.getFilterQuery(factory,"itemID",privilege,partyOID);
    }
}

