com.opengamma.engine.function.resolver.SimpleResolutionRuleTransform.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.engine.function.resolver.SimpleResolutionRuleTransform.java

Source

/**
 * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
 * 
 * Please see distribution for license.
 */
package com.opengamma.engine.function.resolver;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.engine.function.FunctionParameters;
import com.opengamma.engine.function.ParameterizedFunction;

/**
 * Resolution rule transform that matches on the short name of the function.
 */
public class SimpleResolutionRuleTransform implements ResolutionRuleTransform {

    /** Logger. */
    private static final Logger s_logger = LoggerFactory.getLogger(SimpleResolutionRuleTransform.class);

    /**
     * The function transformations.
     */
    private final Map<String, Action> _functionTransformations = new HashMap<String, Action>();

    /**
     * Gets the map of registered transformations.
     * <p>
     * The map is keyed by short function name, with the value being the the action to be applied.
     * If multiple actions are applied, the function will be advertised by multiple new rules in
     * place of the original. If a function is omitted from the set, the original rule is preserved.
     * 
     * @return the set of transformations, not null
     */
    public Map<String, Action> getFunctionTransformations() {
        return Collections.unmodifiableMap(_functionTransformations);
    }

    //-------------------------------------------------------------------------
    /**
     * Suppress any rules using the given function name.
     * 
     * @param shortFunctionName  the function to suppress, not null
     */
    public void suppressRule(final String shortFunctionName) {
        registerAction(shortFunctionName, DontUse.INSTANCE);
    }

    /**
     * Adjust the rules using the given function name.
     * 
     * @param shortFunctionName  the function to adjust, not null
     * @param parameters  the function parameters, null to use the original rule default
     * @param priorityAdjustment  the priority shift, null to use the original rule default
     * @param computationTargetFilter  the computation target filter, null to use the original rule default
     */
    public void adjustRule(final String shortFunctionName, final FunctionParameters parameters,
            final ComputationTargetFilter computationTargetFilter, final Integer priorityAdjustment) {
        registerAction(shortFunctionName, new Adjust(parameters, computationTargetFilter, priorityAdjustment));
    }

    private void registerAction(final String shortFunctionName, final Action action) {
        final Action existing = _functionTransformations.get(shortFunctionName);
        if (existing == null) {
            _functionTransformations.put(shortFunctionName, action);
        } else {
            _functionTransformations.put(shortFunctionName, existing.with(action));
        }
    }

    //-------------------------------------------------------------------------
    @Override
    public Collection<ResolutionRule> transform(final Collection<ResolutionRule> rules) {
        final Collection<ResolutionRule> result = Lists.newArrayListWithCapacity(rules.size());
        for (ResolutionRule rule : rules) {
            final String function = rule.getParameterizedFunction().getFunction().getFunctionDefinition()
                    .getShortName();
            final Action action = _functionTransformations.get(function);
            if (action == null) {
                s_logger.debug("Function {} has no transformation rules", function);
                result.add(rule);
            } else {
                s_logger.debug("Applying transformation rules for function {}", function);
                action.apply(rule, result);
            }
        }
        return result;
    }

    //-------------------------------------------------------------------------
    @Override
    public boolean equals(final Object obj) {
        if (obj == this) {
            return true;
        }
        if (obj instanceof SimpleResolutionRuleTransform) {
            final SimpleResolutionRuleTransform other = (SimpleResolutionRuleTransform) obj;
            return _functionTransformations.equals(other._functionTransformations);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return 0; // not intended to be hashed
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + _functionTransformations;
    }

    //-------------------------------------------------------------------------
    /**
     * Describes an action as part of a rule's transformation. 
     */
    public abstract static class Action {

        protected abstract Action with(Action other);

        protected abstract void apply(final ResolutionRule originalRule, final Collection<ResolutionRule> output);
    }

    //-------------------------------------------------------------------------
    /**
     * Describes a rule that should be suppressed.
     */
    public static final class DontUse extends Action {

        private static final Action INSTANCE = new DontUse();

        private DontUse() {
        }

        @Override
        protected Action with(final Action other) {
            throw new OpenGammaRuntimeException("Resolution rule already marked as \"Don't use\"");
        }

        @Override
        protected void apply(final ResolutionRule originalRule, final Collection<ResolutionRule> output) {
            s_logger.debug("Discarding {}", originalRule);
        }

        @Override
        public boolean equals(final Object o) {
            return (o == this) || (o instanceof DontUse);
        }

        @Override
        public int hashCode() {
            // Not destined for hash tables
            return 0;
        }

        @Override
        public String toString() {
            return "Don't use";
        }
    }

    //-------------------------------------------------------------------------
    /**
     * Describes a rule that should be adjusted.
     */
    public static final class Adjust extends Action {

        private Integer _priorityAdjustment;
        private FunctionParameters _parameters;
        private ComputationTargetFilter _computationTargetFilter;

        private Adjust(final FunctionParameters parameters, final ComputationTargetFilter filter,
                final Integer priorityAdjustment) {
            _priorityAdjustment = priorityAdjustment;
            _parameters = parameters;
            _computationTargetFilter = filter;
        }

        public Integer getPriorityAdjustment() {
            return _priorityAdjustment;
        }

        public FunctionParameters getParameters() {
            return _parameters;
        }

        public ComputationTargetFilter getComputationTargetFilter() {
            return _computationTargetFilter;
        }

        @Override
        protected Action with(final Action other) {
            return new MultipleAdjust().with(this).with(other);
        }

        @Override
        protected void apply(final ResolutionRule originalRule, final Collection<ResolutionRule> output) {
            ParameterizedFunction function = originalRule.getParameterizedFunction();
            if (_parameters != null) {
                function = new ParameterizedFunction(originalRule.getParameterizedFunction().getFunction(),
                        _parameters);
            }
            final ComputationTargetFilter computationTargetFilter;
            if (_computationTargetFilter != null) {
                computationTargetFilter = _computationTargetFilter;
            } else {
                computationTargetFilter = originalRule.getComputationTargetFilter();
            }
            int priority = originalRule.getPriority();
            if (_priorityAdjustment != null) {
                priority += _priorityAdjustment;
            }
            final ResolutionRule replacement = new ResolutionRule(function, computationTargetFilter, priority);
            s_logger.debug("Publishing {} in place of {}", replacement, originalRule);
            output.add(replacement);
        }

        @Override
        public boolean equals(final Object o) {
            if (o == this) {
                return true;
            }
            if (!(o instanceof Adjust)) {
                return false;
            }
            final Adjust other = (Adjust) o;
            return ObjectUtils.equals(_parameters, other._parameters)
                    && ObjectUtils.equals(_computationTargetFilter, other._computationTargetFilter)
                    && ObjectUtils.equals(_priorityAdjustment, other._priorityAdjustment);
        }

        @Override
        public int hashCode() {
            // Not destined for hash tables
            return 0;
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("Adjust[");
            boolean comma = false;
            if (_parameters != null) {
                sb.append("Parameters=").append(_parameters);
                comma = true;
            }
            if (_computationTargetFilter != null) {
                if (comma) {
                    sb.append(',');
                } else {
                    comma = true;
                }
                sb.append("ComputationTargetFilter=").append(_computationTargetFilter);
            }
            if (_priorityAdjustment != null) {
                if (comma) {
                    sb.append(',');
                }
                sb.append("PriorityAdjustment=").append(_priorityAdjustment);
            }
            return sb.append(']').toString();
        }
    }

    //-------------------------------------------------------------------------
    /**
     * Describes a set of adjustments for a single rule.
     */
    public static final class MultipleAdjust extends Action {

        private final List<Adjust> _adjusts = new ArrayList<Adjust>();

        private MultipleAdjust() {
        }

        public List<Adjust> getAdjusts() {
            return Collections.unmodifiableList(_adjusts);
        }

        @Override
        protected Action with(final Action other) {
            if (other instanceof DontUse) {
                throw new OpenGammaRuntimeException("Attempting to mark composite rule as \"Don't Use\"");
            }
            // other can only be Adjust at this point
            _adjusts.add((Adjust) other);
            return this;
        }

        @Override
        protected void apply(final ResolutionRule originalRule, final Collection<ResolutionRule> output) {
            for (Action adjust : _adjusts) {
                adjust.apply(originalRule, output);
            }
        }

        @Override
        public boolean equals(final Object o) {
            if (o == this) {
                return true;
            }
            if (!(o instanceof MultipleAdjust)) {
                return false;
            }
            final MultipleAdjust other = (MultipleAdjust) o;
            if (_adjusts.size() != other._adjusts.size()) {
                return false;
            }
            for (Action adjust : _adjusts) {
                if (!other._adjusts.contains(adjust)) {
                    return false;
                }
            }
            return true;
        }

        @Override
        public int hashCode() {
            // Not destined for hash tables
            return 0;
        }

        @Override
        public String toString() {
            return "Multiple" + _adjusts;
        }
    }

}