ch.sdi.report.SdiReporter.java Source code

Java tutorial

Introduction

Here is the source code for ch.sdi.report.SdiReporter.java

Source

/**
 * Copyright (c) 2014 by the original author or authors.
 *
 * This code is free software; you can redistribute it and/or modify it under the terms of the
 * GNU Lesser General Public License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

package ch.sdi.report;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;

import ch.sdi.core.impl.data.Dataset;
import ch.sdi.core.impl.data.Person;
import ch.sdi.report.ReportMsg.ReportType;

/**
 * Global singleton for collecting ReportMsg items in order to render a report at the end of the
 * data import.
 * <p>
 *
 * @version 1.0 (20.11.2014)
 * @author  Heri
 */
@Component
public class SdiReporter {

    /** logger for this class */
    private Logger myLog = LogManager.getLogger(SdiReporter.class);

    private List<ReportMsg> myMessages = new ArrayList<ReportMsg>();

    /**
     * Constructor
     *
     */
    public SdiReporter() {
        super();
    }

    /**
     * Clears all ReportMsg from internal memory
     */
    public void reset() {
        myLog.info("resetting " + this.getClass().getSimpleName());
        myMessages = new ArrayList<ReportMsg>();
    }

    /**
     * Adds given ReportMsg to the internal memory
     * <p>
     * @param aMsg
     */
    public void add(ReportMsg aMsg) {
        // Since wie are already in a call from a logger there would be an error entry if we call
        // the logger again ("Recursive call to appender "). So log this asynchroneously:
        CompletableFuture.supplyAsync(() -> "adding a message").thenAcceptAsync(myLog::trace);
        myMessages.add(aMsg);
    }

    /**
     * Renders the report
     * <p>
     * @return
     */
    public String getReport() {
        myLog.debug("Rendering the report");
        StringBuilder result = new StringBuilder();

        DateFormat df = new SimpleDateFormat("dd.MM.yyyy, hh:mm:ss");

        appendTitle(result, "Import " + df.format(new Date()), "*");
        result.append("\n");

        appendSimpleEntry(result, "Source:", findSimpleStringEntry(ReportType.COLLECTOR_CFG, "InputSource"));
        result.append("\n");

        Collection<ReportMsg> preparsedFiltered = findOfTypes(ReportType.PREPARSE_FILTER);
        appendSummary(result, preparsedFiltered);

        Collection<ReportMsg> parsed = findOfTypes(ReportType.COLLECTOR);
        appendSummary(result, parsed);

        Collection<ReportMsg> parsedProblems = findOfTypes(ReportType.COLLECTOR_PROBLEM);
        appendSummary(result, parsedProblems);

        Collection<ReportMsg> postparsedFiltered = findOfTypes(ReportType.POSTPARSE_FILTER);
        appendSummary(result, postparsedFiltered);

        Collection<ReportMsg> skippedNoEmail = findOfTypes(ReportType.SKIPPED_NO_EMAIL);
        appendSummary(result, skippedNoEmail);

        Collection<ReportMsg> processed = findOfTypes(ReportType.TARGET);
        appendSummary(result, processed);

        Collection<ReportMsg> processFailed = findOfTypes(ReportType.TARGET_PROBLEM);
        appendSummary(result, processFailed);

        result.append("\n");
        appendProcessedPersons(result, processed);

        result.append("\n");
        appendFailedPersons(result, processFailed);

        result.append("\n");
        appendSkippedNoEmail(result, skippedNoEmail);

        result.append("\n");
        appendFiltered(result, postparsedFiltered);

        result.append("\n");
        appendTitle(result, "All collected report messages (unformatted)", "-");
        result.append("" + myMessages);

        return result.toString();
    }

    /**
     * @param aResult
     * @param aFiltered
     */
    private void appendFiltered(StringBuilder aSb, Collection<ReportMsg> aFiltered) {
        appendTitle(aSb, "Filtered while collecting the raw data", "-");

        aFiltered.stream()
                .filter(msg -> (msg.getKey().equals("Skpped Persons (no mail address)"))
                        && msg.getValue() instanceof Collection)
                .map(msg -> Collection.class.cast(msg.getValue())).forEach(list -> appendDatasetList(aSb, list));
    }

    /**
     * @param aSb
     * @param aList
     * @return
     */
    private void appendDatasetList(StringBuilder aSb, Collection<?> aList) {
        aList.stream().filter(p -> p instanceof Dataset).map(p -> Dataset.class.cast(p))
                .forEach(p -> appendDataset(aSb, p));
    }

    /**
     * @param aSb
     * @param aP
     * @return
     */
    private void appendDataset(StringBuilder aSb, Dataset aDataset) {
        aSb.append("    ").append(aDataset).append("\n");
    }

    /**
     * @param aResult
     * @param aSkippedNoEmail
     */
    private void appendSkippedNoEmail(StringBuilder aSb, Collection<ReportMsg> aSkippedNoEmail) {
        appendTitle(aSb, "Skipped because there is no email address", "-");

        aSkippedNoEmail.stream()
                .filter(msg -> (msg.getKey().equals("Skpped Persons (no mail address)"))
                        && msg.getValue() instanceof Collection)
                .map(msg -> Collection.class.cast(msg.getValue())).forEach(list -> appendPersonList(aSb, list));
    }

    /**
     * @param aResult
     * @param aProcessFailed
     */
    private void appendFailedPersons(StringBuilder aSb, Collection<ReportMsg> aProcessFailed) {
        appendTitle(aSb, "Failed during processing", "-");

        aProcessFailed.stream()
                .filter(msg -> (msg.getKey().equals("FailedPersons")) && msg.getValue() instanceof Collection)
                .map(msg -> Collection.class.cast(msg.getValue())).forEach(list -> appendPersonList(aSb, list));
    }

    /**
     * @param aResult
     * @param aProcessed
     */
    private void appendProcessedPersons(StringBuilder aSb, Collection<ReportMsg> aProcessed) {
        appendTitle(aSb, "Processed Persons", "-");

        aProcessed.stream()
                .filter(msg -> (msg.getKey().equals("ProcessedPersons")) && msg.getValue() instanceof Collection)
                .map(msg -> Collection.class.cast(msg.getValue())).forEach(list -> appendPersonList(aSb, list));

        aSb.append("\n");
        appendTitle(aSb, "Persons already in target platform (duplicate)", "-");

        aProcessed.stream()
                .filter(msg -> (msg.getKey().equals("DuplicatePersons")) && msg.getValue() instanceof Collection)
                .map(msg -> Collection.class.cast(msg.getValue())).forEach(list -> appendPersonList(aSb, list));

    }

    private void appendPersonList(StringBuilder aSb, Collection<?> list) {
        list.stream().filter(p -> p instanceof Person).map(p -> Person.class.cast(p))
                .forEach(p -> appendSimplePerson(aSb, p));
    }

    private void appendSimplePerson(StringBuilder aSb, Person<?> p) {
        aSb.append("    ").append(p.getEMail()).append(" (").append(p.getGivenname()).append(" ")
                .append(p.getFamilyName()).append(")\n");
    }

    /**
     * @param aResult
     * @param aMessages
     */
    private void appendSummary(StringBuilder aSb, Collection<ReportMsg> aMessages) {
        aMessages.forEach(msg -> {
            Object value = msg.getValue();

            if (value instanceof Collection) {
                value = ((Collection<?>) value).size();
            }

            appendSimpleEntry(aSb, msg.getKey(), value);
        });
    }

    /**
     *
     */
    private void appendSimpleEntry(StringBuilder aSb, String aName, Object aValue) {
        aSb.append(aName).append(": ").append(aValue).append("\n");
    }

    /**
     * @param aResult
     * @param aTitle
     * @param aUnderlineChar
     */
    private void appendTitle(StringBuilder aSb, String aTitle, String aUnderlineChar) {
        aSb.append(aTitle).append("\n");
        for (int i = 0; i < aTitle.length(); i++) {
            aSb.append(aUnderlineChar);
        }
        aSb.append("\n");
    }

    private String findSimpleStringEntry(ReportType aReportType, String aKey) {
        return findSimpleEntry(aReportType, aKey, String.class);
    }

    /**
     * @param aCollector
     * @param aString
     * @return
     */
    private <T> T findSimpleEntry(ReportType aReportType, String aKey, Class<T> aClass) {
        Collection<ReportMsg> messages = findOfTypes(aReportType);
        for (ReportMsg msg : messages) {
            if (msg.getKey().equals(aKey)) {
                Object o = msg.getValue();

                if (aClass.isInstance(o)) {
                    return aClass.cast(o);

                } // if aClass.isInstance( obj )

                myLog.warn("Entry found for report type " + aReportType + " and key " + aKey
                        + ", but not of desired type! Entry: " + o.getClass().getName() + "; expected: "
                        + aClass.getName());
                return null;

            } // if key.equals( aKey )
        }

        myLog.warn("No entry found for report type " + aReportType + " and key " + aKey);
        return null;
    }

    /**
     * @param aReportType
     * @return
     */
    private Collection<ReportMsg> findOfTypes(ReportType aReportType) {
        return myMessages.stream().filter(msg -> msg.getType() == aReportType).collect(Collectors.toSet());
    }

}