/*
* 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.resources.entities;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.joda.time.LocalDate;
/**
* Compounds some {@link ICriterion} into one <br />
* @author Óscar González Fernández <ogonzalez@igalia.com>
*/
public class CriterionCompounder {
public static CriterionCompounder build() {
return new CriterionCompounder();
}
public static CriterionCompounder buildAnd(
Collection<? extends ICriterion> criterions) {
CriterionCompounder compounder = new CriterionCompounder();
for (ICriterion criterion : criterions) {
compounder = compounder.and(criterion);
}
return compounder;
}
public static CriterionCompounder atom(ICriterion criterion) {
return build().and(criterion);
}
public static ICriterion not(ICriterion criterion) {
return new Negated(criterion);
}
public static ICriterion not(CriterionCompounder compounder) {
return not(compounder.getResult());
}
private static class Negated implements ICriterion {
private final ICriterion criterion;
private Negated(ICriterion criterion) {
this.criterion = criterion;
}
@Override
public boolean isSatisfiedBy(Resource resource) {
return !criterion.isSatisfiedBy(resource);
}
@Override
public boolean isSatisfiedBy(Resource resource, LocalDate start, LocalDate end) {
return !criterion.isSatisfiedBy(resource, start, end);
}
@Override
public boolean isSatisfiedBy(Resource resource, LocalDate atThisDate) {
return !criterion.isSatisfiedBy(resource, atThisDate);
}
}
private static class OrClause implements ICriterion {
private Collection<? extends ICriterion> criterions;
public OrClause(Collection<? extends ICriterion> atoms) {
this.criterions = atoms;
}
@Override
public boolean isSatisfiedBy(Resource resource) {
for (ICriterion criterion : criterions) {
if (criterion.isSatisfiedBy(resource)) {
return true;
}
}
return false;
}
public boolean isSatisfiedBy(Resource resource, LocalDate start, LocalDate end) {
for (ICriterion criterion : criterions) {
if (criterion.isSatisfiedBy(resource, start, end)) {
return true;
}
}
return false;
}
@Override
public boolean isSatisfiedBy(Resource resource, LocalDate atThisDate) {
for (ICriterion criterion : criterions) {
if (criterion.isSatisfiedBy(resource, atThisDate)) {
return true;
}
}
return false;
}
}
private static class AndClause implements ICriterion {
private List<ICriterion> criterions;
AndClause() {
this.criterions = new LinkedList<ICriterion>();
}
private AndClause(List<ICriterion> atoms) {
this.criterions = atoms;
}
public AndClause and(ICriterion criterion) {
return new AndClause(join(criterions, criterion));
}
private static List<ICriterion> join(List<ICriterion> previous,
ICriterion criterion) {
LinkedList<ICriterion> result = new LinkedList<ICriterion>(previous);
result.add(criterion);
return result;
}
@Override
public boolean isSatisfiedBy(Resource resource) {
for (ICriterion criterion : criterions) {
if (!criterion.isSatisfiedBy(resource)) {
return false;
}
}
return true;
}
@Override
public boolean isSatisfiedBy(Resource resource, LocalDate start, LocalDate end) {
for (ICriterion criterion : criterions) {
if (!criterion.isSatisfiedBy(resource, start, end)) {
return false;
}
}
return true;
}
@Override
public boolean isSatisfiedBy(Resource resource, LocalDate atThisDate) {
for (ICriterion criterion : criterions) {
if (!criterion.isSatisfiedBy(resource, atThisDate)) {
return false;
}
}
return true;
}
}
private final List<AndClause> clauses;
private CriterionCompounder() {
this(new AndClause());
}
private CriterionCompounder(AndClause andClause) {
clauses = new ArrayList<AndClause>();
clauses.add(andClause);
}
private CriterionCompounder(List<AndClause> clauses) {
this.clauses = clauses;
}
private AndClause getLast() {
return clauses.get(clauses.size() - 1);
}
private List<AndClause> updateLast(AndClause clause) {
ArrayList<AndClause> arrayList = new ArrayList<AndClause>(clauses);
arrayList.set(arrayList.size() - 1, clause);
return arrayList;
}
public CriterionCompounder and(CriterionCompounder compounder) {
return and(compounder.getResult());
}
public CriterionCompounder and(ICriterion criterion) {
return new CriterionCompounder(updateLast(getLast().and(criterion)));
}
public CriterionCompounder or(CriterionCompounder compounder) {
return or(compounder.getResult());
}
public CriterionCompounder or(ICriterion criterion) {
ArrayList<AndClause> copied = new ArrayList<AndClause>(clauses);
copied.add(new AndClause());
return new CriterionCompounder(copied).and(criterion);
}
public ICriterion getResult() {
return new OrClause(clauses);
}
}