1 /*******************************************************************************
2 * Copyright (c) 2012-2015 University of Stuttgart.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * and the Apache License 2.0 which both accompany this distribution,
6 * and are available at http://www.eclipse.org/legal/epl-v10.html
7 * and http://www.apache.org/licenses/LICENSE-2.0
10 * Oliver Kopp - initial API and implementation
11 *******************************************************************************/
12 package org.eclipse.winery.repository.resources.servicetemplates.topologytemplates;
15 import java.util.ArrayList;
16 import java.util.List;
18 import javax.ws.rs.Consumes;
19 import javax.ws.rs.GET;
20 import javax.ws.rs.PUT;
21 import javax.ws.rs.Path;
22 import javax.ws.rs.Produces;
23 import javax.ws.rs.QueryParam;
24 import javax.ws.rs.core.Context;
25 import javax.ws.rs.core.HttpHeaders;
26 import javax.ws.rs.core.MediaType;
27 import javax.ws.rs.core.Response;
28 import javax.ws.rs.core.UriInfo;
30 import org.eclipse.winery.common.Util;
31 import org.eclipse.winery.common.ids.definitions.ServiceTemplateId;
32 import org.eclipse.winery.model.tosca.TEntityTemplate;
33 import org.eclipse.winery.model.tosca.TNodeTemplate;
34 import org.eclipse.winery.model.tosca.TRelationshipTemplate;
35 import org.eclipse.winery.model.tosca.TTopologyTemplate;
36 import org.eclipse.winery.repository.Prefs;
37 import org.eclipse.winery.repository.Utils;
38 import org.eclipse.winery.repository.backend.BackendUtils;
39 import org.eclipse.winery.repository.client.IWineryRepositoryClient;
40 import org.eclipse.winery.repository.client.WineryRepositoryClientFactory;
41 import org.eclipse.winery.repository.json.TopologyTemplateModule;
42 import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource;
43 import org.restdoc.annotations.RestDoc;
44 import org.restdoc.annotations.RestDocParam;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
48 import com.fasterxml.jackson.databind.ObjectMapper;
49 import com.fasterxml.jackson.databind.SerializationFeature;
50 import com.sun.jersey.api.client.Client;
51 import com.sun.jersey.api.client.WebResource.Builder;
52 import com.sun.jersey.api.view.Viewable;
54 public class TopologyTemplateResource {
56 private static final Logger logger = LoggerFactory.getLogger(TopologyTemplateResource.class);
58 private final TTopologyTemplate topologyTemplate;
60 private final ServiceTemplateResource serviceTemplateRes;
64 * A topology template is always nested in a service template
66 public TopologyTemplateResource(ServiceTemplateResource parent) {
67 this.topologyTemplate = parent.getServiceTemplate().getTopologyTemplate();
68 this.serviceTemplateRes = parent;
72 public static class DataForJSP {
74 private String location;
75 private TTopologyTemplate topologyTemplate;
76 private URI repositoryURI;
77 private String additonalCSS;
78 private Boolean autoLayoutOnLoad;
79 private String additionalScript;
82 public DataForJSP(String location, URI repositoryURI, TTopologyTemplate topologyTemplate, String additonalCSS, String additionalScript, Boolean autoLayoutOnLoad) {
83 this.location = location;
84 this.repositoryURI = repositoryURI;
85 this.topologyTemplate = topologyTemplate;
86 this.additonalCSS = additonalCSS;
87 this.additionalScript = additionalScript;
88 this.autoLayoutOnLoad = autoLayoutOnLoad;
91 public String getLocation() {
95 public TTopologyTemplate getTopologyTemplate() {
96 return this.topologyTemplate;
99 public String getAdditonalCSS() {
100 return this.additonalCSS;
103 public String getAdditionalScript() {
104 return this.additionalScript;
107 public Boolean getAutoLayoutOnLoad() {
108 return this.autoLayoutOnLoad;
111 public IWineryRepositoryClient getClient() {
113 // IWineryRepository is not implemented by Prefs.INSTANCE.getRepository()
114 // Therefore, we have to generate a real WineryRepositoryClient even if that causes more http load
115 IWineryRepositoryClient client = WineryRepositoryClientFactory.getWineryRepositoryClient();
116 client.addRepository(this.repositoryURI.toString());
124 @RestDoc(methodDescription = "?edit is used in the URL to get the jsPlumb-based editor")
125 @Produces(MediaType.TEXT_HTML)
127 public Response getHTML(
128 @QueryParam(value = "edit") String edit,
129 @QueryParam(value = "script") @RestDocParam(description = "the script to include in a <script> tag. The function wineryViewExternalScriptOnLoad if it is defined. Only available if 'view' is also set") String script,
130 @QueryParam(value = "view") String view,
131 @QueryParam(value = "autoLayoutOnLoad") String autoLayoutOnLoad,
132 @Context UriInfo uriInfo) {
136 String location = Prefs.INSTANCE.getWineryTopologyModelerPath();
137 location = uriInfo.getBaseUri().resolve(location).toString();
138 // at the topology modeler, jersey needs to have an absolute path
139 URI repositoryURI = uriInfo.getBaseUri();
140 location = location + "/?repositoryURL=";
141 location = location + Util.URLencode(repositoryURI.toString());
142 ServiceTemplateId serviceTemplate = (ServiceTemplateId) this.serviceTemplateRes.getId();
143 location = location + "&ns=";
144 location = location + serviceTemplate.getNamespace().getEncoded();
145 location = location + "&id=";
146 location = location + serviceTemplate.getXmlId().getEncoded();
148 String additionalCSS = null;
149 Boolean autoLayoutOnLoadBoolean = false;
151 // integration in Winery
152 // currently not maintained: Winery includes ?view as iframe
153 JSPName = "/jsp/servicetemplates/topologytemplates/topologytemplate.jsp";
156 // fullscreen: additionalCSS and script possible
157 if (!"".equals(view)) {
158 // view with additional CSS
159 URI cssURI = URI.create(view);
160 if (cssURI.isAbsolute()) {
161 additionalCSS = view;
163 // relative URLs starts at "/css/topologyrendering/"
164 additionalCSS = uriInfo.getBaseUri().resolve("css/topologytemplaterendering/").resolve(view).toString();
165 if (!additionalCSS.endsWith(".css")) {
166 additionalCSS += ".css";
170 if (autoLayoutOnLoad != null) {
171 autoLayoutOnLoadBoolean = true;
173 JSPName = "/jsp/servicetemplates/topologytemplates/topologytemplateview.jsp";
175 Viewable viewable = new Viewable(JSPName, new DataForJSP(location, repositoryURI, this.topologyTemplate, additionalCSS, script, autoLayoutOnLoadBoolean));
176 res = Response.ok().header(HttpHeaders.VARY, HttpHeaders.ACCEPT).entity(viewable).build();
179 URI uri = Utils.createURI(location);
180 res = Response.seeOther(uri).build();
187 * @param uriInfo the URI ending with "topologytemplate/" of a service
191 @Produces(MediaType.TEXT_PLAIN)
192 public Response triggerGenerateBuildPlan(@Context UriInfo uriInfo) {
193 String plansURI = uriInfo.getAbsolutePath().resolve("../plans/").toString();
194 String csarURI = uriInfo.getAbsolutePath().resolve("../?csar").toString();
196 String request = "<generatePlanForTopology><CSARURL>";
198 request += "</CSARURL><PLANPOSTURL>";
200 request += "</PLANPOSTURL></generatePlanForTopology>";
202 Client client = Client.create();
203 Builder wr = client.resource("http://localhost:1339/planbuilder/sync").type(MediaType.APPLICATION_XML);
206 wr.post(String.class, request);
207 } catch (com.sun.jersey.api.client.UniformInterfaceException e) {
208 return Response.serverError().entity(e.getMessage()).build();
211 return Response.ok().build();
216 @RestDoc(methodDescription="Returns a JSON representation of the topology template. <br />" +
217 "X and Y coordinates are embedded as attributes. QName string with Namespace: <br />" +
218 "{@link org.eclipse.winery.repository.common.constants.Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE} <br />" +
219 "@return The JSON representation of the topology template <em>without</em> associated artifacts and without the parent service template")
220 @Produces(MediaType.APPLICATION_JSON)
222 public Response getComponentInstanceJSON() {
224 ObjectMapper mapper = new ObjectMapper();
225 mapper.enable(SerializationFeature.INDENT_OUTPUT);
226 mapper.registerModule(new TopologyTemplateModule());
228 // convert it to json
229 String json = mapper.writeValueAsString(this.topologyTemplate);
230 res = Response.ok(json).build();
231 } catch (Exception e) {
232 TopologyTemplateResource.logger.error(e.getMessage(), e);
233 res = Response.serverError().entity(e.getMessage()).build();
238 @Path("nodetemplates/")
239 public NodeTemplatesResource getNodeTemplatesResource() {
240 // FIXME: onDelete will not work as we have a copy of the original list. We have to add a "listener" to remove at the list and route that remove to the original list
241 List<TNodeTemplate> l = BackendUtils.getAllNestedNodeTemplates(this.serviceTemplateRes.getServiceTemplate());
242 return new NodeTemplatesResource(l, this.serviceTemplateRes);
245 @Path("relationshiptemplates/")
246 public RelationshipTemplatesResource getRelationshipTemplatesResource() {
247 // FIXME: onDelete will not work. See getNodeTemplatesResource
248 List<TRelationshipTemplate> l = new ArrayList<TRelationshipTemplate>();
249 for (TEntityTemplate t : this.topologyTemplate.getNodeTemplateOrRelationshipTemplate()) {
250 if (t instanceof TRelationshipTemplate) {
251 l.add((TRelationshipTemplate) t);
254 return new RelationshipTemplatesResource(l, this.serviceTemplateRes);
258 @RestDoc(methodDescription = "Replaces the topology by the information given in the XML")
259 @Consumes(MediaType.TEXT_XML)
260 public Response setModel(TTopologyTemplate topologyTemplate) {
261 this.serviceTemplateRes.getServiceTemplate().setTopologyTemplate(topologyTemplate);
262 return BackendUtils.persist(this.serviceTemplateRes);
267 @RestDoc(methodDescription="<p>Returns an XML representation of the topology template." +
268 " X and Y coordinates are embedded as attributes. Namespace:" +
269 "{@link org.eclipse.winery.repository.common.constants.Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE} </p>" +
270 "<p>{@link org.eclipse.winery.repository.client.WineryRepositoryClient." +
271 "getTopologyTemplate(QName)} consumes this template</p>" +
272 "<p>@return The XML representation of the topology template <em>without</em>" +
273 "associated artifacts and without the parent service template </p>")
274 @Produces(MediaType.TEXT_XML)
276 public Response getComponentInstanceXML() {
277 return Utils.getXML(TTopologyTemplate.class, this.topologyTemplate);