/*
 * $Id: ProjectViewForm.java,v 1.1 2006/10/04 03:14:46 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: ProjectViewForm.java,v $
 * Revision 1.1  2006/10/04 03:14:46  marbobo
 * + Vollständige Unterstützung für Templates implementiert
 * + Alles von Virtoweb auf ProCoBa umgestellt
 *
 * Revision 1.36  2006/07/26 11:38:51  marbobo
 * + Document-Lock eingebaut
 *
 * Revision 1.35  2006/07/10 11:24:58  marbobo
 * + Bugfix
 *
 * Revision 1.34  2006/07/05 21:00:08  marbobo
 * + History-Funktionalität für Projekt- und Funktionssicht-Tabs implementiert
 *
 * Revision 1.33  2006/07/03 23:46:31  marbobo
 * + Neu implementierung der Projekt- und Funktionssicht-Tabs
 *
 * Revision 1.32  2006/02/27 16:16:16  marbobo
 * + Systemsichten hinzugefügt
 * + SysLinks angepasst
 * + Benutzer können falls gewünscht Dokumentqueries anlegen
 *
 * Revision 1.31  2005/09/15 13:42:57  marbobo
 * + Sprachabhängige Sortierung implementiert
 *
 * Revision 1.30  2005/09/07 13:51:01  marbobo
 * + Sortierung nach Erstellungsdatum implementiert
 *
 * Revision 1.29  2005/03/21 20:28:08  marbobo
 * + DocSize auf Type Long umgestellt
 *
 * Revision 1.28  2005/02/10 12:29:00  marbobo
 * + Verwendung der Unicode-Konformen Filtermethode
 *
 * Revision 1.27  2004/11/09 14:35:38  marbobo
 * + Umstellung von authorId auf publisherId
 * + Hinzufügen von AuthorName für Dokumente
 * + Nötwendige Änderungen betreffend AuthorName und PublisherId
 *
 * Revision 1.26  2004/10/31 03:04:57  marbobo
 * + Verbesserungen und Bugfixes
 *
 * Revision 1.25  2004/08/20 21:54:15  marbobo
 * + Messages Löschen per Auswahl ( geändert )
 *
 * Revision 1.24  2004/07/20 15:22:49  jonyp
 * added some functionality to display dialog in mainframe or popup-window
 *
 * Revision 1.23  2004/07/20 09:00:51  jonyp
 * added copyright info + cvs log
 *
 *
 */

package vkc.procoba.project;

import java.text.CollationKey;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMapping;

import vkc.db.entities.VKCCatProjectStep;
import vkc.db.entities.VKCCategory;
import vkc.db.entities.VKCDocument;
import vkc.db.entities.VKCSubCategory;
import vkc.db.serializer.VKCCategorySerializer;
import vkc.db.serializer.VKCDocumentStatusSerializer;
import vkc.db.serializer.VKCUserSerializer;
import vkc.exception.DBException;
import vkc.misc.VKCLogManager;
import vkc.procoba.project.entities.VKCProject;
import vkc.util.DateUtils;
import vkc.util.DocumentUtils;
import vkc.util.ProjectUtils;
import vkc.util.StringUtils;
import vkc.util.VKCCategoryPathNode;
import vkc.util.VKCStringUtils;
import vkc.util.sort.ProjectMessageSortFactory;
import vkc.view.InputFieldConstraints;
import vkc.view.PageId;
import vkc.view.WebShare;
import vkc.view.bean.NewProjectStepInfo;
import vkc.view.bean.UserInfo;
import vkc.view.form.BasicActionForm;

public class ProjectViewForm extends BasicActionForm {
	public static final Integer VIEW_MODE_FOLDER       	= new Integer(0);
	public static final Integer VIEW_MODE_MESSAGES     	= new Integer(2);
	public static final Integer VIEW_MODE_CONTACTS     	= new Integer(3);
	public static final Integer VIEW_MODE_NEW_MESSAGE  	= new Integer(4);
	public static final Integer VIEW_MODE_EDIT_STEPS   	= new Integer(5);

	public final static int CATEGORY_SORT_NAME_UP   		= 1;
	public final static int CATEGORY_SORT_NAME_DOWN 		= 2;

	public final static int DOCUMENT_SORT_PUBLISHING_DATE_UP   	= 1;
	public final static int DOCUMENT_SORT_PUBLISHING_DATE_DOWN 	= 2;

	public final static int DOCUMENT_SORT_TITLE_UP  			= 3;
	public final static int DOCUMENT_SORT_TITLE_DOWN			= 4;

	public final static int DOCUMENT_SORT_AUTHOR_UP 			= 5;
	public final static int DOCUMENT_SORT_AUTHOR_DOWN			= 6;
	
	public final static int DOCUMENT_SORT_SIZE_UP  				= 7;
	public final static int DOCUMENT_SORT_SIZE_DOWN 			= 8;

	public final static int DOCUMENT_SORT_TYPE_UP  				= 9;
	public final static int DOCUMENT_SORT_TYPE_DOWN 			= 10;

	public final static int DOCUMENT_SORT_PUBLISHER_UP 			= 13;
	public final static int DOCUMENT_SORT_PUBLISHER_DOWN		= 14;

	public final static int DOCUMENT_SORT_CREATION_DATE_UP   	= 15;
	public final static int DOCUMENT_SORT_CREATION_DATE_DOWN 	= 16;

	protected boolean reloadTab    		= false;

	protected Integer categorySortMode 	= new Integer(CATEGORY_SORT_NAME_UP);
	protected Integer documentSortMode 	= new Integer(DOCUMENT_SORT_PUBLISHING_DATE_DOWN);
	protected Integer selectedId   		= null;
	protected Integer projectId 		= null;
	protected Integer subfolderId 		= null;
	protected Integer uniqueId 			= new Integer(0);
	protected Integer viewMode     		= VIEW_MODE_FOLDER;
	
	protected Integer[] changedStepProcessedIds 	= new Integer[0];
	protected Integer[] changedStepCheckedIds 		= new Integer[0];
	protected Integer[] selectedIds 				= new Integer[0];
	protected Integer[] selectedStepProcessedIds 	= new Integer[0];
	protected Integer[] selectedStepEnabledIds 		= new Integer[0];
	protected Integer[] selectedStepCheckedIds 		= new Integer[0];
	protected Integer[] selectedStepDeleteIds 		= new Integer[0];
	protected Integer[]	showDocumentDetails 		= new Integer[0];

	protected List accessibleSubCategories	= null;
	protected List documentStati 			= new ArrayList();
	protected List leaders					= new ArrayList();
    protected List members  				= new ArrayList();
	protected List projectStepInfos 		= new ArrayList();
	protected List virtualDocuments 		= null;

	protected Map dynaValues = new HashMap();

	protected String newMessage = "";
	
	protected VKCCategory subfolder = null;

	protected VKCProject project = null;
	
	public void reset(ActionMapping mapping, HttpServletRequest request) {
		super.reset(mapping, request);

		reloadTab    		= false;

		categorySortMode 	= new Integer(CATEGORY_SORT_NAME_UP);
		documentSortMode 	= new Integer(DOCUMENT_SORT_PUBLISHING_DATE_DOWN);
		selectedId   		= null;
		projectId 			= null;
		subfolderId 		= null;
		uniqueId 			= new Integer(0);
		viewMode     		= VIEW_MODE_FOLDER;
		
		changedStepProcessedIds 	= new Integer[0];
		changedStepCheckedIds 		= new Integer[0];
		selectedIds 				= new Integer[0];
		selectedStepProcessedIds 	= new Integer[0];
		selectedStepEnabledIds 		= new Integer[0];
		selectedStepCheckedIds 		= new Integer[0];
		selectedStepDeleteIds 		= new Integer[0];
		showDocumentDetails 		= new Integer[0];

		accessibleSubCategories	= null;
		documentStati 			= new ArrayList();
		leaders					= new ArrayList();
	    members  				= new ArrayList();
		projectStepInfos 		= new ArrayList();
		virtualDocuments 		= null;

		dynaValues = new HashMap();

		newMessage = "";
		
		subfolder = null;

		project = null;
	}

	public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
		ActionErrors errors = new ActionErrors();

		try {
			if (request.getParameter("action.save.new.message") != null) {
				if (isEmpty(getNewMessage())) {
					errors.add("newMessage", new ActionError("project.error.message.empty"));
				} else if (!isLengthValid(getNewMessage(), "project.message")) {
					errors.add("newMessage", new ActionError("project.error.message.length" , InputFieldConstraints.getMaxLength("project.message")));
				}
			}

			if (request.getParameter("action.save.edit.steps") != null && getUserIsLeader()) {
				List selectedProcessedIds = new ArrayList(Arrays.asList(getSelectedStepProcessedIds()));
				List selectedCheckedIds = new ArrayList(Arrays.asList(getSelectedStepCheckedIds()));

				for (int i = 0; i < getProjectSteps().size(); i++) {
					VKCCatProjectStep step = (VKCCatProjectStep)getProjectSteps().get(i);
					String activityId = "activityId_" + step.getCatProjStepId().toString();
					String activity = (String) getDynaValue(activityId);
					String startdateId = "startdateId_" + step.getCatProjStepId().toString();
					String startdate = (String) getDynaValue(startdateId);
					String enddateId = "enddateId_" + step.getCatProjStepId().toString();
					String enddate = (String) getDynaValue(enddateId);

					Date sd = DateUtils.parseDate(startdate);
					Date ed = DateUtils.parseDate(enddate);
					
					if (isEmpty(activity)) {
						errors.add(activityId, new ActionError("project.error.edit.steps.empty", step.getStep().toString()));
					} else if (!isLengthValid(activity, "project.steps")) {
						errors.add(activityId, new ActionError("project.error.edit.steps.length" , step.getStep().toString(), InputFieldConstraints.getMaxLength("project.steps")));
					}
					
					if (isEmpty(startdate) || sd == null) {
						errors.add(startdateId, new ActionError("project.error.edit.steps.startDate", step.getStep().toString()));
					}
					
					if (isEmpty(enddate) || ed == null) {
						errors.add(enddateId, new ActionError("project.error.edit.steps.endDate", step.getStep().toString()));
					}
					
					if (sd != null && ed != null && ed.before(sd)) {
						errors.add("rangeId_" + step.getCatProjStepId().toString(), new ActionError("project.error.edit.steps.date.range", step.getStep().toString()));
					}
					
					if (selectedProcessedIds.contains(step.getCatProjStepId()) && selectedCheckedIds.contains(step.getCatProjStepId())) {
						if (step.getProcessorId().intValue() > 0 && step.getCheckerId().intValue() > 0) {
							if (step.getProcessorId().equals(step.getCheckerId())) {
								errors.add("sameProcessorCheckerId_" + step.getCatProjStepId().toString(), new ActionError("project.error.edit.steps.sameprocessorchecker", step.getStep().toString()));
							}
						} else if (step.getProcessorId().intValue() <= 0 && step.getCheckerId().intValue() > 0) {
							if (step.getCheckerId().equals(getUser().getUserId())) {
								errors.add("sameProcessorCheckerId_" + step.getCatProjStepId().toString(), new ActionError("project.error.edit.steps.sameprocessorchecker", step.getStep().toString()));
							}
						} else if (step.getProcessorId().intValue() > 0 && step.getCheckerId().intValue() <= 0) {
							if (step.getProcessorId().equals(getUser().getUserId())) {
								errors.add("sameProcessorCheckerId_" + step.getCatProjStepId().toString(), new ActionError("project.error.edit.steps.sameprocessorchecker", step.getStep().toString()));
							}
						} else {
							errors.add("sameProcessorCheckerId_" + step.getCatProjStepId().toString(), new ActionError("project.error.edit.steps.sameprocessorchecker", step.getStep().toString()));
						}
					}
				}
			}
		} catch (Exception e) {
			VKCLogManager.errorLog(getClass().getName(), "1", "", e);
			errors.add("error", new ActionError("error.general", e.getMessage()));
		}
		
		return errors;
	}
	
	public Integer getSelectedId() {
		return selectedId;
	}

	public Integer[] getSelectedIds() {
		return selectedIds;
	}

	public void setSelectedId(Integer i) {
		selectedId = i;
	}

	public void setSelectedIds(Integer[] integers) {
		selectedIds = integers;
	}

	public Integer getViewMode() {
		return viewMode;
	}

	public void setViewMode(Integer i) {
		viewMode = i == null ? VIEW_MODE_FOLDER : i;
	}

	public String getNewMessage() {
		return newMessage;
	}

	public void setNewMessage(String s) {
		newMessage = StringUtils.normalize(s);
	}
	
	public List getMembers() throws DBException {
		if (members.size() == 0) {
			members = getProject().getMembers();
			members.removeAll(getProject().getLeaders());
		}
		
		return members;
	}

	public List getLeaders() throws DBException {
		if (leaders.size() == 0) {
			leaders = getProject().getLeaders();
		}
		
		return leaders;
	}
	
	public List getCurrentProjectPath() throws DBException {
		if (getSubfolder() != null) {
			List cpp = getSubfolder().getAbsPathDescr().getPathNodes();
			
			for (Iterator iter = cpp.iterator(); iter.hasNext();) {
				VKCCategoryPathNode node = (VKCCategoryPathNode)iter.next();
				
				if (node.getPathId().equals(getProjectId())) {
					break;
				}

				iter.remove();
			}
			
			return cpp;
		}

		return new ArrayList();
	}
	
	public String getExternalContacts() throws DBException {
		return VKCStringUtils.filterUnicodeChars(getProject().getExternalContacts());
	}

	public String getProjectFolderViewLink() {
		return "/projectView.do" +
			   "?viewMode=" + VIEW_MODE_FOLDER +
		       "&projectId=" + getProjectId();
	}

	public String getProjectMessagesViewLink() {
		return "/projectView.do" + 
			   "?viewMode=" + VIEW_MODE_MESSAGES + 
               "&projectId=" + getProjectId() + 
               "&subfolderId=" + getSubfolderId();
	}

	public String getProjectContactsViewLink() {
		return "/projectView.do" + 
			   "?viewMode=" + VIEW_MODE_CONTACTS + 
               "&projectId=" + getProjectId() + 
               "&subfolderId=" + getSubfolderId();
	}

	public String getProjectEditStepsViewLink() {
		return "/projectView.do" + 
			   "?viewMode=" + VIEW_MODE_EDIT_STEPS + 
			   "&projectId=" + getProjectId() + 
			   "&subfolderId=" + getSubfolderId();
	}

	public String getNewDocumentLink() {
		Integer subTargetId = null;

		if (getSubfolderId() == null) {
			subTargetId = getProjectId();
		} else {
			subTargetId = getSubfolderId();
		}

		return "/newDocument.do" + 
			   "?sourcePageId=" + PageId.PROJECT_VIEW +
			   "&targetId=" + getProjectId() + 
			   "&subTargetId=" + subTargetId + 
			   "&categoryId=" + getSubfolderId();
	}

	public String getNewDocumentVersionLink() {
		Integer subTargetId = null;

		if (getSubfolderId() == null) {
			subTargetId = getProjectId();
		} else {
			subTargetId = getSubfolderId();
		}

		return "/newDocumentVersion.do" + 
			   "?sourcePageId=" + PageId.PROJECT_VIEW +
			   "&targetId=" + getProjectId() + 
			   "&subTargetId=" + subTargetId;
	}

	public String getShowDocumentVersionsLink() {
		Integer subTargetId = null;

		if (getSubfolderId() == null) {
			subTargetId = getProjectId();
		} else {
			subTargetId = getSubfolderId();
		}

		return "/showDocumentVersions.do" + 
			   "?sourcePageId=" + PageId.PROJECT_VIEW +
			   "&targetId=" + getProjectId() + 
			   "&subTargetId=" + subTargetId;
	}


	public String getDeleteCategoryLink() {
		return "/projectView.do" + 
			   "?viewMode=" + VIEW_MODE_FOLDER + 
		       "&projectId=" + getProjectId() +
		       "&subfolderId=" + getSubfolderId() + 
		       "&action.delete.subfolder=true";			
	}

	public String getCreateCategoryLink() throws DBException {
		Integer subTargetId = null;

		if (getSubfolderId() == null) {
			subTargetId = getProjectId();
		} else {
			subTargetId = getSubfolderId();
		}

		return "/createCategory.do" + 
			   "?sourcePageId=" + PageId.PROJECT_VIEW +
			   "&targetId=" + getProjectId() + 
			   "&subTargetId=" + subTargetId + 
			   "&parentCategoryId=" + getSubfolder().getCategoryId() +
			   "&validate=false" +
			   "&copyParentAcl=true";
	}

	public String getCreateProjectLink() throws DBException {
		Integer subTargetId = null;

		if (getSubfolderId() == null) {
			subTargetId = getProjectId();
		} else {
			subTargetId = getSubfolderId();
		}

		return "/createProject.do" + 
			   "?sourcePageId=" + PageId.PROJECT_VIEW +
			   "&targetId=" + getProjectId() + 
			   "&subTargetId=" + subTargetId + 
			   "&parentCategoryId=" + getSubfolder().getCategoryId() +
			   "&validate=false" +
			   "&copyParentAcl=true";
	}

	public String getEditCategoryLink() throws DBException {
		Integer subTargetId = null;

		if (getSubfolderId() == null) {
			subTargetId = getProjectId();
		} else {
			subTargetId = getSubfolderId();
		}

		return "/editCategory.do" + 
			   "?sourcePageId=" + PageId.PROJECT_VIEW +
			   "&targetId=" + getProjectId() + 
			   "&subTargetId=" + subTargetId + 
			   "&categoryId=" + getSubfolder().getCategoryId() +
			   "&validate=false";
	}
	
	public String getEditAclLink() throws DBException {
		Integer subTargetId = null;

		if (getSubfolderId() == null) {
			subTargetId = getProjectId();
		} else {
			subTargetId = getSubfolderId();
		}

		return "/editCategoryAcl.do" + 
			   "?sourcePageId=" + PageId.PROJECT_VIEW +
			   "&targetId=" + getProjectId() + 
			   "&subTargetId=" + subTargetId + 
			   "&categoryId=" + getSubfolder().getCategoryId() +
			   "&init=true";
	}

	public String getDisplayAclLink() throws DBException {
		Integer subTargetId = null;

		if (getSubfolderId() == null) {
			subTargetId = getProjectId();
		} else {
			subTargetId = getSubfolderId();
		}

		return "/displayAcl.do" + 
			   "?sourcePageId=" + PageId.PROJECT_VIEW +
			   "&targetId=" + getProjectId() + 
			   "&subTargetId=" + subTargetId + 
			   "&categoryId=" + getSubfolder().getCategoryId() +
			   "&init=true&ownWindow=false";
	}

	public String getEditDocumentLink() throws DBException {
		Integer subTargetId = null;

		if (getSubfolderId() == null) {
			subTargetId = getProjectId();
		} else {
			subTargetId = getSubfolderId();
		}

		return "/editDocument.do" + 
			   "?sourcePageId=" + PageId.PROJECT_VIEW +
			   "&targetId=" + getProjectId() + 
			   "&subTargetId=" + subTargetId + 
			   "&categoryId=" + getSubfolder().getCategoryId() +
			   "&init=true";
	}

	public Integer[] getSelectedStepProcessedIds() {
		return selectedStepProcessedIds;
	}

	public void setSelectedStepProcessedIds(Integer[] integers) {
		selectedStepProcessedIds = integers;
	}

	public Integer[] getSelectedStepEnabledIds() {
		return selectedStepEnabledIds;
	}

	public void setSelectedStepEnabledIds(Integer[] integers) {
		selectedStepEnabledIds = integers;
	}

	public Integer[] getSelectedStepCheckedIds() {
		return selectedStepCheckedIds;
	}

	public void setSelectedStepCheckedIds(Integer[] integers) {
		selectedStepCheckedIds = integers;
	}

	public Integer[] getChangedStepProcessedIds() {
		return changedStepProcessedIds;
	}

	public void setChangedStepProcessedIds(Integer[] integers) {
		changedStepProcessedIds = integers;
	}

	public Integer[] getChangedStepCheckedIds() {
		return changedStepCheckedIds;
	}

	public void setChangedStepCheckedIds(Integer[] integers) {
		changedStepCheckedIds = integers;
	}
    
    public void setDynaValue(String name, Object value) {
        dynaValues.put(name, value);
    }

    public Object getDynaValue(String name) {
        return dynaValues.get(name);
    }

	public Object removeDynaValue(String name) {
		return dynaValues.remove(name);
	}

	public Iterator getDynaKeys(){
		return dynaValues.keySet().iterator();
	}

	public void clearDynaValues(){
		dynaValues.clear();
	}
	
	public int getActiveProjectStepsSize() throws DBException {
		int count = 0;
		
		for (int i = 0; i < getProject().getProjectSteps().size(); i++) {
			VKCCatProjectStep step = (VKCCatProjectStep)getProject().getProjectSteps().get(i);
			
			if (step.isEnabled()) {
				count++;
			}
		}
		
		return count;
	}

	public int getActiveProjectStepsRunningSize() throws DBException {
		int count = 0;
		
		for (int i = 0; i < getProject().getProjectSteps().size(); i++) {
			VKCCatProjectStep step = (VKCCatProjectStep)getProject().getProjectSteps().get(i);
			
			if (step.isStepRunning()) {
				count++;
			}
		}
		
		return count;
	}

	public int getActiveProjectStepsProcessedSize() throws DBException {
		int count = 0;
		
		for (int i = 0; i < getProject().getProjectSteps().size(); i++) {
			VKCCatProjectStep step = (VKCCatProjectStep)getProject().getProjectSteps().get(i);
			
			if (step.isProcessed() && step.isEnabled()) {
				count++;
			}
		}
		
		return count;
	}

	public int getActiveProjectStepsCheckedSize() throws DBException {
		int count = 0;
		
		for (int i = 0; i < getProject().getProjectSteps().size(); i++) {
			VKCCatProjectStep step = (VKCCatProjectStep)getProject().getProjectSteps().get(i);
			
			if (step.isStepChecked()) {
				count++;
			}
		}
		
		return count;
	}
	
	public UserInfo getUserInfo() throws DBException {
		return VKCUserSerializer.retrieveUserInfo(getUser().getUserId());
	}
	
	public String getCurrentTimeString() {
		return DateUtils.getDD_MM_YYYY(new Date(System.currentTimeMillis()));
	}
	
	public boolean getChangedProcessId(int index) {
		if (getChangedStepProcessedIds().length == 0) {
			return false;
		}

		List ids = Arrays.asList(getChangedStepProcessedIds());
		
		return ids.contains(new Integer(index));
	}

	public boolean getSelectedProcessId(int index) {
		if (getSelectedStepProcessedIds().length == 0) {
			return false;
		} 

		List ids = Arrays.asList(getSelectedStepProcessedIds());
		
		return ids.contains(new Integer(index));
	}

	public boolean getChangedCheckerId(int index) {
		if (getChangedStepCheckedIds().length == 0) {
			return false;
		}

		List ids = Arrays.asList(getChangedStepCheckedIds());
		
		return ids.contains(new Integer(index));
	}

	public boolean getSelectedCheckerId(int index) {
		if (getSelectedStepCheckedIds().length == 0) {
			return false;
		}

		List ids = Arrays.asList(getSelectedStepCheckedIds());
		
		return ids.contains(new Integer(index));
	}
	
	public Integer getProjectId() {
		return projectId;
	}

	public void setProjectId(Integer i) {
		projectId = i;
		project = null;
	}

	public VKCProject getProject() throws DBException {
		if (project == null) {
			VKCCategory category = VKCCategorySerializer.retrieveCategory(getProjectId());

			if (category != null) {
				if (category instanceof VKCProject) {
					project = (VKCProject)category;
					
					if (project.getFlag().equals(VKCCategory.FLAG_DELETED)) {
						project = null;
					}
				}
			}
		}

		return project;
	}
	
	public List getProjectMessages() throws DBException {
		if (getUser() == null || getProject() == null) {
			return new ArrayList();
		}

		List messages = ProjectUtils.retrieveProjectMessages(getProjectId(), getUser().getUserId());
		ProjectMessageSortFactory.sort(messages, ProjectMessageSortFactory.SORT_BY_DATE_DOWN);
		
		return messages;
	}

	public List getMostRecentMessages() throws DBException {
		List messages = getProjectMessages(); 

		if (messages.size() > 5) {
			return getProjectMessages().subList(0, 5);
		}

		return messages;
	}

	public List getProjectSteps() {
		List projectSteps = new ArrayList();
		List projectStepInfos = getProjectStepInfos();
		
		for (int i = 0; i < projectStepInfos.size(); i++) {
			NewProjectStepInfo step = (NewProjectStepInfo)projectStepInfos.get(i);
			projectSteps.add(step.toVKCCatProjectStep());
		}
		
		Comparator c = new Comparator() {
			public int compare(Object o1, Object o2) {
				VKCCatProjectStep s1 = (VKCCatProjectStep)o1;
				VKCCatProjectStep s2 = (VKCCatProjectStep)o2;
				
				return (s1.getStep().intValue() > s2.getStep().intValue()) ? 1 : 0;
			}
		};
		
		Collections.sort(projectSteps, c);

		return projectSteps;
	}
	
	public Integer getProjectStepsSize() throws DBException {
		return new Integer(getProject().getProjectSteps().size());
	}
	
	public void reloadProject() {
		project = null;
	}

	public Integer getSubfolderId() {
		return subfolderId;
	}

	public void setSubfolderId(Integer i) {
		subfolderId = i;
		subfolder = null;
	}

	public VKCCategory getSubfolder() throws DBException {
		if (subfolder == null) {
			subfolder = VKCCategorySerializer.retrieveCategory(getSubfolderId());
		}

		return subfolder;
	}

	public void reloadSubfolder() {
		subfolder = null;
	}

	public List getAccessibleSubCategories() throws DBException {
		if (accessibleSubCategories == null) {
			if (getSubfolder() == null) {
				accessibleSubCategories = new ArrayList();
			} else {
				accessibleSubCategories = getSubfolder().getAccessibleSubCategories(getUser());
				categorySort(accessibleSubCategories, getCategorySortMode());
			}
		}
		
		return accessibleSubCategories;
	}

	public boolean getUserIsLeader() throws DBException {
		if (getProject() != null && getUser() != null) {
			return getUser().getHasAdminPrivileges() || getProject().getLeaders().contains(new UserInfo(getUser().getUserId()));
		}
		
		return false;
	}

	public boolean getUserIsMember() throws DBException {
		if (getProject() != null && getUser() != null) {
			return getUser().getHasAdminPrivileges() || getProject().getMembers().contains(new UserInfo(getUser().getUserId()));
		}

		return false;
	}

	public boolean getUserHasWritePermission() throws DBException {
		if (getProject() != null && getUser() != null) {
			if (getUserIsLeader()) {
				return true;
			}

			if (getUser().getHasAdminPrivileges()) {
				return true;
			}

			return VKCUserSerializer.retrieveUserInfos(getProject(), "w").contains(new UserInfo(getUser().getUserId()));
		}

		return false;
	}

	public String getTemplatePath() {
		if (getUser() == null) {
			return "/templates/" + WebShare.DEFAULT_TEMPLATE;
		}

		return "/templates/" + getUser().getTemplate().getName();
	}
	
	public List getDocumentStati() {
		if (documentStati == null || documentStati.size() == 0) {
			documentStati = VKCDocumentStatusSerializer.getDocumentStati();
		}

		return documentStati;
	}
	
	public List getVirtualDocuments() throws DBException {
        if (virtualDocuments == null) {
			if (getSubfolder() != null && getUser() != null) {
                virtualDocuments = DocumentUtils.getVirtualDocuments(getSubfolderId(), getUser());
				documentSort(virtualDocuments, getDocumentSortMode());
				
				return virtualDocuments; 
			}

			return new ArrayList();
        }
        
        return virtualDocuments;
	}

	public Integer getUniqueId() {
		return uniqueId;
	}

	public void setUniqueId(Integer i) {
		uniqueId = i;
	}

	public List getProjectStepInfos() {
		return projectStepInfos;
	}

	public NewProjectStepInfo getProjectStepInfo(int index) {
		if (projectStepInfos.size() > 0 && projectStepInfos.size() > index) {
			if (projectStepInfos.get(index) == null) {
				NewProjectStepInfo step = new NewProjectStepInfo();
				projectStepInfos.set(index, step);
			}

			return (NewProjectStepInfo)projectStepInfos.get(index);
		}
		
		NewProjectStepInfo step = new NewProjectStepInfo();

		if (projectStepInfos.size() == 0) {
			ArrayList list = new ArrayList(index + 1);
			
			for (int i = 0; i < index + 1; i++) {
				list.add(null);
			}
			
			projectStepInfos = list;
		} else {
			ArrayList list = new ArrayList(index + 1);
			
			for (int i = 0; i < index + 1; i++) {
				list.add(null);
			}
			
			for (int i = 0; i < projectStepInfos.size(); i++) {
				if (projectStepInfos.get(i) != null) {
					list.set(i, projectStepInfos.get(i));
				}
			}
			
			projectStepInfos = list;
		}

		projectStepInfos.set(index, step);

		return step;
	}

	public void setProjectStepInfo(int index, NewProjectStepInfo step) {
		projectStepInfos.add(index, step);
	}

	public Integer[] getSelectedStepDeleteIds() {
		return selectedStepDeleteIds;
	}

	public void setSelectedStepDeleteIds(Integer[] integers) {
		selectedStepDeleteIds = integers;
	}

	public Integer[] getShowDocumentDetails() {
		return showDocumentDetails;
	}

	public void setShowDocumentDetails(Integer[] integers) {
		showDocumentDetails = integers;
	}

	public boolean getShowDocDetails(int i) {
		List ids = Arrays.asList(getShowDocumentDetails());
		
		return ids.contains(new Integer(i));
	}
	
	private void categorySort(List categories, Integer sortMode) {
		int mode = sortMode.intValue();

		Comparator c = null;
		final Collator collator = Collator.getInstance(getUser().getLanguage().getLocale());

		if (mode == CATEGORY_SORT_NAME_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCSubCategory s1 = (VKCSubCategory)o1;
					VKCSubCategory s2 = (VKCSubCategory)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(s1.getName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(s2.getName()));
                	
                	return key1.compareTo(key2);
				}
			};
		} else if (mode == CATEGORY_SORT_NAME_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCSubCategory s1 = (VKCSubCategory)o1;
					VKCSubCategory s2 = (VKCSubCategory)o2;

                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(s1.getName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(s2.getName()));
                	
                	return key2.compareTo(key1);
				}
			};
		}
		
		Collections.sort(categories, c);		
	}

	private void documentSort(List documents, Integer sortMode) {
		int mode = sortMode.intValue();

		Comparator c = null;
		final Collator collator = Collator.getInstance(getUser().getLanguage().getLocale());

		if (mode == DOCUMENT_SORT_PUBLISHING_DATE_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
					return d1.getPublished().after(d2.getPublished()) ? 1 : 0;
				}
			};
		} else if (mode == DOCUMENT_SORT_PUBLISHING_DATE_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
					return d1.getPublished().before(d2.getPublished()) ? 1 : 0;
				}
			};
		} else if (mode == DOCUMENT_SORT_CREATION_DATE_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
					if (d1.getCreationDate() != null && d2.getCreationDate() != null) {
						return d1.getCreationDate().after(d2.getCreationDate()) ? 1 : 0;
					}
					
					return -1;
				}
			};
		} else if (mode == DOCUMENT_SORT_CREATION_DATE_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
					if (d1.getCreationDate() != null && d2.getCreationDate() != null) {
						return d1.getCreationDate().before(d2.getCreationDate()) ? 1 : 0;
					}
					
					return -1;
				}
			};
		} else if (mode == DOCUMENT_SORT_TITLE_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getTitle()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getTitle()));
                	
                	return key1.compareTo(key2);
				}
			};
		} else if (mode == DOCUMENT_SORT_TITLE_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getTitle()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getTitle()));
                	
                	return key2.compareTo(key1);
				}
			};
		} else if (mode == DOCUMENT_SORT_AUTHOR_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getAuthorName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getAuthorName()));
                	
                	return key1.compareTo(key2);
				}
			};
		} else if (mode == DOCUMENT_SORT_AUTHOR_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getAuthorName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getAuthorName()));
                	
                	return key2.compareTo(key1);
				}
			};
		} else if (mode == DOCUMENT_SORT_PUBLISHER_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getPublisherName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getPublisherName()));
                	
                	return key1.compareTo(key2);
				}
			};
		} else if (mode == DOCUMENT_SORT_PUBLISHER_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getPublisherName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getPublisherName()));
                	
                	return key2.compareTo(key1);
				}
			};
		} else if (mode == DOCUMENT_SORT_SIZE_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
					return d1.getDocSize().longValue() > d2.getDocSize().longValue() ? 1 : 0;
				}
			};
		} else if (mode == DOCUMENT_SORT_SIZE_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
					return d1.getDocSize().longValue() < d2.getDocSize().longValue() ? 1 : 0;
				}
			};
		} else if (mode == DOCUMENT_SORT_TYPE_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getDocumentType().getExtension()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getDocumentType().getExtension()));
                	
                	return key1.compareTo(key2);
				}
			};
		} else if (mode == DOCUMENT_SORT_TYPE_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getDocumentType().getExtension()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getDocumentType().getExtension()));
                	
                	return key2.compareTo(key1);
				}
			};
		}
		
		Collections.sort(documents, c);		
	}

	public List getDocuments() throws DBException {
		List documents = getSubfolder().getDocuments();
		documentSort(documents, getDocumentSortMode());
		
		return documents;
	}

	public boolean getHasDocuments() throws DBException {
		return !getSubfolder().getDocuments().isEmpty() || !getVirtualDocuments().isEmpty();
	}
	
	public Integer getCategorySortMode() {
		return categorySortMode;
	}

	public void setCategorySortMode(Integer i) {
		categorySortMode = i;
	}
	
	public Integer getDocumentSortMode() {
		return documentSortMode;
	}

	public void setDocumentSortMode(Integer i) {
		documentSortMode = i;
	}
	
	public boolean isProjectRoot() {
		if (getProjectId().equals(getSubfolderId())) {
			return true;			
		}
		
		return false;
	}

	public boolean getReloadTab() {
        return reloadTab;
    }
    
	public void setReloadTab(boolean reloadTab1) {
        reloadTab = reloadTab1;
    }
    
    public String getLockUserInfo(String documentId) {
        String lockUser = vkc.webdav.WebDavServlet.getLockUserName(new Integer(documentId));
        
        if (lockUser != null) {
            return getResources().getMessage(getLocale(), "vkc.string.lockUserInfo", lockUser);
        }
        
        return "";
    }
}