/* * 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.business.templates.entities; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.validation.Valid; import org.libreplan.business.i18n.I18nHelper; import org.libreplan.business.orders.entities.CriterionRequirementOrderElementHandler; 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.orders.entities.SchedulingState; import org.libreplan.business.orders.entities.TreeNodeOnListWithSchedulingState; import org.libreplan.business.requirements.entities.DirectCriterionRequirement; import org.libreplan.business.requirements.entities.IndirectCriterionRequirement; import org.libreplan.business.trees.ITreeParentNode; /** * @author Óscar González Fernández <ogonzalez@igalia.com> * */ public class OrderLineGroupTemplate extends OrderElementTemplate implements ITreeParentNode<OrderElementTemplate> { private final CriterionRequirementTemplateHandler criterionRequirementTemplateHandler = CriterionRequirementTemplateHandler.getInstance(); private final class ChildrenManipulator extends TreeNodeOnListWithSchedulingState<OrderElementTemplate> { ChildrenManipulator(List<OrderElementTemplate> templates) { super(templates); } @Override protected void setParentIfRequired(OrderElementTemplate newChild) { newChild.setParent(OrderLineGroupTemplate.this); } @Override public ITreeParentNode<OrderElementTemplate> getParent() { return OrderLineGroupTemplate.this.getParent(); } @Override public OrderElementTemplate getThis() { return OrderLineGroupTemplate.this; } @Override public ITreeParentNode<OrderElementTemplate> toContainer() { return OrderLineGroupTemplate.this.toContainer(); } @Override public OrderElementTemplate toLeaf() { return OrderLineGroupTemplate.this.toLeaf(); } @Override protected SchedulingState getSchedulingStateFrom( OrderElementTemplate node) { return node.getSchedulingState(); } @Override protected void updateWithNewChild(SchedulingState newChildState) { getThis().getSchedulingState().add(newChildState); } @Override public boolean isLeaf() { return false; } @Override public boolean isEmptyLeaf() { return false; } @Override public boolean isUpdatedFromTimesheets() { return false; } @Override public boolean isJiraIssue() { return false; } } public static OrderLineGroupTemplate createNew() { return create(new OrderLineGroupTemplate()); } public static OrderLineGroupTemplate create(OrderLineGroup group) { return create(new OrderLineGroupTemplate(), group); } protected static <T extends OrderLineGroupTemplate> T create(T beingBuilt, OrderLineGroup group) { OrderElementTemplate.create(beingBuilt, group); List<OrderElementTemplate> result = buildChildrenTemplates(beingBuilt, group.getChildren()); beingBuilt.setChildren(result); beingBuilt.propagateIndirectCriterionRequirements(); return beingBuilt; } /** * Propagates {@link IndirectCriterionRequirement} for order to template, * preserving the original value of 'valid' field * * This method is meant to be used the first time an * {@link OrderElementTemplate} was created out from an {@link OrderElement} * and it's needed to propagate its criteria while preserving the original * value of 'valid' field in {@link IndirectCriterionRequirement} */ protected void propagateIndirectCriterionRequirements() { propagateIndirectCriterionRequirementsForOrderLineGroup(this); propagateIndirectCriterionRequirementsForOrderLines(this); } private void propagateIndirectCriterionRequirementsForOrderLineGroup( OrderLineGroupTemplate orderLineGroup) { for (DirectCriterionRequirement each : getDirectCriterionRequirements()) { criterionRequirementTemplateHandler .propagateIndirectCriterionRequirementsForOrderLineGroupKeepingValid( orderLineGroup, each); } } private void propagateIndirectCriterionRequirementsForOrderLines( OrderLineGroupTemplate orderLineGroup) { for (OrderElementTemplate each : orderLineGroup.getChildren()) { if (each instanceof OrderLineTemplate) { criterionRequirementTemplateHandler .propagateIndirectCriterionRequirementsKeepingValid((OrderLineTemplate) each); } } } private static List<OrderElementTemplate> buildChildrenTemplates( OrderLineGroupTemplate parent, List<OrderElement> children) { List<OrderElementTemplate> result = new ArrayList<>(); for (OrderElement each : children) { OrderElementTemplate template = each.createTemplate(); template.setParent(parent); result.add(template); } return result; } private List<OrderElementTemplate> children = new ArrayList<>(); @Override public List<OrderElementTemplate> getChildrenTemplates() { return Collections.unmodifiableList(children); } private ChildrenManipulator getManipulator() { return new ChildrenManipulator(children); } @Override public void add(OrderElementTemplate newChild) { getManipulator().add(newChild); } @Override public void add(int position, OrderElementTemplate newChild) { getManipulator().add(position, newChild); } @Override public void down(OrderElementTemplate existentChild) { getManipulator().down(existentChild); } @Override public void remove(OrderElementTemplate existentChild) { getManipulator().remove(existentChild); } @Override public void replace(OrderElementTemplate previousChild, OrderElementTemplate newChild) { getManipulator().replace(previousChild, newChild); } @Override public void up(OrderElementTemplate existentChild) { getManipulator().up(existentChild); } @Override @Valid public List<OrderElementTemplate> getChildren() { return Collections.unmodifiableList(children); } protected void setChildren(List<OrderElementTemplate> children) { this.children = children; } @Override public ITreeParentNode<OrderElementTemplate> toContainer() { return this; } @Override public OrderElementTemplate toLeaf() { OrderLineTemplate result = OrderLineTemplate.createNew(); copyTo(result); return result; } @Override public boolean isLeaf() { return false; } @Override public boolean isEmptyLeaf() { return false; } private CriterionRequirementOrderElementHandler criterionRequirementOrderElementHandler = CriterionRequirementOrderElementHandler .getInstance(); protected <T extends OrderLineGroup> T setupGroupParts(T group) { T parent = setupElementParts(group); for (OrderElementTemplate each : children) { each.createElement(parent); } return parent; } @Override public OrderElement createElement(OrderLineGroup parent) { OrderLineGroup result = setupSchedulingStateType(setupVersioningInfo( parent, OrderLineGroup.create())); result.initializeTemplate(this); parent.add(result); return setupGroupParts(result); } @Override public String getType() { return I18nHelper._("Group"); } @Override public List<HoursGroup> getHoursGroups() { List<HoursGroup> hoursGroups = new ArrayList<HoursGroup>(); for (OrderElementTemplate orderElement : children) { hoursGroups.addAll(orderElement.getHoursGroups()); } return hoursGroups; } @Override public Integer getWorkHours() { Integer result = 0; for (OrderElementTemplate orderElement : getChildren()) { result += orderElement.getWorkHours(); } return result; } @Override public BigDecimal getBudget() { BigDecimal budget = BigDecimal.ZERO.setScale(2); for (OrderElementTemplate child : children) { budget = budget.add(child.getBudget()); } return budget; } @Override public boolean isOrderTemplate() { return false; } }