/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition 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 General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////
package org.projectforge.common;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.collections.CollectionUtils;
/**
* Represents an imported sheet (e. g. MS Excel sheet) containing the bean objects.
* @author Kai Reinhard (k.reinhard@micromata.de)
*
*/
public class ImportedSheet<T> implements Serializable
{
private static final long serialVersionUID = 3643437932617400461L;
private List<ImportedElement<T>> elements;
private String name;
private boolean open;
private int totalNumberOfElements;
private int numberOfNewElements;
private int numberOfModifiedElements;
private int numberOfUnmodifiedElements;
private int numberOfFaultyElements;
private boolean dirty = true;
private boolean reconciled = false;
private int numberOfCommittedElements = -1;
private Map<String, Object> properties;
private Map<String, Set<Object>> errorProperties;
private ImportStatus status = ImportStatus.NOT_RECONCILED;
/**
* List of imported elements (e. g. MS Excel rows as bean object).
* @return
*/
public List<ImportedElement<T>> getElements()
{
return elements;
}
public void addElement(final ImportedElement<T> element)
{
if (elements == null) {
elements = new ArrayList<ImportedElement<T>>();
}
elements.add(element);
}
public int getTotalNumberOfElements()
{
checkStatistics();
return totalNumberOfElements;
}
/**
* Nur ungleich 0, falls die Datensätze schon verprobt wurden.
*/
public int getNumberOfNewElements()
{
checkStatistics();
return numberOfNewElements;
}
public void selectAll(final boolean select, final boolean onlyModified)
{
if (elements == null) {
return;
}
for (final ImportedElement<T> element : elements) {
if (onlyModified == false || element.isModified() == true || element.isNew() == true) {
element.setSelected(select);
} else {
element.setSelected(!select);
}
}
}
public void select(final boolean select, final boolean onlyModified, final int number)
{
if (elements == null) {
return;
}
int counter = number;
for (final ImportedElement<T> element : elements) {
if (onlyModified == false || element.isModified() == true || element.isNew() == true) {
if (--counter < 0) {
element.setSelected(!select);
} else {
element.setSelected(select);
}
} else {
element.setSelected(!select);
}
}
}
/**
* Nur ungleich 0, falls die Datensätze schon verprobt wurden.
*/
public int getNumberOfModifiedElements()
{
checkStatistics();
return numberOfModifiedElements;
}
/**
* Nur ungleich 0, falls die Datensätze schon verprobt wurden.
*/
public int getNumberOfUnmodifiedElements()
{
return numberOfUnmodifiedElements;
}
public void calculateStatistics()
{
totalNumberOfElements = 0;
numberOfNewElements = 0;
numberOfModifiedElements = 0;
numberOfUnmodifiedElements = 0;
numberOfFaultyElements = 0;
boolean changes = false;
if (elements != null) {
for (final ImportedElement<T> element : elements) {
totalNumberOfElements++;
if (reconciled == true) {
element.setReconciled(true);
if (element.isNew() == true) {
numberOfNewElements++;
changes = true;
} else if (element.isModified() == true) {
numberOfModifiedElements++;
changes = true;
} else if (element.isUnmodified() == true) {
numberOfUnmodifiedElements++;
}
}
if (element.isFaulty() == true) {
numberOfFaultyElements++;
}
}
}
if (status == ImportStatus.RECONCILED) {
if (changes == false) {
status = ImportStatus.NOTHING_TODO;
}
}
if (isFaulty() == true) {
status = ImportStatus.HAS_ERRORS;
}
dirty = false;
}
private void checkStatistics()
{
if (dirty == true) {
calculateStatistics();
}
}
/**
* Name of the sheet (e. g. name of the MS Excel sheet).
* @return
*/
public String getName()
{
return name;
}
public void setName(final String name)
{
this.name = name;
}
/**
* Can be used for opening and closing this sheet in gui.
*/
public boolean isOpen()
{
return open;
}
public void setOpen(final boolean open)
{
this.open = open;
}
public ImportStatus getStatus()
{
if (status == null) {
checkStatistics();
}
return status;
}
public boolean isReconciled()
{
return reconciled;
}
public boolean isFaulty()
{
return numberOfFaultyElements > 0;
}
/**
* After commit, the number of committed values will be given.
*/
public int getNumberOfCommittedElements()
{
return numberOfCommittedElements;
}
public void setNumberOfCommittedElements(final int numberOfCommittedElements)
{
this.numberOfCommittedElements = numberOfCommittedElements;
}
public int getNumberOfFaultyElements()
{
return numberOfFaultyElements;
}
public void setProperty(final String key, final Object value)
{
if (this.properties == null) {
this.properties = new HashMap<String, Object>();
}
this.properties.put(key, value);
}
public Object getProperty(final String key)
{
if (this.properties == null) {
return null;
}
return this.properties.get(key);
}
public Map<String, Set<Object>> getErrorProperties()
{
if (dirty == false && this.errorProperties != null) {
return this.errorProperties;
}
if (CollectionUtils.isEmpty(this.elements) == true) {
return null;
}
errorProperties = null;
for (final ImportedElement<T> el : this.elements) {
if (el.isFaulty() == true) {
final Map<String, Object> map = el.getErrorProperties();
for (final String key : map.keySet()) {
final Object value = map.get(key);
if (errorProperties == null) {
errorProperties = new HashMap<String, Set<Object>>();
}
Set<Object> set = null;
if (errorProperties.containsKey(key) == true) {
set = errorProperties.get(key);
}
if (set == null) {
set = new TreeSet<Object>();
errorProperties.put(key, set);
}
set.add(value);
}
}
}
return errorProperties;
}
public void setStatus(final ImportStatus status)
{
boolean allowed = true;
if (this.status == ImportStatus.NOT_RECONCILED || this.status == null) {
if (status.isIn(ImportStatus.IMPORTED, ImportStatus.NOTHING_TODO) == true) {
// State change not allowed.
allowed = false;
}
} else if (this.status == ImportStatus.RECONCILED) {
// Everything is allowed
} else {
// Everything is allowed
}
if (allowed == false) {
throw new UnsupportedOperationException("State change not allowed: '" + this.status + "' -> '" + status + "'");
}
this.status = status;
if (status == ImportStatus.RECONCILED) {
reconciled = true;
} else if (status == ImportStatus.NOT_RECONCILED) {
reconciled = false;
}
if (isFaulty() == true) {
this.status = ImportStatus.HAS_ERRORS;
}
}
}