/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.core; import java.util.Collection; import java.util.Collections; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.Maps; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.id.ExternalBundleIdentifiable; import com.opengamma.id.ExternalIdBundle; import com.opengamma.id.UniqueIdentifiable; import com.opengamma.id.VersionCorrection; import com.opengamma.util.PoolExecutor; /** * A partial implementation of {@link SourceWithExternalBundle} * * @param <V> the type returned by the source */ public abstract class AbstractSourceWithExternalBundle<V extends UniqueIdentifiable & ExternalBundleIdentifiable> extends AbstractSource<V> implements SourceWithExternalBundle<V> { private static final Logger s_logger = LoggerFactory.getLogger(AbstractSourceWithExternalBundle.class); private static final PoolExecutor.CompletionListener<Void> s_reportExceptions = new PoolExecutor.CompletionListener<Void>() { @Override public void success(final Void result) { s_logger.debug("Asynchronous job completed"); } @Override public void failure(final Throwable error) { s_logger.error("Asynchronous job error: {}", error.getMessage()); s_logger.warn("Caught exception", error); } }; public static <V extends UniqueIdentifiable & ExternalBundleIdentifiable> Map<ExternalIdBundle, Collection<V>> getAllMultiThread(final PoolExecutor executor, final SourceWithExternalBundle<V> source, final Collection<ExternalIdBundle> bundles, final VersionCorrection versionCorrection) { final PoolExecutor.Service<Void> jobs = executor.createService(s_reportExceptions); final Map<ExternalIdBundle, Collection<V>> results = Maps.newHashMapWithExpectedSize(bundles.size()); for (final ExternalIdBundle bundle : bundles) { jobs.execute(new Runnable() { @Override public void run() { final Collection<V> result = source.get(bundle, versionCorrection); if ((result != null) && !result.isEmpty()) { synchronized (results) { results.put(bundle, result); } } } }); } try { s_logger.debug("Joining asynchronous jobs in getAllMultiThread"); jobs.join(); } catch (InterruptedException e) { throw new OpenGammaRuntimeException("Interrupted", e); } s_logger.debug("Returning {} results from getAllMultiThread", results.size()); return results; } public static <V extends UniqueIdentifiable & ExternalBundleIdentifiable> Map<ExternalIdBundle, Collection<V>> getAllSingleThread(final SourceWithExternalBundle<V> source, final Collection<ExternalIdBundle> bundles, final VersionCorrection versionCorrection) { final Map<ExternalIdBundle, Collection<V>> results = Maps.newHashMapWithExpectedSize(bundles.size()); for (ExternalIdBundle bundle : bundles) { final Collection<V> result = source.get(bundle, versionCorrection); if ((result != null) && !result.isEmpty()) { results.put(bundle, result); } } return results; } public static <V extends UniqueIdentifiable & ExternalBundleIdentifiable> Map<ExternalIdBundle, Collection<V>> getAll(final SourceWithExternalBundle<V> source, final Collection<ExternalIdBundle> bundles, final VersionCorrection versionCorrection) { if (bundles.isEmpty()) { return Collections.emptyMap(); } else if (bundles.size() == 1) { final ExternalIdBundle bundle = bundles.iterator().next(); final Collection<V> result = source.get(bundle, versionCorrection); if ((result != null) && !result.isEmpty()) { return Collections.<ExternalIdBundle, Collection<V>>singletonMap(bundle, result); } else { return Collections.emptyMap(); } } final PoolExecutor executor = PoolExecutor.instance(); if (executor != null) { return getAllMultiThread(executor, source, bundles, versionCorrection); } else { return getAllSingleThread(source, bundles, versionCorrection); } } @Override public Map<ExternalIdBundle, Collection<V>> getAll(final Collection<ExternalIdBundle> bundles, final VersionCorrection versionCorrection) { return getAll(this, bundles, versionCorrection); } public static <V extends UniqueIdentifiable & ExternalBundleIdentifiable> Collection<V> get(final SourceWithExternalBundle<V> source, final ExternalIdBundle bundle) { return source.get(bundle, VersionCorrection.LATEST); } @Override public Collection<V> get(ExternalIdBundle bundle) { return get(this, bundle); } public static <V extends UniqueIdentifiable & ExternalBundleIdentifiable> V getSingle(final SourceWithExternalBundle<V> source, final ExternalIdBundle bundle) { return source.getSingle(bundle, VersionCorrection.LATEST); } @Override public V getSingle(ExternalIdBundle bundle) { return getSingle(this, bundle); } public static <V extends UniqueIdentifiable & ExternalBundleIdentifiable> V getSingle(final SourceWithExternalBundle<V> source, final ExternalIdBundle bundle, final VersionCorrection versionCorrection) { Collection<V> results = source.get(bundle, versionCorrection); if ((results == null) || results.isEmpty()) { return null; } return results.iterator().next(); } @Override public V getSingle(ExternalIdBundle bundle, VersionCorrection versionCorrection) { return getSingle(this, bundle, versionCorrection); } public static <V extends UniqueIdentifiable & ExternalBundleIdentifiable> Map<ExternalIdBundle, V> getSingleMultiThread(final PoolExecutor executor, final SourceWithExternalBundle<V> source, final Collection<ExternalIdBundle> bundles, final VersionCorrection versionCorrection) { final PoolExecutor.Service<Void> jobs = executor.createService(s_reportExceptions); final Map<ExternalIdBundle, V> results = Maps.newHashMapWithExpectedSize(bundles.size()); for (final ExternalIdBundle bundle : bundles) { jobs.execute(new Runnable() { @Override public void run() { final V result = source.getSingle(bundle, versionCorrection); if (result != null) { synchronized (results) { results.put(bundle, result); } } } }); } try { s_logger.debug("Joining asynchronous jobs in getSingleMultiThread"); jobs.join(); } catch (InterruptedException e) { throw new OpenGammaRuntimeException("Interrupted", e); } s_logger.debug("Returning {} results from getSingleMultiThread", results.size()); return results; } public static <V extends UniqueIdentifiable & ExternalBundleIdentifiable> Map<ExternalIdBundle, V> getSingleSingleThread(final SourceWithExternalBundle<V> source, final Collection<ExternalIdBundle> bundles, final VersionCorrection versionCorrection) { final Map<ExternalIdBundle, V> results = Maps.newHashMapWithExpectedSize(bundles.size()); for (ExternalIdBundle bundle : bundles) { final V result = source.getSingle(bundle, versionCorrection); if (result != null) { results.put(bundle, result); } } return results; } public static <V extends UniqueIdentifiable & ExternalBundleIdentifiable> Map<ExternalIdBundle, V> getSingle(final SourceWithExternalBundle<V> source, final Collection<ExternalIdBundle> bundles, final VersionCorrection versionCorrection) { if (bundles.isEmpty()) { return Collections.emptyMap(); } else if (bundles.size() == 1) { final ExternalIdBundle bundle = bundles.iterator().next(); final V object = source.getSingle(bundle, versionCorrection); if (object != null) { return Collections.<ExternalIdBundle, V>singletonMap(bundle, object); } else { return Collections.emptyMap(); } } final PoolExecutor executor = PoolExecutor.instance(); if (executor != null) { return getSingleMultiThread(executor, source, bundles, versionCorrection); } else { return getSingleSingleThread(source, bundles, versionCorrection); } } @Override public Map<ExternalIdBundle, V> getSingle(final Collection<ExternalIdBundle> bundles, final VersionCorrection versionCorrection) { return getSingle(this, bundles, versionCorrection); } }