001/*
002 *  Copyright 2020 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.contentio.archive;
017
018import java.io.ByteArrayOutputStream;
019import java.io.OutputStream;
020import java.io.PrintWriter;
021import java.util.ArrayList;
022import java.util.Collection;
023import java.util.Collections;
024import java.util.List;
025
026import org.apache.commons.collections4.CollectionUtils;
027
028/**
029 * A report of an import ,whether it is a global, partial or unitary one.
030 */
031public final class ImportReport
032{
033    private List<ImportError> _errors;
034    
035    /**
036     * Creates a new empty report.
037     */
038    public ImportReport()
039    {
040        _errors = new ArrayList<>();
041    }
042    
043    private ImportReport(Collection<ImportError> errors)
044    {
045        _errors = new ArrayList<>(errors);
046    }
047    
048    /**
049     * Returns a new {@link ImportReport} which is the union of the given ones
050     * @param reports The reports on which to build the union
051     * @return a new {@link ImportReport} which is the union of the given ones
052     */
053    public static ImportReport union(Collection<ImportReport> reports)
054    {
055        return union(reports.toArray(ImportReport[]::new));
056    }
057    
058    /**
059     * Returns a new {@link ImportReport} which is the union of the given ones
060     * @param reports The reports on which to build the union
061     * @return a new {@link ImportReport} which is the union of the given ones
062     */
063    public static ImportReport union(ImportReport... reports)
064    {
065        if (reports.length == 0)
066        {
067            return new ImportReport();
068        }
069        else if (reports.length == 1)
070        {
071            return new ImportReport(reports[0]._errors);
072        }
073        
074        Collection<ImportError> mergedErrors = Collections.EMPTY_LIST;
075        for (ImportReport current : reports)
076        {
077            mergedErrors = CollectionUtils.union(mergedErrors, current._errors);
078        }
079        
080        ImportReport merged = new ImportReport(mergedErrors);
081        return merged;
082    }
083    
084    /**
085     * Gets an unmodifiable view of the errors of this report
086     * @return an unmodifiable view of the errors of this report
087     */
088    public Collection<ImportError> getErrors()
089    {
090        return Collections.unmodifiableCollection(_errors);
091    }
092    
093    /**
094     * Adds an error to this report
095     * @param error The error to add
096     */
097    public void addError(ImportError error)
098    {
099        _errors.add(error);
100    }
101    
102    /**
103     * Adds all information (errors...) from the other report to this report
104     * @param other The other report
105     */
106    public void addFrom(ImportReport other)
107    {
108        _errors.addAll(other._errors);
109    }
110    
111    /**
112     * An error during an import, which can be {@link ImportReport#addError(ImportError) added} to an {@link ImportReport}
113     */
114    public static final class ImportError
115    {
116        private final Throwable _throwable;
117
118        /**
119         * Creates a new error.
120         * @param t The {@link Throwable}
121         */
122        public ImportError(Throwable t)
123        {
124            _throwable = t;
125        }
126        
127        /**
128         * Gets the {@link Throwable#getMessage() message} of the {@link Throwable}
129         * @return the message
130         */
131        public String getMessage()
132        {
133            return _throwable.getMessage();
134        }
135        
136        /**
137         * Gets the {@link Throwable#getStackTrace() stack trace} of the {@link Throwable}, as formatted string
138         * @return the stacktrace as formatted string
139         */
140        public String getStackTrace()
141        {
142            OutputStream os = new ByteArrayOutputStream();
143            var printWriter = new PrintWriter(os); 
144            _throwable.printStackTrace(printWriter);
145            printWriter.flush();
146            return os.toString();
147        }
148    }
149}