ItEr46S19CUProcuraOrganizacionsTraballoItEr40S22: Added multiple search filter to order elements tree.

This commit is contained in:
Manuel Rego Casasnovas 2010-02-04 15:30:34 +01:00 committed by Javier Moran Rua
parent 017b90e5a6
commit b093094831
8 changed files with 299 additions and 48 deletions

View file

@ -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);

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <mrego@igalia.com>
*/
public class OrderElementPredicate implements IPredicate {
private List<FilterPair> filters;
private Date startDate;
private Date finishDate;
public OrderElementPredicate(List<FilterPair> 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<OrderElement> 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;
}
}

View file

@ -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<OrderElement> {
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<OrderElement> {
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<String, String>());
"/orders/_orderElementTreeFilter.zul", filter,
new HashMap<String, String>());
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<OrderElement> {
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<OrderElement> {
/**
* 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<FilterPair> listFilters = (List<FilterPair>) 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<OrderElement> {
*/
public void clear() {
selectDefaultTab();
bdFilter.clear();
bdFilters2.clear();
predicate = null;
}
@ -539,4 +559,42 @@ public class OrderElementTreeController extends TreeController<OrderElement> {
}
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"));
}
}
};
}
}

View file

@ -39,8 +39,8 @@ import org.navalplanner.web.tree.EntitiesTree;
public class OrderElementTreeModel extends EntitiesTree<OrderElement> {
public OrderElementTreeModel(OrderElement root,
List<OrderElement> rootChildren) {
super(OrderElement.class, root, rootChildren);
List<OrderElement> orderElements) {
super(OrderElement.class, root, orderElements);
}
public OrderElementTreeModel(OrderElement root) {

View file

@ -517,12 +517,10 @@ public class OrderModel implements IOrderModel {
IPredicate predicate) {
// Iterate through orderElements from order
List<OrderElement> orderElements = new ArrayList<OrderElement>();
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)) {

View file

@ -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));

View file

@ -56,14 +56,32 @@ public abstract class EntitiesTree<T extends ITreeNode<T>> {
}
}
private static <T extends ITreeNode<T>> MutableTreeModel<T> createFilteredTreeFrom(
Class<T> type, T tree, List<T> elements) {
MutableTreeModel<T> treeModel = MutableTreeModel.create(type, tree);
T parent = treeModel.getRoot();
addFilteredChildren(treeModel, parent, elements);
return treeModel;
}
private static <T extends ITreeNode<T>> void addFilteredChildren(
MutableTreeModel<T> treeModel, T parent, List<T> children) {
for (T each : children) {
if ((each.getParent() != null) && (each.getParent().equals(parent))) {
treeModel.add(parent, each);
addFilteredChildren(treeModel, each, children);
}
}
}
private MutableTreeModel<T> tree;
protected EntitiesTree(Class<T> type, T root) {
tree = createTreeFrom(type, root);
}
protected EntitiesTree(Class<T> type, T root, List<T> rootChildren) {
tree = createTreeFrom(type, root, rootChildren);
protected EntitiesTree(Class<T> type, T root, List<T> elements) {
tree = createFilteredTreeFrom(type, root, elements);
}
public TreeModel asTree() {

View file

@ -1,9 +1,13 @@
<hbox align="right" style="margin-left:700px;">
<!-- Filter by label -->
<label value="${i18n:_('Filter by label:')}" />
<bandboxSearch id="bdFilter" widthBandbox="185px" widthListbox="200px"
finder="LabelBandboxFinder"
model="@{treeController.labels}"/>
<button label="${i18n:_('Filter')}" style="margin-top: -4px"
onClick="treeController.onApplyFilter(event)"/>
<hbox align="center" sclass="filtering-area">
<label value="${i18n:_('Filter by')}"
tooltiptext="${i18n:_('Select required criteria set and press filter button')}"/>
<bandboxMultipleSearch id="bdFilters2" widthBandbox="385px" widthListbox="400px"
finder="multipleFiltersFinder"/>
<label value="${i18n:_('from')}"/>
<datebox id="filterStartDate2" constraint = "@{treeController.checkConstraintStartDate}"/>
<label value="${i18n:_('to')}"/>
<datebox id="filterFinishDate2" constraint = "@{treeController.checkConstraintFinishDate}"/>
<button label="${i18n:_('Filter')}" style="margin-top: -4px"
tooltiptext="${i18n:_('Apply filtering to order elements satisfying required critera')}"
onClick="treeController.onApplyFilter()"/>
</hbox>