class IJob :
    virtual void Start() = 0;
    virtual JobStepResult Step(const std::string& jobId) = 0;
    virtual bool NeedsProgressUpdateBetweenSteps() const // only for jobs whose progress is updated by outside events (like C-Move and C-Get)
    virtual float GetProgress() const = 0;
    ...

class SetOfCommandsJob : IJob
    class ICommand
        virtual bool Execute(const std::string& jobId) = 0;
        virtual void Serialize(Json::Value& target) const = 0;
    class ICommandUnserializer
        virtual ICommand* Unserialize(const Json::Value& source) const = 0;
    
    virtual void Start() ORTHANC_OVERRIDE;
    virtual float GetProgress() ORTHANC_OVERRIDE { returns position_/commands_.size()}
    void SetPermissive(bool permissive);  // if a command fails, the complete job does not fails
    virtual JobStepResult Step(const std::string& jobId) = commands_[position_]->Execute()

class SetOfInstancesJob : SetOfCommandsJob
    virtual bool HandleInstance(const std::string& instance) = 0;
    virtual bool HandleTrailingStep() = 0;


class StoreJob : SetOfInstancesJob   (contains a DicomSequentialReader)

Class ModalityStoreJob : StoreJob
