From a9291d47b726e43fe946341eb6ffbc4ac521eec3 Mon Sep 17 00:00:00 2001 From: Manuel Rego Casasnovas Date: Tue, 11 Oct 2011 08:53:25 +0200 Subject: [PATCH] [Bug #1187] Fix issue filtering TaskElements by criteria in project Gantt view FEA: ItEr75S04BugFixing --- .../planner/entities/TaskElement.java | 10 + .../finders/TaskElementFilterEnum.java | 53 +++++ .../TaskElementsMultipleFiltersFinder.java | 202 ++++++++++++++++ .../web/orders/TaskElementPredicate.java | 219 ++++++++++++++++++ .../order/OrderPlanningController.java | 13 +- .../navalplanner-webapp-spring-config.xml | 2 + 6 files changed, 493 insertions(+), 6 deletions(-) create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/web/common/components/finders/TaskElementFilterEnum.java create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/web/common/components/finders/TaskElementsMultipleFiltersFinder.java create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/web/orders/TaskElementPredicate.java diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/TaskElement.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/TaskElement.java index bbf957fac..b1db655a5 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/TaskElement.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/TaskElement.java @@ -684,4 +684,14 @@ public abstract class TaskElement extends BaseEntity { public abstract boolean isTask(); + public List getAllChildren() { + List children = getChildren(); + List result = new ArrayList(); + for (TaskElement child : children) { + result.add(child); + result.addAll(child.getAllChildren()); + } + return result; + } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/components/finders/TaskElementFilterEnum.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/components/finders/TaskElementFilterEnum.java new file mode 100644 index 000000000..21b337b6b --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/components/finders/TaskElementFilterEnum.java @@ -0,0 +1,53 @@ +/* + * This file is part of NavalPlan + * + * Copyright (C) 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 . + */ + +/** + * @author Susana Montes Pedreira + */ +package org.navalplanner.web.common.components.finders; + +import org.navalplanner.business.planner.entities.TaskElement; + +/** + * Different filters for {@link TaskElement}. + * + * @author Manuel Rego Casasnovas + */ +public enum TaskElementFilterEnum implements IFilterEnum { + + Criterion(_("Criterion")), Label(_("Label")); + + /** + * Forces to mark the string as needing translation + */ + private static String _(String string) { + return string; + } + + private String description; + + private TaskElementFilterEnum(String description) { + this.description = description; + } + + public String toString() { + return this.description; + } + +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/components/finders/TaskElementsMultipleFiltersFinder.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/components/finders/TaskElementsMultipleFiltersFinder.java new file mode 100644 index 000000000..ed636a495 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/components/finders/TaskElementsMultipleFiltersFinder.java @@ -0,0 +1,202 @@ +/* + * This file is part of NavalPlan + * + * Copyright (C) 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 . + */ + +package org.navalplanner.web.common.components.finders; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; + +import org.apache.commons.lang.StringUtils; +import org.navalplanner.business.hibernate.notification.PredefinedDatabaseSnapshots; +import org.navalplanner.business.labels.entities.Label; +import org.navalplanner.business.labels.entities.LabelType; +import org.navalplanner.business.planner.entities.TaskElement; +import org.navalplanner.business.resources.entities.Criterion; +import org.navalplanner.business.resources.entities.CriterionType; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Implements all the methods needed to search the criteria to filter the + * {@link TaskElement}. Provides multiples criteria to filter like + * {@link Criterion} and {@link Label}. + * + * @author Manuel Rego Casasnovas + */ +public class TaskElementsMultipleFiltersFinder extends MultipleFiltersFinder { + + @Autowired + private PredefinedDatabaseSnapshots databaseSnapshots; + + protected TaskElementsMultipleFiltersFinder() { + + } + + @Override + public List getFirstTenFilters() { + getListMatching().clear(); + fillWithFirstTenFiltersLabels(); + fillWithFirstTenFiltersCriterions(); + addNoneFilter(); + return getListMatching(); + } + + private List fillWithFirstTenFiltersLabels() { + Map> mapLabels = getLabelsMap(); + Iterator iteratorLabelType = mapLabels.keySet().iterator(); + while (iteratorLabelType.hasNext() && getListMatching().size() < 10) { + LabelType type = iteratorLabelType.next(); + for (int i = 0; getListMatching().size() < 10 + && i < mapLabels.get(type).size(); i++) { + Label label = mapLabels.get(type).get(i); + addLabel(type, label); + } + } + return getListMatching(); + } + + private Map> getLabelsMap() { + return databaseSnapshots.snapshotLabelsMap(); + } + + private List fillWithFirstTenFiltersCriterions() { + SortedMap> mapCriterions = getMapCriterions(); + Iterator iteratorCriterionType = mapCriterions.keySet() + .iterator(); + while (iteratorCriterionType.hasNext() && getListMatching().size() < 10) { + CriterionType type = iteratorCriterionType.next(); + for (int i = 0; getListMatching().size() < 10 + && i < mapCriterions.get(type).size(); i++) { + Criterion criterion = mapCriterions.get(type).get(i); + addCriterion(type, criterion); + } + } + return getListMatching(); + } + + private SortedMap> getMapCriterions() { + return databaseSnapshots.snapshotCriterionsMap(); + } + + @Override + public List getMatching(String filter) { + getListMatching().clear(); + if ((filter != null) && (!filter.isEmpty())) { + filter = StringUtils.deleteWhitespace(filter.toLowerCase()); + searchInCriterionTypes(filter); + searchInLabelTypes(filter); + } + + addNoneFilter(); + return getListMatching(); + } + + private void searchInCriterionTypes(String filter) { + boolean limited = (filter.length() < 3); + for (CriterionType type : getMapCriterions().keySet()) { + String name = StringUtils.deleteWhitespace(type.getName() + .toLowerCase()); + if (name.contains(filter)) { + setFilterPairCriterionType(type, limited); + } else { + searchInCriterions(type, filter); + } + } + } + + private void searchInCriterions(CriterionType type, String filter) { + List list = getMapCriterions().get(type); + if (list == null) { + return; + } + for (Criterion criterion : list) { + String name = StringUtils.deleteWhitespace(criterion.getName() + .toLowerCase()); + if (name.contains(filter)) { + addCriterion(type, criterion); + if ((filter.length() < 3) && (getListMatching().size() > 9)) { + return; + } + } + } + } + + private void setFilterPairCriterionType(CriterionType type, boolean limited) { + List list = getMapCriterions().get(type); + if (list == null) { + return; + } + for (Criterion criterion : list) { + addCriterion(type, criterion); + if ((limited) && (getListMatching().size() > 9)) { + return; + } + } + } + + private void searchInLabelTypes(String filter) { + boolean limited = (filter.length() < 3); + for (LabelType type : getLabelsMap().keySet()) { + String name = StringUtils.deleteWhitespace(type.getName() + .toLowerCase()); + if (name.contains(filter)) { + setFilterPairLabelType(type, limited); + } else { + searchInLabels(type, filter); + } + } + } + + private void searchInLabels(LabelType type, String filter) { + for (Label label : getLabelsMap().get(type)) { + String name = StringUtils.deleteWhitespace(label.getName() + .toLowerCase()); + if (name.contains(filter)) { + addLabel(type, label); + if ((filter.length() < 3) && (getListMatching().size() > 9)) { + return; + } + } + } + } + + private void setFilterPairLabelType(LabelType type, boolean limited) { + for (Label label : getLabelsMap().get(type)) { + addLabel(type, label); + if ((limited) && (getListMatching().size() > 9)) { + return; + } + } + } + + private void addCriterion(CriterionType type, Criterion criterion) { + String pattern = criterion.getName() + " ( " + type.getName() + " )"; + getListMatching().add( + new FilterPair(TaskElementFilterEnum.Criterion, type + .getResource().toLowerCase(), pattern, criterion)); + } + + private void addLabel(LabelType type, Label label) { + String pattern = label.getName() + " ( " + type.getName() + " )"; + getListMatching().add( + new FilterPair(TaskElementFilterEnum.Label, pattern, label)); + } + +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/TaskElementPredicate.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/TaskElementPredicate.java new file mode 100644 index 000000000..113854361 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/TaskElementPredicate.java @@ -0,0 +1,219 @@ +/* + * This file is part of NavalPlan + * + * Copyright (C) 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 . + */ + +package org.navalplanner.web.orders; + +import java.util.Date; +import java.util.List; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.navalplanner.business.labels.entities.Label; +import org.navalplanner.business.planner.entities.GenericResourceAllocation; +import org.navalplanner.business.planner.entities.ResourceAllocation; +import org.navalplanner.business.planner.entities.TaskElement; +import org.navalplanner.business.resources.entities.Criterion; +import org.navalplanner.web.common.components.finders.FilterPair; +import org.navalplanner.web.common.components.finders.TaskElementFilterEnum; +import org.zkoss.ganttz.IPredicate; + +/** + * Checks if {@link TaskElement} matches with the different filters. + * + * @author Manuel Rego Casasnovas + */ +public class TaskElementPredicate implements IPredicate { + + private List filters; + + private Date startDate; + + private Date finishDate; + + private String name; + + private boolean ignoreLabelsInheritance; + + public TaskElementPredicate(List filters, Date startDate, + Date finishDate, String name, boolean ignoreLabelsInheritance) { + this.filters = filters; + this.startDate = startDate; + this.finishDate = finishDate; + this.name = name; + this.ignoreLabelsInheritance = ignoreLabelsInheritance; + } + + @Override + public boolean accepts(Object object) { + final TaskElement taskElement = (TaskElement) object; + return accepts(taskElement) || accepts(taskElement.getAllChildren()); + } + + private boolean accepts(TaskElement taskElement) { + if (taskElement == null) { + return false; + } + if (acceptFilters(taskElement) && acceptFiltersDates(taskElement) + && acceptFilterName(taskElement)) { + return true; + } + return false; + } + + private boolean accepts(List taskElements) { + for (TaskElement taskElement : taskElements) { + if (accepts(taskElement)) { + return true; + } + } + return false; + } + + private boolean acceptFilters(TaskElement taskElement) { + if ((filters == null) || (filters.isEmpty())) { + return true; + } + for (FilterPair filter : filters) { + if (!acceptFilter(filter, taskElement)) { + return false; + } + } + return true; + } + + private boolean acceptFilter(FilterPair filter, TaskElement taskElement) { + switch ((TaskElementFilterEnum) filter.getType()) { + case Criterion: + return acceptCriterion(filter, taskElement); + case Label: + return acceptLabel(filter, taskElement); + } + return false; + } + + private boolean acceptCriterion(FilterPair filter, TaskElement taskElement) { + Criterion filterCriterion = (Criterion) filter.getValue(); + return existCriterionInTaskElementResourceAllocations(filterCriterion, + taskElement); + } + + private boolean existCriterionInTaskElementResourceAllocations( + Criterion filterCriterion, TaskElement taskElement) { + for (ResourceAllocation each : taskElement + .getAllResourceAllocations()) { + if (acceptsCriterionInResourceAllocation(filterCriterion, each)) { + return true; + } + } + return false; + } + + private boolean acceptsCriterionInResourceAllocation( + Criterion filterCriterion, ResourceAllocation resourceAllocation) { + if (resourceAllocation instanceof GenericResourceAllocation) { + Set criteria = ((GenericResourceAllocation) resourceAllocation) + .getCriterions(); + for (Criterion criterion : criteria) { + if (criterion.getId().equals(filterCriterion.getId())) { + return true; + } + } + } + return false; + } + + private boolean acceptLabel(FilterPair filter, TaskElement taskElement) { + Label filterLabel = (Label) filter.getValue(); + return existLabelInTaskElement(filterLabel, taskElement); + } + + private boolean existLabelInTaskElement(Label filterLabel, + TaskElement taskElement) { + Set