Execute the job, that is, execute all of its tasks.

        Each produced sync map will be stored
        inside the corresponding task object.

        :raises: :class:`~aeneas.executejob.ExecuteJobExecutionError`: if there is a problem during the job execution

def execute(self):
        """
        Execute the job, that is, execute all of its tasks.

        Each produced sync map will be stored
        inside the corresponding task object.

        :raises: :class:`~aeneas.executejob.ExecuteJobExecutionError`: if there is a problem during the job execution
        """
        self.log(u"Executing job")

        if self.job is None:
            self.log_exc(u"The job object is None", None, True, ExecuteJobExecutionError)
        if len(self.job) == 0:
            self.log_exc(u"The job has no tasks", None, True, ExecuteJobExecutionError)
        job_max_tasks = self.rconf[RuntimeConfiguration.JOB_MAX_TASKS]
        if (job_max_tasks > 0) and (len(self.job) > job_max_tasks):
            self.log_exc(u"The Job has %d Tasks, more than the maximum allowed (%d)." % (len(self.job), job_max_tasks), None, True, ExecuteJobExecutionError)
        self.log([u"Number of tasks: '%d'", len(self.job)])

        for task in self.job.tasks:
            try:
                custom_id = task.configuration["custom_id"]
                self.log([u"Executing task '%s'...", custom_id])
                executor = ExecuteTask(task, rconf=self.rconf, logger=self.logger)
                executor.execute()
                self.log([u"Executing task '%s'... done", custom_id])
            except Exception as exc:
                self.log_exc(u"Error while executing task '%s'" % (custom_id), exc, True, ExecuteJobExecutionError)
            self.log(u"Executing task: succeeded")

        self.log(u"Executing job: succeeded")