/*
 * $Id: NewDocumentAction.java,v 1.63 2007/06/29 13:40:21 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: NewDocumentAction.java,v $
 * Revision 1.63  2007/06/29 13:40:21  marbobo
 * + Bugfix (Vermeiden von doppel Benachrichtigungen)
 *
 * Revision 1.62  2006/10/04 03:14:34  marbobo
 * + Vollständige Unterstützung für Templates implementiert
 * + Alles von Virtoweb auf ProCoBa umgestellt
 *
 * Revision 1.61  2006/09/21 11:19:42  marbobo
 * + Bugfix (NPE)
 *
 * Revision 1.60  2006/09/04 13:45:49  marbobo
 * + Bei neuer Version altes Autornamen als Standard-Wert nehmen
 *
 * Revision 1.59  2006/08/01 20:58:51  marbobo
 * + Navigiertes Dokument-Hervorheben für alternative Kategoriesicht, Projektsicht und Funktionssicht implementiert
 *
 * Revision 1.58  2006/07/17 14:16:08  lawern
 * Umstellung der Schlagwort- und Summary-Extraktion auf TFIDF-Gewichtung.
 *
 * Revision 1.57  2006/07/17 13:04:02  lawern
 * Neuer typografiegewichteter Index und k-NN-Klassifikation aus meiner Diss.
 *
 * Revision 1.56  2006/05/31 14:55:00  marbobo
 * + Bugfix
 *
 * Revision 1.55  2006/05/31 14:00:32  marbobo
 * + Zeilenumbrüche bei Beschreibungsfelder anzeigen
 *
 * Revision 1.54  2006/05/24 17:57:49  marbobo
 * + Toolbar des Html-Editors kann optional angezeigt oder verborgen werden
 *
 * Revision 1.53  2005/09/14 00:54:25  marbobo
 * + Url für Webkopien korrigiert
 *
 * Revision 1.52  2005/09/04 23:20:10  marbobo
 * + Neues Metadaten-Attribute (Erstellungsdatum) für Dokumente hinzugefügt
 *
 * Revision 1.51  2005/08/30 14:34:30  jonyp
 * fixes due to changes of STATUS_.../FLAG_... from int to Integer
 *
 * Revision 1.50  2005/08/17 13:53:56  marbobo
 * + autoName in autoTitle umbenannt
 *
 * Revision 1.49  2005/08/16 08:51:27  korowa
 * Ermöglicht Abschalten der Convertergenerierung von Namen, Schlüsselwörter und Beschreibung
 *
 * Revision 1.48  2005/07/19 09:52:53  korowa
 * Bei Hinzufügen einer neuen Version Wird der Uploadtyp des Dokumentes erkannt
 *  und als InitialWert gesetzt
 *
 * Revision 1.47  2005/06/30 13:52:32  marbobo
 * + Bugfix: Referenz-Vor-Dokumente löschen
 *
 * Revision 1.46  2005/04/14 09:02:55  lawern
 * Stemming überarbeitet und erstmal ausgeschaltet.
 *
 * Revision 1.45  2005/03/21 20:26:26  marbobo
 * + DocSize auf Type Long umgestellt
 *
 * Revision 1.44  2005/03/10 14:02:44  marbobo
 * + Verwendung von WebShare.KEYWORDS_DELIMITER für die Keywords aus der Analyse
 *
 * Revision 1.43  2005/02/20 16:59:10  marbobo
 * + Beim Speichern der Entities in die Datenbank wird sichergestellt
 *    dass Unicode-Zeichen in Kodierterform (als &#xxxxx;) gespeichert werden
 *
 * Revision 1.42  2005/02/17 00:29:11  jonyp
 * set LastChanger/LastChanged to null if document is initially published
 *
 * Revision 1.41  2005/02/15 09:26:46  bigmac
 * Refactorings
 *
 * Revision 1.40  2005/02/14 14:01:52  bigmac
 * Applikationsweites CSS konfigurierbar gemacht + Refactorings
 *
 * Revision 1.39  2005/02/10 16:28:18  bigmac
 * Forwards angepasst
 *
 * Revision 1.38  2005/01/27 13:13:43  bigmac
 * Klassifikation für Notizen hinzugefügt
 *
 * Revision 1.37  2005/01/10 09:24:44  jonyp
 * added cvs log
 *
 *
 */

package vkc.view.action;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
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 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.TdfElement;
import vkc.converter.common.ConversionRequest;
import vkc.converter.common.ConversionResponse;
import vkc.converter.common.Status;
import vkc.converter.common.StreamConversionRequest;
import vkc.converter.common.UrlConversionRequest;
import vkc.db.VKCDatabase;
import vkc.db.common.ConversionStatus;
import vkc.db.entities.VKCAddAttribute;
import vkc.db.entities.VKCCategory;
import vkc.db.entities.VKCDocument;
import vkc.db.entities.VKCDocumentType;
import vkc.db.entities.VKCDynaAttribute;
import vkc.db.entities.VKCUser;
import vkc.db.serializer.VKCAddAttributeSerializer;
import vkc.db.serializer.VKCDocumentClassSerializer;
import vkc.db.serializer.VKCDocumentFormatSerializer;
import vkc.db.serializer.VKCDocumentSerializer;
import vkc.db.serializer.VKCDocumentTypeSerializer;
import vkc.exception.ConverterException;
import vkc.exception.DBException;
import vkc.misc.VKCLogManager;
import vkc.procoba.project.ProjectViewForm;
import vkc.search.Classifier;
import vkc.security.PermissionManager;
import vkc.server.ConverterProxy;
import vkc.util.DateUtils;
import vkc.util.ObjectCloner;
import vkc.util.StringUtils;
import vkc.util.VKCInputStream;
import vkc.util.VKCStringUtils;
import vkc.view.PageId;
import vkc.view.WebShare;
import vkc.view.form.BasicActionForm;
import vkc.view.form.NewDocumentForm;


/**
 * Action-Klasse für das Uploaden von Dokumenten, HTML-Verweisen und Notizen
 *
 * @author marbobo
 */
public final class NewDocumentAction extends Action {
	public static final int ANALYSER_KEYWORDS_COUNT  = 5;
    public static final int ANALYSER_SENTENCES_COUNT = 5;
    public static final int CLASSIFY_MAX_HITS        = 20;
    public static final int CLASSIFIER_KEYWORDS_COUNT = -1;

	private ActionForward DEFAULT_FORWARD =	new ActionForward("/templates/${template.name}/admin/NewDocumentTemplate.jsp");
	private ActionForward DEFAULT_FORWARD_ANCHORDYNAATTRIBUTES = new ActionForward("/templates/${template.name}/admin/NewDocumentTemplate.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 {
			NewDocumentForm form = (NewDocumentForm)f;

	        // überprüfen, ob der Benutzer die Berechtigung hat	        
			VKCCategory category = form.getCategory();
	        
			if (form.getUser().isGuestUser()
		      || !PermissionManager.hasPermission(category.getAcl(), form.getUser(), 'w')) {
	            request.setAttribute(WebShare.INFO_KEY, "vkc.info.access_denied");
	            
	            return INFO_FORWARD;
	        }

	        if (request.getParameter("action.cancel") != null) {
	        	return handleCancelAction(form, request);
			} else if (request.getParameter("action.change.uploadtype") != null) {
				return handleChangeUploadTypeAction(form, request);
			} else if (request.getParameter("action.publish") != null) {
				return handlePublishAction(form, request);
			} else if (request.getParameter("action.analyse") != null) {
				return handleAnalyseAction(form, request);
			} else if (request.getParameter("action.classify") != null) {
				return handleClassifyAction(form, request);
			} else if (request.getParameter("action.select.category") != null) {
				return handleSelectCategoryAction(form, request);
			} else if (request.getParameter("action.cancel.classify") != null) {
				return handleCancelClassifyAction(form, request);
	        } else if (request.getParameter("action.add.dynaattribute") != null) {
				return handleAddDynaAttributeAction(form, request);
			} else if (request.getParameter("action.delete.dynaattribute.x") != null &&
					   request.getParameter("action.delete.dynaattribute.y") != null) {
				return handleDeleteDynaAttributeAction(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);
    	}
    }

	protected ActionForward handleInitializeAction(NewDocumentForm form, HttpServletRequest request) throws Exception {
		// Transaktions-Token speichern um doppeltes Publizieren zu verhindern
		// ( wird in handlePublish abgefragt )
		saveToken(request);
        form.setNewDocumentArchiveId("");
        form.setNewDocumentName("");
        form.setAutoDescription(form.isAdminAutoDescription());
	    form.setAutoTitle(form.isAdminAutoTitle());
	    form.setAutoKeyword(form.isAdminAutoKeyword());
	    
        if (form.getNewDocumentPreDocId().intValue() > 0) {
            // Bei neuen Versionen ein paar Felder vorbelegen
            VKCDocument oldVersionDocument = VKCDocumentSerializer.retrieveDocument(form.getNewDocumentPreDocId());
            
            form.setNewDocumentAuthorName(oldVersionDocument.getAuthorName());
            form.setNewDocumentKeywords(oldVersionDocument.getKeywordsAsString());
            
    		String description = oldVersionDocument.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.setNewDocumentDescription(description);
            form.setNewDocumentTitle(oldVersionDocument.getTitle());
            
            if (oldVersionDocument.isNote()) {
                form.setNewDocumentUploadType("note");
            } else if (oldVersionDocument.isLink()) {
            	form.setNewDocumentUploadType("link");
            } else if (oldVersionDocument.isFile()) {
            	form.setNewDocumentUploadType("file");
            } else {
            	form.setNewDocumentUploadType("webcopy");
            }

            if (oldVersionDocument.getCreationDate() != null) {
                form.setNewDocumentCreationDate(DateUtils.getDD_MM_YYYY(oldVersionDocument.getCreationDate()));
            }
            
            if (oldVersionDocument.getExpires() != null) {
                form.setNewDocumentExpDate(DateUtils.getDD_MM_YYYY(oldVersionDocument.getExpires()));
            }
            
            form.setNewDocumentVersionDesc(oldVersionDocument.getVersionDescr());
            
            if (oldVersionDocument.getVersionHigh() != null) {
                form.setNewDocumentVersionHigh((oldVersionDocument.getVersionHigh().intValue() + 1) + "");
            }
            
            if (oldVersionDocument.getVersionLow() != null) {
                form.setNewDocumentVersionLow("");
            }

            if (oldVersionDocument.getAddAttributes() != null && !oldVersionDocument.getAddAttributes().isEmpty()) {
                for (int i = 0; i < oldVersionDocument.getAddAttributes().size(); i++) {
                    VKCAddAttribute attr = (VKCAddAttribute) oldVersionDocument.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 = oldVersionDocument.getDynaAttributes().iterator(); iter.hasNext();) {
                VKCDynaAttribute dynaAttr = (VKCDynaAttribute)iter.next();
                LabelValueBean bean = new LabelValueBean(dynaAttr.getName(), dynaAttr.getValue());
                form.getDynaAttributes().add(bean);
            }
        } else {
            List addDocAttributes = VKCAddAttributeSerializer.getAllAddDocAttributes();
            
            for (int i = 0; i < addDocAttributes.size(); i++) {
                VKCAddAttribute attr = (VKCAddAttribute)addDocAttributes.get(i);
                form.getAddDocAttributes().put("adddocattrId_" + attr.getAttrId(), attr.getDefaultValue());
            }
        }

        return DEFAULT_FORWARD;
    }

	private ActionForward handleDeleteDynaAttributeAction(NewDocumentForm form, HttpServletRequest request) {
		int index = form.getIndex().intValue();
		
		if (index >= 0 && index < form.getDynaAttributes().size()) {
			form.getDynaAttributes().remove(index);
		}

		return DEFAULT_FORWARD_ANCHORDYNAATTRIBUTES;
	}

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

    protected ActionForward handleCancelAction(NewDocumentForm form, HttpServletRequest request) {
		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.getNewDocumentPreDocId();
			
			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.getNewDocumentPreDocId();

			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.getNewDocumentPreDocId();
			} else {
				forwardURL = "/showCategory.do?categoryId=" + form.getCategoryId() + "&anchor=doc" + form.getNewDocumentPreDocId();
			}

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

	protected ActionForward handleSelectCategoryAction(NewDocumentForm form, HttpServletRequest request) throws Exception {
		if (form.getSelectedId().intValue() > 0) {
			form.setCategoryId(form.getSelectedId());
			
			return DEFAULT_FORWARD;
		}

		ActionErrors errors = new ActionErrors();
		errors.add("error", new ActionError("vkc.document.classify.selection.empty"));
		saveErrors(request, errors);
		
		return DEFAULT_FORWARD;
	}

	protected ActionForward handleCancelClassifyAction(NewDocumentForm form, HttpServletRequest request) {
		return DEFAULT_FORWARD;
	}

	protected ActionForward handleChangeUploadTypeAction(NewDocumentForm form, HttpServletRequest request) throws Exception {
		form.setNewDocumentArchiveId("");
		form.setNewDocumentName("");
		form.setNewDocumentFormFile(null);

		return DEFAULT_FORWARD;
	}

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

		try {
			if (form.isFileUpload()) {
				VKCDocumentType type = VKCDocumentTypeSerializer.getDocumentTypeByExtension(form.getNewDocumentExtension());
				
				if (type == null || !type.isConvertible()) {
					errors.add("action.error", new ActionError("vkc.document.analyse.not.possible"));
					
					return DEFAULT_FORWARD;
				}
			}
			
			String convRespString = form.getConversionResponse();
			
			ConversionResponse response = (convRespString != null && convRespString.trim().length() > 0)
					? (ConversionResponse)ObjectCloner.toObject(convRespString)
					: new ConverterProxy().convert(createConversionRequest(form));
					
			if (response == null) {
				errors.add("action.error", new ActionError("vkc.document.analyse_failed"));
				
				return DEFAULT_FORWARD;
			} else if (response.getStatus().equals(Status.FAILED)) {
				errors.add("action.error", new ActionError("vkc.document.analyse_failed"));
				
				return DEFAULT_FORWARD;
			}
				
			if (convRespString == null || convRespString.trim().length() == 0) {
				form.setConversionResponse(ObjectCloner.toString(response));	
			}
					
			Collection tdfElements = response.getTdfElements();
			Analyser analyser = Analyser.createAnalyser(tdfElements, false);

			// Titel ggfs. setzen
			if (form.isAutoTitle()) {
				if (form.getNewDocumentTitle().length() == 0) {
					form.setNewDocumentTitle(response.getTitle());
				}
			}
			
			// Keywords ggfs. setzen
			if (form.isAutoKeyword()) {
				if (form.getNewDocumentKeywords().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.setNewDocumentKeywords(keys);
				}
			}
			
			// Beschreibung ggfs. setzen
			if (form.isAutoDescription()) {
				if (form.getNewDocumentDescription().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.setNewDocumentDescription(description.toString());
				}
			}				
		} catch (ConverterException ex) {
			VKCLogManager.errorLog(this, "", ex.getMessage(), ex);
			errors.add("action.error", new ActionError(ex.getMessageKey()));
		} 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;
	}

	protected ActionForward handleClassifyAction(NewDocumentForm form, HttpServletRequest request) throws Exception {
		ActionErrors errors = new ActionErrors();

        try {
    		if (form.isNoteUpload()) {
				String text = StringUtils.normalize(
								  form.getNewDocumentDescription() + " " +
					  			  form.getNewDocumentTitle() + " " +
								  form.getNewDocumentKeywords());

    			if (StringUtils.isEmpty(text)) {
	                errors.add("action.error", new ActionError("vkc.document.classify.note.input"));
	                
	                return DEFAULT_FORWARD;
    			}

                VKCCategory category = form.getClassifyFromCategory() ? form.getCategory() : null;

				TdfElement tdfElement = new TdfElement(text, 1, true, true);
				ArrayList list = new ArrayList();
				list.add(tdfElement);

                Analyser analyser = Analyser.createAnalyser(list);
				Collection results = WebShare.classifier.classify(
						analyser.getKeyWords(CLASSIFIER_KEYWORDS_COUNT),
                        analyser.getLangPackId().intValue(),
						Classifier.RANGE_NO_LIMIT,
						form.getUser(),
						category,
						CLASSIFY_MAX_HITS);

				if ((results == null) || (results.size() == 0)) {
					errors.add("action.error", new ActionError("vkc.document.no.categories.found"));
				}

	            form.setClassifyResults(results);
    		} else {
            	if (form.isFileUpload()) {
    				VKCDocumentType type = VKCDocumentTypeSerializer.getDocumentTypeByExtension(form.getNewDocumentExtension());
    				
    				if (type == null || !type.isConvertible()) {
    					errors.add("action.error", new ActionError("vkc.document.classify.not.possible"));
    					
    					return DEFAULT_FORWARD;
    				}
    			}

				String convRespString = form.getConversionResponse();
	            
				ConversionResponse response = (convRespString != null && convRespString.trim().length() > 0)
							? (ConversionResponse)ObjectCloner.toObject(convRespString)
							: new ConverterProxy().convert(createConversionRequest(form));
	
	            if (response == null) {
	                errors.add("action.error", new ActionError("vkc.document.classify_failed"));
	                
	                return DEFAULT_FORWARD;
	            } else if (response.getStatus().equals(Status.FAILED)) {
	                errors.add("action.error", new ActionError("vkc.document.classify_failed"));
	                
	                return DEFAULT_FORWARD;
	            }
				
				if (convRespString == null  || convRespString.trim().length() == 0) {
					form.setConversionResponse(ObjectCloner.toString(response));	
				}

	            Collection tdfElements = response.getTdfElements();
	            Analyser analyser = Analyser.createAnalyser(tdfElements);
	
	            VKCCategory category = form.getClassifyFromCategory() ? form.getCategory() : null;

				Collection results = null;
				
				if (analyser != null) {
					results = WebShare.classifier.classify(
							analyser.getKeyWords(CLASSIFIER_KEYWORDS_COUNT),
		                    analyser.getLangPackId().intValue(),
							Classifier.RANGE_NO_LIMIT,
							form.getUser(),
							category,
							CLASSIFY_MAX_HITS);
				}

                if (results == null || results.size() == 0) {
					errors.add("action.error", new ActionError("vkc.document.no.categories.found"));
				}

	            form.setClassifyResults(results);
			}
			
            return DEFAULT_FORWARD;
        } catch (ConverterException ex) {
            VKCLogManager.errorLog(this, "", ex.getMessage(), ex);
            errors.add("action.error", new ActionError(ex.getMessageKey()));
			
            return DEFAULT_FORWARD;
        } catch (Exception ex) {
            VKCLogManager.errorLog(this, "", ex.getMessage(), ex);
            errors.add("action.error", new ActionError("vkc.document.classify_failed"));
			
            return DEFAULT_FORWARD;
        } finally {
			if (!errors.isEmpty()) {
				saveErrors(request, errors);
			}
        }
	}

	protected ActionForward handlePublishAction(NewDocumentForm form, HttpServletRequest request) throws Exception {
	    ActionErrors errors = new ActionErrors();

		if (!isTokenValid(request)) {
			// doppeltes Publizieren verhindern
			return new ActionForward(
				"/newDocument.do" +
				"?categoryId=" + form.getCategoryId() +
				"&sourePageId=" + form.getSourcePageId(),
				true);
		}

		VKCUser     user = form.getUser();
		VKCCategory category = form.getCategory();

		VKCDocument oldVersionDocument = form.getNewDocumentPreDocId().intValue() > 0
			? VKCDocumentSerializer.retrieveDocument(form.getNewDocumentPreDocId())
			: null;

		Integer documentVersion = form.getNewDocumentPreDocId().intValue() > 0
			? new Integer(oldVersionDocument.getVersionNo().intValue() + 1)
			: new Integer(1);

		Integer publisherId = form.getProxyUserId().intValue() > 0
			? form.getProxyUserId()
			: user.getUserId();

		Integer preDocId = form.getNewDocumentPreDocId().intValue() > 0
			? form.getNewDocumentPreDocId()
			: null;

		VKCDocument document = new VKCDocument();

		document.setCategoryId(category.getCategoryId());
		document.setPreDocId(preDocId);

		document.setVersionNo(documentVersion);
        document.setVersionDescr(VKCStringUtils.filterUnicodeChars(form.getNewDocumentVersionDesc()));

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

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

        document.setCreationDate(form.getCreationDate());
		document.setPublished(form.getPublishingDate());
        document.setExpires(form.getExpirationDate());
		document.setLastAccessed(null);
		document.setLastAccessorId(null);
		document.setLastChanged(null);
		document.setLastChangerId(null);
		
		document.setStatus(form.getNewDocumentStatus());

        document.setPublisherId(publisherId);
        document.setAuthorName(VKCStringUtils.filterUnicodeChars(form.getNewDocumentAuthorName()));
		document.setTitle(VKCStringUtils.filterUnicodeChars(form.getNewDocumentTitle()));
		
		String description = VKCStringUtils.filterUnicodeChars(form.getNewDocumentDescription());
		
		if (!form.isTinyMCECompatible()) {
			description = VKCStringUtils.decodeXmlEntities(description);
			description = VKCStringUtils.encodeNamedXmlEntities(description);
		}
		
		document.setDescription(description);
		document.setKeywordsByString(VKCStringUtils.filterUnicodeChars(form.getNewDocumentKeywords()));
        
		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 (form.isNoteUpload()) {
			document.setName("");
			document.setArchiveId("0");
			document.setDocSize(new Long(0));
            document.setZipped(new Integer(0));
			document.setDocumentType(VKCDocumentTypeSerializer.getDocumentTypeByExtension("NOTE"));
		} else if (form.isWebCopyUpload()) {
			document.setName(VKCStringUtils.filterUnicodeChars(form.getNewDocumentWebcopyName()));
			document.setDocSize(form.getNewDocumentSize());
			document.setArchiveId(form.getNewDocumentArchiveId());
			document.setZipped(new Integer(1));
			document.setDocumentType(getWebCopyDocType(form.getNewDocumentWebcopyName()));
		} else if (form.isLinkUpload()) {
			document.setName(VKCStringUtils.filterUnicodeChars(form.getNewDocumentName()));
			document.setDocSize(new Long(0));
            document.setZipped(new Integer(0));
			document.setDocumentType(VKCDocumentTypeSerializer.getDocumentTypeByExtension("LINK"));
			document.setArchiveId("0");
		} else {
			document.setDocumentClass(VKCDocumentClassSerializer.getDocumentClass(form.getNewDocumentClassId()));
			document.setName(VKCStringUtils.filterUnicodeChars(form.getNewDocumentName()));
			document.setArchiveId(form.getNewDocumentArchiveId());
			document.setDocSize(form.getNewDocumentSize());
			document.setDocumentType(VKCDocumentTypeSerializer.getDocumentTypeByExtension(form.getNewDocumentExtension()));
		}

		String convRespString = form.getConversionResponse();
		
		if (convRespString != null && convRespString.trim().length() == 0) {
			convRespString = null;
		} 
		
		ConversionResponse response = null;
		
		if (document.getDocumentType().isConvertible() && convRespString != null) {
			response = (ConversionResponse)ObjectCloner.toObject(convRespString);
			document.setAdditionalDocumentFormats(response.getAdditionalDocFormats());
		}

        try {
			if (form.getPublishNow()) {
			    VKCDocumentSerializer.saveDocument(document, true, true);
			} else {
			    document.setFlag(VKCDocument.FLAG_TOBEPUBLISHED);
			    VKCDocumentSerializer.saveDocument(document, false, false);
			}
			
		    if (oldVersionDocument != null) {
		        VKCDocumentSerializer.deleteCategoryDocument(oldVersionDocument.getDocumentId());
		    }

		    if (document.getDocumentType().isConvertible() && convRespString == null) {
				// Erzeugung der zusätzlichen Dokumentformate anstossen
				ConversionStatus s = new ConversionStatus();
				s.setDocumentId(document.getDocumentId());
                s.setSendmail(false);
				s.makePersistent();
			}
        } catch (DBException e) {
			// catch quota exceed message !!!
			if (VKCDatabase.QUOTA_EXCEEDED.equals(e.getMessage())) {
				errors.add("vkc.document.publish.quota.exceeded", new ActionError("vkc.document.publish.quota.exceeded", user.getQuota()));
				saveErrors(request, errors);
				
				return DEFAULT_FORWARD;
			} 

			throw new DBException(e);
        }
		
		if (response != null) {
			VKCDocumentFormatSerializer.saveAdditionalDocumentFormats(document.getDocumentId(), response.getAdditionalDocFormats());
		}
		
		// Transaktions-Token aus der Session löschen
		resetToken(request);
		form.setNewDocumentPreDocId(document.getDocumentId());
		
		return handleCancelAction(form, request);
	}

	/**
     * @param newDocumentName
     * @return
     */
    private VKCDocumentType getWebCopyDocType(String newDocumentName) {
        int lastPIndex = newDocumentName.lastIndexOf('.');
        
        if (lastPIndex > 0) {
            String ext = newDocumentName.substring(lastPIndex + 1);
            VKCDocumentType docType = VKCDocumentTypeSerializer.getDocumentTypeByExtension(ext.toUpperCase());
            
            if (docType != null) {
                return docType;
            }
        }
        
        return VKCDocumentTypeSerializer.getDocumentTypeByExtension("HTML"); 
    }

    /**
	 * Returns a conversion request according
	 * to the information on this form
	 * @return
	 * @throws IOException
	 */
	public ConversionRequest createConversionRequest(NewDocumentForm form) throws ConverterException {
		try {
			if (form.isLinkUpload() || form.isWebCopyUpload()) {
				return new UrlConversionRequest(form.getNewDocumentName());
			} 

			File file = WebShare.archive.getFile(form.getNewDocumentArchiveId());
			InputStream fileIn = new BufferedInputStream(new FileInputStream(file));
			VKCInputStream fileIs = new VKCInputStream(fileIn, file.length());

			VKCDocumentType docType = VKCDocumentTypeSerializer.getDocumentTypeByExtension(form.getNewDocumentExtension());
			
			return new StreamConversionRequest(fileIs, docType.getDocTypeId().intValue());
		} catch (Exception e) {
			VKCLogManager.errorLog(this, "", e.getMessage(), e);
			throw new ConverterException(e.getLocalizedMessage(), "vkc.converter.error.general");
		}
	}
}