add more errors and handle change

main
Julius Sula 2023-05-22 15:45:46 +02:00
parent 4a06622e62
commit a2a1368518
8 changed files with 136 additions and 83 deletions

View File

@ -12,7 +12,6 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.bmc.arsys.api.ARException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.nttdata.calender.approval.Approval;
@ -23,6 +22,8 @@ import com.nttdata.calender.changes.ChangeResponse;
import com.nttdata.calender.changes.ChangeUpdateRequest;
import com.nttdata.calender.contracts.Contract;
import com.nttdata.calender.contracts.ContractGetResponse;
import com.nttdata.calender.errorhandling.ErrorTypes.NotFoundError;
import com.nttdata.calender.errorhandling.ErrorTypes.ValidationError;
import com.nttdata.calender.implementer.Implementer;
import com.nttdata.calender.implementer.ImplementerGetRequest;
import com.nttdata.calender.implementer.ImplementerGetResponse;
@ -176,7 +177,7 @@ public class KalenderRestController {
@PostMapping("/api/getChanges")
@ResponseBody
public ChangeResponse getChanges(@RequestBody ChangeRequest request)
throws ARException {
throws ARException, NotFoundError, ValidationError {
return change.get(request);
}

View File

@ -6,11 +6,11 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.Optional;
import java.util.TimeZone;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bmc.arsys.api.ARException;
import com.bmc.arsys.api.Entry;
import com.bmc.arsys.api.Timestamp;
@ -18,7 +18,8 @@ import com.bmc.arsys.api.Value;
import com.nttdata.calender.api.Query;
import com.nttdata.calender.api.RemedyJavaAPI;
import com.nttdata.calender.changes.query.Filter;
import com.nttdata.calender.errorhandling.NotFoundError;
import com.nttdata.calender.errorhandling.ErrorTypes.NotFoundError;
import com.nttdata.calender.errorhandling.ErrorTypes.ValidationError;
/**
* Class representing the change with all of the change specific attributes.
@ -39,7 +40,6 @@ public class Change {
@Autowired
public Change(RemedyJavaAPI api) {
this.api = api;
// TODO: Contract
this.queryChange = new Query.QueryBuilder(formName)
.addFieldId("ChangeNr", 1000000182)
.addFieldId("SupportGroup", 1000000015)
@ -74,7 +74,7 @@ public class Change {
* @return a List of {@link Change} for every entry found
* @throws ARException if an error occurs during the retrieval process
*/
public ChangeResponse get(ChangeRequest request) throws ARException {
public ChangeResponse get(ChangeRequest request) throws ARException, NotFoundError, ValidationError {
api.impersonateUser("ext_StanzPa");
var peopleFullName = processPeopleInfo(request);
@ -127,7 +127,7 @@ public class Change {
return new ChangeResponse(entriesSize, changes);
}
private String processPeopleInfo(ChangeRequest request) throws ARException {
private String processPeopleInfo(ChangeRequest request) throws ARException, NotFoundError {
// Queries for SupportGroup of impersonated User
var queryPerson = new Query.QueryBuilder("CTM:Support Group Association")
.addFieldId("FullName", 1000000017)

View File

@ -2,6 +2,7 @@ package com.nttdata.calender.changes;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import com.bmc.arsys.api.ARException;
@ -9,6 +10,7 @@ import com.nttdata.calender.api.Query;
import com.nttdata.calender.api.RemedyJavaAPI;
import com.nttdata.calender.changes.query.Filter;
import com.nttdata.calender.changes.query.Sort;
import com.nttdata.calender.errorhandling.ErrorTypes.ValidationError;
/**
* Represents a change request object that stores information about slice start,
@ -113,76 +115,97 @@ public class ChangeRequest {
* invalid filter is provided.
*/
// TODO: Exception handling (unsuppoprted qualifier)
public String constructQualifier(Query query, RemedyJavaAPI api) throws ARException {
public String constructQualifier(Query query, RemedyJavaAPI api) throws ARException, ValidationError {
var qualifier = "";
for (int i = 0; i < this.filter.size(); i++) {
var column = this.filter.get(i).getColumn();
if (!column.isEmpty()) {
var inner_qualifier = "";
var current_filter = this.filter.get(i);
var column = current_filter.getColumn();
var criteria = current_filter.getCriteria();
if (column.equals("D2")) {
var startFrom = filter.get(i).getCriteria()[0];
var startTo = filter.get(i).getCriteria()[1];
String inputFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
String outputFormat = "dd/MM/yyyy";
LocalDateTime dateTimeFrom = LocalDateTime.parse(startFrom, DateTimeFormatter.ofPattern(inputFormat));
LocalDateTime dateTimeTo = LocalDateTime.parse(startTo, DateTimeFormatter.ofPattern(inputFormat));
String startFromFormatted = dateTimeFrom.format(DateTimeFormatter.ofPattern(outputFormat));
String startToFormatted = dateTimeTo.format(DateTimeFormatter.ofPattern(outputFormat));
if (!startFromFormatted.isEmpty() && !startToFormatted.isEmpty()) {
var dateColumn = api.getFieldDatabaseName(query.getFormName(), query.getFieldId(column));
// Same day changes need to startFrom=day and startTo=day+24h 60m 60s
if (startFromFormatted.equals(startToFormatted)) {
startToFormatted = "\' < (\"" + startToFormatted + "\"" + " + (24 * (60 * 60)))";
} else
startToFormatted = "\' <= \"" + startToFormatted + "\"";
qualifier += "\'" + dateColumn + "\' >= \"" + startFromFormatted + "\" AND ";
qualifier += "\'" + dateColumn + startToFormatted;
}
qualifier = "(" + qualifier + ")";
} else {
column = api.getFieldDatabaseName(query.getFormName(), query.getFieldId(column));
var inner_filter = "\'" + column + "\' ";
var criterias = filter.get(i).getCriteria();
var inner_concat = " OR ";
var inner_criteria_prefix = "";
switch (filter.get(i).getFilter()) {
case "equals":
inner_filter += "= ";
break;
case "contains":
inner_filter += "LIKE ";
inner_concat = " AND ";
inner_criteria_prefix = "%";
break;
default:
throw new ARException();
}
for (int j = 0; j < criterias.length; j++) {
criterias[j] = inner_criteria_prefix + criterias[j] + inner_criteria_prefix;
inner_qualifier += "(" + inner_filter + "\"" + criterias[j] + "\")";
if (j < criterias.length - 1) {
inner_qualifier += inner_concat;
}
}
qualifier += "(" + inner_qualifier + ")";
}
if (i < filter.size() - 1) {
qualifier += " AND ";
}
if (column.isEmpty() || criteria.length <= 0) {
throw new ValidationError("Fields inside filter empty");
}
var inner_qualifier = "";
if (column.equals("D2")) {
var dateQualifier = constructDateQualifier(current_filter, column, query, api);
qualifier = "(" + dateQualifier + ")";
} else {
column = api.getFieldDatabaseName(query.getFormName(), query.getFieldId(column));
var inner_filter = "\'" + column + "\' ";
var criterias = current_filter.getCriteria();
var inner_concat = " OR ";
var inner_criteria_prefix = "";
switch (current_filter.getFilter()) {
case "equals":
inner_filter += "= ";
break;
case "contains":
inner_filter += "LIKE ";
inner_concat = " AND ";
inner_criteria_prefix = "%";
break;
default:
throw new ARException();
}
for (int j = 0; j < criterias.length; j++) {
criterias[j] = inner_criteria_prefix + criterias[j] + inner_criteria_prefix;
inner_qualifier += "(" + inner_filter + "\"" + criterias[j] + "\")";
if (j < criterias.length - 1) {
inner_qualifier += inner_concat;
}
}
qualifier += "(" + inner_qualifier + ")";
}
if (i < filter.size() - 1) {
qualifier += " AND ";
}
}
return qualifier;
}
private String constructDateQualifier(Filter current_filter, String column, Query query, RemedyJavaAPI api)
throws ValidationError, ARException {
if (current_filter.getCriteria().length != 2) {
throw new ValidationError("Date Filter does not contain 2 date elements");
}
var startFrom = current_filter.getCriteria()[0];
var startTo = current_filter.getCriteria()[1];
var startFromFormatted = convertDate(startFrom);
var startToFormatted = convertDate(startTo);
var qualifier = "";
var dateColumn = api.getFieldDatabaseName(query.getFormName(), query.getFieldId(column));
// Same day changes need to startFrom=day and startTo=day+24h 60m 60s
if (startFromFormatted.equals(startToFormatted)) {
startToFormatted = "\' < (\"" + startToFormatted + "\"" + " + (24 * (60 * 60)))";
} else
startToFormatted = "\' <= \"" + startToFormatted + "\"";
qualifier += "\'" + dateColumn + "\' >= \"" + startFromFormatted + "\" AND ";
qualifier += "\'" + dateColumn + startToFormatted;
return qualifier;
}
private String convertDate(String date) throws ValidationError {
String inputFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
String outputFormat = "dd/MM/yyyy";
LocalDateTime parser = LocalDateTime.parse(date, DateTimeFormatter.ofPattern(inputFormat));
var parsed = "";
try {
parsed = parser.format(DateTimeFormatter.ofPattern(outputFormat));
} catch (DateTimeParseException e) {
throw new ValidationError("Provided date format cannot be parsed into Remedy specific date format");
}
return parsed;
}
}

View File

@ -4,6 +4,7 @@ import com.bmc.arsys.api.Constants;
import com.bmc.arsys.api.SortInfo;
import com.nttdata.calender.api.Query;
import com.nttdata.calender.changes.Change;
import com.nttdata.calender.errorhandling.ErrorTypes.ValidationError;
/**
* Defines the sort object needed for the retrieval of {@link Change}.
@ -58,7 +59,7 @@ public class Sort {
* the column
* @return the constructed SortInfo object
*/
public SortInfo getSortInfo(Query changeQuery) {
public SortInfo getSortInfo(Query changeQuery) throws ValidationError {
var column = changeQuery.getFieldId(this.column);
// TODO: handle default of sortOrder
int sortOrder = 0;
@ -70,6 +71,8 @@ public class Sort {
case "dsc":
sortOrder = Constants.AR_SORT_DESCENDING;
break;
default:
throw new ValidationError("Unknown sort order specified");
}
return new SortInfo(column, sortOrder);

View File

@ -1,19 +1,17 @@
package com.nttdata.calender.errorhandling;
package com.nttdata.calender.errorhandling.ErrorTypes;
import org.springframework.http.HttpStatus;
public class NotFoundError extends RuntimeException {
public abstract class BackendError extends Exception {
private int errorCode;
private HttpStatus httpStatus;
public NotFoundError(String message) {
public BackendError(String message, int errorCode, HttpStatus httpStatus) {
super(message);
this.errorCode = 404;
this.httpStatus = HttpStatus.NOT_FOUND;
this.errorCode = errorCode;
this.httpStatus = httpStatus;
}
// Include getters for errorCode and httpStatus
public int getErrorCode() {
return errorCode;
}

View File

@ -0,0 +1,9 @@
package com.nttdata.calender.errorhandling.ErrorTypes;
import org.springframework.http.HttpStatus;
public class NotFoundError extends BackendError {
public NotFoundError(String message) {
super(message, 404, HttpStatus.NOT_FOUND);
}
}

View File

@ -0,0 +1,11 @@
package com.nttdata.calender.errorhandling.ErrorTypes;
import org.springframework.http.HttpStatus;
public class ValidationError extends BackendError {
public ValidationError(String message) {
super(message, 400, HttpStatus.BAD_REQUEST);
}
}

View File

@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import com.bmc.arsys.api.ARException;
import com.nttdata.calender.errorhandling.ErrorTypes.BackendError;
@ControllerAdvice
public class GlobalExceptionHandler {
@ -18,17 +19,24 @@ public class GlobalExceptionHandler {
@ExceptionHandler(ARException.class)
public ResponseEntity<ErrorResponse> handleARException(ARException e, HttpServletRequest request) {
var errorMessage = "Remedy server error: \n" + e.getMessage();
var errorResponse = new ErrorResponse(errorMessage, e.getClass().getSimpleName());
errorLogger.error(errorMessage, e);
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
return entityResponse(errorMessage, e, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGenericException(Exception e, HttpServletRequest request) {
var errorMessage = "Backend internal server error: \n" + e.getMessage();
return entityResponse(errorMessage, e, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(BackendError.class)
public ResponseEntity<ErrorResponse> handleBackendErrorException(BackendError e, HttpServletRequest request) {
var errorMessage = "Backend internal server error: \n" + e.getMessage();
return entityResponse(errorMessage, e, e.getHttpStatus());
}
private ResponseEntity<ErrorResponse> entityResponse(String errorMessage, Exception e, HttpStatus status) {
var errorResponse = new ErrorResponse(errorMessage, e.getClass().getSimpleName());
errorLogger.error(errorMessage, e);
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
return new ResponseEntity<>(errorResponse, status);
}
}