/*
 * Version 1.1
 * CeCILL Copyright (c) 2006-2007, AtolCD, ADULLACT-projet
 * Initiated by AtolCD S.A. & ADULLACT-projet S.A.
 * Developped by AtolCD
 * 
 * contact@atolcd.com
 * contact@adullact-projet.coop
 * 
 * Ce logiciel est un programme informatique servant à faire circuler des 
 * documents au travers d'un circuit de validation, où chaque acteur vise 
 * le dossier, jusqu'à l'étape finale de signature.
 * 
 * Ce logiciel est régi par la licence CeCILL soumise au droit français et
 * respectant les principes de diffusion des logiciels libres. Vous pouvez
 * utiliser, modifier et/ou redistribuer ce programme sous les conditions
 * de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA 
 * sur le site "http://www.cecill.info".
 * 
 * En contrepartie de l'accessibilité au code source et des droits de copie,
 * de modification et de redistribution accordés par cette licence, il n'est
 * offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,
 * seule une responsabilité restreinte pèse sur l'auteur du programme,  le
 * titulaire des droits patrimoniaux et les concédants successifs.
 * 
 * A cet égard  l'attention de l'utilisateur est attirée sur les risques
 * associés au chargement,  à l'utilisation,  à la modification et/ou au
 * développement et à la reproduction du logiciel par l'utilisateur étant 
 * donné sa spécificité de logiciel libre, qui peut le rendre complexe à 
 * manipuler et qui le réserve donc à des développeurs et des professionnels
 * avertis possédant  des  connaissances  informatiques approfondies.  Les
 * utilisateurs sont donc invités à charger  et  tester  l'adéquation  du
 * logiciel à leurs besoins dans des conditions permettant d'assurer la
 * sécurité de leurs systèmes et ou de leurs données et, plus généralement, 
 * à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. 
 * 
 * Le fait que vous puissiez accéder à cet en-tête signifie que vous avez 
 * pris connaissance de la licence CeCILL, et que vous en avez accepté les
 * termes.
 *  
 */

package com.atolcd.parapheur.repo;

import java.io.InputStream;
import java.io.Serializable;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.alfresco.service.Auditable;
import org.alfresco.service.NotAuditable;
import org.alfresco.service.PublicService;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.NoSuchPersonException;
import org.alfresco.service.namespace.QName;

@PublicService
public interface ParapheurService
{
    /**
     * Indique si un noeud est un ph:parapheur.
     * 
     * @param nodeRef le noeud à tester
     * @return <code>true</code> si nodeRef est un ph:parapheur
     * @throws IllegalArgumentException si nodeRef est null ou n'existe pas dans le repository
     */
    @NotAuditable
    public abstract boolean isParapheur(NodeRef nodeRef);

    /**
     * Indique si un noeud est une ph:corbeille.
     * 
     * @param nodeRef le noeud à tester
     * @return <code>true</code> si nodeRef est une ph:corbeille
     * @throws IllegalArgumentException si nodeRef est null ou n'existe pas dans le repository
     */
    @NotAuditable
    public abstract boolean isCorbeille(NodeRef nodeRef);
    
    /**
     * Indique si un noeud est une ph:corbeilleVirtuelle.
     * 
     * @param nodeRef le noeud à tester
     * @return <code>true</code> si nodeRef est une ph:corbeilleVirtuelle
     * @throws IllegalArgumentException si nodeRef est null ou n'existe pas dans le repository
     */
    @NotAuditable
    public abstract boolean isCorbeilleVirtuelle(NodeRef nodeRef);

    /**
     * Indique si un noeud est un ph:dossier.
     * 
     * @param nodeRef le noeud à tester
     * @return <code>true</code> si nodeRef est un ph:dossier
     * @throws IllegalArgumentException si nodeRef est null ou n'existe pas dans le repository
     */
    @NotAuditable
    public abstract boolean isDossier(NodeRef nodeRef);

    /**
     * Renvoie la liste de tous les parapheurs de l'application.
     * 
     * @return la liste des parapheurs
     */
    @NotAuditable
    public abstract List<NodeRef> getParapheurs();

    /**
     * Renvoie la liste de corbeilles d'un parapheur.
     * 
     * @param parapheur le parapheur
     * @return les NodeRef des corbeilles du parapheur
     * @throws IllegalArgumentException si <code>parapheur</code> n'est pas un parapheur
     */
    @NotAuditable
    public abstract List<NodeRef> getCorbeilles(NodeRef parapheur);
    
    /**
     * Renvoie la liste des dossiers d'une corbeille.
     * 
     * @param corbeille la corbeille
     * @return les NodeRef des dossiers de la corbeille
     * @throws IllegalArgumentException si <code>corbeille</code> n'est pas une corbeille
     */
    @NotAuditable
    public abstract List<NodeRef> getDossiers(NodeRef corbeille);
    
    @NotAuditable
    public abstract List<NodeRef> getDocuments(NodeRef dossier);
    
    /**
     * Recherche une corbeille spécifique dans un parapheur.
     * 
     * Le nom de la corbeille est en fait le {@link QName}
     * de la {@link org.alfresco.service.cmr.repository.ChildAssociationRef}.
     * 
     * @param parapheur le parapheur contenant la corbeille.
     * @param name      le nom de la corbeille.
     * @return le NodeRef de la corbeille, ou <code>null</code> si elle n'a pas été trouvée.
     * @throws IllegalArgumentException si parapheur n'est pas un ph:parapheur.
     * @throws IllegalArgumentException si name est null
     */
    @NotAuditable
    public abstract NodeRef getCorbeille(NodeRef parapheur, QName name);

    /**
     * Parcourt les parents d'un noeud et renvoie le premier ph:dossier trouvé.
     * 
     * @param nodeRef le noeud à partir duquel chercher
     * @return le NodeRef du ph:dossier ou <code>null</code> s'il n'a pas été trouvé.
     * @throws IllegalArgumentException si nodeRef est null ou n'existe pas dans le repository
     */
    @NotAuditable
    public abstract NodeRef getParentDossier(NodeRef nodeRef);

    /**
     * Parcourt les parents d'un noeud et renvoie la première corbeille trouvée.
     * 
     * @param nodeRef le noeud à partir duquel chercher
     * @return le NodeRef de la corbeille ou <code>null</code> si elle n'a pas été trouvée.
     * @throws IllegalArgumentException si nodeRef est null ou n'existe pas dans le repository
     */
    @NotAuditable
    public abstract NodeRef getParentCorbeille(NodeRef nodeRef);

    /**
     * Parcourt les parents d'un noeud et renvoie le premier parapheur trouvé.
     * 
     * @param nodeRef le noeud à partir duquel chercher
     * @return le NodeRef du parapheur ou <code>null</code> s'il n'a pas été trouvé.
     * @throws IllegalArgumentException si nodeRef est null ou n'existe pas dans le repository
     */
    @NotAuditable
    public abstract NodeRef getParentParapheur(NodeRef nodeRef);

    /**
     * Renvoie l'autorité propriétaire d'un parapheur, c'est-à-dire un
     * nom d'utilisateur (userName) ou de groupe.
     * 
     * @param parapheur le parapheur
     * @return le nom d'autorité du propriétaire, ou <code>null</code> si le noeud n'est pas <em>dans</em> un parapheur.
     * @throws IllegalArgumentException si nodeRef est null ou n'existe pas dans le repository
     */
    @NotAuditable
    public abstract String getParapheurOwner(NodeRef parapheur);

    /**
     * Indique si un utilisateur est propriétaire d'un parapheur, y compris
     * s'il fait partie du groupe propriétaire d'un parapheur partagé.
     * 
     * @param nodeRef un parapheur ou un noeud se trouvant dans un parapheur
     * @param userName le userName de l'utilisateur
     * @return <code>true</code> si l'utilisateur est propriétaire du parapheur.
     * @throws IllegalArgumentException si nodeRef est null ou n'existe pas dans le repository
     * @throws IllegalArgumentException si userName est null ou vide
     */
    @NotAuditable
    public abstract boolean isParapheurOwner(NodeRef nodeRef, String userName);
    
    /**
     * Renvoie le parapheur dont l'utilisateur est propriétaire.
     * 
     * @param userName le nom d'utilisateur
     * @return le NodeRef du parapheur, ou <code>null</code> s'il n'a pas été trouvé.
     * @throws IllegalArgumentException si userName est null ou vide
     */
    @NotAuditable
    public abstract NodeRef getOwnedParapheur(String userName);

    /**
     * EN OPTION POUR PLUS TARD
     * 
     * Renvoie les parapheurs dont le propriétaire est un groupe
     * duquel l'utilisateur fait partie.
     * 
     * @param userName le nom de l'utilisateur
     * @return la liste des NodeRef des parapheurs
     * @throws IllegalArgumentException si userName est null ou vide
     */
    @NotAuditable
    public abstract List<NodeRef> getSharedParapheurs(String userName);

    /**
     * Indique si un utilisateur est secrétaire d'un parapheur, y compris
     * s'il fait partie du groupe secrétaire d'un parapheur à secrétariat partagé.
     * 
     * @param nodeRef un parapheur ou un noeud se trouvant dans un parapheur
     * @param userName le userName de l'utilisateur
     * @return <code>true</code> si l'utilisateur est secrétaire du parapheur.
     * @throws IllegalArgumentException si nodeRef est null ou n'existe pas dans le repository
     * @throws IllegalArgumentException si userName est null ou vide
     */
    @NotAuditable
    public abstract boolean isParapheurSecretaire(NodeRef nodeRef, String userName);
    
    /**
     * Renvoie les parapheurs pour lequel l'utilisateur est secrétaire.
     * 
     * @param userName le nom de l'utilisateur
     * @return la liste des NodeRef des parapheurs
     * @throws IllegalArgumentException si userName est null ou vide
     */
    @NotAuditable
    public abstract List<NodeRef> getSecretariatParapheurs(String userName);
    
    /**
     * Crée un nouveau dossier dans un parapheur (dans la corbeille "en préparation").
     * Le nom du dossier est récupéré de la propriété <code>cm:name</code> passée en argument.
     * 
     * @param parapheur  le parapheur dans lequel créer le dossier
     * @param properties les propriétés du dossier
     * @return le NodeRef du dossier qui vient d'être créé
     * @throws IllegalArgumentException si <code>parapheur</code> ne représente pas un parapheur
     *                                  ou si <code>properties</code> ne contient pas de propriété
     *                                  <code>cm:name</code>.
     */
    @Auditable(key = Auditable.Key.RETURN ,parameters = {"parapheur", "properties"})
    public abstract NodeRef createDossier(NodeRef parapheur,
            Map<QName, Serializable> properties) throws FileExistsException;

    /**
     * Renvoie le parapheur (rôle) de l'émetteur d'un dossier.
     * 
     * @param dossier le dossier
     * @return le NodeRef du parapheur émetteur
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     */
    @NotAuditable
    public abstract NodeRef getEmetteur(NodeRef dossier);

    /**
     * Indique si le dossier a été émis.
     * 
     * @param dossier le dossier
     * @return <code>true</code> si le dossier a été émis
     */
    @NotAuditable
    public abstract boolean isEmis(NodeRef dossier);
    
    /**
     * Indique si le dossier a fini son circuit (signé ou retourné).
     * 
     * @param dossier le dossier
     * @return <code>true</code> si le dossier est terminé.
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     */
    @NotAuditable
    public abstract boolean isTermine(NodeRef dossier);

    /**
     * Renvoie la liste des étapes du circuit de validation d'un dossier.
     * 
     * @param dossier le dossier
     * @return la liste des NodeRef des étapes du circuit
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     */
    @NotAuditable
    public abstract List<EtapeCircuit> getCircuit(NodeRef dossier);

    /**
     * Renvoie la liste des "parapheurs" membres de la liste de diffusion
     * d'un dossier.
     * 
     * @param dossier le dossier
     * @return la liste des NodeRef des parapheurs membres de la liste
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     */
    @NotAuditable
    public abstract Set<NodeRef> getDiffusion(NodeRef dossier);

    /**
     * Renvoie l'autorité (utilisateur ou groupe) acteur courant d'un dossier.
     * 
     * @param dossier le dossier
     * @return le nom de l'autorité acteur courant
     * @throws IllegalArgumentException si le dossier n'est pas un dossier
     */
    @NotAuditable
    public abstract String getActeurCourant(NodeRef dossier);

    /**
     * Indique si l'utilisateur est acteur courant du dossier.
     * 
     * @param dossier le dossier à tester
     * @param userName le nom d'utilisateur
     * @return <code>true</code> si l'utilisateur est acteur courant du dossier
     * @throws IllegalArgumentException si <code>dossier</code> n'est pas un dossier
     * @throws IllegalArgumentException si <code>userName</code> est <code>null</code> ou vide
     */
    @NotAuditable
    public abstract boolean isActeurCourant(NodeRef dossier, String userName);
    
    /**
     * Renvoie l'annotation publique d'un dossier pour l'étape en cours.
     * 
     * @param dossier le dossier
     * @return l'annotation publique pour l'étape en cours
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     */
    @NotAuditable
    public abstract String getAnnotationPublique(NodeRef dossier);
    /**
     * Remplace l'annotation publique d'un dossier pour l'étape en cours.
     * 
     * @param dossier le dossier
     * @param annotation la nouvelle annotation publique
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     */
    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"dossier", "annotation"})
    public abstract void setAnnotationPublique(NodeRef dossier, String annotation);

    /**
     * Renvoie l'annotation privée courante d'un dossier.
     * 
     * @param dossier le dossier
     * @return l'annotation privée
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier
     */
    @NotAuditable
    public abstract String getAnnotationPrivee(NodeRef dossier);
    
    /**
     * Renvoie l'annotation privée précédente d'un dossier.
     * 
     * @param dossier le dossier
     * @return l'annotation privée de l'étape précédente
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier
     */
    @NotAuditable
    public abstract String getAnnotationPriveePrecedente(NodeRef dossier);
    
    /**
     * Remplace l'annotation courante privée d'un dossier
     * 
     * @param dossier le dossier
     * @param annotation la nouvelle annotation privée
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     */
    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"dossier", "annotation"})
    public abstract void setAnnotationPrivee(NodeRef dossier, String annotation);
    
    /**
     * Approuve l'étape en cours d'un dossier et le fait passer à l'étape suivante.
     * 
     * @param dossier le dossier
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     * @throws RuntimeException si l'étape suivante du circuit de validation n'existe pas
     * @throws RuntimeException si une boucle de déléation a été détectée
     */
    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"dossier"})
    public abstract void approve(NodeRef dossier);
    /**
     * Rejette le dossier (le fait passer à l'émetteur comme dossier retourné)
     * 
     * @param dossier le dossier
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     */
    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"dossier"})
    public abstract void reject(NodeRef dossier);

    /**
     * Reprend le dossier (copie le dossier vers les dossiers à transmettre)
     * 
     * @param dossier le dossier
     * @return la référence du dossier copié
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     */
    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"dossier"})
    public abstract NodeRef reprendreDossier(NodeRef dossier);
    
    /**
     * Transfère un dossier au secrétariat ou le ramène dans sa corbeille d'origine selon son état
     * 
     * @param dossier le dossier
     * @return la référence du dossier copié
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     */
    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"dossier"})
    public abstract void secretariat(NodeRef dossier);
    
    /**
     * Récupère le dossier (le circuit repasse à l'étape précédente et le dossier est déplacé vers le parapheur précédent)
     * 
     * @param dossier le dossier
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     */
    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"dossier"})
    public abstract void recupererDossier(NodeRef dossier);
    
    /**
     * Archive le dossier
     * 
     * @param dossier le dossier
     * @param nom le nom que l'on souhaite donner à l'archive
     * @return l'URL d'archive
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     */
    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"dossier", "nom"})
    public abstract String archiver(NodeRef dossier, String nom);
    
    /**
     * Retourne une map contenant les circuits enregistrés dans le système
     * 
     * @return les couples (nom, référence) des circuits enregistrés, jamais <code>null</code>
     */
    @NotAuditable
    public abstract Map<String,NodeRef> getSavedWorkflows();
    
    /**
     * Retourne la liste de validation et l'ensemble de diffusion d'un circuit prédéfini passé en paramètre
     * 
     * @param workflow la référence du circuit prédéfini
     * @return la définition du circuit prédéfini
     */
    @NotAuditable
    public abstract SavedWorkflow loadSavedWorkflow(NodeRef workflow);
    
    /**
     * Crée un noeud dans Data dictionary/Circuits et enregistre le circuit passé en paramètre
     * Si le circuit existait déjà, il est remplacé
     * 
     * @param name le nom du circuit à enregistrer
     * @param circuit la liste des parapheurs composant le circuit de validation
     * @param diffusion l'ensemble des parapheurs de la liste de notification
     * @param publicWorkflow indique si le workflow doit être accessible par les autres utilisateurs
     * @return la référence du noeud créé
     * @throws IllegalArgumentException si <code>name</code> ne contient pas une chaîne de caractères valide
     */
    @NotAuditable
    public abstract NodeRef saveWorkflow(String name, List<NodeRef> circuit, Set<NodeRef> diffusion, boolean publicWorkflow);
    
    /**
     * Indique si le dossier peut être récupéré (droit de remord).
     * 
     * @param dossier le dossier
     * @return <code>true</code> si le dossier est récupérable.
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     */
    @NotAuditable
    public abstract boolean isRecuperable(NodeRef dossier);
    
    /**
     * Retourne le parapheur responsable dans la hiérarchie
     * 
     * @param parapheur le parapheur
     * @return la référence du parapheur responsable, ou null si le parapheur passé en paramètre n'a pas de responsable
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un parapheur.
     */
    @NotAuditable
    public abstract NodeRef getParapheurResponsable(NodeRef parapheur);
    
    /**
     * Remplace le signataire d'un dossier pour l'étape en cours.
     * 
     * @param dossier le dossier
     * @param signataire le nom complet du signataire
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     */
    @NotAuditable
    public abstract void setSignataire(NodeRef dossier, String signataire);
    
    /**
     * Remplace le signataire d'un dossier pour l'étape en cours.
     * 
     * @param dossier le dossier
     * @param signataire le nom complet du signataire
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier.
     */
    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"dossier", "signataire", "cert"})
    public abstract void setSignataire(NodeRef dossier, String signataire, X509Certificate[] cert);
    
    /**
     * Retourne le nom d'un parapheur.
     * 
     * @param parapheur le parapheur
     * @return nom le nom du parapheur (propriété ContentModel.PROP_NAME)
     * @throws IllegalArgumentException si <code>parapheur</code> ne représente pas un parapheur.
     */
    @NotAuditable
    public abstract String getNomParapheur(NodeRef parapheur);
    
    /**
     * Retourne le nom du propriétaire d'un parapheur.
     * 
     * @param parapheur le parapheur
     * @return nom le nom de son propriétaire
     * @throws IllegalArgumentException si <code>parapheur</code> ne représente pas un parapheur.
     */
    @NotAuditable
    public abstract String getNomProprietaire(NodeRef parapheur);
    
    /**
     * Crée un nouveau parapheur
     * Le nom du parapheur est récupéré de la propriété <code>cm:name</code> passée en argument.
     * 
     * @param properties les propriétés du parapheur
     * @return le NodeRef du parapheur qui vient d'être créé
     * @throws IllegalArgumentException  si <code>properties</code> ne contient pas de propriété <code>cm:name</code>.
     */
    @NotAuditable
    public abstract NodeRef createParapheur(Map<QName, Serializable> properties) throws FileExistsException;
    
    /**
     * Remplace le parapheur de délégation d'un parapheur donné.
     * 
     * @param parapheur
     * @param parapheurDelegue
     * @throws IllegalArgumentException  si <code>parapheur</code> ne représente pas un parapheur.
     * @throws IllegalArgumentException  si <code>parapheurDelegue</code> ne représente pas un parapheur et n'est pas null.
     * @throws RuntimeException  si l'opération conduit à une boucle de délégation.
     */
    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"parapheur", "parapheurDelegue"})
    public abstract void setDelegation(NodeRef parapheur, NodeRef parapheurDelegue);
    
    /**
     * Retourne le parapheur de délégation d'un parapheur donné, ou null si il n'en a pas.
     * 
     * @param parapheur
     * @return le NodeRef du parapheur délégué.
     * @throws IllegalArgumentException  si <code>parapheur</code> ne représente pas un parapheur.
     */
    @NotAuditable
    public abstract NodeRef getDelegation(NodeRef parapheur);
    
    /**
     * Remplace le circuit de validation d'un dossier donné. L'émetteur peut éventuellement
     * être inclus comme premier élément de la liste.
     * 
     * @param dossier le NodeRef du dossier concerné
     * @param circuit la liste des NodeRef des parapheurs composant le circuit de validation
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier non-émis
     * @throws IllegalArgumentException si le circuit contient des doublons
     */
    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"dossier", "circuit"})
    public abstract void setCircuit(NodeRef dossier, List<NodeRef> circuit);
    
    /**
     * Remplace la liste de diffusion d'un dossier donné
     * 
     * @param dossier le NodeRef du dossier concerné
     * @param diffusion l'ensemble des NodeRef des parapheurs composant la liste de diffusion
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier ou est null
     */
    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"dossier", "diffusion"})
    public abstract void setDiffusion(NodeRef dossier, Set<NodeRef> diffusion);
    
    /**
     * Retourne la liste des usernames composant le secrétariat du parapheur passé en paramètre
     * 
     * @param parapheur le NodeRef du parapheur à évaluer
     * @return la liste des secrétaires de ce parapheur
     * @throws IllegalArgumentException si <code>parapheur</code> ne représente pas un parapheur ou est null
     */
    @NotAuditable
    public abstract List<String> getSecretariatParapheur(NodeRef parapheur);
    
    /**
     * Modifie l'étape courante du dossier passé en paramètre et le déplace vers un nouveau parapheur
     * 
     * @param dossier le dossier à modifier
     * @param parapheur le parpaheur de destination
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier non-terminé
     * @throws IllegalArgumentException si <code>parapheur</code> ne représente pas un parapheur
     */
    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"dossier", "parapheur"})
    public abstract void moveDossier(NodeRef dossier, NodeRef parapheur);
    
    /**
     * Retourne le NodeRef du parapheur dont le nom est passé en paramètre ou null si il n'existe pas
     * 
     * @param parapheurName le nom du parapheur à chercher
     * @return la référence du parapheur ou null
     * @throws IllegalArgumentException si <code>parapheurName</code> n'est pas une chaîne de caractères valide 
     */
    @NotAuditable
    public abstract NodeRef parapheurFromName(String parapheurName);
    
    /**
     * Stocke la signature de la pièce principale dans une propriété d:text d'Alfresco
     * 
     * @param dossier le dossier à modifier
     * @param signedBytes la valeur de la signature sous forme d'un tableau d'octets
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier
     */
    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"dossier", "signedBytes"})
    public abstract void setSignature(NodeRef dossier, byte[] signedBytes);
    
    /**
     * Retourne la signature de la pièce principale d'un dossier si elle existe, null sinon
     * 
     * @param dossier le dossier concerné
     * @return la signature sous forme d'un tableau d'octets
     * @throws IllegalArgumentException si <code>dossier</code> ne représente pas un dossier
     */
    @NotAuditable
    public abstract byte[] getSignature(NodeRef dossier);
    
    /**
     * Retourne l'URL de téléchargement de l'applet utilisée pour la signature électronique
     * 
     * @return l'url sous forme de chaîne de caractères
     */
    @NotAuditable
    public abstract String getSignAppletURL();
    
    /**
     * Retourne les propriétés nécessaires pour signature électronique XAdES
     * 
     * @return un objet Properties
     */
    @NotAuditable
    public abstract Properties getXadesSignatureProperties(NodeRef dossier);
    
    /**
     * Retourne la configuration du service (principalement des childnames)
     * 
     * @return un objet Properties contenant la configuration
     */
    @NotAuditable
    public abstract Properties getConfiguration();

    /**
     * crée un dossier PES_Retour (HELIOS) depuis une requete de TdT
     * @param id
     * @param xmlIS
     * @return true si Ok, false sinon
     */
    @NotAuditable
    public abstract NodeRef createDossierPesRetour(String id, String parapheurName, InputStream xmlIS);
    
    /**
     * Interface de gestion des meta-donnees sur les dossiers,
     * en particulier le typage métier: type technique + sous-type
     * 
     * Les Meta-Données sont portées par le dossier. Il peut y en avoir plusieurs:
     *  - Types: stocké au format XML dans le dictionnaire des données
     *  - Sous-types: Un fichier XML par TypeTechnique référent.
     * 
     * les autres MetaDonnées pourraient être des tags (catégories) Alfresco
     */
  
    /**
     * Interroge iParapheur pour obtenir la liste des Types techniques
     * @return flux XML des types techniques
     */
    @NotAuditable
    public abstract InputStream getSavedXMLTypes();
    
    /**
     * Interroge iParapheur pour obtenir la liste des sous-Types techniques
     * @return flux XML des sous-types techniques
     */
    @NotAuditable
    public abstract InputStream getSavedXMLSousTypes(String typeID);
    
    /**
     * Fournit les caractéristiques du Type technique donné en paramètre
     * @param typeID : le Type technique iParapheur
     * @return Description, infos TdT
     */
    @NotAuditable
    public abstract Map<QName, Serializable> getTypeMetierProperties(String typeID);
    
    /**
     * à un couple (type, sous-type) correspond un circuit de validation.
     * Cette méthode retourne ne nodeRef de ce circuit sauvegardé.
     * @param typeID
     * @param sousTypeID
     * @return le nodeRef du circuit de validation correspondant
     */
    @NotAuditable
    public abstract NodeRef getCircuitRef(String typeID, String sousTypeID);
    
    @NotAuditable
    public abstract NodeRef findUserByEmail(String from) throws NoSuchPersonException;

    @NotAuditable
    public abstract NodeRef rechercheDossier(String nomDossier);

    /**
     * Détection de doublon dans l'attribution de nom de dossier.
     * @param nomDossier
     * @return
     */
    @NotAuditable
    public abstract boolean isNomDossierAlreadyExists(String nomDossier);
    
    @NotAuditable
    public abstract List<NodeRef> rechercheDossiers(String type, String soustype, String status);

}
