package org.softlang.company.features.template; import org.softlang.company.model.*; /** * Provide the template method "reduce" for querying values from companies. * The "reduce" method is configured with "visit" methods for all possible types. * There are also abstract methods for the result domain: "zero" and "append". */ public abstract class Reducer<R> { public R visit(Company c) { return zero(); } public R visit(Department d) { return zero(); } public R visit(Employee e) { return zero(); } /** * @return the default (the algebraic unit) for the result type. */ public abstract R zero(); /** * Combine two query results. */ public abstract R append(R x, R y); /** * Provide the template method "reduce" for querying values from companies. */ public final R reduce(Company c) { R result = visit(c); for (Department d : c.getDepts()) result = append(result,reduce(d)); return result; } private R reduce(Department d) { R result = visit(d); result = append(result,reduce(d.getManager())); for (Department s : d.getSubdepts()) result = append(result,reduce(s)); for (Employee e : d.getEmployees()) result = append(result,reduce(e)); return result; } private R reduce(Employee e) { return visit(e); } }