package gw.rating.rtm.validation uses gw.rating.rtm.domain.ErrorCollectingVisitor uses gw.rating.rtm.domain.table.RateBookModel uses gw.rating.rtm.domain.table.RateTableRow uses gw.rating.rtm.domain.table.RateTableCell uses java.lang.Comparable uses gw.rating.rtm.domain.ErrorCollector uses gw.rating.rtm.query.StatelessRowLoadUtil uses gw.rating.rtm.domain.OrderedPersistenceAdapter uses gw.rating.rtm.domain.OrderedPersistenceElement.OrderedPersistenceWrapper uses java.lang.IllegalStateException uses gw.rating.rtm.domain.table.RateTableModel uses gw.api.system.PCLoggerCategory class NormalizingRowValidationVisitor extends ErrorCollectingVisitor { var rowSet : List = {} var util = new StatelessRowLoadUtil() var def : RateTableDefinition = null var hasRangeColumn : boolean construct(collector : ErrorCollector) { super(collector) } override function visit(model : RateTableModel) { super.visit(model) } override function visitAfter(tableModel: RateTableModel) { if (def != null and rowSet.HasElements) { normalizeAndValidate(rowSet) } } override function visit(ratingRow: RateTableRow) { if (def == null) { def = ratingRow.Cells.firstWhere(\r -> r.ColumnDefinition.Definition != null).ColumnDefinition.Definition hasRangeColumn = def.MatchOps.hasMatch(\ matchOp -> matchOp.IsRange) } if (rowSet.size() == 0 or partialParameterMatch(rowSet.get(0), ratingRow)) { rowSet.add(ratingRow) } else { if (def == null) { throw new IllegalStateException("Can't validate because we haven't got a RateTableDefinition") } else { normalizeAndValidate(rowSet) } rowSet.clear() rowSet.add(ratingRow) } } private function normalizeAndValidate(rows: List) { var normalizedRows = util.normalizeTableRows(rows, def) if (PCLoggerCategory.RTM.DebugEnabled) { PCLoggerCategory.RTM.debug("Normalized rows: " + normalizedRows.size()) normalizedRows.each( \ elt -> PCLoggerCategory.RTM.debug(elt.toString())) } for (i in 1..|normalizedRows.size()) { if (allParamsMatch(normalizedRows[i-1], normalizedRows[i])) { var foundRow = rowSet.firstWhere(\ r -> r.Row == (normalizedRows[i] as OrderedPersistenceWrapper).Adapter) if (hasRangeColumn) { addRowError(foundRow, RateTableErrorType.TC_RANGEOVERLAP) } else { addRowError(foundRow, RateTableErrorType.TC_DUPLICATEROW) } } } } private function allParamsMatch(r1 : OrderedPersistenceAdapter, r2 : OrderedPersistenceAdapter) : boolean { return def.MatchOps.allMatch( \ matchOp -> matchOp.newStatelessInstance().overlaps(r1, r2)) } private function partialParameterMatch(r1 : RateTableRow, r2 : RateTableRow) : boolean { for (p in r1.Cells index i) { if (p.MatchOp == null or p.MatchOp.sortedParams().first().MultiSelect or p.MatchOp.IsRange) { continue } if (r2.Cells.size() <= i or p.compareTo(r2.Cells.get(i)) != 0) { return false } } return true } private function apply(ratingCell : RateTableCell) { // maybe nothing to do, because we operate row-by-row. } override function visitBoolean(ratingCell : RateTableCell) { apply(ratingCell) } override function visitDate(ratingCell : RateTableCell) { apply(ratingCell) } override function visitDecimal(ratingCell : RateTableCell) { apply(ratingCell) } override function visitInteger(ratingCell : RateTableCell) { apply(ratingCell) } override function visitString(ratingCell : RateTableCell) { apply(ratingCell) } override function visitEmpty(ratingCell : RateTableCell) { apply(ratingCell) } override function visitingEmptyCells() : boolean { return true } override function visit(bookModel: RateBookModel) { } }