/** * 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.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.threeten.bp.Instant; import com.opengamma.engine.view.ViewProcessor; import com.opengamma.util.ArgumentChecker; /** * An in-memory implementation of {@link FunctionRepository}. This can either be used as-is through a factory which scans available functions, or it can be used as a cache on top of a more costly * function repository. */ public class InMemoryFunctionRepository implements FunctionRepository { private static final Logger s_logger = LoggerFactory.getLogger(InMemoryFunctionRepository.class); private final Map<String, FunctionDefinition> _functions = new HashMap<String, FunctionDefinition>(); private final AtomicInteger _nextIdentifier = new AtomicInteger(); public InMemoryFunctionRepository() { } private static final class IdentifiedFunction implements FunctionDefinition { private final FunctionDefinition _underlying; private final String _id; public IdentifiedFunction(final FunctionDefinition underlying, final String id) { _underlying = underlying; _id = id; } @Override public void init(final FunctionCompilationContext context) { _underlying.init(context); } @Override public CompiledFunctionDefinition compile(final FunctionCompilationContext context, final Instant atInstant) { return _underlying.compile(context, atInstant); } @Override public String getUniqueId() { return _id; } @Override public String getShortName() { return _underlying.getShortName(); } @Override public FunctionParameters getDefaultParameters() { return _underlying.getDefaultParameters(); } } private String createId(final String shortName) { String id; do { id = new StringBuilder().append(_nextIdentifier.getAndIncrement()).append(" (").append(shortName).append(")").toString(); } while (_functions.containsKey(id)); return id; } public synchronized void addFunction(FunctionDefinition function) { ArgumentChecker.notNull(function, "Function definition"); if (function.getUniqueId() == null) { if (function instanceof AbstractFunction) { ((AbstractFunction) function).setUniqueId(createId(function.getShortName())); } else { function = new IdentifiedFunction(function, createId(function.getShortName())); } } else if (_functions.containsKey(function.getUniqueId())) { function = new IdentifiedFunction(function, createId(function.getShortName())); } _functions.put(function.getUniqueId(), function); } public synchronized void replaceFunction(String functionIdentifier, FunctionDefinition function) { ArgumentChecker.notNull(functionIdentifier, "functionIdentifier"); ArgumentChecker.notNull(function, "function"); _functions.remove(functionIdentifier); addFunction(function); } @Override public Collection<FunctionDefinition> getAllFunctions() { return Collections.unmodifiableCollection(_functions.values()); } @Override public FunctionDefinition getFunction(final String uniqueId) { return _functions.get(uniqueId); } /** * This method is primarily useful for testing, as otherwise it will be done explicitly by the {@link ViewProcessor} on startup. * * @param compilationContext The context to provide to each function. */ public void initFunctions(FunctionCompilationContext compilationContext) { compilationContext.setFunctionReinitializer(new DummyFunctionReinitializer()); for (FunctionDefinition function : _functions.values()) { try { function.init(compilationContext); } catch (Throwable t) { s_logger.warn("Couldn't initialise function {}", function); s_logger.debug("Caught exception", t); } } compilationContext.setFunctionReinitializer(null); } }