6a6379135da1aa9d2057f95dc9b11df3465ba8dd
[vfc/nfvo/wfengine.git] / winery / org.eclipse.winery.repository / src / main / java / org / eclipse / winery / repository / resources / entitytypes / properties / PropertiesDefinitionResource.java
1 /*******************************************************************************
2  * Copyright (c) 2012-2013 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
8  *
9  * Contributors:
10  *     Oliver Kopp - initial API and implementation
11  *******************************************************************************/
12 package org.eclipse.winery.repository.resources.entitytypes.properties;
13
14 import java.util.ArrayList;
15 import java.util.List;
16
17 import javax.ws.rs.Consumes;
18 import javax.ws.rs.DELETE;
19 import javax.ws.rs.FormParam;
20 import javax.ws.rs.GET;
21 import javax.ws.rs.POST;
22 import javax.ws.rs.Path;
23 import javax.ws.rs.Produces;
24 import javax.ws.rs.core.MediaType;
25 import javax.ws.rs.core.Response;
26 import javax.ws.rs.core.Response.Status;
27 import javax.xml.namespace.QName;
28
29 import org.apache.commons.lang3.StringUtils;
30 import org.eclipse.winery.common.ModelUtilities;
31 import org.eclipse.winery.common.constants.MimeTypes;
32 import org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition;
33 import org.eclipse.winery.model.tosca.TEntityType;
34 import org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition;
35 import org.eclipse.winery.repository.backend.BackendUtils;
36 import org.eclipse.winery.repository.resources.EntityTypeResource;
37 import org.eclipse.winery.repository.resources.entitytypes.properties.winery.WinerysPropertiesDefinitionResource;
38 import org.restdoc.annotations.RestDoc;
39 import org.restdoc.annotations.RestDocParam;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 import com.sun.jersey.api.view.Viewable;
44
45 /**
46  * Models
47  * <ol>
48  * <li>TOSCA conforming properties definition (XML element / XML schema / none)</li>
49  * <li>Winery's KV properties (in the subresource "winery")</li>
50  * </ol>
51  * 
52  * This class does not have "KV" in its name, because it models
53  * {@link TEntityType.PropertiesDefinition}
54  */
55 public class PropertiesDefinitionResource {
56         
57         private static final Logger logger = LoggerFactory.getLogger(PropertiesDefinitionResource.class);
58         
59         // We hold a copy of super.res as we work on the type EntityTypeResource instead of AbstractComponentInstanceResource
60         private final EntityTypeResource parentRes;
61         
62         // we assume that this class is created at each request
63         // therefore, we can have "wpd" final
64         private final WinerysPropertiesDefinition wpd;
65         
66         
67         public PropertiesDefinitionResource(EntityTypeResource res) {
68                 this.parentRes = res;
69                 this.wpd = ModelUtilities.getWinerysPropertiesDefinition(res.getEntityType());
70         }
71         
72         @GET
73         @Produces(MediaType.TEXT_HTML)
74         public Viewable getHTML() {
75                 return new Viewable("/jsp/entitytypes/properties/propertiesDefinition.jsp", new JSPData(this, this.wpd));
76         }
77         
78         public TEntityType getEntityType() {
79                 return this.parentRes.getEntityType();
80         }
81         
82         @Path("winery/")
83         public WinerysPropertiesDefinitionResource getWinerysPropertiesDefinitionResource() {
84                 // this.wpd is null if there is no winery definition exisitin. The subresource handles that case, too
85                 return new WinerysPropertiesDefinitionResource(this.parentRes, this.wpd);
86         }
87         
88         @DELETE
89         public Response clearPropertiesDefinition() {
90                 this.getEntityType().setPropertiesDefinition(null);
91                 ModelUtilities.removeWinerysPropertiesDefinition(this.getEntityType());
92                 return BackendUtils.persist(this.parentRes);
93         }
94         
95         public boolean getIsWineryKeyValueProperties() {
96                 return (this.wpd != null);
97         }
98         
99         @GET
100         @Produces(MimeTypes.MIMETYPE_XSD)
101         public Response getXSD() {
102                 if (this.getIsWineryKeyValueProperties()) {
103                         return Response.ok().entity(ModelUtilities.getWinerysPropertiesDefinitionXSDAsDocument(this.wpd)).build();
104                 } else {
105                         // not yet implemented
106                         // We would have to check the imports in the repo for the defined property
107                         // This also has to be similarly done at the export to determine the right imports
108                         return Response.status(Status.NOT_FOUND).build();
109                 }
110         }
111         
112         @GET
113         @RestDoc(methodDescription = "We provide the XSD at . and at ./xsd/ to enable simple quering in the browser without the hazzle of setting the correct mime type.")
114         @Path("xsd/")
115         @Produces(MimeTypes.MIMETYPE_XSD)
116         public Response getXSDAtSubResource() {
117                 return this.getXSD();
118         }
119         
120         // @formatter:off
121         @POST
122         @RestDoc(methodDescription="Updates/creates a property based on XSD element or XML schema.")
123         @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
124         @Produces(MediaType.TEXT_PLAIN)
125         public Response onPost(
126                 @FormParam("name") @RestDocParam(description="Either xsdelement or xsdtype. 'name' comes from x-editable, which uses that as field name") String name,
127                 @FormParam("value") @RestDocParam(description="The qname") String value) {
128         // @formatter:on
129                 if (StringUtils.isEmpty(name)) {
130                         return Response.status(Status.BAD_REQUEST).entity("You have to provide a key/type or a name/value pair").build();
131                 }
132                 if (StringUtils.isEmpty(value)) {
133                         return Response.status(Status.BAD_REQUEST).entity("If a name is provided, a value has also to be provided").build();
134                 }
135                 
136                 // first of all, remove Winery's Properties definition (if it exists)
137                 ModelUtilities.removeWinerysPropertiesDefinition(this.getEntityType());
138                 
139                 QName qname = QName.valueOf(value);
140                 
141                 // replace old properties definition by new one
142                 PropertiesDefinition def = new PropertiesDefinition();
143                 if (name.equals("xsdtype")) {
144                         def.setType(qname);
145                 } else if (name.equals("xsdelement")) {
146                         def.setElement(qname);
147                 } else {
148                         return Response.status(Status.BAD_REQUEST).entity("Invalid name. Choose xsdelement or xsdtype").build();
149                 }
150                 this.getEntityType().setPropertiesDefinition(def);
151                 List<String> errors = new ArrayList<>();
152                 BackendUtils.deriveWPD(this.getEntityType(), errors);
153                 // currently the errors are just logged
154                 for (String error : errors) {
155                         PropertiesDefinitionResource.logger.debug(error);
156                 }
157                 return BackendUtils.persist(this.parentRes);
158                 
159         }
160         
161 }