/**
* DataCleaner (community edition)
* Copyright (C) 2014 Neopost - Customer Information Management
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.datacleaner.result.save;
import java.io.OutputStream;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.io.output.NullOutputStream;
import org.apache.commons.lang.SerializationException;
import org.apache.commons.lang.SerializationUtils;
import org.apache.metamodel.util.FileHelper;
import org.apache.metamodel.util.Resource;
import org.datacleaner.api.AnalyzerResult;
import org.datacleaner.job.ComponentJob;
import org.datacleaner.result.AnalysisResult;
import org.datacleaner.result.SimpleAnalysisResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AnalysisResultSaveHandler {
private static final Logger logger = LoggerFactory.getLogger(AnalysisResultSaveHandler.class);
private final AnalysisResult _analysisResult;
private final Resource _resource;
private Map<ComponentJob, AnalyzerResult> _unsafeResultElements;
public AnalysisResultSaveHandler(final AnalysisResult analysisResult, final Resource resource) {
_analysisResult = analysisResult;
_resource = resource;
}
private static void saveOrThrow(final AnalysisResult analysisResult, final Resource resource) {
final SimpleAnalysisResult simpleAnalysisResult;
if (analysisResult instanceof SimpleAnalysisResult) {
simpleAnalysisResult = (SimpleAnalysisResult) analysisResult;
} else {
simpleAnalysisResult =
new SimpleAnalysisResult(analysisResult.getResultMap(), analysisResult.getCreationDate());
}
final OutputStream out = resource.write();
try {
SerializationUtils.serialize(simpleAnalysisResult, out);
} catch (final SerializationException e) {
logger.error("Error serializing analysis result: " + analysisResult, e);
throw e;
} finally {
FileHelper.safeClose(out);
}
}
public boolean saveAttempt() {
try {
saveOrThrow();
return true;
} catch (final SerializationException e) {
return false;
}
}
public void saveWithoutUnsafeResultElements() {
final AnalysisResult safeAnalysisResult = createSafeAnalysisResult();
saveOrThrow(safeAnalysisResult, _resource);
}
public void saveOrThrow() throws SerializationException {
saveOrThrow(_analysisResult, _resource);
}
/**
* Gets a map of unsafe result elements, ie. elements that cannot be saved
* because serialization fails.
*
* @return
*/
public Map<ComponentJob, AnalyzerResult> getUnsafeResultElements() {
if (_unsafeResultElements == null) {
_unsafeResultElements = new LinkedHashMap<>();
final Map<ComponentJob, AnalyzerResult> resultMap = _analysisResult.getResultMap();
for (final Entry<ComponentJob, AnalyzerResult> entry : resultMap.entrySet()) {
final AnalyzerResult analyzerResult = entry.getValue();
try {
SerializationUtils.serialize(analyzerResult, new NullOutputStream());
} catch (final SerializationException e) {
_unsafeResultElements.put(entry.getKey(), analyzerResult);
}
}
}
return _unsafeResultElements;
}
/**
* Creates a safe {@link AnalysisResult} for saving
*
* @return a new {@link AnalysisResult} or null if it is not possible to
* create a result that is safer than the previous.
*/
public AnalysisResult createSafeAnalysisResult() {
final Set<ComponentJob> unsafeKeys = getUnsafeResultElements().keySet();
if (unsafeKeys.isEmpty()) {
return _analysisResult;
}
final Map<ComponentJob, AnalyzerResult> resultMap = new LinkedHashMap<>(_analysisResult.getResultMap());
for (final ComponentJob unsafeKey : unsafeKeys) {
resultMap.remove(unsafeKey);
}
if (resultMap.isEmpty()) {
return null;
}
return new SimpleAnalysisResult(resultMap, _analysisResult.getCreationDate());
}
}