package com.capgemini.reports.execution.actions;

import com.capgemini.framework.teamcenter.authent.TcSession;
import com.capgemini.framework.teamcenter.exceptions.KurtException;
import com.capgemini.reports.database.javabean.DbReport;
import com.capgemini.reports.exceptions.InvalidUserInputException;
import com.capgemini.reports.execution.AbstractExecutionReport;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;

/**
 * This abstract class makes it easy do define a report-specific action, with strong typing.<br>
 * Intercepts the default (weakly-typed)<br>
 * {@link IPreExecutionStep#performPreAction(AbstractExecutionReport, DbReport, TcSession) performPreAction}<br>
 * And forwards it to this class's (strongly-typed)<br>
 * {@link AbstractPreExecutionStep#performPreActionOnReport(AbstractExecutionReport, DbReport, TcSession) performPreActionOnReport}
 * @param <T> the exact report type
 */
@AllArgsConstructor
@EqualsAndHashCode
public abstract class AbstractPreExecutionStep<T extends AbstractExecutionReport<T, ?>> implements IPreExecutionStep {

    private static final long serialVersionUID = -1516821856454786852L;

    private final Class<T> reportClass;

    @Override
    public <K extends AbstractExecutionReport<K, ?>> void performPreAction(K reportRaw, DbReport dbReport, TcSession session)
            throws KurtException {
        try {
            T report = reportClass.cast(reportRaw);
            performPreActionOnReport(report, dbReport, session);
        } catch (ClassCastException e) {
            throw new KurtException(
                    "Unable to perform Specialized action because input report is not of the right type, UID=" + reportRaw.getReportTechnicalUid(),
                    e);
        }
    }

    /**
     * Performs a specific action on a particular report type before the report execution.
     *
     * @param reportRaw
     * @param dbReport the report which has just finished printing
     * @param session
     * 
     * @throws KurtException anything that happens must be a {@link KurtException} so it can be caught and dealt with appropriately. <br>
     *         Particularly, if the error is a functional error, do throw an {@link InvalidUserInputException}
     */
    protected abstract void performPreActionOnReport(T reportRaw, DbReport dbReport, TcSession session) throws KurtException;

}

