/*
 * $Id: VKCCategoryDAO.java,v 1.21 2007/06/29 13:40:29 marbobo 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: VKCCategoryDAO.java,v $
 * Revision 1.21  2007/06/29 13:40:29  marbobo
 * + Bugfix (Vermeiden von doppel Benachrichtigungen)
 *
 * Revision 1.20  2007/02/13 12:28:38  lawern
 * Delegator-Konstruktor-Methoden nur noch friendly oder private.
 *
 * Revision 1.19  2007/02/06 08:54:34  lawern
 * Dynamische Attribute zu Delegator-Objekten gemacht + getDynaAttributes()-Methoden implementiert.
 *
 * Revision 1.18  2007/01/29 10:24:00  lawern
 * Erweiterung der External-API
 *
 * Revision 1.17  2007/01/09 11:56:27  korowa
 * VKCExternalException wird nicht mehr abgefangen sondern weitergereicht
 *
 * Revision 1.16  2007/01/04 14:41:56  lawern
 * addDocument setzt jetzt auch die DocSize für Notizen richtig.
 *
 * Revision 1.15  2007/01/04 14:04:45  lawern
 * addDocument setzt jetzt auch die DocSize
 *
 * Revision 1.14  2007/01/03 13:09:55  korowa
 * bugfixing bei If-Abfragen
 *
 * Revision 1.13  2007/01/03 08:27:24  korowa
 * Bug behoben: Acl-Außenfunktionen haben auf sich selbst verwiesen
 *
 * Revision 1.12  2007/01/02 10:43:12  lawern
 * Bugfixing
 *
 * Revision 1.11  2006/12/20 09:42:53  korowa
 * ACL-Methoden implementiert
 *
 * Revision 1.10  2006/12/15 12:32:45  lawern
 * ACL-Methoden ergänzt.
 *
 * Revision 1.9  2006/12/15 11:21:04  lawern
 * Konzept für die neuen ACL-Methoden.
 *
 * Revision 1.8  2006/09/20 14:21:47  lawern
 * Überarbeitung
 *
 * Revision 1.7  2006/09/14 09:04:33  lawern
 * DB-Persistenz nur noch nach .save-Aufruf
 *
 * Revision 1.6  2006/09/13 09:32:46  lawern
 * allgemeine Überarbeitung
 *
 * Revision 1.5  2006/08/24 14:54:21  marbobo
 * + Überarbeitet und mit Funktionalität gefüllt
 *
 * Revision 1.4  2006/08/24 01:01:32  marbobo
 * + Behandlung von dyn. Attributen
 * + Bugfixes
 *
 * Revision 1.3  2006/08/23 18:37:59  marbobo
 * + Behandlung von Unterkategorien, Dokumenten und dyn. Attributen eingebaut
 *
 * Revision 1.2  2006/08/21 13:37:02  marlin
 * Instanzierung des Strukturtemplates eingebaut
 *
 * Revision 1.1  2006/08/17 13:01:14  lawern
 * Erster unvollständiger Schnellschuss für die Externe API.
 *
 */
package vkc.external;

import vkc.converter.DocConverter;

import vkc.db.VKCDatabase;

import vkc.db.common.ConversionStatus;

import vkc.db.entities.VKCAclEntry;
import vkc.db.entities.VKCAclType;
import vkc.db.entities.VKCCategory;
import vkc.db.entities.VKCDocument;
import vkc.db.entities.VKCDocumentType;
import vkc.db.entities.VKCDynaAttribute;
import vkc.db.entities.VKCPermission;
import vkc.db.entities.VKCSubCategory;
import vkc.db.entities.VKCUser;

import vkc.db.serializer.VKCAclSerializer;
import vkc.db.serializer.VKCAclTypeSerializer;
import vkc.db.serializer.VKCCategorySerializer;
import vkc.db.serializer.VKCDocumentSerializer;
import vkc.db.serializer.VKCPermissionSerializer;

import vkc.exception.AclException;
import vkc.exception.DBException;

import vkc.security.PermissionManager;
import vkc.security.VKCAcl;

import vkc.util.CategoryUtils;
import vkc.util.DocumentUtils;
import vkc.util.VKCStringUtils;

import vkc.view.WebShare;

import java.io.InputStream;

import java.sql.Timestamp;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpSession;

import javax.swing.text.BadLocationException;



/**
 * Diese Klasse kapselt eine im VKC-System liegende Kategorie. Mit Hilfe der
 * Methoden dieser Klasse können vorhandene Kategorien geholt und bestimmte
 * Metadaten verändert werden. Ebenso können auch neue Kategorien angelegt
 * werden.
 *
 * @author marbobo
 */
public class VKCCategoryDAO {
    VKCCategory internalCategory; // internes VKCCategory-Objekt

    VKCCategoryDAO() {
        try {
            internalCategory = new VKCCategory();
            internalCategory.setName("");
            internalCategory.setDescription("");
            internalCategory.setParentCategoryId(new Integer(
                    VKCCategory.ROOT_CATEGORY_ID));

            VKCAcl acl = VKCAclSerializer.getAclByCategoryId(internalCategory.getParentCategoryId());
            acl.setAclId(null);
            internalCategory.setAcl(acl);
        } catch (DBException e) {
            e.printStackTrace();
        }
    }

    /**
     * Konstruktor zum Anlegen eines neuen Kategorie-Objekts
     *
     * @param name
     *            Name der Kategorie
     * @param description
     *            Beschreibung der Kategorie
     * @param parentCategoryId
     *            ID der übergeordneten Kategorie
     */
    public VKCCategoryDAO(String name, String description,
        Integer parentCategoryId) {
        try {
            internalCategory = new VKCCategory();

            if (name != null) {
                internalCategory.setName(VKCStringUtils.filterUnicodeChars(name));
            } else {
                internalCategory.setName("");
            }

            if (description != null) {
                description = VKCStringUtils.filterUnicodeChars(description);
                description = VKCStringUtils.decodeXmlEntities(description);
                description = VKCStringUtils.encodeNamedXmlEntities(description);
                internalCategory.setDescription(description);
            } else {
                internalCategory.setDescription("");
            }

            if (parentCategoryId != null) {
                internalCategory.setParentCategoryId(parentCategoryId);
            } else {
                internalCategory.setParentCategoryId(new Integer(
                        VKCCategory.ROOT_CATEGORY_ID));
            }

            VKCAcl acl = VKCAclSerializer.getAclByCategoryId(internalCategory.getParentCategoryId());
            acl.setAclId(null);
            internalCategory.setAcl(acl);
        } catch (DBException e) {
            e.printStackTrace();
        }
    }

    /**
     * Konstruktor zum Anlegen eines neuen Kategorie-Objekts aus einem regulären
     * VKC Kategorie-Objekt
     *
     * @param category
     *            Reguläre VKC Kategorie
     */
    VKCCategoryDAO(VKCCategory category) {
        internalCategory = category;
    }

    /**
     * Liefert die Wurzel-Kategorie des VKC-Systems
     *
     * @param session
     *            Session-Objekt in dem der aktuelle Benutzer hinterlegt ist
     * @return Das <code>VKCCategoryDAO</code>-Objekt der Wurzel-Kategorie
     * @throws VKCExternalException 
     */
    public static VKCCategoryDAO retrieveVKCRootCategoryDAO(HttpSession session) throws VKCExternalException {
        return retrieveVKCCategoryDAO(new Integer(VKCCategory.ROOT_CATEGORY_ID),
            (VKCUser) session.getAttribute(WebShare.USER_KEY));
    }

    /**
     * Liefert die Wurzel-Kategorie des VKC-Systems für den angegeben Benutzer
     *
     * @param user
     *            Der aktuelle Benutzer
     * @return Das <code>VKCCategoryDAO</code>-Objekt der Wurzel-Kategorie
     * @throws VKCExternalException 
     */
    public static VKCCategoryDAO retrieveVKCRootCategoryDAO(VKCUserDAO user) throws VKCExternalException {
        if (user.isAuthorized()) {
            return retrieveVKCCategoryDAO(new Integer(
                    VKCCategory.ROOT_CATEGORY_ID), user.getIntUser());
        }

        return null;
    }

    /**
     * Liefert für eine Kategorie-ID und einen Benutzer das Kategorie-Objekt
     * zurück
     *
     * @param categoryId
     *            ID der Kategorie, die geholt werden soll
     * @param session
     *            Session-Objekt in dem der aktuelle Benutzer hinterlegt ist
     * @return Das gewünschte Kategorie-Objekt, falls der Benutzer die
     *         entsprechenden Rechte hat, null sonst
     * @throws VKCExternalException 
     */
    public static VKCCategoryDAO retrieveVKCCategoryDAO(Integer categoryId,
        HttpSession session) throws VKCExternalException {
        return retrieveVKCCategoryDAO(categoryId,
            (VKCUser) session.getAttribute(WebShare.USER_KEY));
    }

    /**
     * Liefert für eine Kategorie-ID und einen Benutzer das Kategorie-Objekt
     * zurück
     *
     * @param categoryId
     *            ID der Kategorie, die geholt werden soll
     * @param user
     *            Der aktuelle Benutzer
     * @return Das gewünschte Kategorie-Objekt, falls der Benutzer die
     *         entsprechenden Rechte hat, null sonst
     * @throws VKCExternalException 
     */
    public static VKCCategoryDAO retrieveVKCCategoryDAO(Integer categoryId,
        VKCUserDAO user) throws VKCExternalException {
        if (user.isAuthorized()) {
            return retrieveVKCCategoryDAO(categoryId, user.getIntUser());
        }

        return null;
    }

    /**
     * Liefert für eine Kategorie-ID und einen Benutzer das Kategorie-Objekt
     * zurück
     *
     * @param categoryId
     *            ID der Kategorie, die geholt werden soll
     * @param user
     *            Der aktuelle Benutzer
     * @return Das gewünschte Kategorie-Objekt, falls der Benutzer die
     *         entsprechenden Rechte hat, null sonst
     * @throws VKCExternalException 
     */
    private static VKCCategoryDAO retrieveVKCCategoryDAO(Integer categoryId,
        VKCUser user) throws VKCExternalException {
        if (user == null) {
            return null;
        }

        VKCCategory cat = null;

        try {
            if (PermissionManager.hasPermission(
                        VKCAclSerializer.getAclByCategoryId(categoryId), user,
                        'r')) {
                cat = VKCCategorySerializer.retrieveCategory(categoryId);

                if (cat != null) {
                    return new VKCCategoryDAO(cat);
                }

                throw new VKCExternalException(VKCExternalException.UNKNOWN);
            }

            throw new VKCExternalException(VKCExternalException.READ_PERMISSION_FAILED);
        } catch (DBException e) {
            e.printStackTrace();
            return null;  
        }
    }

    /**
     * Speichert die aktuelle Kategorie
     *
     * @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 Kategorie
     *
     * @param user
     *            Der aktuelle Benutzer
     * @throws VKCExternalException 
     */
    public void save(VKCUserDAO user) throws VKCExternalException {
        if (user.isAuthorized()) {
            save(user.getIntUser());
        }
    }

    /**
     * Speichert die aktuelle Kategorie
     *
     * @param user
     *            Der aktuelle Benutzer
     * @throws VKCExternalException 
     */
    private void save(VKCUser user) throws VKCExternalException {
        if (internalCategory.getCategoryId() != null) {
            try {
                if (internalCategory.getCreatorId() == null) {
                    if (PermissionManager.hasPermission(
                                internalCategory.getAcl(), user, 'C')) {
                        internalCategory.setCreated(new Date(
                                System.currentTimeMillis()));
                        internalCategory.setCreatorId(user.getUserId());

                        VKCAcl acl = VKCAclSerializer.getAclByCategoryId(internalCategory.getParentCategoryId());
                        PermissionManager.setCategoryOwnerPermissions(new Integer(
                                VKCAclType.USER_TYPE), user.getUserId(),
                            user.getUserId(), acl);
                        acl.setAclId(null);
                        internalCategory.setAcl(acl);
                        VKCCategorySerializer.saveCategory(internalCategory);
                    } else {
                        throw new VKCExternalException(VKCExternalException.CREATE_CATEGORY_PERMISSION_FAILED);
                    }
                } else {
                    if (PermissionManager.hasPermission(
                                internalCategory.getAcl(), user, 'w')) {
                        internalCategory.setLastChanged(new Date(
                                System.currentTimeMillis()));
                        internalCategory.setLastChangerId(user.getUserId());
                        VKCCategorySerializer.saveCategory(internalCategory);
                    } else {
                        throw new VKCExternalException(VKCExternalException.WRITE_PERMISSION_FAILED);
                    }
                }
            } catch (DBException e) {
                e.printStackTrace();
            } catch (AclException e) {
                e.printStackTrace();
            }
        } else {            
            throw new VKCExternalException(VKCExternalException.ID_MISSED);
        }
    }

    /**
     * Fügt dieser Kategorie eine Unterkategorie hinzu
     *
     * @param subCategory
     *            Hinzuzufügende Unterkategorie
     * @param session
     *            Session-Objekt in dem der aktuelle Benutzer hinterlegt ist
     * @throws VKCExternalException 
     */
    public void addSubCategory(VKCCategoryDAO subCategory, HttpSession session) throws VKCExternalException {
        addSubCategory(subCategory,
            (VKCUser) session.getAttribute(WebShare.USER_KEY));
    }

    /**
     * Fügt dieser Kategorie eine Unterkategorie hinzu
     *
     * @param subCategory
     *            Hinzuzufügende Unterkategorie
     * @param user
     *            Benutzer-Objekt
     * @throws VKCExternalException 
     */
    public void addSubCategory(VKCCategoryDAO subCategory, VKCUserDAO user) throws VKCExternalException {
        if (user.isAuthorized()) {
            addSubCategory(subCategory, user.getIntUser());
        }
    }

    /**
     * Fügt dieser Kategorie eine Unterkategorie hinzu
     *
     * @param subCategory
     *            Hinzuzufügende Unterkategorie
     * @param user
     *            Benutzer-Objekt
     * @throws VKCExternalException 
     */
    private void addSubCategory(VKCCategoryDAO subCategory, VKCUser user) throws VKCExternalException {
        if (subCategory == null) {
            return;
        }

        if (internalCategory.getCategoryId() != null) {
            try {
                if (PermissionManager.hasPermission(internalCategory.getAcl(),
                            user, 'C')) {
                    VKCAcl acl = internalCategory.getAcl();

                    try {
                        PermissionManager.setCategoryOwnerPermissions(new Integer(
                                VKCAclType.USER_TYPE), user.getUserId(),
                            user.getUserId(), acl);
                    } catch (Exception ex) {
                    }

                    acl.setAclId(null);

                    VKCCategory newCategory = subCategory.internalCategory;
                    newCategory.setAcl(acl);
                    newCategory.setParentCategoryId(internalCategory.getCategoryId());
                    newCategory.setCreated(new Timestamp(
                            System.currentTimeMillis()));
                    newCategory.setCreatorId(user.getUserId());
                    
                    if (!CategoryUtils.isCategoryNameUnique(newCategory, internalCategory.getSubCategories())) {
                        throw new VKCExternalException(VKCExternalException.CATEGORY_NAME_VIOLATION);
                    }
                    
                    // Fügt die Kategorie ein
                    VKCCategorySerializer.saveCategory(newCategory);
                } else {
                    throw new VKCExternalException(VKCExternalException.CREATE_CATEGORY_PERMISSION_FAILED);
                }
            } catch (DBException e) {
                e.printStackTrace();
            }
        } else {            
            throw new VKCExternalException(VKCExternalException.ID_MISSED);
           
        }
    }

    /**
     * Fügt dieser Kategorie ein Dokument hinzu
     *
     * @param document
     *            Hinzufügendes Dokument
     * @param session
     *            Session-Objekt in dem der aktuelle Benutzer hinterlegt ist
     * @throws VKCExternalException 
     */
    public void addDocument(VKCDocumentDAO document, HttpSession session) throws VKCExternalException {
        if ((document.getDocTypeId().intValue() == DocConverter.link) ||
                (document.getDocTypeId().intValue() == DocConverter.note)) {
            addDocument(document, null,
                (VKCUser) session.getAttribute(WebShare.USER_KEY));
        } else {            
        	throw new VKCExternalException(VKCExternalException.DOCUMENT_STREAM_MISSED); 
        }
    }

    /**
     * Fügt dieser Kategorie ein Dokument hinzu
     *
     * @param document
     *            Hinzufügendes Dokument
     * @param user
     *            Benutzer-Objekt
     * @throws VKCExternalException 
     */
    public void addDocument(VKCDocumentDAO document, VKCUserDAO user) throws VKCExternalException {
        if (user.isAuthorized()) {
            if ((document.getDocTypeId().intValue() == DocConverter.link) ||
                    (document.getDocTypeId().intValue() == DocConverter.note)) {
                addDocument(document, null, user.getIntUser());
            } else {
                throw new VKCExternalException(VKCExternalException.DOCUMENT_STREAM_MISSED);
            }
        }
    }

    /**
     * Fügt dieser Kategorie ein Dokument mit dem angegebenem InputStream hinzu
     *
     * @param document
     *            Hinzufügendes Dokument
     * @param docStream
     *            InputStream des Dokuments
     * @param session
     *            Session-Objekt in dem der aktuelle Benutzer hinterlegt ist
     * @throws VKCExternalException 
     */
    public void addDocument(VKCDocumentDAO document, InputStream docStream,
        HttpSession session) throws VKCExternalException {
        if (docStream == null) {
           throw new VKCExternalException(VKCExternalException.DOCUMENT_STREAM_MISSED);           
        }
        addDocument(document, docStream,
            (VKCUser) session.getAttribute(WebShare.USER_KEY));
    }

    /**
     * Fügt dieser Kategorie ein Dokument mit dem angegebenem InputStream hinzu
     *
     * @param document
     *            Hinzufügendes Dokument
     * @param docStream
     *            InputStream des Dokuments
     * @param user
     *            Benutzer-Objekt
     * @throws VKCExternalException 
     */
    public void addDocument(VKCDocumentDAO document, InputStream docStream,
        VKCUserDAO user) throws VKCExternalException {
        if (user.isAuthorized()) {
            if (docStream == null) {
               throw new VKCExternalException(VKCExternalException.DOCUMENT_STREAM_MISSED);
            }
            addDocument(document, docStream, user.getIntUser());
        }
    }

    /**
     * Fügt dieser Kategorie ein Dokument mit dem angegebenem InputStream hinzu
     *
     * @param document
     *            Hinzufügendes Dokument
     * @param docStream
     *            InputStream des Dokuments
     * @param user
     *            Benutzer-Objekt
     * @throws VKCExternalException 
     */
    private void addDocument(VKCDocumentDAO document, InputStream docStream,
        VKCUser user) throws VKCExternalException {
        if (document == null) {
            return;
        }

        if (internalCategory.getCategoryId() != null) {
            try {
                if (PermissionManager.hasPermission(internalCategory.getAcl(),
                            user, 'w')) {
                    String archiveId = null;

                    VKCDocument doc = document.getInternalDocument();
                    
                    if (docStream != null) {
                        doc.setDocSize(new Long(docStream.available()));
                        
                        // Stream im Archiv speichern
                        archiveId = WebShare.archive.store(docStream);
                    } else {
                        doc.setDocSize(new Long(0));
                    }

                    doc.setPublished(new Date(System.currentTimeMillis()));
                    doc.setPublisherId(user.getUserId());

                    // set tracking data to null
                    doc.setLastAccessed(null);
                    doc.setLastAccessorId(null);
                    doc.setLastChanged(null);
                    doc.setLastChangerId(null);

                    doc.setArchiveId(archiveId);
                    doc.setPreDocId(null);
                    doc.setCategoryId(internalCategory.getCategoryId());

                    try {
                        VKCDocumentType docType = doc.getDocumentType();

                        if (docType.isConvertible()) {
                            VKCDocumentSerializer.saveDocument(doc, false, true);

                            ConversionStatus cs = new ConversionStatus();
                            cs.setDocumentId(doc.getDocumentId());
                            cs.setSendmail(false);
                            cs.makePersistent();
                        } else {
                            VKCDocumentSerializer.saveDocument(doc, true, true);
                        }

                        internalCategory.addDocument(doc);
                    } catch (DBException e3) {
                        if (!e3.getMessage().equals(VKCDatabase.QUOTA_EXCEEDED)) {
                            throw new VKCExternalException(VKCExternalException.QUOTA_EXCEEDED);
                        }

                        if (archiveId != null) {
                            WebShare.archive.delete(archiveId);
                        }

                        return;
                    }
                } else {
                    throw new VKCExternalException(VKCExternalException.WRITE_PERMISSION_FAILED);
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            throw new VKCExternalException(VKCExternalException.ID_MISSED);           
        }
    }

    /**
     * Löschen des Kategorie-Objekts
     *
     * @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öschen des Kategorie-Objekts
     *
     * @param user
     *            Benutzer-Objekt
     * @throws VKCExternalException 
     */
    public void delete(VKCUserDAO user) throws VKCExternalException {
        if (user.isAuthorized()) {
            delete(user.getIntUser());
        }
    }

    /**
     * Löschen des Kategorie-Objekts
     *
     * @param user
     *            Benutzer-Objekt
     * @throws VKCExternalException 
     */
    private void delete(VKCUser user) throws VKCExternalException {
        try {
            if (PermissionManager.hasPermission(internalCategory.getAcl(),
                        user, 'D')) {
                VKCCategorySerializer.deleteCategory(user,
                    internalCategory.getCategoryId(),
                    !WebShare.isTrashEnabled(), null);
            } else {
                throw new VKCExternalException(VKCExternalException.DELETE_PERMISSION_FAILED);
            }
        } catch (DBException e) {
            e.printStackTrace();
        } 
    }

    /**
     * Liefert für die aktuelle Kategorie alle direkten Unterkategorie IDs
     * zurück
     *
     * @return <code>Set</code> der Unterkategorie IDs
     */
    public Set getSubCategoryIds() {
        return internalCategory.getSubCategoriesIds();
    }

    /**
     * Liefert für die aktuelle Kategorie alle vom Benutzer lesbaren direkten
     * Unterkategorie IDs zurück
     *
     * @param user
     *            Der aktuelle Benutzer
     * @return <code>Set</code> der Unterkategorie IDs
     */
    public Set getAccessibleSubCategoryIds(VKCUserDAO user) {
        if (user.isAuthorized()) {
            List subCategories = internalCategory.getAccessibleSubCategories(user.getIntUser());
            HashSet ids = new HashSet();

            for (Iterator iter = subCategories.iterator(); iter.hasNext();) {
                VKCSubCategory subCategory = (VKCSubCategory) iter.next();
                ids.add(subCategory.getSubCategoryId());
            }

            return ids;
        }

        return new HashSet();
    }

    /**
     * Liefert für die aktuelle Kategorie rekursiv alle Unterkategorie IDs
     * zurück
     *
     * @return <code>Set</code> der Unterkategorie IDs
     */
    public Set getSubCategoryIdsRecursiv() throws DBException {
        return CategoryUtils.getAllSubCategoryIdsRecursiv(internalCategory.getCategoryId());
    }

    /**
     * Liefert für die aktuelle Kategorie alle Dokument IDs zurück
     *
     * @return <code>Set</code> der Dokument IDs
     */
    public Set getDocumentIds() {
        Set ids = new HashSet();

        if ((internalCategory != null) &&
                (internalCategory.getDocuments() != null)) {
            for (Iterator iter = internalCategory.getDocuments().iterator();
                    iter.hasNext();) {
                VKCDocument document = (VKCDocument) iter.next();
                ids.add(document.getDocumentId());
            }
        }

        return ids;
    }

    /**
     * Liefert für die aktuelle Kategorie alle Dokument IDs von Dokumenten 
     * zurück deren Namen dem Parameter documentName entspricht.
     * 
     * @param documentName Name für den IDs geliefert werden sollen.
     * @return <code>Set</code> der Dokument IDs
     */
    public Collection getDocumentIdsByName(String documentName) {
        try {
            if ((internalCategory != null) &&
                    (internalCategory.getDocuments() != null)) {
                return DocumentUtils.retrieveDocumentIdsByCategoryIdAndName(internalCategory.getCategoryId(),
                    documentName);
            }
        } catch (DBException e) {
            // TODO Auto-generated catch block
        }

        return null;
    }

    /**
     * Liefert den Namen dieser Kategorie (in Unicode) zurück
     *
     * @return Der Name dieser Kategorie (in Unicode)
     */
    public String getName() {
        if (internalCategory != null) {
            return VKCStringUtils.decodeXmlEntities(VKCStringUtils.filterUnicodeChars(
                    internalCategory.getName()));
        }

        return "";
    }

    /**
     * Liefert die Beschreibung dieser Kategorie (in Unicode) zurück
     *
     * @return Die Beschreibung dieser Kategorie (in Unicode)
     */
    public String getDescription() {
        if (internalCategory != null) {
            String s = VKCStringUtils.filterUnicodeChars(internalCategory.getDescription());
            s = VKCStringUtils.htmlFormatedText(s);
            s = VKCStringUtils.decodeXmlEntities(s);
            s = VKCStringUtils.decodeNamedXmlEntitiesNotInSwing(s);

            try {
                s = VKCStringUtils.removeHtmlTags(s);
            } catch (BadLocationException e) {
                e.printStackTrace();
            }

            return s;
        }

        return "";
    }

    /**
     * Fügt dieser Kategorie ein dynamisches Attribut hinzu
     *
     * @param dynaAttribute
     *            Hinzufügendes Attribute
     */
    public void addDynaAttribute(VKCDynaAttributeDAO dynaAttribute) {
        if (internalCategory.getCategoryId() != null) {
            VKCDynaAttribute attr = new VKCDynaAttribute();
            attr.setName(VKCStringUtils.filterUnicodeChars(
                    dynaAttribute.getName()));
            attr.setValue(VKCStringUtils.filterUnicodeChars(
                    dynaAttribute.getValue()));
            internalCategory.addDynaAttribute(attr);
        }
    }

    /**
     * Gibt das dynamische Attribute zurück
     *
     * @param name
     *            Der Name des Attributes
     * @return Falls vorhanden das dynamische Attribut, sonst null
     */
    public VKCDynaAttributeDAO getDynaAttribute(String name) {
        for (Iterator iter = internalCategory.getDynaAttributes().iterator();
                iter.hasNext();) {
            VKCDynaAttribute da = (VKCDynaAttribute) iter.next();

            if (da.getName().equals(name)) {
                VKCDynaAttributeDAO attr = new VKCDynaAttributeDAO(da);
                
                return attr;
            }
        }

        return null;
    }
    
    /**
     * Gibt eine Liste der dynamischen Attribute zurück
     * 
     * @return Falls vorhanden eine Collection mit dynamischen Attributen
     *         (VKCDynaAttributeDAO), sonst null.
     */
    public Collection getDynaAttributes() {
        Collection attributes = internalCategory.getDynaAttributes();

        if (attributes != null) {
            ArrayList extAttributes = new ArrayList(attributes.size());
            for (Iterator iter = attributes.iterator(); iter.hasNext();) {
                VKCDynaAttribute da = (VKCDynaAttribute) iter.next();

                extAttributes.add(new VKCDynaAttributeDAO(da));
            }

            return extAttributes;
        } else {
            return null;
        }
    }

    /**
     * Löscht das dynamische Attribute mit dem angegebenen Namen
     *
     * @param name
     *            Der Name des Attributes
     */
    public void deleteDynaAttribute(String name) {
        if (internalCategory.getCategoryId() != null) {
            VKCDynaAttribute attr = null;

            for (Iterator iter = internalCategory.getDynaAttributes().iterator();
                    iter.hasNext();) {
                attr = (VKCDynaAttribute) iter.next();

                if (attr.getName()
                            .equals(VKCStringUtils.filterUnicodeChars(name))) {
                    break;
                }
            }

            if (attr != null) {
                internalCategory.getDynaAttributes().remove(attr);
            }
        }
    }

    /**
     * Ändert den Wert des angegebenen dynamischen Attributes in dieser Kategorie
     *
     * @param name
     *            Zu änderndes Attribute
     * @param newValue
     *            Der neue Wert
     * @param session
     *            Session-Objekt in dem der aktuelle Benutzer hinterlegt ist
     * @throws VKCExternalException 
     */
    public void setDynaAttribute(String name, String newValue,
        HttpSession session) throws VKCExternalException {
        setDynaAttribute(name, newValue,
            (VKCUser) session.getAttribute(WebShare.USER_KEY));
    }

    /**
     * Ändert den Wert des angegebenen dynamischen Attributes in dieser Kategorie
     *
     * @param name
     *            Zu änderndes Attribute
     * @param newValue
     *            Der neue Wert
     * @param user
     *            Der aktuelle Benutzer
     * @throws VKCExternalException 
     */
    public void setDynaAttribute(String name, String newValue, VKCUserDAO user) throws VKCExternalException {
        if (user.isAuthorized()) {
            setDynaAttribute(name, newValue, user.getIntUser());
        }
    }

    /**
     * Ändert den Wert des angegebenen dynamischen Attributes in dieser Kategorie
     *
     * @param name
     *            Zu änderndes Attribute
     * @param newValue
     *            Der neue Wert
     * @param user
     *            Der aktuelle Benutzer
     * @throws VKCExternalException 
     */
    private void setDynaAttribute(String name, String newValue, VKCUser user) throws VKCExternalException {
        if (internalCategory.getCategoryId() != null) {
            if (PermissionManager.hasPermission(internalCategory.getAcl(),
                        user, 'w')) {
                try {
                    VKCDynaAttribute attr = null;

                    for (Iterator iter = internalCategory.getDynaAttributes()
                                                         .iterator();
                            iter.hasNext();) {
                        attr = (VKCDynaAttribute) iter.next();

                        if (attr.getName()
                                    .equals(VKCStringUtils.filterUnicodeChars(
                                        name))) {
                            break;
                        }
                    }

                    if (attr != null) {
                        internalCategory.getDynaAttributes().remove(attr);
                        attr.setValue(VKCStringUtils.filterUnicodeChars(
                                newValue));
                        internalCategory.addDynaAttribute(attr);
                        internalCategory.setLastChanged(new Date(
                                System.currentTimeMillis()));
                        internalCategory.setLastChangerId(user.getUserId());
                        VKCCategorySerializer.saveCategory(internalCategory);
                    }
                } catch (DBException e) {
                    e.printStackTrace();
                }
            } else {
                throw new VKCExternalException(VKCExternalException.WRITE_PERMISSION_FAILED);               
            }
        }
    }

    /**
     * Liefert die ID dieser Kategorie
     *
     * @return Die Kategorie ID
     */
    public Integer getCategoryId() {
        return internalCategory.getCategoryId();
    }

    /**
     * Liefert die Eltern-Kategorie ID
     *
     * @return Die Eltern-Kategorie ID
     */
    public Integer getParentCategoryId() {
        return internalCategory.getParentCategoryId();
    }
  
    /**
     * Ergänzt die Zugriffsberechtigungen für die Öffentlichkeit. Bereits
     * gesetzte Rechte werden überschrieben.
     * 
     * @param session
     * @param changeACL
     * @param readCategory
     * @param writeCategory
     * @param deleteDocuments
     * @param deleteCategory
     * @param createSubcategory
     * @throws VKCExternalException 
     * @throws VKCExternalException 
     */
    public void addPublicPermission(HttpSession session, boolean changeACL,
            boolean readCategory, boolean writeCategory,
            boolean deleteDocuments, boolean deleteCategory,
            boolean createSubcategory) throws VKCExternalException {
        addPublicPermission((VKCUser) session.getAttribute(WebShare.USER_KEY),
                changeACL, readCategory, writeCategory, deleteDocuments,
                deleteCategory, createSubcategory);
    }

    /**
     * Ergänzt die Zugriffsberechtigungen für die Öffentlichkeit. Bereits
     * gesetzte Rechte werden überschrieben.
     * 
     * @param user
     * @param changeACL
     * @param readCategory
     * @param writeCategory
     * @param deleteDocuments
     * @param deleteCategory
     * @param createSubcategory
     * @throws VKCExternalException 
     */
    public void addPublicPermission(VKCUserDAO user, boolean changeACL,
            boolean readCategory, boolean writeCategory,
            boolean deleteDocuments, boolean deleteCategory,
            boolean createSubcategory) throws VKCExternalException {
        if (user.isAuthorized()) {
            addPublicPermission(user.getIntUser(), changeACL, readCategory, writeCategory,
                    deleteDocuments, deleteCategory, createSubcategory);
        }
    }

    /**
	 * Ergänzt die Zugriffsberechtigungen für die Öffentlichkeit. Bereits
	 * gesetzte Rechte werden überschrieben.
	 * 
	 * @param user
	 * @param changeACL
	 * @param readCategory
	 * @param writeCategory
	 * @param deleteDocuments
	 * @param deleteCategory
	 * @param createSubcategory
     * @throws VKCExternalException 
	 * @throws VKCExternalException
	 */
	private void addPublicPermission(VKCUser user, boolean changeACL,
			boolean readCategory, boolean writeCategory,
			boolean deleteDocuments, boolean deleteCategory,
			boolean createSubcategory) throws VKCExternalException {
		try {
			if (PermissionManager.hasPermission(VKCAclSerializer
					.getAclByCategoryId(this.getCategoryId()), user, 'c')) {
				// falls der Eintrag für public schon forhanden ist ---> löschen
				if (this.internalCategory.getAcl().hasPublicEntry()){
					internalCategory.getAcl().deleteAclEntry(
							VKCAclType.ANYOTHER_TYPE, 0);
				}
				Map permissions = VKCPermissionSerializer
						.getPermissions(VKCPermission.CONTEXT_CATEGORY);				
				VKCAclType aclt = null;
				aclt = (VKCAclType) VKCAclTypeSerializer.retrieveAclTypes().get( "anyother" );

				if (changeACL) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("c");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(0));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
				if (readCategory) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("r");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(0));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
				if (writeCategory) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("w");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(0));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
				if (deleteDocuments) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("d");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(0));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
				if (deleteCategory) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("D");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(0));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
				if (createSubcategory) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("C");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(0));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
			} else {
				throw new VKCExternalException(
						VKCExternalException.CHANGE_ACL_PERMISSION_FAILED);
			}
		} catch (DBException e) {
			e.printStackTrace();
		}
	}

    /**
	 * Ergänzt die Zugriffsberechtigungen für den übergebenen Benutzer. Bereits
	 * gesetzte Rechte werden überschrieben.
	 * 
	 * @param session
	 * @param permissionUser
	 *            Benutzer, dem Rechte an dieser Kategorie gegeben werden.
	 * @param changeACL
	 * @param readCategory
	 * @param writeCategory
	 * @param deleteDocuments
	 * @param deleteCategory
	 * @param createSubcategory
     * @throws VKCExternalException 
	 */
    public void addUserPermission(HttpSession session,
            VKCUserDAO permissionUser, boolean changeACL, boolean readCategory,
            boolean writeCategory, boolean deleteDocuments,
            boolean deleteCategory, boolean createSubcategory) throws VKCExternalException {
        addUserPermission((VKCUser) session.getAttribute(WebShare.USER_KEY),
                permissionUser, changeACL, readCategory, writeCategory,
                deleteDocuments, deleteCategory, createSubcategory);
    }
   
	
    /**
     * Ergänzt die Zugriffsberechtigungen für den übergebenen Benutzer. Bereits
     * gesetzte Rechte werden überschrieben.
     * 
     * @param user
     * @param permissionUser
     *            Benutzer, dem Rechte an dieser Kategorie gegeben werden.
     * @param changeACL
     * @param readCategory
     * @param writeCategory
     * @param deleteDocuments
     * @param deleteCategory
     * @param createSubcategory
     * @throws VKCExternalException 
     */
    public void addUserPermission(VKCUserDAO user, VKCUserDAO permissionUser,
            boolean changeACL, boolean readCategory, boolean writeCategory,
            boolean deleteDocuments, boolean deleteCategory,
            boolean createSubcategory) throws VKCExternalException {
        if (user.isAuthorized()) {
            addUserPermission(user.getIntUser(), permissionUser, changeACL, readCategory,
                    writeCategory, deleteDocuments, deleteCategory,
                    createSubcategory);
        }
    }

    /**
	 * Ergänzt die Zugriffsberechtigungen für den übergebenen Benutzer. Bereits
	 * gesetzte Rechte werden überschrieben.
	 * 
	 * @param user
	 * @param permissionUser
	 *            Benutzer, dem Rechte an dieser Kategorie gegeben werden.
	 * @param changeACL
	 * @param readCategory
	 * @param writeCategory
	 * @param deleteDocuments
	 * @param deleteCategory
	 * @param createSubcategory
     * @throws VKCExternalException 
	 */
	private void addUserPermission(VKCUser user, VKCUserDAO permissionUser,
			boolean changeACL, boolean readCategory, boolean writeCategory,
			boolean deleteDocuments, boolean deleteCategory,
			boolean createSubcategory) throws VKCExternalException {

		try {
			// falls der Benutzer die Rechte zur Änderung des ACL hat
			if (PermissionManager.hasPermission(VKCAclSerializer
					.getAclByCategoryId(this.getCategoryId()), user, 'c')) {
				// falls der Eintrag für zu ändernden Benutzer schon forhanden
				// ist ---> löschen
				if (this.internalCategory.getAcl().hasUserEntry(
						permissionUser.getIntUser()))
					internalCategory.getAcl().deleteAclEntry(
							VKCAclType.USER_TYPE, permissionUser.getUserId());

				Map permissions = VKCPermissionSerializer
						.getPermissions(VKCPermission.CONTEXT_CATEGORY);				
				VKCAclType aclt = (VKCAclType) VKCAclTypeSerializer.retrieveAclTypes().get( "user" );

				if (changeACL) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("c");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(permissionUser.getUserId()));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
				if (readCategory) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("r");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(permissionUser.getUserId()));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
				if (writeCategory) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("w");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(permissionUser.getUserId()));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
				if (deleteDocuments) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("d");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(permissionUser.getUserId()));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
				if (createSubcategory) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("C");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(permissionUser.getUserId()));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
				if (deleteCategory) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("D");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(permissionUser.getUserId()));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
			} else {
				throw new VKCExternalException(
						VKCExternalException.CHANGE_ACL_PERMISSION_FAILED);
			}
		} catch (DBException e) {
			e.printStackTrace();
		}

	}

    /**
	 * Ergänzt die Zugriffsberechtigungen für die übergebenen Gruppe. Bereits
	 * gesetzte Rechte werden überschrieben.
	 * 
	 * @param session
	 * @param permissionGroup
	 *            Gruppe, der Rechte an dieser Kategorie gegeben werden.
	 * @param changeACL
	 * @param readCategory
	 * @param writeCategory
	 * @param deleteDocuments
	 * @param deleteCategory
	 * @param createSubcategory
     * @throws VKCExternalException 
	 */
    public void addGroupPermission(HttpSession session,
            VKCGroupDAO permissionGroup, boolean changeACL,
            boolean readCategory, boolean writeCategory,
            boolean deleteDocuments, boolean deleteCategory,
            boolean createSubcategory) throws VKCExternalException {
        addGroupPermission((VKCUser) session.getAttribute(WebShare.USER_KEY),
                permissionGroup, changeACL, readCategory, writeCategory,
                deleteDocuments, deleteCategory, createSubcategory);
    }

    /**
     * Ergänzt die Zugriffsberechtigungen für die übergebenen Gruppe. Bereits
     * gesetzte Rechte werden überschrieben.
     * 
     * @param user
     * @param permissionGroup
     *            Gruppe, der Rechte an dieser Kategorie gegeben werden.
     * @param changeACL
     * @param readCategory
     * @param writeCategory
     * @param deleteDocuments
     * @param deleteCategory
     * @param createSubcategory
     * @throws VKCExternalException 
     */
    public void addGroupPermission(VKCUserDAO user,
            VKCGroupDAO permissionGroup, boolean changeACL,
            boolean readCategory, boolean writeCategory,
            boolean deleteDocuments, boolean deleteCategory,
            boolean createSubcategory) throws VKCExternalException {
        if (user.isAuthorized()) {
            addGroupPermission(user.getIntUser(), permissionGroup, changeACL, readCategory,
                    writeCategory, deleteDocuments, deleteCategory,
                    createSubcategory);
        }
    }

    /**
	 * Ergänzt die Zugriffsberechtigungen für die übergebenen Gruppe. Bereits
	 * gesetzte Rechte werden überschrieben.
	 * 
	 * @param user
	 * @param permissionGroup
	 *            Gruppe, der Rechte an dieser Kategorie gegeben werden.
	 * @param changeACL
	 * @param readCategory
	 * @param writeCategory
	 * @param deleteDocuments
	 * @param deleteCategory
	 * @param createSubcategory
     * @throws VKCExternalException 
	 */
	private void addGroupPermission(VKCUser user, VKCGroupDAO permissionGroup,
			boolean changeACL, boolean readCategory, boolean writeCategory,
			boolean deleteDocuments, boolean deleteCategory,
			boolean createSubcategory) throws VKCExternalException {

		try {
			// falls der Benutzer die Rechte zur Änderung des ACL hat
			if (PermissionManager.hasPermission(VKCAclSerializer
					.getAclByCategoryId(this.getCategoryId()), user, 'c')) {
				// falls der Eintrag für zu ändernder Gruppe schon forhanden ist
				// ---> löschen
				if (this.internalCategory.getAcl().hasGroupEntry(
						permissionGroup.getIntGroup()))
					internalCategory.getAcl()
							.deleteAclEntry(VKCAclType.GROUP_TYPE,
									permissionGroup.getGroupId());

				Map permissions = VKCPermissionSerializer
						.getPermissions(VKCPermission.CONTEXT_CATEGORY);				
				VKCAclType aclt  = (VKCAclType) VKCAclTypeSerializer.retrieveAclTypes().get( "group" );

				if (changeACL) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("c");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(permissionGroup.getGroupId()));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
				if (readCategory) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("r");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(permissionGroup.getGroupId()));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
				if (writeCategory) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("w");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(permissionGroup.getGroupId()));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
				if (deleteDocuments) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("d");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(permissionGroup.getGroupId()));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
				if (createSubcategory) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("C");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(permissionGroup.getGroupId()));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
				if (deleteCategory) {
					VKCAclEntry ae = new VKCAclEntry();
					ae.setAclId(internalCategory.getAcl().getAclId());
					ae.setAclType(aclt);
					VKCPermission permission = (VKCPermission) permissions
							.get("D");
					ae.setPermission(permission);
					ae.setAccessorId(new Integer(permissionGroup.getGroupId()));
					ae.setCreated(new Timestamp(System.currentTimeMillis()));
					ae.setCreatorId(user.getUserId());
					try {
						this.internalCategory.getAcl().addAclEntry(ae);
					} catch (AclException e) {
						e.printStackTrace();
					}
				}
			} else {
				throw new VKCExternalException(
						VKCExternalException.CHANGE_ACL_PERMISSION_FAILED);
			}
		} catch (DBException e) {
			e.printStackTrace();
		} 

	}

    /**
	 * Entfernt alle Berechtigungen des übergebenen Benutzers.
	 * 
	 * @param session
     * @throws VKCExternalException 
	 */
    public void removePublicPermission(HttpSession session) throws VKCExternalException {
        removePublicPermission((VKCUser) session
                .getAttribute(WebShare.USER_KEY));
    }

    /**
     * Entfernt alle Berechtigungen für die Öffentlichkeit.
     * 
     * @param user
     * @throws VKCExternalException 
     */
    public void removePublicPermission(VKCUserDAO user) throws VKCExternalException {
        if (user.isAuthorized()) {
            removePublicPermission(user.getIntUser());
        }
    }

    /**
	 * Entfernt alle Berechtigungen für die Öffentlichkeit.
	 * 
	 * @param user
     * @throws VKCExternalException 
	 */
	private void removePublicPermission(VKCUser user) throws VKCExternalException {
		try {
			if (PermissionManager.hasPermission(VKCAclSerializer
					.getAclByCategoryId(this.getCategoryId()), user, 'c')) {
				// falls der Eintrag für public forhanden ist ---> löschen
				if (this.internalCategory.getAcl().hasPublicEntry()) {
					internalCategory.getAcl().deleteAclEntry(
							VKCAclType.ANYOTHER_TYPE, 0);
				}
			} else {
				throw new VKCExternalException(
						VKCExternalException.CHANGE_ACL_PERMISSION_FAILED);
			}
		} catch (DBException e) {
			e.printStackTrace();
		}
	}
    
    /**
	 * Entfernt alle Berechtigungen für die Öffentlichkeit.
	 * 
	 * @param session
	 * @param permissionUser
	 *            Benutzer dessen Rechte entfernt werden sollen.
     * @throws VKCExternalException 
	 */
    public void removeUserPermission(HttpSession session,
            VKCUserDAO permissionUser) throws VKCExternalException {
        removeUserPermission((VKCUser) session.getAttribute(WebShare.USER_KEY),
                permissionUser);
    }

    /**
     * Entfernt alle Berechtigungen des übergebenen Benutzers.
     * 
     * @param user
     * @param permissionUser
     *            Benutzer dessen Rechte entfernt werden sollen.
     * @throws VKCExternalException 
     */
    public void removeUserPermission(VKCUserDAO user, VKCUserDAO permissionUser) throws VKCExternalException {
        if (user.isAuthorized()) {
            removeUserPermission(user.getIntUser(), permissionUser);
        }
    }

    /**
	 * Entfernt alle Berechtigungen des übergebenen Benutzers.
	 * 
	 * @param user
	 * @param permissionUser
	 *            Benutzer dessen Rechte entfernt werden sollen.
     * @throws VKCExternalException 
	 */
	private void removeUserPermission(VKCUser user, VKCUserDAO permissionUser) throws VKCExternalException {
		try {
			if (PermissionManager.hasPermission(VKCAclSerializer
					.getAclByCategoryId(this.getCategoryId()), user, 'c')) {
				// falls der Eintrag für public forhanden ist ---> löschen
				if (this.internalCategory.getAcl().hasUserEntry(
						permissionUser.getIntUser())) {
					internalCategory.getAcl().deleteAclEntry(
							VKCAclType.USER_TYPE, permissionUser.getUserId());
				}
			} else {
				throw new VKCExternalException(
						VKCExternalException.CHANGE_ACL_PERMISSION_FAILED);
			}
		} catch (DBException e) {
			e.printStackTrace();
		} 
	}

    /**
	 * Entfernt alle Berechtigungen der übergebenen Gruppe.
	 * 
	 * @param session
	 * @param permissionGroup
	 *            Gruppe deren Rechte entfernt werden sollen.
     * @throws VKCExternalException 
	 */
    public void removeGroupPermission(HttpSession session,
            VKCGroupDAO permissionGroup) throws VKCExternalException {
        removeGroupPermission(
                (VKCUser) session.getAttribute(WebShare.USER_KEY),
                permissionGroup);
    }

    /**
     * Entfernt alle Berechtigungen der übergebenen Gruppe.
     * 
     * @param user
     * @param permissionGroup
     *            Gruppe deren Rechte entfernt werden sollen.
     * @throws VKCExternalException 
     */
    public void removeGroupPermission(VKCUserDAO user,
            VKCGroupDAO permissionGroup) throws VKCExternalException {
        if (user.isAuthorized()) {
            removeGroupPermission(user.getIntUser(), permissionGroup);
        }
    }

    /**
	 * Entfernt alle Berechtigungen der übergebenen Gruppe.
	 * @param user
	 * @param permissionGroup Gruppe deren Rechte entfernt werden sollen.
     * @throws VKCExternalException 
	 */
	private void removeGroupPermission(VKCUser user, VKCGroupDAO permissionGroup) throws VKCExternalException {
		try {
			if (PermissionManager.hasPermission(VKCAclSerializer
					.getAclByCategoryId(this.getCategoryId()), user, 'c')) {
				//falls der Eintrag für diese Gruppe forhanden ist ---> löschen
				if (this.internalCategory.getAcl().hasGroupEntry(
						permissionGroup.getIntGroup())) {
					internalCategory.getAcl()
							.deleteAclEntry(VKCAclType.GROUP_TYPE,
									permissionGroup.getGroupId());
				}
			} else {
				throw new VKCExternalException(
						VKCExternalException.CHANGE_ACL_PERMISSION_FAILED);
			}
		} catch (DBException e) {
			e.printStackTrace();
		}
	}

    public void setDescription(String s) {
        internalCategory.setDescription(s);
    }

    public void setKeywordsByString(String keys) {
        internalCategory.setKeywordsByString(keys);
    }

    public void setName(String s) {
        internalCategory.setName(s);
    }

    public String getCategoryLink() {
        return internalCategory.getCategoryLink();
    }

    public Date getCreated() {
        return internalCategory.getCreated();
    }

    public Integer getCreatorId() {
        return internalCategory.getCreatorId();
    }

    public String getKeywordsAsString() {
        return internalCategory.getKeywordsAsString();
    }

    public Date getLastAccessed() {
        return internalCategory.getLastAccessed();
    }

    public Integer getLastAccessorId() {
        return internalCategory.getLastAccessorId();
    }

    public Date getLastChanged() {
        return internalCategory.getLastChanged();
    }

    public Integer getLastChangerId() {
        return internalCategory.getLastChangerId();
    }
}
