summaryrefslogtreecommitdiffstats
path: root/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityResource.java
blob: 361fcfb02a0692433792c71d43e28b291a83e6c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*******************************************************************************
 * Copyright (c) 2012-2013,2015 University of Stuttgart.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and the Apache License 2.0 which both accompany this distribution,
 * and are available at http://www.eclipse.org/legal/epl-v10.html
 * and http://www.apache.org/licenses/LICENSE-2.0
 *
 * Contributors:
 *     Oliver Kopp - initial API and implementation
 *******************************************************************************/
package org.eclipse.winery.repository.resources._support.collections;

import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.eclipse.winery.repository.Utils;
import org.eclipse.winery.repository.backend.BackendUtils;
import org.eclipse.winery.repository.resources._support.IPersistable;

/**
 * Class to hold a single entity residing in a list of entities
 * 
 * @param <EntityT> the entity type contained in the list
 */
public abstract class EntityResource<EntityT> {
	
	// This is non-final as a "PUT" may update the object
	// it might be unnecessary to update this object as the resource is created at each request
	// We update the reference nevertheless to be safe if the resource is used in another context
	protected EntityT o;
	
	protected final int idx;
	
	protected final List<EntityT> list;
	
	protected final IPersistable res;
	
	protected IIdDetermination<EntityT> idDetermination;
	
	
	/**
	 * 
	 * @param idDetermination the object offering determination of an id of
	 *            EntityT. May be null. If null, then setIdDetermination(obj)
	 *            has to be called to enable this class functioning properly
	 * @param o the object this resource is representing
	 * @param idx the index of the object in the list
	 * @param list the list, where the object is stored in
	 * @param res the resource the object/list belongs to
	 */
	public EntityResource(IIdDetermination<EntityT> idDetermination, EntityT o, int idx, List<EntityT> list, IPersistable res) {
		this.idDetermination = idDetermination;
		this.o = o;
		this.idx = idx;
		this.list = list;
		this.res = res;
	}
	
	/**
	 * Quick hack for AbstractReqOrCapDefResource which is itself an
	 * IIdDetermination
	 */
	protected final void setIdDetermination(IIdDetermination<EntityT> idDetermination) {
		this.idDetermination = idDetermination;
	}
	
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public Response getJSON() {
		assert (this.o != null);
		return Response.ok().entity(this.o).build();
	}
	
	@GET
	@Produces(MediaType.TEXT_XML)
	@SuppressWarnings("unchecked")
	public Response getXML() {
		assert (this.o != null);
		// Utils.getXML has to be used as Jersey can only serialize XMLRootElements
		return Utils.getXML((Class<EntityT>) this.o.getClass(), this.o);
	}
	
	/**
	 * Replaces the whole entity by the given entity
	 * 
	 * As we use the hash code as index, the index changes when the resource is
	 * updated. This is not in line with REST. The alternative implementation is
	 * to use the index in the list as resource identification. That changes at
	 * each modification of the list itself (if elements are deleted / inserted
	 * before the current entry). When using the hash value, users may
	 * concurrently edit items and the list may also be updated
	 * 
	 * @return the new id.
	 */
	@PUT
	@Consumes(MediaType.TEXT_XML)
	@Produces(MediaType.TEXT_PLAIN)
	public Response setValue(EntityT o) {
		this.list.set(this.idx, o);
		this.o = o;
		return CollectionsHelper.persist(this.res, this.idDetermination, o);
	}
	
	@DELETE
	public Response onDelete() {
		try {
			this.list.remove(this.idx);
		} catch (IndexOutOfBoundsException e) {
			return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not delete entity, even if it should exist").build();
		}
		return BackendUtils.persist(this.res);
	}
	
}