/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.function; import java.util.Collections; import java.util.Map; import java.util.Set; import org.threeten.bp.Instant; import org.threeten.bp.ZonedDateTime; import com.opengamma.engine.ComputationTarget; import com.opengamma.engine.value.ValueProperties; import com.opengamma.engine.value.ValuePropertyNames; import com.opengamma.engine.value.ValueRequirement; import com.opengamma.engine.value.ValueSpecification; import com.opengamma.util.PublicSPI; /** * The base class from which most {@link FunctionDefinition} implementations should inherit. * * @author kirk */ @PublicSPI public abstract class AbstractFunction implements FunctionDefinition { /** * The base class from which most {@link CompiledFunctionDefinition} implementations returned by a {@link AbstractFunction} derived class should inherit. */ protected abstract class AbstractCompiledFunction implements CompiledFunctionDefinition { private Instant _earliestInvocationTime; private Instant _latestInvocationTime; protected AbstractCompiledFunction() { } /** * Creates an instance. * * @param earliestInvocation earliest time this metadata and invoker are valid, null to indicate no lower validity bound * @param latestInvocation latest time this metadata and invoker are valid, null to indicate no upper validity bound */ protected AbstractCompiledFunction(final Instant earliestInvocation, final Instant latestInvocation) { setEarliestInvocationTime(earliestInvocation); setLatestInvocationTime(latestInvocation); } @Override public final FunctionDefinition getFunctionDefinition() { return AbstractFunction.this; } /** * Default implementation always returns true - the function is applicable. Overload this if there is a cheap test that should suppress the call to {@link #getResults}. * * @param context The compilation context with view-specific parameters and configurations. * @param target the Target for which capability is to be tests * @return always true */ @Override public boolean canApplyTo(final FunctionCompilationContext context, final ComputationTarget target) { return true; } /** * Default implementation returns the same results as {@link #getResults (FunctionCompilationContext, ComputationTarget)}. * * @param context The compilation context with view-specific parameters and configurations. * @param target The target for which calculation is desired. * @param inputs The resolved inputs to the function. * @return the same results as {@link #getResults (FunctionCompilationContext, ComputationTarget)} */ @Override public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target, final Map<ValueSpecification, ValueRequirement> inputs) { return getResults(context, target); } @Override public Set<ValueRequirement> getAdditionalRequirements(final FunctionCompilationContext context, final ComputationTarget target, final Set<ValueSpecification> inputs, final Set<ValueSpecification> outputs) { return getAdditionalRequirementsImpl(context, target, inputs, outputs); } /** * Sets the earliest time that this metadata and invoker will be valid for. * * @param timestamp the earliest time, null to indicate no lower validity bound */ public void setEarliestInvocationTime(final Instant timestamp) { _earliestInvocationTime = timestamp; } /** * Sets the latest time that this metadata and invoker will be valid for. * * @param timestamp the latest time, null to indicate no upper validity bound */ public void setLatestInvocationTime(final Instant timestamp) { _latestInvocationTime = timestamp; } @Override public final Instant getEarliestInvocationTime() { return _earliestInvocationTime; } @Override public final Instant getLatestInvocationTime() { return _latestInvocationTime; } /** * Returns false indicating the requirements to the function must be produced within the dependency graph. * * @return always false */ @Override public boolean canHandleMissingRequirements() { return false; } } /** * Extension to {@link AbstractCompiledFunction} that also implements the {@link FunctionInvoker} interface for functions that can be invoked directly at the local node. */ protected abstract class AbstractInvokingCompiledFunction extends AbstractCompiledFunction implements FunctionInvoker { protected AbstractInvokingCompiledFunction() { super(); } /** * Creates an instance. * * @param earliestInvocation earliest time this metadata and invoker are valid, null to indicate no lower validity bound * @param latestInvocation latest time this metadata and invoker are valid, null to indicate no upper validity bound */ protected AbstractInvokingCompiledFunction(final Instant earliestInvocation, final Instant latestInvocation) { super(earliestInvocation, latestInvocation); } /** * Creates an instance. * * @param earliestInvocation earliest time this metadata and invoker are valid, null to indicate no lower validity bound * @param latestInvocation latest time this metadata and invoker are valid, null to indicate no upper validity bound */ protected AbstractInvokingCompiledFunction(final ZonedDateTime earliestInvocation, final ZonedDateTime latestInvocation) { super(earliestInvocation.toInstant(), latestInvocation.toInstant()); } /** * Returns this instance. * * @return this instance */ @Override public final FunctionInvoker getFunctionInvoker() { return this; } @Override public boolean canHandleMissingInputs() { return false; } } //------------------------------------------------------------------------- /** * The unique identifier of the function. */ private String _uniqueId; @Override public String getUniqueId() { return _uniqueId; } /** * Sets the unique identifier for the function. Once set, the identifier cannot be changed. * * @param uniqueId the unique identifier to set */ public void setUniqueId(final String uniqueId) { if (_uniqueId != null) { throw new IllegalStateException("Function unique ID already set"); } _uniqueId = uniqueId; } @Override public String getShortName() { // Note: don't use simple name as some are inner classes called "Impl" or similarly unhelpful final String s = getClass().getName(); return s.substring(s.lastIndexOf('.') + 1); } //------------------------------------------------------------------------- /** * Default implementation performs no initialization action. * * @param context the function compilation context * @deprecated See [PLAT-2240]. Sub-classes should avoid overriding this function and use {@code compile} instead. */ @Deprecated @Override public void init(final FunctionCompilationContext context) { } /** * Default implementation of {@link CompiledFunctionDefinition#getAdditionalRequirements (FunctionCompilationContext, ComputationTarget, Set<ValueSpecification>)}. * * @param context the function compilation context * @param target the computation target * @param inputs the resolved inputs * @param outputs the resolved outputs * @return the empty set indicating no additional data requirements */ protected static Set<ValueRequirement> getAdditionalRequirementsImpl(final FunctionCompilationContext context, final ComputationTarget target, final Set<ValueSpecification> inputs, final Set<ValueSpecification> outputs) { return Collections.emptySet(); } /** * Creates a value property builder populated with the function identifier and otherwise empty. * * @return the builder */ protected ValueProperties.Builder createValueProperties() { return ValueProperties.with(ValuePropertyNames.FUNCTION, getUniqueId()); } /** * Default implementation indicates no parameters. * * @return an {@link EmptyFunctionParameters} instance */ @Override public FunctionParameters getDefaultParameters() { return EmptyFunctionParameters.INSTANCE; } /** * Extension to {@link AbstractFunction} that does not require time based compilation. */ public abstract static class NonCompiled extends AbstractFunction implements CompiledFunctionDefinition { @Override public final FunctionDefinition getFunctionDefinition() { return this; } @Override public Set<ValueRequirement> getAdditionalRequirements(final FunctionCompilationContext context, final ComputationTarget target, final Set<ValueSpecification> inputs, final Set<ValueSpecification> outputs) { return getAdditionalRequirementsImpl(context, target, inputs, outputs); } /** * Returns this instance - there is no compile time state. * * @param context the function compilation context * @param atInstant the compilation time * @return this instance */ @Override public final CompiledFunctionDefinition compile(final FunctionCompilationContext context, final Instant atInstant) { return this; } /** * Default implementation always returns true - the function is applicable. Overload this if there is a cheap test that should suppress the call to {@link #getResults}. * * @param context The compilation context with view-specific parameters and configurations. * @param target the Target for which capability is to be tests * @return always true */ @Override public boolean canApplyTo(final FunctionCompilationContext context, final ComputationTarget target) { return true; } /** * Default implementation returns the same results as {@link #getResults (FunctionCompilationContext, ComputationTarget)}. * * @param context The compilation context with view-specific parameters and configurations. * @param target The target for which calculation is desired. * @param inputs The resolved inputs to the function. * @return the same results as {@link #getResults (FunctionCompilationContext, ComputationTarget)} */ @Override public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target, final Map<ValueSpecification, ValueRequirement> inputs) { return getResults(context, target); } /** * Returns null indicating always valid. * * @return null always */ @Override public final Instant getEarliestInvocationTime() { return null; } /** * Returns null indicating always valid. * * @return null always */ @Override public final Instant getLatestInvocationTime() { return null; } /** * Returns false indicating the requirements to the function must be produced within the dependency graph. * * @return always false */ @Override public boolean canHandleMissingRequirements() { return false; } } /** * Extension to {@link AbstractFunction} that does not require time based compilation and may invoke the underlying function. */ public abstract static class NonCompiledInvoker extends NonCompiled implements FunctionInvoker { /** * Returns this instance. * * @return this instance */ @Override public final FunctionInvoker getFunctionInvoker() { return this; } @Override public boolean canHandleMissingInputs() { return false; } } }