Groovy closure delegation not delegating to child objects

Viewed 26

I have this code that is to handle two separate sheets of a data source spreadsheet. I have some BaseRecordHandler that is dedicated to handling the spreadsheet itself. It contains method

    protected void initDataSourceFile() throws IOException {
        File file = new File(this.dataSourceFilename);
        this.excelFile = this.getWorkbook(file);

        if (file.exists())
            return;

        file.getParentFile().mkdirs();

        FileOutputStream outputStream = new FileOutputStream(file);

        this.setupSpreadsheet({ Sheet sheet ->
            setupFirstRow(sheet.createRow(0));

            sheet.createFreezePane(0, 1);

            // returning the sheet allows for the functional programming technique known as composition
            return sheet;
        });

        this.excelFile.write(outputStream);
        outputStream.close();
        this.excelFile.close();
    }

The actual spreadsheet handler, called PracticeProfileHandler has two child BaseSheetHandlers. Its setupSpreadsheet() is defined to be:

    @Override
    protected void setupSpreadsheet(Closure<Sheet> onSetupSheet) {

        Closure onGetAndSetupSheet = SMDSpreadsheetUtils.OnCreateIfNotExistSheet(this.excelFile) >> onSetupSheet;

        this.childPracticeURLHandler = new PracticeURLHandler(onGetAndSetupSheet);
        this.childOrgNameHandler = new OrganizationNameHandler(onGetAndSetupSheet);
    }

    @Override
    protected void setupFirstRow(Row firstRow) {
        throw new Exception("PracticeProfileHandler should not be trying to set up the first row of a Sheet");
    }

BaseSheetHandler is defined as follows:

public abstract class BaseSheetHandler<T> {
    protected Sheet sheet;
    protected List<T> usedRecords;

    protected BaseSheetHandler(Closure<Sheet> onGetSheet) {
        onGetSheet.setDelegate(this);
        this.sheet = onGetSheet(this.getSheetName());
        this.init();
    }

    // ...rest of code...
}

the child handlers' fillInRow() is implemented on their respective classes.

The problem is that, when I hit this practiceProfileHandler.initDataSourceFile(), it acts as if the child fillInRow() doesn't exist, and instead hits the one on PracticeProfileHandler, despite that I delegated the callback that contains that line of code, to the child instances themselves (via the BaseSheetHandler constructor)!

What is causing this to happen, and how do I fix it?

1 Answers

Per @emilles suggestion, I set the resolve strategy in BaseSheetHandler constructor:

    protected BaseSheetHandler(Closure<Sheet> onGetSheet) {
        onGetSheet.setResolveStrategy(Closure.DELEGATE_FIRST);
        onGetSheet.setDelegate(this);
        this.sheet = onGetSheet(this.getSheetName());
        this.init();
    }

and it works!

I should write this on some closure utils class...!

Related