Package com.opengamma.master.config.impl

Source Code of com.opengamma.master.config.impl.InMemoryConfigMaster

/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.master.config.impl;

import static com.google.common.collect.Maps.newHashMap;
import static com.opengamma.lambdava.streams.Lambdava.functional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;

import org.threeten.bp.Instant;

import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import com.opengamma.DataNotFoundException;
import com.opengamma.core.change.BasicChangeManager;
import com.opengamma.core.change.ChangeManager;
import com.opengamma.core.change.ChangeType;
import com.opengamma.core.config.impl.ConfigItem;
import com.opengamma.id.IdUtils;
import com.opengamma.id.ObjectId;
import com.opengamma.id.ObjectIdSupplier;
import com.opengamma.id.ObjectIdentifiable;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.lambdava.functions.Function1;
import com.opengamma.master.MasterUtils;
import com.opengamma.master.config.ConfigDocument;
import com.opengamma.master.config.ConfigHistoryRequest;
import com.opengamma.master.config.ConfigHistoryResult;
import com.opengamma.master.config.ConfigMaster;
import com.opengamma.master.config.ConfigMetaDataRequest;
import com.opengamma.master.config.ConfigMetaDataResult;
import com.opengamma.master.config.ConfigSearchRequest;
import com.opengamma.master.config.ConfigSearchResult;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.paging.Paging;
import com.opengamma.util.paging.PagingRequest;

/**
* A simple, in-memory implementation of {@code ConfigMaster}.
* <p>
* This master does not support versioning of configuration documents.
* <p>
* This implementation does not copy stored elements, making it thread-hostile. As such, this implementation is currently most useful for testing scenarios.
*/
public class InMemoryConfigMaster implements ConfigMaster {

  /**
   * The default scheme used for each {@link ObjectId}.
   */
  public static final String DEFAULT_OID_SCHEME = "MemCfg";

  /**
   * A cache of configurations by identifier.
   */
  private final ConcurrentMap<ObjectId, ConfigDocument> _store = new ConcurrentHashMap<ObjectId, ConfigDocument>();
  /**
   * The supplied of identifiers.
   */
  private final Supplier<ObjectId> _objectIdSupplier;
  /**
   * The change manager.
   */
  private final ChangeManager _changeManager;
  /**
   * A source of version strings so that updates to an object identifier get a new unique identifier.
   */
  private final AtomicLong _versions = new AtomicLong();

  /**
   * Creates an instance.
   */
  public InMemoryConfigMaster() {
    this(new ObjectIdSupplier(InMemoryConfigMaster.DEFAULT_OID_SCHEME));
  }

  /**
   * Creates an instance specifying the change manager.
   *
   * @param changeManager the change manager, not null
   */
  public InMemoryConfigMaster(final ChangeManager changeManager) {
    this(new ObjectIdSupplier(InMemoryConfigMaster.DEFAULT_OID_SCHEME), changeManager);
  }

  /**
   * Creates an instance specifying the supplier of object identifiers.
   *
   * @param objectIdSupplier the supplier of object identifiers, not null
   */
  public InMemoryConfigMaster(final Supplier<ObjectId> objectIdSupplier) {
    this(objectIdSupplier, new BasicChangeManager());
  }

  /**
   * Creates an instance specifying the supplier of object identifiers and change manager.
   *
   * @param objectIdSupplier the supplier of object identifiers, not null
   * @param changeManager the change manager, not null
   */
  public InMemoryConfigMaster(final Supplier<ObjectId> objectIdSupplier, final ChangeManager changeManager) {
    ArgumentChecker.notNull(objectIdSupplier, "objectIdSupplier");
    ArgumentChecker.notNull(changeManager, "changeManager");
    _objectIdSupplier = objectIdSupplier;
    _changeManager = changeManager;
  }

  //-------------------------------------------------------------------------
  @Override
  public <T> ConfigSearchResult<T> search(final ConfigSearchRequest<T> request) {
    ArgumentChecker.notNull(request, "request");
    final List<ConfigDocument> list = new ArrayList<ConfigDocument>();
    for (final ConfigDocument doc : _store.values()) {
      if (request.matches(doc)) {
        list.add(doc);
      }
    }
    Collections.sort(list, request.getSortOrder());

    final ConfigSearchResult<T> result = new ConfigSearchResult<T>();
    result.setPaging(Paging.of(request.getPagingRequest(), list));
    result.getDocuments().addAll(request.getPagingRequest().select(list));
    return result;
  }

  //-------------------------------------------------------------------------
  @Override
  public ConfigDocument get(final ObjectIdentifiable objectId, final VersionCorrection versionCorrection) {
    ArgumentChecker.notNull(objectId, "objectId");
    ArgumentChecker.notNull(versionCorrection, "versionCorrection");
    final ConfigDocument document = _store.get(objectId.getObjectId());
    if (document == null) {
      throw new DataNotFoundException("Config not found: " + objectId);
    }
    return document;
  }

  //-------------------------------------------------------------------------
  @Override
  public ConfigDocument add(final ConfigDocument document) {
    ArgumentChecker.notNull(document, "document");
    ArgumentChecker.notNull(document.getConfig(), "document.object");
    ArgumentChecker.notNull(document.getConfig().getName(), "document.object.name");
    ArgumentChecker.notNull(document.getConfig().getValue(), "document.object.value");

    final ConfigItem<?> item = document.getConfig();
    final ObjectId objectId = _objectIdSupplier.get();
    final UniqueId uniqueId = objectId.atVersion(Long.toString(_versions.incrementAndGet()));
    final Instant now = Instant.now();
    item.setUniqueId(uniqueId);
    IdUtils.setInto(item.getValue(), uniqueId);
    final ConfigDocument doc = new ConfigDocument(item);
    doc.setConfig(document.getConfig());
    doc.setUniqueId(uniqueId);
    doc.setVersionFromInstant(now);
    _store.put(objectId, doc);
    _changeManager.entityChanged(ChangeType.ADDED, objectId, doc.getVersionFromInstant(), doc.getVersionToInstant(), now);
    return doc;
  }

  //-------------------------------------------------------------------------
  @Override
  public ConfigDocument update(final ConfigDocument document) {
    ArgumentChecker.notNull(document, "document");
    ArgumentChecker.notNull(document.getUniqueId(), "document.uniqueId");
    ArgumentChecker.notNull(document.getConfig(), "document.object");
    ArgumentChecker.notNull(document.getConfig().getValue(), "document.object.value");

    UniqueId uniqueId = document.getUniqueId();
    final Instant now = Instant.now();
    final ConfigDocument storedDocument = _store.get(uniqueId.getObjectId());
    if (storedDocument == null) {
      throw new DataNotFoundException("Config not found: " + uniqueId);
    }
    document.setVersionFromInstant(now);
    document.setVersionToInstant(null);
    document.setCorrectionFromInstant(now);
    document.setCorrectionToInstant(null);
    uniqueId = uniqueId.withVersion(Long.toString(_versions.incrementAndGet()));
    document.setUniqueId(uniqueId);
    IdUtils.setInto(document.getConfig().getValue(), uniqueId);
    if (_store.replace(uniqueId.getObjectId(), storedDocument, document) == false) {
      throw new IllegalArgumentException("Concurrent modification");
    }
    _changeManager.entityChanged(ChangeType.CHANGED, document.getObjectId(), document.getVersionFromInstant(), document.getVersionToInstant(), now);
    return document;
  }

  //-------------------------------------------------------------------------
  @Override
  public void remove(final ObjectIdentifiable objectIdentifiable) {
    ArgumentChecker.notNull(objectIdentifiable, "objectIdentifiable");
    if (_store.remove(objectIdentifiable.getObjectId()) == null) {
      throw new DataNotFoundException("Config not found: " + objectIdentifiable);
    }
    _changeManager.entityChanged(ChangeType.REMOVED, objectIdentifiable.getObjectId(), null, null, Instant.now());
  }

  //-------------------------------------------------------------------------
  @Override
  public ConfigDocument correct(final ConfigDocument document) {
    return update(document);
  }

  //-------------------------------------------------------------------------
  @Override
  public ChangeManager changeManager() {
    return _changeManager;
  }

  //-------------------------------------------------------------------------
  @Override
  public ConfigDocument get(final UniqueId uniqueId) {
    ArgumentChecker.notNull(uniqueId, "document.uniqueId");
    final ConfigDocument document = _store.get(uniqueId.getObjectId());
    if (document == null) {
      throw new DataNotFoundException("Config not found: " + uniqueId.getObjectId());
    }
    return document;
  }

  //-------------------------------------------------------------------------
  @Override
  public ConfigMetaDataResult metaData(final ConfigMetaDataRequest request) {
    ArgumentChecker.notNull(request, "request");
    final ConfigMetaDataResult result = new ConfigMetaDataResult();
    if (request.isConfigTypes()) {
      final Set<Class<?>> types = Sets.newHashSet();
      for (final ConfigDocument doc : _store.values()) {
        types.add(doc.getConfig().getType());
      }
      result.getConfigTypes().addAll(types);
    }
    return result;
  }

  @Override
  public List<UniqueId> replaceVersions(final ObjectIdentifiable objectId, final List<ConfigDocument> replacementDocuments) {
    return replaceAllVersions(objectId, replacementDocuments);
  }

  @Override
  public List<UniqueId> replaceVersion(final UniqueId uniqueId, final List<ConfigDocument> replacementDocuments) {
    return replaceAllVersions(uniqueId.getObjectId(), replacementDocuments);
  }

  @Override
  public List<UniqueId> replaceAllVersions(final ObjectIdentifiable objectId, final List<ConfigDocument> replacementDocuments) {
    ArgumentChecker.notNull(replacementDocuments, "replacementDocuments");
    ArgumentChecker.notNull(objectId, "objectId");
    for (final ConfigDocument replacementDocument : replacementDocuments) {
      validateDocument(replacementDocument);
    }
    final Instant now = Instant.now();
    ArgumentChecker.isTrue(MasterUtils.checkUniqueVersionsFrom(replacementDocuments), "No two versioned documents may have the same \"version from\" instant");

    final ConfigDocument storedDocument = _store.get(objectId.getObjectId());
    if (storedDocument == null) {
      throw new DataNotFoundException("Document not found: " + objectId.getObjectId());
    }

    if (replacementDocuments.isEmpty()) {
      _store.remove(objectId.getObjectId());
      _changeManager.entityChanged(ChangeType.REMOVED, objectId.getObjectId(), null, null, now);
      return Collections.emptyList();
    } else {
      final Instant storedVersionFrom = storedDocument.getVersionFromInstant();
      final Instant storedVersionTo = storedDocument.getVersionToInstant();

      final List<ConfigDocument> orderedReplacementDocuments = MasterUtils.adjustVersionInstants(now, storedVersionFrom, storedVersionTo, replacementDocuments);

      final ConfigDocument lastReplacementDocument = orderedReplacementDocuments.get(orderedReplacementDocuments.size() - 1);

      if (_store.replace(objectId.getObjectId(), storedDocument, lastReplacementDocument) == false) {
        throw new IllegalArgumentException("Concurrent modification");
      }
      return ImmutableList.of(lastReplacementDocument.getUniqueId());
    }
  }

  @Override
  public UniqueId addVersion(final ObjectIdentifiable objectId, final ConfigDocument documentToAdd) {
    final List<UniqueId> result = replaceVersions(objectId, Collections.singletonList(documentToAdd));
    if (result.isEmpty()) {
      return null;
    } else {
      return result.get(0);
    }
  }

  @Override
  public void removeVersion(final UniqueId uniqueId) {
    replaceVersion(uniqueId, Collections.<ConfigDocument>emptyList());
  }

  @Override
  public UniqueId replaceVersion(final ConfigDocument replacementDocument) {
    final List<UniqueId> result = replaceVersion(replacementDocument.getUniqueId(), Collections.singletonList(replacementDocument));
    if (result.isEmpty()) {
      return null;
    } else {
      return result.get(0);
    }
  }

  private <T> void validateDocument(final ConfigDocument document) {
    ArgumentChecker.notNull(document.getConfig(), "document.object");
    ArgumentChecker.notNull(document.getConfig().getValue(), "document.object.value");
    ArgumentChecker.notNull(document.getName(), "document.name");
  }

  //-------------------------------------------------------------------------
  @Override
  public <R> ConfigHistoryResult<R> history(final ConfigHistoryRequest<R> request) {
    final Class<?> type = request.getType();
    final ObjectId oid = request.getObjectId();
    final PagingRequest pagingRequest = request.getPagingRequest();

    return new ConfigHistoryResult<R>(
        pagingRequest.select(
            functional(_store.keySet())
                .map(new Function1<ObjectId, ConfigDocument>() {
                  @Override
                  public ConfigDocument execute(final ObjectId objectId) {
                    return _store.get(objectId);
                  }
                })
                .filter(new Function1<ConfigDocument, Boolean>() {
                  @Override
                  public Boolean execute(final ConfigDocument configDocument) {
                    return
                    (oid == null || (configDocument.getObjectId().equals(oid)))
                        &&
                        (type == null || (type.isAssignableFrom(configDocument.getType())));
                  }
                })
                .sortBy(new Comparator<ConfigDocument>() {
                  @Override
                  public int compare(final ConfigDocument configDocument, final ConfigDocument configDocument1) {
                    return configDocument.getVersionFromInstant().compareTo(configDocument1.getVersionFromInstant());
                  }
                })
                .asList()));
  }

  @Override
  public Map<UniqueId, ConfigDocument> get(final Collection<UniqueId> uniqueIds) {
    final Map<UniqueId, ConfigDocument> resultMap = newHashMap();
    for (final UniqueId uniqueId : uniqueIds) {
      resultMap.put(uniqueId, _store.get(uniqueId.getObjectId()));
    }
    return resultMap;
  }

}
TOP

Related Classes of com.opengamma.master.config.impl.InMemoryConfigMaster

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.