001package org.maxur.perfmodel.backend.rest.resources;
002
003
004import org.jsondoc.core.annotation.*;
005import org.jsondoc.core.pojo.ApiVerb;
006import org.maxur.perfmodel.backend.domain.ConflictException;
007import org.maxur.perfmodel.backend.domain.Project;
008import org.maxur.perfmodel.backend.domain.Repository;
009import org.maxur.perfmodel.backend.rest.dto.ProjectDto;
010import org.slf4j.Logger;
011import org.slf4j.LoggerFactory;
012
013import javax.inject.Inject;
014import javax.ws.rs.*;
015import javax.ws.rs.core.MediaType;
016import javax.ws.rs.core.Response;
017import java.util.Collection;
018import java.util.Optional;
019
020import static com.google.common.base.Strings.isNullOrEmpty;
021import static java.lang.String.format;
022import static org.maxur.perfmodel.backend.rest.WebException.*;
023import static org.maxur.perfmodel.backend.rest.dto.ProjectDto.dto;
024import static org.maxur.perfmodel.backend.rest.dto.ProjectDto.dtoList;
025
026
027/**
028 * @author Maxim Yunusov
029 * @version 1.0 01.09.13
030 */
031@Path("/{a:project}")
032@Api(name = "Project Resource", description = "Methods for managing Project")
033@ApiVersion(since = "1.0")
034public class ProjectResource {
035
036    private static final String PROJECT_IS_NOT_SAVED = "Project is not saved";
037
038    private static final Logger LOGGER = LoggerFactory.getLogger(ProjectResource.class);
039
040    @Inject
041    private Repository<Project> repository;
042
043    @GET
044    @Produces(MediaType.APPLICATION_JSON)
045    @ApiMethod(
046            path = "/project",
047            verb = ApiVerb.GET,
048            description = "Gets all projects",
049            produces = { MediaType.APPLICATION_JSON },
050            responsestatuscode = "200 - OK"
051    )
052    @ApiErrors(apierrors={
053            @ApiError(code="500", description="Application critical error")
054    })
055    @ApiResponseObject
056    public Collection<ProjectDto> findAll() {
057        return dtoList(repository.findAll());
058    }
059
060    @GET
061    @Path("/{id}")
062    @Produces(MediaType.APPLICATION_JSON)
063    @ApiMethod(
064            path = "/project/{id}",
065            verb = ApiVerb.GET,
066            description = "Get the project by it's identifier",
067            produces = { MediaType.APPLICATION_JSON },
068            responsestatuscode = "200 - OK"
069    )
070    @ApiErrors(apierrors={
071            @ApiError(code="400", description="Bad request"),
072            @ApiError(code="404", description="Project not found"),
073            @ApiError(code="500", description="Application critical error")
074    })
075    @ApiResponseObject
076    public ProjectDto load(
077            @ApiPathParam(name = "id", description = "The project identifier")
078            @PathParam("id") String id
079    ) {
080        checkIdIsNotNull(id);
081        final Optional<Project> result = repository.get(id);
082        checkResult(id, result);
083        return dto(result.get());
084    }
085
086    @DELETE
087    @Path("/{id}")
088    @Produces(MediaType.APPLICATION_JSON)
089    @ApiMethod(
090            path = "/project/{id}",
091            verb = ApiVerb.DELETE,
092            description = "Delete the project by it's identifier",
093            produces = { MediaType.APPLICATION_JSON },
094            responsestatuscode = "200 - OK"
095    )
096    @ApiErrors(apierrors={
097            @ApiError(code="400", description="Bad request"),
098            @ApiError(code="404", description="Project not found"),
099            @ApiError(code="500", description="Application critical error")
100    })
101    @ApiResponseObject
102    public ProjectDto delete(
103            @ApiPathParam(name = "id", description = "The project identifier")
104            @PathParam("id") String id
105    ) {
106        checkIdIsNotNull(id);
107        final Optional<Project> result = repository.remove(id);
108        checkResult(id, result);
109        return dto(result.get());
110    }
111
112    @POST
113    @Consumes(MediaType.APPLICATION_JSON)
114    @Produces(MediaType.APPLICATION_JSON)
115    @ApiMethod(
116            path = "/project",
117            verb = ApiVerb.POST,
118            description = "Create new project version by project's identifier",
119            produces = { MediaType.APPLICATION_JSON },
120            consumes = { MediaType.APPLICATION_JSON },
121            responsestatuscode = "201 - Created"
122    )
123    @ApiErrors(apierrors={
124            @ApiError(code="400", description="Bad request"),
125            @ApiError(code="404", description="Project not found"),
126            @ApiError(code="500", description="Application critical error")
127    })
128    @ApiResponseObject
129    public Response create(
130            @ApiBodyObject final ProjectDto dto
131    ) {
132        try {
133            final Project project = dto.assemble();
134            checkIdIsNotNull(dto.getId());
135            final Optional<Project> result = repository.add(project);
136            return created(result.get());
137        } catch (NumberFormatException e) {
138            LOGGER.error(PROJECT_IS_NOT_SAVED, e);
139            throw badRequestException(PROJECT_IS_NOT_SAVED, e.getMessage());
140        } catch (ConflictException e) {
141            LOGGER.error(format("%s: %s", PROJECT_IS_NOT_SAVED, e.getMessage()));
142            throw conflictException(PROJECT_IS_NOT_SAVED, e.getMessage());
143        }
144    }
145
146    @PUT
147    @Path("/{id}")
148    @Consumes(MediaType.APPLICATION_JSON)
149    @Produces(MediaType.APPLICATION_JSON)
150    @ApiMethod(
151            path = "/project/{id}",
152            verb = ApiVerb.PUT,
153            description = "Create new project version by project's identifier",
154            produces = { MediaType.APPLICATION_JSON },
155            consumes = { MediaType.APPLICATION_JSON },
156            responsestatuscode = "200 - OK"
157    )
158    @ApiErrors(apierrors={
159            @ApiError(code="400", description="Bad request"),
160            @ApiError(code="404", description="Project not found"),
161            @ApiError(code="500", description="Application critical error")
162    })
163    @ApiResponseObject
164    public ProjectDto update(
165            @ApiPathParam(name = "id", description = "The project identifier")
166            @PathParam("id") String id,
167            @ApiBodyObject final ProjectDto dto
168    ) {
169        try {
170            checkIdIsNotNull(id);
171            final Project project = dto.assemble();
172            final Optional<Project> result = repository.amend(project);
173            checkResult(id, result);
174            return dto(result.get());
175        } catch (NumberFormatException e) {
176            LOGGER.error(PROJECT_IS_NOT_SAVED, e);
177            throw badRequestException(PROJECT_IS_NOT_SAVED, e.getMessage());
178        } catch (ConflictException e) {
179            LOGGER.error(format("%s: %s", PROJECT_IS_NOT_SAVED, e.getMessage()));
180            throw conflictException(PROJECT_IS_NOT_SAVED, e.getMessage());
181        }
182    }
183
184    private Response created(final Project result) {
185        return Response.status(Response.Status.CREATED).entity(dto(result)).build();
186    }
187
188    private void checkIdIsNotNull(final String id) {
189        if (isNullOrEmpty(id)) {
190            final String msg = "Bad get request. 'Id' must not be null";
191            LOGGER.error(msg);
192            throw notFoundException(msg);
193        }
194    }
195
196    private void checkResult(final String id, final Optional<Project> result) {
197        if (!result.isPresent()) {
198            final String msg = format("Project '%s' is not founded", id);
199            LOGGER.error(msg);
200            throw notFoundException(msg);
201        }
202    }
203
204}