From 0467dbb11015dfae9ec5b896ce41f79a518e2218 Mon Sep 17 00:00:00 2001
From: gmantele <gmantele@ari.uni-heidelberg.de>
Date: Thu, 28 Sep 2017 17:48:36 +0200
Subject: [PATCH] [UWS] Add the new Execution Phase `ARCHIVED` and check phase
 transitions.

A JUnit test case has been added in order to check that all possible phase
transitions are respecting the UWS-1.1 standard. However, there is anyway
a bit more freedom for some of them:

    - it is possible to go to and come from UNKNOWN at any time, whatever is
	  the source or target phase.

	- it is possible to go to ERROR or ABORTED from the phases HELD and
	  SUSPENDED. This fact was not specified in the State Machine figure of the
	  UWS standard but the following sentence at section
	  "2.1.3 Execution Phase" (page 7) should allow that:
	  "At any time before the COMPLETED phase a job may either be ABORTED or
	   may suffer an ERROR."

	- the UWS-1.1 document has an inconsistency about the HELD phase. At
	  section "2.1.3 Execution Phase" (page 7), the following sentence implies
	  that it is only possible to go to HELD from PENDING (because it would not
	  be possible to queue the job). And so, when PHASE=RUN is sent by the UWS
      client, if now possible, the job should go in phase QUEUED. However the
	  State Machine figure suggests that it is possible to go to HELD only from
	  EXECUTING and that a PHASE=RUN would make the job go back to EXECUTING (if
	  now possible). Because of this inconsistency, the UWSLibrary made possible
	  the following transitions: PENDING/EXECUTING->HELD->QUEUED/EXECUTING.

(note: a figure illustrating the phase transitions supported by the
       UWSLibrary-4.3 has been created in the directory `img` of the
	   UWS-Tutorial website under the file name `state_machine.png`...which of
	   course will be visible only when uwslib-4.3 will be released)

Besides, this commit also include almost a full rewriting of the Javadoc of
JobPhase and ExecutionPhase. The Javadoc of UWSJob has just been reformated
so that comments do not exceed 80 (+2) characters. This reformating aims to
improve the human reading of the Javadoc while looking at the source files ;
however this should not affect much the HTML version of the Javadoc.
---
 src/uws/UWSExceptionFactory.java |  28 +-
 src/uws/job/ExecutionPhase.java  | 226 ++++++++--
 src/uws/job/JobPhase.java        | 298 +++++++------
 src/uws/job/UWSJob.java          | 695 +++++++++++++++++++++----------
 test/uws/job/TestJobPhase.java   | 648 ++++++++++++++++++++++++++++
 5 files changed, 1500 insertions(+), 395 deletions(-)
 create mode 100644 test/uws/job/TestJobPhase.java

diff --git a/src/uws/UWSExceptionFactory.java b/src/uws/UWSExceptionFactory.java
index c88fff2..f5321c7 100644
--- a/src/uws/UWSExceptionFactory.java
+++ b/src/uws/UWSExceptionFactory.java
@@ -2,21 +2,21 @@ package uws;
 
 /*
  * This file is part of UWSLibrary.
- * 
+ *
  * UWSLibrary is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * UWSLibrary is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public License
  * along with UWSLibrary.  If not, see <http://www.gnu.org/licenses/>.
- * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *
+ * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -25,10 +25,10 @@ import uws.job.user.JobOwner;
 
 /**
  * Let's creating the common exceptions of a UWS service.
- * 
+ *
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 4.1 (09/2014)
- * 
+ * @version 4.3 (09/2017)
+ *
  * @see UWSException
  */
 public final class UWSExceptionFactory {
@@ -54,7 +54,7 @@ public final class UWSExceptionFactory {
 	}
 
 	public final static String incorrectPhaseTransition(final String jobID, final ExecutionPhase fromPhase, final ExecutionPhase toPhase, final String consequence){
-		return "Incorrect phase transition ! => the job " + jobID + " is in the phase " + fromPhase + ". It can not go to " + toPhase + "." + appendMessage(consequence);
+		return "Incorrect phase transition! => the job " + jobID + " is in the phase " + fromPhase + ". It can not go to " + toPhase + "." + appendMessage(consequence);
 	}
 
 	public final static String readPermissionDenied(final JobOwner user, final boolean jobList, final String containerName){
@@ -62,7 +62,7 @@ public final class UWSExceptionFactory {
 	}
 
 	public final static String readPermissionDenied(final JobOwner user, final boolean jobList, final String containerName, final String consequence){
-		return user.getID() + ((user.getPseudo() == null) ? "" : (" (alias " + user.getPseudo() + ")")) + " is not allowed to read the content of the " + (jobList ? "jobs list" : "job") + " \"" + containerName + "\" !" + appendMessage(consequence);
+		return user.getID() + ((user.getPseudo() == null) ? "" : (" (alias " + user.getPseudo() + ")")) + " is not allowed to read the content of the " + (jobList ? "jobs list" : "job") + " \"" + containerName + "\"!" + appendMessage(consequence);
 	}
 
 	public final static String writePermissionDenied(final JobOwner user, final boolean jobList, final String containerName){
@@ -70,7 +70,7 @@ public final class UWSExceptionFactory {
 	}
 
 	public final static String writePermissionDenied(final JobOwner user, final boolean jobList, final String containerName, final String consequence){
-		return user.getID() + ((user.getPseudo() == null) ? "" : (" (alias " + user.getPseudo() + ")")) + " is not allowed to update the content of the " + (jobList ? "jobs list" : "job") + " \"" + containerName + "\" !" + appendMessage(consequence);
+		return user.getID() + ((user.getPseudo() == null) ? "" : (" (alias " + user.getPseudo() + ")")) + " is not allowed to update the content of the " + (jobList ? "jobs list" : "job") + " \"" + containerName + "\"!" + appendMessage(consequence);
 	}
 
 	public final static String executePermissionDenied(final JobOwner user, final String jobID){
@@ -78,7 +78,7 @@ public final class UWSExceptionFactory {
 	}
 
 	public final static String executePermissionDenied(final JobOwner user, final String jobID, final String consequence){
-		return user.getID() + ((user.getPseudo() == null) ? "" : (" (alias " + user.getPseudo() + ")")) + " is not allowed to execute/abort the job \"" + jobID + "\" !" + appendMessage(consequence);
+		return user.getID() + ((user.getPseudo() == null) ? "" : (" (alias " + user.getPseudo() + ")")) + " is not allowed to execute/abort the job \"" + jobID + "\"!" + appendMessage(consequence);
 	}
 
 	public final static String jobModificationForbidden(final String jobId, final ExecutionPhase phase, final String parameter){
@@ -87,9 +87,9 @@ public final class UWSExceptionFactory {
 
 	public final static String jobModificationForbidden(final String jobId, final ExecutionPhase phase, final String parameter, final String consequence){
 		if (parameter != null && !parameter.trim().isEmpty())
-			return "Impossible to change the parameter \"" + parameter + "\" of the job " + jobId + ((phase != null) ? (" (phase: " + phase + ")") : "") + " !" + appendMessage(consequence);
+			return "Impossible to change the parameter \"" + parameter + "\" of the job " + jobId + ((phase != null) ? (" (phase: " + phase + ")") : "") + "!" + appendMessage(consequence);
 		else
-			return "Impossible to change the parameters of the job " + jobId + ((phase != null) ? (" (phase: " + phase + ")") : "") + " !" + appendMessage(consequence);
+			return "Impossible to change the parameters of the job " + jobId + ((phase != null) ? (" (phase: " + phase + ")") : "") + "!" + appendMessage(consequence);
 	}
 
 }
diff --git a/src/uws/job/ExecutionPhase.java b/src/uws/job/ExecutionPhase.java
index d803f82..acfb95c 100644
--- a/src/uws/job/ExecutionPhase.java
+++ b/src/uws/job/ExecutionPhase.java
@@ -2,70 +2,214 @@ package uws.job;
 
 /*
  * This file is part of UWSLibrary.
- * 
+ *
  * UWSLibrary is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * UWSLibrary is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public License
  * along with UWSLibrary.  If not, see <http://www.gnu.org/licenses/>.
- * 
- * Copyright 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
+ *
+ * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *                       Astronomisches Rechen Institut (ARI)
  */
 
 /**
- * <p>A job is treated as a state machine where the Execution Phase is the job state. The phases are:</p>
- * <ul>
- *	<li>{@link #PENDING}: 	the job is accepted by the service but not yet committed for
- *          				execution by the client. In this state, the job quote can be read
- *          				and evaluated. This is the state into which a job enters when it
- *          				is first created.</li>
- *
- *	<li>{@link #QUEUED}: 	the job is committed for execution by the client but the service
- *         					has not yet assigned it to a processor. No Results are produced in
- *         					this phase.</li>
- *
- *	<li>{@link #EXECUTING}: the job has been assigned to a processor. Results may be produced
- *            				at any time during this phase.</li>
- *
- *	<li>{@link #COMPLETED}: the execution of the job is over. The Results may be collected.</li>
- *
- *	<li>{@link #ERROR}: 	the job failed to complete. No further work will be done nor Results
- *        					produced. Results may be unavailable or available but invalid; either
- *        					way the Results should not be trusted.</li>
+ * A job is treated as a state machine where the Execution Phase is the job
+ * state. This enum class gathers all Execution Phases declared by the IVOA
+ * since UWS-1.1.
  *
- *	<li>{@link #ABORTED}: 	the job has been manually aborted by the user, or the system has
- *          				aborted the job due to lack of or overuse of resources.</li>
+ * <p>
+ * 	The transitions of the state machine described by the IVOA are implemented
+ * 	in a different class: {@link JobPhase}.
+ * </p>
  *
- *	<li>{@link #UNKNOWN}: 	the job is in an unknown state.</li>
+ * @see JobPhase
  *
- *	<li>{@link #HELD}: 		The job is HELD pending execution and will not automatically be
- *      	 				executed (cf pending).</li>
- * 
- *	<li>{@link #SUSPENDED}:	The job has been suspended by the system during execution. This might
- *							be because of temporary lack of resource. The UWS will automatically
- *							resume the job into the EXECUTING phase without any intervention
- *							when resource becomes available.</li>
- * </ul>
- * 
- * @see UWSJob
- * 
- * @author Gr&eacute;gory Mantelet (CDS)
- * @version 02/2011
+ * @author Gr&eacute;gory Mantelet (CDS;ARI)
+ * @version 4.3 (09/2017)
  */
 public enum ExecutionPhase{
-	PENDING, QUEUED, EXECUTING, COMPLETED, ERROR, ABORTED, UNKNOWN, HELD, SUSPENDED;
+	/**
+	 * The job is accepted by the service but not yet committed for execution by
+	 * the client. In this state, the job quote can be read and evaluated. This
+	 * is the state into which a job enters when it is first created.
+	 *
+	 * <p><b>Allowed previous phases:</b> <i>none</i>.</p>
+	 *
+	 * <p><b>Possible next phases:</b>
+	 * 	{@link #HELD}, {@link #QUEUED}, {@link #ABORTED} or {@link #ERROR}.
+	 * </p>
+	 */
+	PENDING,
+	/**
+	 * The job is committed for execution by the client but the service has not
+	 * yet assigned it to a processor. No Results are produced in this phase.
+	 *
+	 * <p><b>Allowed previous phases:</b>
+	 * 	{@link #PENDING} or {@link #HELD}.
+	 * </p>
+	 *
+	 * <p><b>Possible next phases:</b>
+	 * 	{@link #EXECUTING}, {@link #ABORTED} or {@link #ERROR}.
+	 * </p>
+	 */
+	QUEUED,
+	/**
+	 * The job has been assigned to a processor. Results may be produced at any
+	 * time during this phase.
+	 *
+	 * <p><b>Allowed previous phases:</b>
+	 * 	{@link #QUEUED}, {@link #HELD} or {@link #SUSPENDED}.
+	 * </p>
+	 *
+	 * <p><b>Possible next phases:</b>
+	 * 	{@link #HELD}, {@link #SUSPENDED}, {@link #COMPLETED}, {@link #ABORTED}
+	 * 	or {@link #ERROR}.
+	 * </p>
+	 */
+	EXECUTING,
+	/**
+	 * The execution of the job is over. The Results may be collected.
+	 *
+	 * <p><b>Allowed previous phases:</b>
+	 * 	{@link #EXECUTING}.
+	 * </p>
+	 *
+	 * <p><b>Possible next phases:</b>
+	 * 	{@link #ARCHIVED}.
+	 * </p>
+	 */
+	COMPLETED,
+	/**
+	 * The job failed to complete. No further work will be done nor Results
+	 * produced. Results may be unavailable or available but invalid; either
+	 * way the Results should not be trusted.
+	 *
+	 * <p><b>Allowed previous phases:</b>
+	 * 	{@link #EXECUTING}, {@link #QUEUED} or {@link #PENDING}.
+	 * </p>
+	 *
+	 * <p><b>Possible next phases:</b>
+	 * 	{@link #ARCHIVED}.
+	 * </p>
+	 */
+	ERROR,
+	/**
+	 * The job has been manually aborted by the user, or the system has aborted
+	 * the job due to lack of or overuse of resources.
+	 *
+	 * <p><b>Allowed previous phases:</b>
+	 * 	{@link #PENDING}, {@link #QUEUED}, {@link #EXECUTING}, {@link #HELD} or
+	 * 	{@link #SUSPENDED}.
+	 * </p>
+	 *
+	 * <p><b>Possible next phases:</b>
+	 * 	{@link #ARCHIVED}.
+	 * </p>
+	 */
+	ABORTED,
+	/**
+	 * The job is in an unknown state.
+	 *
+	 * <p><i>Note:
+	 * 	If the UWS reports an UNKNOWN phase, then all the client can do is
+	 * 	re-query the phase until a known phase is reported.
+	 * </i></p>
+	 *
+	 * <p><b>Allowed previous phases:</b> <i>any</i>.</p>
+	 *
+	 * <p><b>Possible next phases:</b> <i>any</i>.</p>
+	 */
+	UNKNOWN,
+	/**
+	 * The job is HELD pending execution and will not automatically be executed
+	 * (cf {@link #PENDING}).
+	 *
+	 * <p><i>Note:
+	 * 	A UWS may place a job in a HELD phase on receipt of a PHASE=RUN request
+	 * 	if for some reason the job cannot be immediately queued - in this case
+	 * 	it is the responsibility of the client to request PHASE=RUN again at
+	 * 	some later time.
+	 * </i></p>
+	 *
+	 * <p><b>Allowed previous phases:</b>
+	 * 	{@link #PENDING} or {@link #EXECUTING}.
+	 * </p>
+	 *
+	 * <p><b>Possible next phases:</b>
+	 * 	{@link #QUEUED}, {@link #EXECUTING}, {@link #ABORTED} or {@link #ERROR}.
+	 * </p>
+	 */
+	HELD,
+	/**
+	 * The job has been suspended by the system during execution. This might be
+	 * because of temporary lack of resource. The UWS will automatically resume
+	 * the job into the EXECUTING phase without any intervention when resource
+	 * becomes available.
+	 *
+	 * <p><b>Allowed previous phases:</b>
+	 * 	{@link #EXECUTING}.
+	 * </p>
+	 *
+	 * <p><b>Possible next phases:</b>
+	 * 	{@link #EXECUTING}, {@link #ABORTED} or {@link #ERROR}.
+	 * </p>
+	 */
+	SUSPENDED,
+	/**
+	 * At destruction time the results associated with a job have been deleted
+	 * to free up resource, but the metadata associated with the job have been
+	 * retained. This is an alternative that the server may choose in contrast
+	 * to completely destroying all record of the job to allow a longer
+	 * historical record of the existence of the job to be kept that would
+	 * otherwise be the case if limited result storage resources forces
+	 * destruction.
+	 *
+	 * <p><b>Allowed previous phases:</b>
+	 * 	{@link #ABORTED}, {@link #COMPLETED} or {@link #ERROR}.
+	 * </p>
+	 *
+	 * <p><b>Possible next phases:</b> <i>none</i>.</p>
+	 *
+	 * @since 4.3 */
+	ARCHIVED;
 
+	/**
+	 * Get the label of the given Execution Phase.
+	 *
+	 * <p><i>Note:
+	 * 	The reverse operation is {@link #getPhase(String)}.
+	 * </i></p>
+	 *
+	 * @param ph	An Execution Phase.
+	 *
+	 * @return	The label of the given phase,
+	 *        	or {@link #UNKNOWN} if NULL is given.
+	 */
 	public static final String getStr(ExecutionPhase ph){
 		return (ph == null) ? ExecutionPhase.UNKNOWN.name() : ph.name();
 	}
 
+	/**
+	 * Get the Execution Phase corresponding to the given label.
+	 *
+	 * <p><i>Note:
+	 * 	The reverse operation is {@link #getStr(ExecutionPhase)}.
+	 * </i></p>
+	 *
+	 * @param phStr	Label of the Execution Phase to resolve.
+	 *
+	 * @return	The corresponding {@link ExecutionPhase},
+	 *        	or {@link #UNKNOWN} if the given String is NULL
+	 *        	                    or does not match any legal Execution Phase.
+	 */
 	public static final ExecutionPhase getPhase(String phStr){
 		try{
 			return valueOf(phStr);
diff --git a/src/uws/job/JobPhase.java b/src/uws/job/JobPhase.java
index 1de05bb..01926e4 100644
--- a/src/uws/job/JobPhase.java
+++ b/src/uws/job/JobPhase.java
@@ -2,21 +2,21 @@ package uws.job;
 
 /*
  * This file is part of UWSLibrary.
- * 
+ *
  * UWSLibrary is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * UWSLibrary is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public License
  * along with UWSLibrary.  If not, see <http://www.gnu.org/licenses/>.
- * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *
+ * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -26,12 +26,12 @@ import uws.UWSException;
 import uws.UWSExceptionFactory;
 
 /**
- * An instance of this class represents the current execution phase of a given job,
- * and it describes the transitions between the different phases.
- * 
+ * An instance of this class represents the current execution phase of a given
+ * job, and it describes the transitions between the different phases.
+ *
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 4.1 (08/2014)
- * 
+ * @version 4.3 (09/2017)
+ *
  * @see ExecutionPhase
  * @see UWSJob
  */
@@ -46,9 +46,10 @@ public class JobPhase implements Serializable {
 
 	/**
 	 * Builds the phase manager of the given job.
-	 * 
-	 * @param j				The job whose the execution phase must be represented by the built JobPhase instance.
-	 * 
+	 *
+	 * @param j	The job whose the execution phase must be represented by the
+	 *         	built JobPhase instance.
+	 *
 	 * @throws NullPointerException	If the given job is <i>null</i>.
 	 */
 	public JobPhase(UWSJob j) throws NullPointerException{
@@ -59,7 +60,7 @@ public class JobPhase implements Serializable {
 
 	/**
 	 * Gets the job whose the execution phase is represented by this object.
-	 * 
+	 *
 	 * @return	The associated job.
 	 */
 	public final UWSJob getJob(){
@@ -68,7 +69,7 @@ public class JobPhase implements Serializable {
 
 	/**
 	 * Gets the current phase of the job.
-	 * 
+	 *
 	 * @return	The current job phase.
 	 */
 	public final ExecutionPhase getPhase(){
@@ -76,12 +77,14 @@ public class JobPhase implements Serializable {
 	}
 
 	/**
-	 * Lets changing the current phase of the associated job considering the order of execution phases.
-	 * 
-	 * @param p				The new execution phase.
-	 * 
-	 * @throws UWSException	If the given phase is <i>null</i> or if the phase transition is forbidden.
-	 * 
+	 * Lets changing the current phase of the associated job considering the
+	 * order of execution phases.
+	 *
+	 * @param p	The new execution phase.
+	 *
+	 * @throws UWSException	If the given phase is <i>null</i> or if the phase
+	 *                     	transition is forbidden.
+	 *
 	 * @see #setPhase(ExecutionPhase, boolean)
 	 */
 	public final void setPhase(ExecutionPhase p) throws UWSException{
@@ -89,17 +92,19 @@ public class JobPhase implements Serializable {
 	}
 
 	/**
-	 * <p>Lets changing the current phase of the associated job considering or not the order of execution phases.</p>
-	 * 
+	 * Lets changing the current phase of the associated job considering or
+	 * not the order of execution phases.
+	 *
 	 * <p><i>Note:
 	 * 	If the given phase is <i>null</i>, nothing is done.
 	 * </i></p>
-	 * 
-	 * @param p				The new phase.
-	 * @param force			<i>true</i> to ignore the phases order, <i>false</i> otherwise.
-	 * 
+	 *
+	 * @param p		The new phase.
+	 * @param force	<i>true</i> to ignore the phases order,
+	 *             	<i>false</i> otherwise.
+	 *
 	 * @throws UWSException	If the phase transition is forbidden.
-	 * 
+	 *
 	 * @see #setPendingPhase(boolean)
 	 * @see #setQueuedPhase(boolean)
 	 * @see #setExecutingPhase(boolean)
@@ -108,6 +113,7 @@ public class JobPhase implements Serializable {
 	 * @see #setErrorPhase(boolean)
 	 * @see #setHeldPhase(boolean)
 	 * @see #setSuspendedPhase(boolean)
+	 * @see #setArchivedPhase(boolean)
 	 * @see #setUnknownPhase(boolean)
 	 */
 	public void setPhase(ExecutionPhase p, boolean force) throws UWSException{
@@ -140,6 +146,9 @@ public class JobPhase implements Serializable {
 			case SUSPENDED:
 				setSuspendedPhase(force);
 				break;
+			case ARCHIVED:
+				setArchivedPhase(force);
+				break;
 			case UNKNOWN:
 			default:
 				setUnknownPhase(force);
@@ -149,172 +158,215 @@ public class JobPhase implements Serializable {
 
 	/**
 	 * Changes the current phase to {@link ExecutionPhase#PENDING PENDING}.
-	 * 
-	 * @param force			<i>true</i> to ignore the phases order, <i>false</i> otherwise.
-	 * 
-	 * @throws UWSException	If this phase transition is forbidden <i>(by default: IF force=false AND currentPhase != PENDING or UNKNOWN)</i>.
+	 *
+	 * @param force	<i>true</i> to ignore the phases order,
+	 *             	<i>false</i> otherwise.
+	 *
+	 * @throws UWSException	If this phase transition is forbidden
+	 *                     	<i>(by default: IF force=false
+	 *                     	AND currentPhase != PENDING and UNKNOWN)</i>.
 	 */
 	protected void setPendingPhase(boolean force) throws UWSException{
 		if (!force && phase != ExecutionPhase.PENDING && phase != ExecutionPhase.UNKNOWN)
 			throw new UWSException(UWSException.BAD_REQUEST, UWSExceptionFactory.incorrectPhaseTransition(job.getJobId(), phase, ExecutionPhase.PENDING));
-
 		phase = ExecutionPhase.PENDING;
 	}
 
 	/**
 	 * Changes the current phase to {@link ExecutionPhase#QUEUED QUEUED}.
-	 * 
-	 * @param force			<i>true</i> to ignore the phases order, <i>false</i> otherwise.
-	 * 
-	 * @throws UWSException	If this phase transition is forbidden <i>(by default: IF force=false AND currentPhase != QUEUED or HELD or PENDING or UNKNOWN)</i>.
+	 *
+	 * @param force	<i>true</i> to ignore the phases order,
+	 *             	<i>false</i> otherwise.
+	 *
+	 * @throws UWSException	If this phase transition is forbidden
+	 *                     	<i>(by default: IF force=false
+	 *                     	AND currentPhase != QUEUED, HELD, PENDING
+	 *                     	                    and UNKNOWN)</i>.
 	 */
 	protected void setQueuedPhase(boolean force) throws UWSException{
-		if (force)
-			phase = ExecutionPhase.QUEUED;
-		else{
-			if (phase != ExecutionPhase.QUEUED && phase != ExecutionPhase.HELD && phase != ExecutionPhase.PENDING && phase != ExecutionPhase.UNKNOWN)
-				throw new UWSException(UWSException.BAD_REQUEST, UWSExceptionFactory.incorrectPhaseTransition(job.getJobId(), phase, ExecutionPhase.QUEUED));
-
-			phase = ExecutionPhase.QUEUED;
-		}
+		if (!force && phase != ExecutionPhase.QUEUED && phase != ExecutionPhase.HELD && phase != ExecutionPhase.PENDING && phase != ExecutionPhase.UNKNOWN)
+			throw new UWSException(UWSException.BAD_REQUEST, UWSExceptionFactory.incorrectPhaseTransition(job.getJobId(), phase, ExecutionPhase.QUEUED));
+		phase = ExecutionPhase.QUEUED;
 	}
 
 	/**
 	 * Changes the current phase to {@link ExecutionPhase#EXECUTING EXECUTING}.
-	 * 
-	 * @param force			<i>true</i> to ignore the phases order, <i>false</i> otherwise.
-	 * 
-	 * @throws UWSException	If this phase transition is forbidden <i>(by default: IF force=false AND currentPhase != EXECUTING or SUSPENDED or QUEUED or UNKNOWN)</i>.
+	 *
+	 * @param force	<i>true</i> to ignore the phases order,
+	 *             	<i>false</i> otherwise.
+	 *
+	 * @throws UWSException	If this phase transition is forbidden
+	 *                     	<i>(by default: IF force=false
+	 *                     	AND currentPhase != EXECUTING, HELD, SUSPENDED,
+	 *                     	                    QUEUED and UNKNOWN)</i>.
 	 */
 	protected void setExecutingPhase(boolean force) throws UWSException{
-		if (force)
-			phase = ExecutionPhase.EXECUTING;
-		else{
-			if (phase != ExecutionPhase.EXECUTING && phase != ExecutionPhase.SUSPENDED && phase != ExecutionPhase.PENDING && phase != ExecutionPhase.QUEUED && phase != ExecutionPhase.UNKNOWN)
-				throw new UWSException(UWSException.BAD_REQUEST, UWSExceptionFactory.incorrectPhaseTransition(job.getJobId(), phase, ExecutionPhase.EXECUTING));
-
-			phase = ExecutionPhase.EXECUTING;
-		}
+		if (!force && phase != ExecutionPhase.EXECUTING && phase != ExecutionPhase.HELD && phase != ExecutionPhase.SUSPENDED && phase != ExecutionPhase.QUEUED && phase != ExecutionPhase.UNKNOWN)
+			throw new UWSException(UWSException.BAD_REQUEST, UWSExceptionFactory.incorrectPhaseTransition(job.getJobId(), phase, ExecutionPhase.EXECUTING));
+		phase = ExecutionPhase.EXECUTING;
 	}
 
 	/**
 	 * Changes the current phase to {@link ExecutionPhase#COMPLETED COMPLETED}.
-	 * 
-	 * @param force			<i>true</i> to ignore the phases order, <i>false</i> otherwise.
-	 * 
-	 * @throws UWSException	If this phase transition is forbidden <i>(by default: IF force=false AND currentPhase != COMPLETED or EXECUTING or UNKNOWN)</i>.
+	 *
+	 * @param force	<i>true</i> to ignore the phases order,
+	 *             	<i>false</i> otherwise.
+	 *
+	 * @throws UWSException	If this phase transition is forbidden
+	 *                     	<i>(by default: IF force=false
+	 *                     	AND currentPhase != COMPLETED, EXECUTING
+	 *                     	                    and UNKNOWN)</i>.
 	 */
 	protected void setCompletedPhase(boolean force) throws UWSException{
-		if (force)
-			phase = ExecutionPhase.COMPLETED;
-		else{
-			if (phase != ExecutionPhase.COMPLETED && phase != ExecutionPhase.EXECUTING && phase != ExecutionPhase.UNKNOWN)
-				throw new UWSException(UWSException.BAD_REQUEST, UWSExceptionFactory.incorrectPhaseTransition(job.getJobId(), phase, ExecutionPhase.COMPLETED));
-
-			phase = ExecutionPhase.COMPLETED;
-		}
+		if (!force && phase != ExecutionPhase.COMPLETED && phase != ExecutionPhase.EXECUTING && phase != ExecutionPhase.UNKNOWN)
+			throw new UWSException(UWSException.BAD_REQUEST, UWSExceptionFactory.incorrectPhaseTransition(job.getJobId(), phase, ExecutionPhase.COMPLETED));
+		phase = ExecutionPhase.COMPLETED;
 	}
 
 	/**
 	 * Changes the current phase to {@link ExecutionPhase#ABORTED ABORTED}.
-	 * 
-	 * @param force			<i>true</i> to ignore the phases order, <i>false</i> otherwise.
-	 * 
-	 * @throws UWSException	If this phase transition is forbidden <i>(by default: IF force=false AND currentPhase = COMPLETED or ERROR)</i>.
+	 *
+	 * @param force	<i>true</i> to ignore the phases order,
+	 *             	<i>false</i> otherwise.
+	 *
+	 * @throws UWSException	If this phase transition is forbidden
+	 *                     	<i>(by default: IF force=false
+	 *                     	AND currentPhase = COMPLETED, ERROR
+	 *                     	                   or ARCHIVED)</i>.
 	 */
 	protected void setAbortedPhase(boolean force) throws UWSException{
-		if (force)
-			phase = ExecutionPhase.ABORTED;
-		else{
-			if (phase == ExecutionPhase.COMPLETED || phase == ExecutionPhase.ERROR)
-				throw new UWSException(UWSException.BAD_REQUEST, UWSExceptionFactory.incorrectPhaseTransition(job.getJobId(), phase, ExecutionPhase.ABORTED));
-
-			phase = ExecutionPhase.ABORTED;
-		}
+		if (!force && (phase == ExecutionPhase.COMPLETED || phase == ExecutionPhase.ERROR || phase == ExecutionPhase.ARCHIVED))
+			throw new UWSException(UWSException.BAD_REQUEST, UWSExceptionFactory.incorrectPhaseTransition(job.getJobId(), phase, ExecutionPhase.ABORTED));
+		phase = ExecutionPhase.ABORTED;
 	}
 
 	/**
 	 * Changes the current phase to {@link ExecutionPhase#ERROR ERROR}.
-	 * 
-	 * @param force			<i>true</i> to ignore the phases order, <i>false</i> otherwise.
-	 * 
-	 * @throws UWSException	If this phase transition is forbidden <i>(by default: IF force=false AND currentPhase = COMPLETED or ABORTED)</i>.
+	 *
+	 * @param force	<i>true</i> to ignore the phases order,
+	 *             	<i>false</i> otherwise.
+	 *
+	 * @throws UWSException	If this phase transition is forbidden
+	 *                     	<i>(by default: IF force=false
+	 *                     	AND currentPhase = COMPLETED, ABORTED
+	 *                     	                   or ARCHIVED)</i>.
 	 */
 	protected void setErrorPhase(boolean force) throws UWSException{
-		if (force)
-			phase = ExecutionPhase.ERROR;
-		else{
-			if (phase == ExecutionPhase.COMPLETED || phase == ExecutionPhase.ABORTED)
-				throw new UWSException(UWSException.BAD_REQUEST, UWSExceptionFactory.incorrectPhaseTransition(job.getJobId(), phase, ExecutionPhase.ERROR));
-
-			phase = ExecutionPhase.ERROR;
-		}
+		if (!force && (phase == ExecutionPhase.COMPLETED || phase == ExecutionPhase.ABORTED || phase == ExecutionPhase.ARCHIVED))
+			throw new UWSException(UWSException.BAD_REQUEST, UWSExceptionFactory.incorrectPhaseTransition(job.getJobId(), phase, ExecutionPhase.ERROR));
+		phase = ExecutionPhase.ERROR;
 	}
 
 	/**
 	 * Changes the current phase to {@link ExecutionPhase#HELD HELD}.
-	 * 
-	 * @param force			<i>true</i> to ignore the phases order, <i>false</i> otherwise.
-	 * 
-	 * @throws UWSException	If this phase transition is forbidden <i>(by default: IF force=false AND currentPhase != HELD or PENDING or UNKNOWN)</i>.
+	 *
+	 * @param force	<i>true</i> to ignore the phases order,
+	 *             	<i>false</i> otherwise.
+	 *
+	 * @throws UWSException	If this phase transition is forbidden
+	 *                     	<i>(by default: IF force=false
+	 *                     	AND currentPhase != HELD, PENDING, EXECUTING
+	 *                     	                    and UNKNOWN)</i>.
 	 */
 	protected void setHeldPhase(boolean force) throws UWSException{
-		if (!force && phase != ExecutionPhase.HELD && phase != ExecutionPhase.PENDING && phase != ExecutionPhase.UNKNOWN)
+		if (!force && phase != ExecutionPhase.HELD && phase != ExecutionPhase.PENDING && phase != ExecutionPhase.EXECUTING && phase != ExecutionPhase.UNKNOWN)
 			throw new UWSException(UWSException.BAD_REQUEST, UWSExceptionFactory.incorrectPhaseTransition(job.getJobId(), phase, ExecutionPhase.HELD));
 		phase = ExecutionPhase.HELD;
 	}
 
 	/**
 	 * Changes the current phase to {@link ExecutionPhase#SUSPENDED SUSPENDED}.
-	 * 
-	 * @param force			<i>true</i> to ignore the phases order, <i>false</i> otherwise.
-	 * 
-	 * @throws UWSException	By default, never !
+	 *
+	 * @param force	<i>true</i> to ignore the phases order,
+	 *             	<i>false</i> otherwise.
+	 *
+	 * @throws UWSException	If this phase transition is forbidden
+	 *                     	<i>(by default: IF force=false
+	 *                     	AND currentPhase != SUSPENDED, EXECUTING
+	 *                     	                    and UNKNOWN)</i>.
 	 */
 	protected void setSuspendedPhase(boolean force) throws UWSException{
+		if (!force && phase != ExecutionPhase.SUSPENDED && phase != ExecutionPhase.EXECUTING && phase != ExecutionPhase.UNKNOWN)
+			throw new UWSException(UWSException.BAD_REQUEST, UWSExceptionFactory.incorrectPhaseTransition(job.getJobId(), phase, ExecutionPhase.SUSPENDED));
 		phase = ExecutionPhase.SUSPENDED;
 	}
 
+	/**
+	 * Changes the current phase to {@link ExecutionPhase#ARCHIVED ARCHIVED}.
+	 *
+	 * @param force	<i>true</i> to ignore the phases order,
+	 *             	<i>false</i> otherwise.
+	 *
+	 * @throws UWSException	If this phase transition is forbidden
+	 *                     	<i>(by default: IF force=false
+	 *                     	AND currentPhase != ARCHIVED, COMPLETED, ABORTED,
+	 *                     	                    and UNKNOWN)</i>.
+	 *
+	 * @since 4.3
+	 */
+	protected void setArchivedPhase(boolean force) throws UWSException{
+		if (!force && phase != ExecutionPhase.ARCHIVED && phase != ExecutionPhase.COMPLETED && phase != ExecutionPhase.ABORTED && phase != ExecutionPhase.ERROR && phase != ExecutionPhase.UNKNOWN)
+			throw new UWSException(UWSException.BAD_REQUEST, UWSExceptionFactory.incorrectPhaseTransition(job.getJobId(), phase, ExecutionPhase.ARCHIVED));
+		phase = ExecutionPhase.ARCHIVED;
+	}
+
 	/**
 	 * Changes the current phase to {@link ExecutionPhase#UNKNOWN UNKNOWN}.
-	 * 
-	 * @param force			<i>true</i> to ignore the phases order, <i>false</i> otherwise.
-	 * 
-	 * @throws UWSException	By default, never !
+	 *
+	 * @param force	<i>true</i> to ignore the phases order,
+	 *             	<i>false</i> otherwise.
+	 *
+	 * @throws UWSException	By default, never!
 	 */
 	protected void setUnknownPhase(boolean force) throws UWSException{
 		phase = ExecutionPhase.UNKNOWN;
 	}
 
 	/**
-	 * <p>Indicates whether the job attributes (except errors and results) can be updated, considering its current phase.</p>
-	 * 
-	 * <p><i><u>Note:</u> By default, it returns TRUE only if the current phase is equals to {@link ExecutionPhase#PENDING PENDING} !</i></p>
-	 * 
-	 * @return	<i>true</i> if the job can be updated, <i>false</i> otherwise.
+	 * Indicates whether the job attributes (except errors and results) can be
+	 * updated, considering its current phase.
+	 *
+	 * <p><i>Note:
+	 * 	By default, it returns TRUE only if the current phase is equals to
+	 * 	{@link ExecutionPhase#PENDING PENDING}!
+	 * </i></p>
+	 *
+	 * @return	<i>true</i> if the job can be updated,
+	 *        	<i>false</i> otherwise.
 	 */
 	public boolean isJobUpdatable(){
 		return phase == ExecutionPhase.PENDING;
 	}
 
 	/**
-	 * <p>Indicates whether the job is finished or not, considering its current phase.</p>
-	 * 
-	 * <p><i><u>Note:</u> By default, it returns TRUE only if the current phase is either {@link ExecutionPhase#COMPLETED COMPLETED},
-	 * {@link ExecutionPhase#ABORTED ABORTED} or {@link ExecutionPhase#ERROR ERROR} !</i></p>
-	 * 
-	 * @return	<i>true</i> if the job is finished, <i>false</i> otherwise.
+	 * Indicates whether the job is finished or not, considering its current
+	 * phase.
+	 *
+	 * <p><i>Note:
+	 * 	By default, it returns TRUE only if the current phase is either
+	 * 	{@link ExecutionPhase#COMPLETED COMPLETED},
+	 * 	{@link ExecutionPhase#ABORTED ABORTED},
+	 * 	{@link ExecutionPhase#ERROR ERROR}
+	 * 	or {@link ExecutionPhase#ARCHIVED ARCHIVED}!
+	 * </i></p>
+	 *
+	 * @return	<i>true</i> if the job is finished,
+	 *        	<i>false</i> otherwise.
 	 */
 	public boolean isFinished(){
-		return phase == ExecutionPhase.COMPLETED || phase == ExecutionPhase.ABORTED || phase == ExecutionPhase.ERROR;
+		return phase == ExecutionPhase.COMPLETED || phase == ExecutionPhase.ABORTED || phase == ExecutionPhase.ERROR || phase == ExecutionPhase.ARCHIVED;
 	}
 
 	/**
-	 * <p>Indicates whether the job is executing, considering its current phase.</p>
-	 * 
-	 * <p><i><u>Note:</u> By default, it returns TRUE only if the current phase is {@link ExecutionPhase#EXECUTING EXECUTING} !</i></p>
-	 * 
-	 * @return	<i>true</i> if the job is executing, <i>false</i> otherwise.
+	 * Indicates whether the job is executing, considering its current phase.
+	 *
+	 * <p><i>Note:
+	 * 	By default, it returns TRUE only if the current phase is
+	 * 	{@link ExecutionPhase#EXECUTING EXECUTING}!
+	 * </i></p>
+	 *
+	 * @return	<i>true</i> if the job is executing,
+	 *        	<i>false</i> otherwise.
 	 */
 	public boolean isExecuting(){
 		return phase == ExecutionPhase.EXECUTING;
diff --git a/src/uws/job/UWSJob.java b/src/uws/job/UWSJob.java
index 35b45af..ddf5504 100644
--- a/src/uws/job/UWSJob.java
+++ b/src/uws/job/UWSJob.java
@@ -59,27 +59,35 @@ import uws.service.request.UploadFile;
  *
  * <ul>
  * 	<li>
- * 		The job attributes <i>startTime</i> and <i>endTime</i> are automatically managed by {@link UWSJob}. You don't have to do anything !
- * 		The date/time format is managed automatically by the library and can not be customized since it is imposed by the UWS
+ * 		The job attributes <i>creationTime</i>, <i>startTime</i> and
+ * 		<i>endTime</i> are automatically managed by {@link UWSJob}. You don't
+ * 		have to do anything! The date/time format is managed automatically by
+ * 		the library and can not be customized since it is imposed by the UWS
  * 		protocol definition: ISO-8601.
  * 	</li>
  * 	<br />
- * 	<li>Once set, the <i>destruction</i> and the <i>executionDuration</i> attributes are automatically managed. That is to say:
+ * 	<li>
+ * 		Once set, the <i>destruction</i> and the <i>executionDuration</i>
+ * 		attributes are automatically managed. That is to say:
  * 		<ul>
- * 			<li><u>if the destruction time is reached:</u> the job stops and it is destroyed by its job list</li>
- * 			<li><u>if the execution duration is elapsed:</u> the job stops and the phase is put to {@link ExecutionPhase#ABORTED ABORTED}.</li>
+ * 			<li><u>if the destruction time is reached:</u> the job stops and it
+ * 				is destroyed by its job list</li>
+ * 			<li><u>if the execution duration is elapsed:</u> the job stops and
+ * 				the phase is put to {@link ExecutionPhase#ABORTED ABORTED}.</li>
  * 		</ul>
  * 	</li>
  * 	<br />
  * 	<li>
- * 		<u>The <i>owner</i> attribute is set at the job creation and can not be changed after</u> ! If no owner is given at the job creation,
- * 		its default value is <i>null</i>.
+ * 		<u>The <i>owner</i> attribute is set at the job creation and can not be
+ * 		changed after</u> ! If no owner is given at the job creation, its
+ * 		default value is <i>null</i>.
  * 	</li>
  * 	<br />
  * 	<li>
- * 		If your job is executable, do not forget to set the <i>quote</i> parameter
- * 		ONLY by using the {@link #setQuote(long)} method (a negative value or {@link #QUOTE_NOT_KNOWN} value
- * 		indicates the quote is not known ; {@link #QUOTE_NOT_KNOWN} is the default value).
+ * 		If your job is executable, do not forget to set the <i>quote</i>
+ * 		parameter ONLY by using the {@link #setQuote(long)} method (a negative
+ * 		value or {@link #QUOTE_NOT_KNOWN} value indicates the quote is not
+ * 		known ; {@link #QUOTE_NOT_KNOWN} is the default value).
  * 	</li>
  * </ul>
  *
@@ -88,29 +96,33 @@ import uws.service.request.UploadFile;
  * <ul>
  * 	<li>
  * 		<b>{@link #generateJobId()}:</b>
- * 					This function is called at the construction of any {@link UWSJob}. It allows to generate a unique job ID.
- * 					By default: time (in milliseconds) + a upper-case letter (A, B, C, ....).
- * 					<u>If you want customizing the job ID of your jobs</u>, you need to override this function or to use the new function
- * 	                {@link #UWSJob(JobOwner, UWSParameters, String)}.
+ * 		This function is called at the construction of any {@link UWSJob}. It
+ * 		allows to generate a unique job ID. By default:
+ * 		       time (in milliseconds) + a upper-case letter (A, B, C, ....).
+ * 		<u>If you want customizing the job ID of your jobs</u>, you need to
+ * 		override this function or to use the new function
+ * 		{@link #UWSJob(JobOwner, UWSParameters, String)}.
  * 	</li>
  * 	<br />
  * 	<li>
  * 		<b>{@link #clearResources()}:</b>
- * 					This method is called <u>only at the destruction of the job</u>.
- * 					By default, the job is stopped (if running), thread resources are freed,
- * 					the job is removed from its jobs list and result/error files are deleted.
+ * 		This method is called <u>only at the destruction of the job</u>.
+ * 		By default, the job is stopped (if running), thread resources are freed,
+ * 		the job is removed from its jobs list and result/error files are
+ * 		deleted.
  * 	</li>
  * 	<br />
  * 	<li>
  * 		<b>{@link #setPhaseManager(JobPhase)}:</b>
- * 					Lets customizing the default behaviors of all the execution phases for any job instance.
- * 					For more details see {@link JobPhase}.
+ * 		Lets customizing the default behaviors of all the execution phases for
+ * 		any job instance. For more details see {@link JobPhase}.
  * 	</li>
  * 	<br />
  * 	<li>
  * 		<b>{@link #addObserver(JobObserver)}:</b>
- * 					An instance of any kind of AbstractJob can be observed by objects which implements {@link JobObserver} (i.e. {@link uws.service.UWSService}).
- * 					Observers are notified at any change of the execution phase.
+ * 		An instance of any kind of AbstractJob can be observed by objects which
+ * 		implements {@link JobObserver} (i.e. {@link uws.service.UWSService}).
+ * 		Observers are notified at any change of the execution phase.
  * 	</li>
  * </ul>
  *
@@ -196,44 +208,62 @@ public class UWSJob extends SerializableUWSObject {
 	/* ********* */
 	/* VARIABLES */
 	/* ********* */
-	/** The last generated job ID. <b>It SHOULD be used ONLY by the function {@link #generateJobId()} !</b> */
+	/** The last generated job ID. <b>It SHOULD be used ONLY by the function
+	 * {@link #generateJobId()} !</b> */
 	protected static String lastId = System.currentTimeMillis() + "A";
 
-	/** The identifier of the job (it MUST be different from any other job).<BR />
-	 * <i><u>Note:</u> It is assigned automatically at the job creation in any job constructor
-	 * by the function {@link #generateJobId()}.
-	 * To change the way this ID is generated or its format you must override this function.</i> */
+	/** The identifier of the job (it MUST be different from any other job).
+	 * <p><i>Note:
+	 * 	It is assigned automatically at the job creation in any job constructor
+	 * 	by the function {@link #generateJobId()}. To change the way this ID is
+	 * 	generated or its format you must override this function.
+	 * </i></p> */
 	protected final String jobId;
 
-	/** Date of the initial creation of this job.<BR />
-	  * <i><u>Note:</u> This attribute can be set only automatically at creation
-	  * by the UWS service and can not be set or changed by a user (even its
-	  * owner).</i>
+	/** Date of the initial creation of this job.
+	  * <p><i>Note:
+	  * 	This attribute can be set only automatically at creation by the UWS
+	  * 	service and can not be set or changed by a user (even its owner).
+	  * </i></p>
 	  * @since 4.3 */
 	protected final Date creationTime;
 
-	/** The identifier of the creator of this job.<BR />
-	 * <i><u>Note:</u> This object will not exist for all invocations of the UWS conformant protocol,
-	 * but only in cases where the access to the service is authenticated.</i> */
+	/** The identifier of the creator of this job.
+	 * <p><i>Note:
+	 * 	This object will not exist for all invocations of the UWS conformant
+	 * 	protocol, but only in cases where the access to the service is
+	 * 	authenticated.
+	 * </i></p> */
 	protected final JobOwner owner;
 
 	/** The jobs list which is supposed to managed this job. */
 	private JobList myJobList = null;
 
 	/**
-	 * <p>The current phase of the job.</p>
-	 * <i><u>Remember:</u> A job is treated as a state machine thanks to this attribute.
+	 * The current phase of the job.
+	 * <p><b>Remember:</b>
+	 * 	A job is treated as a state machine thanks to this attribute.
+	 * </p>
 	 * <ul>
-	 * 	<li>A successful job will normally progress through the {@link ExecutionPhase#PENDING PENDING},
-	 * 		{@link ExecutionPhase#QUEUED QUEUED}, {@link ExecutionPhase#EXECUTING EXECUTING}, {@link ExecutionPhase#COMPLETED COMPLETED}
-	 * 		phases in that order.</li>
-	 * 	<li>At any time before the {@link ExecutionPhase#COMPLETED COMPLETED} phase a job may either be {@link ExecutionPhase#ABORTED ABORTED}
-	 * 		or may suffer an {@link ExecutionPhase#ERROR ERROR}.</li>
-	 * 	<li>If the UWS reports an {@link ExecutionPhase#UNKNOWN UNKNOWN} phase, then all the client can do is re-query the phase until a known phase is reported.</li>
-	 * 	<li>A UWS may place a job in a {@link ExecutionPhase#HELD HELD} phase on receipt of a PHASE=RUN request it for some reason the job cannot be immediately queued
-	 * 	- in this case it is the responsibility of the client to request PHASE=RUN again at some later time.</li>
-	 * </ul></i>
-	 */
+	 * 	<li>A successful job will normally progress through the
+	 * 		{@link ExecutionPhase#PENDING PENDING},
+	 * 		{@link ExecutionPhase#QUEUED QUEUED},
+	 * 		{@link ExecutionPhase#EXECUTING EXECUTING},
+	 * 		{@link ExecutionPhase#COMPLETED COMPLETED} phases in that
+	 * 		order.</li>
+	 * 	<li>At any time before the
+	 * 		{@link ExecutionPhase#COMPLETED COMPLETED} phase a job may
+	 * 		either be {@link ExecutionPhase#ABORTED ABORTED} or may suffer
+	 * 		an {@link ExecutionPhase#ERROR ERROR}.</li>
+	 * 	<li>If the UWS reports an {@link ExecutionPhase#UNKNOWN UNKNOWN}
+	 * 		phase, then all the client can do is re-query the phase until a
+	 * 		known phase is reported.</li>
+	 * 	<li>A UWS may place a job in a {@link ExecutionPhase#HELD HELD}
+	 * 		phase on receipt of a PHASE=RUN request it for some reason the
+	 * 		job cannot be immediately queued - in this case it is the
+	 * 		responsibility of the client to request PHASE=RUN again at some
+	 * 		later time.</li>
+	 * </ul> */
 	private JobPhase phase;
 
 	/** The used date formatter.
@@ -242,9 +272,12 @@ public class UWSJob extends SerializableUWSObject {
 	public static final DateFormat dateFormat = new SimpleDateFormat(DEFAULT_DATE_FORMAT);
 
 	/**
-	 * This time (in seconds) predicts when the job is likely to complete.<br />
-	 * <b>It CAN NOT be changed after the job creation !<br />
-	 * <i>By default if no ID is given, {@link #quote} is set to {@link #QUOTE_NOT_KNOWN} (= {@value #QUOTE_NOT_KNOWN}).</i></b>
+	 * This time (in seconds) predicts when the job is likely to complete.
+	 * <p><b>WARNING:</b>
+	 * 	It CAN NOT be changed after the job creation!
+	 * 	By default if no ID is given, {@link #quote} is set to
+	 * 	{@link #QUOTE_NOT_KNOWN} (= {@value #QUOTE_NOT_KNOWN}).
+	 * </p>
 	 */
 	private long quote = QUOTE_NOT_KNOWN;
 
@@ -254,9 +287,12 @@ public class UWSJob extends SerializableUWSObject {
 	/** The time at which the job execution ended. */
 	private Date endTime = null;
 
-	/** <p>This error summary gives a human-readable error message for the underlying job.</p>
-	 * <i><u>Note:</u> This object is intended to be a detailed error message, and consequently,
-	 * might be a large piece of text such as a stack trace.</i> */
+	/** This error summary gives a human-readable error message for the
+	 * underlying job.
+	 * <p><i>Note:
+	 * 	This object is intended to be a detailed error message, and
+	 * 	consequently, might be a large piece of text such as a stack trace.
+	 * </i></p> */
 	protected ErrorSummary errorSummary = null;
 
 	/** This is a list of all results of this job. */
@@ -275,20 +311,27 @@ public class UWSJob extends SerializableUWSObject {
 	/** The time (in ms) to wait the end of the thread after an interruption. */
 	protected long waitForStop = 1000;
 
-	/** Objects which want to be notified at each modification of the execution phase of this job. */
+	/** Objects which want to be notified at each modification of the execution
+	 * phase of this job. */
 	private Vector<JobObserver> observers = new Vector<JobObserver>();
 
-	/** If this job has been restored, this attribute should be set with the date of its restoration. */
+	/** If this job has been restored, this attribute should be set with the
+	 * date of its restoration. */
 	private final Date restorationDate;
 
 	/* ************ */
 	/* CONSTRUCTORS */
 	/* ************ */
 	/**
-	 * <p>Builds a job with no owner from a map of all parameters (UWS and additional parameters).</p>
+	 * Builds a job with no owner from a map of all parameters (UWS and
+	 * additional parameters).
 	 *
-	 * <p><i><u>Note:</u> if the parameter {@link UWSJob#PARAM_PHASE} (</i>phase<i>) is given with the value {@link UWSJob#PHASE_RUN}
-	 * the job execution starts immediately after the job has been added to a job list or after {@link #applyPhaseParam(JobOwner)} is called.</i></p>
+	 * <p><i>Note:
+	 * 	If the parameter {@link UWSJob#PARAM_PHASE} (</i>phase<i>) is given with
+	 * 	the value {@link UWSJob#PHASE_RUN} the job execution starts immediately
+	 * 	after the job has been added to a job list or after
+	 * 	{@link #applyPhaseParam(JobOwner)} is called.
+	 * </i></p>
 	 *
 	 * @param params	UWS standard and non-standard parameters.
 	 *
@@ -323,7 +366,7 @@ public class UWSJob extends SerializableUWSObject {
 
 		results = new HashMap<String,Result>();
 
-		inputParams = params;
+		inputParams = (params == null ? new UWSParameters() : params);
 		inputParams.init();
 
 		jobId = generateJobId();
@@ -339,16 +382,23 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Builds a job of the given owner and from a map of all parameters (UWS and additional parameters).
-	 * The given HTTP request ID will be used as Job ID if not already used by another job.</p>
+	 * Builds a job of the given owner and from a map of all parameters (UWS and
+	 * additional parameters). The given HTTP request ID will be used as Job ID
+	 * if not already used by another job.
 	 *
-	 * <p><i><u>Note:</u> if the parameter {@link #PARAM_PHASE} (</i>phase<i>) is given with the value {@link #PHASE_RUN}
-	 * the job execution starts immediately after the job has been added to a job list or after {@link #applyPhaseParam(JobOwner)} is called.</i></p>
+	 * <p><i>Note:
+	 * 	If the parameter {@link #PARAM_PHASE} (</i>phase<i>) is given with the
+	 * 	value {@link #PHASE_RUN} the job execution starts immediately after the
+	 * 	job has been added to a job list or after
+	 * 	{@link #applyPhaseParam(JobOwner)} is called.
+	 * </i></p>
 	 *
 	 * @param owner		Job.owner ({@link #PARAM_OWNER}).
 	 * @param params	UWS standard and non-standard parameters.
-	 * @param requestID	ID of the HTTP request which has initiated the creation of this job.
-	 *                 	<i>Note: if NULL, empty or already used, a job ID will be generated thanks to {@link #generateJobId()}.</i>
+	 * @param requestID	ID of the HTTP request which has initiated the creation
+	 *                 	of this job.
+	 *                 	<i>Note: if NULL, empty or already used, a job ID will
+	 *                 	be generated thanks to {@link #generateJobId()}.</i>
 	 *
 	 * @see UWSParameters#init()
 	 *
@@ -363,7 +413,7 @@ public class UWSJob extends SerializableUWSObject {
 
 		results = new HashMap<String,Result>();
 
-		inputParams = params;
+		inputParams = (params == null ? new UWSParameters() : params);
 		inputParams.init();
 
 		// Set the Job ID with the value of the HTTP request ID (if not already used by a job):
@@ -471,13 +521,21 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>This function lets generating a unique ID.</p>
+	 * This function lets generating a unique ID.
 	 *
-	 * <p><i><b>By default:</b> System.currentTimeMillis()+UpperCharacter (UpperCharacter: one upper-case character chosen in order to guarantee the unicity of the ID: A, B, C, ....)</i></p>
+	 * <p><b>By default:</b>
+	 * 	System.currentTimeMillis()+UpperCharacter (UpperCharacter: one
+	 * 	upper-case character chosen in order to guarantee the unicity of the
+	 * 	ID: A, B, C, ....)
+	 * </p>
 	 *
-	 * <p><i><u>note: </u> DO NOT USE in this function any of the following functions: {@link #getLogger()},
-	 * {@link #getFileManager()} and {@link #getFactory()}. All of them will return NULL, because this job does not
-	 * yet know its jobs list (which is needed to know the UWS and so, all of the objects returned by these functions).</i></p>
+	 * <p><i>Note:
+	 * 	DO NOT USE in this function any of the following functions:
+	 * 	{@link #getLogger()}, {@link #getFileManager()} and
+	 * 	{@link #getFactory()}. All of them will return NULL, because this job
+	 * 	does not yet know its jobs list (which is needed to know the UWS and so,
+	 * 	all of the objects returned by these functions).
+	 * </i></p>
 	 *
 	 * @return	A unique job identifier.
 	 */
@@ -496,7 +554,7 @@ public class UWSJob extends SerializableUWSObject {
 	/**
 	 * <p>Gets the value of the specified parameter.</p>
 	 *
-	 * <p><i><u>note:</u>
+	 * <p><i>Note:
 	 * 	No case sensitivity for the UWS parameters ON THE CONTRARY TO the names
 	 * 	of the additional parameters (which are case sensitive).
 	 * </i></p>
@@ -532,17 +590,27 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Looks for an additional parameters which corresponds to the Execution Phase. If it exists and:</p>
+	 * Looks for an additional parameters which corresponds to the Execution
+	 * Phase. If it exists and:
+	 *
 	 * <ul>
-	 * 	<li> is equals to {@link UWSJob#PHASE_RUN RUN} => remove it from the attribute {@link #inputParams} and start the job.</li>
-	 * 	<li> is equals to {@link UWSJob#PHASE_ABORT ABORT} => remove it from the attribute {@link #inputParams} and abort the job.</li>
-	 * 	<li> is another value => the attribute is though removed from the attribute {@link #inputParams} but nothing is done.</li>
+	 * 	<li>is equals to {@link UWSJob#PHASE_RUN RUN}
+	 * 		=> remove it from the attribute {@link #inputParams}
+	 * 		   and start the job.</li>
+	 * 	<li>is equals to {@link UWSJob#PHASE_ABORT ABORT}
+	 * 		=> remove it from the attribute {@link #inputParams}
+	 * 		   and abort the job.</li>
+	 * 	<li>is another value
+	 * 		=> the attribute is though removed from the attribute
+	 * 		   {@link #inputParams} but nothing is done.</li>
 	 * </ul>
 	 *
-	 * @param user			The user who asks to apply the phase parameter (start/abort). (may be NULL)
+	 * @param user	The user who asks to apply the phase parameter
+	 *            	(start/abort). <i>May be NULL.</i>
 	 *
-	 * @throws UWSException	If it is impossible the state of this job (into EXECUTING or ABORTED)
-	 * 						or if the given user is not allowed to execute this job.
+	 * @throws UWSException	If it is impossible the state of this job
+	 *                     	(into EXECUTING or ABORTED) or if the given user is
+	 *                     	not allowed to execute this job.
 	 *
 	 * @see UWSParameters#hasInputPhase()
 	 * @see UWSParameters#getInputPhase()
@@ -574,7 +642,8 @@ public class UWSJob extends SerializableUWSObject {
 	/**
 	 * Gets the file manager used in this job.
 	 *
-	 * @return	Its file manager or <i>null</i> if this job is not into a {@link JobList} or if this jobs list is not into a {@link UWS}.
+	 * @return	Its file manager or <i>null</i> if this job is not into a
+	 *        	{@link JobList} or if this jobs list is not into a {@link UWS}.
 	 *
 	 * @see JobList#getUWS()
 	 * @see uws.service.UWS#getFileManager()
@@ -587,7 +656,8 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * Gets the logger of its UWS or a default one if the job list or the UWS is unknown.
+	 * Gets the logger of its UWS or a default one if the job list or the UWS
+	 * is unknown.
 	 *
 	 * @return	A logger.
 	 *
@@ -603,7 +673,8 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * Gets the factory to use to create the thread to execute when this job starts.
+	 * Gets the factory to use to create the thread to execute when this job
+	 * starts.
 	 *
 	 * @return	The factory to use to create a {@link JobThread}.
 	 */
@@ -635,18 +706,38 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Sets the current phase of this job.</p>
+	 * Sets the current phase of this job.
 	 *
-	 * <p><b><u>IMPORTANT:</u></b>
-	 * <ul><li>The order of all phases must be respected:<i> BY DEFAULT</i> <BR /> {@link ExecutionPhase#PENDING PENDING} ---> {@link ExecutionPhase#QUEUED QUEUED} ---> {@link ExecutionPhase#EXECUTING EXECUTING} ---> {@link ExecutionPhase#COMPLETED COMPLETED}.</li>
-	 * 	<li>The only way to go to the {@link ExecutionPhase#EXECUTING EXECUTING} phase is by sending a POST query with the value {@link UWSJob#PHASE_RUN RUN} for the parameter {@link UWSJob#PARAM_PHASE PHASE}.</li>
-	 * 	<li>The only way to go to the {@link ExecutionPhase#ABORTED ABORTED} phase is by sending a POST query with the value {@link UWSJob#PHASE_ABORT ABORT} for the parameter {@link UWSJob#PARAM_PHASE PHASE}.</li>
-	 * 	<li>The start time and the end time are set automatically when the phase is set to {@link ExecutionPhase#EXECUTING EXECUTING} and {@link ExecutionPhase#COMPLETED COMPLETED}, {@link ExecutionPhase#ABORTED ABORTED} or {@link ExecutionPhase#ERROR ERROR}</li>
-	 *</ul></p>
+	 * <p><b>IMPORTANT:</b></p>
+	 * <ul>
+	 * 	<li>
+	 * 		The order of all phases must be respected. By default:
+	 * 		{@link ExecutionPhase#PENDING PENDING} --->
+	 * 		{@link ExecutionPhase#QUEUED QUEUED} --->
+	 * 		{@link ExecutionPhase#EXECUTING EXECUTING} --->
+	 * 		{@link ExecutionPhase#COMPLETED COMPLETED}.</li>
+	 * 	<li>
+	 * 		The only way to go to the {@link ExecutionPhase#EXECUTING EXECUTING}
+	 * 		phase is by sending a POST query with the value
+	 * 		{@link UWSJob#PHASE_RUN RUN} for the parameter
+	 * 		{@link UWSJob#PARAM_PHASE PHASE}.</li>
+	 * 	<li>
+	 * 		The only way to go to the {@link ExecutionPhase#ABORTED ABORTED}
+	 * 		phase is by sending a POST query with the value
+	 * 		{@link UWSJob#PHASE_ABORT ABORT} for the parameter
+	 * 		{@link UWSJob#PARAM_PHASE PHASE}.</li>
+	 * 	<li>
+	 * 		The start time and the end time are set automatically when the phase
+	 * 		is set to {@link ExecutionPhase#EXECUTING EXECUTING} and
+	 * 		{@link ExecutionPhase#COMPLETED COMPLETED},
+	 * 		{@link ExecutionPhase#ABORTED ABORTED}
+	 * 		or {@link ExecutionPhase#ERROR ERROR}</li>
+	 * </ul>
 	 *
-	 * @param p					The phase to set for this job.
+	 * @param p	The phase to set for this job.
 	 *
-	 * @throws UWSException 	If the given phase does not respect the job's phases order.
+	 * @throws UWSException If the given phase does not respect the job's
+	 *                     	phases order.
 	 *
 	 * @see #setPhase(ExecutionPhase, boolean)
 	 */
@@ -655,19 +746,41 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Sets the current phase of this job, respecting or not the imposed order.</p>
+	 * Sets the current phase of this job, respecting or not the imposed order.
 	 *
-	 * <p><b><u>IMPORTANT:</u></b>
-	 * <ul><li><b><u>If the parameter <i>force</i> is <i>false</i></u></b>, the order of all phases must be respected:<BR /> {@link ExecutionPhase#PENDING PENDING} ---> {@link ExecutionPhase#QUEUED QUEUED} ---> {@link ExecutionPhase#EXECUTING EXECUTING} ---> {@link ExecutionPhase#COMPLETED COMPLETED}.</li>
-	 * 	<li>The only way to go to the {@link ExecutionPhase#EXECUTING EXECUTING} phase is by sending a POST query with the value {@link UWSJob#PHASE_RUN RUN} for the parameter {@link UWSJob#PARAM_PHASE PARAM_PHASE}.</li>
-	 * 	<li>The only way to go to the {@link ExecutionPhase#ABORTED ABORTED} phase is by sending a POST query with the value {@link UWSJob#PHASE_ABORT ABORT} for the parameter {@link UWSJob#PARAM_PHASE PARAM_PHASE}.</li>
-	 * 	<li>The start time and the end time are set automatically when the phase is set to {@link ExecutionPhase#EXECUTING EXECUTING} and {@link ExecutionPhase#COMPLETED COMPLETED}, {@link ExecutionPhase#ABORTED ABORTED} or {@link ExecutionPhase#ERROR ERROR}</li>
-	 *</ul></p>
-	 *
-	 * @param p		 The phase to set for this job.
-	 * @param force	<i>true</i> to impose the given execution phase, <i>false</i> to take into account the order of all phases.
-	 *
-	 * @throws UWSException If the given phase does not respect the job's phases order.
+	 * <p><b>IMPORTANT:</b></p>
+	 * <ul>
+	 * 	<li>
+	 * 		<b><u>If the parameter <i>force</i> is <i>false</i></u></b>,
+	 * 		the order of all phases must be respected:
+	 * 		{@link ExecutionPhase#PENDING PENDING} --->
+	 * 		{@link ExecutionPhase#QUEUED QUEUED} --->
+	 * 		{@link ExecutionPhase#EXECUTING EXECUTING} --->
+	 * 		{@link ExecutionPhase#COMPLETED COMPLETED}.</li>
+	 * 	<li>
+	 * 		The only way to go to the {@link ExecutionPhase#EXECUTING EXECUTING}
+	 * 		phase is by sending a POST query with the value
+	 * 		{@link UWSJob#PHASE_RUN RUN} for the parameter
+	 * 		{@link UWSJob#PARAM_PHASE PARAM_PHASE}.</li>
+	 * 	<li>
+	 * 		The only way to go to the {@link ExecutionPhase#ABORTED ABORTED}
+	 * 		phase is by sending a POST query with the value
+	 * 		{@link UWSJob#PHASE_ABORT ABORT} for the parameter
+	 * 		{@link UWSJob#PARAM_PHASE PARAM_PHASE}.</li>
+	 * 	<li>
+	 * 		The start time and the end time are set automatically when the phase
+	 * 		is set to {@link ExecutionPhase#EXECUTING EXECUTING} and
+	 * 		{@link ExecutionPhase#COMPLETED COMPLETED},
+	 * 		{@link ExecutionPhase#ABORTED ABORTED}
+	 * 		or {@link ExecutionPhase#ERROR ERROR}</li>
+	 *</ul>
+	 *
+	 * @param p		The phase to set for this job.
+	 * @param force	<i>true</i> to impose the given execution phase,
+	 *             	<i>false</i> to take into account the order of all phases.
+	 *
+	 * @throws UWSException If the given phase does not respect the job's
+	 *                     	phases order.
 	 *
 	 * @see JobPhase#setPhase(ExecutionPhase, boolean)
 	 * @see JobPhase#isFinished()
@@ -692,9 +805,12 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Gets the phase manager of this job.</p>
+	 * Gets the phase manager of this job.
 	 *
-	 * <p><i><u>Note:</u> The phase manager manages all the transitions between all the execution phases.</i></p>
+	 * <p><i>Note:
+	 * 	The phase manager manages all the transitions between all the execution
+	 * 	phases.
+	 * </i></p>
 	 *
 	 * @return	Its phase manager.
 	 */
@@ -703,11 +819,15 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Sets the phase manager of this job.</p>
+	 * Sets the phase manager of this job.
 	 *
-	 * <p><i><u>Note:</u> The phase manager manages all the transitions between all the execution phases.</i></p>
+	 * <p><i>Note:
+	 * 	The phase manager manages all the transitions between all the execution
+	 * 	phases.
+	 * </i></p>
 	 *
-	 * @param jobPhase	Its new phase manager (if <i>null</i> this function does nothing).
+	 * @param jobPhase	Its new phase manager (if <i>null</i> this function does
+	 *                	nothing).
 	 */
 	public final void setPhaseManager(JobPhase jobPhase){
 		if (jobPhase != null){
@@ -772,9 +892,13 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Sets the duration (in seconds) for which this job shall run ONLY IF the job can updated (considering its current execution phase, see {@link JobPhase#isJobUpdatable()}).</p>
+	 * Sets the duration (in seconds) for which this job shall run ONLY IF the
+	 * job can updated (considering its current execution phase, see
+	 * {@link JobPhase#isJobUpdatable()}).
 	 *
-	 * <p><i><u>Note:</u> A duration of 0 (or less) implies unlimited execution duration.</i></p>
+	 * <p><i>Note:
+	 * 	A duration of 0 (or less) implies unlimited execution duration.
+	 * </i></p>
 	 *
 	 * @param executionDuration The execution duration of this job.
 	 *
@@ -802,12 +926,13 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>
-	 * 	Sets the instant when the job shall be destroyed ONLY IF the job can updated (considering its current execution phase, see {@link JobPhase#isJobUpdatable()}).
-	 * 	If known the jobs list is notify of this destruction time update.
-	 * </p>
+	 * Sets the instant when the job shall be destroyed ONLY IF the job can
+	 * updated (considering its current execution phase, see
+	 * {@link JobPhase#isJobUpdatable()}). If known the jobs list is notify of
+	 * this destruction time update.
 	 *
-	 * @param destructionTime The destruction time of this job. <i>MUST NOT be NULL</i>
+	 * @param destructionTime	The destruction time of this job.
+	 *                       	<i>MUST NOT be NULL</i>
 	 *
 	 * @see JobList#updateDestruction(UWSJob)
 	 * @see UWSParameters#set(String, Object)
@@ -834,14 +959,20 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Sets the error that occurs during the execution of this job.</p>
+	 * Sets the error that occurs during the execution of this job.
 	 *
-	 * <p><b><u>IMPORTANT:</u> This function will have no effect if the job is finished, that is to say if the current phase is
-	 * {@link ExecutionPhase#ABORTED ABORTED}, {@link ExecutionPhase#ERROR ERROR} or {@link ExecutionPhase#COMPLETED COMPLETED}.</i>.</b></p>
+	 * <p><b>IMPORTANT:</b>
+	 * 	This function will have no effect if the job is finished, that is to say
+	 * 	if the current phase is {@link ExecutionPhase#ABORTED ABORTED},
+	 * 	{@link ExecutionPhase#ERROR ERROR},
+	 * 	{@link ExecutionPhase#COMPLETED COMPLETED}
+	 * 	or {@link ExecutionPhase#ARCHIVED ARCHIVED}.
+	 * </p>
 	 *
 	 * @param errorSummary	A summary of the error. <i>MUST NOT be NULL</i>
 	 *
-	 * @throws UWSException	If the job execution is finished that is to say if the phase is ABORTED, ERROR or COMPLETED.
+	 * @throws UWSException	If the job execution is finished that is to say if
+	 *                     	the phase is ABORTED, ERROR, COMPLETED or ARCHIVED.
 	 *
 	 * @see #isFinished()
 	 */
@@ -866,10 +997,15 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Gets the RunID of this job given by the UWS user (presumed to be the owner of this job).
-	 * This ID isn't the one used to access to this job thanks to the jobs list: it is more likely a label/name than an ID => it is not unique.</p>
+	 * Gets the RunID of this job given by the UWS user (presumed to be the
+	 * owner of this job). This ID isn't the one used to access to this job
+	 * thanks to the jobs list: it is more likely a label/name than an ID
+	 * => it is not unique.
 	 *
-	 * <p><b><u>Warning:</u> This ID may be used by other jobs BUT their job id (cf {@link UWSJob#getJobId()}) must be different.</b></p>
+	 * <p><b>WARNING:</b>
+	 * 	This ID may be used by other jobs BUT their job id
+	 * 	(cf {@link UWSJob#getJobId()}) must be different.
+	 * </p>
 	 *
 	 * @return The Run ID (a kind of job name/label).
 	 *
@@ -880,7 +1016,8 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Sets the RunID of this job ONLY IF the job can updated (considering its current execution phase, see {@link JobPhase#isJobUpdatable()}).</p>
+	 * Sets the RunID of this job ONLY IF the job can updated (considering
+	 * its current execution phase, see {@link JobPhase#isJobUpdatable()}).
 	 *
 	 * @param name	Its name/label.
 	 *
@@ -917,9 +1054,12 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Sets the quote attribute of this job ONLY IF the job can updated (considering its current execution phase, see {@link JobPhase#isJobUpdatable()}).</p>
+	 * Sets the quote attribute of this job ONLY IF the job can updated
+	 * (considering its current execution phase, see
+	 * {@link JobPhase#isJobUpdatable()}).
 	 *
-	 * @param nbSeconds	The estimated duration of the job execution (in seconds).
+	 * @param nbSeconds	The estimated duration of the job execution
+	 *                 	(in seconds).
 	 *
 	 * @see JobPhase#isJobUpdatable()
 	 */
@@ -952,20 +1092,25 @@ public class UWSJob extends SerializableUWSObject {
 	 * Gets the value of the specified additional parameter.
 	 *
 	 * @param paramName	The name of the parameter whose the value is wanted.
-	 * @return			The value of the specified parameter or <i>null</i> if it doesn't exist.
+	 *
+	 * @return	The value of the specified parameter
+	 *        	or <i>null</i> if it doesn't exist.
 	 */
 	public final Object getAdditionalParameterValue(String paramName){
 		return inputParams.getAdditionalParameters().get(paramName);
 	}
 
 	/**
-	 * Adds or updates the specified parameter with the given value ONLY IF the job can be updated (considering its current execution phase, see {@link JobPhase#isJobUpdatable()}).
+	 * Adds or updates the specified parameter with the given value ONLY IF the
+	 * job can be updated (considering its current execution phase, see
+	 * {@link JobPhase#isJobUpdatable()}).
 	 *
 	 * @param paramName		The name of the parameter to add or to update.
 	 * @param paramValue	The (new) value of the specified parameter.
 	 *
-	 * @return				<ul><li><i>true</i> if the parameter has been successfully added/updated,</li>
-	 * 						<li><i>false</i> otherwise <i>(particularly if paramName=null or paramName="" or paramValue=null)</i>.</li></ul>
+	 * @return	<i>true</i> if the parameter has been successfully added/updated,
+	 *        	<i>false</i> otherwise <i>(particularly if paramName=null or
+	 *        	paramName="" or paramValue=null)</i>.
 	 *
 	 * @throws UWSException	If a parameter value is incorrect.
 	 *
@@ -976,14 +1121,17 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * Adds or updates the specified parameter with the given value ONLY IF the job can be updated (considering its current execution phase, see {@link JobPhase#isJobUpdatable()}).
+	 * Adds or updates the specified parameter with the given value ONLY IF the
+	 * job can be updated (considering its current execution phase, see
+	 * {@link JobPhase#isJobUpdatable()}).
 	 *
 	 * @param paramName		The name of the parameter to add or to update.
 	 * @param paramValue	The (new) value of the specified parameter.
 	 * @param user			The user who asks for this update.
 	 *
-	 * @return				<ul><li><i>true</i> if the parameter has been successfully added/updated,</li>
-	 * 						<li><i>false</i> otherwise <i>(particularly if paramName=null or paramName="" or paramValue=null)</i>.</li></ul>
+	 * @return	<i>true</i> if the parameter has been successfully added/updated,
+	 *        	<i>false</i> otherwise <i>(particularly if paramName=null or
+	 *        	paramName="" or paramValue=null)</i>.
 	 *
 	 * @throws UWSException	If a parameter value is incorrect.
 	 *
@@ -1021,18 +1169,31 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Adds or updates the given parameters ONLY IF the job can be updated (considering its current execution phase, see {@link JobPhase#isJobUpdatable()}).</p>
+	 * Adds or updates the given parameters ONLY IF the job can be updated
+	 * (considering its current execution phase, see
+	 * {@link JobPhase#isJobUpdatable()}).
 	 *
-	 * <p>At the end of this function, the method {@link #applyPhaseParam(JobOwner)} is called so that if there is an additional parameter {@link #PARAM_PHASE} with the value:
+	 * <p>
+	 * 	At the end of this function, the method
+	 * 	{@link #applyPhaseParam(JobOwner)} is called so that if there is an
+	 * 	additional parameter {@link #PARAM_PHASE} with the value:
+	 * </p>
 	 * <ul>
-	 * 	<li>{@link UWSJob#PHASE_RUN RUN} then the job is starting and the phase goes to {@link ExecutionPhase#EXECUTING EXECUTING}.</li>
-	 * 	<li>{@link UWSJob#PHASE_ABORT ABORT} then the job is aborting.</li>
-	 * 	<li>otherwise the parameter {@link UWSJob#PARAM_PHASE PARAM_PHASE} is removed from {@link UWSJob#inputParams inputParams} and nothing is done.</li>
-	 * </ul></p>
+	 * 	<li>
+	 * 		{@link UWSJob#PHASE_RUN RUN} then the job is starting and the phase
+	 * 		goes to {@link ExecutionPhase#EXECUTING EXECUTING}.</li>
+	 * 	<li>
+	 * 		{@link UWSJob#PHASE_ABORT ABORT} then the job is aborting.</li>
+	 * 	<li>
+	 * 		otherwise the parameter {@link UWSJob#PARAM_PHASE PARAM_PHASE} is
+	 * 		removed from {@link UWSJob#inputParams inputParams} and nothing is
+	 * 		done.</li>
+	 * </ul>
 	 *
-	 * @param params		A list of parameters to add/update.
-	 * @return				<ul><li><i>true</i> if all the given parameters have been successfully added/updated,</li>
-	 * 						<li><i>false</i> if some parameters have not been managed.</li></ul>
+	 * @param params	A list of parameters to add/update.
+	 * @return	<i>true</i> if all the given parameters have been successfully
+	 *        	added/updated,
+	 *        	<i>false</i> if some parameters have not been managed.
 	 *
 	 * @throws UWSException	If a parameter value is incorrect.
 	 *
@@ -1054,22 +1215,36 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Adds or updates the given parameters ONLY IF the job can be updated (considering its current execution phase, see {@link JobPhase#isJobUpdatable()}).</p>
+	 * Adds or updates the given parameters ONLY IF the job can be updated
+	 * (considering its current execution phase, see
+	 * {@link JobPhase#isJobUpdatable()}).
 	 *
-	 * <p>At the end of this function, the method {@link #applyPhaseParam(JobOwner)} is called so that if there is an additional parameter {@link #PARAM_PHASE} with the value:
+	 * <p>
+	 * 	At the end of this function, the method
+	 * 	{@link #applyPhaseParam(JobOwner)} is called so that if there is an
+	 * 	additional parameter {@link #PARAM_PHASE} with the value:
+	 * </p>
 	 * <ul>
-	 * 	<li>{@link UWSJob#PHASE_RUN RUN} then the job is starting and the phase goes to {@link ExecutionPhase#EXECUTING EXECUTING}.</li>
-	 * 	<li>{@link UWSJob#PHASE_ABORT ABORT} then the job is aborting.</li>
-	 * 	<li>otherwise the parameter {@link UWSJob#PARAM_PHASE PARAM_PHASE} is removed from {@link UWSJob#inputParams inputParams} and nothing is done.</li>
+	 * 	<li>
+	 * 		{@link UWSJob#PHASE_RUN RUN} then the job is starting and the phase
+	 * 		goes to {@link ExecutionPhase#EXECUTING EXECUTING}.</li>
+	 * 	<li>
+	 * 		{@link UWSJob#PHASE_ABORT ABORT} then the job is aborting.</li>
+	 * 	<li>
+	 * 		otherwise the parameter {@link UWSJob#PARAM_PHASE PARAM_PHASE} is
+	 * 		removed from {@link UWSJob#inputParams inputParams} and nothing is
+	 * 		done.</li>
 	 * </ul></p>
 	 *
-	 * @param params		The UWS parameters to update.
-	 * @param user			The user who asks for this update.
+	 * @param params	The UWS parameters to update.
+	 * @param user		The user who asks for this update.
 	 *
-	 * @return				<ul><li><i>true</i> if all the given parameters have been successfully added/updated,</li>
-	 * 						<li><i>false</i> if some parameters have not been managed.</li></ul>
+	 * @return	<i>true</i> if all the given parameters have been successfully
+	 *        	added/updated,
+	 *        	<i>false</i> if some parameters have not been managed.
 	 *
-	 * @throws UWSException	If a parameter value is incorrect or if the given user can not update or execute this job.
+	 * @throws UWSException	If a parameter value is incorrect or if the given
+	 *                     	user can not update or execute this job.
 	 *
 	 * @see JobPhase#isJobUpdatable()
 	 * @see #applyPhaseParam(JobOwner)
@@ -1115,11 +1290,14 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * Removes the specified additional parameter ONLY IF the job can be updated (considering its current execution phase, see {@link JobPhase#isJobUpdatable()}).
+	 * Removes the specified additional parameter ONLY IF the job can be updated
+	 * (considering its current execution phase, see
+	 * {@link JobPhase#isJobUpdatable()}).
 	 *
 	 * @param paramName	The name of the parameter to remove.
 	 *
-	 * @return	<i>true</i> if the parameter has been successfully removed, <i>false</i> otherwise.
+	 * @return	<i>true</i> if the parameter has been successfully removed,
+	 *        	<i>false</i> otherwise.
 	 *
 	 * @see JobPhase#isJobUpdatable()
 	 * @see UWSParameters#remove(String)
@@ -1172,15 +1350,20 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Adds the given result in the results list of this job.</p>
+	 * Adds the given result in the results list of this job.
 	 *
-	 * <p><b><u>IMPORTANT:</u> This function will throw an error if the job is finished.</b></p>
+	 * <p><b>IMPORTANT:</b>
+	 * 	This function will throw an error if the job is finished.
+	 * </p>
 	 *
-	 * @param res			The result to add (<b>not null</b>).
+	 * @param res	The result to add (<b>not null</b>).
 	 *
-	 * @return				<i>true</i> if the result has been successfully added, <i>false</i> otherwise (for instance, if a result has the same ID).
+	 * @return	<i>true</i> if the result has been successfully added,
+	 *        	<i>false</i> otherwise (for instance, if a result has the same
+	 *        	ID).
 	 *
-	 * @throws UWSException	If the job execution is finished that is to say if the phase is ABORTED, ERROR or COMPLETED.
+	 * @throws UWSException	If the job execution is finished that is to say if
+	 *                     	the phase is ABORTED, ERROR, COMPLETED or ARCHIVED.
 	 *
 	 * @see #isFinished()
 	 */
@@ -1270,13 +1453,21 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Sets its jobs list.</p>
+	 * Sets its jobs list.
 	 *
-	 * <p><i><u>note 1:</u> a job can change its jobs list ONLY WHILE PENDING !</i></p>
-	 * <p><i><u>note 2:</u> this job is removed from its previous job list, if there is one.</i></p>
-	 * <p><i><u>note 3:</u> this job is NOT automatically added into the new jobs list. Indeed, this function should be called by {@link JobList#addNewJob(UWSJob)}.</i></p>
+	 * <p><i>Note 1:
+	 * 	A job can change its jobs list ONLY WHILE PENDING!
+	 * </i></p>
+	 * <p><i>Note 2:
+	 * 	This job is removed from its previous job list, if there is one.
+	 * </i></p>
+	 * <p><i>Note 3:
+	 * 	This job is NOT automatically added into the new jobs list. Indeed, this
+	 * 	function should be called by {@link JobList#addNewJob(UWSJob)}.
+	 * </i></p>
 	 *
-	 * @param jobList		Its new jobs list. <i><u>note:</u> if NULL, nothing is done !</i>
+	 * @param jobList	Its new jobs list.
+	 *               	<i>Note: if NULL, nothing is done!</i>
 	 *
 	 * @throws IllegalStateException	If this job is not PENDING.
 	 *
@@ -1319,7 +1510,8 @@ public class UWSJob extends SerializableUWSObject {
 	/**
 	 * Gets the time to wait for the end of the thread after an interruption.
 	 *
-	 * @return	The time to wait for the end of the thread  (a negative or null value means no wait for the end of the thread).
+	 * @return	The time to wait for the end of the thread (a negative or null
+	 *          value means no wait for the end of the thread).
 	 */
 	public final long getTimeToWaitForEnd(){
 		return waitForStop;
@@ -1328,14 +1520,16 @@ public class UWSJob extends SerializableUWSObject {
 	/**
 	 * Sets the time to wait for the end of the thread after an interruption.
 	 *
-	 * @param timeToWait	The new time to wait for the end of the thread (a negative or null value means no wait for the end of the thread).
+	 * @param timeToWait	The new time to wait for the end of the thread (a
+	 *                  	negative or null value means no wait for the end of
+	 *                  	the thread).
 	 */
 	public final void setTimeToWaitForEnd(long timeToWait){
 		waitForStop = timeToWait;
 	}
 
 	/**
-	 * <p>Starts the job by using the execution manager if any.</p>
+	 * Starts the job by using the execution manager if any.
 	 *
 	 * @throws UWSException
 	 */
@@ -1344,14 +1538,24 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Starts the job.</p>
+	 * Starts the job.
 	 *
-	 * <p><i><u>Note:</u> This function does nothing if the job is already running !</i></p>
+	 * <p><i>Note:
+	 * 	This function does nothing if the job is already running!
+	 * </i></p>
 	 *
-	 * @param useManager	<i>true</i> to let the execution manager deciding whether the job starts immediately or whether it must be put in a queue until enough resources are available, <i>false</i> to start the execution immediately.
+	 * @param useManager	<i>true</i> to let the execution manager deciding
+	 *                  	whether the job starts immediately or whether it
+	 *                  	must be put in a queue until enough resources are
+	 *                  	available,
+	 *                  	<i>false</i> to start the execution immediately.
 	 *
-	 * @throws NullPointerException	If this job is not associated with a job list or the associated job list is not part of a UWS service or if no thread is created.
-	 * @throws UWSException			If there is an error while changing the execution phase or when starting the corresponding thread.
+	 * @throws NullPointerException	If this job is not associated with a job
+	 *                             	list or the associated job list is not part
+	 *                             	of a UWS service or if no thread is created.
+	 * @throws UWSException			If there is an error while changing the
+	 *                     			execution phase or when starting the
+	 *                     			corresponding thread.
 	 *
 	 * @see #isRunning()
 	 * @see UWSFactory#createJobThread(UWSJob)
@@ -1424,11 +1628,16 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Tells whether the job is still running.</p>
+	 * Tells whether the job is still running.
 	 *
-	 * <p><i><u>Note:</u> This function tests the execution phase (see {@link JobPhase#isExecuting()}) AND the status of the thread (see {@link #isStopped()}).</i></p>
+	 * <p><i>Note:
+	 * 	This function tests the execution phase (see
+	 * 	{@link JobPhase#isExecuting()}) AND the status of the thread (see
+	 * 	{@link #isStopped()}).
+	 * </i></p>
 	 *
-	 * @return	<i>true</i> if the job is still running, <i>false</i> otherwise.
+	 * @return	<i>true</i> if the job is still running,
+	 *        	<i>false</i> otherwise.
 	 *
 	 * @see JobPhase#isExecuting()
 	 * @see #isStopped()
@@ -1438,11 +1647,17 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Tells whether the job is already finished (completed, aborted, error, ...).</p>
+	 * Tells whether the job is already finished (completed, aborted,
+	 * error, archived, ...).
 	 *
-	 * <p><i><u>Note:</u> This function test the execution phase (see {@link JobPhase#isFinished()}) AND the status of the thread (see {@link #isStopped()})</i></p>
+	 * <p><i>Note:
+	 * 	This function test the execution phase (see
+	 * 	{@link JobPhase#isFinished()}) AND the status of the thread (see
+	 * 	{@link #isStopped()}).
+	 * </i></p>
 	 *
-	 * @return	<i>true</i> if the job is finished, <i>false</i> otherwise.
+	 * @return	<i>true</i> if the job is finished,
+	 *        	<i>false</i> otherwise.
 	 *
 	 * @see JobPhase#isFinished()
 	 * @see #isStopped()
@@ -1452,12 +1667,18 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Stops immediately the job, sets its phase to {@link ExecutionPhase#ABORTED ABORTED} and sets its end time.</p>
+	 * Stops immediately the job, sets its phase to
+	 * {@link ExecutionPhase#ABORTED ABORTED} and sets its end time.
 	 *
-	 * <p><b><u>IMPORTANT:</u> If the thread does not stop immediately the phase and the end time are not modified. However it can be done by calling one more time {@link #abort()}.
-	 * Besides you should check that you test regularly the interrupted flag of the thread in {@link JobThread#jobWork()} !</b></p>
+	 * <p><b>IMPORTANT:</b>
+	 * 	If the thread does not stop immediately the phase and the end time are
+	 * 	not modified. However it can be done by calling one more time
+	 * 	{@link #abort()}. Besides you should check that you test regularly the
+	 * 	interrupted flag of the thread in {@link JobThread#jobWork()}!
+	 * </p>
 	 *
-	 * @throws UWSException	If there is an error while changing the execution phase.
+	 * @throws UWSException	If there is an error while changing the execution
+	 *                     	phase.
 	 *
 	 * @see #stop()
 	 * @see #isStopped()
@@ -1482,15 +1703,21 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Stops immediately the job, sets its error summary, sets its phase to {@link ExecutionPhase#ERROR} and sets its end time.</p>
+	 * Stops immediately the job, sets its error summary, sets its phase to
+	 * {@link ExecutionPhase#ERROR} and sets its end time.
 	 *
-	 * <p><b><u>IMPORTANT:</u> If the thread does not stop immediately the phase, the error summary and the end time are not modified.
-	 * However it can be done by calling one more time {@link #error(ErrorSummary)}.
-	 * Besides you should check that you test regularly the interrupted flag of the thread in {@link JobThread#jobWork()} !</b></p>
+	 * <p><b>IMPORTANT:</b>
+	 * 	If the thread does not stop immediately the phase, the error summary and
+	 * 	the end time are not modified. However it can be done by calling one
+	 * 	more time {@link #error(ErrorSummary)}. Besides you should check that
+	 * 	you test regularly the interrupted flag of the thread in
+	 * 	{@link JobThread#jobWork()}!
+	 * </p>
 	 *
-	 * @param error			The error that has interrupted this job.
+	 * @param error	The error that has interrupted this job.
 	 *
-	 * @throws UWSException	If there is an error while setting the error summary or while changing the phase.
+	 * @throws UWSException	If there is an error while setting the error summary
+	 *                     	or while changing the phase.
 	 *
 	 * @see #stop()
 	 * @see #isStopped()
@@ -1519,7 +1746,8 @@ public class UWSJob extends SerializableUWSObject {
 			getLogger().logJob(LogLevel.WARNING, this, "ERROR", "Stopping of the job \"" + getJobId() + "\" with error asked but not yet effective (after having waited " + waitForStop + "ms)!", null);
 	}
 
-	/** Used by the thread to known whether the {@link #stop()} method has already been called, and so, that the job is stopping. */
+	/** Used by the thread to known whether the {@link #stop()} method has
+	 * already been called, and so, that the job is stopping. */
 	protected boolean stopping = false;
 
 	/**
@@ -1546,27 +1774,37 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Tells whether the thread is different from <i>null</i>, is not alive or is finished (see {@link JobThread#isFinished()}).</p>
+	 * Tells whether the thread is different from <i>null</i>, is not alive or
+	 * is finished (see {@link JobThread#isFinished()}).
 	 *
 	 * <p><i><b>Important note:</b>
-	 * 	Having the interrupted flag set to <code>true</code> is not enough to consider the job as stopped.
-	 * 	So, if the job has been interrupted but is still running, it should mean that the {@link JobThread#jobWork()} does not
-	 * 	check the interrupted flag of the thread often enough or not at the right moments. In such case, the job can not be
-	 * 	considered as stopped/aborted - so the phase stays {@link ExecutionPhase#EXECUTING EXECUTING} - until the thread is "unblocked"
-	 * 	and the interruption is detected.
+	 * 	Having the interrupted flag set to <code>true</code> is not enough to
+	 * 	consider the job as stopped. So, if the job has been interrupted but is
+	 * 	still running, it should mean that the {@link JobThread#jobWork()} does
+	 * 	not check the interrupted flag of the thread often enough or not at the
+	 * 	right moments. In such case, the job can not be considered as
+	 * 	stopped/aborted - so the phase stays
+	 * 	{@link ExecutionPhase#EXECUTING EXECUTING} - until the thread is
+	 * 	"unblocked" and the interruption is detected.
 	 * </i></p>
 	 *
-	 * @return	<i>true</i> if the thread is not still running, <i>false</i> otherwise.
+	 * @return	<i>true</i> if the thread is not still running,
+	 *        	<i>false</i> otherwise.
 	 */
 	protected final boolean isStopped(){
 		return thread == null || !thread.isAlive() || thread.isFinished();
 	}
 
 	/**
-	 * <p>Stops the job if running, removes the job from the execution manager, stops the timer for the execution duration
-	 * and may clear all files or any other resources associated to this job.</p>
+	 * Stops the job if running, removes the job from the execution manager,
+	 * stops the timer for the execution duration and may clear all files or any
+	 * other resources associated to this job.
 	 *
-	 * <p><i>By default the job is aborted, the {@link UWSJob#thread} attribute is set to null, the timers are stopped and uploaded files, results and the error summary are deleted and the jobInfo is destroyed.</i></p>
+	 * <p><i>Note:
+	 * 	By default the job is aborted, the {@link UWSJob#thread} attribute is
+	 * 	set to null, the timers are stopped and uploaded files, results and the
+	 * 	error summary are deleted and the jobInfo is destroyed.
+	 * </i></p>
 	 */
 	public void clearResources(){
 		// If still running, abort/stop the job:
@@ -1631,11 +1869,14 @@ public class UWSJob extends SerializableUWSObject {
 	/* OBSERVER MANAGEMENT */
 	/* ******************* */
 	/**
-	 * Lets adding an observer of this job. The observer will be notified each time the execution phase changes.
+	 * Lets adding an observer of this job. The observer will be notified each
+	 * time the execution phase changes.
 	 *
 	 * @param observer	A new observer of this job.
 	 *
-	 * @return			<i>true</i> if the given object has been successfully added as observer of this job, <i>false</i> otherwise.
+	 * @return	<i>true</i> if the given object has been successfully added as
+	 *        	observer of this job,
+	 *        	<i>false</i> otherwise.
 	 */
 	public final boolean addObserver(JobObserver observer){
 		if (observer != null && !observers.contains(observer)){
@@ -1666,9 +1907,12 @@ public class UWSJob extends SerializableUWSObject {
 	/**
 	 * Lets removing the given object from the list of observers of this job.
 	 *
-	 * @param observer	The object which must not be considered as observer of this job.
+	 * @param observer	The object which must not be considered as observer of
+	 *                	this job.
 	 *
-	 * @return			<i>true</i> if the given object is not any more an observer of this job, <i>false</i> otherwise.
+	 * @return	<i>true</i> if the given object is not any more an observer of
+	 *        	this job,
+	 *        	<i>false</i> otherwise.
 	 */
 	public final boolean removeObserver(JobObserver observer){
 		return observers.remove(observer);
@@ -1710,13 +1954,20 @@ public class UWSJob extends SerializableUWSObject {
 	/* ERROR MANAGEMENT */
 	/* **************** */
 	/**
-	 * <p>Gets the error (if any) which has occurred during the job execution.</p>
+	 * Gets the error (if any) which has occurred during the job execution.
 	 *
-	 * <p><i><u>Note:</u> In the case an error summary can not have been published, the job has no error summary.
-	 * However the last {@link UWSException} caught during the execution of a {@link JobThread} is saved and is available thanks to {@link JobThread#getError()}.
-	 * In that case, the {@link UWSJob#getWorkError() getWorkError()} method can be used to get back the occurred error.</i></p>
+	 * <p><i>Note:
+	 * 	In the case an error summary can not have been published, the job has no
+	 * 	error summary. However the last {@link UWSException} caught during the
+	 * 	execution of a {@link JobThread} is saved and is available thanks to
+	 * 	{@link JobThread#getError()}. In that case, the
+	 * 	{@link UWSJob#getWorkError() getWorkError()} method can be used to get
+	 * 	back the occurred error.
+	 * </i></p>
 	 *
-	 * @return	The error which interrupts the thread or <i>null</i> if there was no error or if the job is still running.
+	 * @return	The error which interrupts the thread
+	 *        	or <i>null</i> if there was no error or if the job is still
+	 *        	running.
 	 */
 	public final UWSException getWorkError(){
 		return (thread == null || !thread.isAlive()) ? null : thread.getError();
@@ -1734,14 +1985,18 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * Serializes the specified attribute of this job by using the given serializer.
+	 * Serializes the specified attribute of this job by using the given
+	 * serializer.
 	 *
-	 * @param attributes		All the given attributes (may be <i>null</i> or empty).
-	 * @param serializer		The serializer to use.
+	 * @param attributes	All the given attributes.
+	 *                  	<i>May be <i>null</i> or empty.</i>
+	 * @param serializer	The serializer to use.
 	 *
-	 * @return					The serialized job attribute (or the whole job if <i>attributes</i> is an empty array or is <i>null</i>).
+	 * @return	The serialized job attribute (or the whole job if
+	 *        	<i>attributes</i> is an empty array or is <i>null</i>).
 	 *
-	 * @throws Exception		If there is an unexpected error during the serialization.
+	 * @throws Exception	If there is an unexpected error during the
+	 *                  	serialization.
 	 *
 	 * @see UWSSerializer#getJob(UWSJob, String[], boolean)
 	 */
@@ -1750,13 +2005,17 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * Serializes the specified attribute of this job in the given output stream by using the given serializer.
+	 * Serializes the specified attribute of this job in the given output stream
+	 * by using the given serializer.
 	 *
-	 * @param output			The output stream in which the job attribute must be serialized.
-	 * @param attributes		The name of the attribute to serialize (if <i>null</i>, the whole job will be serialized).
-	 * @param serializer		The serializer to use.
+	 * @param output		The output stream in which the job attribute must be
+	 *              		serialized.
+	 * @param attributes	The name of the attribute to serialize (if
+	 *                  	<i>null</i>, the whole job will be serialized).
+	 * @param serializer	The serializer to use.
 	 *
-	 * @throws Exception		If there is an unexpected error during the serialization.
+	 * @throws Exception	If there is an unexpected error during the
+	 *                  	serialization.
 	 *
 	 * @see #serialize(String[], UWSSerializer)
 	 */
@@ -1791,9 +2050,11 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>2 instances of AbstractJob are equals ONLY IF their ID are equals.</p>
+	 * 2 instances of AbstractJob are equals ONLY IF their ID are equals.
 	 *
-	 * <p><i><u>Note:</u> If the given object is not an AbstractJob, FALSE is returned.</i></p>
+	 * <p><i>Note:
+	 * 	If the given object is not an AbstractJob, FALSE is returned.
+	 * </i></p>
 	 *
 	 * @see java.lang.Object#equals(java.lang.Object)
 	 */
diff --git a/test/uws/job/TestJobPhase.java b/test/uws/job/TestJobPhase.java
new file mode 100644
index 0000000..f275d75
--- /dev/null
+++ b/test/uws/job/TestJobPhase.java
@@ -0,0 +1,648 @@
+package uws.job;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+
+import uws.UWSException;
+
+public class TestJobPhase {
+
+	@Test
+	public void testSetPhase(){
+		/*
+		 * Here, we just want to ensure that all Execution Phases are supported.
+		 * So, we just test to test the phase with force=true.
+		 * Tests with force=false, have to be done individually for each
+		 * phase ; hence the other JUnit test functions of this JUnit test case.
+		 */
+		try{
+			JobPhase jobPhase = (new UWSJob(null)).getPhaseManager();
+			for(ExecutionPhase phase : ExecutionPhase.values()){
+				jobPhase.setPhase(phase, true);
+				assertEquals(phase, jobPhase.getPhase());
+			}
+		}catch(Exception ex){
+			ex.printStackTrace();
+			fail("Setting a phase with force=true must NEVER throw an error. See console for more details.");
+		}
+	}
+
+	@Test
+	public void testSetPendingPhase(){
+		/*
+		 * The phase PENDING can be NEVER be set coming from another different
+		 * (normal) phase.
+		 */
+		try{
+			UWSJob job = new UWSJob(null);
+			JobPhase jobPhase = job.getPhaseManager();
+			for(ExecutionPhase phase : ExecutionPhase.values()){
+
+				/* CASE: FORCE=TRUE */
+				// set the phase to turn into PENDING:
+				jobPhase.setPhase(phase, true);
+				// try to set PENDING:
+				switch(phase){
+					case PENDING:
+					case UNKNOWN:
+						try{
+							jobPhase.setPhase(ExecutionPhase.PENDING, false);
+						}catch(Exception e){
+							e.printStackTrace();
+							fail("Setting the PENDING phase from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+						}
+						break;
+					default:
+						try{
+							jobPhase.setPhase(ExecutionPhase.PENDING, false);
+							fail("It is not allowed to go from " + phase + " to PENDING.");
+						}catch(Exception e){
+							assertEquals(UWSException.class, e.getClass());
+							assertEquals("Incorrect phase transition! => the job " + job.getJobId() + " is in the phase " + phase + ". It can not go to PENDING.", e.getMessage());
+						}
+						break;
+				}
+
+				/* CASE: FORCE=FALSE */
+				// set the phase to turn into PENDING:
+				jobPhase.setPhase(phase, true);
+				// try to set PENDING:
+				try{
+					jobPhase.setPhase(ExecutionPhase.PENDING, true);
+				}catch(Exception e){
+					e.printStackTrace();
+					fail("Setting the PENDING phase with force=true from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+				}
+
+			}
+		}catch(Exception ex){
+			ex.printStackTrace();
+			fail("Setting a phase with force=true must NEVER throw an error. See console for more details.");
+		}
+	}
+
+	@Test
+	public void testSetQueuedPhase(){
+		/*
+		 * The phase QUEUED can be set only if the current phase is
+		 * HELD or PENDING.
+		 */
+		try{
+			UWSJob job = new UWSJob(null);
+			JobPhase jobPhase = job.getPhaseManager();
+			for(ExecutionPhase phase : ExecutionPhase.values()){
+
+				/* CASE: FORCE=TRUE */
+				// set the phase to turn into QUEUED:
+				jobPhase.setPhase(phase, true);
+				// try to set QUEUED:
+				switch(phase){
+					case QUEUED:
+					case HELD:
+					case PENDING:
+					case UNKNOWN:
+						try{
+							jobPhase.setPhase(ExecutionPhase.QUEUED, false);
+						}catch(Exception e){
+							e.printStackTrace();
+							fail("Setting the QUEUED phase from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+						}
+						break;
+					default:
+						try{
+							jobPhase.setPhase(ExecutionPhase.QUEUED, false);
+							fail("It is not allowed to go from " + phase + " to QUEUED.");
+						}catch(Exception e){
+							assertEquals(UWSException.class, e.getClass());
+							assertEquals("Incorrect phase transition! => the job " + job.getJobId() + " is in the phase " + phase + ". It can not go to QUEUED.", e.getMessage());
+						}
+						break;
+				}
+
+				/* CASE: FORCE=FALSE */
+				// set the phase to turn into QUEUED:
+				jobPhase.setPhase(phase, true);
+				// try to set QUEUED:
+				try{
+					jobPhase.setPhase(ExecutionPhase.QUEUED, true);
+				}catch(Exception e){
+					e.printStackTrace();
+					fail("Setting the QUEUED phase with force=true from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+				}
+
+			}
+		}catch(Exception ex){
+			ex.printStackTrace();
+			fail("Setting a phase with force=true must NEVER throw an error. See console for more details.");
+		}
+	}
+
+	@Test
+	public void testSetExecutingPhase(){
+		/*
+		 * The phase EXECUTING can be set only if the current phase is
+		 * HELD, SUSPENDED or QUEUED.
+		 */
+		try{
+			UWSJob job = new UWSJob(null);
+			JobPhase jobPhase = job.getPhaseManager();
+			for(ExecutionPhase phase : ExecutionPhase.values()){
+
+				/* CASE: FORCE=TRUE */
+				// set the phase to turn into EXECUTING:
+				jobPhase.setPhase(phase, true);
+				// try to set EXECUTING:
+				switch(phase){
+					case EXECUTING:
+					case HELD:
+					case SUSPENDED:
+					case QUEUED:
+					case UNKNOWN:
+						try{
+							jobPhase.setPhase(ExecutionPhase.EXECUTING, false);
+						}catch(Exception e){
+							e.printStackTrace();
+							fail("Setting the EXECUTING phase from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+						}
+						break;
+					default:
+						try{
+							jobPhase.setPhase(ExecutionPhase.EXECUTING, false);
+							fail("It is not allowed to go from " + phase + " to EXECUTING.");
+						}catch(Exception e){
+							assertEquals(UWSException.class, e.getClass());
+							assertEquals("Incorrect phase transition! => the job " + job.getJobId() + " is in the phase " + phase + ". It can not go to EXECUTING.", e.getMessage());
+						}
+						break;
+				}
+
+				/* CASE: FORCE=FALSE */
+				// set the phase to turn into EXECUTING:
+				jobPhase.setPhase(phase, true);
+				// try to set EXECUTING:
+				try{
+					jobPhase.setPhase(ExecutionPhase.EXECUTING, true);
+				}catch(Exception e){
+					e.printStackTrace();
+					fail("Setting the EXECUTING phase with force=true from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+				}
+
+			}
+		}catch(Exception ex){
+			ex.printStackTrace();
+			fail("Setting a phase with force=true must NEVER throw an error. See console for more details.");
+		}
+	}
+
+	@Test
+	public void testSetCompletedPhase(){
+		/*
+		 * The phase COMPLETED can be set only if the current phase is
+		 * EXECUTING.
+		 */
+		try{
+			UWSJob job = new UWSJob(null);
+			JobPhase jobPhase = job.getPhaseManager();
+			for(ExecutionPhase phase : ExecutionPhase.values()){
+
+				/* CASE: FORCE=TRUE */
+				// set the phase to turn into COMPLETED:
+				jobPhase.setPhase(phase, true);
+				// try to set COMPLETED:
+				switch(phase){
+					case COMPLETED:
+					case EXECUTING:
+					case UNKNOWN:
+						try{
+							jobPhase.setPhase(ExecutionPhase.COMPLETED, false);
+						}catch(Exception e){
+							e.printStackTrace();
+							fail("Setting the COMPLETED phase from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+						}
+						break;
+					default:
+						try{
+							jobPhase.setPhase(ExecutionPhase.COMPLETED, false);
+							fail("It is not allowed to go from " + phase + " to COMPLETED.");
+						}catch(Exception e){
+							assertEquals(UWSException.class, e.getClass());
+							assertEquals("Incorrect phase transition! => the job " + job.getJobId() + " is in the phase " + phase + ". It can not go to COMPLETED.", e.getMessage());
+						}
+						break;
+				}
+
+				/* CASE: FORCE=FALSE */
+				// set the phase to turn into COMPLETED:
+				jobPhase.setPhase(phase, true);
+				// try to set COMPLETED:
+				try{
+					jobPhase.setPhase(ExecutionPhase.COMPLETED, true);
+				}catch(Exception e){
+					e.printStackTrace();
+					fail("Setting the COMPLETED phase with force=true from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+				}
+
+			}
+		}catch(Exception ex){
+			ex.printStackTrace();
+			fail("Setting a phase with force=true must NEVER throw an error. See console for more details.");
+		}
+	}
+
+	@Test
+	public void testSetAbortedPhase(){
+		/*
+		 * The phase ABORTED can be set if the current phase is none of the
+		 * following phases: COMPLETED, ERROR and ARCHIVED.
+		 */
+		try{
+			UWSJob job = new UWSJob(null);
+			JobPhase jobPhase = job.getPhaseManager();
+			for(ExecutionPhase phase : ExecutionPhase.values()){
+
+				/* CASE: FORCE=TRUE */
+				// set the phase to turn into ABORTED:
+				jobPhase.setPhase(phase, true);
+				// try to set ABORTED:
+				switch(phase){
+					case COMPLETED:
+					case ERROR:
+					case ARCHIVED:
+						try{
+							jobPhase.setPhase(ExecutionPhase.ABORTED, false);
+							fail("It is not allowed to go from " + phase + " to ABORTED.");
+						}catch(Exception e){
+							assertEquals(UWSException.class, e.getClass());
+							assertEquals("Incorrect phase transition! => the job " + job.getJobId() + " is in the phase " + phase + ". It can not go to ABORTED.", e.getMessage());
+						}
+						break;
+					default:
+						try{
+							jobPhase.setPhase(ExecutionPhase.ABORTED, false);
+						}catch(Exception e){
+							e.printStackTrace();
+							fail("Setting the ABORTED phase from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+						}
+						break;
+				}
+
+				/* CASE: FORCE=FALSE */
+				// set the phase to turn into ABORTED:
+				jobPhase.setPhase(phase, true);
+				// try to set ABORTED:
+				try{
+					jobPhase.setPhase(ExecutionPhase.ABORTED, true);
+				}catch(Exception e){
+					e.printStackTrace();
+					fail("Setting the ERROR phase with force=true from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+				}
+
+			}
+		}catch(Exception ex){
+			ex.printStackTrace();
+			fail("Setting a phase with force=true must NEVER throw an error. See console for more details.");
+		}
+	}
+
+	@Test
+	public void testSetErrorPhase(){
+		/*
+		 * The phase ERROR can be set if the current phase is none of the
+		 * following phases: COMPLETED, ABORTED and ARCHIVED.
+		 */
+		try{
+			UWSJob job = new UWSJob(null);
+			JobPhase jobPhase = job.getPhaseManager();
+			for(ExecutionPhase phase : ExecutionPhase.values()){
+
+				/* CASE: FORCE=TRUE */
+				// set the phase to turn into ERROR:
+				jobPhase.setPhase(phase, true);
+				// try to set ERROR:
+				switch(phase){
+					case COMPLETED:
+					case ABORTED:
+					case ARCHIVED:
+						try{
+							jobPhase.setPhase(ExecutionPhase.ERROR, false);
+							fail("It is not allowed to go from " + phase + " to ERROR.");
+						}catch(Exception e){
+							assertEquals(UWSException.class, e.getClass());
+							assertEquals("Incorrect phase transition! => the job " + job.getJobId() + " is in the phase " + phase + ". It can not go to ERROR.", e.getMessage());
+						}
+						break;
+					default:
+						try{
+							jobPhase.setPhase(ExecutionPhase.ERROR, false);
+						}catch(Exception e){
+							e.printStackTrace();
+							fail("Setting the ERROR phase from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+						}
+						break;
+				}
+
+				/* CASE: FORCE=FALSE */
+				// set the phase to turn into ERROR:
+				jobPhase.setPhase(phase, true);
+				// try to set ERROR:
+				try{
+					jobPhase.setPhase(ExecutionPhase.ERROR, true);
+				}catch(Exception e){
+					e.printStackTrace();
+					fail("Setting the ERROR phase with force=true from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+				}
+
+			}
+		}catch(Exception ex){
+			ex.printStackTrace();
+			fail("Setting a phase with force=true must NEVER throw an error. See console for more details.");
+		}
+	}
+
+	@Test
+	public void testSetHeldPhase(){
+		/*
+		 * The phase HELD can be set only if the current phase is
+		 * PENDING or EXECUTING.
+		 */
+		try{
+			UWSJob job = new UWSJob(null);
+			JobPhase jobPhase = job.getPhaseManager();
+			for(ExecutionPhase phase : ExecutionPhase.values()){
+
+				/* CASE: FORCE=TRUE */
+				// set the phase to turn into HELD:
+				jobPhase.setPhase(phase, true);
+				// try to set HELD:
+				switch(phase){
+					case HELD:
+					case PENDING:
+					case EXECUTING:
+					case UNKNOWN:
+						try{
+							jobPhase.setPhase(ExecutionPhase.HELD, false);
+						}catch(Exception e){
+							e.printStackTrace();
+							fail("Setting the HELD phase from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+						}
+						break;
+					default:
+						try{
+							jobPhase.setPhase(ExecutionPhase.HELD, false);
+							fail("It is not allowed to go from " + phase + " to HELD.");
+						}catch(Exception e){
+							assertEquals(UWSException.class, e.getClass());
+							assertEquals("Incorrect phase transition! => the job " + job.getJobId() + " is in the phase " + phase + ". It can not go to HELD.", e.getMessage());
+						}
+						break;
+				}
+
+				/* CASE: FORCE=FALSE */
+				// set the phase to turn into HELD:
+				jobPhase.setPhase(phase, true);
+				// try to set HELD:
+				try{
+					jobPhase.setPhase(ExecutionPhase.HELD, true);
+				}catch(Exception e){
+					e.printStackTrace();
+					fail("Setting the HELD phase with force=true from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+				}
+
+			}
+		}catch(Exception ex){
+			ex.printStackTrace();
+			fail("Setting a phase with force=true must NEVER throw an error. See console for more details.");
+		}
+	}
+
+	@Test
+	public void testSetSuspendedPhase(){
+		/*
+		 * The phase SUSPENDED can be set only if the current phase is
+		 * EXECUTING.
+		 */
+		try{
+			UWSJob job = new UWSJob(null);
+			JobPhase jobPhase = job.getPhaseManager();
+			for(ExecutionPhase phase : ExecutionPhase.values()){
+
+				/* CASE: FORCE=TRUE */
+				// set the phase to turn into SUSPENDED:
+				jobPhase.setPhase(phase, true);
+				// try to set SUSPENDED:
+				switch(phase){
+					case SUSPENDED:
+					case EXECUTING:
+					case UNKNOWN:
+						try{
+							jobPhase.setPhase(ExecutionPhase.SUSPENDED, false);
+						}catch(Exception e){
+							e.printStackTrace();
+							fail("Setting the SUSPENDED phase from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+						}
+						break;
+					default:
+						try{
+							jobPhase.setPhase(ExecutionPhase.SUSPENDED, false);
+							fail("It is not allowed to go from " + phase + " to SUSPENDED.");
+						}catch(Exception e){
+							assertEquals(UWSException.class, e.getClass());
+							assertEquals("Incorrect phase transition! => the job " + job.getJobId() + " is in the phase " + phase + ". It can not go to SUSPENDED.", e.getMessage());
+						}
+						break;
+				}
+
+				/* CASE: FORCE=FALSE */
+				// set the phase to turn into SUSPENDED:
+				jobPhase.setPhase(phase, true);
+				// try to set SUSPENDED:
+				try{
+					jobPhase.setPhase(ExecutionPhase.SUSPENDED, true);
+				}catch(Exception e){
+					e.printStackTrace();
+					fail("Setting the SUSPENDED phase with force=true from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+				}
+
+			}
+		}catch(Exception ex){
+			ex.printStackTrace();
+			fail("Setting a phase with force=true must NEVER throw an error. See console for more details.");
+		}
+	}
+
+	@Test
+	public void testSetArchivedPhase(){
+		/*
+		 * The phase ARCHIVED can be set only if the current phase is one of:
+		 * ARCHIVED, COMPLETED, ABORTED and ERROR.
+		 */
+		try{
+			UWSJob job = new UWSJob(null);
+			JobPhase jobPhase = job.getPhaseManager();
+			for(ExecutionPhase phase : ExecutionPhase.values()){
+
+				/* CASE: FORCE=TRUE */
+				// set the phase to turn into ARCHIVED:
+				jobPhase.setPhase(phase, true);
+				// try to set ARCHIVED:
+				switch(phase){
+					case ARCHIVED:
+					case COMPLETED:
+					case ABORTED:
+					case ERROR:
+					case UNKNOWN:
+						try{
+							jobPhase.setPhase(ExecutionPhase.ARCHIVED, false);
+						}catch(Exception e){
+							e.printStackTrace();
+							fail("Setting the ARCHIVED phase from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+						}
+						break;
+					default:
+						try{
+							jobPhase.setPhase(ExecutionPhase.ARCHIVED, false);
+							fail("It is not allowed to go from " + phase + " to ARCHIVED.");
+						}catch(Exception e){
+							assertEquals(UWSException.class, e.getClass());
+							assertEquals("Incorrect phase transition! => the job " + job.getJobId() + " is in the phase " + phase + ". It can not go to ARCHIVED.", e.getMessage());
+						}
+				}
+
+				/* CASE: FORCE=FALSE */
+				// set the phase to turn into ARCHIVED:
+				jobPhase.setPhase(phase, true);
+				// try to set ARCHIVED:
+				try{
+					jobPhase.setPhase(ExecutionPhase.ARCHIVED, true);
+				}catch(Exception e){
+					e.printStackTrace();
+					fail("Setting the ARCHIVED phase with force=true from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+				}
+
+			}
+		}catch(Exception ex){
+			ex.printStackTrace();
+			fail("Setting a phase with force=true must NEVER throw an error. See console for more details.");
+		}
+	}
+
+	@Test
+	public void testSetUnknownPhase(){
+		/*
+		 * The phase UNKNOWN is not really part of the Execution Phase state
+		 * machine declared in the UWS standard. So, an exception can never be
+		 * thrown when setting this phase, with force=true, or not.
+		 */
+		try{
+			JobPhase jobPhase = (new UWSJob(null)).getPhaseManager();
+			for(ExecutionPhase phase : ExecutionPhase.values()){
+
+				/* CASE: FORCE=TRUE */
+				// set the phase to turn into UNKNOWN:
+				jobPhase.setPhase(phase, true);
+				// try to set UNKNOWN:
+				try{
+					jobPhase.setPhase(ExecutionPhase.UNKNOWN, false);
+				}catch(Exception e){
+					e.printStackTrace();
+					fail("Setting the UNKNOWN phase from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+				}
+
+				/* CASE: FORCE=FALSE */
+				// set the phase to turn into UNKNOWN:
+				jobPhase.setPhase(phase, true);
+				// try to set UNKNOWN:
+				try{
+					jobPhase.setPhase(ExecutionPhase.UNKNOWN, true);
+				}catch(Exception e){
+					e.printStackTrace();
+					fail("Setting the UNKNOWN phase (especially with force=true) from any other phase (here: " + phase + ") MUST always be possible. See console for more details.");
+				}
+
+			}
+		}catch(Exception ex){
+			ex.printStackTrace();
+			fail("Setting a phase with force=true must NEVER throw an error. See console for more details.");
+		}
+	}
+
+	@Test
+	public void testIsJobUpdatable(){
+		/*
+		 * A UWS job can be updated in only one execution phase: PENDING.
+		 */
+		try{
+			JobPhase jobPhase = (new UWSJob(null)).getPhaseManager();
+			for(ExecutionPhase phase : ExecutionPhase.values()){
+				// set the phase to test:
+				jobPhase.setPhase(phase, true);
+				// ensure isJobUpdatable(...) returns TRUE only for PENDING:
+				if (phase == ExecutionPhase.PENDING)
+					assertTrue(jobPhase.isJobUpdatable());
+				else
+					assertFalse(jobPhase.isJobUpdatable());
+			}
+		}catch(Exception ex){
+			ex.printStackTrace();
+			fail("Setting the phase with force=true must NEVER throw an error. See console for more details.");
+		}
+	}
+
+	@Test
+	public void testIsFinished(){
+		/*
+		 * A UWS job is finished only if in the execution phase COMPLETED,
+		 * ABORTED, ERROR or ARCHIVED.
+		 */
+		try{
+			JobPhase jobPhase = (new UWSJob(null)).getPhaseManager();
+			for(ExecutionPhase phase : ExecutionPhase.values()){
+				// set the phase to test:
+				jobPhase.setPhase(phase, true);
+				// ensure isFinished(...) returns TRUE only for COMPLETED,
+				// ABORTED, ERROR and ARCHIVED:
+				switch(phase){
+					case COMPLETED:
+					case ABORTED:
+					case ERROR:
+					case ARCHIVED:
+						assertTrue(jobPhase.isFinished());
+						break;
+					default:
+						assertFalse(jobPhase.isFinished());
+						break;
+				}
+			}
+		}catch(Exception ex){
+			ex.printStackTrace();
+			fail("Setting the phase with force=true must NEVER throw an error. See console for more details.");
+		}
+	}
+
+	@Test
+	public void testIsExecuting(){
+		/*
+		 * A UWS job is executing if in only one execution phase: EXECUTING.
+		 */
+		try{
+			JobPhase jobPhase = (new UWSJob(null)).getPhaseManager();
+			for(ExecutionPhase phase : ExecutionPhase.values()){
+				// set the phase to test:
+				jobPhase.setPhase(phase, true);
+				// ensure isExecuting(...) returns TRUE only for EXECUTING:
+				if (phase == ExecutionPhase.EXECUTING)
+					assertTrue(jobPhase.isExecuting());
+				else
+					assertFalse(jobPhase.isExecuting());
+			}
+		}catch(Exception ex){
+			ex.printStackTrace();
+			fail("Setting the phase with force=true must NEVER throw an error. See console for more details.");
+		}
+	}
+
+}
-- 
GitLab