/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.depgraph; import com.opengamma.engine.ComputationTargetSpecification; import com.opengamma.engine.function.CompiledFunctionDefinition; import com.opengamma.engine.target.ComputationTargetType; import com.opengamma.engine.target.ComputationTargetTypeMap; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.function.BinaryOperator; /** * Default implementation of {@link ComputationTargetCollapser} that allows delegate instances to be registered for known target types. */ public class DefaultComputationTargetCollapser implements ComputationTargetCollapser { private static final class ChainedCollapser implements ComputationTargetCollapser { private final ComputationTargetCollapser _first; private final ComputationTargetCollapser _second; public ChainedCollapser(final ComputationTargetCollapser first, final ComputationTargetCollapser second) { _first = first; _second = second; } @Override public boolean canApplyTo(final ComputationTargetSpecification target) { return _first.canApplyTo(target) || _second.canApplyTo(target); } @Override public ComputationTargetSpecification collapse(final CompiledFunctionDefinition function, final ComputationTargetSpecification a, final ComputationTargetSpecification b) { ComputationTargetSpecification result = _first.collapse(function, a, b); if (result == null) { result = _second.collapse(function, a, b); } return result; } } private final ComputationTargetTypeMap<ComputationTargetCollapser> _collapsers = new ComputationTargetTypeMap<ComputationTargetCollapser>( new BinaryOperator<ComputationTargetCollapser>() { @Override public ComputationTargetCollapser apply(ComputationTargetCollapser a, ComputationTargetCollapser b) { return new ChainedCollapser(a, b); } }); /** * Creates a new instance with no underlying collapsers. Unless one or more collapser instances are added to it by {@link #addCollapser}, {@link #canApplyTo} will always return false. */ public DefaultComputationTargetCollapser() { } public void addCollapser(final ComputationTargetType type, final ComputationTargetCollapser collapser) { ArgumentChecker.notNull(type, "type"); ArgumentChecker.notNull(collapser, "collapser"); _collapsers.put(type, collapser); } protected ComputationTargetCollapser getCollapser(final ComputationTargetType type) { return _collapsers.get(type); } // ComputationTargetCollapser @Override public boolean canApplyTo(final ComputationTargetSpecification target) { final ComputationTargetCollapser collapser = getCollapser(target.getType()); if (collapser != null) { return collapser.canApplyTo(target); } else { return false; } } @Override public ComputationTargetSpecification collapse(final CompiledFunctionDefinition function, final ComputationTargetSpecification a, final ComputationTargetSpecification b) { // A and B are the same type, and the type must have been matched for canApplyTo to return true return getCollapser(a.getType()).collapse(function, a, b); } }