// Path: src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVRow.java
// public class CSVRow {
//     private ObservableMap<String, ObjectProperty<CSVValue>> columns = FXCollections.observableHashMap();
//     private int rowNumber;
// 
//     /**
//      * sets the row number
//      * @param rowNumber
//      */
//     public void setRowNumber(int rowNumber) {
//         this.rowNumber = rowNumber;
//     }
// 
//     /**
//      * return the row number
//      * @return row number
//      */
//     public int getRowNumber() {
//         return rowNumber;
//     }
// 
// 
//     /**
//      * returns the columns with data as Map
//      * @return columns with data
//      */
//     public ObservableMap<String, ObjectProperty<CSVValue>> getColumns() {
//         return columns;
//     }
// 
//     /**
//      * stores the given value in the given column of this row
//      * @param column column name
//      * @param value the value to store
//      */
//     CSVValue addValue(String column, String value) {
//         CSVValue v = new CSVValue();
//         v.setValue(value);
//         columns.put(column, new SimpleObjectProperty<>(v));
//         return v;
//     }
// 
// }
// 
// Path: src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVValue.java
// public class CSVValue {
//     private StringProperty value = new SimpleStringProperty();
//     private ValidationError valid;
// 
//     /**
//      * returns the real value
//      * @return the real value
//      */
//     public String getValue() {
//         return value.get();
//     }
// 
//     /**
//      * JavaFX property representation of the real value
//      * @return property of real value
//      */
//     public StringProperty valueProperty() {
//         return value;
//     }
// 
//     /**
//      * sets the real value
//      * @param value the real value
//      */
//     public void setValue(String value) {
//         this.value.set(value);
//     }
// 
//     /**
//      * returns if the value is valid to the rules of the validator
//      * @return
//      */
//     public ValidationError getValidationError() {
//         return valid;
//     }
// 
//     /**
//      * sets the state if a value is valid or not
//      * @param valid the validation state
//      */
//     public void setValidationError(ValidationError valid) {
//         this.valid = valid;
//     }
// }


import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javafx.beans.property.ObjectProperty;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import ninja.javafx.smartcsv.fx.table.model.CSVRow;
import ninja.javafx.smartcsv.fx.table.model.CSVValue;
        this.validator = validator;
    }

    public void setRows(List<CSVRow> rows) {
        this.rows = rows;
    }

    public void setHeader(String[] header) {
        this.header = header;
    }

    @Override
    protected Task<List<ValidationError>> createTask() {
        return new Task<List<ValidationError>>() {
            @Override
            protected List<ValidationError> call() throws Exception {
                List<ValidationError> errors = new ArrayList<>();
                try {
                    if (header != null) {
                        ValidationError headerError = validator.isHeaderValid(header);
                        if (headerError != null) {
                            logger.info("revalidate: header error found");
                            errors.add(headerError);
                        }
                    }

                    int maxRows = rows.size();
                    for (int lineNumber = 0; lineNumber < maxRows; lineNumber++) {
                        CSVRow row = rows.get(lineNumber);

// Path: src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVRow.java
// public class CSVRow {
//     private ObservableMap<String, ObjectProperty<CSVValue>> columns = FXCollections.observableHashMap();
//     private int rowNumber;
// 
//     /**
//      * sets the row number
//      * @param rowNumber
//      */
//     public void setRowNumber(int rowNumber) {
//         this.rowNumber = rowNumber;
//     }
// 
//     /**
//      * return the row number
//      * @return row number
//      */
//     public int getRowNumber() {
//         return rowNumber;
//     }
// 
// 
//     /**
//      * returns the columns with data as Map
//      * @return columns with data
//      */
//     public ObservableMap<String, ObjectProperty<CSVValue>> getColumns() {
//         return columns;
//     }
// 
//     /**
//      * stores the given value in the given column of this row
//      * @param column column name
//      * @param value the value to store
//      */
//     CSVValue addValue(String column, String value) {
//         CSVValue v = new CSVValue();
//         v.setValue(value);
//         columns.put(column, new SimpleObjectProperty<>(v));
//         return v;
//     }
// 
// }
// 
// Path: src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVValue.java
// public class CSVValue {
//     private StringProperty value = new SimpleStringProperty();
//     private ValidationError valid;
// 
//     /**
//      * returns the real value
//      * @return the real value
//      */
//     public String getValue() {
//         return value.get();
//     }
// 
//     /**
//      * JavaFX property representation of the real value
//      * @return property of real value
//      */
//     public StringProperty valueProperty() {
//         return value;
//     }
// 
//     /**
//      * sets the real value
//      * @param value the real value
//      */
//     public void setValue(String value) {
//         this.value.set(value);
//     }
// 
//     /**
//      * returns if the value is valid to the rules of the validator
//      * @return
//      */
//     public ValidationError getValidationError() {
//         return valid;
//     }
// 
//     /**
//      * sets the state if a value is valid or not
//      * @param valid the validation state
//      */
//     public void setValidationError(ValidationError valid) {
//         this.valid = valid;
//     }
// }


// Path: src/main/java/ninja/javafx/smartcsv/validation/RevalidationService.java
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javafx.beans.property.ObjectProperty;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import ninja.javafx.smartcsv.fx.table.model.CSVRow;
import ninja.javafx.smartcsv.fx.table.model.CSVValue;

        this.validator = validator;
    }

    public void setRows(List<CSVRow> rows) {
        this.rows = rows;
    }

    public void setHeader(String[] header) {
        this.header = header;
    }

    @Override
    protected Task<List<ValidationError>> createTask() {
        return new Task<List<ValidationError>>() {
            @Override
            protected List<ValidationError> call() throws Exception {
                List<ValidationError> errors = new ArrayList<>();
                try {
                    if (header != null) {
                        ValidationError headerError = validator.isHeaderValid(header);
                        if (headerError != null) {
                            logger.info("revalidate: header error found");
                            errors.add(headerError);
                        }
                    }

                    int maxRows = rows.size();
                    for (int lineNumber = 0; lineNumber < maxRows; lineNumber++) {
                        CSVRow row = rows.get(lineNumber);

                        Map<String, ObjectProperty<CSVValue>> table = row.getColumns();