/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.target.resolver; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import com.google.common.collect.Iterables; import com.opengamma.core.change.ChangeManager; import com.opengamma.core.change.DummyChangeManager; import com.opengamma.engine.target.ComputationTargetType; import com.opengamma.engine.target.Primitive; import com.opengamma.engine.target.Primitive.ExternalBundleIdentifiablePrimitive; import com.opengamma.engine.target.Primitive.ExternalIdentifiablePrimitive; import com.opengamma.id.ExternalId; import com.opengamma.id.ExternalIdBundle; import com.opengamma.id.ObjectId; import com.opengamma.id.UniqueId; import com.opengamma.id.VersionCorrection; /** * A {@link ObjectResolver} for {@link ComputationTargetType#PRIMITIVE}. */ public class PrimitiveResolver extends AbstractIdentifierResolver implements Resolver<Primitive> { private static final String SCHEME_PREFIX = "ExternalId-"; private static void escape(final String str, final StringBuilder into) { if ((str.indexOf('-') < 0) && (str.indexOf('\\') < 0)) { into.append(str); } else { final int l = str.length(); for (int i = 0; i < l; i++) { final char c = str.charAt(i); if ((c == '-') || (c == '\\')) { into.append('\\').append(c); } else { into.append(c); } } } } private static String[] unescape(final String str, final int i) { final int l = str.length(); int count = 1; boolean backslash = false; for (int j = i; j < l; j++) { final char c = str.charAt(j); if (c == '-') { count++; } else if (c == '\\') { j++; backslash = true; } } if ((count == 1) && !backslash) { return new String[] {str.substring(i) }; } final String[] result = new String[count]; final StringBuilder sb = new StringBuilder(); count = 0; for (int j = i; j < l; j++) { final char c = str.charAt(j); if (c == '-') { result[count++] = sb.toString(); sb.delete(0, sb.length()); } else if (c == '\\') { j++; if (j >= l) { return null; } sb.append(str.charAt(j)); } else { sb.append(c); } } result[count] = sb.toString(); return result; } // IdentifierResolver public static UniqueId resolveExternalId(final ExternalIdBundle identifiers) { final List<ExternalId> ids = new ArrayList<>(identifiers.getExternalIds()); // Natural sorting of external identifiers is by scheme and then by value Collections.sort(ids); final StringBuilder scheme = new StringBuilder(SCHEME_PREFIX); final StringBuilder value = new StringBuilder(); boolean first = true; for (final ExternalId id : ids) { if (first) { first = false; } else { scheme.append('-'); value.append('-'); } escape(id.getScheme().getName(), scheme); escape(id.getValue(), value); } return UniqueId.of(scheme.toString(), value.toString()); } @Override public UniqueId resolveExternalId(final ExternalIdBundle identifiers, final VersionCorrection versionCorrection) { return resolveExternalId(identifiers); } @Override public UniqueId resolveObjectId(final ObjectId identifier, final VersionCorrection versionCorrection) { return identifier.atLatestVersion(); } @Override public Map<ObjectId, UniqueId> resolveObjectIds(final Collection<ObjectId> identifiers, final VersionCorrection versionCorrection) { return resolveObjectIdsSingleThread(this, identifiers, versionCorrection); } // ObjectResolver /** * Utility function for resolving external ids from unique identifier * @param uniqueId unique identifier * @param schemePrefix the scheme prefix * @return external id bundle */ public static ExternalIdBundle resolveExternalIds(final UniqueId uniqueId, String schemePrefix) { final String scheme = uniqueId.getScheme(); final String[] schemes = unescape(scheme, schemePrefix.length()); if (schemes != null) { final String[] values = unescape(uniqueId.getValue(), 0); if (values != null) { if (schemes.length == values.length) { if (schemes.length == 1) { return ExternalIdBundle.of(schemes[0], values[0]); } else { final ExternalId[] identifiers = new ExternalId[schemes.length]; for (int i = 0; i < schemes.length; i++) { identifiers[i] = ExternalId.of(schemes[i], values[i]); } return ExternalIdBundle.of(identifiers); } } } } return null; } @Override public Primitive resolveObject(final UniqueId uniqueId, final VersionCorrection versionCorrection) { final String scheme = uniqueId.getScheme(); if (scheme.startsWith(SCHEME_PREFIX)) { ExternalIdBundle externalIdBundle = resolveExternalIds(uniqueId, SCHEME_PREFIX); if (externalIdBundle.size() == 1) { return new ExternalIdentifiablePrimitive(uniqueId, Iterables.getOnlyElement(externalIdBundle.getExternalIds())); } else { return new ExternalBundleIdentifiablePrimitive(uniqueId, externalIdBundle); } } else { return new Primitive(uniqueId); } } @Override public DeepResolver deepResolver() { return null; } @Override public ChangeManager changeManager() { return DummyChangeManager.INSTANCE; } }