From b0930948318166603e56aa6d4d39d4bd58394c1f Mon Sep 17 00:00:00 2001 From: Manuel Rego Casasnovas Date: Thu, 4 Feb 2010 15:30:34 +0100 Subject: [PATCH] ItEr46S19CUProcuraOrganizacionsTraballoItEr40S22: Added multiple search filter to order elements tree. --- .../navalplanner/web/orders/IOrderModel.java | 7 +- .../web/orders/OrderElementPredicate.java | 176 ++++++++++++++++++ .../orders/OrderElementTreeController.java | 112 ++++++++--- .../web/orders/OrderElementTreeModel.java | 4 +- .../navalplanner/web/orders/OrderModel.java | 4 +- .../templates/TemplatesTreeController.java | 2 +- .../navalplanner/web/tree/EntitiesTree.java | 22 ++- .../webapp/orders/_orderElementTreeFilter.zul | 20 +- 8 files changed, 299 insertions(+), 48 deletions(-) create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementPredicate.java diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/IOrderModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/IOrderModel.java index d6dc25de3..aebff5db5 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/IOrderModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/IOrderModel.java @@ -70,11 +70,8 @@ public interface IOrderModel { IOrderElementModel getOrderElementModel(OrderElement orderElement); /** - * Iterates through order.orderElements, and checks if orderElement holds - * predicate. In case it's true, add orderElement and all its children to - * filtered orderElements list - * - * @return + * Iterates through all the orderElements of an order, and checks if + * orderElement holds predicate. In case it is true, adds orderElement. */ OrderElementTreeModel getOrderElementsFilteredByPredicate(IPredicate predicate); diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementPredicate.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementPredicate.java new file mode 100644 index 000000000..c35030c91 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementPredicate.java @@ -0,0 +1,176 @@ +/* + * This file is part of ###PROJECT_NAME### + * + * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e + * Desenvolvemento Tecnolóxico de Galicia + * + * 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 . + */ + +package org.navalplanner.web.orders; + +import java.util.Date; +import java.util.List; + +import org.navalplanner.business.labels.entities.Label; +import org.navalplanner.business.orders.entities.OrderElement; +import org.navalplanner.business.requirements.entities.CriterionRequirement; +import org.navalplanner.business.resources.entities.Criterion; +import org.navalplanner.web.common.components.finders.FilterPair; + +/** + * Checks if {@link OrderElement} matches with the different filters. + * + * @author Manuel Rego Casasnovas + */ +public class OrderElementPredicate implements IPredicate { + + private List filters; + + private Date startDate; + + private Date finishDate; + + public OrderElementPredicate(List filters, Date startDate, + Date finishDate) { + this.filters = filters; + this.startDate = startDate; + this.finishDate = finishDate; + } + + @Override + public boolean accepts(Object object) { + final OrderElement orderElement = (OrderElement) object; + return accepts(orderElement) || accepts(orderElement.getAllChildren()); + } + + private boolean accepts(OrderElement orderElement) { + if (orderElement == null) { + return false; + } + if (acceptFilters(orderElement) && acceptFiltersDates(orderElement)) { + return true; + } + return false; + } + + private boolean accepts(List orderElements) { + for (OrderElement orderElement : orderElements) { + if (accepts(orderElement)) { + return true; + } + } + return false; + } + + private boolean acceptFilters(OrderElement orderElement) { + if ((filters == null) || (filters.isEmpty())) { + return true; + } + for (FilterPair filter : filters) { + if (!acceptFilter(filter, orderElement)) { + return false; + } + } + return true; + } + + private boolean acceptFilter(FilterPair filter, OrderElement orderElement) { + switch (filter.getType()) { + case Criterion: + return acceptCriterion(filter, orderElement); + case Label: + return acceptLabel(filter, orderElement); + } + return false; + } + + private boolean acceptCriterion(FilterPair filter, OrderElement orderElement) { + Criterion filterCriterion = (Criterion) filter.getValue(); + return existCriterionInOrderElement(filterCriterion, orderElement); + } + + private boolean existCriterionInOrderElement(Criterion filterCriterion, + OrderElement orderElement) { + for (CriterionRequirement criterionRequirement : orderElement + .getCriterionRequirements()) { + if(criterionRequirement.getCriterion().getId().equals(filterCriterion.getId())){ + return true; + } + } + return false; + } + + private boolean acceptLabel(FilterPair filter, OrderElement orderElement) { + Label filterLabel = (Label) filter.getValue(); + return existLabelInOrderElement(filterLabel, orderElement); + } + + private boolean existLabelInOrderElement(Label filterLabel, + OrderElement order) { + for(Label label : order.getLabels()){ + if(label.getId().equals(filterLabel.getId())){ + return true; + } + } + return false; + } + + private boolean acceptFiltersDates(OrderElement orderElement) { + return (acceptStartDate(orderElement.getInitDate()) && (acceptFinishDate(orderElement + .getDeadline()))); + } + + private boolean acceptStartDate(Date initDate) { + if ((initDate == null) && (startDate == null)) { + return true; + } + return isInTheRangeFilterDates(initDate); + } + + private boolean acceptFinishDate(Date deadLine) { + if ((deadLine == null) && (finishDate == null)) { + return true; + } + return isInTheRangeFilterDates(deadLine); + } + + private boolean isInTheRangeFilterDates(Date date) { + // Check if date is into interval between the startdate and finish date + return (isGreaterToStartDate(date, startDate) && isLowerToFinishDate( + date, finishDate)); + } + + private boolean isGreaterToStartDate(Date date, Date startDate) { + if (startDate == null) { + return true; + } + + if (date != null && (date.compareTo(startDate) >= 0)) { + return true; + } + return false; + } + + private boolean isLowerToFinishDate(Date date, Date finishDate) { + if (finishDate == null) { + return true; + } + if (date != null && (date.compareTo(finishDate) <= 0)) { + return true; + } + return false; + } + +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementTreeController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementTreeController.java index 738b17b49..287289570 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementTreeController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementTreeController.java @@ -43,6 +43,7 @@ import org.navalplanner.web.common.Util.Getter; import org.navalplanner.web.common.Util.Setter; import org.navalplanner.web.common.components.bandboxsearch.BandboxMultipleSearch; import org.navalplanner.web.common.components.bandboxsearch.BandboxSearch; +import org.navalplanner.web.common.components.finders.FilterPair; import org.navalplanner.web.orders.assigntemplates.TemplateFinderPopup; import org.navalplanner.web.orders.assigntemplates.TemplateFinderPopup.IOnResult; import org.navalplanner.web.templates.IOrderTemplatesControllerEntryPoints; @@ -54,7 +55,6 @@ import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; import org.zkoss.zul.Button; -import org.zkoss.zul.Checkbox; import org.zkoss.zul.Constraint; import org.zkoss.zul.Datebox; import org.zkoss.zul.Hbox; @@ -78,15 +78,11 @@ public class OrderElementTreeController extends TreeController { private Hbox orderFilter; - private BandboxSearch bdFilter; + private BandboxMultipleSearch bdFilters2; - private Datebox filterStartDate; + private Datebox filterStartDate2; - private Datebox filterFinishDate; - - private BandboxMultipleSearch bdFilters; - - private Checkbox checkIncludeOrderElements; + private Datebox filterFinishDate2; private OrderElementTreeitemRenderer renderer = new OrderElementTreeitemRenderer(); @@ -194,13 +190,17 @@ public class OrderElementTreeController extends TreeController { super.doAfterCompose(comp); // Configuration of the order elements filter - orderFilter.setVisible(false); - filter.setVisible(true); Component filterComponent = Executions.createComponents( - "/orders/_orderElementTreeFilter.zul", - filter, new HashMap()); + "/orders/_orderElementTreeFilter.zul", filter, + new HashMap()); filterComponent.setVariable("treeController", this, true); - bdFilter = (BandboxSearch) filterComponent.getFellow("bdFilter"); + bdFilters2 = (BandboxMultipleSearch) filterComponent + .getFellow("bdFilters2"); + filterStartDate2 = (Datebox) filterComponent + .getFellow("filterStartDate2"); + filterFinishDate2 = (Datebox) filterComponent + .getFellow("filterFinishDate2"); + templateFinderPopup = (TemplateFinderPopup) comp .getFellow("templateFinderPopupAtTree"); } @@ -404,8 +404,8 @@ public class OrderElementTreeController extends TreeController { final OrderElement currentOrderElement) { addCell(createEditButton(currentOrderElement, item), createTemplateButton(currentOrderElement), - createUpButton(item,currentOrderElement), createDownButton(item,currentOrderElement), + createUpButton(item,currentOrderElement), createUnindentButton(item, currentOrderElement), createIndentButton(item, currentOrderElement), createRemoveButton(currentOrderElement)); @@ -448,21 +448,41 @@ public class OrderElementTreeController extends TreeController { /** * Apply filter to order elements in current order - * @param event */ - public void onApplyFilter(Event event) { - org.navalplanner.business.labels.entities.Label label = getSelectedLabel(); - if (label == null) { - label = org.navalplanner.business.labels.entities.Label.create(""); - } - // Create predicate and filter order elements by predicate - predicate = new LabelOrderElementPredicate(label); - filterByPredicate(); + public void onApplyFilter() { + OrderElementPredicate predicate = createPredicate(); + this.predicate = predicate; + + if (predicate != null) { + filterByPredicate(predicate); + } else { + showAllOrderElements(); + } } - private org.navalplanner.business.labels.entities.Label getSelectedLabel() { - return (org.navalplanner.business.labels.entities.Label) bdFilter - .getSelectedElement(); + private OrderElementPredicate createPredicate() { + List listFilters = (List) bdFilters2 + .getSelectedElements(); + Date startDate = filterStartDate2.getValue(); + Date finishDate = filterFinishDate2.getValue(); + + if (listFilters.isEmpty() && startDate == null && finishDate == null) { + return null; + } + return new OrderElementPredicate(listFilters, startDate, finishDate); + } + + private void filterByPredicate(OrderElementPredicate predicate) { + OrderElementTreeModel orderElementTreeModel = orderModel + .getOrderElementsFilteredByPredicate(predicate); + tree.setModel(orderElementTreeModel.asTree()); + tree.invalidate(); + } + + public void showAllOrderElements() { + this.predicate = null; + tree.setModel(orderModel.getOrderElementTreeModel().asTree()); + tree.invalidate(); } @Override @@ -476,7 +496,7 @@ public class OrderElementTreeController extends TreeController { */ public void clear() { selectDefaultTab(); - bdFilter.clear(); + bdFilters2.clear(); predicate = null; } @@ -539,4 +559,42 @@ public class OrderElementTreeController extends TreeController { } return null; } + + /** + * Operations to filter the orders by multiple filters + */ + public Constraint checkConstraintFinishDate() { + return new Constraint() { + @Override + public void validate(Component comp, Object value) + throws WrongValueException { + Date finishDate = (Date) value; + if ((finishDate != null) + && (filterStartDate2.getValue() != null) + && (finishDate.compareTo(filterStartDate2.getValue()) < 0)) { + filterFinishDate2.setValue(null); + throw new WrongValueException(comp, + _("must be greater than start date")); + } + } + }; + } + + public Constraint checkConstraintStartDate() { + return new Constraint() { + @Override + public void validate(Component comp, Object value) + throws WrongValueException { + Date startDate = (Date) value; + if ((startDate != null) + && (filterFinishDate2.getValue() != null) + && (startDate.compareTo(filterFinishDate2.getValue()) > 0)) { + filterStartDate2.setValue(null); + throw new WrongValueException(comp, + _("must be lower than finish date")); + } + } + }; + } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementTreeModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementTreeModel.java index 417ad8e79..14424ca05 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementTreeModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementTreeModel.java @@ -39,8 +39,8 @@ import org.navalplanner.web.tree.EntitiesTree; public class OrderElementTreeModel extends EntitiesTree { public OrderElementTreeModel(OrderElement root, - List rootChildren) { - super(OrderElement.class, root, rootChildren); + List orderElements) { + super(OrderElement.class, root, orderElements); } public OrderElementTreeModel(OrderElement root) { diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderModel.java index 4ca87d0f1..47172223a 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderModel.java @@ -517,12 +517,10 @@ public class OrderModel implements IOrderModel { IPredicate predicate) { // Iterate through orderElements from order List orderElements = new ArrayList(); - for (OrderElement orderElement : order.getOrderElements()) { + for (OrderElement orderElement : order.getAllOrderElements()) { if (!orderElement.isNewObject()) { reattachOrderElement(orderElement); } - reattachLabels(); - initializeLabels(orderElement.getLabels()); // Accepts predicate, add it to list of orderElements if (predicate.accepts(orderElement)) { diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/templates/TemplatesTreeController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/templates/TemplatesTreeController.java index 857a9abae..93d3cbeb5 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/templates/TemplatesTreeController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/templates/TemplatesTreeController.java @@ -64,8 +64,8 @@ public class TemplatesTreeController extends protected void addOperationsCell(Treeitem item, OrderElementTemplate currentElement) { addCell(createEditButton(currentElement), - createUpButton(item, currentElement), createDownButton(item, currentElement), + createUpButton(item, currentElement), createUnindentButton(item, currentElement), createIndentButton(item, currentElement), createRemoveButton(currentElement)); diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/tree/EntitiesTree.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/tree/EntitiesTree.java index e4b3d4835..8943c3132 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/tree/EntitiesTree.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/tree/EntitiesTree.java @@ -56,14 +56,32 @@ public abstract class EntitiesTree> { } } + private static > MutableTreeModel createFilteredTreeFrom( + Class type, T tree, List elements) { + MutableTreeModel treeModel = MutableTreeModel.create(type, tree); + T parent = treeModel.getRoot(); + addFilteredChildren(treeModel, parent, elements); + return treeModel; + } + + private static > void addFilteredChildren( + MutableTreeModel treeModel, T parent, List children) { + for (T each : children) { + if ((each.getParent() != null) && (each.getParent().equals(parent))) { + treeModel.add(parent, each); + addFilteredChildren(treeModel, each, children); + } + } + } + private MutableTreeModel tree; protected EntitiesTree(Class type, T root) { tree = createTreeFrom(type, root); } - protected EntitiesTree(Class type, T root, List rootChildren) { - tree = createTreeFrom(type, root, rootChildren); + protected EntitiesTree(Class type, T root, List elements) { + tree = createFilteredTreeFrom(type, root, elements); } public TreeModel asTree() { diff --git a/navalplanner-webapp/src/main/webapp/orders/_orderElementTreeFilter.zul b/navalplanner-webapp/src/main/webapp/orders/_orderElementTreeFilter.zul index 63af646a2..f0b946d0c 100644 --- a/navalplanner-webapp/src/main/webapp/orders/_orderElementTreeFilter.zul +++ b/navalplanner-webapp/src/main/webapp/orders/_orderElementTreeFilter.zul @@ -1,9 +1,13 @@ - - -