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

import java.net.URI;
import java.util.Collection;

import javax.time.Instant;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;

import com.opengamma.core.config.ConfigSource;
import com.opengamma.id.ObjectId;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.ReflectionUtils;
import com.opengamma.util.fudgemsg.FudgeListWrapper;
import com.opengamma.util.rest.AbstractDataResource;

/**
 * RESTful resource for configuration.
 * <p>
 * This resource receives and processes RESTful calls to the configuration source.
 */
@Path("/cfgSource")
public class DataConfigSourceResource extends AbstractDataResource {

  /**
   * The config source.
   */
  private final ConfigSource _exgSource;

  /**
   * Creates the resource, exposing the underlying source over REST.
   * 
   * @param configSource  the underlying config source, not null
   */
  public DataConfigSourceResource(final ConfigSource configSource) {
    ArgumentChecker.notNull(configSource, "configSource");
    _exgSource = configSource;
  }

  //-------------------------------------------------------------------------
  /**
   * Gets the configuration source.
   * 
   * @return the configuration source, not null
   */
  public ConfigSource getConfigSource() {
    return _exgSource;
  }

  //-------------------------------------------------------------------------
  @GET
  @Path("configs")
  public Response search(
      @QueryParam("type") String typeStr,
      @QueryParam("versionAsOf") String versionAsOf,
      @QueryParam("correctedTo") String correctedTo,
      @QueryParam("name") String name) {
    final Class<?> type = ReflectionUtils.loadClass(typeStr);
    final VersionCorrection vc = VersionCorrection.parse(versionAsOf, correctedTo);
    Collection<?> result = getConfigSource().getConfigs(type, name, vc);
    return Response.ok(FudgeListWrapper.of(result)).build();
  }

  @GET
  @Path("configs/{configId}")
  public Response get(
      @PathParam("configId") String idStr,
      @QueryParam("type") String typeStr,
      @QueryParam("version") String version,
      @QueryParam("versionAsOf") String versionAsOf,
      @QueryParam("correctedTo") String correctedTo) {
    final Class<?> type = ReflectionUtils.loadClass(typeStr);
    final ObjectId objectId = ObjectId.parse(idStr);
    if (version != null) {
      Object result = getConfigSource().getConfig(type, objectId.atVersion(version));
      return Response.ok(result).build();
    } else {
      VersionCorrection vc = VersionCorrection.parse(versionAsOf, correctedTo);
      Object result = getConfigSource().getConfig(type, objectId, vc);
      return Response.ok(result).build();
    }
  }

  //-------------------------------------------------------------------------
  /**
   * Builds a URI.
   * 
   * @param baseUri  the base URI, not null
   * @param vc  the version-correction, null means latest
   * @param name  the name, may be null
   * @param type  the config type, may be null
   * @return the URI, not null
   */
  public static URI uriSearch(URI baseUri, VersionCorrection vc, String name, Class<?> type) {
    UriBuilder bld = UriBuilder.fromUri(baseUri).path("/configs");
    if (vc != null) {
      bld.queryParam("versionAsOf", vc.getVersionAsOfString());
      bld.queryParam("correctedTo", vc.getCorrectedToString());
    }
    if (type != null) {
      bld.queryParam("type", type.getName());
    }
    bld.queryParam("name", name);
    return bld.build();
  }

  /**
   * Builds a URI.
   * 
   * @param baseUri  the base URI, not null
   * @param uniqueId  the unique identifier, may be null
   * @param type  the config type, may be null
   * @return the URI, not null
   */
  public static URI uriGet(URI baseUri, UniqueId uniqueId, Class<?> type) {
    UriBuilder bld = UriBuilder.fromUri(baseUri).path("/configs/{configId}");
    if (uniqueId.getVersion() != null) {
      bld.queryParam("version", uniqueId.getVersion());
    }
    if (type != null) {
      bld.queryParam("type", type.getName());
    }
    return bld.build(uniqueId.getObjectId());
  }

  /**
   * Builds a URI.
   * 
   * @param baseUri  the base URI, not null
   * @param objectId  the object identifier, may be null
   * @param vc  the version-correction, null means latest
   * @param type  the config type, may be null
   * @return the URI, not null
   */
  public static URI uriGet(URI baseUri, ObjectId objectId, VersionCorrection vc, Class<?> type) {
    UriBuilder bld = UriBuilder.fromUri(baseUri).path("/configs/{configId}");
    if (vc != null) {
      bld.queryParam("versionAsOf", vc.getVersionAsOfString());
      bld.queryParam("correctedTo", vc.getCorrectedToString());
    }
    if (type != null) {
      bld.queryParam("type", type.getName());
    }
    return bld.build(objectId);
  }

  // deprecated
  //-------------------------------------------------------------------------
  @GET
  @Path("configs/searchSingle")
  public Response searchSingle(
      @QueryParam("type") String typeStr,
      @QueryParam("versionAsOf") String versionAsOfStr,
      @QueryParam("name") String name) {
    final Class<?> type = ReflectionUtils.loadClass(typeStr);
    if (versionAsOfStr != null) {
      final Instant versionAsOf = VersionCorrection.parse(versionAsOfStr, null).getVersionAsOf();
      Object result = getConfigSource().getByName(type, name, versionAsOf);
      return Response.ok(result).build();
    } else {
      Object result = getConfigSource().getLatestByName(type, name);
      return Response.ok(result).build();
    }
  }

  /**
   * Builds a URI.
   * 
   * @param baseUri  the base URI, not null
   * @param name  the name, may be null
   * @param versionAsOf  the version to fetch, null means latest
   * @param type  the config type, may be null
   * @return the URI, not null
   */
  public static URI uriSearchSingle(URI baseUri, String name, Instant versionAsOf, Class<?> type) {
    UriBuilder bld = UriBuilder.fromUri(baseUri).path("/configs/searchSingle");
    bld.queryParam("name", name);
    if (type != null) {
      bld.queryParam("type", type.getName());
    }
    if (versionAsOf != null) {
      bld.queryParam("versionAsOf", versionAsOf.toString());
    }
    return bld.build();
  }

}

@@ -930,11 +930,13 @@
 th(%22
-/cf
+confi
 gSou
@@ -3525,25 +3525,24 @@
 eUri).path(%22
-/
 configs%22);%0A 
@@ -4174,33 +4174,32 @@
 (baseUri).path(%22
-/
 configs/%7BconfigI
@@ -4853,33 +4853,32 @@
 (baseUri).path(%22
-/
 configs/%7BconfigI
@@ -5264,33 +5264,34 @@
 Path(%22config
-s/s
+S
 earch
-S
+es/s
 ingle%22)%0A  pu
@@ -6327,24 +6327,24 @@
 th(%22
-/
 config
-s/s
+S
 earch
-S
+es/s
 ingl

Tidy URI management