package org.softlang.company.features.template;
import org.softlang.company.model.company.*;
import org.softlang.company.features.util.Monoid;
import org.softlang.company.features.visitor.ReturningVisitor;
/**
* Provide a template for reduction over company objects.
* Reduction is parametric in a monoid.
* The template is customized by overriding visitor methods.
* By default the visit methods return the unit of the monoid.
* The visit methods do not traverse into the objects.
* Instead, object traversal is taken care of by the template method.
*/
public abstract class Reducer<R> implements ReturningVisitor<R> {
private Monoid<R> monoid;
protected Reducer(Monoid<R> m) { this.monoid = m; }
public R visit(Company c) {
return monoid.unit();
}
public R visit(Department d) {
return monoid.unit();
}
public R visit(Employee e) {
return monoid.unit();
}
public final R reduce(Component c) {
//
// Use an inner visitor to organize traversal.
//
final ReturningVisitor<R> that = this;
return c.accept(
new ReturningVisitor<R>() {
public R visit(Company c) {
R result = that.visit(c);
for (Subunit u : c.subunits())
result = monoid.append(result, u.accept(this));
return result;
}
public R visit(Department d) {
R result = that.visit(d);
for (Subunit u : d.subunits())
result = monoid.append(result, u.accept(this));
return result;
}
public R visit(Employee e) {
return that.visit(e);
}
});
}
}