1 /*******************************************************************************
2 * Copyright (c) 2012-2014 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._support.collections;
14 import java.util.ArrayList;
15 import java.util.List;
17 import javax.ws.rs.Consumes;
18 import javax.ws.rs.GET;
19 import javax.ws.rs.POST;
20 import javax.ws.rs.Path;
21 import javax.ws.rs.PathParam;
22 import javax.ws.rs.Produces;
23 import javax.ws.rs.QueryParam;
24 import javax.ws.rs.core.HttpHeaders;
25 import javax.ws.rs.core.MediaType;
26 import javax.ws.rs.core.Response;
27 import javax.ws.rs.core.Response.Status;
29 import org.eclipse.winery.common.Util;
30 import org.eclipse.winery.repository.datatypes.select2.Select2DataItem;
31 import org.eclipse.winery.repository.resources._support.IPersistable;
32 import org.restdoc.annotations.RestDoc;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 import com.sun.jersey.api.NotFoundException;
37 import com.sun.jersey.api.view.Viewable;
40 * Class managing a list of entities. It is intended to manage subresources,
41 * which are stored in a list. Either all entities have a unique key given by
42 * the TOSCA specification (subclass EntityWithIdCollectionResource) or a unique
43 * key is generated (subclass EntityWithoutIdCollectionResource)
45 * @param <EntityResourceT> the resource modeling the entity
46 * @param <EntityT> the entity type of single items in the list
48 public abstract class EntityCollectionResource<EntityResourceT extends EntityResource<EntityT>, EntityT> implements IIdDetermination<EntityT> {
50 private static final Logger logger = LoggerFactory.getLogger(EntityCollectionResource.class);
52 protected final List<EntityT> list;
54 protected final IPersistable res;
56 protected final Class<EntityT> entityTClazz;
58 protected final Class<EntityResourceT> entityResourceTClazz;
62 * @param clazz the class of EntityT. Required as it is not possible to call
63 * new EntityT (see http://stackoverflow.com/a/1090488/873282)
64 * @param list the list of entities contained in this resource. Has to be
65 * typed <Object> as not all TOSCA elements in the specification
66 * inherit from TExtensibleElements
67 * @param res the main resource the list is belonging to. Required for
70 public EntityCollectionResource(Class<EntityResourceT> entityResourceTClazz, Class<EntityT> entityTClazz, List<EntityT> list, IPersistable res) {
71 this.entityResourceTClazz = entityResourceTClazz;
72 this.entityTClazz = entityTClazz;
78 * Returns a list of ids of all entities nested here
81 @Produces(MediaType.APPLICATION_JSON)
82 public Object getListOfAllEntityIds(@QueryParam("select2") String select2) {
83 if (select2 == null) {
84 return this.getListOfAllEntityIdsAsList();
86 // return data ready for consumption by select2
87 List<Select2DataItem> res = new ArrayList<Select2DataItem>(this.list.size());
88 for (EntityT o : this.list) {
89 String id = this.getId(o);
90 Select2DataItem di = new Select2DataItem(id, id);
97 public List<String> getListOfAllEntityIdsAsList() {
98 List<String> res = new ArrayList<String>(this.list.size());
99 for (EntityT o : this.list) {
100 // We assume that different Object serializations *always* have different hashCodes
101 res.add(this.getId(o));
107 * Required by reqandcapdefs.jsp
109 public List<EntityResourceT> getAllEntityResources() {
110 List<String> listOfAllSubResources = this.getListOfAllEntityIdsAsList();
111 List<EntityResourceT> res = new ArrayList<EntityResourceT>(listOfAllSubResources.size());
112 for (String id : listOfAllSubResources) {
113 res.add(this.getEntityResourceFromDecodedId(id));
118 public EntityResourceT getEntityResourceFromDecodedId(String id) {
119 EntityT entity = null;
121 for (EntityT c : this.list) {
123 String cId = this.getId(c);
124 if (cId.equals(id)) {
129 if (entity == null) {
130 throw new NotFoundException();
132 return this.getEntityResourceInstance(entity, idx);
137 public EntityResourceT getEntityResource(@PathParam("id") String id) {
139 throw new IllegalArgumentException("id has to be given");
141 id = Util.URLdecode(id);
142 return this.getEntityResourceFromDecodedId(id);
146 * @param entity the entity to create a resource for
147 * @param idx the index in the list
148 * @return the resource managing the given entity
150 protected abstract EntityResourceT getEntityResourceInstance(EntityT entity, int idx);
153 @Produces(MediaType.TEXT_HTML)
154 @RestDoc(methodDescription = "@return the HTML fragment (DIV-container) to be embedded in the 'Interface' part of nodetype.js ")
155 public Response getHTMLAsResponse() {
156 Viewable viewable = this.getHTML();
157 return Response.ok().header(HttpHeaders.VARY, HttpHeaders.ACCEPT).entity(viewable).build();
161 * called by getHTMLAsResponse
163 public abstract Viewable getHTML();
168 * In case the element already exists, we return "CONFLICT"
171 @Consumes({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
172 public Response addNewElement(EntityT entity) {
173 if (entity == null) {
174 return Response.status(Status.BAD_REQUEST).entity("a valid XML/JSON element has to be posted").build();
176 if (this.alreadyContains(entity)) {
177 // we do not replace the element, but replace it
178 return Response.status(Status.CONFLICT).build();
180 this.list.add(entity);
181 return CollectionsHelper.persist(this.res, this, entity);
185 public abstract String getId(EntityT entity);
188 * Checks for containment of e in the list. <code>equals</code> is not used
189 * as most EntityT do not offer a valid implementation
191 * @return true if list already contains e.
193 public boolean alreadyContains(EntityT e) {
194 String id = this.getId(e);
195 for (EntityT el : this.list) {
196 if (this.getId(el).equals(id)) {
198 // we found an equal list item
202 // all items checked: nothing equal contained