Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API Entity Model and basic CRUD operations #263

Closed
wants to merge 15 commits into from
Closed
5 changes: 5 additions & 0 deletions server/wfprev-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<scope>test</scope>
</dependency>

<!-- Common Software Framework -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ AuthenticationEntryPoint authenticationEntryPoint() {
BasicAuthenticationEntryPoint result;

result = new BasicAuthenticationEntryPoint();
result.setRealmName("wfim-incidents-api");
result.setRealmName("wfprev-api");

return result;
}
Expand All @@ -60,7 +60,7 @@ public TokenService tokenServiceImpl() {

@Bean
public AuthenticationProvider authenticationProvider() {
return new WebadeOauth2AuthenticationProvider(tokenServiceImpl(), "WFIM.*");
return new WebadeOauth2AuthenticationProvider(tokenServiceImpl(), "WFPREV.*");
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@
import org.springframework.core.Ordered;
import org.springframework.web.filter.ForwardedHeaderFilter;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.vividsolutions.jts.geom.Geometry;

import ca.bc.gov.nrs.wfprev.common.serializers.GeoJsonJacksonDeserializer;
import ca.bc.gov.nrs.wfprev.common.serializers.GeoJsonJacksonSerializer;
import jakarta.servlet.DispatcherType;

@SpringBootApplication
Expand Down Expand Up @@ -45,4 +52,14 @@ public FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
}

@Bean
public ObjectMapper registerObjectMapper(){
ObjectMapper mapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(new GeoJsonJacksonSerializer());
simpleModule.addDeserializer(Geometry.class, new GeoJsonJacksonDeserializer());
mapper.registerModule(simpleModule);
return mapper;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
@Data
@EqualsAndHashCode(callSuper = false)
public abstract class CommonModel<T extends RepresentationModel<? extends T>> extends RepresentationModel<T> implements Serializable {
private Integer revisionCount;
private String createUser;
private Date createDate;
private String updateUser;
private Date updateDate;
public String eTag() {
return ETag.generate(this);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ca.bc.gov.nrs.wfprev.common.enums;

public class CodeTables {
public static final String FOREST_AREA_CODE = "forestAreaCodes";
public static final String GENERAL_SCOPE_CODE = "generalScopeCodes";
public static final String PROJECT_TYPE_CODE = "projectTypeCodes";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package ca.bc.gov.nrs.wfprev.common.serializers;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.geojson.GeoJsonReader;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

@Slf4j
public class GeoJsonJacksonDeserializer extends StdDeserializer<Geometry> {

public GeoJsonJacksonDeserializer() {
super(Geometry.class);
}

public Geometry deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
log.trace("<deserialize");
Geometry result = null;
ObjectCodec oc = jsonParser.getCodec();
JsonNode node = (JsonNode)oc.readTree(jsonParser);
String geoJson = node.toString();
GeoJsonReader geoJsonReader = new GeoJsonReader();

try {
Reader reader = new StringReader(geoJson);
result = geoJsonReader.read(reader);
} catch (ParseException var9) {
log.error("Failed to deserialize geojson: " + geoJson, var9);
throw new IOException("Failed to deserialize geojson: " + geoJson, var9);
} catch (RuntimeException var10) {
log.error("Failed to deserialize geojson: " + geoJson, var10);
}

log.trace(">deserialize " + result);
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package ca.bc.gov.nrs.wfprev.common.serializers;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.geojson.GeoJsonWriter;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.StringWriter;

@Slf4j
public class GeoJsonJacksonSerializer extends StdSerializer<Geometry> {

public GeoJsonJacksonSerializer() {
super(Geometry.class);
}

public void serialize(Geometry geometry, JsonGenerator generator, SerializerProvider provider) throws IOException, JsonProcessingException {
log.trace("<serialize");

try {
GeoJsonWriter geoJsonWriter = new GeoJsonWriter();
StringWriter writer = new StringWriter();
geoJsonWriter.write(geometry, writer);
String json = writer.toString();
generator.writeRawValue(json);
} catch (RuntimeException var7) {
log.error("Failed to serialize Geometry: " + geometry, var7);
}

log.trace(">serialize");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package ca.bc.gov.nrs.wfprev.controllers;

import org.springframework.hateoas.CollectionModel;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import ca.bc.gov.nrs.common.wfone.rest.resource.HeaderConstants;
import ca.bc.gov.nrs.common.wfone.rest.resource.MessageListRsrc;
import ca.bc.gov.nrs.wfone.common.service.api.ServiceException;
import ca.bc.gov.nrs.wfprev.common.controllers.CommonController;
import ca.bc.gov.nrs.wfprev.common.entities.CommonModel;
import ca.bc.gov.nrs.wfprev.common.enums.CodeTables;
import ca.bc.gov.nrs.wfprev.services.CodesService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.extensions.Extension;
import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import lombok.extern.slf4j.Slf4j;

@RestController
@Slf4j
@RequestMapping(value="/codes")
public class CodesController extends CommonController {
private CodesService codesService;

public CodesController(CodesService codesService) {
super(CodesController.class.getName());
this.codesService = codesService;
}

@GetMapping("/{codeTable}")
@Operation(summary = "Fetch all Forest Area Code Resources",
description = "Fetch all Forest Area Code Resources",
security = @SecurityRequirement(name = "Webade-OAUTH2",
scopes = { "WFPREV" }),
extensions = { @Extension(properties = { @ExtensionProperty(name = "auth-type", value = "#{wso2.x-auth-type.app_and_app_user}"), @ExtensionProperty(name = "throttling-tier", value = "Unlimited") }) })
@ApiResponses(value = { @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CollectionModel.class))), @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(schema = @Schema(implementation = MessageListRsrc.class))), @ApiResponse(responseCode = "403", description = "Forbidden"), @ApiResponse(responseCode = "404", description = "Not Found"), @ApiResponse(responseCode = "409", description = "Conflict"), @ApiResponse(responseCode = "412", description = "Precondition Failed"), @ApiResponse(responseCode = "500", description = "Internal Server Error", content = @Content(schema = @Schema(implementation = MessageListRsrc.class))) })
@Parameters({ @Parameter(name = HeaderConstants.VERSION_HEADER, description = HeaderConstants.VERSION_HEADER_DESCRIPTION, required = false, schema = @Schema(implementation = Integer.class), in = ParameterIn.HEADER), @Parameter(name = HeaderConstants.IF_MATCH_HEADER, description = HeaderConstants.IF_MATCH_DESCRIPTION, required = true, schema = @Schema(implementation = String.class), in = ParameterIn.HEADER) })
public ResponseEntity getCodes(@PathVariable("codeTable") String codeTable) {
log.debug(" >> getCodes");
ResponseEntity response;

try {
switch(codeTable) {
case CodeTables.FOREST_AREA_CODE -> {
response = ok(codesService.getAllForestAreaCodes());
}
case CodeTables.GENERAL_SCOPE_CODE -> {
response = ok(codesService.getAllGeneralScopeCodes());
}
case CodeTables.PROJECT_TYPE_CODE -> {
response = ok(codesService.getAllProjectTypeCodes());
}
default -> {
response = internalServerError();
}
}

} catch (ServiceException e) {
response = internalServerError();
log.error(" ### Error while fetching codes", e);
}

log.debug(" << getCodes");
return response;
}

@GetMapping("/{codeTable}/{id}")
@Operation(summary = "Fetch a Code Resource",
description = "Fetch a Code Resource",
security = @SecurityRequirement(name = "Webade-OAUTH2",
scopes = { "WFPREV" }),
extensions = { @Extension(properties = { @ExtensionProperty(name = "auth-type", value = "#{wso2.x-auth-type.app_and_app_user}"), @ExtensionProperty(name = "throttling-tier", value = "Unlimited") }) })
@ApiResponses(value = { @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CollectionModel.class))), @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(schema = @Schema(implementation = MessageListRsrc.class))), @ApiResponse(responseCode = "403", description = "Forbidden"), @ApiResponse(responseCode = "404", description = "Not Found"), @ApiResponse(responseCode = "409", description = "Conflict"), @ApiResponse(responseCode = "412", description = "Precondition Failed"), @ApiResponse(responseCode = "500", description = "Internal Server Error", content = @Content(schema = @Schema(implementation = MessageListRsrc.class))) })
@Parameters({ @Parameter(name = HeaderConstants.VERSION_HEADER, description = HeaderConstants.VERSION_HEADER_DESCRIPTION, required = false, schema = @Schema(implementation = Integer.class), in = ParameterIn.HEADER), @Parameter(name = HeaderConstants.IF_MATCH_HEADER, description = HeaderConstants.IF_MATCH_DESCRIPTION, required = true, schema = @Schema(implementation = String.class), in = ParameterIn.HEADER) })
public ResponseEntity getCodeById(@PathVariable("codeTable") String codeTable, @PathVariable("id") String id) {
log.debug(" >> getCodeById");
CommonModel resource;
ResponseEntity response;

try {
switch(codeTable) {
case CodeTables.FOREST_AREA_CODE -> {
resource = codesService.getForestAreaCodeById(id);
}
case CodeTables.GENERAL_SCOPE_CODE -> {
resource = codesService.getGeneralScopeCodeById(id);
}
case CodeTables.PROJECT_TYPE_CODE -> {
resource = codesService.getProjectTypeCodeById(id);
}
default -> {
resource = null;
}
}

response = resource == null ? notFound() : ok(resource);
} catch (ServiceException e) {
response = internalServerError();
log.error(" ### Error while fetching code", e);
}

log.debug(" << getCodeById");
return response;
}
}
Loading
Loading