/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.marketdata.availability; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.List; import com.opengamma.engine.ComputationTargetSpecification; import com.opengamma.engine.target.ComputationTargetType; import com.opengamma.engine.value.ValueRequirement; import com.opengamma.engine.value.ValueSpecification; import com.opengamma.id.ExternalBundleIdentifiable; import com.opengamma.id.ExternalId; import com.opengamma.id.ExternalIdBundle; import com.opengamma.id.ExternalIdentifiable; import com.opengamma.id.UniqueId; import com.opengamma.id.UniqueIdentifiable; /** * A partial implementation of {@link MarketDataAvailabilityFilter}. */ public abstract class AbstractMarketDataAvailabilityFilter implements MarketDataAvailabilityFilter { /** * Tests the availability of an item that can be referenced by external identifier. * <p> * The default implementation here returns false. * * @param targetSpec the target specification as passed to {@link MarketDataAvailabilityProvider#getAvailability}, possibly null * @param identifier the external identifier of the target object, not null * @param desiredValue the requested value to test and resolve, not null * @return true if the value is available, false otherwise */ protected boolean isAvailable(final ComputationTargetSpecification targetSpec, final ExternalId identifier, final ValueRequirement desiredValue) { return false; } protected ValueSpecification getAvailability(final ComputationTargetSpecification targetSpec, final ExternalId identifier, final ValueRequirement desiredValue, final AbstractMarketDataAvailabilityProvider underlying) { if (isAvailable(targetSpec, identifier, desiredValue)) { return underlying.getAvailability(targetSpec, identifier, desiredValue); } else { return null; } } /** * Tests the availability of an item that can be referenced by one or more external identifiers. * * @param targetSpec the target specification as passed to {@link MarketDataAvailabilityProvider#getAvailability}, possibly null * @param identifiers the external identifiers of the target object, not null * @param desiredValue the requested value to test and resolve, not null * @return true if the value is available, false otherwise */ protected final boolean isAvailable(final ComputationTargetSpecification targetSpec, final ExternalIdBundle identifiers, final ValueRequirement desiredValue) { for (final ExternalId identifier : identifiers) { if (isAvailable(targetSpec, identifier, desiredValue)) { return true; } } return false; } protected ValueSpecification getAvailability(final ComputationTargetSpecification targetSpec, final ExternalIdBundle identifiers, final ValueRequirement desiredValue, final AbstractMarketDataAvailabilityProvider underlying) { List<ExternalId> acceptable = null; for (final ExternalId identifier : identifiers) { if (isAvailable(targetSpec, identifier, desiredValue)) { if (acceptable == null) { acceptable = new ArrayList<ExternalId>(); } acceptable.add(identifier); } } if (acceptable != null) { if (acceptable.size() > 1) { return underlying.getAvailability(targetSpec, ExternalIdBundle.of(acceptable), desiredValue); } else { return underlying.getAvailability(targetSpec, acceptable.get(0), desiredValue); } } else { return null; } } /** * Tests the availability of an item that can only be referenced by unique identifier * <p> * The default implementation here returns false. * * @param targetSpec the target specification as passed to {@link MarketDataAvailabilityProvider#getAvailability}, possibly null * @param identifier the unique identifier of the target object, null only if {@code targetSpec} is {@link ComputationTargetType#NULL} * @param desiredValue the requested value to test and resolve, not null * @return true if the value is available, false otherwise */ protected boolean isAvailable(final ComputationTargetSpecification targetSpec, final UniqueId identifier, final ValueRequirement desiredValue) { return false; } protected ValueSpecification getAvailability(final ComputationTargetSpecification targetSpec, final UniqueId identifier, final ValueRequirement desiredValue, final AbstractMarketDataAvailabilityProvider underlying) { if (isAvailable(targetSpec, identifier, desiredValue)) { return underlying.getAvailability(targetSpec, identifier, desiredValue); } else { return null; } } /** * Tests the availability of the null target. * <p> * The default implementation here calls the {@link #isAvailable(ComputationTargetSpecification,UniqueId,ValueRequirement)} form. * * @param targetSpec the target specification, always {@link ComputationTargetSpecification#NULL} * @param desiredValue the requested value to test and resolve, not null * @return true if the value is available, false otherwise */ protected boolean isAvailable(final ComputationTargetSpecification targetSpec, final ValueRequirement desiredValue) { return isAvailable(targetSpec, (UniqueId) null, desiredValue); } protected ValueSpecification getAvailability(final ComputationTargetSpecification targetSpec, final ValueRequirement desiredValue, final AbstractMarketDataAvailabilityProvider underlying) { if (isAvailable(targetSpec, desiredValue)) { return underlying.getAvailability(targetSpec, desiredValue); } else { return null; } } /** * Tests how the target can be referenced and defers to one of the other {@code isAvailable} methods. * * @param targetSpec the target specification as passed to {@link MarketDataAvailabilityFilter#isAvailable}, possibly null * @param target the target to evaluate, not null * @param desiredValue the requested value to test and resolve, not null * @return true if the value is available, false otherwise */ @Override public final boolean isAvailable(final ComputationTargetSpecification targetSpec, final Object target, final ValueRequirement desiredValue) { if (target instanceof ExternalBundleIdentifiable) { if (isAvailable(targetSpec, ((ExternalBundleIdentifiable) target).getExternalIdBundle(), desiredValue)) { return true; } } if (target instanceof ExternalIdentifiable) { if (isAvailable(targetSpec, ((ExternalIdentifiable) target).getExternalId(), desiredValue)) { return true; } } if (target instanceof UniqueIdentifiable) { if (isAvailable(targetSpec, ((UniqueIdentifiable) target).getUniqueId(), desiredValue)) { return true; } } if (target == null) { return isAvailable(targetSpec, desiredValue); } else { return false; } } /** * Updates a collection containing keys that will be used to form the cache hint when this is used to construct an availability provider. A sub-class should put any construction parameters into the * key that distinguish its behavior from other filters of the same class. * * @param key the key to update */ protected abstract void populateAvailabilityHintKey(Collection<Serializable> key); @Override public MarketDataAvailabilityProvider withProvider(final MarketDataAvailabilityProvider provider) { final AbstractMarketDataAvailabilityProvider underlying = AbstractMarketDataAvailabilityProvider.of(provider); return new AbstractMarketDataAvailabilityProvider() { @Override public MarketDataAvailabilityFilter getAvailabilityFilter() { return AbstractMarketDataAvailabilityFilter.this; } @Override protected ValueSpecification getAvailability(final ComputationTargetSpecification targetSpec, final ExternalId identifier, final ValueRequirement desiredValue) { return AbstractMarketDataAvailabilityFilter.this.getAvailability(targetSpec, identifier, desiredValue, underlying); } @Override protected ValueSpecification getAvailability(final ComputationTargetSpecification targetSpec, final ExternalIdBundle identifiers, final ValueRequirement desiredValue) { return AbstractMarketDataAvailabilityFilter.this.getAvailability(targetSpec, identifiers, desiredValue, underlying); } @Override protected ValueSpecification getAvailability(final ComputationTargetSpecification targetSpec, final UniqueId identifier, final ValueRequirement desiredValue) { return AbstractMarketDataAvailabilityFilter.this.getAvailability(targetSpec, identifier, desiredValue, underlying); } @Override protected ValueSpecification getAvailability(final ComputationTargetSpecification targetSpec, final ValueRequirement desiredValue) { return AbstractMarketDataAvailabilityFilter.this.getAvailability(targetSpec, desiredValue, underlying); } @Override public Serializable getAvailabilityHintKey() { final ArrayList<Serializable> key = new ArrayList<Serializable>(5); key.add(getClass().getName()); key.add(AbstractMarketDataAvailabilityFilter.this.getClass().getName()); key.add(provider.getAvailabilityHintKey()); key.trimToSize(); return key; } }; } }