/*
 * $Id: EditDocumentAction.java,v 1.38 2006/10/04 03:14:31 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: EditDocumentAction.java,v $
 * Revision 1.38  2006/10/04 03:14:31  marbobo
 * + Vollständige Unterstützung für Templates implementiert
 * + Alles von Virtoweb auf ProCoBa umgestellt
 *
 * Revision 1.37  2006/08/01 20:58:51  marbobo
 * + Navigiertes Dokument-Hervorheben für alternative Kategoriesicht, Projektsicht und Funktionssicht implementiert
 *
 * Revision 1.36  2006/07/17 14:16:08  lawern
 * Umstellung der Schlagwort- und Summary-Extraktion auf TFIDF-Gewichtung.
 *
 * Revision 1.35  2006/05/31 14:55:01  marbobo
 * + Bugfix
 *
 * Revision 1.34  2006/05/31 14:00:32  marbobo
 * + Zeilenumbrüche bei Beschreibungsfelder anzeigen
 *
 * Revision 1.33  2006/05/24 17:57:49  marbobo
 * + Toolbar des Html-Editors kann optional angezeigt oder verborgen werden
 *
 * Revision 1.32  2005/09/04 23:20:11  marbobo
 * + Neues Metadaten-Attribute (Erstellungsdatum) für Dokumente hinzugefügt
 *
 * Revision 1.31  2005/08/30 14:34:30  jonyp
 * fixes due to changes of STATUS_.../FLAG_... from int to Integer
 *
 * Revision 1.30  2005/08/17 13:53:56  marbobo
 * + autoName in autoTitle umbenannt
 *
 * Revision 1.29  2005/08/16 08:51:27  korowa
 * Ermöglicht Abschalten der Convertergenerierung von Namen, Schlüsselwörter und Beschreibung
 *
 * Revision 1.28  2005/05/04 11:33:28  marbobo
 * + Bugfix (Verfallsdatum richtig setzen)
 *
 * Revision 1.27  2005/04/14 09:02:55  lawern
 * Stemming überarbeitet und erstmal ausgeschaltet.
 *
 * Revision 1.26  2005/03/21 14:49:25  marbobo
 * + Analyse-Funktion eingebunden
 *
 * Revision 1.25  2005/02/20 16:59:11  marbobo
 * + Beim Speichern der Entities in die Datenbank wird sichergestellt
 *    dass Unicode-Zeichen in Kodierterform (als &#xxxxx;) gespeichert werden
 *
 * Revision 1.24  2005/02/14 14:01:51  bigmac
 * Applikationsweites CSS konfigurierbar gemacht + Refactorings
 *
 * Revision 1.23  2005/02/10 16:28:18  bigmac
 * Forwards angepasst
 *
 * Revision 1.22  2004/11/09 14:35:37  marbobo
 * + Umstellung von authorId auf publisherId
 * + Hinzufügen von AuthorName für Dokumente
 * + Nötwendige Änderungen betreffend AuthorName und PublisherId
 *
 * Revision 1.21  2004/11/02 21:42:29  marbobo
 * + Einige Funktionen für Gast-Benutzer gesperrt
 * + WebShare.LOGIN_PAGE mit WebShare.getLoginPage() ersetzt
 *
 * Revision 1.20  2004/10/19 19:54:27  marbobo
 * + Rechte-Überprüfung zur Anfang verlegt
 *
 * Revision 1.19  2004/10/17 20:05:27  marbobo
 * + Globale Dokumentattribute überarbeitet
 * + Publikationszeitpunkt frei wählbar
 *
 * Revision 1.18  2004/07/20 08:48:48  jonyp
 * added copyright info + cvs log
 *
 *
 */
package vkc.view.action;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.text.BadLocationException;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.util.LabelValueBean;

import vkc.analyse.Analyser;
import vkc.analyse.SummaryEntry;
import vkc.converter.DocConverter;
import vkc.converter.TdfDocConverter;
import vkc.db.entities.VKCAddAttribute;
import vkc.db.entities.VKCAdditionalDocumentFormat;
import vkc.db.entities.VKCCategory;
import vkc.db.entities.VKCDocument;
import vkc.db.entities.VKCDynaAttribute;
import vkc.db.serializer.VKCDocumentSerializer;
import vkc.exception.DBException;
import vkc.misc.VKCLogManager;
import vkc.procoba.project.ProjectViewForm;
import vkc.security.PermissionManager;
import vkc.util.DateUtils;
import vkc.util.VKCStringUtils;
import vkc.view.PageId;
import vkc.view.WebShare;
import vkc.view.form.BasicActionForm;
import vkc.view.form.EditDocumentForm;

/**
 * Action-Klasse zum editieren von Dokumenten, HTML-Verweisen und Notizen
 */
public final class EditDocumentAction extends Action {
	public static final int ANALYSER_KEYWORDS_COUNT  = 5;
    public static final int ANALYSER_SENTENCES_COUNT = 5;

	private ActionForward DEFAULT_FORWARD = new ActionForward("/templates/${template.name}/admin/EditDocumentTemplate.jsp");
	private ActionForward DEFAULT_FORWARD_ANCHORDYNAATTRIBUTES = new ActionForward("/templates/${template.name}/admin/EditDocumentTemplate.jsp?anchor=dynaattributes");
    
    private ActionForward INFO_FORWARD = new ActionForward("/templates/${template.name}/common/InfoPage.jsp");

    public final ActionForward execute(ActionMapping mapping, 
    								   ActionForm f,
        							   HttpServletRequest request, 
        							   HttpServletResponse response)
    throws ServletException {
		try {
            EditDocumentForm form = (EditDocumentForm)f;

            if (form.getUser().isGuestUser()
              || !PermissionManager.hasPermission(form.getDocumentCategory().getAcl(), form.getUser(), 'w')) {
                request.setAttribute(WebShare.INFO_KEY, "vkc.info.access_denied");
                
                return INFO_FORWARD;
            }

	        if (request.getParameter("action.save") != null) {
	            return handleSaveAction(form, request);
            } else if (request.getParameter("action.analyse") != null) {
                return handleAnalyseAction(form, request);
            } else if (request.getParameter("action.cancel") != null) {
                return handleCancelAction(form, request);
            } else if (request.getParameter("action.add.dynaattribute") != null) {
                return handleAddDynAttributeAction(form, request);
            } else if (request.getParameter("action.delete.dynaattribute.x") != null) {
                return handleDeleteDynAttributeAction(form, request);
	        } else if (request.getParameter("action.toggle.tinymcetoolbar") != null) {
				return DEFAULT_FORWARD;
			} else {
                return handleInitializeAction(form, request);
	        }
		} catch (Exception ex) {
			throw new ServletException(ex);
		}
    }

    private ActionForward handleInitializeAction(EditDocumentForm form, HttpServletRequest request) throws DBException, BadLocationException {
        ActionErrors errors = new ActionErrors();
        VKCDocument document = form.getDocument();
        form.setAutoDescription(form.isAdminAutoDescription());
	    form.setAutoTitle(form.isAdminAutoTitle());
	    form.setAutoKeyword(form.isAdminAutoKeyword());
        
        if (document == null) {
            errors.add("document", new ActionError("edit.document.error.not.found", form.getDocumentId()));
            saveErrors(request, errors);
            
            return DEFAULT_FORWARD;
        }

        VKCCategory category = form.getDocumentCategory();
        
        if (category == null) {
            errors.add("document", new ActionError("edit.document.category.not.found", form.getDocumentId()));
            saveErrors(request, errors);
            
            return DEFAULT_FORWARD;
        }

        form.setDocumentAuthorName(document.getAuthorName());
        form.setDocumentTitle(document.getTitle());
        form.setDocumentKeywords(document.getKeywordsAsString());

		String description = document.getDescription();

		if (!form.isTinyMCECompatible()) {
			description = VKCStringUtils.filterUnicodeChars(description);
			description = VKCStringUtils.htmlFormatedText(description);
			description = VKCStringUtils.decodeXmlEntities(description);
			description = VKCStringUtils.decodeNamedXmlEntitiesNotInSwing(description);
			description = VKCStringUtils.encodeNewLine(description);
			description = VKCStringUtils.removeHtmlTags(description);
			description = VKCStringUtils.decodeNewLine(description);
		} else {
			description = VKCStringUtils.convertNewLineInHTML(description);
		}

        form.setDocumentDescription(description);
        form.setDocumentClassId(document.getDocClassId());
        form.setDocumentStatus(document.getStatus());
        form.setVersionDescription(document.getVersionDescr());
        form.setVersionHigh(document.getVersionHigh().toString());
        form.setVersionLow(document.getVersionLow().toString());

        if (document.getExpires() != null) {
            form.setExpirationDate(DateUtils.getDD_MM_YYYY(document.getExpires()));
        }
        
        if (document.getCreationDate() != null) {
            form.setCreationDate(DateUtils.getDD_MM_YYYY(document.getCreationDate()));
        }
        
        if (VKCDocument.FLAG_TOBEPUBLISHED.equals(document.getFlag())) {
            form.setPublishingDate(DateUtils.getDD_MM_YYYY(document.getPublished()));
        }

        if (document.getAddAttributes() != null && !document.getAddAttributes().isEmpty()) {
            for (int i = 0; i < document.getAddAttributes().size(); i++) {
                VKCAddAttribute attr = (VKCAddAttribute) document.getAddAttributes().get(i);
                
                if (BasicActionForm.isEmpty(attr.getValuestring())) {
                    form.getAddDocAttributes().put("adddocattrId_" + attr.getAttrId(), attr.getDefaultValue());
                } else {
                    form.getAddDocAttributes().put("adddocattrId_" + attr.getAttrId(), attr.getValuestring());
                }
            }
        }

        for (Iterator iter = document.getDynaAttributes().iterator(); iter.hasNext();) {
            VKCDynaAttribute dynaAttr = (VKCDynaAttribute)iter.next();
            LabelValueBean bean = new LabelValueBean(dynaAttr.getName(), dynaAttr.getValue());
            form.getDynaAttributes().add(bean);
        }

        return DEFAULT_FORWARD;
    }

    private ActionForward handleSaveAction(EditDocumentForm form, HttpServletRequest request) throws DBException {
        // Und ab in die DB ...
        VKCDocument document = form.getDocument();

        // Save meta-data in db
        //document.setLastAccessed( new Date() );
		//document.setLastAccessorId( form.getUser().getUserId());
        
        document.setLastChanged(new Date());
		document.setLastChangerId(form.getUser().getUserId());

        document.setAuthorName(VKCStringUtils.filterUnicodeChars(form.getDocumentAuthorName()));
		document.setTitle(VKCStringUtils.filterUnicodeChars(form.getDocumentTitle()));
        document.setKeywordsByString(VKCStringUtils.filterUnicodeChars(form.getDocumentKeywords()));

        String description = VKCStringUtils.filterUnicodeChars(form.getDocumentDescription());
		
		if (!form.isTinyMCECompatible()) {
			description = VKCStringUtils.decodeXmlEntities(description);
			description = VKCStringUtils.encodeNamedXmlEntities(description);
		}
		
        document.setDescription(description);

        if (form.getDocumentClassId() != null) {
            document.setDocClassId(form.getDocumentClassId());
        }

        if (form.getDocumentStatus() != null) {
            document.setStatus(form.getDocumentStatus());
        }

        if (!BasicActionForm.isEmpty(form.getExpirationDate())) {
            document.setExpires(DateUtils.parseDate(form.getExpirationDate()));
        } else {
            document.setExpires(null);
        }

        if (!BasicActionForm.isEmpty(form.getCreationDate())) {
            document.setCreationDate(DateUtils.parseDate(form.getCreationDate()));
        } else {
            document.setCreationDate(null);
        }

        document.setVersionDescr(VKCStringUtils.filterUnicodeChars(form.getVersionDescription()));

        if (!BasicActionForm.isEmpty(form.getVersionHigh())) {
            document.setVersionHigh(new Integer(form.getVersionHigh()));
        }

        if (!BasicActionForm.isEmpty(form.getVersionLow())) {
            document.setVersionLow(new Integer(form.getVersionLow()));
        }

        Iterator it = form.getAllAddDocAttributes().keySet().iterator();
        
        while (it.hasNext()) {
            String key = (String)it.next();
            VKCAddAttribute attr = (VKCAddAttribute)form.getAllAddDocAttributes().get(key);
            attr.setValuestring(VKCStringUtils.filterUnicodeChars((String)form.getAddDocAttributeValue(key)));
        }
        
        document.setAddAttributes(new Vector(form.getAllAddDocAttributes().values()));

        List dynaAttributes = new ArrayList();
        
        for (int i = 0; i < form.getDynaAttributes().size(); i++) {
            LabelValueBean bean = ( LabelValueBean )form.getDynaAttributes().get(i);
            VKCDynaAttribute dynaAttr = new VKCDynaAttribute();
            dynaAttr.setName(VKCStringUtils.filterUnicodeChars(bean.getLabel()));
            dynaAttr.setValue(VKCStringUtils.filterUnicodeChars(bean.getValue()));
            dynaAttributes.add(dynaAttr);
        }
		
        document.setDynaAttributes(dynaAttributes);

        if (!VKCDocument.FLAG_TOBEPUBLISHED.equals(document.getFlag())) {
            VKCDocumentSerializer.saveDocument(document, true, false);
        } else if (form.getPublishNow()) {
            document.setPublished(form.getPublishingDateObject());
            document.setFlag(VKCDocument.FLAG_PUBLISHED);
            VKCDocumentSerializer.saveDocument(document, true, false);
        } else {
            document.setPublished(form.getPublishingDateObject());
            VKCDocumentSerializer.saveDocument(document, false, false);
        }

		return handleCancelAction(form, request);
    }

    private ActionForward handleCancelAction(EditDocumentForm form, HttpServletRequest request) throws DBException {
    	VKCCategory category = form.getDocumentCategory();
    	String forwardURL = "";
    	
    	if (form.getSourcePageId().equals(PageId.PROJECT_VIEW)) {
			forwardURL = "/projectView.do?viewMode=" + ProjectViewForm.VIEW_MODE_FOLDER + "&projectId=" + form.getTargetId() + "&subfolderId=" + form.getSubTargetId() + "&anchor=doc" + form.getDocumentId();
			
			return new ActionForward(forwardURL, true);
    	} else if (form.getSourcePageId().equals(PageId.FUNCTIONAL_VIEW)) {
			forwardURL = "/functionalView.do?functionalViewId=" + form.getTargetId() + "&subfolderId=" + form.getSubTargetId() + "&anchor=doc" + form.getDocumentId();

			return new ActionForward(forwardURL, true);
		} else if (form.getSourcePageId().equals(PageId.CATEGORY_VIEW)) {
			if (form.getTargetId() != null) {
				forwardURL = "/showCategory.do?categoryId=" + form.getTargetId() + "&anchor=doc" + form.getDocumentId();
			} else {
				forwardURL = "/showCategory.do?categoryId=" + category.getCategoryId() + "&anchor=doc" + form.getDocumentId();
			}

			return new ActionForward(forwardURL, true);
		} else {
			return new ActionForward("/showCategory.do?categoryId=" + VKCCategory.ROOT_CATEGORY_ID, true);
		}
    }

    private ActionForward handleAddDynAttributeAction(EditDocumentForm form, HttpServletRequest request) {
        form.getDynaAttributes().add(new LabelValueBean("", ""));
        
        return DEFAULT_FORWARD_ANCHORDYNAATTRIBUTES;
    }

    private ActionForward handleDeleteDynAttributeAction(EditDocumentForm form, HttpServletRequest request) {
        int index = form.getSelectedIndex().intValue();

        if (index >= 0 && index < form.getDynaAttributes().size()) {
            form.getDynaAttributes().remove(index);
        }
        
        return DEFAULT_FORWARD_ANCHORDYNAATTRIBUTES;
    }

	protected ActionForward handleAnalyseAction(EditDocumentForm form, HttpServletRequest request) {
		ActionErrors errors = new ActionErrors();

		try {
			VKCDocument document = form.getDocument();
			
			if (document == null || !document.getDocumentType().isConvertible()) {
				errors.add("action.error", new ActionError("vkc.document.analyse.not.possible"));
				
				return DEFAULT_FORWARD;
			}
			
            TdfDocConverter tdf = null;
            Collection addDocFormats = document.getAdditionalDocumentFormats();

            if (addDocFormats != null) {
                for (Iterator it = addDocFormats.iterator(); it.hasNext();) {
                    VKCAdditionalDocumentFormat actDocForm = (VKCAdditionalDocumentFormat) it.next();

                    if (actDocForm.getDocTypeId().intValue() == DocConverter.tdf) {
                        //TDF-Format gefunden, Reader holen
                        tdf = new TdfDocConverter();
                        tdf.convert(actDocForm.getInputStream(), null);
                        
                        break;
                    }
                }
            }

			if (tdf == null) {
				errors.add("action.error", new ActionError("vkc.document.analyse_failed"));

				return DEFAULT_FORWARD;
			}
            
			Collection tdfElements = tdf.getElements();
			Analyser analyser = Analyser.createAnalyser(tdfElements, false);
//			 Titel ggfs. setzen
			if (form.isAutoTitle()) {
				if (form.getDocumentTitle().length() == 0) {
					form.setDocumentTitle(tdf.getTitle());
				}
			}
//			 Keywords ggfs. setzen
			if (form.isAutoKeyword()) {
				if (form.getDocumentKeywords().length() == 0 && analyser != null) {
					// Keywords vom Analyser holen
					SummaryEntry[] keywords = analyser.getKeyWords(ANALYSER_KEYWORDS_COUNT, true);
					String keys = "";
					
					for (int i = 0; i < keywords.length; i++) {
						keys += (i > 0 ? WebShare.KEYWORDS_DELIMITER + keywords[i].getText() : keywords[i].getText());
					}
					
					form.setDocumentKeywords(keys);
				}
			}
//			 Beschreibung ggfs. setzen
			if (form.isAutoDescription()) {
				if (form.getDocumentDescription().length() == 0 && analyser != null) {
					SummaryEntry[] summary = analyser.getSummary(ANALYSER_SENTENCES_COUNT);
					StringBuffer description = new StringBuffer(ANALYSER_SENTENCES_COUNT);
	
					for (int i = 0; i < summary.length; i++) {
						if (i > 0) {
							description.append("\n");
							description.append(summary[i].getText());
						} else {
							description.append(summary[i].getText());
						}
					}
	
					form.setDocumentDescription(description.toString());
				}				
			}
		} catch (Exception ex) {
			VKCLogManager.errorLog(this, "", ex.getMessage(), ex);
			errors.add("action.error", new ActionError("vkc.document.analyse_failed"));
		} finally {
			if (!errors.isEmpty()) {
				saveErrors(request, errors);
			}
		}

		return DEFAULT_FORWARD;
	}
}