/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.web.config; import java.net.URI; import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; import org.joda.beans.impl.flexi.FlexiBean; import com.google.common.collect.BiMap; import com.opengamma.DataNotFoundException; import com.opengamma.core.config.impl.ConfigItem; import com.opengamma.financial.analytics.ircurve.CurveSpecificationBuilderConfiguration; import com.opengamma.id.ObjectId; import com.opengamma.id.UniqueId; 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.ConfigSearchRequest; import com.opengamma.master.config.ConfigSearchResult; import com.opengamma.master.config.ConfigSearchSortOrder; import com.opengamma.util.paging.Paging; import com.opengamma.util.paging.PagingRequest; import com.opengamma.web.WebPaging; import com.opengamma.web.analytics.rest.MasterType; import com.opengamma.web.analytics.rest.Subscribe; import com.opengamma.web.analytics.rest.SubscribeMaster; import com.opengamma.web.json.JSONBuilder; import com.sun.jersey.api.client.ClientResponse.Status; /** * RESTful resource for all configuration documents. * <p> * The configuration documents resource represents all the data for one element type in the config master. * */ @Path("/configs") public class WebConfigsResource extends AbstractWebConfigResource { /** * Creates the resource. * @param configMaster the config master, not null */ public WebConfigsResource(final ConfigMaster configMaster) { super(configMaster); } //------------------------------------------------------------------------- @GET @Produces(MediaType.TEXT_HTML) @SubscribeMaster(MasterType.CONFIG) public String getHTML( @QueryParam("pgIdx") Integer pgIdx, @QueryParam("pgNum") Integer pgNum, @QueryParam("pgSze") Integer pgSze, @QueryParam("sort") String sort, @QueryParam("name") String name, @QueryParam("type") String type, @QueryParam("configId") List<String> configIdStrs, @Context UriInfo uriInfo) { PagingRequest pr = buildPagingRequest(pgIdx, pgNum, pgSze); ConfigSearchSortOrder so = buildSortOrder(sort, ConfigSearchSortOrder.NAME_ASC); FlexiBean out = search(pr, so, name, type, configIdStrs, uriInfo); return getFreemarker().build(HTML_DIR + "configs.ftl", out); } @GET @Produces(MediaType.APPLICATION_JSON) @SubscribeMaster(MasterType.CONFIG) public String getJSON( @QueryParam("pgIdx") Integer pgIdx, @QueryParam("pgNum") Integer pgNum, @QueryParam("pgSze") Integer pgSze, @QueryParam("sort") String sort, @QueryParam("name") String name, @QueryParam("type") String type, @QueryParam("configId") List<String> configIdStrs, @Context UriInfo uriInfo) { PagingRequest pr = buildPagingRequest(pgIdx, pgNum, pgSze); ConfigSearchSortOrder so = buildSortOrder(sort, ConfigSearchSortOrder.NAME_ASC); FlexiBean out = search(pr, so, name, type, configIdStrs, uriInfo); return getFreemarker().build(JSON_DIR + "configs.ftl", out); } @SuppressWarnings("unchecked") private FlexiBean search(PagingRequest request, ConfigSearchSortOrder so, String name, String typeName, List<String> configIdStrs, UriInfo uriInfo) { FlexiBean out = createRootData(); @SuppressWarnings("rawtypes") ConfigSearchRequest searchRequest = new ConfigSearchRequest(); typeName = StringUtils.trimToNull(typeName); if (typeName != null) { Class<?> typeClazz = data().getTypeMap().get(typeName); searchRequest.setType(typeClazz); } else { searchRequest.setType(Object.class); } searchRequest.setPagingRequest(request); searchRequest.setSortOrder(so); searchRequest.setName(StringUtils.trimToNull(name)); out.put("searchRequest", searchRequest); out.put("type", typeName); for (String configIdStr : configIdStrs) { searchRequest.addConfigId(ObjectId.parse(configIdStr)); } if (data().getUriInfo().getQueryParameters().size() > 0) { ConfigSearchResult<Object> searchResult = null; if (searchRequest.getType() != null) { searchResult = data().getConfigMaster().search(searchRequest); } else { searchResult = new ConfigSearchResult<Object>(); searchResult.setPaging(Paging.of(searchRequest.getPagingRequest(), searchResult.getDocuments())); } out.put("searchResult", searchResult); out.put("paging", new WebPaging(searchResult.getPaging(), uriInfo)); } return out; } //------------------------------------------------------------------------- @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Produces(MediaType.TEXT_HTML) public Response postHTML( @FormParam("name") String name, @FormParam(CONFIG_XML) String configXml, @FormParam("type") String typeName) { name = StringUtils.trimToNull(name); configXml = StringUtils.trimToNull(configXml); typeName = StringUtils.trimToNull(typeName); final Class<?> type = (typeName != null ? data().getTypeMap().get(typeName) : null); if (name == null || configXml == null || type == null) { FlexiBean out = createRootData(); if (name == null) { out.put("err_nameMissing", true); } if (configXml == null) { out.put("err_xmlMissing", true); } if (typeName == null) { out.put("err_typeMissing", true); } else if (type == null) { out.put("err_typeInvalid", true); } out.put("name", StringUtils.defaultString(name)); out.put("type", StringUtils.defaultString(typeName)); out.put(CONFIG_XML, StringEscapeUtils.escapeJavaScript(StringUtils.defaultString(configXml))); String html = getFreemarker().build(HTML_DIR + "config-add.ftl", out); return Response.ok(html).build(); } final Object configObj = parseXML(configXml, type); if (configObj == null || !type.isAssignableFrom(configObj.getClass())) { throw new IllegalArgumentException("Given configuration XML is not of type: " + typeName); } ConfigItem<?> item = ConfigItem.of(configObj); item.setName(name); item.setType(type); ConfigDocument doc = new ConfigDocument(item); ConfigDocument added = data().getConfigMaster().add(doc); URI uri = data().getUriInfo().getAbsolutePathBuilder().path(added.getUniqueId().toLatest().toString()).build(); return Response.seeOther(uri).build(); } @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Produces(MediaType.APPLICATION_JSON) public Response postJSON( @FormParam("name") String name, @FormParam("configJSON") String json, @FormParam(CONFIG_XML) String configXml, @FormParam("type") String typeName) { name = StringUtils.trimToNull(name); json = StringUtils.trimToNull(json); configXml = StringUtils.trimToNull(configXml); typeName = StringUtils.trimToNull(typeName); final Class<?> type = (typeName != null ? data().getTypeMap().get(typeName) : null); Response result = null; if (name == null || type == null || isEmptyConfigData(json, configXml)) { result = Response.status(Status.BAD_REQUEST).build(); } else { Object configObj = null; if (json != null) { configObj = parseJSON(json); } else if (configXml != null) { configObj = parseXML(configXml, type); } if (configObj == null || !type.isAssignableFrom(configObj.getClass())) { result = Response.status(Status.BAD_REQUEST).build(); } else { ConfigItem<?> item = ConfigItem.of(configObj); item.setName(name); item.setType(type); ConfigDocument doc = new ConfigDocument(item); ConfigDocument added = data().getConfigMaster().add(doc); URI uri = data().getUriInfo().getAbsolutePathBuilder().path(added.getUniqueId().toLatest().toString()).build(); result = Response.created(uri).build(); } } return result; } private boolean isEmptyConfigData(String json, String xml) { return (json == null && xml == null); } //------------------------------------------------------------------------- @GET @Path("metaData") @Produces(MediaType.APPLICATION_JSON) public String getMetaDataJSON() { FlexiBean out = createRootData(); return getFreemarker().build(JSON_DIR + "metadata.ftl", out); } //------------------------------------------------------------------------- @GET @Path("templates/{configType}") @Produces(MediaType.APPLICATION_JSON) public String getTemplateJSON(@PathParam("configType") String configType) { BiMap<String, Class<?>> typeMap = data().getTypeMap(); Class<?> typeClazz = typeMap.get(configType); String template = null; if (typeClazz != null) { JSONBuilder<?> jsonBuilder = data().getJsonBuilderMap().get(typeClazz); if (jsonBuilder != null) { template = jsonBuilder.getTemplate(); } } FlexiBean out = super.createRootData(); out.put("template", template); if (typeClazz != null) { out.put("type", typeClazz.getSimpleName()); } return getFreemarker().build(JSON_DIR + "template.ftl", out); } //------------------------------------------------------------------------- @Path("{configId}") public WebConfigResource findConfig(@Subscribe @PathParam("configId") String idStr) { data().setUriConfigId(idStr); UniqueId oid = UniqueId.parse(idStr); try { ConfigDocument doc = data().getConfigMaster().get(oid); data().setConfig(doc); } catch (DataNotFoundException ex) { ConfigHistoryRequest<Object> historyRequest = new ConfigHistoryRequest<Object>(oid, Object.class); historyRequest.setPagingRequest(PagingRequest.ONE); ConfigHistoryResult<?> historyResult = data().getConfigMaster().history(historyRequest); if (historyResult.getDocuments().size() == 0) { throw ex; } data().setConfig(historyResult.getFirstDocument()); } return new WebConfigResource(this); } //------------------------------------------------------------------------- /** * Creates the output root data. * @return the output root data, not null */ @Override protected FlexiBean createRootData() { FlexiBean out = super.createRootData(); ConfigSearchRequest<Object> searchRequest = new ConfigSearchRequest<Object>(); searchRequest.setType(Object.class); out.put("searchRequest", searchRequest); out.put("configTypes", getConfigTypesProvider().getConfigTypes()); out.put("configDescriptionMap", getConfigTypesProvider().getDescriptionMap()); out.put("configGroupMap", getConfigTypesProvider().getGroupMap()); out.put("curveSpecs", CurveSpecificationBuilderConfiguration.s_curveSpecNames); return out; } //------------------------------------------------------------------------- /** * Builds a URI for configs. * @param data the data, not null * @return the URI, not null */ public static URI uri(WebConfigData data) { UriBuilder builder = data.getUriInfo().getBaseUriBuilder().path(WebConfigsResource.class); return builder.build(); } }