Add winery source code
[vfc/nfvo/wfengine.git] / winery / org.eclipse.winery.repository / src / main / java / org / eclipse / winery / repository / resources / _support / collections / EntityResource.java
1 /*******************************************************************************
2  * Copyright (c) 2012-2013,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
8  *
9  * Contributors:
10  *     Oliver Kopp - initial API and implementation
11  *******************************************************************************/
12 package org.eclipse.winery.repository.resources._support.collections;
13
14 import java.util.List;
15
16 import javax.ws.rs.Consumes;
17 import javax.ws.rs.DELETE;
18 import javax.ws.rs.GET;
19 import javax.ws.rs.PUT;
20 import javax.ws.rs.Produces;
21 import javax.ws.rs.core.MediaType;
22 import javax.ws.rs.core.Response;
23 import javax.ws.rs.core.Response.Status;
24
25 import org.eclipse.winery.repository.Utils;
26 import org.eclipse.winery.repository.backend.BackendUtils;
27 import org.eclipse.winery.repository.resources._support.IPersistable;
28
29 /**
30  * Class to hold a single entity residing in a list of entities
31  * 
32  * @param <EntityT> the entity type contained in the list
33  */
34 public abstract class EntityResource<EntityT> {
35         
36         // This is non-final as a "PUT" may update the object
37         // it might be unnecessary to update this object as the resource is created at each request
38         // We update the reference nevertheless to be safe if the resource is used in another context
39         protected EntityT o;
40         
41         protected final int idx;
42         
43         protected final List<EntityT> list;
44         
45         protected final IPersistable res;
46         
47         protected IIdDetermination<EntityT> idDetermination;
48         
49         
50         /**
51          * 
52          * @param idDetermination the object offering determination of an id of
53          *            EntityT. May be null. If null, then setIdDetermination(obj)
54          *            has to be called to enable this class functioning properly
55          * @param o the object this resource is representing
56          * @param idx the index of the object in the list
57          * @param list the list, where the object is stored in
58          * @param res the resource the object/list belongs to
59          */
60         public EntityResource(IIdDetermination<EntityT> idDetermination, EntityT o, int idx, List<EntityT> list, IPersistable res) {
61                 this.idDetermination = idDetermination;
62                 this.o = o;
63                 this.idx = idx;
64                 this.list = list;
65                 this.res = res;
66         }
67         
68         /**
69          * Quick hack for AbstractReqOrCapDefResource which is itself an
70          * IIdDetermination
71          */
72         protected final void setIdDetermination(IIdDetermination<EntityT> idDetermination) {
73                 this.idDetermination = idDetermination;
74         }
75         
76         @GET
77         @Produces(MediaType.APPLICATION_JSON)
78         public Response getJSON() {
79                 assert (this.o != null);
80                 return Response.ok().entity(this.o).build();
81         }
82         
83         @GET
84         @Produces(MediaType.TEXT_XML)
85         @SuppressWarnings("unchecked")
86         public Response getXML() {
87                 assert (this.o != null);
88                 // Utils.getXML has to be used as Jersey can only serialize XMLRootElements
89                 return Utils.getXML((Class<EntityT>) this.o.getClass(), this.o);
90         }
91         
92         /**
93          * Replaces the whole entity by the given entity
94          * 
95          * As we use the hash code as index, the index changes when the resource is
96          * updated. This is not in line with REST. The alternative implementation is
97          * to use the index in the list as resource identification. That changes at
98          * each modification of the list itself (if elements are deleted / inserted
99          * before the current entry). When using the hash value, users may
100          * concurrently edit items and the list may also be updated
101          * 
102          * @return the new id.
103          */
104         @PUT
105         @Consumes(MediaType.TEXT_XML)
106         @Produces(MediaType.TEXT_PLAIN)
107         public Response setValue(EntityT o) {
108                 this.list.set(this.idx, o);
109                 this.o = o;
110                 return CollectionsHelper.persist(this.res, this.idDetermination, o);
111         }
112         
113         @DELETE
114         public Response onDelete() {
115                 try {
116                         this.list.remove(this.idx);
117                 } catch (IndexOutOfBoundsException e) {
118                         return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not delete entity, even if it should exist").build();
119                 }
120                 return BackendUtils.persist(this.res);
121         }
122         
123 }