/*
* This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
*
* Copyright 2008-2015 Geosparc nv, http://www.geosparc.com/, Belgium.
*
* The program is available in open source according to the GNU Affero
* General Public License. All contributions in this program are covered
* by the Geomajas Contributors License Agreement. For full licensing
* details, see LICENSE.txt in the project root.
*/
package org.geomajas.gwt2.plugin.wfs.server.dto.query;
import org.geomajas.gwt2.client.map.feature.query.AttributeCriterion;
import org.geomajas.gwt2.client.map.feature.query.BboxCriterion;
import org.geomajas.gwt2.client.map.feature.query.Criterion;
import org.geomajas.gwt2.client.map.feature.query.CriterionVisitor;
import org.geomajas.gwt2.client.map.feature.query.DWithinCriterion;
import org.geomajas.gwt2.client.map.feature.query.ExcludeCriterion;
import org.geomajas.gwt2.client.map.feature.query.FidCriterion;
import org.geomajas.gwt2.client.map.feature.query.FullTextCriterion;
import org.geomajas.gwt2.client.map.feature.query.GeometryCriterion;
import org.geomajas.gwt2.client.map.feature.query.IncludeCriterion;
import org.geomajas.gwt2.client.map.feature.query.LogicalCriterion;
import org.geomajas.gwt2.client.map.feature.query.LogicalCriterion.Operator;
/**
* Simplifies a complex {@link CriterionDto} by simplifying logical expressions, if possible.
*
* @author Jan De Moerloose
*
*/
public class CriterionSimplifier implements CriterionVisitor {
public CriterionDto simplify(CriterionDto criterionDto) {
CriterionContext context = new CriterionContext();
criterionDto.accept(this, context);
return (CriterionDto) context.getCriterion();
}
@Override
public void visit(LogicalCriterion criterion, Object context) {
CriterionContext fc = (CriterionContext) context;
Operator operator = criterion.getOperator();
if (criterion.getChildren().size() == 0) {
fc.setCriterion(CriterionDto.EXCLUDE);
} else {
Criterion simple = null;
for (Criterion child : criterion.getChildren()) {
child.accept(this, fc);
if (fc.getCriterion().equals(CriterionDto.EXCLUDE) && operator == Operator.AND) {
simple = CriterionDto.EXCLUDE;
break;
} else if (fc.getCriterion().equals(CriterionDto.INCLUDE) && operator == Operator.OR) {
simple = CriterionDto.INCLUDE;
break;
} else if (simple == null) {
simple = fc.getCriterion();
} else if (simple.equals(CriterionDto.INCLUDE) && operator == Operator.AND) {
simple = fc.getCriterion();
} else if (simple.equals(CriterionDto.EXCLUDE) && operator == Operator.OR) {
simple = fc.getCriterion();
} else {
LogicalCriterionDto tmp = new LogicalCriterionDto(criterion.getOperator());
tmp.getChildren().add(simple);
tmp.getChildren().add(fc.getCriterion());
simple = tmp;
}
}
fc.setCriterion(simple);
}
}
@Override
public void visit(AttributeCriterion<?> criterion, Object context) {
CriterionContext fc = (CriterionContext) context;
fc.setCriterion(criterion);
}
@Override
public void visit(GeometryCriterion criterion, Object context) {
CriterionContext fc = (CriterionContext) context;
fc.setCriterion(criterion);
}
@Override
public void visit(BboxCriterion criterion, Object context) {
CriterionContext fc = (CriterionContext) context;
fc.setCriterion(criterion);
}
@Override
public void visit(FidCriterion criterion, Object context) {
CriterionContext fc = (CriterionContext) context;
fc.setCriterion(criterion);
}
@Override
public void visit(DWithinCriterion criterion, Object context) {
CriterionContext fc = (CriterionContext) context;
fc.setCriterion(criterion);
}
@Override
public void visit(FullTextCriterion criterion, Object context) {
CriterionContext fc = (CriterionContext) context;
fc.setCriterion(criterion);
}
@Override
public void visit(IncludeCriterion criterion, Object context) {
CriterionContext fc = (CriterionContext) context;
fc.setCriterion(criterion);
}
@Override
public void visit(ExcludeCriterion criterion, Object context) {
CriterionContext fc = (CriterionContext) context;
fc.setCriterion(criterion);
}
@Override
public void visit(Criterion criterionDto, Object context) {
CriterionContext fc = (CriterionContext) context;
fc.setCriterion(criterionDto);
}
/**
* Context class to pass along the visitor.
*
* @author Jan De Moerloose
*
*/
protected class CriterionContext {
private Criterion criterion;
public void setCriterion(Criterion criterion) {
this.criterion = criterion;
}
public Criterion getCriterion() {
return criterion;
}
}
}