196 lines
5.7 KiB
Java
196 lines
5.7 KiB
Java
package de.pzzz.vertx;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.Map;
|
|
import java.util.UUID;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
import io.vertx.core.Vertx;
|
|
import io.vertx.core.eventbus.Message;
|
|
import io.vertx.core.eventbus.MessageConsumer;
|
|
import io.vertx.core.json.Json;
|
|
import io.vertx.ext.web.Router;
|
|
import io.vertx.ext.web.RoutingContext;
|
|
|
|
public class RestDataAccess<T extends SerializableWithId> {
|
|
private Map<String, T> dataMap = new ConcurrentHashMap<>();
|
|
protected final Class<T> classReference;
|
|
|
|
public RestDataAccess(final Class<T> classReference) {
|
|
this.classReference = classReference;
|
|
}
|
|
|
|
public void registerRoutes(final Router router, final String baseUrl) {
|
|
router.get(baseUrl).handler(this::list);
|
|
router.post(baseUrl).handler(this::add);
|
|
router.get(baseUrl + "/:id").handler(this::get);
|
|
router.put(baseUrl + "/:id").handler(this::update);
|
|
router.delete(baseUrl + "/:id").handler(this::delete);
|
|
}
|
|
|
|
/**
|
|
* Returns bus address.
|
|
*
|
|
* @param vertx
|
|
* @return
|
|
*/
|
|
public String setupConsumer(final Vertx vertx) {
|
|
final String busAddress = this.getClass().getName() + "." + UUID.randomUUID();
|
|
MessageConsumer<RestDataRequest<T>> consumer = vertx.eventBus()
|
|
.consumer(busAddress);
|
|
consumer.handler(this::handleMessage);
|
|
return busAddress;
|
|
}
|
|
|
|
public Collection<T> list() {
|
|
return dataMap.values();
|
|
}
|
|
|
|
public T get(final String id) {
|
|
return dataMap.get(id);
|
|
}
|
|
|
|
public boolean contains(final String id) {
|
|
return dataMap.containsKey(id);
|
|
}
|
|
|
|
public void add(final T data) {
|
|
dataMap.put(data.getId(), data);
|
|
}
|
|
|
|
public void update(final T newData) {
|
|
dataMap.put(newData.getId(), newData);
|
|
}
|
|
|
|
public void delete(final String id) {
|
|
dataMap.remove(id);
|
|
}
|
|
|
|
protected void update(final String id, final RoutingContext context) {
|
|
T newData = context.body().asPojo(classReference);
|
|
if (!newData.getId().equals(id)) {
|
|
context.fail(400);
|
|
}
|
|
update(newData);
|
|
}
|
|
|
|
protected T getDataFromRequest(final RoutingContext context) {
|
|
return context.body().asPojo(classReference);
|
|
}private void handleMessage(final Message<RestDataRequest<T>> request) {
|
|
try {
|
|
RestDataRequest<T> req = request.body();
|
|
switch (req.getCommand()) {
|
|
case LIST -> handleList(request);
|
|
case GET -> handleGet(request, req.getId());
|
|
case ADD -> handleAdd(request, req.getData());
|
|
case UPDATE -> handleUpdate(request, req.getData());
|
|
case DELETE -> handleDelete(request, req.getId());
|
|
default -> request.fail(500, "Unsupported request type");
|
|
}
|
|
} catch (Exception e) {
|
|
request.fail(500, "Internal server error: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
private void handleList(Message<RestDataRequest<T>> request) {
|
|
request.reply(new ArrayList<>(list()));
|
|
}
|
|
|
|
private void handleGet(Message<RestDataRequest<T>> request, String id) {
|
|
T data = get(id);
|
|
if (data == null) {
|
|
request.fail(404, "Not found");
|
|
} else {
|
|
request.reply(data);
|
|
}
|
|
}
|
|
|
|
private void handleAdd(Message<RestDataRequest<T>> request, T data) {
|
|
if (data == null) {
|
|
request.fail(400, "No data provided");
|
|
} else {
|
|
add(data);
|
|
request.reply(data.getId());
|
|
}
|
|
}
|
|
|
|
private void handleUpdate(Message<RestDataRequest<T>> request, T data) {
|
|
if (data == null || !contains(data.getId())) {
|
|
request.fail(400, "Invalid data or ID not found");
|
|
} else {
|
|
update(data);
|
|
request.reply(data.getId());
|
|
}
|
|
}
|
|
|
|
private void handleDelete(Message<RestDataRequest<T>> request, String id) {
|
|
if (id == null || !contains(id)) {
|
|
request.fail(404, "Not found");
|
|
} else {
|
|
delete(id);
|
|
request.reply(true);
|
|
}
|
|
}
|
|
|
|
|
|
private void list(final RoutingContext context) {
|
|
if (context.response().ended()) {
|
|
return;
|
|
}
|
|
context.response().end(Json.encodePrettily(list()));
|
|
}
|
|
|
|
private void add(final RoutingContext context) {
|
|
if (context.response().ended()) {
|
|
return;
|
|
}
|
|
T data = getDataFromRequest(context);
|
|
if (context.response().ended()) {
|
|
return;
|
|
}
|
|
add(data);
|
|
context.response().setStatusCode(201).end();
|
|
}
|
|
|
|
private void get(final RoutingContext context) {
|
|
if (context.response().ended()) {
|
|
return;
|
|
}
|
|
final String id = context.pathParam("id");
|
|
if (!dataMap.containsKey(id)) {
|
|
context.fail(404);
|
|
return;
|
|
}
|
|
context.response().end(Json.encodePrettily(get(id)));
|
|
}
|
|
|
|
private void update(final RoutingContext context) {
|
|
if (context.response().ended()) {
|
|
return;
|
|
}
|
|
final String id = context.pathParam("id");
|
|
if (!dataMap.containsKey(id)) {
|
|
context.fail(404);
|
|
return;
|
|
}
|
|
update(id, context);
|
|
if (context.response().ended()) {
|
|
return;
|
|
}
|
|
context.response().setStatusCode(204).end();
|
|
}
|
|
|
|
private void delete(final RoutingContext context) {
|
|
if (context.response().ended()) {
|
|
return;
|
|
}
|
|
final String id = context.pathParam("id");
|
|
if (!dataMap.containsKey(id)) {
|
|
context.fail(404);
|
|
return;
|
|
}
|
|
delete(id);
|
|
context.response().setStatusCode(204).end();
|
|
}
|
|
}
|