All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gs.obevocomparer.output.simple.SimpleBreakFormatter Maven / Gradle / Ivy

/**
 * Copyright 2017 Goldman Sachs.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.gs.obevocomparer.output.simple;

import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import com.gs.obevocomparer.compare.CatoDataSide;
import com.gs.obevocomparer.compare.breaks.Break;
import com.gs.obevocomparer.compare.breaks.FieldBreak;
import com.gs.obevocomparer.compare.breaks.GroupBreak;
import com.gs.obevocomparer.output.CatoComparisonMetadata;
import com.gs.obevocomparer.output.CatoContentFormatter;
import com.gs.obevocomparer.output.CatoContentMetadata;
import com.gs.obevocomparer.output.CatoContentRow;
import com.gs.obevocomparer.output.CatoContentRow.ValueType;
import com.gs.obevocomparer.output.CatoContentWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SimpleBreakFormatter implements CatoContentFormatter {

    private static final String BREAK_TYPE = "Break Type";
    private static final String BREAK_GROUP = "Group";

    private final boolean excludeWriter;

    private static final Logger LOG = LoggerFactory.getLogger(SimpleBreakFormatter.class);

    public SimpleBreakFormatter(boolean excludeWriter) {
        this.excludeWriter = excludeWriter;
    }

    public void writeData(CatoComparisonMetadata comparisonMetadata, CatoContentWriter contentWriter) throws IOException {

        Map> fieldMap = new LinkedHashMap>();
        Map fieldBreakMap = new LinkedHashMap();

        int fieldCount = this.calculateFieldMaps(comparisonMetadata, fieldMap, fieldBreakMap);

        for (String keyField : comparisonMetadata.getComparison().getKeyFields()) {
            if (!fieldMap.containsKey(keyField)) {
                throw new IllegalArgumentException("Could not find key field '" + keyField + "' in comparison " + comparisonMetadata.getComparison().getName());
            }
        }

        CatoContentMetadata contentMetadata = new SimpleContentMetadata(
                comparisonMetadata.getComparison().getName() + (this.excludeWriter ? " Excluded" : ""),
                1, comparisonMetadata.hasGroupBreaks() ? 2 : 1);

        contentWriter.openContent(contentMetadata);

        contentWriter.writeRow(this.createHeaderRow(comparisonMetadata, fieldCount, fieldMap, fieldBreakMap));

        int count = 0;

        for (Break br : comparisonMetadata.getComparison().getBreaks()) {
            if (this.excludeWriter == br.isExcluded()) {
                contentWriter.writeRow(this.createBreakRow(br, comparisonMetadata, fieldCount, fieldMap, fieldBreakMap));
                if (++count % 10000 == 0) {
                    LOG.info("Wrote {} {}breaks", count, this.excludeWriter ? "excluded " : "");
                }
            }
        }
        LOG.info("Wrote {} total {}breaks", count, this.excludeWriter ? "excluded " : "");

        contentWriter.closeContent();
    }

    private CatoContentRow createBreakRow(Break br, CatoComparisonMetadata comparisonMetadata, int fieldCount, Map> fieldMap, Map fieldBreakMap) {

        SimpleContentRow row = new SimpleContentRow(fieldCount);

        String breakTypeStr = "N/A";
        int groupId = -1;

        for (String field : br.getDataObject().getFields()) {
            this.setFieldValue(field, br.getDataObject().getValue(field), row, fieldMap);
        }

        if (br instanceof FieldBreak) {
            FieldBreak fieldBreak = (FieldBreak) br;

            for (String field : fieldBreak.getFields()) {
                this.setFieldValue(fieldBreakMap.get(field), fieldBreak.getExpectedValue(field), row, fieldMap);
                this.setFieldType(fieldBreakMap.get(field), ValueType.RIGHT_VALUE, row, fieldMap);

                if (!this.excludeWriter && fieldBreak.isExcluded(field)) {
                    this.setFieldType(field, ValueType.EXCLUDE, row, fieldMap);
                } else {
                    this.setFieldType(field, ValueType.FIELD_BREAK, row, fieldMap);
                }
            }
            breakTypeStr = "Different values";
        } else {
            if (br.getDataSide() == CatoDataSide.LEFT) {
                this.setRowType(ValueType.LEFT_ONLY, row, fieldCount);
                breakTypeStr = "Only in " + comparisonMetadata.getComparison().getLeftDataSource().getShortName();
            } else if (br.getDataSide() == CatoDataSide.RIGHT) {
                this.setRowType(ValueType.RIGHT_ONLY, row, fieldCount);
                breakTypeStr = "Only in " + comparisonMetadata.getComparison().getRightDataSource().getShortName();
            }
        }

        if (br instanceof GroupBreak) {
            GroupBreak groupBreak = (GroupBreak) br;
            breakTypeStr += " group";
            groupId = groupBreak.getGroupId();

            for (String field : groupBreak.getFields()) {
                this.setFieldType(field, ValueType.FIELD_BREAK, row, fieldMap);
            }
        }

        for (String field : comparisonMetadata.getComparison().getExcludeFields()) {
            this.setFieldType(field, ValueType.EXCLUDE, row, fieldMap);
        }

        this.setFieldValue(BREAK_TYPE, breakTypeStr, row, fieldMap);
        if (groupId != -1) {
            this.setFieldValue(BREAK_GROUP, groupId, row, fieldMap);
        }

        return row;
    }

    private CatoContentRow createHeaderRow(CatoComparisonMetadata comparisonMetadata, int fieldCount, Map> fieldMap, Map fieldBreakMap) {

        SimpleContentRow row = new SimpleContentRow(fieldCount);

        for (String field : fieldMap.keySet()) {
            this.setFieldValue(field, field, row, fieldMap);
        }

        this.setFieldType(comparisonMetadata.getComparison().getKeyFields(), ValueType.KEY, row, fieldMap);
        this.setFieldType(comparisonMetadata.getComparison().getExcludeFields(), ValueType.EXCLUDE, row, fieldMap);
        this.setFieldType(comparisonMetadata.getExcludedFieldBreakFields(), ValueType.EXCLUDE, row, fieldMap);
        this.setFieldType(comparisonMetadata.getIncludedFieldBreakFields(), ValueType.FIELD_BREAK, row, fieldMap);
        this.setFieldType(comparisonMetadata.getGroupBreakFields(), ValueType.FIELD_BREAK, row, fieldMap);
        this.setFieldType(fieldBreakMap.values(), ValueType.RIGHT_VALUE, row, fieldMap);

        return row;
    }

    private void setFieldValue(String field, Object value, SimpleContentRow row, Map> fieldMap) {
        for (int index : fieldMap.get(field)) {
            row.setValue(index, value);
        }
    }

    private void setFieldType(String field, ValueType type, SimpleContentRow row, Map> fieldMap) {
        if (!fieldMap.containsKey(field)) {
            return;
        }

        for (int index : fieldMap.get(field)) {
            row.setValueType(index, type);
        }
    }

    private void setFieldType(Collection fields, ValueType type, SimpleContentRow row, Map> fieldMap) {
        for (String field : fields) {
            this.setFieldType(field, type, row, fieldMap);
        }
    }

    private void setRowType(ValueType type, SimpleContentRow row, int fieldCount) {
        for (int index = 0; index < fieldCount; index++) {
            row.setValueType(index, type);
        }
    }

    private int calculateFieldMaps(CatoComparisonMetadata comparisonMetadata, Map> fieldMap, Map fieldBreakMap) {

        Set leftFields = new LinkedHashSet(comparisonMetadata.getLeftFields());
        leftFields.addAll(comparisonMetadata.getFieldBreakFields());

        String fieldBreakField;
        int fieldCount = 0;

        this.addField(BREAK_TYPE, fieldCount++, fieldMap);
        if (comparisonMetadata.hasGroupBreaks()) {
            this.addField(BREAK_GROUP, fieldCount++, fieldMap);
        }

        // Add key fields first
        for (String field : comparisonMetadata.getComparison().getKeyFields()) {
            this.addField(field, fieldCount++, fieldMap);
        }

        for (String field : leftFields) {
            // key fields already added
            if (comparisonMetadata.getComparison().getKeyFields().contains(field)) {
                continue;
            }

            // add exclude fields last
            if (comparisonMetadata.getComparison().getExcludeFields().contains(field)) {
                continue;
            }

            this.addField(field, fieldCount++, fieldMap);

            if (comparisonMetadata.getFieldBreakFields().contains(field)) {
                fieldBreakField = comparisonMetadata.getComparison().getProperties().getMappedFields().get(field);

                // if there is no mapped field, use the same field name with a suffix
                if (fieldBreakField == null) {
                    fieldBreakField = this.getRefFieldSuffix(field, comparisonMetadata);
                }

                // if there is a mapped field, use that name instead
                else {
                    // if the mapped field name is also in the left dataset, then add the suffix
                    if (leftFields.contains(fieldBreakField)) {
                        fieldBreakField = this.getRefFieldSuffix(fieldBreakField, comparisonMetadata);
                    }
                }

                fieldBreakMap.put(field, fieldBreakField);
                this.addField(fieldBreakField, fieldCount++, fieldMap);
            }
        }

        for (String field : comparisonMetadata.getRightFields()) {
            // key fields already added
            if (comparisonMetadata.getComparison().getKeyFields().contains(field)) {
                continue;
            }

            // add exclude fields last
            if (comparisonMetadata.getComparison().getExcludeFields().contains(field)) {
                continue;
            }

            if (!fieldMap.keySet().contains(field)) {
                this.addField(field, fieldCount++, fieldMap);
            }
        }

        // add exclude fields
        for (String field : comparisonMetadata.getComparison().getExcludeFields()) {
            if (leftFields.contains(field) || comparisonMetadata.getRightFields().contains(field)) {
                this.addField(field, fieldCount++, fieldMap);
            }
        }

        return fieldCount;
    }

    private void addField(String field, int fieldCount, Map> fieldMap) {
        if (!fieldMap.containsKey(field)) {
            fieldMap.put(field, new HashSet());
        }

        fieldMap.get(field).add(fieldCount);
    }

    private String getRefFieldSuffix(String field, CatoComparisonMetadata info) {
        return field.concat(" (" + info.getComparison().getRightDataSource().getShortName() + ")");
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy