package com.github.daniel.shuy.ws.rs.jpa.crud;

import java.io.Closeable;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

/**
 * Extend this class to create a CRUD JAX-RS Repository Class.
 *
 * @param <E> The Entity Class type
 */
public interface ResourceCRUD<E extends EntityCRUD> extends Closeable {
    public abstract RepositoryCRUD<E> getRepository();

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public default void create(E content) {
        try {
            getRepository().add(content);
        }
        finally {
            close();
        }
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public default List<E> readAll() {
        try {
            return getRepository().getAll();
        }
        finally {
            close();
        }
    }

    @GET
    @Path("{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public default Response read(@PathParam("id") String id) {
        try {
            return doWithID(id, (idLong) -> {
                return Response.ok(getRepository().get(idLong)).build();
            });
        }
        finally {
            close();
        }
    }

    @PUT
    @Consumes(MediaType.APPLICATION_JSON)
    public default void update(E content) {
        try {
            getRepository().update(content);
        }
        finally {
            close();
        }
    }

    @DELETE
    @Path("{id}")
    public default void delete(@PathParam("id") String id) {
        try {
            doWithID(id, (idLong) -> {
                getRepository().remove(idLong);
            });
        }
        finally {
            close();
        }
    }

    @Override
    public default void close() {}

    // TODO: change to private in Java 9
    public default Response doWithID(String id, Function<Long, Response> function) {
        long idLong;
        try {
            idLong = Long.parseLong(id);
        } catch (NumberFormatException e) {
            return Response.status(Response.Status.BAD_REQUEST).entity("id must be a Number").build();
        }

        return function.apply(idLong);
    }

    // TODO: change to private in Java 9
    public default void doWithID(String id, Consumer<Long> consumer) {
        doWithID(id, (idLong) -> {
            consumer.accept(idLong);
            return null;
        });
    }
}

@@ -699,32 +699,60 @@
 T%0A    @Consumes(
+%7BMediaType.APPLICATION_XML, 
 MediaType.APPLIC
@@ -753,32 +753,33 @@
 APPLICATION_JSON
+%7D
 )%0A    public def
@@ -935,24 +935,63 @@
 %7D%0A%0A    @GET%0A
+    public default List%3CE%3E readAll() %7B%0A
     @Produce
@@ -984,32 +984,33 @@
 %7B%0A    @Produces(
+%7B
 MediaType.APPLIC
@@ -1019,52 +1019,41 @@
 ION_
-JSON)%0A    public default List%3CE%3E readAll() %7B
+XML, MediaType.APPLICATION_JSON%7D)
 %0A   
@@ -1205,50 +1205,8 @@
 %7D%22)%0A
-    @Produces(MediaType.APPLICATION_JSON)%0A
     
@@ -1256,32 +1256,103 @@
 %22) String id) %7B%0A
+    @Produces(%7BMediaType.APPLICATION_XML, MediaType.APPLICATION_JSON%7D)%0A
         try %7B%0A  
@@ -1567,89 +1567,118 @@
     
-@Consumes(MediaType.APPLICATION_JSON)%0A    public default void update(E content) %7B
+public default void update(E content) %7B%0A    @Produces(%7BMediaType.APPLICATION_XML, MediaType.APPLICATION_JSON%7D)
 %0A   

Add support for application/xml MediaType