// Path: src/main/java/com/edwise/completespring/assemblers/BookResource.java
// @Getter
// @Setter
// @Accessors(chain = true)
// public class BookResource extends ResourceSupport {
//     private Book book;
// }
// 
// Path: src/main/java/com/edwise/completespring/assemblers/BookResourceAssembler.java
// @Component
// public class BookResourceAssembler extends ResourceAssemblerSupport<Book, BookResource> {
// 
//     public BookResourceAssembler() {
//         super(BookController.class, BookResource.class);
//     }
// 
//     @Override
//     protected BookResource instantiateResource(Book book) {
//         BookResource bookResource = super.instantiateResource(book);
//         bookResource.setBook(book);
// 
//         return bookResource;
//     }
// 
//     public BookResource toResource(Book book) {
//         return createResourceWithId(book.getId(), book);
//     }
// }
// 
// Path: src/main/java/com/edwise/completespring/entities/Book.java
// @Document(collection = "books")
// @ApiModel(value = "Book entity", description = "Complete info of a entity book")
// @Data
// @Accessors(chain = true)
// @EqualsAndHashCode(exclude = {"id"}, doNotUseGetters = true)
// @ToString(doNotUseGetters = true)
// public class Book {
// 
//     @ApiModelProperty(value = "The id of the book")
//     @Id
//     private Long id;
// 
//     @ApiModelProperty(value = "The title of the book", required = true)
//     @NotEmpty
//     private String title;
// 
//     @ApiModelProperty(value = "The authors of the book", required = true)
//     @Valid
//     private List<Author> authors;
// 
//     @ApiModelProperty(value = "The isbn of the book", required = true)
//     @NotEmpty
//     private String isbn;
// 
//     @ApiModelProperty(value = "The release date of the book", required = true, dataType = "LocalDate")
//     @NotNull
//     private LocalDate releaseDate;
// 
//     @ApiModelProperty(value = "The publisher of the book", required = true)
//     @Valid
//     @NotNull
//     private Publisher publisher;
// 
//     public Book copyFrom(Book other) {
//         this.title = other.title;
//         if (other.authors != null) {
//             this.authors = new ArrayList<>();
//             this.authors.addAll(other.authors.stream().map(new Author()::copyFrom).collect(Collectors.toList()));
//         }
//         this.isbn = other.isbn;
//         this.releaseDate = other.releaseDate;
//         if (other.publisher != null) {
//             this.publisher = new Publisher().copyFrom(other.publisher);
//         }
// 
//         return this;
//     }
// }
// 
// Path: src/main/java/com/edwise/completespring/exceptions/InvalidRequestException.java
// public class InvalidRequestException extends RuntimeException {
// 
//     @Getter
//     private final ErrorInfo errors;
// 
//     public InvalidRequestException(BindingResult bindingResultErrors) {
//         super(bindingResultErrors.toString());
//         this.errors = ErrorInfo.generateErrorInfoFromBindingResult(bindingResultErrors);
//     }
// 
// }
// 
// Path: src/main/java/com/edwise/completespring/services/BookService.java
// public interface BookService extends Service<Book, Long> {
// 
//     List<Book> findByTitle(String title);
// 
//     List<Book> findByReleaseDate(LocalDate releaseDate);
// 
//     Book create(Book book);
// }


import com.edwise.completespring.assemblers.BookResource;
import com.edwise.completespring.assemblers.BookResourceAssembler;
import com.edwise.completespring.entities.Book;
import com.edwise.completespring.exceptions.InvalidRequestException;
import com.edwise.completespring.services.BookService;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.Link;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.net.URI;
import java.util.List;
    })
    public ResponseEntity<List<BookResource>> getAll() {
        List<Book> books = bookService.findAll();
        List<BookResource> resourceList = bookResourceAssembler.toResources(books);

        log.info("Books found: {}", books);
        return new ResponseEntity<>(resourceList, HttpStatus.OK);
    }

    @RequestMapping(method = RequestMethod.GET, value = "{id}", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "Get one Book", response = BookResource.class, notes = "Returns one book")
    @ApiResponses({
            @ApiResponse(code = RESPONSE_CODE_OK, message = "Exists this book")
    })
    public ResponseEntity<BookResource> getBook(@ApiParam(defaultValue = "1", value = "The id of the book to return")
                                                @PathVariable long id) {
        Book book = bookService.findOne(id);

        log.info("Book found: {}", book);
        return new ResponseEntity<>(bookResourceAssembler.toResource(book), HttpStatus.OK);
    }

    @RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE,
            consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "Create Book", notes = "Create a book")
    @ApiResponses({
            @ApiResponse(code = RESPONSE_CODE_CREATED, message = "Successful create of a book")
    })
    public ResponseEntity<BookResource> createBook(@Valid @RequestBody Book book, BindingResult errors) {
        if (errors.hasErrors()) {
// Path: src/main/java/com/edwise/completespring/assemblers/BookResource.java
// @Getter
// @Setter
// @Accessors(chain = true)
// public class BookResource extends ResourceSupport {
//     private Book book;
// }
// 
// Path: src/main/java/com/edwise/completespring/assemblers/BookResourceAssembler.java
// @Component
// public class BookResourceAssembler extends ResourceAssemblerSupport<Book, BookResource> {
// 
//     public BookResourceAssembler() {
//         super(BookController.class, BookResource.class);
//     }
// 
//     @Override
//     protected BookResource instantiateResource(Book book) {
//         BookResource bookResource = super.instantiateResource(book);
//         bookResource.setBook(book);
// 
//         return bookResource;
//     }
// 
//     public BookResource toResource(Book book) {
//         return createResourceWithId(book.getId(), book);
//     }
// }
// 
// Path: src/main/java/com/edwise/completespring/entities/Book.java
// @Document(collection = "books")
// @ApiModel(value = "Book entity", description = "Complete info of a entity book")
// @Data
// @Accessors(chain = true)
// @EqualsAndHashCode(exclude = {"id"}, doNotUseGetters = true)
// @ToString(doNotUseGetters = true)
// public class Book {
// 
//     @ApiModelProperty(value = "The id of the book")
//     @Id
//     private Long id;
// 
//     @ApiModelProperty(value = "The title of the book", required = true)
//     @NotEmpty
//     private String title;
// 
//     @ApiModelProperty(value = "The authors of the book", required = true)
//     @Valid
//     private List<Author> authors;
// 
//     @ApiModelProperty(value = "The isbn of the book", required = true)
//     @NotEmpty
//     private String isbn;
// 
//     @ApiModelProperty(value = "The release date of the book", required = true, dataType = "LocalDate")
//     @NotNull
//     private LocalDate releaseDate;
// 
//     @ApiModelProperty(value = "The publisher of the book", required = true)
//     @Valid
//     @NotNull
//     private Publisher publisher;
// 
//     public Book copyFrom(Book other) {
//         this.title = other.title;
//         if (other.authors != null) {
//             this.authors = new ArrayList<>();
//             this.authors.addAll(other.authors.stream().map(new Author()::copyFrom).collect(Collectors.toList()));
//         }
//         this.isbn = other.isbn;
//         this.releaseDate = other.releaseDate;
//         if (other.publisher != null) {
//             this.publisher = new Publisher().copyFrom(other.publisher);
//         }
// 
//         return this;
//     }
// }
// 
// Path: src/main/java/com/edwise/completespring/exceptions/InvalidRequestException.java
// public class InvalidRequestException extends RuntimeException {
// 
//     @Getter
//     private final ErrorInfo errors;
// 
//     public InvalidRequestException(BindingResult bindingResultErrors) {
//         super(bindingResultErrors.toString());
//         this.errors = ErrorInfo.generateErrorInfoFromBindingResult(bindingResultErrors);
//     }
// 
// }
// 
// Path: src/main/java/com/edwise/completespring/services/BookService.java
// public interface BookService extends Service<Book, Long> {
// 
//     List<Book> findByTitle(String title);
// 
//     List<Book> findByReleaseDate(LocalDate releaseDate);
// 
//     Book create(Book book);
// }


// Path: src/main/java/com/edwise/completespring/controllers/BookController.java
import com.edwise.completespring.assemblers.BookResource;
import com.edwise.completespring.assemblers.BookResourceAssembler;
import com.edwise.completespring.entities.Book;
import com.edwise.completespring.exceptions.InvalidRequestException;
import com.edwise.completespring.services.BookService;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.Link;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.net.URI;
import java.util.List;

    })
    public ResponseEntity<List<BookResource>> getAll() {
        List<Book> books = bookService.findAll();
        List<BookResource> resourceList = bookResourceAssembler.toResources(books);

        log.info("Books found: {}", books);
        return new ResponseEntity<>(resourceList, HttpStatus.OK);
    }

    @RequestMapping(method = RequestMethod.GET, value = "{id}", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "Get one Book", response = BookResource.class, notes = "Returns one book")
    @ApiResponses({
            @ApiResponse(code = RESPONSE_CODE_OK, message = "Exists this book")
    })
    public ResponseEntity<BookResource> getBook(@ApiParam(defaultValue = "1", value = "The id of the book to return")
                                                @PathVariable long id) {
        Book book = bookService.findOne(id);

        log.info("Book found: {}", book);
        return new ResponseEntity<>(bookResourceAssembler.toResource(book), HttpStatus.OK);
    }

    @RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE,
            consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "Create Book", notes = "Create a book")
    @ApiResponses({
            @ApiResponse(code = RESPONSE_CODE_CREATED, message = "Successful create of a book")
    })
    public ResponseEntity<BookResource> createBook(@Valid @RequestBody Book book, BindingResult errors) {
        if (errors.hasErrors()) {
            throw new InvalidRequestException(errors);