/* * Copyright (c) 2012 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * HUMBOLDT EU Integrated Project #030962 * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.common.align.transformation.report.impl; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; import com.google.common.collect.LinkedHashMultiset; import com.google.common.collect.Multiset; import com.google.common.collect.Multiset.Entry; import de.fhg.igd.slf4jplus.ALogger; import de.fhg.igd.slf4jplus.ALoggerFactory; import eu.esdihumboldt.hale.common.align.transformation.report.TransformationMessage; import eu.esdihumboldt.hale.common.align.transformation.report.TransformationReport; import eu.esdihumboldt.hale.common.align.transformation.report.TransformationReporter; import eu.esdihumboldt.hale.common.core.report.Report; import eu.esdihumboldt.hale.common.core.report.ReportLog; import eu.esdihumboldt.hale.common.core.report.impl.AbstractReporter; /** * Reporter for transformation messages * * @author Simon Templer */ public class DefaultTransformationReporter extends AbstractReporter<TransformationMessage> implements TransformationReport, TransformationReporter { /** * The logger */ private static final ALogger log = ALoggerFactory.getMaskingLogger( DefaultTransformationReporter.class, null); /** * Transformation message key that decides on message equality. Messages are * equal if the cell ID and message are the same, the stack trace is * ignored. */ public class TMessageKey { private final TransformationMessage message; /** * Create a transformation message key. * * @param message the original message */ public TMessageKey(TransformationMessage message) { this.message = message; } /** * @return the original message */ public TransformationMessage getMessage() { return message; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + getOuterType().hashCode(); result = prime * result + ((message == null || message.getCellId() == null) ? 0 : message.getCellId() .hashCode()); result = prime * result + ((message == null || message.getMessage() == null) ? 0 : message.getMessage() .hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; TMessageKey other = (TMessageKey) obj; if (!getOuterType().equals(other.getOuterType())) return false; if (message == null) { return other.message == null; } if (message.getCellId() == null) { if (other.message.getCellId() != null) return false; } else if (!message.getCellId().equals(other.message.getCellId())) return false; if (message.getMessage() == null) { if (other.message.getMessage() != null) return false; } else if (!message.getMessage().equals(other.message.getMessage())) return false; return true; } private DefaultTransformationReporter getOuterType() { return DefaultTransformationReporter.this; } } /** * Organizes transformation messages. */ public class TMessages { /** * Cell IDs mapped to message keys. */ private final Map<String, Multiset<TMessageKey>> messages = new HashMap<String, Multiset<TMessageKey>>(); /** * Add a message. * * @param message the message to add */ public void add(TransformationMessage message) { String cell = message.getCellId(); Multiset<TMessageKey> msgs = messages.get(cell); if (msgs == null) { msgs = LinkedHashMultiset.create(); messages.put(cell, msgs); } msgs.add(new TMessageKey(message)); } /** * Get the collected messages, if applicable extended with the message * count. * * @return the messages */ public Collection<TransformationMessage> getMessages() { Collection<TransformationMessage> result = new ArrayList<TransformationMessage>(); for (Multiset<TMessageKey> msgs : messages.values()) { for (Entry<TMessageKey> entry : msgs.entrySet()) { if (entry.getCount() > 1) { TransformationMessage org = entry.getElement().getMessage(); Throwable throwable = org.getThrowable(); String stackTrace = null; if (throwable == null) { stackTrace = org.getStackTrace(); } result.add(new TransformationMessageImpl(org.getCellId(), org.getMessage() + " (" + entry.getCount() + " times)", throwable, stackTrace)); } else { result.add(entry.getElement().getMessage()); } } } return result; } /** * Determines if there are any messages contained. * * @return if there are any messages present */ public boolean hasMessages() { return !messages.isEmpty(); } } private final boolean doLog; private final TMessages warn = new TMessages(); private final TMessages error = new TMessages(); private final TMessages info = new TMessages(); /** * Create an empty report. It is set to not successful by default. But you * should call {@link #setSuccess(boolean)} nonetheless to update the * timestamp after the task has finished. * * @param taskName the name of the task the report is related to * @param doLog if added messages shall also be logged using {@link ALogger} */ public DefaultTransformationReporter(String taskName, boolean doLog) { super(taskName, TransformationMessage.class); this.doLog = doLog; } @Override public void warn(TransformationMessage message) { warn.add(message); } @Override public void error(TransformationMessage message) { error.add(message); } @Override public void info(TransformationMessage message) { info.add(message); } @Override public Collection<TransformationMessage> getWarnings() { return warn.getMessages(); } @Override public Collection<TransformationMessage> getErrors() { return error.getMessages(); } @Override public Collection<TransformationMessage> getInfos() { return info.getMessages(); } @Override public void setSuccess(boolean success) { super.setSuccess(success); if (doLog) { // print warnings for (TransformationMessage msg : getWarnings()) { log.warn(msg.getMessage(), msg.getThrowable()); } // print errors for (TransformationMessage msg : getErrors()) { log.error(msg.getMessage(), msg.getThrowable()); } // print summary String message = getTaskName() + " - " + getSummary(); if (error.hasMessages()) { log.error(message); } else if (warn.hasMessages()) { log.warn(message); } else { log.info(message); } } } /** * Add all messages of the given report to this report. They may the logged * (again) with a call to {@link #setSuccess(boolean)}. * * @see ReportLog#importMessages(Report) */ @Override public void importMessages(Report<? extends TransformationMessage> report) { for (TransformationMessage message : report.getErrors()) { error.add(message); } for (TransformationMessage message : report.getWarnings()) { warn.add(message); } for (TransformationMessage message : report.getInfos()) { info.add(message); } } }