/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.web.orders;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.libreplan.business.INewObject;
import org.libreplan.business.orders.entities.HoursGroup;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.OrderLineGroup;
import org.libreplan.business.requirements.entities.CriterionRequirement;
import org.libreplan.business.requirements.entities.IndirectCriterionRequirement;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.resources.entities.CriterionType;
import org.libreplan.business.resources.entities.CriterionWithItsType;
import org.libreplan.business.resources.entities.ResourceEnum;
import org.libreplan.business.templates.entities.OrderElementTemplate;
import org.libreplan.business.templates.entities.OrderLineGroupTemplate;
/**
* Wrapper represents the handled data in the form of assigning criterion requirement.
*
* Note: this class has a natural ordering that is inconsistent with equals.
*
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
public class HoursGroupWrapper implements INewObject, Comparable<HoursGroupWrapper> {
private static final Log LOG = LogFactory.getLog(HoursGroupWrapper.class);
private Boolean newObject = false;
private List<CriterionRequirementWrapper> directRequirementWrappers = new ArrayList<>();
private List<CriterionRequirementWrapper> exceptionRequirementWrappers = new ArrayList<>();
private OrderElement orderElement;
private OrderElementTemplate template;
private HoursGroup hoursGroup;
public HoursGroupWrapper(HoursGroup hoursGroup, OrderElement orderElement, boolean newObject) {
this.newObject = newObject;
this.orderElement = orderElement;
this.template = null;
this.hoursGroup = hoursGroup;
initRequirementWrappers(hoursGroup);
}
public HoursGroupWrapper(HoursGroup hoursGroup, OrderElementTemplate template, boolean newObject) {
this.newObject = newObject;
this.orderElement = null;
this.template = template;
this.hoursGroup = hoursGroup;
initRequirementWrappers(hoursGroup);
}
private void initRequirementWrappers(HoursGroup hoursGroup) {
directRequirementWrappers = new ArrayList<>();
for (CriterionRequirement requirement : hoursGroup.getDirectCriterionRequirement()) {
CriterionRequirementWrapper wrapper = new CriterionRequirementWrapper(requirement, this, false);
directRequirementWrappers.add(wrapper);
}
exceptionRequirementWrappers = new ArrayList<>();
for (CriterionRequirement requirement : getInvalidIndirectCriterionRequirement()) {
CriterionRequirementWrapper wrapper = new CriterionRequirementWrapper(requirement, this, false);
exceptionRequirementWrappers.add(wrapper);
}
}
public String getCode() {
return this.hoursGroup.getCode();
}
public void setCode(String code) {
if (hoursGroup != null) {
hoursGroup.setCode(code);
}
}
public ResourceEnum getResourceType() {
return hoursGroup.getResourceType();
}
/**
* In ComboBox, value is ResourceEnum, but ZK returns String.
*/
public void setResourceType(String resource) {
if ( ResourceEnum.MACHINE.toString().equals(resource) ) {
hoursGroup.setResourceType(ResourceEnum.MACHINE);
} else {
hoursGroup.setResourceType(ResourceEnum.WORKER);
}
}
@Override
public boolean isNewObject() {
return newObject == null ? false : newObject;
}
public List<CriterionRequirementWrapper> getDirectRequirementWrappers() {
return directRequirementWrappers;
}
public List<CriterionRequirementWrapper> getExceptionRequirementWrappers() {
return exceptionRequirementWrappers;
}
/**
* Used in _listOrderElementCriterionRequirements.zul
* Should be public!
*/
public Integer getWorkingHours() {
return hoursGroup.getWorkingHours();
}
/**
* Used in _listOrderElementCriterionRequirements.zul
* Should be public!
*/
public void setWorkingHours(Integer workingHours) {
hoursGroup.setWorkingHours(workingHours);
}
public BigDecimal getPercentage() {
return orderElementIsOrderLineGroup()
? getPercentageInOrderLineGroup(getWorkHours())
: hoursGroup.getPercentage().scaleByPowerOfTen(2);
}
private boolean orderElementIsOrderLineGroup() {
return getOrderElement() instanceof OrderLineGroup || getTemplate() instanceof OrderLineGroupTemplate;
}
private Integer getWorkHours() {
return (getOrderElement() != null) ? getOrderElement().getWorkHours() : getTemplate().getWorkHours();
}
private OrderElement getOrderElement() {
return orderElement;
}
private OrderElementTemplate getTemplate() {
return template;
}
private BigDecimal getPercentageInOrderLineGroup(Integer workHours) {
BigDecimal workingHours = new BigDecimal(hoursGroup.getWorkingHours()).setScale(2);
BigDecimal total = new BigDecimal(workHours).setScale(2);
return total.equals(new BigDecimal(0).setScale(2))
? new BigDecimal(0).setScale(2)
: workingHours.divide(total, BigDecimal.ROUND_DOWN).scaleByPowerOfTen(2);
}
public void setPercentage(BigDecimal percentage) {
if (percentage != null) {
BigDecimal proportion = percentage.divide(new BigDecimal(100), BigDecimal.ROUND_DOWN);
hoursGroup.setPercentage(proportion);
} else {
hoursGroup.setPercentage(new BigDecimal(0).setScale(2));
}
}
/**
* Used in _listOrderElementCriterionRequirements.zul
* Should be public!
*/
public Boolean getFixedPercentage() {
return hoursGroup.isFixedPercentage();
}
/**
* Used in _listOrderElementCriterionRequirements.zul
* Should be public!
*/
public void setFixedPercentage(Boolean fixedPercentage) {
hoursGroup.setFixedPercentage(fixedPercentage);
}
public HoursGroup getHoursGroup() {
return hoursGroup;
}
public void setHoursGroup(HoursGroup hoursGroup) {
this.hoursGroup = hoursGroup;
}
/**
* Used in _listOrderElementCriterionRequirements.zul
* Should be public!
*/
public boolean isPercentageReadOnly() {
return (!hoursGroup.isFixedPercentage()) || (orderElementIsOrderLineGroup());
}
/**
* Used in _listOrderElementCriterionRequirements.zul
* Should be public!
*/
public boolean isWorkingHoursReadOnly() {
return (hoursGroup.isFixedPercentage()) || (orderElementIsOrderLineGroup());
}
/**
* Operations to manage the criterions requirements
*/
public void assignCriterionRequirementWrapper(CriterionRequirementWrapper newRequirementWrapper) {
directRequirementWrappers.add(newRequirementWrapper);
}
public void addDirectCriterionToHoursGroup(CriterionRequirementWrapper requirementWrapper) {
hoursGroup.addCriterionRequirement(requirementWrapper.getCriterionRequirement());
}
public void addExceptionRequirementWrappers(CriterionRequirementWrapper exceptionWrapper) {
exceptionRequirementWrappers.add(exceptionWrapper);
}
public void selectCriterionToExceptionRequirementWrapper(
CriterionRequirementWrapper exception, CriterionWithItsType criterionAndType) {
exception.setCriterionWithItsType(criterionAndType);
IndirectCriterionRequirement indirect = findValidRequirementByCriterion(criterionAndType.getCriterion());
exception.setCriterionRequirement(indirect);
exception.setValid(false);
}
public void removeDirectCriterionRequirementWrapper(CriterionRequirementWrapper directWrapper) {
removeDirectCriterionRequirement(directWrapper);
getDirectRequirementWrappers().remove(directWrapper);
}
public void removeDirectCriterionRequirement(CriterionRequirementWrapper directWrapper) {
if (directWrapper.getCriterionWithItsType() != null) {
CriterionRequirement direct = directWrapper.getCriterionRequirement();
hoursGroup.removeCriterionRequirement(direct);
}
}
public void removeExceptionCriterionRequirementWrapper(CriterionRequirementWrapper exception) {
if (exception.getCriterionWithItsType() != null) {
exception.setValid(true);
}
getExceptionRequirementWrappers().remove(exception);
}
public void updateListExceptionCriterionRequirementWrapper() {
// Removes the old exception into list ExceptionRequirementWrappers
List<CriterionRequirementWrapper> list = new ArrayList<>(getExceptionRequirementWrappers());
for (CriterionRequirementWrapper exception : list) {
if ( (exception.getCriterionWithItsType() != null) && (exceptionWasRemoved(exception)) ) {
getExceptionRequirementWrappers().remove(exception);
}
}
// Add new exception into list ExceptionRequirementWrappers
for (CriterionRequirement requirement : getInvalidIndirectCriterionRequirement()) {
CriterionRequirementWrapper exception = findRequirementWrapperByRequirement(requirement);
if (exception == null) {
exception = new CriterionRequirementWrapper(requirement, this, false);
exceptionRequirementWrappers.add(exception);
}
}
}
private boolean exceptionWasRemoved(CriterionRequirementWrapper exception) {
return !hoursGroup.getCriterionRequirements().contains(exception.getCriterionRequirement());
}
public void removeDirectCriterionsWithDifferentResourceType() {
for (CriterionRequirement requirement : hoursGroup.getDirectCriterionRequirement()) {
if (!hoursGroup.isValidResourceType(requirement)) {
removeCriterionRequirementWrapper(requirement);
} else if ( !hoursGroup.isValidResourceTypeChanged(requirement) ) {
removeCriterionRequirementWrapper(requirement);
}
}
}
private void removeCriterionRequirementWrapper(CriterionRequirement requirement) {
CriterionRequirementWrapper requirementWrapper = findRequirementWrapperByRequirement(requirement);
if (requirementWrapper != null) {
this.removeDirectCriterionRequirementWrapper(requirementWrapper);
}
}
public List<CriterionRequirementWrapper> getCriterionRequirementWrappersView() {
List<CriterionRequirementWrapper> list = new ArrayList<>();
list.addAll(getDirectRequirementWrappers());
list.addAll(getExceptionRequirementWrappers());
return list;
}
/**
* Used in _listHoursGroupCriterionRequirements.zul
* Should be public!
*/
public List<CriterionWithItsType> getValidCriterions() {
List<CriterionWithItsType> list = new ArrayList<>();
for (IndirectCriterionRequirement requirement : getValidIndirectCriterionRequirement()) {
Criterion criterion = requirement.getCriterion();
CriterionType type = criterion.getType();
list.add(new CriterionWithItsType(type, criterion));
}
return list;
}
/**
* Used in _listOrderElementCriterionRequirements.zul
* Should be public!
*/
public boolean dontExistValidCriterions() {
return getValidCriterions().isEmpty();
}
private IndirectCriterionRequirement findValidRequirementByCriterion(Criterion criterion) {
for (IndirectCriterionRequirement requirement : getValidIndirectCriterionRequirement()) {
if (requirement.getCriterion().equals(criterion)) {
return requirement;
}
}
return null;
}
private CriterionRequirementWrapper findRequirementWrapperByRequirement(CriterionRequirement requirement) {
for (CriterionRequirementWrapper requirementWrapper : this.getCriterionRequirementWrappersView()) {
if ( (requirementWrapper.getCriterionRequirement() != null) &&
(requirementWrapper.getCriterionRequirement()).equals(requirement) ) {
return requirementWrapper;
}
}
return null;
}
private List<IndirectCriterionRequirement> getInvalidIndirectCriterionRequirement() {
List<IndirectCriterionRequirement> result = new ArrayList<>();
for (IndirectCriterionRequirement requirement : hoursGroup.getIndirectCriterionRequirement()) {
if (!requirement.isValid()) {
result.add(requirement);
}
}
return result;
}
public List<IndirectCriterionRequirement> getValidIndirectCriterionRequirement() {
List<IndirectCriterionRequirement> result = new ArrayList<>();
for (IndirectCriterionRequirement requirement : hoursGroup.getIndirectCriterionRequirement()) {
if (requirement.isValid()) {
result.add(requirement);
}
}
return result;
}
@Override
public int compareTo(HoursGroupWrapper hoursGroupWrapper) {
final String code = getCode();
final String otherCode = hoursGroupWrapper.getCode();
if (code == null) {
LOG.warn(hoursGroup + " has a null code");
return -1;
}
if (otherCode == null) {
LOG.warn(hoursGroupWrapper.hoursGroup + " has a null code");
return 1;
}
return code.compareTo(otherCode);
}
}