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 { private Map dataMap = new ConcurrentHashMap<>(); protected final Class classReference; public RestDataAccess(final Class 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> consumer = vertx.eventBus() .consumer(busAddress); consumer.handler(this::handleMessage); return busAddress; } public Collection 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> request) { try { RestDataRequest 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> request) { request.reply(new ArrayList<>(list())); } private void handleGet(Message> request, String id) { T data = get(id); if (data == null) { request.fail(404, "Not found"); } else { request.reply(data); } } private void handleAdd(Message> request, T data) { if (data == null) { request.fail(400, "No data provided"); } else { add(data); request.reply(data.getId()); } } private void handleUpdate(Message> 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> 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(); } }