/* * 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.materials; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.libreplan.business.materials.daos.IMaterialCategoryDAO; import org.libreplan.business.materials.daos.IMaterialDAO; import org.libreplan.business.materials.daos.IUnitTypeDAO; import org.libreplan.business.materials.entities.Material; import org.libreplan.business.materials.entities.MaterialCategory; import org.libreplan.business.materials.entities.UnitType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.zkoss.ganttz.util.MutableTreeModel; import org.zkoss.zul.TreeModel; /** * @author Óscar González Fernández <ogonzalez@igalia.com> */ public abstract class AssignedMaterialsModel<T, A> implements IAssignedMaterialsModel<T, A> { @Autowired private IMaterialCategoryDAO categoryDAO; @Autowired private IMaterialDAO materialDAO; @Autowired private IUnitTypeDAO unitTypeDAO; private MutableTreeModel<MaterialCategory> materialCategories = MutableTreeModel.create(MaterialCategory.class); private MutableTreeModel<MaterialCategory> allMaterialCategories = MutableTreeModel.create(MaterialCategory.class); private List<Material> matchingMaterials = new ArrayList<>(); private List<UnitType> unitTypes = new ArrayList<>(); @Transactional(readOnly = true) public void initEdit(T element) { assignAndReattach(element); materialCategories = MutableTreeModel.create(MaterialCategory.class); initializeMaterialAssignments(); // Initialize matching materials matchingMaterials.clear(); matchingMaterials.addAll(materialDAO.getAll()); initializeMaterials(matchingMaterials); } protected abstract void initializeMaterialAssignments(); protected abstract void assignAndReattach(T element); protected void reattachMaterial(Material material) { materialDAO.reattachUnmodifiedEntity(material); } private void initializeMaterials(Collection<Material> materials) { for (Material each : materials) { initializeMaterial(each); } } protected void initializeMaterialCategories( Collection<MaterialCategory> materialCategories) { for (MaterialCategory each : materialCategories) { initializeMaterialCategory(each); } } protected void initializeMaterialCategory(MaterialCategory materialCategory) { categoryDAO.reattach(materialCategory); materialCategory.getName(); initializeMaterials(materialCategory.getMaterials()); initializeMaterialCategories(materialCategory.getSubcategories()); } private void initializeMaterial(Material material) { material.getDescription(); material.getCategory().getName(); material.getUnitType().getMeasure(); } @Transactional(readOnly = true) public MutableTreeModel<MaterialCategory> getMaterialCategories() { if (isInitialized() && materialCategories.isEmpty()) { feedTree(materialCategories, getAssignments()); initializeMaterialCategories(materialCategories.asList()); } return materialCategories; } protected abstract List<A> getAssignments(); protected abstract Material getMaterial(A assignment); private void feedTree(MutableTreeModel<MaterialCategory> tree, Collection<? extends A> materialAssignments) { for (A each : materialAssignments) { final Material material = getMaterial(each); addCategory(tree, material.getCategory()); } } /** * Adds category to treeModel If category.parent is not in treeModel add it to treeModel recursively. */ private void addCategory( MutableTreeModel<MaterialCategory> materialCategories, MaterialCategory materialCategory) { categoryDAO.reattach(materialCategory); final MaterialCategory parent = materialCategory.getParent(); if (!materialCategories.contains(parent, materialCategory)) { if (parent == null) { materialCategories.addToRoot(materialCategory); } else { addCategory(materialCategories, parent); materialCategories.add(parent, materialCategory); } } } @Transactional(readOnly = true) public TreeModel getAllMaterialCategories() { if (allMaterialCategories.isEmpty()) { feedTree(allMaterialCategories, categoryDAO.getAll()); initializeMaterialCategories(allMaterialCategories.asList()); } return allMaterialCategories; } private void feedTree(MutableTreeModel<MaterialCategory> tree, List<MaterialCategory> materialCategories) { for (MaterialCategory each : materialCategories) { addCategory(tree, each); } } protected abstract boolean isInitialized(); public List<A> getAssignedMaterials(MaterialCategory materialCategory) { List<A> result = new ArrayList<>(); if (isInitialized()) { for (A each : getAssignments()) { final Material material = getMaterial(each); if (materialCategory == null || materialCategory.getId().equals(material.getCategory().getId())) { result.add(each); } } } return result; } @Transactional(readOnly = true) public void searchMaterials(String text, MaterialCategory materialCategory) { matchingMaterials = materialDAO.findMaterialsInCategoryAndSubCategories(text, materialCategory); initializeMaterials(matchingMaterials); } public List<Material> getMatchingMaterials() { return matchingMaterials; } @Transactional(readOnly = true) public void addMaterialAssignment(A materialAssignment) { MaterialCategory category = addAssignment(materialAssignment); addCategory(materialCategories, category); } protected abstract MaterialCategory addAssignment(A materialAssignment); protected abstract MaterialCategory removeAssignment(A materialAssignment); @Transactional(readOnly = true) public void removeMaterialAssignment(A materialAssignment) { MaterialCategory materialCategory = removeAssignment(materialAssignment); removeCategory(materialCategories, materialCategory); } private void removeCategory( MutableTreeModel<MaterialCategory> materialCategories, MaterialCategory materialCategory) { categoryDAO.reattach(materialCategory); final boolean canDelete = materialCategory.getSubcategories().isEmpty() && getAssignedMaterials(materialCategory).isEmpty(); if (canDelete) { materialCategories.remove(materialCategory); final MaterialCategory parent = materialCategory.getParent(); if (parent != null) { removeCategory(materialCategories, parent); } } } @Override public BigDecimal getUnits(MaterialCategory materialCategory) { BigDecimal result = BigDecimal.ZERO; if (isInitialized()) { for (A each : getAssignments()) { final Material material = getMaterial(each); if (materialCategory.equals(material.getCategory())) { result = result.add(getUnits(each)); } } } return result; } protected abstract BigDecimal getUnits(A assignment); public BigDecimal getPrice(MaterialCategory category) { BigDecimal result = new BigDecimal(0); if (isInitialized()) { for (A each : getAssignments()) { final Material material = getMaterial(each); if (category.equals(material.getCategory())) { result = result.add(getTotalPrice(each)); } } } return result; } protected abstract BigDecimal getTotalPrice(A each); @Override @Transactional(readOnly = true) public void loadUnitTypes() { unitTypes = unitTypeDAO.findAll(); } @Override public List<UnitType> getUnitTypes() { return unitTypes; } }