/*
 * $Id: UserProfileForm.java,v 1.39 2008/02/13 07:45:02 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: UserProfileForm.java,v $
 * Revision 1.39  2008/02/13 07:45:02  marbobo
 * + Bugfix
 *
 * Revision 1.38  2008/02/12 09:33:59  korowa
 * Eine Möglichkeit für den Benutzer hinzugefügt die Emailsart auszuwählen(HTML oder Plaintext)
 *
 * Revision 1.37  2007/10/30 13:32:00  marbobo
 * + removed unnecessary statements
 *
 * Revision 1.36  2007/09/05 08:28:31  marbobo
 * + Benutzer mit Adminrechten können dynamische Attributte bearbeiten
 *
 * Revision 1.35  2007/08/28 12:16:11  korowa
 * Export- und Importfunktionen hinzugefügt
 *
 * Revision 1.34  2007/08/09 14:38:57  marbobo
 * - 2 falsch zugeordnete LDAP- Parameter entfernt
 * + Löschen und Aktivieren von Lizenzen hinzugefügt
 *
 * Revision 1.33  2007/02/01 14:32:23  korowa
 * Zwei Felder zu SystemParameter hinzugefügt die einem Administrator erlauben das Anlegen von neuen Benutzer oder das Ändern der Passwörter zu regeln.
 *
 * Revision 1.32  2006/09/17 21:19:02  marbobo
 * + virtowebView-Einträge und Methoden wegen Migration entfernt (nicht mehr nötig)
 *
 * Revision 1.31  2006/09/17 18:52:02  marbobo
 * + Bei Vergleichen immer die Statischenvariablen verwenden statt fester Werte
 *
 * Revision 1.30  2006/09/14 07:37:13  korowa
 * *** empty log message ***
 *
 * Revision 1.29  2006/09/01 07:32:05  korowa
 * Feld name in einem dynamischen Attribut für User darf vom User nicht verändert werden
 *
 * Revision 1.28  2006/08/31 12:25:47  korowa
 * Dynamische Attribute für Users eingefügt
 *
 * Revision 1.27  2006/05/18 22:50:02  marbobo
 * + Beim Menusprache-Wechsel werden jetzt auch alle 3 Frames aktualisiert
 *
 * Revision 1.26  2006/05/12 08:09:12  korowa
 * +showTree zum Userprofil hinzugefügt. Dieser parameter regelt die Anzeige des Explorerfensters beim VKC-Anmeldung. Lässt sich im Userprofil umschalten.
 *
 * Revision 1.25  2006/02/27 16:15:54  marbobo
 * + Systemsichten hinzugefügt
 * + SysLinks angepasst
 * + Benutzer können falls gewünscht Dokumentqueries anlegen
 *
 * Revision 1.24  2005/09/15 13:42:12  marbobo
 * + Sprachabhängige Sortierung implementiert
 *
 * Revision 1.23  2005/09/07 22:05:18  marbobo
 * + Sortierung in der Bestseller-Liste standardmäßig auf Absteigend nach Zugriffen gesetzt
 *
 * Revision 1.22  2005/09/07 13:51:02  marbobo
 * + Sortierung nach Erstellungsdatum implementiert
 *
 * Revision 1.21  2005/05/31 16:22:36  marbobo
 * + Aktualisierung des Navigators korrigiert
 *
 * Revision 1.20  2005/05/11 19:31:26  marbobo
 * + Einstellungen für die Sortierung gefixt
 *
 * Revision 1.19  2005/04/28 15:27:50  korowa
 * Die Sortierungs Methoden werden jetzt im Profil in Datenbank gespeichert
 *
 * Revision 1.18  2005/02/20 16:58:03  marbobo
 * + Beim Speichern der Entities in die Datenbank wird sichergestellt
 *    dass Unicode-Zeichen in Kodierterform (als &#xxxxx;) gespeichert werden
 *
 * Revision 1.17  2005/02/08 16:16:19  bigmac
 * Quotabehandlung überarbeitet
 *
 * Revision 1.16  2005/01/26 14:46:49  bigmac
 * Exception beseitigt bei Abruf der Benutzerprofil-Seite mit abgeschaltetem Quotasystem
 *
 * Revision 1.15  2004/12/01 16:46:04  jonyp
 * synchrinze form: added support for ldap context
 *
 * Revision 1.14  2004/11/15 17:31:06  vchris
 * Anpassungen für VKCLdapUser
 *
 * Revision 1.13  2004/11/10 15:02:53  koppy
 * Projektweite Überarbeitung von Error-Logs, Stacktraces,..
 *
 * Revision 1.12  2004/10/20 12:05:58  marbobo
 * + Bugfix wegen Startkategorie
 *
 * Revision 1.11  2004/10/07 12:58:32  marbobo
 * + Festlegen der Startkategorie
 *
 * Revision 1.10  2004/08/07 18:17:06  marbobo
 * + Bugfix für Zeitangaben und Refactorings
 *
 * Revision 1.9  2004/08/03 14:27:48  jonyp
 * added method to show deleted files
 *
 * Revision 1.8  2004/07/20 15:26:29  jonyp
 * changed due to move of VKCQuotaInfo from util to view.bean
 *
 * Revision 1.7  2004/06/27 17:23:40  marbobo
 * + Quellcode maintenance
 *
 * Revision 1.6  2004/04/26 10:44:41  marbobo
 * + Unterstützung für Virtoweb-Sicht eingebaut
 *
 * Revision 1.5  2004/04/06 15:47:54  marbobo
 * Anzeige von Homekategorie gefixt
 *
 * Revision 1.4  2004/03/31 09:22:49  marbobo
 * + getHomeLinkParams()
 *
 * Revision 1.3  2004/03/31 08:09:33  jonyp
 * fixed bug: npe when homeCategoryId points to a deleted category
 *
 * Revision 1.2  2004/03/30 13:17:23  jonyp
 * display home category
 *
 * Revision 1.1  2004/03/16 00:41:44  marbobo
 * UserProfileAction und UserProfileForm auf request-scope umgestellt
 *
 * Revision 1.10  2004/03/11 20:17:18  bigmac
 * Anpassungen an VKCUserSerializer
 *
 * Revision 1.1  2003/08/07 01:56:25  marbobo
 * Initial Version
 *
 */
package vkc.profile.form;

import java.sql.Timestamp;
import java.text.CollationKey;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

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.VKCCategory;
import vkc.db.entities.VKCDynUserAttribute;
import vkc.db.entities.VKCLanguage;
import vkc.db.entities.VKCProxyUser;
import vkc.db.entities.VKCUser;
import vkc.db.helper.UserHelper;
import vkc.db.serializer.VKCLanguageSerializer;
import vkc.db.serializer.VKCCategorySerializer;
import vkc.db.serializer.VKCProxyUserSerializer;
import vkc.db.serializer.VKCSysParameterSerializer;
import vkc.db.serializer.VKCUserSerializer;
import vkc.exception.DBException;
import vkc.ldap.VKCLdapUser;
import vkc.misc.VKCLogManager;
import vkc.util.DateUtils;
import vkc.util.StringUtils;
import vkc.util.ServletUtils;
import vkc.util.VKCCategoryAbsPath;
import vkc.util.VKCStringUtils;
import vkc.view.PageId;
import vkc.view.WebShare;
import vkc.view.bean.UserDynAttr;
import vkc.view.bean.UserStatistics;
import vkc.view.bean.VKCQuotaInfo;
import vkc.view.bean.UserInfo;
import vkc.view.form.DynaForm;
import vkc.view.form.ShowBestsellerForm;
import vkc.view.form.ShowCategoryForm;
import vkc.view.form.ShowLatestAdditionsForm;
import vkc.view.form.SysLinkForm;

/**
 * Form Bean zum Editieren von eigenen Benutzerprofile
 *
 * @author marbobo
 * @version $Revision: 1.39 $
 */
public final class UserProfileForm extends DynaForm {
    //~ Instance fields --------------------------------------------------------
    private VKCUser  	user						= null;

    private List   		dynaAttributes				= new ArrayList();
    private List	 	languageLabels				= new ArrayList();
    private List		addProxyUserLabels			= new ArrayList();
    private List		removeProxyUserLabels		= new ArrayList();
    private Integer[] 	addProxyUserIds				= new Integer[0];
    private Integer[]	selectedAddProxyUserIds		= new Integer[0];
    private Integer[]	selectedRemoveProxyUserIds	= new Integer[0];
    private Integer		currentProxyUserId			= null;
    private Integer   	selectedLanguageId        	= null;
	private Integer   	selectedSystemViewTypeId   	= PageId.CATEGORY_VIEW;
    private Integer 	searchDocumentSortMode		= new Integer(1);
    private Integer 	bestsellerDocumentSortMode	= new Integer(ShowBestsellerForm.DOCUMENT_SORT_ACCESSCOUNT_DOWN);
    private Integer 	latestAdditionsDocumentSortMode	= new Integer(ShowLatestAdditionsForm.DOCUMENT_SORT_PUBLISHING_DATE_DOWN);
    private Integer 	categoryViewDocumentSortMode	= new Integer(ShowCategoryForm.DOCUMENT_SORT_PUBLISHING_DATE_DOWN);
    private String		proxyValidFrom				= "";
    private String		proxyValidUntil				= "";
    private String		proxyDescription			= "";

    private String 		title 						= "";
    private String 		firstname 					= "";
    private String 		lastname 					= "";
    private String 		email 						= "";
    private String 		company 					= "";
    private String 		department 					= "";
    private String 		street 						= "";
    private String 		zip 						= "";
    private String 		city 						= "";
    private String 		fax 						= "";
    private String 		phone 						= "";
    private String 		mobile 						= "";
    private String 		contactURL 					= "";
    private String 		homepageURL 				= "";
    private String  	selectedCategoryId			= String.valueOf(VKCCategory.ROOT_CATEGORY_ID);
    private boolean		showEmail					= false;
    private boolean     showTree                    = false;
	private boolean		languageChanged				= false;	
    private VKCQuotaInfo quotaInfo = null;
    private UserStatistics userStatistics = null;
    private boolean enableHtmlNotification          = false;

    //~ Methods ----------------------------------------------------------------

    /**
     * Reset der Eingabefelder auf Defaultwerte
     *
     * @param mapping The mapping used to select this instance
     * @param request The servlet request we are processing
     */
    public void reset(ActionMapping mapping, HttpServletRequest request) {
        super.reset(mapping, request);

        user						= null;        
        dynaAttributes				= new ArrayList();
        languageLabels				= new ArrayList();
        addProxyUserLabels			= new ArrayList();
        removeProxyUserLabels		= new ArrayList();
        addProxyUserIds				= new Integer[0];
        selectedAddProxyUserIds		= new Integer[0];
        selectedRemoveProxyUserIds	= new Integer[0];
        currentProxyUserId			= null;
        selectedLanguageId        	= null;
    	selectedSystemViewTypeId   	= PageId.CATEGORY_VIEW;
        searchDocumentSortMode		= new Integer(1);
        bestsellerDocumentSortMode	= new Integer(ShowBestsellerForm.DOCUMENT_SORT_ACCESSCOUNT_DOWN);
        latestAdditionsDocumentSortMode	= new Integer(ShowLatestAdditionsForm.DOCUMENT_SORT_PUBLISHING_DATE_DOWN);
        categoryViewDocumentSortMode	= new Integer(ShowCategoryForm.DOCUMENT_SORT_PUBLISHING_DATE_DOWN);
        proxyValidFrom				= "";
        proxyValidUntil				= "";
        proxyDescription			= "";

        title 						= "";
        firstname 					= "";
        lastname 					= "";
        email 						= "";
        company 					= "";
        department 					= "";
        street 						= "";
        zip 						= "";
        city 						= "";
        fax 						= "";
        phone 						= "";
        mobile 						= "";
        contactURL 					= "";
        homepageURL 				= "";
        selectedCategoryId			= String.valueOf(VKCCategory.ROOT_CATEGORY_ID);
        showEmail					= false;
        showTree					= false;
    	languageChanged				= false;
        quotaInfo 					= null;
        userStatistics              = null;
        enableHtmlNotification      = false;
    }

    /**
     * Validiert die Eingabefelder und gibt gegebenfalls die Fehler zurück
     *
     * @param mapping The mapping used to select this instance
     * @param request The servlet request we are processing
     */
    public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
        ActionErrors errors = new ActionErrors();

        setEnableHtmlNotification(request.getParameter("enableHtmlNotification") != null);
        setShowEmail(request.getParameter("showEmail") != null);
        setShowTree(request.getParameter("showTree") != null);

        if (request.getParameter("action.save.profile") != null) {
            synchronizeForm(request);

            if (!getUser().isExternalUser())
                validateUser(errors);

            if (!getAddProxyUserLabels().isEmpty() && getEditOwnProxys()) {
                validateProxyUsers(errors);
            }
        }
        
        return errors;
    }

    private void validateUser(ActionErrors errors) {
        if (isEmpty(getFirstname())) {
            errors.add("firstname", new ActionError("vkc.profile.error.firstname.required"));
        }

        if (isEmpty(getLastname())) {
            errors.add("lastname", new ActionError("vkc.profile.error.lastname.required"));
        }

        if (isEmpty(getEmail())) {
            errors.add("email", new ActionError("vkc.profile.error.email.required"));
        } else if (!StringUtils.isEmailValid(getEmail())) {
            errors.add("email", new ActionError("vkc.profile.error.email.invalid"));
        }
    }

    private void validateProxyUsers(ActionErrors errors) {
        for (int i = 0; i < getAddProxyUserLabels().size(); i++) {
            UserInfo userInfo = (UserInfo)getAddProxyUserLabels().get(i);
            String from  = null;
            String until = null;
            Date f = null;
            Date u = null;

            if (!userInfo.getUserId().equals(getCurrentProxyUserId())) {
                from  = (String)getDynaValue("proxyValidFrom_" + userInfo.getUserId().toString());
                until = (String)getDynaValue("proxyValidUntil_" + userInfo.getUserId().toString());
            } else {
                from  = getProxyValidFrom();
                until = getProxyValidUntil();
            }

            if (!isEmpty(from)) {
                if (DateUtils.parseDate(from ) == null) {
                    errors.add( "validFrom_" + userInfo.getUserId().toString(),	new ActionError("error.proxy.startdate", userInfo.getLastnameLabel()));
                } else {
                    f = DateUtils.parseDate(from);
                }
            }

            if (!isEmpty(until)) {
                if (DateUtils.parseDate(until) == null) {
                    errors.add("validUntil_" + userInfo.getUserId().toString(), new ActionError("error.proxy.enddate", userInfo.getLastnameLabel()));
                } else {
                    u = DateUtils.parseDate(until);
                }
            }

            if (f != null && u != null && f.after(u)) {
                errors.add("date_" + userInfo.getUserId().toString(), new ActionError("error.proxy.date.range", userInfo.getLastnameLabel()));
            }
        }
    }
    
    
    private void synchronizeDynaAttributes(HttpServletRequest request) {    	
    	List userDynAttrs = new ArrayList(getUser().getDynaAttributes());
    	getDynaAttributes().clear();
        int i=0;

        while (request.getParameter("dynaAttributeValue_" + i) != null)  {
            String value = StringUtils.normalize(request.getParameter("dynaAttributeValue_" + i));
            String name = ((VKCDynUserAttribute)userDynAttrs.get(i)).getName();
            int authorization = ((VKCDynUserAttribute)userDynAttrs.get(i)).getAutorization().intValue();
            getDynaAttributes().add(new UserDynAttr(name, value, authorization));
            i++;
        }	      
    }
    
    public void synchronizeForm(HttpServletRequest request) {
        try {
            // something very special here to getta da performance higha !!!
            //

            // get most current data for given user from db
            // does not return an ldapContext
            VKCUser user = VKCUserSerializer.retrieveUser(super.getUser().getUserId());

            // get current user from session, may contain an ldapContext
            VKCUser sessionUser = ServletUtils.getUser(request);

            // if user is of VKCLdapUser then set existing ldapContext from sessionUser
            // this is done here because VKCUserSerializer.retrieveUser should not
            // generated everytime an ldapContext (which is done through LdapProxy.authenticate)
            if (user instanceof VKCLdapUser) {
                ((VKCLdapUser) user).setLdapContext(((VKCLdapUser)sessionUser).getLdapContext());
            }

            // normaly this should do it without being too up-to-date unfortunatelly
            // but i dunnow da damn side effects'a
            // du schaust, isch guck... jp of 29.11.2004
            // setUser(ServletUtils.getUser(request));

            setUser(user);

/* commented out: jp of 29.11.2004
            // setUser(VKCUserSerializer.retrieveUser(super.getUser().getUserId()));
            // setUser(ServletUtils.getUser(request));
*/
            List languageLabels = VKCLanguageSerializer.getLanguages();

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

    		Comparator language_c = new Comparator() {
                public int compare(Object o1, Object o2) {
                    VKCLanguage l1 = (VKCLanguage) o1;
                    VKCLanguage l2 = (VKCLanguage) o2;

                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(l1.getName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(l2.getName()));
                	
                	return key1.compareTo(key2);
                }
            };

            Collections.sort(languageLabels, language_c);
            setLanguageLabels(languageLabels);
            
            synchronizeDynaAttributes(request);

            if (!init(request) && getEditOwnProxys()) {
                UserInfo userInfo = VKCUserSerializer.retrieveUserInfo(getUser().getUserId());
                List addProxyUserLabels = new ArrayList();
                List removeProxyUserLabels = new ArrayList();
                List userInfos = VKCUserSerializer.retrieveUserInfos();
                Integer[] addProxyUserIds = getAddProxyUserIds();

                //Eigenen Eintrag entfernen
                userInfos.remove(userInfo);

                for (int i = 0; i < addProxyUserIds.length; i++) {
                    for (int j = 0; j < userInfos.size(); j++) {
                        UserInfo u = (UserInfo) userInfos.get(j);

                        if (addProxyUserIds[i].equals(u.getUserId())) {
                            addProxyUserLabels.add(u);
                            userInfos.remove(j);
                            break;
                        }
                    }
                }

                removeProxyUserLabels = userInfos;

        		Comparator lastname_c = new Comparator() {
                    public int compare(Object o1, Object o2) {
                        UserInfo u1 = (UserInfo) o1;
                        UserInfo u2 = (UserInfo) o2;
                        
                    	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(u1.getLastname()));
                    	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(u2.getLastname()));
                    	
                    	return key1.compareTo(key2);
                    }
                };

                Collections.sort(addProxyUserLabels, lastname_c);
                Collections.sort(removeProxyUserLabels, lastname_c);
                setAddProxyUserLabels(addProxyUserLabels);
                setRemoveProxyUserLabels(removeProxyUserLabels);
                List list = Arrays.asList(getAddProxyUserIds());
                
                if (!list.isEmpty() && !list.contains(getCurrentProxyUserId())) {
                    setCurrentProxyUserId(((UserInfo)addProxyUserLabels.get(0)).getUserId());
                    Integer[] ids = {getCurrentProxyUserId()};
                    setSelectedRemoveProxyUserIds(ids);
                    setProxyDescription((String)getDynaValue("proxyDescription_" + getCurrentProxyUserId().toString()));
                    setProxyValidFrom((String)getDynaValue("proxyValidFrom_" + getCurrentProxyUserId().toString()));
                    setProxyValidUntil((String)getDynaValue("proxyValidUntil_" + getCurrentProxyUserId().toString()));
                } else if (!list.isEmpty()){
                    Integer[] ids = {getCurrentProxyUserId()};

                    if (!getSelectedRemoveProxyUserIds()[0].equals(ids[0])) {
                        setSelectedRemoveProxyUserIds(ids);
                        setProxyDescription((String)getDynaValue("proxyDescription_" + getCurrentProxyUserId().toString()));
                        setProxyValidFrom((String)getDynaValue("proxyValidFrom_" + getCurrentProxyUserId().toString()));
                        setProxyValidUntil((String)getDynaValue("proxyValidUntil_" + getCurrentProxyUserId().toString()));
                    }
                } else {
                    setCurrentProxyUserId(null);
                    setProxyDescription("");
                    setProxyValidFrom("");
                    setProxyValidUntil("");
                }
            }
            
            if (init(request)) {
                initializeForm(request);
            }
        } catch (DBException e) {
            VKCLogManager.errorLog(this, "", e.getMessage(), e);
        }
    }

    private boolean init(HttpServletRequest request) {
        return request.getParameter("initialize") != null;
    }

    private void initializeForm(HttpServletRequest request) throws DBException {
        setTitle(getUser().getTitle());
        setFirstname(getUser().getFirstname());
        setLastname(getUser().getLastname());
        setEmail(getUser().getEmail());
        setCompany(getUser().getCompany());
        setDepartment(getUser().getDepartment());
        setStreet(getUser().getStreet());
        setZip(getUser().getZip());
        setCity(getUser().getCity());
        setFax(getUser().getFax());
        setPhone(getUser().getPhone());
        setMobile(getUser().getMobile());
        setContactURL(getUser().getContactURL());
        setHomepageURL(getUser().getHomepageURL());
        setShowEmail(getUser().getShowEmail());
        setSelectedSystemViewTypeId(getUser().getSystemViewTypeId());
        setShowTree(getUser().getShowTree());
        setEnableHtmlNotification(user.isEnableHtmlNotification());

        Integer homeCategoryId = getUser().getHomeCategoryId();

        if (homeCategoryId != null && homeCategoryId.intValue() > 0) {
            setSelectedCategoryId(homeCategoryId.toString());
        }

        if (getUser().getSearchDocumentSortMode() != null) {
            setSearchDocumentSortMode(getUser().getSearchDocumentSortMode());
        }
        
                
        if (getUser().getBestsellerDocumentSortMode() != null) {
            setBestsellerDocumentSortMode(getUser().getBestsellerDocumentSortMode());
        }

        if (getUser().getLatestAdditionsDocumentSortMode() != null) {
            setLatestAdditionsDocumentSortMode(getUser().getLatestAdditionsDocumentSortMode());
        }

        if (getUser().getCategoryViewDocumentSortMode() != null) {
            setCategoryViewDocumentSortMode(getUser().getCategoryViewDocumentSortMode());
        }

        if (getLanguageLabels().contains(getUser().getLanguage())) {
            int index = getLanguageLabels().indexOf(getUser().getLanguage());
            VKCLanguage l = (VKCLanguage)getLanguageLabels().get(index);
            setSelectedLanguageId(l.getLanguageId());
        } else {
            setSelectedLanguageId(VKCLanguageSerializer.getDefaultLanguage().getLanguageId());
        }
        
        if (getEditOwnProxys()) {
            UserInfo userInfo = VKCUserSerializer.retrieveUserInfo(getUser().getUserId());

            List proxyUsers = new ArrayList(VKCProxyUserSerializer.getUsersForProxy(getUser().getUserId(), false));
            List addProxyUserLabels = new ArrayList();
            List removeProxyUserLabels = new ArrayList();
            List userInfos = VKCUserSerializer.retrieveUserInfos();
            List addProxyUserIds = new ArrayList();

            //Eigenen Eintrag entfernen
            userInfos.remove(userInfo);

            for (int i = 0; i < proxyUsers.size(); i++){
                VKCProxyUser pu = (VKCProxyUser) proxyUsers.get(i);
                addProxyUserIds.add(pu.getUserId());
                int index = userInfos.indexOf(new UserInfo(pu.getUserId()));
                UserInfo u = (UserInfo)userInfos.get(index);
                addProxyUserLabels.add(u);
                userInfos.remove(index);
                setDynaValue("proxyDescription_" + pu.getUserId().toString(), pu.getDescription());
                setDynaValue("proxyValidFrom_" + pu.getUserId().toString(), pu.getValidFromLabel());
                setDynaValue("proxyValidUntil_" + pu.getUserId().toString(), pu.getValidUntilLabel());
            }

            removeProxyUserLabels = userInfos;

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

    		Comparator lastname_c = new Comparator() {
                public int compare(Object o1, Object o2) {
                    UserInfo u1 = (UserInfo) o1;
                    UserInfo u2 = (UserInfo) o2;
                    
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(u1.getLastname()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(u2.getLastname()));
                	
                	return key1.compareTo(key2);
                }
            };

            Collections.sort(addProxyUserLabels, lastname_c);
            Collections.sort(removeProxyUserLabels, lastname_c);
            setAddProxyUserLabels(addProxyUserLabels);
            setRemoveProxyUserLabels(removeProxyUserLabels);
            setAddProxyUserIds((Integer[])addProxyUserIds.toArray(new Integer[0]));

            if (!addProxyUserLabels.isEmpty()) {
                setCurrentProxyUserId(((UserInfo)addProxyUserLabels.get(0)).getUserId());
                Integer[] ids = {getCurrentProxyUserId()};
                setSelectedRemoveProxyUserIds(ids);
                setProxyDescription((String)getDynaValue("proxyDescription_" + getCurrentProxyUserId().toString()));
                setProxyValidFrom((String)getDynaValue("proxyValidFrom_" + getCurrentProxyUserId().toString()));
                setProxyValidUntil((String)getDynaValue("proxyValidUntil_" + getCurrentProxyUserId().toString()));
            }
        }
        
		List userDynAttr = new ArrayList(getUser().getDynaAttributes());
		getDynaAttributes().clear();

		for (int i = 0; i < userDynAttr.size(); i++) {
			VKCDynUserAttribute dynaAttr = (VKCDynUserAttribute) userDynAttr.get(i);
			UserDynAttr bean = new UserDynAttr(dynaAttr.getName(), dynaAttr.getValue(), dynaAttr.getAutorization().intValue());
			getDynaAttributes().add(bean);
		}
    }

    public Integer[] getAddProxyUserIds() {
        return addProxyUserIds;
    }

    public List getAddProxyUserLabels() {
        return addProxyUserLabels;
    }

    public String getCategoryPath() {
        VKCCategoryAbsPath cap = null;
        Integer categoryId = null;

        categoryId = Integer.valueOf(getSelectedCategoryId());

        try {
            cap = VKCCategorySerializer.getCategoryAbsPath(categoryId);
        } catch (DBException e) {
        }

        if (cap == null) {
            return getResources().getMessage(getLocale(), "vkc.profile.error.homecategory");
        }

        return cap.getAbsolutePathString();
    }

    public String getCity() {
        return city;
    }

    public String getCompany() {
        return company;
    }

    public String getContactURL() {
        return contactURL;
    }

    public Integer getCurrentProxyUserId() {
        return currentProxyUserId;
    }

    public String getDepartment() {
        return department;
    }

    public boolean getEditOwnProxys() {
        return getUser().hasAdminPrivileges() || getUser().getManageOwnProxies();
    }

    public String getEmail() {
        return email;
    }

    public String getFax() {
        return fax;
    }

    public String getFirstname() {
        return firstname;
    }

    public String getSelectedCategoryId() {
        return selectedCategoryId;
    }

    public String getHomepageURL() {
        return homepageURL;
    }

    public HashMap getHomeLinkParams() {
        HashMap params = new HashMap();
        params.put("categoryId", getSelectedCategoryId());

        return params;
    }

    public HashMap getHomeSysLinkParams() {
        HashMap params = new HashMap();
        params.put("linkType", SysLinkForm.CATEGORY_LINK);
        params.put("objectId", getUser().getHomeCategoryId());

        return params;
    }

    public List getLanguageLabels() {
        return languageLabels;
    }

    public String getLastname() {
        return lastname;
    }

    public String getMobile() {
        return mobile;
    }

    public String getPhone() {
        return phone;
    }

    public String getProxyDescription() {
        return proxyDescription;
    }

    public List getOwnProxiesAsUserInfoSortedByLastname() throws DBException {
        List proxyUsers = new ArrayList(VKCProxyUserSerializer.getUsersForProxy(getUser().getUserId(), false));
        List userInfos = new ArrayList();

        if (proxyUsers.isEmpty()) {
            return userInfos;
        }

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

		Comparator lastname_c = new Comparator() {
            public int compare(Object o1, Object o2) {
                UserInfo u1 = (UserInfo) o1;
                UserInfo u2 = (UserInfo) o2;
                
            	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(u1.getLastname()));
            	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(u2.getLastname()));
            	
            	return key1.compareTo(key2);
            }
        };

        for (int i = 0; i < proxyUsers.size(); i++) {
            VKCProxyUser pu = (VKCProxyUser)proxyUsers.get(i);
            userInfos.add(VKCUserSerializer.retrieveUserInfo(pu.getUserId()));
        }

        Collections.sort(userInfos, lastname_c);

        return userInfos;
    }

    public List getProxiesAsUserInfoSortedByLastname() throws DBException {
        List proxyUsers = new ArrayList(VKCProxyUserSerializer.getProxyUsersForUser(getUser().getUserId(), false));
        List userInfos = new ArrayList();

        if (proxyUsers.isEmpty()) {
            return userInfos;
        }

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

		Comparator lastname_c = new Comparator() {
            public int compare(Object o1, Object o2) {
                UserInfo u1 = (UserInfo) o1;
                UserInfo u2 = (UserInfo) o2;
                
            	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(u1.getLastname()));
            	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(u2.getLastname()));
            	
            	return key1.compareTo(key2);
            }
        };

        for (int i = 0; i < proxyUsers.size(); i++) {
            VKCProxyUser pu = (VKCProxyUser)proxyUsers.get(i);
            userInfos.add(VKCUserSerializer.retrieveUserInfo(pu.getProxyUserId()));
        }

        Collections.sort(userInfos, lastname_c);

        return userInfos;
    }

    public List getProxyUsers() {
        List proxyUsers = new ArrayList();

        for (int i = 0; i < getAddProxyUserLabels().size(); i++) {
            UserInfo u = (UserInfo)getAddProxyUserLabels().get(i);
            VKCProxyUser pu = new VKCProxyUser();
            String description = null;
            String from  = null;
            String until = null;

            if (!u.getUserId().equals(getCurrentProxyUserId())) {
                description  = (String)getDynaValue("proxyDescription_" + u.getUserId().toString());
                from  = (String)getDynaValue("proxyValidFrom_" + u.getUserId().toString());
                until = (String)getDynaValue("proxyValidUntil_" + u.getUserId().toString());
            } else {
                description = getProxyDescription();
                from  = getProxyValidFrom();
                until = getProxyValidUntil();
            }

            if (!isEmpty(from)) {
                pu.setValidFrom(new Timestamp(DateUtils.parseDate(from).getTime()));
            } else {
                pu.setValidFrom(null);
            }

            if (!isEmpty(until)) {
                Calendar c = Calendar.getInstance();
                c.setTime(DateUtils.parseDate(until));
                c.set(Calendar.HOUR_OF_DAY, 23);
                c.set(Calendar.MINUTE, 59);
                c.set(Calendar.SECOND, 59);
                pu.setValidUntil(new Timestamp(c.getTimeInMillis()));
            } else {
                pu.setValidUntil(null);
            }

            pu.setUserId(u.getUserId());
            pu.setProxyUserId(getUser().getUserId());
            pu.setCreatorId(getUser().getUserId());
            pu.setDescription(VKCStringUtils.filterUnicodeChars(description));
            pu.setCreated(new Timestamp(System.currentTimeMillis()));

            proxyUsers.add(pu);
        }

        return proxyUsers;
    }

    public Object getOwnProxyUser(int id) throws DBException {
        List proxyUsers = new ArrayList(VKCProxyUserSerializer.getUsersForProxy(getUser().getUserId(), false));

        for (int i = 0; i < proxyUsers.size(); i++) {
            VKCProxyUser pu = (VKCProxyUser)proxyUsers.get(i);

            if (pu.getUserId().intValue() == id) {
                return proxyUsers.get(i);
            }
        }

        return null;
    }

    public Object getProxyUser(int id) throws DBException {
        List proxyUsers = new ArrayList(VKCProxyUserSerializer.getProxyUsersForUser(getUser().getUserId(), false));

        for (int i = 0; i < proxyUsers.size(); i++) {
            VKCProxyUser pu = (VKCProxyUser)proxyUsers.get(i);

            if (pu.getProxyUserId().intValue() == id) {
                return proxyUsers.get(i);
            }
        }

        return null;
    }

    public String getProxyValidFrom() {
        return proxyValidFrom;
    }

    public String getProxyValidUntil() {
        return proxyValidUntil;
    }

    public boolean isQuotaCheckingEnabled() {
        return VKCSysParameterSerializer.isQuotaCheckingEnabled();
    }

    public VKCQuotaInfo getUserQuotaInfo() throws DBException {
        if (quotaInfo == null) {
            quotaInfo = WebShare.database.getQuotaInfo(getUser().getUserId(), true);
        }
        
        return quotaInfo;
    }

    public UserStatistics getUserStatistics() throws DBException {
        if (userStatistics == null) {
            userStatistics = UserHelper.getUserStatistics(getUser().getUserId());
        }
        
        return userStatistics;
    }

    public List getRemoveProxyUserLabels() {
        return removeProxyUserLabels;
    }

    public Integer[] getSelectedAddProxyUserIds() {
        return selectedAddProxyUserIds;
    }

    public Integer getSelectedLanguageId() {
        return selectedLanguageId;
    }

    public Integer[] getSelectedRemoveProxyUserIds() {
        return selectedRemoveProxyUserIds;
    }

    public boolean isShowEmail() {
        return showEmail;
    }

    public String getStreet() {
        return street;
    }

    public String getTitle() {
        return title;
    }

    public VKCUser getUser() {
        return user;
    }

    public String getZip() {
        return zip;
    }

    public void setAddProxyUserIds(Integer[] integers) {
        addProxyUserIds = integers;
    }

    public void setAddProxyUserLabels(List list) {
        addProxyUserLabels = list;
    }

    public void setCity(String s) {
        city = StringUtils.normalize(s);
    }

    public void setCompany(String s) {
        company = StringUtils.normalize(s);
    }

    public void setContactURL(String s) {
        contactURL = StringUtils.normalize(s);
    }

    public void setCurrentProxyUserId(Integer integer) {
        currentProxyUserId = integer;
    }

    public void setDepartment(String s) {
        department = StringUtils.normalize(s);
    }

    public void setEmail(String s) {
        email = StringUtils.normalize(s);
    }

    public void setFax(String s) {
        fax = StringUtils.normalize(s);
    }

    public void setFirstname(String s) {
        firstname = StringUtils.normalize(s);
    }

    public void setSelectedCategoryId(String s) {
        selectedCategoryId = StringUtils.normalize(s);
    }

    public void setHomepageURL(String s) {
        homepageURL = StringUtils.normalize(s);
    }

    public void setLanguageLabels(List list) {
        languageLabels = list;
    }

    public void setLastname(String s) {
        lastname = StringUtils.normalize(s);
    }

    public void setMobile(String s) {
        mobile = StringUtils.normalize(s);
    }

    public void setPhone(String s) {
        phone = StringUtils.normalize(s);
    }

    public void setProxyDescription(String s) {
        proxyDescription = StringUtils.normalize(s);
    }

    public void setProxyValidFrom(String s) {
        proxyValidFrom = StringUtils.normalize(s);
    }

    public void setProxyValidUntil(String s) {
        proxyValidUntil = StringUtils.normalize(s);
    }

    public void setRemoveProxyUserLabels(List list) {
        removeProxyUserLabels = list;
    }

    public void setSelectedAddProxyUserIds(Integer[] integers) {
        selectedAddProxyUserIds = integers;
    }

    public void setSelectedLanguageId(Integer integer) {
        selectedLanguageId = integer;
    }

    public void setSelectedRemoveProxyUserIds(Integer[] integers) {
        selectedRemoveProxyUserIds = integers;
    }

    public void setShowEmail(boolean b) {
        showEmail = b;
    }

    public void setStreet(String s) {
        street = StringUtils.normalize(s);
    }

    public void setTitle(String s) {
        title = StringUtils.normalize(s);
    }

    public void setUser(VKCUser u) {
        user = u;
    }

    public void setZip(String s) {
        zip = StringUtils.normalize(s);
    }

    public Integer getBestsellerDocumentSortMode() {
        return bestsellerDocumentSortMode;
    }

    public void setBestsellerDocumentSortMode(Integer bestsellerDocumentSortMode) {
        this.bestsellerDocumentSortMode = bestsellerDocumentSortMode;
    }

    public Integer getCategoryViewDocumentSortMode() {
        return categoryViewDocumentSortMode;
    }

    public void setCategoryViewDocumentSortMode(Integer categoryViewDocumentSortMode) {
        this.categoryViewDocumentSortMode = categoryViewDocumentSortMode;
    }

    public Integer getLatestAdditionsDocumentSortMode() {
        return latestAdditionsDocumentSortMode;
    }

    public void setLatestAdditionsDocumentSortMode(Integer latestAdditionsDocumentSortMode) {
        this.latestAdditionsDocumentSortMode = latestAdditionsDocumentSortMode;
    }

    public Integer getSearchDocumentSortMode() {
        return searchDocumentSortMode;
    }

    public void setSearchDocumentSortMode(Integer searchDocumentSortMode) {
        this.searchDocumentSortMode = searchDocumentSortMode;
    }

	public Integer getSelectedSystemViewTypeId() {
		return selectedSystemViewTypeId;
	}

	public void setSelectedSystemViewTypeId(Integer selectedSystemViewTypeId) {
		this.selectedSystemViewTypeId = selectedSystemViewTypeId;
	}

	public boolean getShowTree() {
		return showTree;
	}

	public void setShowTree(boolean showTree) {
		this.showTree = showTree;
	}

	public boolean isLanguageChanged() {
		return languageChanged;
	}

	public void setLanguageChanged(boolean languageChanged) {
		this.languageChanged = languageChanged;
	}

	public List getDynaAttributes() {
		return dynaAttributes;
	}

	public void setDynaAttributes(List dynaAttribute) {
		this.dynaAttributes = dynaAttribute;
	}

	public boolean getReadableDynAttr() {
		if (getDynaAttributes() != null) {
			for (int i = 0; i < getDynaAttributes().size(); i++) {
				if (((UserDynAttr) getDynaAttributes().get(i)).getAutorization() != UserDynAttr.AUTORIZATION_NO || getUser().hasAdminPrivileges()) {
					return true;
				}
			}
		}
		
		return false;
	}

    public boolean isEnableHtmlNotification() {
        return enableHtmlNotification;
    }

    public void setEnableHtmlNotification(boolean enableHtmlNotification) {
        this.enableHtmlNotification = enableHtmlNotification;
    }

}