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_XML, MediaType.APPLICATION_JSON})
    public default void create(E content) {
        try {
            getRepository().create(content);
        }
        finally {
            close();
        }
    }

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

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

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

    @DELETE
    @Path("{id}")
    public default void remove(@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;
        });
    }
}

@@ -94,80 +94,8 @@
 st;%0A
-import java.util.function.Consumer;%0Aimport java.util.function.Function;%0A
 impo
@@ -341,42 +341,8 @@
 ype;
-%0Aimport javax.ws.rs.core.Response;
 %0A%0A/*
@@ -1189,24 +1189,17 @@
 default 
-Response
+E
  find(@P
@@ -1205,36 +1205,34 @@
 PathParam(%22id%22) 
-Stri
+Lo
 ng id) %7B%0A       
@@ -1261,122 +1261,31 @@
 urn 
-doWithID(id, (idLong) -%3E %7B%0A                return Response.ok(getRepository().find(idLong)).build();%0A            %7D
+getRepository().find(id
 );%0A 
@@ -1672,20 +1672,18 @@
 m(%22id%22) 
-Stri
+Lo
 ng id) %7B
@@ -1701,51 +1701,8 @@
 y %7B%0A
-            doWithID(id, (idLong) -%3E %7B%0A    
     
@@ -1738,28 +1738,8 @@
 e(id
-Long);%0A            %7D
 );%0A 
@@ -1855,641 +1855,7 @@
 ) %7B%7D
-%0A%0A    // TODO: change to private in Java 9%0A    public default Response doWithID(String id, Function%3CLong, Response%3E function) %7B%0A        long idLong;%0A        try %7B%0A            idLong = Long.parseLong(id);%0A        %7D catch (NumberFormatException e) %7B%0A            return Response.status(Response.Status.BAD_REQUEST).entity(%22id must be a Number%22).build();%0A        %7D%0A%0A        return function.apply(idLong);%0A    %7D%0A%0A    // TODO: change to private in Java 9%0A    public default void doWithID(String id, Consumer%3CLong%3E consumer) %7B%0A        doWithID(id, (idLong) -%3E %7B%0A            consumer.accept(idLong);%0A            return null;%0A        %7D);%0A    %7D
 %0A%7D%0A

Remove doWithID