class InsertLine extends TransformationOperation<InsertLine> {

    @Override
    @edu.umd.cs.findbugs.annotations.SuppressFBWarnings (value="NP_ALWAYS_NULL_EXCEPTION")
    protected TOExecutionResult execution(File transformedAppFolder, TransformationContext transformationContext) {
        File fileToBeChanged = getAbsoluteFile(transformedAppFolder, transformationContext);

        if (!fileToBeChanged.exists()) {
            // TODO Should this be done as pre-validation?
            FileNotFoundException ex = new FileNotFoundException("File to be modified has not been found");
            return TOExecutionResult.error(this, ex);
        }

        BufferedReader reader = null;
        BufferedWriter writer = null;
        TOExecutionResult result = null;

        try {
            final String eol = EolHelper.findEolDefaultToOs(fileToBeChanged);
            File readFile = getOrCreateReadFile(transformedAppFolder, transformationContext);
            reader = new BufferedReader(new InputStreamReader(new FileInputStream(readFile), StandardCharsets.UTF_8));
            writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileToBeChanged), StandardCharsets.UTF_8));

            switch (insertionMode) {
                case LINE_NUMBER:
                    result = insertAtSpecificLine(reader, writer, eol);
                    break;
                case REGEX_FIRST:
                    result = insertRegex(reader, writer, true, true, eol);
                    break;
                case REGEX_ALL:
                    result = insertRegex(reader, writer, false, true, eol);
                    break;
                case REGEX_BEFORE_FIRST:
                    result = insertRegex(reader, writer, true, false, eol);
                    break;
                case REGEX_BEFORE_ALL:
                    result = insertRegex(reader, writer, false, false, eol);
                    break;
                default:
                case CONCAT:
                    result = concat(reader, writer, eol);
                    break;
            }
        } catch (IOException e) {
            result = TOExecutionResult.error(this, e);
        } finally {
            try {
                if (writer != null) try {
                    writer.close();
                } catch (IOException e) {
                    result.addWarning(e);
                }
            } finally {
                if(reader != null) try {
                    reader.close();
                } catch (IOException e) {
                    result.addWarning(e);
                }
            }
        }

        return result;
    }

    public  InsertLine();
    public  InsertLine(String newLine);
    public  InsertLine(String newLine, Integer lineNumber);
    public  InsertLine(String newLine, String regex);

}