/*
ESUP-portail is a french academic project developed under the GPL (General Public License) augmented according to the following :
A binary or source file developped by ESUP-portail can be used or compiled with products under Apache license.
The official english text of the GPL can be found here : http://www.gnu.org/licenses/gpl.html .
A non official french translation can be found here : http://www.linux-France.org/article/these/gpl.html .
The different kinds of licenses governing the products developed by the Apache foundation can be found here : http://www.apache.org/licenses .
It follows that you can as well as use download contents as well modify and redistribute them provided you respect the GPL terms.
Downloading and using such contents do not provide any guaranty.
Be sure that you have well understood the terms of the license before using the contents it covers.
The ESUP-portail distribution includes the following distributions :
    * UPortal :
      software developed by JA-SIG (Java Architecture - Special Interest Group)
      You can find the license page here : http://mis105.udel.edu/ja-sig/uportal/license.html
    * CAS :
      SSO solution developed by Yale University
      You can find the project page here : http://www.yale.edu/tp/auth
    * Cocoon :
      XML framework distributed by the Apache foundation under Apache license;
      Please find the full text here : http://cocoon.apache.org/2.1/license.html
    * Mod_dav:
      A DAV module for Apache web server
      You can find the project page here : http://www.webdav.org/mod_dav
    * IMP :
      webmail from Horde application framework
      You can find the project page here : http://www.horde.org
    * …. To be completed
*/
package org.esupportail.portal.channels.CStockage.channelAction.injac.actions;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.esupportail.portal.channels.CStockage.channelAction.BufferAction;
import org.esupportail.portal.channels.CStockage.channelAction.injac.DirectoryProperties;
import org.esupportail.portal.channels.CStockage.channelAction.injac.ChannelAction;
import org.esupportail.portal.channels.CStockage.channelAction.injac.DefaultRenderXml;
import org.esupportail.portal.channels.CStockage.channelAction.injac.metadata.MetaDataConstants;
import org.esupportail.portal.channels.CStockage.channelAction.injac.metadata.MetaDataManager;
import org.esupportail.portal.channels.CStockage.channelAction.injac.metadata.parse.ParseRequiredMetaData;
import org.esupportail.portal.channels.CStockage.channelAction.injac.metadata.parse.RequiredMetaData;
import org.esupportail.portal.channels.CStockage.config.Space;
import org.esupportail.portal.channels.CStockage.exception.ApplicationException;
import org.esupportail.portal.channels.CStockage.exception.CancelException;
import org.esupportail.portal.channels.CStockage.exception.CopyException;
import org.esupportail.portal.channels.CStockage.exception.DeleteException;
import org.esupportail.portal.channels.CStockage.exception.InjacDocumentException;
import org.esupportail.portal.channels.CStockage.exception.MetadataException;
import org.esupportail.portal.channels.CStockage.exception.NoneSelectedResourceException;
import org.esupportail.portal.channels.CStockage.exception.NotAuthorizedAccessPublishedDocumentException;
import org.esupportail.portal.channels.CStockage.exception.NotAuthorizedDeleteException;
import org.esupportail.portal.channels.CStockage.exception.NotAuthorizedException;
import org.esupportail.portal.channels.CStockage.exception.NotAuthorizedModifyMetadataException;
import org.esupportail.portal.channels.CStockage.exception.NotAuthorizedUploadException;
import org.esupportail.portal.channels.CStockage.exception.NotExistsResourceException;
import org.esupportail.portal.channels.CStockage.exception.OverQuotaException;
import org.esupportail.portal.channels.CStockage.exception.PasteNotAuthorizedResourceException;
import org.esupportail.portal.channels.CStockage.exception.ServerException;
import org.esupportail.portal.channels.CStockage.exception.StillExistsException;
import org.esupportail.portal.channels.CStockage.exception.ChannelException;
import org.esupportail.portal.channels.CStockage.exception.UploadException;
import org.esupportail.portal.channels.CStockage.provider.access.ServerAccess;
import org.jasig.portal.ChannelRuntimeData;
import org.jasig.portal.MultipartDataSource;

/**
 * Id: MetadataManagerAction.java,v 1.0 27 oct. 2004
 * Copyright (c) 2004 Esup Portail (www.esup-portail.org)
 * Classes: MetadataManagerAction
 * Original Author: Yohan Colmant
 * Actions of the metadata management
 */
public class MetadataManagerAction {



	/**
	 * Logger object
	 */
	protected static final Log log = LogFactory.getLog(MetadataManagerAction.class);
	
	
	
	/**
	 * If we are editing a document form the clipboard
	 */
	public final static String EDIT_DOC_FROM_CLIPBOARD = "edit-doc-from-clipboard";

	/**
	 * If we are editing a document form the upload
	 */
	public final static String EDIT_DOC_FROM_UPLOAD = "edit-doc-from-upload";
	
	/**
	 * If we are re-editing an existing document
	 */
	public final static String EDIT_OLD_DOC = "edit-old-doc";
	
	/**
	 * If we are only setting metadata
	 */
	public final static String SET_METADATA = "set-metadata";
	
	
	
	
	/**
	 * If we are publishing a document form the clipboard
	 */
	public final static String PUBLISH_DOC_FROM_CLIPBOARD = "publish-doc-from-clipboard";

	/**
	 * If we are publishing a document form the upload
	 */
	public final static String PUBLISH_DOC_FROM_UPLOAD = "publish-doc-from-upload";
	
	/**
	 * If we are publishing a document wich have still been edited before
	 */
	public final static String PUBLISH_EDITED_DOC = "publish-edited-doc";
	
	

	/**
	 * If we are rejecting a document wich have still been edited before
	 */
	public final static String REJECT_DOC = "reject-doc";
	
	

	/**
	 * Start the upload
	 * @param runtimeData the runtime data channel object
	 * @throws ChannelException
	 */
	private static Object[] getInputStream(ChannelRuntimeData runtimeData, Space currentSpace) throws ChannelException {

		Object inputFile = runtimeData.getObjectParameter("input_file");        
				
		// if file is null
		if (inputFile == null) {
			// log
			if (log.isDebugEnabled()){
				log.debug("getInputStream"+" :: NotExistsResourceException");
			}
				
			throw new NotExistsResourceException();
		}			
			
		// get a reference to the file
		MultipartDataSource mps = (MultipartDataSource)inputFile;   	        	
		InputStream stream = null;
		String fileName = null;
		try {
			// check the file size				
			stream = mps.getInputStream();
			fileName = mps.getName();
			
			// check if it still exist

			// the file to upload to the webdav			           					
	        String cible = currentSpace.getCurrentPath()+DirectoryProperties.getResourceNameWithoutLastDot(fileName);                                            
	           
	        // check if the file still exists 
	        boolean exist = false;                       
	        exist = currentSpace.getServerAccessObject().exists(cible);
	            
	        // we check if a directory has this name
	        /*if(!cible.endsWith(("/"))){            	
	          	exist = exist || currentSpace.getServerAccessObject().exists(cible+"/");
	        }*/
	            
	        if ( exist ) {            	

	        	// log
	        	if (log.isDebugEnabled()){
	        		log.debug("getInputStream"+" :: "+fileName+" already exist");
	        	}
	        		
	            throw new StillExistsException();
	        } 
				
			// log
			if (log.isDebugEnabled()){
				log.debug("getInputStream"+" :: inputFile = "+fileName);
			}
				
				
		}
		catch(IOException e) {
			log.error("getInputStream"+" :: inputFile = "+mps.getName()+" "+e);
			throw new UploadException();		
		}			
	        
		Object[] res = new Object[2];
		res[0] = fileName;
		res[1] = stream;
		return res;
	}
	
	

	/**
	 * Generate the xml for the metadata management
	 * @param runtimeData the channel runtime data
	 * @param stylesheet the stylesheet used
	 * @param spaces the spaces list
	 * @param metadataToSet the metadata list to set
	 * @param userPortalLogin the user portal login
	 * @param userGroups the user portal groups
	 * @param currentSpace the current space
	 * @param directoryProperties the current directory properties
	 * @param buffer the buffer used for the clipboard
	 * @param currentSortType The current and default sort type for the resources
	 * @return the xml generation
	 * @throws ChannelException
	 */	
	public static StringBuffer renderXmlMetadataManager(ChannelRuntimeData runtimeData, StringBuffer stylesheet, ArrayList spaces, Vector metadatasToSet, String userPortalLogin, Vector userGroups, Space currentSpace, DirectoryProperties directoryProperties, BufferAction buffer, String currentSortType) throws ChannelException{
		return renderXmlMetadataManager(null, null, null, runtimeData, stylesheet, spaces, metadatasToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, buffer, currentSortType);
	}

	
	/**
	 * Generate the xml for the metadata management
	 * @param runtimeData the channel runtime data
	 * @param stylesheet the stylesheet used
	 * @param spaces the spaces list
	 * @param metadataToSet the metadata list to set
	 * @param userPortalLogin the user portal login
	 * @param userGroups the user portal groups
	 * @param currentSpace the current space
	 * @param directoryProperties the current directory properties
	 * @param buffer the buffer used for the clipboard
	 * @param currentSortType The current and default sort type for the resources
	 * @return the xml generation
	 * @throws ChannelException
	 */	
	private static StringBuffer renderXmlMetadataManager(String[] documentsNameParam, String documentPathParam, String actionTypeParam, ChannelRuntimeData runtimeData, StringBuffer stylesheet, ArrayList spaces, Vector metadatasToSet, String userPortalLogin, Vector userGroups, Space currentSpace, DirectoryProperties directoryProperties, BufferAction buffer, String currentSortType) throws ChannelException{
		
		try {
			
			// the document in edition properties
			String[] documentsName = null;
			if (documentsNameParam!=null)
				documentsName = documentsNameParam;
			else documentsName = runtimeData.getParameterValues("documentName");
			
			String documentPath = null;
			if (documentPathParam!=null)
				documentPath = actionTypeParam;
			else documentPath = runtimeData.getParameter("documentPath");
			
			String actionType = null;
			if (actionTypeParam!=null)
				actionType = actionTypeParam;
			else actionType = runtimeData.getParameter("actionType");
			
			// if it is the first call
			if (metadatasToSet.isEmpty()) {
			
				// if we upload
				if (actionType!=null && ( actionType.equals(EDIT_DOC_FROM_UPLOAD) || actionType.equals(PUBLISH_DOC_FROM_UPLOAD))) {
					Object[] obj = getInputStream(runtimeData, currentSpace);
					documentsName = new String[1];
					documentsName[0] = (String)obj[0];
					InputStream stream = (InputStream)obj[1];
					buffer.setInputStream(stream);
				}
				
				// we don't upload
				else {
					
					// if no known document
					if (documentsName==null || documentsName.length==0) {
				
						// get the resource choosen
						String[] files = runtimeData.getParameterValues("listeFic");

						if (files == null) {
							NoneSelectedResourceException e = new NoneSelectedResourceException();

							// log
							if (log.isDebugEnabled()){
								log.debug("renderXmlMetadataManager"+" :: NoneSelectedResourceException ");
							}
						
							throw e;
						} 
						//TODO
						/*else {
							// if there is more than one file
							if (files.length > 1) {
								TooMuchSelectedException e = new TooMuchSelectedException();

								// log
								if (log.isDebugEnabled()){
									log.debug("renderXmlMetadataManager"+" :: TooMuchSelectedException ");
								}
							
								throw e;
							}
						}*/

						// the resource
						documentsName = files;
						documentPath = currentSpace.getCurrentPath();
						actionType = SET_METADATA;
						//String fullDocumentPath = documentPath + documentName;										
					}
				}
				
				// for each document, we set the metadata
				for (int i=0; i<documentsName.length; i++) {
				
					ArrayList metadataToSet = new ArrayList();
					
					// set the metadata to set
					setMetadataToSet(runtimeData, metadataToSet, userPortalLogin, currentSpace, directoryProperties, documentsName[i], documentPath, actionType, buffer);
					
					metadatasToSet.addElement(metadataToSet);
				
					documentsName[i] = documentsName[i].replaceAll("&","&amp;");
					documentsName[i] = documentsName[i].replaceAll("\"","&#148;");
					
				}
				
				if (documentPath!=null) {
					documentPath = documentPath.replaceAll("&","&amp;");
					documentPath = documentPath.replaceAll("\"","&#148;");
				}
			}

		
			
			// if click on ok
			String submit = runtimeData.getParameter("Submit_MD");
			if (submit != null) {
				return submitMetadataManager(runtimeData, stylesheet, spaces, metadatasToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, documentsName, documentPath, actionType, buffer, currentSortType);
			}

			// if click on cancel
			String cancel = runtimeData.getParameter("Cancel_MD");
			if (cancel != null) {
				
				// if this is the last one document to edit, we return to classical interface
				if (documentsName.length==1) {
					metadatasToSet.clear();
					CancelException e = new CancelException();

					// log
					if (log.isDebugEnabled()){
						log.debug("renderXmlMetadataManager"+" :: CancelException ");
					}
					
					throw e;
				}
				
				// edit the next documents
				else {
					metadatasToSet.remove(0);
					String[] documentsNameClone = new String[documentsName.length-1];
					for (int i=1; i<documentsName.length; i++) {
						documentsNameClone[i-1] = documentsName[i];
					}
					
					stylesheet.delete(0, stylesheet.length());
					stylesheet.append("documentMetaData");
					return generateXmlForMetadataSettings(metadatasToSet, userPortalLogin, currentSpace, documentsNameClone, documentPath, actionType);	
				}
			}
			
			
			
			// generate the xml with the metadata list
			stylesheet.delete(0, stylesheet.length());
			stylesheet.append("documentMetaData");
			return generateXmlForMetadataSettings(metadatasToSet, userPortalLogin, currentSpace, documentsName, documentPath, actionType);	
		}
		catch(ChannelException e) {			
			metadatasToSet.clear();			

			// log
			if (log.isDebugEnabled()){
				log.debug("renderXmlMetadataManager"+" :: ChannelException "+e);
			}
			
			throw e;
		}
		
	}
	
	
	
	
	/**
	 * Generate the xml and submit the metadata
	 * @param runtimeData the channel runtime data
	 * @param stylesheet the stylesheet used
	 * @param spaces the spaces list
	 * @param metadataToSet the metadata list to set
	 * @param userPortalLogin the user portal login
	 * @param userGroups the user portal groups
	 * @param currentSpace the current space
	 * @param directoryProperties the current directory properties
	 * @param documentName the name of the document we want to set metadata
	 * @param documentPath the path of the document we want to set metadata
	 * @param actionType the action type. For example EDIT_NEW_DOC, ....
	 * @param buffer the buffer used for the clipboard
	 * @param currentSortType The current and default sort type for the resources
	 * @return the xml generation
	 * @throws ChannelException
	 */	
	private static StringBuffer submitMetadataManager(ChannelRuntimeData runtimeData, StringBuffer stylesheet, ArrayList spaces, Vector metadatasToSet, String userPortalLogin, Vector userGroups, Space currentSpace, DirectoryProperties directoryProperties, String[] documentsName, String documentPath, String actionType, BufferAction buffer, String currentSortType) throws ChannelException {

		ArrayList metadataToSet = (ArrayList)metadatasToSet.elementAt(0);
		String documentName = documentsName[0];
		
		// we get each metadata
		for (int i = 0; i < metadataToSet.size(); i++) {
			RequiredMetaData metadata = (RequiredMetaData) metadataToSet.get(i);

			String metadataName = metadata.getName();
			String value = runtimeData.getParameter(metadataName);

			metadata.setValue(value);
		}

		// we check if all required metadata have been set
		boolean valid = true;
		for (int i = 0; valid && i < metadataToSet.size(); i++) {

			RequiredMetaData metadata = (RequiredMetaData) metadataToSet.get(i);
			if (!metadata.isValid() && metadata.isModifiable())
				valid = false;

		}

		// if set is ok
		if (valid) {

			StringBuffer xml = null;
			
			String documentFullPath = currentSpace.getCurrentPath()+documentName;
			
			try {
			
				// if we are editing a document from the clipboard into the edition space
				if (actionType.equals(EDIT_DOC_FROM_CLIPBOARD)) {
					xml = editDocFromClipboard(stylesheet, spaces, metadataToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, documentName, documentPath, documentFullPath, buffer, currentSortType);
				}
	
				// if we are editing a document from the upload into the edition space
				else if (actionType.equals(EDIT_DOC_FROM_UPLOAD)) {
					xml = editDocFromUpload(stylesheet, spaces, metadataToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, documentName, documentPath, documentFullPath, buffer, currentSortType);
				}
	
				// it'a a publication of a new document (we don't edit it)
				else if (actionType.equals(PUBLISH_DOC_FROM_CLIPBOARD)) {
					xml = publishDocFromClipboard(stylesheet, spaces, metadataToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, documentName, documentPath, documentFullPath, buffer, currentSortType);
				}
	
				// it'a a publication of a new document (we don't edit it)
				else if (actionType.equals(PUBLISH_DOC_FROM_UPLOAD)) {
					xml = publishDocFromUpload(stylesheet, spaces, metadataToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, documentName, documentPath, documentFullPath, buffer, currentSortType);
					
				}
				
				// if we are changing metadata on an existing document
				else if (actionType.equals(SET_METADATA)) {
					xml = setMetadataOnDocument(stylesheet, spaces, metadataToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, documentFullPath, currentSortType);
				}
					
				// if we are editing an old document
				else if (actionType.equals(EDIT_OLD_DOC)) {			
					xml = editDocument(stylesheet, spaces, metadataToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, documentFullPath, currentSortType);
				}			
				
				// it'a a publication of an edited document
				else if (actionType.equals(PUBLISH_EDITED_DOC)) {					
					xml = publishDocument(stylesheet, spaces, metadataToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, documentFullPath, currentSortType);
				}
	
				// it'a a rejection of an edited document
				else if (actionType.equals(REJECT_DOC)) {			
					xml = rejectDocument(stylesheet, spaces, metadataToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, documentFullPath, currentSortType);
				}
				
				
				// if this is the last one document to edit, we return to classical interface
				if (documentsName.length==1) {
					metadatasToSet.clear();
					return xml;
				}
				
				// edit the next documents
				else {
					metadatasToSet.remove(0);
					String[] documentsNameClone = new String[documentsName.length-1];
					for (int i=1; i<documentsName.length; i++) {
						documentsNameClone[i-1] = documentsName[i];
					}
					
					stylesheet.delete(0, stylesheet.length());
					stylesheet.append("documentMetaData");
					return generateXmlForMetadataSettings(metadatasToSet, userPortalLogin, currentSpace, documentsNameClone, documentPath, actionType);	
				}
			
			}
			catch (ChannelException e) {
				metadataToSet.clear();
				throw e;
			}
			
		}
		
		// generate the xml with the metadata list
		stylesheet.delete(0, stylesheet.length());
		stylesheet.append("documentMetaData");
		return generateXmlForMetadataSettings(metadatasToSet, userPortalLogin, currentSpace, documentsName, documentPath, actionType);	
	}
	
	
	
	/**
	 * When we edit a document from the clipboard
	 * @param stylesheet
	 * @param spaces
	 * @param metadataToSet
	 * @param userPortalLogin
	 * @param userGroups
	 * @param currentSpace
	 * @param directoryProperties
	 * @param documentName
	 * @param documentPath
	 * @param documentFullPath
	 * @param buffer
	 * @param currentSortType
	 * @return
	 * @throws NotAuthorizedException
	 * @throws ApplicationException
	 * @throws NotExistsResourceException
	 * @throws DeleteException
	 * @throws NotAuthorizedDeleteException
	 * @throws CopyException
	 * @throws ServerException
	 * @throws MetadataException
	 * @throws OverQuotaException
	 * @throws NotAuthorizedUploadException
	 * @throws PasteNotAuthorizedResourceException
	 * @throws ChannelException
	 */
	private static StringBuffer editDocFromClipboard(StringBuffer stylesheet, ArrayList spaces, ArrayList metadataToSet, String userPortalLogin, Vector userGroups, Space currentSpace, DirectoryProperties directoryProperties, String documentName, String documentPath, String documentFullPath, BufferAction buffer, String currentSortType) throws NotAuthorizedException, ApplicationException, NotExistsResourceException, DeleteException, NotAuthorizedDeleteException, CopyException, ServerException, MetadataException, OverQuotaException, NotAuthorizedUploadException, PasteNotAuthorizedResourceException, ChannelException{

		ServerAccess access = currentSpace.getServerAccessObject();								

		// if the document is a file
		if (!buffer.getClipboardSpace().getServerAccessObject().isDirectory(documentName, documentPath)) {
				
			// we create a directory with the same name as the document
			String newDirectoryName = DirectoryProperties.getResourceNameWithoutLastDot(documentName);
			String newDirectoryPath = currentSpace.getCurrentPath();
			String newDirectoryFullPath = newDirectoryPath+newDirectoryName;
			
			boolean wellDone = true; 
			
			try {
				wellDone = access.createDir(newDirectoryName, newDirectoryPath);							
				
				// we put the document into the directory
				wellDone = wellDone && access.copy(documentName, documentName, buffer.getClipboardSpace(), documentPath, currentSpace.getKey(), newDirectoryFullPath+"/");							
				
				// we set the current user as the owner
				wellDone = wellDone && MetaDataManager.setUserAsDocumentOwner(currentSpace, newDirectoryFullPath, userPortalLogin);
			}
			catch(ChannelException e) {
				wellDone = false;
			}
			
			// we set metadata on document
			if (!wellDone) {
				access.delete(newDirectoryName, newDirectoryPath);
				CopyException e = new CopyException();

				// log
				if (log.isDebugEnabled()){
					log.debug("editDocFromClipboard"+" :: CopyException "+e);
				}
				
				throw e;
			}
			else {														
				return editDocument(stylesheet, spaces, metadataToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, newDirectoryFullPath, currentSortType);
			}
		}
		
		// the document is a directory
		else {
								
			// we paste the document
			boolean wellDone = access.copy(documentName, documentName, buffer.getClipboardSpace(), documentPath, currentSpace.getKey(), currentSpace.getCurrentPath());
			
			// we set the current user as the owner
			wellDone = wellDone && MetaDataManager.setUserAsDocumentOwner(currentSpace, documentFullPath, userPortalLogin);
			
			// we set metadata on document
			if (!wellDone) {
				access.delete(documentName, documentPath);
				CopyException e = new CopyException();

				// log
				if (log.isDebugEnabled()){
					log.debug("editDocFromClipboard"+" :: CopyException "+e);
				}
				
				throw e;
			}
			else {														
				return editDocument(stylesheet, spaces, metadataToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, documentFullPath, currentSortType);
			}
			
		}
	}
	
	
	/**
	 * When we edit a document from the upload
	 * @param stylesheet
	 * @param spaces
	 * @param metadataToSet
	 * @param userPortalLogin
	 * @param userGroups
	 * @param currentSpace
	 * @param directoryProperties
	 * @param documentName
	 * @param documentPath
	 * @param documentFullPath
	 * @param buffer
	 * @param currentSortType
	 * @return
	 * @throws NotAuthorizedException
	 * @throws ApplicationException
	 * @throws NotExistsResourceException
	 * @throws DeleteException
	 * @throws NotAuthorizedDeleteException
	 * @throws CopyException
	 * @throws ServerException
	 * @throws MetadataException
	 * @throws OverQuotaException
	 * @throws NotAuthorizedUploadException
	 * @throws PasteNotAuthorizedResourceException
	 * @throws ChannelException
	 */
	private static StringBuffer editDocFromUpload(StringBuffer stylesheet, ArrayList spaces, ArrayList metadataToSet, String userPortalLogin, Vector userGroups, Space currentSpace, DirectoryProperties directoryProperties, String documentName, String documentPath, String documentFullPath, BufferAction buffer, String currentSortType) throws NotAuthorizedException, ApplicationException, NotExistsResourceException, DeleteException, NotAuthorizedDeleteException, CopyException, ServerException, MetadataException, OverQuotaException, NotAuthorizedUploadException, PasteNotAuthorizedResourceException, ChannelException{

		ServerAccess access = currentSpace.getServerAccessObject();								

		// we create a directory with the same name as the document
		String newDirectoryName = DirectoryProperties.getResourceNameWithoutLastDot(documentName);
		String newDirectoryPath = currentSpace.getCurrentPath();
		String newDirectoryFullPath = newDirectoryPath+newDirectoryName;
			
		boolean wellDone = true; 
		ChannelException e = null;
		try {
			wellDone = access.createDir(newDirectoryName, newDirectoryPath);							
			
			// we put the document into the directory
			wellDone = wellDone && access.upload(documentName, buffer.getInputStream(), newDirectoryFullPath+"/");							
			
			// we set the current user as the owner
			wellDone = wellDone && MetaDataManager.setUserAsDocumentOwner(currentSpace, newDirectoryFullPath, userPortalLogin);
			
		}
		catch(ChannelException ex) {
			wellDone = false;
			e = ex;
		}
		
		// we set metadata on document
		if (!wellDone) {
			access.delete(newDirectoryName, newDirectoryPath);
			if (e == null)
				e = new UploadException();
			
			// log
			if (log.isDebugEnabled()){
				log.debug("editDocFromUpload"+" :: UploadException "+e);
			}
			
			throw e;
		}
		else {														
			return editDocument(stylesheet, spaces, metadataToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, newDirectoryFullPath, currentSortType);
		}
	}
	
	
	
	

	/**
	 * When we publish a document from the clipboard
	 * @param stylesheet
	 * @param spaces
	 * @param metadataToSet
	 * @param userPortalLogin
	 * @param userGroups
	 * @param currentSpace
	 * @param directoryProperties
	 * @param documentName
	 * @param documentPath
	 * @param documentFullPath
	 * @param buffer
	 * @param currentSortType
	 * @return
	 * @throws NotAuthorizedException
	 * @throws ApplicationException
	 * @throws NotExistsResourceException
	 * @throws DeleteException
	 * @throws NotAuthorizedDeleteException
	 * @throws CopyException
	 * @throws ServerException
	 * @throws MetadataException
	 * @throws OverQuotaException
	 * @throws NotAuthorizedUploadException
	 * @throws PasteNotAuthorizedResourceException
	 * @throws ChannelException
	 */
	private static StringBuffer publishDocFromClipboard(StringBuffer stylesheet, ArrayList spaces, ArrayList metadataToSet, String userPortalLogin, Vector userGroups, Space currentSpace, DirectoryProperties directoryProperties, String documentName, String documentPath, String documentFullPath, BufferAction buffer, String currentSortType) throws NotAuthorizedException, ApplicationException, NotExistsResourceException, DeleteException, NotAuthorizedDeleteException, CopyException, ServerException, MetadataException, OverQuotaException, NotAuthorizedUploadException, PasteNotAuthorizedResourceException, ChannelException{
		ServerAccess access = currentSpace.getServerAccessObject();								

		// if the document is a file
		if (!buffer.getClipboardSpace().getServerAccessObject().isDirectory(documentName, documentPath)) {
				
			// we create a directory with the same name as the document
			String newDirectoryName = DirectoryProperties.getResourceNameWithoutLastDot(documentName);
			String newDirectoryPath = currentSpace.getCurrentPath();
			String newDirectoryFullPath = newDirectoryPath+newDirectoryName;
			
			boolean wellDone = access.createDir(newDirectoryName, newDirectoryPath);							
			
			// we put the document into the directory
			wellDone = wellDone && access.copy(documentName, documentName, buffer.getClipboardSpace(), documentPath, currentSpace.getKey(), newDirectoryFullPath+"/");							
			
			// we set the current user as the owner
			wellDone = wellDone && MetaDataManager.setUserAsDocumentOwner(currentSpace, newDirectoryFullPath, userPortalLogin);
			
			// we set metadata on document
			if (!wellDone) {
				CopyException e = new CopyException();

				// log
				if (log.isDebugEnabled()){
					log.debug("publishDocFromClipboard"+" :: CopyException "+e);
				}
				
				throw e;
			}
			else {														
				return publishDocument(stylesheet, spaces, metadataToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, newDirectoryFullPath, currentSortType);
			}
		}
		
		// the document is a directory
		else {
								
			// we paste the document
			boolean wellDone = access.copy(documentName, documentName, buffer.getClipboardSpace(), documentPath, currentSpace.getKey(), currentSpace.getCurrentPath());
			
			// we set the current user as the owner
			wellDone = wellDone && MetaDataManager.setUserAsDocumentOwner(currentSpace, documentFullPath, userPortalLogin);
			
			// we set metadata on document
			if (!wellDone) {
				CopyException e = new CopyException();

				// log
				if (log.isDebugEnabled()){
					log.debug("publishDocFromClipboard"+" :: CopyException "+e);
				}
				
				throw e;
			}
			else {														
				return publishDocument(stylesheet, spaces, metadataToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, documentFullPath, currentSortType);
			}
			
		}
		
	}
	
	
	/**
	 * When we publish a document from the upload
	 * @param stylesheet
	 * @param spaces
	 * @param metadataToSet
	 * @param userPortalLogin
	 * @param userGroups
	 * @param currentSpace
	 * @param directoryProperties
	 * @param documentName
	 * @param documentPath
	 * @param documentFullPath
	 * @param buffer
	 * @param currentSortType
	 * @return
	 * @throws NotAuthorizedException
	 * @throws ApplicationException
	 * @throws NotExistsResourceException
	 * @throws DeleteException
	 * @throws NotAuthorizedDeleteException
	 * @throws CopyException
	 * @throws ServerException
	 * @throws MetadataException
	 * @throws OverQuotaException
	 * @throws NotAuthorizedUploadException
	 * @throws PasteNotAuthorizedResourceException
	 * @throws ChannelException
	 */
	private static StringBuffer publishDocFromUpload(StringBuffer stylesheet, ArrayList spaces, ArrayList metadataToSet, String userPortalLogin, Vector userGroups, Space currentSpace, DirectoryProperties directoryProperties, String documentName, String documentPath, String documentFullPath, BufferAction buffer, String currentSortType) throws NotAuthorizedException, ApplicationException, NotExistsResourceException, DeleteException, NotAuthorizedDeleteException, CopyException, ServerException, MetadataException, OverQuotaException, NotAuthorizedUploadException, PasteNotAuthorizedResourceException, ChannelException{
		ServerAccess access = currentSpace.getServerAccessObject();								
		
		// we create a directory with the same name as the document
		String newDirectoryName = DirectoryProperties.getResourceNameWithoutLastDot(documentName);
		String newDirectoryPath = currentSpace.getCurrentPath();
		String newDirectoryFullPath = newDirectoryPath+newDirectoryName;
		
		boolean wellDone = true; 
		ChannelException e = null;
		try {
			wellDone = access.createDir(newDirectoryName, newDirectoryPath);							
			
			// we put the document into the directory
			wellDone = wellDone && access.upload(documentName, buffer.getInputStream(), newDirectoryFullPath+"/");							
			
			// we set the current user as the owner
			wellDone = wellDone && MetaDataManager.setUserAsDocumentOwner(currentSpace, newDirectoryFullPath, userPortalLogin);
			
		}
		catch(ChannelException ex) {
			wellDone = false;
			e = ex;
		}
		
		// we set metadata on document
		if (!wellDone) {
			access.delete(newDirectoryName, newDirectoryPath);
			if (e == null)
				e = new UploadException();
			
			// log
			if (log.isDebugEnabled()){
				log.debug("publishDocFromUpload"+" :: UploadException "+e);
			}
			
			throw e;
		}
		else {														
			return publishDocument(stylesheet, spaces, metadataToSet, userPortalLogin, userGroups, currentSpace, directoryProperties, newDirectoryFullPath, currentSortType);
		}
	}
	
	
	
	
	
	/**
	 * Set the metadata list we want to set
	 * @param runtimeData the channel runtime data
	 * @param metadataToSet the metadata list to set
	 * @param userPortalLogin the user portal login
	 * @param currentSpace the current space
	 * @param directoryProperties the current directory properties
	 * @param documentName the name of the document we want to set metadata
	 * @param documentPath the path of the document we want to set metadata
	 * @param actionType the action type. For example EDIT_NEW_DOC, .... 
	 * @throws ChannelException
	 */	
	private static void setMetadataToSet(ChannelRuntimeData runtimeData, ArrayList metadataToSet, String userPortalLogin, Space currentSpace, DirectoryProperties directoryProperties, String documentName, String documentPath, String actionType, BufferAction buffer) throws ChannelException {
		
		// to know the metadata to set
		ServerAccess access = currentSpace.getServerAccessObject();
		String spacePath = currentSpace.getCurrentPath();

		// get the metadata we have to set
		ParseRequiredMetaData parse = directoryProperties.getMetadataList();
		if (parse==null) {
			String xmlMetadataToSet = MetaDataManager.getMetadataSpaceProfile(currentSpace, spacePath);
			parse = new ParseRequiredMetaData(xmlMetadataToSet);
			directoryProperties.setMetadataList(parse);
		}
			

		//boolean writerInSpace = directoryProperties.isUserWriter();
		boolean editorInSpace = directoryProperties.isUserEditor();
		
		// the document full path
		String fullDocumentPath = documentPath+documentName;		
	
		//boolean userIsOwnerOfDocument = directoryProperties.isUserWriter();//ChannelAction.isUserDocumentOwner(fullDocumentPath, access, userPortalLogin);
		boolean writer = false;
		if (actionType.equals(EDIT_DOC_FROM_UPLOAD) || actionType.equals(EDIT_DOC_FROM_CLIPBOARD) || actionType.equals(PUBLISH_DOC_FROM_UPLOAD) || actionType.equals(PUBLISH_DOC_FROM_CLIPBOARD)) {
			writer = directoryProperties.isUserWriter();
		}
		else {
			writer = directoryProperties.isUserWriter() && ChannelAction.isUserDocumentOwner(fullDocumentPath, currentSpace, userPortalLogin);
		}
		
		
		

		
		
		// if writer in space and on document
		if (writer) {
			
			// if writer and editor
			if (editorInSpace) {
				metadataToSet.clear();
				ArrayList parseResult = parse.getMetadataListEditionAndPublication();
				for (int i=0; i<parseResult.size(); i++) {
					RequiredMetaData md = (RequiredMetaData)parseResult.get(i);										
					metadataToSet.add(md);
				}
			}

			// if only writer
			else {
				metadataToSet.clear();
				ArrayList parseResult = parse.getMetadataListEdition();
				for (int i=0; i<parseResult.size(); i++) {
					metadataToSet.add(parseResult.get(i));
				}
			}
		}

		else {
			
			// if only editor
			if (editorInSpace) {
				metadataToSet.clear();
				ArrayList parseResult = parse.getMetadataListPublication();
				for (int i=0; i<parseResult.size(); i++) {
					metadataToSet.add(parseResult.get(i));
				}
			} 
			else {
				NotAuthorizedModifyMetadataException e = new NotAuthorizedModifyMetadataException();

				// log
				if (log.isDebugEnabled()){
					log.debug("setMetadataToSet"+" :: NotAuthorizedModifyMetadataException "+e);
				}
				
				throw e;
			}
			
		}
		
		
		

		// the list of files inside the document for the root-file-name metadata
		/*RequiredMetaData rootFileNameMD = new RequiredMetaData();
		rootFileNameMD.setChoicelist("a,b,c");
		rootFileNameMD.setInput(RequiredMetaData.INPUT_SELECT);
		rootFileNameMD.setLevel(RequiredMetaData.LEVEL_EDITION);
		rootFileNameMD.setModifiable(true);
		rootFileNameMD.setName(MetaDataConstants.ROOT_FILE_NAME);
		rootFileNameMD.setLabel(MetaDataConstants.ROOT_FILE_NAME);
		rootFileNameMD.setRequiredData(true);
		rootFileNameMD.setType(RequiredMetaData.TYPE_STRING);
		metadataToSet.add(rootFileNameMD);*/
		
		
		

		// if we are not editing a document, but changing metadata on an existing document
		if (actionType.equals(SET_METADATA)) {

			// the list of files inside the document for the root-file-name metadata
			RequiredMetaData rootFileNameMD = RequiredMetaData.getNewRootFileNameMetatada(currentSpace.getServerAccessObject(), documentPath, documentName, writer);			
			metadataToSet.add(rootFileNameMD);
			
			// check if this resource is an injac document			
			String type = MetaDataManager.getDirectoryType(currentSpace, fullDocumentPath);
			if (!type.equals(MetaDataConstants.INJAC_TYPE_DOCUMENT)) {				
				InjacDocumentException e = new InjacDocumentException();

				// log
				if (log.isDebugEnabled()){
					log.debug("setMetadataToSet"+" :: InjacDocumentException "+e);
				}
				
				throw e;
			}
			
			// if the document is published and we are not editor, we can't access the metadata
			String state = MetaDataManager.getDocumentState(currentSpace, fullDocumentPath);
			if (state.equals(MetaDataConstants.DOCUMENT_PUBLISHED_STATE) && !editorInSpace) {

				NotAuthorizedAccessPublishedDocumentException e = new NotAuthorizedAccessPublishedDocumentException();

				// log
				if (log.isDebugEnabled()){
					log.debug("setMetadataToSet"+" :: NotAuthorizedAccessPublishedDocumentException "+e);//TODO
				}
				
				throw e;
			}

			// if we are only writer on space, we check if we can access this document
			if (writer && !editorInSpace) {

				if (!writer) {
					
					NotAuthorizedModifyMetadataException e = new NotAuthorizedModifyMetadataException();

					// log
					if (log.isDebugEnabled()){
						log.debug("setMetadataToSet"+" :: NotAuthorizedModifyMetadataException "+e);
					}
					
					throw e;
				}

			}

			// if document state is published, we add the publication dates. if rejected, we add the reject cause
			String documentState = MetaDataManager.getDocumentState(currentSpace, fullDocumentPath);
			if (documentState.equals(MetaDataConstants.DOCUMENT_PUBLISHED_STATE) || documentState.equals(MetaDataConstants.DOCUMENT_EXPIRED_STATE)) {
				RequiredMetaData dateBegin = RequiredMetaData.getNewPublicationDateBeginMetatada();				
				RequiredMetaData dateEnd = RequiredMetaData.getNewPublicationDateEndMetatada();
				
				if (editorInSpace) {
					dateBegin.setModifiable(true);
					dateEnd.setModifiable(true);
				}
				else {
					dateBegin.setModifiable(false);
					dateEnd.setModifiable(false);
				}
				
				metadataToSet.add(dateBegin);
				metadataToSet.add(dateEnd);				
			}
			else if (documentState.equals(MetaDataConstants.DOCUMENT_REFUSED_STATE)) {
				RequiredMetaData reject = RequiredMetaData.getNewRejectCauseMetatada();
				
				if (editorInSpace) {
					reject.setModifiable(true);
					reject.setRequiredData(true);
				}
				else {
					reject.setModifiable(false);					
				}
				
				metadataToSet.add(reject);	
			}
			
			// we check if the document still has metadata set
			for (int i = 0; i < metadataToSet.size(); i++) {

				RequiredMetaData metadata = (RequiredMetaData) metadataToSet.get(i);								
				
				String metadataName = metadata.getName();
				String metadataValue = access.getProperty(currentSpace.getMetadataNamespace(), fullDocumentPath, metadataName);

				if (metadataValue==null)
					metadataValue="";												
				
				// if not modifiable and empty, we remove
				if (!metadata.isModifiable() && metadataValue.equals("")) {
					metadataToSet.remove(i);
					i--;					
				}
				else {				
					metadata.setValue(metadataValue);
				}
								
			}
		}
		
		
		// it'a an edition of an old document
		else if (actionType.equals(EDIT_OLD_DOC)) {					
			
			// the list of files inside the document for the root-file-name metadata
			RequiredMetaData rootFileNameMD = RequiredMetaData.getNewRootFileNameMetatada(currentSpace.getServerAccessObject(), documentPath, documentName, writer);			
			metadataToSet.add(rootFileNameMD);
			
			// we check if the document still has metadata set
			for (int i = 0; i < metadataToSet.size(); i++) {

				RequiredMetaData metadata = (RequiredMetaData) metadataToSet.get(i);
				
				String metadataName = metadata.getName();
				String metadataValue = access.getProperty(currentSpace.getMetadataNamespace(), fullDocumentPath, metadataName);
				
				// if not empty, we set the value
				if (metadataValue != null && !metadataValue.trim().equals("")) {
					metadata.setValue(metadataValue);
				}
				
				// if not modifiable, we remove this MD from the list 
				else if (!metadata.isModifiable()) {
					metadataToSet.remove(i);
					i--;					
				}				

			}
			
		}
		

		// it'a an edition of a document from the clipboard
		else if (actionType.equals(EDIT_DOC_FROM_CLIPBOARD)) {	

			// the list of files inside the document for the root-file-name metadata
			RequiredMetaData rootFileNameMD = RequiredMetaData.getNewRootFileNameMetatada(buffer.getClipboardSpace().getServerAccessObject(), documentPath, documentName, writer);			
			metadataToSet.add(rootFileNameMD);

			
			// we set empty the values for the non modifiable metadata
			for (int i = 0; i < metadataToSet.size(); i++) {

				RequiredMetaData metadata = (RequiredMetaData) metadataToSet.get(i);
				
				// if not modifiable, we remove it from the list
				if (!metadata.isModifiable()) {
					metadataToSet.remove(i);
					i--;					
				}				

			}
			
		}
		

		// it'a an edition of a document from the upload
		else if (actionType.equals(EDIT_DOC_FROM_UPLOAD)) {	

			
			// the list of files inside the document for the root-file-name metadata
			RequiredMetaData rootFileNameMD = RequiredMetaData.getNewRootFileNameMetatada(documentName, writer);			
			metadataToSet.add(rootFileNameMD);

			
			// we set empty the values for the non modifiable metadata
			for (int i = 0; i < metadataToSet.size(); i++) {

				RequiredMetaData metadata = (RequiredMetaData) metadataToSet.get(i);
				
				// if not modifiable, we remove it from the list
				if (!metadata.isModifiable()) {
					metadataToSet.remove(i);
					i--;					
				}				

			}
			
		}
		

		// it'a a publication of an edited document
		else if (actionType.equals(PUBLISH_EDITED_DOC)) {

			// the list of files inside the document for the root-file-name metadata
			RequiredMetaData rootFileNameMD = RequiredMetaData.getNewRootFileNameMetatada(currentSpace.getServerAccessObject(), documentPath, documentName, writer);			
			metadataToSet.add(rootFileNameMD);
			
			// we add the publication date MD 
			RequiredMetaData dateBegin = RequiredMetaData.getNewPublicationDateBeginMetatada();				
			RequiredMetaData dateEnd = RequiredMetaData.getNewPublicationDateEndMetatada();
			dateBegin.setModifiable(true);
			dateEnd.setModifiable(true);	
			metadataToSet.add(dateBegin);
			metadataToSet.add(dateEnd);	
			
			// we check if the document still has metadata set
			for (int i = 0; i < metadataToSet.size(); i++) {

				RequiredMetaData metadata = (RequiredMetaData) metadataToSet.get(i);
				
				String metadataName = metadata.getName();
				String metadataValue = access.getProperty(currentSpace.getMetadataNamespace(), fullDocumentPath, metadataName);
				
				// if not empty, we set the value
				if (metadataValue != null && !metadataValue.trim().equals("")) {
					metadata.setValue(metadataValue);
				}
				
				// if not modifiable, we remove this MD from the list 
				else if (!metadata.isModifiable()) {
					metadataToSet.remove(i);
					i--;					
				}
				
			}
			
		}
		

		// it'a a publication of a new document (we don't edit it)
		else if (actionType.equals(PUBLISH_DOC_FROM_CLIPBOARD)) {					


			// the list of files inside the document for the root-file-name metadata
			RequiredMetaData rootFileNameMD = RequiredMetaData.getNewRootFileNameMetatada(buffer.getClipboardSpace().getServerAccessObject(), documentPath, documentName, writer);			
			metadataToSet.add(rootFileNameMD);

			
			// we add the publication date MD 
			RequiredMetaData dateBegin = RequiredMetaData.getNewPublicationDateBeginMetatada();				
			RequiredMetaData dateEnd = RequiredMetaData.getNewPublicationDateEndMetatada();
			dateBegin.setModifiable(true);
			dateEnd.setModifiable(true);
			metadataToSet.add(dateBegin);
			metadataToSet.add(dateEnd);	
			
			// we set empty the values for the non modifiable metadata
			for (int i = 0; i < metadataToSet.size(); i++) {

				RequiredMetaData metadata = (RequiredMetaData) metadataToSet.get(i);
				
				// if not modifiable, we remove it from the list
				if (!metadata.isModifiable()) {
					metadataToSet.remove(i);
					i--;					
				}				
				
			}
			
		}
		
		


		// it'a a publication of a new document (we don't edit it)
		else if (actionType.equals(PUBLISH_DOC_FROM_UPLOAD)) {


			// the list of files inside the document for the root-file-name metadata
			RequiredMetaData rootFileNameMD = RequiredMetaData.getNewRootFileNameMetatada(documentName, writer);			
			metadataToSet.add(rootFileNameMD);

			
			// we add the publication date MD 
			RequiredMetaData dateBegin = RequiredMetaData.getNewPublicationDateBeginMetatada();				
			RequiredMetaData dateEnd = RequiredMetaData.getNewPublicationDateEndMetatada();
			dateBegin.setModifiable(true);
			dateEnd.setModifiable(true);
			metadataToSet.add(dateBegin);
			metadataToSet.add(dateEnd);	
			
			// we set empty the values for the non modifiable metadata
			for (int i = 0; i < metadataToSet.size(); i++) {

				RequiredMetaData metadata = (RequiredMetaData) metadataToSet.get(i);
				
				// if not modifiable, we remove it from the list
				if (!metadata.isModifiable()) {
					metadataToSet.remove(i);
					i--;					
				}				
				
			}
			
		}


		// it'a a rejection of a document
		else if (actionType.equals(REJECT_DOC)) {						


			// the list of files inside the document for the root-file-name metadata
			RequiredMetaData rootFileNameMD = RequiredMetaData.getNewRootFileNameMetatada(currentSpace.getServerAccessObject(), documentPath, documentName, writer);			
			metadataToSet.add(rootFileNameMD);
			
			
			// we add the reject cause MD 
			RequiredMetaData reject = RequiredMetaData.getNewRejectCauseMetatada();
			reject.setModifiable(true);
			reject.setRequiredData(true);
			metadataToSet.add(reject);	
			
			// we check if the document still has metadata set
			for (int i = 0; i < metadataToSet.size(); i++) {

				RequiredMetaData metadata = (RequiredMetaData) metadataToSet.get(i);
				
				String metadataName = metadata.getName();
				String metadataValue = access.getProperty(currentSpace.getMetadataNamespace(), fullDocumentPath, metadataName);
				
				// if not empty, we set the value
				if (metadataValue != null && !metadataValue.trim().equals("")) {
					metadata.setValue(metadataValue);
				}
				
				// if not modifiable, we remove this MD from the list 
				else if (!metadata.isModifiable()) {
					metadataToSet.remove(i);
					i--;					
				}
				
			}
			
		}
		
		
	}
	
	
	
	
	/**
	 * Generate the xml for the metadata setting
	 * @param metadataToSet the metadata list to set
	 * @param userPortalLogin the user portal login
	 * @param currentSpace the current space
	 * @param documentName the name of the document we want to set metadata
	 * @param documentPath the path of the document we want to set metadata
	 * @param actionType the action type. For example EDIT_NEW_DOC, ....
	 * @return the xml generation
	 */	
	private static StringBuffer generateXmlForMetadataSettings(Vector metadatasToSet, String userPortalLogin, Space currentSpace, String[] documentsName, String documentPath, String actionType) {	
		StringBuffer xml = new StringBuffer();
		
		// the final link
		String finalLink = currentSpace.getServer().getInjacFinalUrl();
		
		if (finalLink!=null) {
			if (finalLink.endsWith("/")) {
				finalLink = finalLink.substring(0, finalLink.length()-1);
			}
			String finalPath = "/";
			for (int i=1;i<currentSpace.getPathSize(); i++) {
				finalPath += currentSpace.getPathElementAt(i)+"/";
			}
			
			finalLink += finalPath;
			xml.append("<finalLink link=\""+finalLink+"\"/>");
		}
		
		// the documents we have to edit after
		xml.append("<others_documents documentPath=\""+documentPath+"\" actionType=\""+actionType+"\" >");
		for (int i=1; i<documentsName.length; i++) {
			xml.append("<document documentName=\""+documentsName[i]+"\"/>");
		}
		xml.append("</others_documents>");
		
		// the current document
		xml.append("<metas documentName=\""+documentsName[0]+"\" documentPath=\""+documentPath+"\" actionType=\""+actionType+"\" >");
		
		// the current metadatas
		ArrayList metadataToSet = (ArrayList)metadatasToSet.elementAt(0);
		
		for (int i=0; i<metadataToSet.size(); i++) {
			
			try {
			
				StringBuffer xmlTemp = new StringBuffer();
			
				RequiredMetaData metadata = (RequiredMetaData)metadataToSet.get(i);
			
				// if modifiable
				if (metadata.isModifiable()) {				
				
					// the metadata
					xmlTemp.append("<meta ");
					
					// 	the attributes
					String name = metadata.getName();
					String label = metadata.getLabel();
					String input = metadata.getInput();					
					
					if (name == null || name.trim().equals("") || label == null || label.trim().equals("") || input == null || input.trim().equals("")) {
						Exception e = new Exception();

						// log
						if (log.isDebugEnabled()){
							log.debug("generateXmlForMetadataSettings"+" :: Exception "+e);
						}
						
						throw e;					
					}
					
					xmlTemp.append("name=\""+name+"\" ");
					xmlTemp.append("label=\""+label+"\" ");
					xmlTemp.append("required=\""+metadata.isRequired()+"\" ");
					xmlTemp.append("default-value=\""+metadata.getValue()+"\" ");
					xmlTemp.append("comment=\""+metadata.getComment()+"\" ");
					
					xmlTemp.append("modifiable=\"true\" ");
					
					xmlTemp.append("input=\""+input+"\" ");
					
					if (metadata.isValid())
						xmlTemp.append("good-format=\"true\" ");
					
					xmlTemp.append(">");
			
					// test input type
					if (input.equals(RequiredMetaData.INPUT_SELECT)) {
						
						String [] choiceListArray = metadata.getChoiceList();
						for (int j=0; j<choiceListArray.length; j++) {
							xmlTemp.append("<choice value=\""+choiceListArray[j]+"\" />");
						}
						
					}			
					
					// 	close
					xmlTemp.append("</meta>");	
					
					xml.append(xmlTemp);
				
				}
				
				// not modifiable
				else {
					

					// the metadata
					xmlTemp.append("<meta ");
					
					// 	the attributes
					String name = metadata.getName();
					String label = metadata.getLabel();
					String input = metadata.getInput();					
					
					if (name == null || name.trim().equals("") || label == null || label.trim().equals("") || input == null || input.trim().equals("")) {
						Exception e = new Exception();

						// log
						if (log.isDebugEnabled()){
							log.debug("generateXmlForMetadataSettings"+" :: Exception "+e);
						}
						
						throw e;					
					}
					
					// test input type
					if (input.equals(RequiredMetaData.INPUT_SELECT)) {						
						input = RequiredMetaData.INPUT_TEXT;						
					}
					
					xmlTemp.append("name=\""+name+"\" ");
					xmlTemp.append("label=\""+label+"\" ");
					xmlTemp.append("required=\""+metadata.isRequired()+"\" ");
					xmlTemp.append("default-value=\""+metadata.getValue()+"\" ");
					xmlTemp.append("comment=\""+metadata.getComment()+"\" ");
					
					xmlTemp.append("modifiable=\"false\" ");
					
					xmlTemp.append("input=\""+input+"\" ");
					
					xmlTemp.append("good-format=\"true\" ");
					
					xmlTemp.append(">");
			
								
					
					// 	close
					xmlTemp.append("</meta>");	
					
					xml.append(xmlTemp);
									
				}
				
				
			}
			catch(Exception e) {
				metadataToSet.remove(i);
				i--;
			}
						
		}
		
		xml.append("</metas>");
		
		return xml;
		
	}
	
	
	
	
	
	
	/**
	 * Set the metadata on document and return the xml for the next action
	 * @param stylesheet the stylesheet used
	 * @param spaces the spaces list
	 * @param metadataToSet the metadata list to set
	 * @param userPortalLogin the user portal login
	 * @param userGroups the user portal groups
	 * @param currentSpace the current space
	 * @param directoryProperties the current directory properties
	 * @param documentFullPath the full path of the document we want to set metadata
	 * @param currentSortType The current and default sort type for the resources
	 * @return the xml generation
	 * @throws ServerException
	 * @throws MetadataException
	 */	
	private static StringBuffer setMetadataOnDocument(StringBuffer stylesheet, ArrayList spaces, ArrayList metadataToSet, String userPortalLogin, Vector userGroups, Space currentSpace, DirectoryProperties directoryProperties, String documentFullPath, String currentSortType) throws ServerException, MetadataException {
		
		// set the metadata on the document
		boolean wellDone = MetaDataManager.setMetadataOnDocument(currentSpace, documentFullPath, metadataToSet);
		
		if (!wellDone) {
			metadataToSet.clear();			
			MetadataException e = new MetadataException();

			// log
			if (log.isDebugEnabled()){
				log.debug("setMetadataOnDocument"+" :: MetadataException "+e);
			}
			
			throw e;
		}
		
		// return
		metadataToSet.clear();		
		stylesheet.delete(0, stylesheet.length());
		stylesheet.append("CStockage");
		return DefaultRenderXml.getXml(spaces, currentSpace, null, "2008", userPortalLogin, userGroups, directoryProperties, currentSortType);
	}
	
	
	
	

	/**
	 * Edit the document and return the xml for the next action
	 * @param stylesheet the stylesheet used
	 * @param spaces the spaces list
	 * @param metadataToSet the metadata list to set
	 * @param userPortalLogin the user portal login
	 * @param userGroups the user portal groups
	 * @param currentSpace the current space
	 * @param directoryProperties the current directory properties
	 * @param documentFullPath the full path of the document we want to set metadata
	 * @param currentSortType The current and default sort type for the resources
	 * @return the xml generation
	 * @throws ServerException
	 * @throws MetadataException
	 */
	private static StringBuffer editDocument(StringBuffer stylesheet, ArrayList spaces, ArrayList metadataToSet, String userPortalLogin, Vector userGroups, Space currentSpace, DirectoryProperties directoryProperties, String documentFullPath, String currentSortType) throws ServerException, MetadataException {
		
		// set the metadata on the document
		boolean wellDone = MetaDataManager.setMetadataOnDocument(currentSpace, documentFullPath, metadataToSet);		
		wellDone = wellDone && MetaDataManager.setDirectoryAsWaitingDocument(currentSpace, documentFullPath);
		
		if (!wellDone) {
			metadataToSet.clear();		
			MetadataException e = new MetadataException();

			// log
			if (log.isDebugEnabled()){
				log.debug("editDocument"+" :: MetadataException "+e);
			}
			
			throw e;
		}
		
		// return
		metadataToSet.clear();
		stylesheet.delete(0, stylesheet.length());
		stylesheet.append("CStockage");
		return DefaultRenderXml.getXml(spaces, currentSpace, null, "2010", userPortalLogin, userGroups, directoryProperties, currentSortType);
	}
	

	

	/**
	 * Publish the document and return the xml for the next action
	 * @param stylesheet the stylesheet used
	 * @param spaces the spaces list
	 * @param metadataToSet the metadata list to set
	 * @param userPortalLogin the user portal login
	 * @param userGroups the user portal groups
	 * @param currentSpace the current space
	 * @param directoryProperties the current directory properties
	 * @param documentFullPath the full path of the document we want to set metadata
	 * @param currentSortType The current and default sort type for the resources
	 * @return the xml generation
	 * @throws ServerException
	 * @throws MetadataException
	 */
	private static StringBuffer publishDocument(StringBuffer stylesheet, ArrayList spaces, ArrayList metadataToSet, String userPortalLogin, Vector userGroups, Space currentSpace, DirectoryProperties directoryProperties, String documentFullPath, String currentSortType) throws ServerException, MetadataException { 
		
		// set the metadata on the document
		boolean wellDone = MetaDataManager.setMetadataOnDocument(currentSpace, documentFullPath, metadataToSet);		
		wellDone = wellDone && MetaDataManager.setDirectoryAsPublishedDocument(currentSpace, documentFullPath);
		wellDone = wellDone && MetaDataManager.setRejectCause(currentSpace, documentFullPath, "");
		
		if (!wellDone) {
			metadataToSet.clear();		
			MetadataException e = new MetadataException();

			// log
			if (log.isDebugEnabled()){
				log.debug("publishDocument"+" :: MetadataException "+e);
			}
			
			throw e;
		}
		
		// return
		metadataToSet.clear();
		stylesheet.delete(0, stylesheet.length());
		stylesheet.append("CStockage");
		return DefaultRenderXml.getXml(spaces, currentSpace, null, "2011", userPortalLogin, userGroups, directoryProperties, currentSortType);
	}
	
	
	

	
	/**
	 * Reject the document and return the xml for the next action
	 * @param stylesheet the stylesheet used
	 * @param spaces the spaces list
	 * @param metadataToSet the metadata list to set
	 * @param userPortalLogin the user portal login
	 * @param userGroups the user portal groups
	 * @param currentSpace the current space
	 * @param directoryProperties the current directory properties
	 * @param documentFullPath the full path of the document we want to set metadata
	 * @param currentSortType The current and default sort type for the resources
	 * @return the xml generation
	 * @throws ServerException
	 * @throws MetadataException
	 */
	private static StringBuffer rejectDocument(StringBuffer stylesheet, ArrayList spaces, ArrayList metadataToSet, String userPortalLogin, Vector userGroups, Space currentSpace, DirectoryProperties directoryProperties, String documentFullPath, String currentSortType) throws ServerException, MetadataException { 
		
		// set the metadata on the document
		boolean wellDone = MetaDataManager.setMetadataOnDocument(currentSpace, documentFullPath, metadataToSet);		
		wellDone = wellDone && MetaDataManager.setDirectoryAsRejectedDocument(currentSpace, documentFullPath);
		wellDone = wellDone && MetaDataManager.setPublicationDateBegin(currentSpace, documentFullPath, "");
		wellDone = wellDone && MetaDataManager.setPublicationDateEnd(currentSpace, documentFullPath, "");
		
		if (!wellDone) {
			metadataToSet.clear();		
			MetadataException e = new MetadataException();

			// log
			if (log.isDebugEnabled()){
				log.debug("rejectDocument"+" :: MetadataException "+e);
			}
			
			throw e;
		}
		
		// return
		metadataToSet.clear();
		stylesheet.delete(0, stylesheet.length());
		stylesheet.append("CStockage");
		return DefaultRenderXml.getXml(spaces, currentSpace, null, "2012", userPortalLogin, userGroups, directoryProperties, currentSortType);
	}
	
	
	
}
