/*
 * $Id: VKCGroupDAO.java,v 1.5 2006/11/24 10:23:53 lawern Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
 * THIS SOFTWARE OR ITS DERIVATIVES.
 *
 * $Log: VKCGroupDAO.java,v $
 * Revision 1.5  2006/11/24 10:23:53  lawern
 * Anpassungen für PWS
 *
 * Revision 1.4  2006/09/22 12:19:49  lawern
 * Überarbeitung der Kommentare
 *
 * Revision 1.3  2006/09/22 10:36:32  korowa
 * Konstruktor und save() hinzugefügt + Dokumentation
 *
 * Revision 1.2  2006/09/20 14:21:48  lawern
 * Überarbeitung
 *
 * Revision 1.1  2006/08/17 13:01:14  lawern
 * Erster unvollständiger Schnellschuss für die Externe API.
 *
 */
package vkc.external;

import java.sql.Timestamp;
import java.util.Date;
import java.util.Set;

import javax.servlet.http.HttpSession;

import vkc.db.entities.VKCGroup;
import vkc.db.entities.VKCUser;

import vkc.db.serializer.VKCGroupSerializer;

import vkc.exception.DBException;
import vkc.util.VKCStringUtils;
import vkc.view.WebShare;

/**
 * Diese Klasse kapselt eine im VKC-System vorhandene Gruppe. Mit Hilfe der
 * Methoden dieser Klasse können vorhandene Gruppen geholt und bestimmte
 * Metadaten verändert werden. Ebenso können auch neue Gruppen angelegt werden.
 *  
 */
public class VKCGroupDAO {
    private VKCGroup intGroup; // internes VKCGroup-Objekt

    /**
     * Kapselt ein VKCGroup in VKCGroupDAO Objekt
     * 
     * @param intGroup
     */
    private VKCGroupDAO(VKCGroup intGroup) {
        this.intGroup = intGroup;
    }

    /**
     * Konstruktor der eine leeres Objekt vom Typ VKCGroupDAO erzeugt
     * 
     */
    public VKCGroupDAO() {
        intGroup = new VKCGroup();
    }

    /**
     * 
     * @param id
     *            ID der zu holender Gruppe
     * @return VKCGroupDAO Objekt falls vorhanden, sonst null
     */
    public static VKCGroupDAO retrieveVKCGroupDAO(int id) {
        try {
            return new VKCGroupDAO(VKCGroupSerializer
                    .retrieveGroup(new Integer(id)));
        } catch (DBException e) {
            // TODO Auto-generated catch block
            return null;
        }

    }
    
    /**
     * 
     * @param name
     *            Name der zu holender Gruppe
     * @return VKCGroupDAO Objekt falls vorhanden, sonst null
     */
    public static VKCGroupDAO retrieveVKCGroupDAO(String name) {
        try {
            return new VKCGroupDAO(VKCGroupSerializer
                    .retrieveGroup(VKCGroupSerializer.retrieveGroupInfo(name)
                            .getGroupId()));
        } catch (DBException e) {
            // TODO Auto-generated catch block
            return null;
        }
    }

    /**
     * 
     * @return interne VKCGroup Objekt
     */
    VKCGroup getIntGroup() {
        return intGroup;
    }

    /**
     * @param o
     *            Objekt das mit dem internen VKCGroup Objekt verglichen werden
     *            soll
     * @return true falls Objekte eines Typs sind und identische Id haben, sonst
     *         false
     */
    public boolean equals(Object o) {
        return intGroup.equals(o);
    }

//    /**
//     * 
//     * @return liefert Id der Gruppe, die bei einer Zugriffskontroltabelle
//     *         verwendet wird
//     */
//
//    public int getAccessorId() {
//        return intGroup.getAccessorId().intValue();
//    }
//
//    /**
//     * 
//     * @return liefert Name der Gruppe, der bei einer Zugriffskontroltabelle
//     *         verwendet wird
//     */
//    public String getAccessorName() {
//        return intGroup.getAccessorName();
//    }

    /**
     * 
     * @return true falls Gruppe aktiviert ist, sonst false
     */
    public boolean getAccountValid() {
        return intGroup.getAccountValid().booleanValue();
    }

    /**
     * 
     * @return true falls diese Gruppe Adminrechte besitzt, sonst false
     */
    public boolean getAdminPrivileges() {
        return intGroup.getAdminPrivileges().booleanValue();
    }

    /**
     * 
     * @return Erzeugungsdatum der Gruppe
     */
    public Date getCreated() {
        return intGroup.getCreated();
    }

    /**
     * 
     * @return Erzeuger der Gruppe
     */
    public int getCreatorId() {
        return intGroup.getCreatorId().intValue();
    }

    /**
     * 
     * @return Beschreibung der Gruppe
     */
    public String getDescription() {
        return intGroup.getDescription();
    }

    /**
     * 
     * @return Id der Gruppe
     */
    public int getGroupId() {
        return intGroup.getGroupId().intValue();
    }

    /**
     * 
     * @return Menge der BenutzerIDs von Mitgliedern dieser Gruppe
     */
    public Set getGroupUserIds() {
        try {
            return intGroup.getGroupUserIds();
        } catch (DBException e) {
            // TODO Auto-generated catch block
            return null;
        }
    }

    /**
     * 
     * @return Datum der letzten Änderung der Gruppe
     */
    public Date getLastChanged() {
        return intGroup.getLastChanged();
    }

    /**
     * 
     * @return Id des Benutzers, der die letzte Änderung an der Gruppe
     *         durchgeführt hat
     */
    public int getLastChangerId() {
        return intGroup.getLastChangerId().intValue();
    }

    /**
     * 
     * @return Name der Gruppe
     */
    public String getName() {
        return intGroup.getName();
    }

    /**
     * 
     * @return Datum, seit dem die Gruppe freigeschaltet wurde
     */
    public Date getValidFrom() {
        return intGroup.getValidFrom();
    }

    /**
     * 
     * @return Datum, bis zu welchem die Gruppe freigeschaltet wurde
     */
    public Date getValidUntil() {
        return intGroup.getValidUntil();
    }

    /**
     * @return hash code von dem Namen der Gruppe, wird folgendermaßen berechnet
     *         <blockquote>
     * 
     * <pre>
     *         s[0]*31&circ;(n-1) + s[1]*31&circ;(n-2) + ... + s[n-1]
     * </pre>
     * 
     * </blockquote> using <code>int</code> arithmetic, where
     * <code>s[i]</code> is the <i>i</i>th character of the string,
     * <code>n</code> is the length of the string, and <code>^</code>
     * indicates exponentiation. (The hash value of the empty string is zero.)
     */
    public int hashCode() {
        return intGroup.hashCode();
    }

    /**
     * 
     * @return true fals die Gruppe freigeschaltet ist, sonst false
     */
    public boolean isGroupValid() {
        return intGroup.isGroupValid().booleanValue();
    }

    /**
     * Funktion schaltet die Gruppe frei falls Parameter true ist, sperrt sie
     * sonst.
     * 
     * @param b
     */
    public void setAccountValid(boolean b) {
        intGroup.setAccountValid(new Boolean(b));
    }

    /**
     * Falls Parameter true ist erhalten alle Mitglieder Administrationsrechte
     * 
     * @param b
     */
    public void setAdminPrivileges(boolean b) {
        intGroup.setAdminPrivileges(new Boolean(b));
    }

    /**
     * Setzt die Beschreibung der Gruppe auf den mitgelieferten String
     * 
     * @param s
     */
    public void setDescription(String s) {
        if (s != null) {
            s = VKCStringUtils.filterUnicodeChars(s);
            s = VKCStringUtils.decodeXmlEntities(s);
            s = VKCStringUtils.encodeNamedXmlEntities(s);
            intGroup.setDescription(s);
        } else
            intGroup.setDescription("");
    }

    /**
     * Setzt den Namen der Gruppe auf den mitgelieferten String
     * 
     * @param s
     */
    public void setName(String s) {
        if (s != null)
            intGroup.setName(VKCStringUtils.filterUnicodeChars(s));
        else
            intGroup.setName("");
    }

    /**
     * Setzt das Startdatum, ab dem die Gruppe freigeschaltet werden soll
     * 
     * @param d
     */
    public void setValidFrom(Date d) {
        intGroup.setValidFrom(new Timestamp(d.getTime()));
    }

    /**
     * Setzt das Enddatum, bis den die Gruppe freigeschaltet bleibt
     * 
     * @param d
     */
    public void setValidUntil(Date d) {
        intGroup.setValidUntil(new Timestamp(d.getTime()));
    }

    /**
     * Speichert die aktuelle Gruppe permanent in der Datenbank
     * 
     * @param session
     *            Session-Objekt in dem der aktuelle Benutzer hinterlegt ist
     * @throws VKCExternalException
     */
    public void save(HttpSession session) throws VKCExternalException {
        save((VKCUser) session.getAttribute(WebShare.USER_KEY));
    }

    /**
     * Speichert die aktuelle Gruppe permanent in der Datenbank
     * 
     * @param user
     *            Der aktuelle Benutzer
     * @throws VKCExternalException
     */
    public void save(VKCUserDAO user) throws VKCExternalException {
        if (user.isAuthorized()) {
            save(user.getIntUser());
        }
    }

    /**
     * Speichert die aktuelle Gruppe
     * 
     * @param user
     *            Der aktuelle Benutzer
     * @throws VKCExternalException
     */
    private void save(VKCUser user) throws VKCExternalException {
        if (intGroup.getName() != null && !intGroup.getName().equals("")) {
            if (getValidFrom() != null && getValidUntil() != null
                    && getValidFrom().after(getValidUntil())) {
                throw new VKCExternalException(
                        VKCExternalException.ERROR_DATE_RANGE);
            }
            if (user.hasAdminPrivileges()) {
                try {
                    VKCGroup group = null;
                    if (intGroup.getGroupId() != null) {
                        group = VKCGroupSerializer.retrieveGroup(intGroup
                                .getGroupId());
                    }

                    if (group != null) {
                        intGroup.setLastChanged(new Timestamp(System
                                .currentTimeMillis()));
                        intGroup.setLastChangerId(user.getUserId());
                        VKCGroupSerializer.saveGroup(intGroup);
                    } else {// Vorhandene Gruppe ändern
                        if (VKCGroupSerializer.isGroupExistent(VKCStringUtils
                                .filterUnicodeChars(getName()))) {
                            throw new VKCExternalException(
                                    VKCExternalException.GROUP_NAME_EXIST);
                        } else {// Neue Gruppe speichern
                            intGroup.setCreatorId(user.getUserId());
                            intGroup.setCreated(new Timestamp(System
                                    .currentTimeMillis()));
                            intGroup.setLastChanged(new Timestamp(System
                                    .currentTimeMillis()));
                            intGroup.setLastChangerId(user.getUserId());
                            VKCGroupSerializer.saveGroup(intGroup);
                        }
                    }
                } catch (DBException e) {
                    throw new VKCExternalException(VKCExternalException.UNKNOWN);
                }
            } else {
                throw new VKCExternalException(
                        VKCExternalException.ADMIN_PERMISSION_FAILED);
            }
        } else {
            throw new VKCExternalException(
                    VKCExternalException.GROUP_NAME_MISSED);
        }
    }
    
    /**
     * Löscht die aktuelle Gruppe permanent in der Datenbank
     * 
     * @param session
     *            Session-Objekt in dem der aktuelle Benutzer hinterlegt ist
     * @throws VKCExternalException
     */
    public void delete(HttpSession session) throws VKCExternalException {
        delete((VKCUser) session.getAttribute(WebShare.USER_KEY));
    }
    
    /**
     * Löscht die aktuelle Gruppe permanent in der Datenbank
     * 
     * @param user
     *            Der aktuelle Benutzer
     * @throws VKCExternalException
     */
    public void delete(VKCUserDAO user) throws VKCExternalException {
        if (user.isAuthorized()) {
            delete(user.getIntUser());
        }
    }
    
    /**
     * Löscht die aktuelle Gruppe
     * 
     * @param user
     *            Der aktuelle Benutzer
     * @throws VKCExternalException
     */
    private void delete(VKCUser user) throws VKCExternalException {
        if (intGroup.getName() != null && !intGroup.getName().equals("")) {
            
            if (user.hasAdminPrivileges()) {
                try {
                    VKCGroupSerializer.deleteGroup(intGroup.getGroupId());
                } catch (DBException e) {
                    throw new VKCExternalException(VKCExternalException.UNKNOWN);
                }
            }
        }
    }
}
