class GenericMigrationWrapper {

    public MigrateResult migrate(DigitalObject sourceObject, URI sourceFormat,
                                 URI destinationFormat, List<Parameter> toolParameters)
            throws MigrationException, IOException {

        /*
         * - Validate that the proper parameters are set for the migration path
         * identified by sourceFormat and destinationFormat
         */
        final MigrationPath migrationPath = migrationPaths
                .getMigrationPath(sourceFormat, destinationFormat);

        log.info("Found migrationpath from "+sourceFormat+" to "+destinationFormat);

        //If called with null parameters, use an empty list instead
        if (toolParameters == null){
            log.info("Called with null parameters");
            toolParameters = new ArrayList<Parameter>();
        }


        //make workfolder, and reserve filenames in this folder.
        log.info("Making workfolder for migration");
        File workfolder = handleTempfiles(migrationPath);

        //handle temp input file

        if (migrationPath.useTempSourceFile()){
            log.info("Migrationpath uses temp source file, reading digital object into file");
            handleTempSourceFile(migrationPath,sourceObject, workfolder);
        }


        //handle temp output file
        if (migrationPath.useTempDestinationFile()){
            log.info("Migrationpath uses temp destination path");
            handleTempDestinationFile(migrationPath,workfolder);
        }


        List<String> command = migrationPath.getCommandLine(toolParameters);
        log.info("Command line found: ");
        log.info(command.toString());


        InputStream processStandardInput = null;
        if (!migrationPath.useTempSourceFile()) {
            //serve the file on standard input
            processStandardInput = sourceObject.getContent().getInputStream();
        } else {
            //fine, is alreade written
        }

        //Execute the tool
        final ProcessRunner toolProcessRunner = new ProcessRunner();
        ServiceReport serviceReport = executeToolProcess(toolProcessRunner,
                                                         command, processStandardInput);



        if (serviceReport.getType() == Type.ERROR) {
            String message = "Failed migrating object with title '"
                             + sourceObject.getTitle() + "' from format URI: "
                             + sourceFormat + " to " + destinationFormat
                             + " Standard output: "
                             + toolProcessRunner.getProcessOutputAsString()
                             + "\nStandard error output: "
                             + toolProcessRunner.getProcessErrorAsString();
            serviceReport = new ServiceReport(Type.ERROR,
                                              Status.TOOL_ERROR, message);
            return new MigrateResult(null, serviceReport);
        }


        //cleanup
        if (migrationPath.useTempSourceFile()){
            migrationPath.getTempSourceFile().getFile().delete();
        }
        for (TempFile tempFile : migrationPath.getTempFileDeclarations()) {
            tempFile.getFile().delete();
        }


        //READING THE OUTPUT
        //TODO return a reference to the outputfile
        DigitalObject.Builder builder;


        if (migrationPath.useTempDestinationFile()){
            //we should read a temp file afterwards
            File outputfile = migrationPath.getTempOutputFile().getFile();
            if (returnByReference){
                builder = new DigitalObject.Builder(Content.byReference(outputfile));
            } else {
                builder = new DigitalObject.Builder(Content.byValue(outputfile));
                outputfile.delete();
            }


            String message = "Successfully migrated object with title '"
                             + sourceObject.getTitle() + "' from format URI: "
                             + sourceFormat + " to " + destinationFormat
                             + " Standard output: "
                             + toolProcessRunner.getProcessOutputAsString()
                             + "\nStandard error output: "
                             + toolProcessRunner.getProcessErrorAsString();
            serviceReport = new ServiceReport(Type.INFO, Status.SUCCESS,
                                              message);

        } else {

            if (returnByReference){
                //we should read the output
                builder = new DigitalObject.Builder(Content.byReference(toolProcessRunner.getProcessOutput()));
            } else{
                builder = new DigitalObject.Builder(Content.byValue(toolProcessRunner.getProcessOutput()));
            }
            String message = "Successfully migrated object with title '"
                             + sourceObject.getTitle() + "' from format URI: "
                             + sourceFormat + " to " + destinationFormat
                             + " Standard error output: "
                             + toolProcessRunner.getProcessErrorAsString();
            serviceReport = new ServiceReport(Type.INFO, Status.SUCCESS,
                                              message);


        }


        //TODO cleanup the dir
        DigitalObject destinationObject = builder
                .format(destinationFormat)
                .build();

        return new MigrateResult(destinationObject, serviceReport);

    }

    public  GenericMigrationWrapper(Document configuration, String canonicalName);

}