diff --git a/backend/src/main/java/com/nttdata/calender/api/KalenderRestController.java b/backend/src/main/java/com/nttdata/calender/api/KalenderRestController.java index b920b30..9a50692 100644 --- a/backend/src/main/java/com/nttdata/calender/api/KalenderRestController.java +++ b/backend/src/main/java/com/nttdata/calender/api/KalenderRestController.java @@ -1,27 +1,20 @@ package com.nttdata.calender.api; -import java.lang.annotation.Repeatable; import java.util.ArrayList; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.checkerframework.common.util.report.qual.ReportCall; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; 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.ErrorResponse; -import com.nttdata.calender.api.rsso.Rsso; import com.nttdata.calender.approval.Approval; import com.nttdata.calender.approval.ApprovalUpdateRequest; import com.nttdata.calender.changes.Change; @@ -30,6 +23,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; @@ -55,16 +50,20 @@ public class KalenderRestController { private final PackageType packageType; private final Approval approval; private final UrlConstructor urlConstructor; + private final StateChange stateChange; + + private static final Logger applicationLogger = LogManager.getLogger("application"); @Autowired public KalenderRestController(RemedyJavaAPI javaAPI, Change change, Implementer implementer, - PackageType packageType, Approval approval, UrlConstructor urlConstructor) { + PackageType packageType, Approval approval, UrlConstructor urlConstructor, StateChange stateChange) { this.javaAPI = javaAPI; this.change = change; this.implementer = implementer; this.packageType = packageType; this.approval = approval; this.urlConstructor = urlConstructor; + this.stateChange = stateChange; } /** @@ -78,9 +77,9 @@ public class KalenderRestController { @CrossOrigin("*") @GetMapping("/api/getStates") @ResponseBody - public ArrayList printState() throws JsonProcessingException { + public ArrayList printState() { var state = State.getInstance(); - return state.returnJson(); + return state.get(); } /** @@ -177,7 +176,7 @@ public class KalenderRestController { @PostMapping("/api/getChanges") @ResponseBody public ChangeResponse getChanges(@RequestBody ChangeRequest request) - throws ARException { + throws ARException, NotFoundError, ValidationError { return change.get(request); } @@ -187,12 +186,14 @@ public class KalenderRestController { * @param request the request object containing the ID of the change entry and * the new timestamp * @return the updated {@link ChangeUpdateRequest} object - * @throws ARException if an AR exception occurs + * @throws ARException if an AR exception occurs + * @throws ValidationError */ @CrossOrigin("*") @PostMapping("/api/updateChange") @ResponseBody - public ChangeUpdateRequest updateChange(@RequestBody ChangeUpdateRequest request) throws ARException { + public ChangeUpdateRequest updateChange(@RequestBody ChangeUpdateRequest request) + throws ARException, ValidationError { change.modifyTimestamp(request); return request; } @@ -210,8 +211,8 @@ public class KalenderRestController { */ @CrossOrigin("*") @PostMapping("/api/updateState") - public ResponseEntity updateState(@RequestBody StateChangeRequest request, - @Autowired StateChange stateChange) throws ARException { + public ResponseEntity updateState(@RequestBody StateChangeRequest request) throws ARException { + logRequest("/updateState", request.toString()); var response = stateChange.createStateChange(request); return ResponseEntity.ok(response); } @@ -254,17 +255,8 @@ public class KalenderRestController { return implementer.get(request); } - /** - * Handles the exception raised by ARException. - * - * @param e the ARException raised - * @return an {@link ErrorResponse} with the error message - */ - @CrossOrigin("*") - @ExceptionHandler(ARException.class) - public ResponseEntity handleARException(ARException e) { - var errorResponse = new ErrorResponse("Error occured", e.getMessage()); - javaAPI.handleException(e, e.getMessage()); - return new ResponseEntity(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR); + private void logRequest(String endpoint, String request) { + applicationLogger.info("Received request on endpoint %s with body:", endpoint); + applicationLogger.info(request); } } diff --git a/backend/src/main/java/com/nttdata/calender/api/RemedyJavaAPI.java b/backend/src/main/java/com/nttdata/calender/api/RemedyJavaAPI.java index f4a0a16..49efaee 100644 --- a/backend/src/main/java/com/nttdata/calender/api/RemedyJavaAPI.java +++ b/backend/src/main/java/com/nttdata/calender/api/RemedyJavaAPI.java @@ -16,11 +16,11 @@ import com.bmc.arsys.api.Field; import com.bmc.arsys.api.OutputInteger; import com.bmc.arsys.api.QualifierInfo; import com.bmc.arsys.api.SortInfo; -import com.bmc.arsys.api.StatusInfo; import com.bmc.arsys.api.Timestamp; import com.bmc.arsys.api.Value; import com.nttdata.calender.changes.Change; import com.nttdata.calender.contracts.Contract; +import com.nttdata.calender.errorhandling.ErrorTypes.NotFoundError; import com.nttdata.calender.states.State; import com.nttdata.calender.supportgroup.SupportGroup; @@ -32,14 +32,14 @@ public class RemedyJavaAPI { private ARServerUser server; private String formName = "ASF:WI_TAS_Paket"; - private static Logger logger = LogManager.getLogger("logger"); + private static Logger applicationLogger = LogManager.getLogger("application"); // TODO: work with form CTM:Support Group private static final String QUALSTR = "\'Request ID\' != \"\""; /** * Sets up the Remedy API with the server and admin user/password. */ - public RemedyJavaAPI() { + public RemedyJavaAPI() throws ARException, NotFoundError { server = new ARServerUser(); server.setServer("itsm-app-dev.asfinag.at"); server.setUser("changecalender_integration"); @@ -60,20 +60,10 @@ public class RemedyJavaAPI { /** * Connects the current user to the server. */ - void connect() { - logger.info("Connecting to AR Server"); - try { - server.verifyUser(); - } catch (ARException e) { - // This exception is triggered by a bad server, password or, - // if guest access is turned off, by an unknown username. - logger.error(e + "| Cannot verify user " + - server.getUser() + "."); - handleException(e, "Cannot verify user " + - server.getUser() + "."); - System.exit(1); - } - logger.info("Connected to AR Server " + + void connect() throws ARException { + applicationLogger.info("Connecting to AR Server"); + server.verifyUser(); + applicationLogger.info("Connected to AR Server " + server.getServer()); } @@ -134,12 +124,12 @@ public class RemedyJavaAPI { }); var entryIdOut = server.createEntry(formName, entry); - logger.info("Entry created. The id # is " + + applicationLogger.info("Entry created. The id # is " + entryIdOut); var lastStatus = server.getLastStatus(); if (!server.getLastStatus().isEmpty()) { - logger.info("Warning: " + lastStatus); + applicationLogger.info("Warning: " + lastStatus); return lastStatus.toString(); } @@ -194,7 +184,7 @@ public class RemedyJavaAPI { if (qualStr.isEmpty()) qualStr = QUALSTR; - logger.info("Retrieving entries from Form :" + formName + " with qualification " + + applicationLogger.info("Retrieving entries from Form :" + formName + " with qualification " + qualStr); // Retrieve the detail info of all fields from the form. List fields = server.getListFieldObjects(formName); @@ -248,9 +238,6 @@ public class RemedyJavaAPI { var total = sliceEnd - sliceStart; var remainder = total % maxEntriesNumber; var loop = total / maxEntriesNumber; - System.out.println(loop); - System.out.println(remainder); - System.out.println(sliceStart); for (int i = 0; i < loop; i++) { fetched = server.getListEntryObjects( @@ -275,57 +262,6 @@ public class RemedyJavaAPI { return statistics.get(0).getResult().getIntValue(); } - /** - * Exception handling method that logs errors, prints a stack trace, and outputs - * the last server status. - * - * @param e the ARException - * @param errMessage the error message - */ - public void handleException(ARException e, String errMessage) { - logger.error(errMessage, e); - logger.error(server.getLastStatus()); - e.printStackTrace(); - } - - /** - * Prints a specific status type depending on the status list. - * - * @param statusList the information about the status - */ - public void printStatusList(List statusList) { - if (statusList == null || statusList.size() == 0) { - System.out.println("Status List is empty."); - return; - } - System.out.print("Message type: "); - switch (statusList.get(0).getMessageType()) { - case Constants.AR_RETURN_OK: - System.out.println("Note"); - break; - case Constants.AR_RETURN_WARNING: - System.out.println("Warning"); - break; - case Constants.AR_RETURN_ERROR: - System.out.println("Error"); - break; - case Constants.AR_RETURN_FATAL: - System.out.println("Fatal Error"); - break; - default: - System.out.println("Unknown (" + - statusList.get(0).getMessageType() + ")"); - break; - } - System.out.println("Status List:"); - for (int i = 0; i < statusList.size(); i++) { - - System.out.println(statusList.get(i).getMessageText()); - - System.out.println(statusList.get(i).getAppendedText()); - } - } - /** * Modifies entries by entry ID and field ID with a new date. * @@ -333,17 +269,15 @@ public class RemedyJavaAPI { * @param date the new date to be modified * @param fieldId the ID of the field */ - void modifyEntryForReset(String entryId, Date date, int fieldId) { + void modifyEntryForReset(String entryId, Date date, int fieldId) throws ARException { Timestamp ts = new Timestamp(date); - try { - Entry entry = server.getEntry(formName, entryId, null); - entry.put(fieldId, new Value(ts)); - if (entry.get(fieldId) != null) { - server.setEntry(formName, entryId, entry, null, 0); - System.out.println("Entry #" + entryId + " modified successfully."); - } - } catch (ARException e) { - handleException(e, "Cannot modify the entry. "); + + Entry entry = server.getEntry(formName, entryId, null); + entry.put(fieldId, new Value(ts)); + if (entry.get(fieldId) != null) { + server.setEntry(formName, entryId, entry, null, 0); + System.out.println("Entry #" + entryId + " modified successfully."); } + } } \ No newline at end of file diff --git a/backend/src/main/java/com/nttdata/calender/approval/Approval.java b/backend/src/main/java/com/nttdata/calender/approval/Approval.java index 1cd03a7..1ecaead 100644 --- a/backend/src/main/java/com/nttdata/calender/approval/Approval.java +++ b/backend/src/main/java/com/nttdata/calender/approval/Approval.java @@ -3,7 +3,6 @@ package com.nttdata.calender.approval; import org.springframework.stereotype.Service; import com.bmc.arsys.api.ARException; -import com.bmc.arsys.api.Entry; import com.bmc.arsys.api.Value; import com.nttdata.calender.api.Query; import com.nttdata.calender.api.RemedyJavaAPI; @@ -41,40 +40,42 @@ public class Approval { .addFieldValue("ApprovalAction", 1000003264, request.getApprovalActionValue()) .build(); - /* - String user = remedyJavaAPI.getUser(); - var queryChanges = new Query.QueryBuilder("ASF:WI_TAS_Paket") - .addFieldId("ChangeNr", 1000000182) - .addFieldId("ActualStatus", 7) - .build(); - - - Entry change = remedyJavaAPI - .queryFieldsById("\'Infrastructure Change ID\' = \"" + request.getChangeNrValue().toString() + "\"", - queryChanges.getFieldIds(), queryChanges.getFormName(), null, 0, 0) - .get(0); - - - int approvalAction = queryUpdate.getFieldValue("ApprovalAction").getIntValue(); - var actualStatus = change.get(queryChanges.getFieldId("ActualStatus")); - - - if (approvalAction == 1 || approvalAction == 2) { - if (inApprovalList(user, request.getChangeNr())) - return this.remedyJavaAPI.createEntry(queryUpdate); - else - return "user (" + user + ") has no authorization for approval."; - } else if (approvalAction == 3) { - if (request.getChangeNr().contains("PKG") && actualStatus.getIntValue() == 1) - return this.remedyJavaAPI.createEntry(queryUpdate); - else - return request.getChangeNr().contains("PKG") - ? "actual status not set to 'request for authorization'." - : "is not a package (PKG)"; - } else { - return "invalid approval status (must be 1, 2 or 3)"; - } - */ + /* + * String user = remedyJavaAPI.getUser(); + * var queryChanges = new Query.QueryBuilder("ASF:WI_TAS_Paket") + * .addFieldId("ChangeNr", 1000000182) + * .addFieldId("ActualStatus", 7) + * .build(); + * + * + * Entry change = remedyJavaAPI + * .queryFieldsById("\'Infrastructure Change ID\' = \"" + + * request.getChangeNrValue().toString() + "\"", + * queryChanges.getFieldIds(), queryChanges.getFormName(), null, 0, 0) + * .get(0); + * + * + * int approvalAction = + * queryUpdate.getFieldValue("ApprovalAction").getIntValue(); + * var actualStatus = change.get(queryChanges.getFieldId("ActualStatus")); + * + * + * if (approvalAction == 1 || approvalAction == 2) { + * if (inApprovalList(user, request.getChangeNr())) + * return this.remedyJavaAPI.createEntry(queryUpdate); + * else + * return "user (" + user + ") has no authorization for approval."; + * } else if (approvalAction == 3) { + * if (request.getChangeNr().contains("PKG") && actualStatus.getIntValue() == 1) + * return this.remedyJavaAPI.createEntry(queryUpdate); + * else + * return request.getChangeNr().contains("PKG") + * ? "actual status not set to 'request for authorization'." + * : "is not a package (PKG)"; + * } else { + * return "invalid approval status (must be 1, 2 or 3)"; + * } + */ return this.remedyJavaAPI.createEntry(queryUpdate); } @@ -87,16 +88,21 @@ public class Approval { * @return True if the user is in the approval list, false otherwise * @throws ARException If an error occurs during the query */ - /* - public boolean inApprovalList(String user, String changeNr) throws ARException { - var queryApprovalList = new Query.QueryBuilder("ASF:OverviewConsole_TicketsJoinAPDetailSignature") - .addFieldId("Approvers", 13207).build(); - - var approversOI = remedyJavaAPI.queryFieldsById("\'Ticketnumber\' = \"" + changeNr + "\"", - queryApprovalList.getFieldIds(), queryApprovalList.getFormName(), null, 0, 0); - - String approvers = approversOI.get(0).get(queryApprovalList.getFieldId("Approvers")).toString(); - return approvers.contains(user); - } - */ + /* + * public boolean inApprovalList(String user, String changeNr) throws + * ARException { + * var queryApprovalList = new + * Query.QueryBuilder("ASF:OverviewConsole_TicketsJoinAPDetailSignature") + * .addFieldId("Approvers", 13207).build(); + * + * var approversOI = remedyJavaAPI.queryFieldsById("\'Ticketnumber\' = \"" + + * changeNr + "\"", + * queryApprovalList.getFieldIds(), queryApprovalList.getFormName(), null, 0, + * 0); + * + * String approvers = + * approversOI.get(0).get(queryApprovalList.getFieldId("Approvers")).toString(); + * return approvers.contains(user); + * } + */ } diff --git a/backend/src/main/java/com/nttdata/calender/changes/Change.java b/backend/src/main/java/com/nttdata/calender/changes/Change.java index d067ba6..71c0d0d 100644 --- a/backend/src/main/java/com/nttdata/calender/changes/Change.java +++ b/backend/src/main/java/com/nttdata/calender/changes/Change.java @@ -5,22 +5,20 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Optional; -import java.util.Set; import java.util.TimeZone; -import java.util.stream.Collectors; -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.SortInfo; import com.bmc.arsys.api.Timestamp; 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.ErrorTypes.NotFoundError; +import com.nttdata.calender.errorhandling.ErrorTypes.ValidationError; /** * Class representing the change with all of the change specific attributes. @@ -30,7 +28,6 @@ public class Change { private Query queryChange; private RemedyJavaAPI api; private final static String formName = "ASF:WI_TAS_Paket"; - private static Logger logger = LogManager.getLogger("logger"); /** * Constructor for the {@link Change} class which gets autowired with the @@ -41,7 +38,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) @@ -76,41 +72,19 @@ 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"); - // Queries for SupportGroup of impersonated User - var queryPerson = new Query.QueryBuilder("CTM:Support Group Association") - .addFieldId("FullName", 1000000017) - .addFieldId("SupportGroupId", 1000000079) - .build(); - var peopleInfos = api.queryFieldsById("\'Login ID\' = \"" + api.getUser() + "\"", - queryPerson.getFieldIds(), - queryPerson.getFormName(), null, 0, 0); - if (peopleInfos.isEmpty()) { - throw new RuntimeException("No user found with this loginId"); - } + var peopleFullName = processPeopleInfo(request); - // constructs set of supportGroups and full name of impersonated User - String[] peopleSupportGroup = peopleInfos.stream() - .map(entry -> entry.get(queryPerson.getFieldId("SupportGroupId")).toString()) - .toArray(String[]::new); - var peopleFullName = peopleInfos.get(0).get(queryPerson.getFieldId("FullName")).toString(); - - request.addFilter( - new Filter("SupportGroupId", "equals", peopleSupportGroup)); - - var qualifier = ""; - if (request.getFilter() != null) { - qualifier = request.constructQualifier(queryChange, api); - } + var qualifier = request.constructQualifier(queryChange, api); + SortInfo sort = request.constructSortInfo(queryChange); var entries = api.queryFieldsById(qualifier, this.queryChange.getFieldIds(), this.queryChange.getFormName(), - request.getSort().getSortInfo(queryChange), request.getSliceStart(), + sort, request.getSliceStart(), request.getSliceEnd()); var entriesSize = api.getFormSize(qualifier, this.queryChange.getFormName()); - System.out.println(entriesSize); var changes = new ArrayList(); for (var entry : entries) { @@ -143,16 +117,18 @@ public class Change { .isPresent()); // var state = getValue(entry, "State").getIntValue(); - // var inApproval = inApprovalList(api.getUser(), getValueStringByID(entry, "ChangeNr")); + // var inApproval = inApprovalList(api.getUser(), getValueStringByID(entry, + // "ChangeNr")); // change.setFlagPermit(flagPermit(state)); // change.setFlagApprove(flagApproval(inApproval, state)); // change.setFlagReject(flagApproval(inApproval, state)); - // change.setFlagCancel(flagCancel(getValueStringByID(entry, "SupportGroupId"), state)); - + // change.setFlagCancel(flagCancel(getValueStringByID(entry, "SupportGroupId"), + // state)); try { - change.setPackageName(queryPackageName(getValueStringByID(entry, "PackageType").toString())); + change.setPackageName( + queryPackageName(getValueStringByID(entry, "PackageType").toString())); } catch (ARException e) { e.printStackTrace(); } @@ -163,73 +139,117 @@ public class Change { return new ChangeResponse(entriesSize, changes); } + 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) + .addFieldId("SupportGroupId", 1000000079) + .build(); + var peopleInfos = api.queryFieldsById("\'Login ID\' = \"" + api.getUser() + "\"", + queryPerson.getFieldIds(), + queryPerson.getFormName(), null, 0, 0); + if (peopleInfos.isEmpty()) { + throw new NotFoundError("No user found with this loginId"); + } + + // constructs set of supportGroups and full name of impersonated User + String[] peopleSupportGroup = peopleInfos.stream() + .map(entry -> entry.get(queryPerson.getFieldId("SupportGroupId")).toString()) + .toArray(String[]::new); + if (peopleSupportGroup.length <= 0) { + throw new NotFoundError("No supportGroups associated to the loginId "); + } + request.addFilter( + new Filter("SupportGroupId", "equals", peopleSupportGroup)); + + return peopleInfos.get(0).get(queryPerson.getFieldId("FullName")).toString(); + } + // /** - // * Determines if the change item can be approved based on the approval status - // * and the current state. - // * - // * @param approval The flag indicating whether the change item has been - // * approved. - // * @param state The current state of the change item. - // * @return {@code true} if the change item can be approved, {@code false} - // * otherwise. - // */ + // * Determines if the change item can be approved based on the approval status + // * and the current state. + // * + // * @param approval The flag indicating whether the change item has been + // * approved. + // * @param state The current state of the change item. + // * @return {@code true} if the change item can be approved, {@code false} + // * otherwise. + // */ // public boolean flagApproval(boolean approval, int state) { - // boolean approvableState = (state == 1 || state == 10); - // return approval && approvableState; + // boolean approvableState = (state == 1 || state == 10); + // return approval && approvableState; // } // /** - // * Determines if the change item can be canceled based on the support group ID - // * and the current state. - // * - // * @param supportGroupId The ID of the support group associated with the change item - // * @param state The current state of the change item - // * @return {@code true} if the change item can be canceled, {@code false} otherwise. - // * @throws ARException if an error occurs during the operation - // */ - // public boolean flagCancel(String supportGroupId, int state) throws ARException { - // var queryRoles = new Query.QueryBuilder("CTM:SupportGroupFuncRoleLookUp").addFieldId("Role", 1000000014) - // .build(); - // var role = api.queryFieldsById("\'Support Group ID\' = \"" + supportGroupId + "\"", - // queryRoles.getFieldIds(), queryRoles.getFormName(), null, 0, 0) - // .get(0).get(queryRoles.getFieldId("Role")).toString(); + // * Determines if the change item can be canceled based on the support group ID + // * and the current state. + // * + // * @param supportGroupId The ID of the support group associated with the + // change item + // * @param state The current state of the change item + // * @return {@code true} if the change item can be canceled, {@code false} + // otherwise. + // * @throws ARException if an error occurs during the operation + // */ + // public boolean flagCancel(String supportGroupId, int state) throws + // ARException { + // var queryRoles = new + // Query.QueryBuilder("CTM:SupportGroupFuncRoleLookUp").addFieldId("Role", + // 1000000014) + // .build(); + // var role = api.queryFieldsById("\'Support Group ID\' = \"" + supportGroupId + + // "\"", + // queryRoles.getFieldIds(), queryRoles.getFormName(), null, 0, 0) + // .get(0).get(queryRoles.getFieldId("Role")).toString(); - // boolean approvableState = state == 1; - // boolean isChangeManager = role.equals("Change Manager"); + // boolean approvableState = state == 1; + // boolean isChangeManager = role.equals("Change Manager"); - // return approvableState && isChangeManager; + // return approvableState && isChangeManager; // } // /** - // * Determines if the change item has a permit based on the current state. - // * - // * @param state The current state of the change item. - // * @return {@code true} if the change item has a permit, {@code false} otherwise. - // */ + // * Determines if the change item has a permit based on the current state. + // * + // * @param state The current state of the change item. + // * @return {@code true} if the change item has a permit, {@code false} + // otherwise. + // */ // public boolean flagPermit(int state) { - // return state == 0; + // return state == 0; // } // /** - // * Checks if the logged in user is in the approval list for the specified change item. - // * - // * @param user The username of the user to check - // * @param changeNr The change number of the change item - // * @return {@code true} if the user is in the approval list, {@code false} otherwise. - // * @throws ARException if an error occurs during the operation - // */ - // public boolean inApprovalList(String user, String changeNr) throws ARException { - // var queryApprovalList = new Query.QueryBuilder("ASF:OverviewConsole_TicketsJoinAPDetailSignature") - // .addFieldId("Approvers", 13207).build(); - // var approversOI = api.queryFieldsById("\'Ticketnumber\' = \"" + changeNr + "\"", - // queryApprovalList.getFieldIds(), queryApprovalList.getFormName(), null, 0, 0); - // var approvers = approversOI.isEmpty() ? null - // : approversOI.get(0).get(queryApprovalList.getFieldId("Approvers")).toString(); - // return approvers != null ? approvers.contains(user) : false; + // * Checks if the logged in user is in the approval list for the specified + // change item. + // * + // * @param user The username of the user to check + // * @param changeNr The change number of the change item + // * @return {@code true} if the user is in the approval list, {@code false} + // otherwise. + // * @throws ARException if an error occurs during the operation + // */ + // public boolean inApprovalList(String user, String changeNr) throws + // ARException { + // var queryApprovalList = new + // Query.QueryBuilder("ASF:OverviewConsole_TicketsJoinAPDetailSignature") + // .addFieldId("Approvers", 13207).build(); + // var approversOI = api.queryFieldsById("\'Ticketnumber\' = \"" + changeNr + + // "\"", + // queryApprovalList.getFieldIds(), queryApprovalList.getFormName(), null, 0, + // 0); + // var approvers = approversOI.isEmpty() ? null + // : + // approversOI.get(0).get(queryApprovalList.getFieldId("Approvers")).toString(); + // return approvers != null ? approvers.contains(user) : false; // } - private String queryPackageName(String packageType) throws ARException{ - var queryPackage = new Query.QueryBuilder("CTR:GenericContractJoinCFG_Package").addFieldId("PackageName", 200000020).build(); - var packageName = api.queryFieldsById("\'InstanceId_Package\' = \"" + packageType + "\"", queryPackage.getFieldIds(), queryPackage.getFormName(), null, 0, 0).get(0); + private String queryPackageName(String packageType) throws ARException { + var queryPackage = new Query.QueryBuilder("CTR:GenericContractJoinCFG_Package") + .addFieldId("PackageName", 200000020).build(); + var packageName = api + .queryFieldsById("\'InstanceId_Package\' = \"" + packageType + "\"", + queryPackage.getFieldIds(), queryPackage.getFormName(), null, 0, 0) + .get(0); return packageName.get(queryPackage.getFieldId("PackageName")).toString(); } @@ -237,7 +257,8 @@ public class Change { * Returns the {@link Value} of an entry based on the provided description. * * @param entry the {@link Entry} from which a value will be retrieved - * @param description the name of the field from which the value should be retrieved + * @param description the name of the field from which the value should be + * retrieved * @return the value of the entry */ private Value getValue(Entry entry, String description) { @@ -249,7 +270,8 @@ public class Change { * timestamp is null. * * @param entry the {@link Entry} containing the timestamp value - * @param description the description of the field containing the timestamp value + * @param description the description of the field containing the timestamp + * value * @return the converted {@link Date} or null if the timestamp is null */ private Date timestampToDateById(Entry entry, String description) { @@ -282,9 +304,10 @@ public class Change { * * @param request the object containing the ID of the change entry and the new * timestamp - * @throws ARException if an error occurs during the modification process + * @throws ARException if an error occurs during the modification process + * @throws ValidationError */ - public void modifyTimestamp(ChangeUpdateRequest request) throws ARException { + public void modifyTimestamp(ChangeUpdateRequest request) throws ARException, ValidationError { String entryId = request.getResourceId(); String d2 = request.getD2(); int state = request.getState(); @@ -309,9 +332,9 @@ public class Change { api.modifyEntry(change.get(0).getEntryId(), queryInfrastructureChange); } - } catch (ParseException e) { - logger.error(e, e); + throw new ValidationError("Incorrect dateformat in request"); } + } } diff --git a/backend/src/main/java/com/nttdata/calender/changes/ChangeRequest.java b/backend/src/main/java/com/nttdata/calender/changes/ChangeRequest.java index 8d53f3b..3e7521c 100644 --- a/backend/src/main/java/com/nttdata/calender/changes/ChangeRequest.java +++ b/backend/src/main/java/com/nttdata/calender/changes/ChangeRequest.java @@ -2,13 +2,16 @@ 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; +import com.bmc.arsys.api.SortInfo; 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, @@ -101,6 +104,13 @@ public class ChangeRequest { this.filter.add(filter); } + public SortInfo constructSortInfo(Query query) throws ValidationError { + if (this.sort != null) { + return this.sort.getSortInfo(query); + } + return null; + } + /** * Constructs a qualifier based on the filters defined in the object and the * given Query object. @@ -112,77 +122,100 @@ public class ChangeRequest { * @throws ARException if an error occurs while constructing the qualifier or an * 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 = ""; + if (this.filter == null) { + return 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 criterias = 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() || criterias.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 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 ValidationError("Invalid inner filter argument"); + } + + 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"; + + var parsed = ""; + try { + LocalDateTime parser = LocalDateTime.parse(date, DateTimeFormatter.ofPattern(inputFormat)); + 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; + } } diff --git a/backend/src/main/java/com/nttdata/calender/changes/query/Sort.java b/backend/src/main/java/com/nttdata/calender/changes/query/Sort.java index 3e19245..3f27e29 100644 --- a/backend/src/main/java/com/nttdata/calender/changes/query/Sort.java +++ b/backend/src/main/java/com/nttdata/calender/changes/query/Sort.java @@ -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,9 +59,8 @@ 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; switch (this.mode) { @@ -70,6 +70,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); diff --git a/backend/src/main/java/com/nttdata/calender/contracts/Contract.java b/backend/src/main/java/com/nttdata/calender/contracts/Contract.java index 59ccead..340bf29 100644 --- a/backend/src/main/java/com/nttdata/calender/contracts/Contract.java +++ b/backend/src/main/java/com/nttdata/calender/contracts/Contract.java @@ -3,12 +3,10 @@ package com.nttdata.calender.contracts; import java.util.ArrayList; import java.util.stream.Collectors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - import com.bmc.arsys.api.ARException; import com.nttdata.calender.api.Query; import com.nttdata.calender.api.RemedyJavaAPI; +import com.nttdata.calender.errorhandling.ErrorTypes.NotFoundError; /** * Represents a singleton instance of the Contract class, which provides @@ -19,7 +17,6 @@ public class Contract { private static final String formName_changes = "ASF:WI_TAS_Paket"; private static final String formName_contracts = "CTR:ContractBase"; private static final Contract INSTANCE = new Contract(); - private static final Logger logger = LogManager.getLogger("logger"); private ArrayList contracts; /** @@ -44,47 +41,45 @@ public class Contract { * @param api RemedyJavaAPI object used to connect to the Remedy AR Server */ - public void queryContracts(RemedyJavaAPI api) { - try { - ArrayList allChanges = new ArrayList(); - ArrayList allContracts = new ArrayList(); + public void queryContracts(RemedyJavaAPI api) throws ARException, NotFoundError { + ArrayList allChanges = new ArrayList(); + ArrayList allContracts = new ArrayList(); - var queryChanges = new Query.QueryBuilder(formName_changes) - .addFieldId("Contract", 670031002).build(); + var queryChanges = new Query.QueryBuilder(formName_changes) + .addFieldId("Contract", 670031002).build(); - allChanges = api.queryFieldsById("", queryChanges.getFieldIds(), formName_changes, null, 0, 0) - .stream() - .map(entry -> new ContractGetResponse(null, - entry.get(queryChanges.getFieldId("Contract")).toString())) - .distinct() - .collect(Collectors.toCollection(ArrayList::new)); + allChanges = api.queryFieldsById("", queryChanges.getFieldIds(), formName_changes, null, 0, 0) + .stream() + .map(entry -> new ContractGetResponse(null, + entry.get(queryChanges.getFieldId("Contract")).toString())) + .distinct() + .collect(Collectors.toCollection(ArrayList::new)); - var queryContracts = new Query.QueryBuilder(formName_contracts) - .addFieldId("Id", 179) - .addFieldId("Name", 8).build(); + var queryContracts = new Query.QueryBuilder(formName_contracts) + .addFieldId("Id", 179) + .addFieldId("Name", 8).build(); - allContracts = api - .queryFieldsById("\'Contract ID+\' != \"\"", queryContracts.getFieldIds(), formName_contracts, null, - 0, 0) - .stream() - .map(entry -> new ContractGetResponse( - entry.get(queryContracts.getFieldId("Name")).toString(), - entry.get(queryContracts.getFieldId("Id")).toString())) - .distinct() - .collect(Collectors.toCollection(ArrayList::new)); + allContracts = api + .queryFieldsById("\'Contract ID+\' != \"\"", queryContracts.getFieldIds(), formName_contracts, null, + 0, 0) + .stream() + .map(entry -> new ContractGetResponse( + entry.get(queryContracts.getFieldId("Name")).toString(), + entry.get(queryContracts.getFieldId("Id")).toString())) + .distinct() + .collect(Collectors.toCollection(ArrayList::new)); - for (var change : allChanges) { - for (var contract : allContracts) { - if (change.id.equals(contract.id)) { - this.contracts.add(contract); - break; - } + for (var change : allChanges) { + for (var contract : allContracts) { + if (change.id.equals(contract.id)) { + this.contracts.add(contract); + break; } } + } - } catch (ARException e) { - logger.error("An error occured while querying: " + e.getMessage()); - e.printStackTrace(); + if (contracts.isEmpty()) { + throw new NotFoundError("No contracts found in this context"); } } diff --git a/backend/src/main/java/com/nttdata/ErrorResponse.java b/backend/src/main/java/com/nttdata/calender/errorhandling/ErrorResponse.java similarity index 84% rename from backend/src/main/java/com/nttdata/ErrorResponse.java rename to backend/src/main/java/com/nttdata/calender/errorhandling/ErrorResponse.java index 62178f5..8e60221 100644 --- a/backend/src/main/java/com/nttdata/ErrorResponse.java +++ b/backend/src/main/java/com/nttdata/calender/errorhandling/ErrorResponse.java @@ -1,4 +1,4 @@ -package com.nttdata; +package com.nttdata.calender.errorhandling; /** * The ErrorResponse class represents an error response that can be returned by @@ -7,7 +7,7 @@ package com.nttdata; */ public class ErrorResponse { private String message; - private String details; + private String error; /** * Constructs an ErrorResponse instance with the provided message and details. @@ -17,7 +17,7 @@ public class ErrorResponse { */ public ErrorResponse(String message, String details) { this.message = message; - this.details = details; + this.error = details; } /** @@ -34,8 +34,8 @@ public class ErrorResponse { * * @return String providing additional details about the error */ - public String getDetails() { - return details; + public String getError() { + return error; } /** @@ -52,7 +52,7 @@ public class ErrorResponse { * * @param details String providing additional details about the error */ - public void setDetails(String details) { - this.details = details; + public void setError(String details) { + this.error = details; } } \ No newline at end of file diff --git a/backend/src/main/java/com/nttdata/calender/errorhandling/ErrorTypes/BackendError.java b/backend/src/main/java/com/nttdata/calender/errorhandling/ErrorTypes/BackendError.java new file mode 100644 index 0000000..59837f8 --- /dev/null +++ b/backend/src/main/java/com/nttdata/calender/errorhandling/ErrorTypes/BackendError.java @@ -0,0 +1,22 @@ +package com.nttdata.calender.errorhandling.ErrorTypes; + +import org.springframework.http.HttpStatus; + +public abstract class BackendError extends Exception { + private int errorCode; + private HttpStatus httpStatus; + + public BackendError(String message, int errorCode, HttpStatus httpStatus) { + super(message); + this.errorCode = errorCode; + this.httpStatus = httpStatus; + } + + public int getErrorCode() { + return errorCode; + } + + public HttpStatus getHttpStatus() { + return httpStatus; + } +} diff --git a/backend/src/main/java/com/nttdata/calender/errorhandling/ErrorTypes/NotFoundError.java b/backend/src/main/java/com/nttdata/calender/errorhandling/ErrorTypes/NotFoundError.java new file mode 100644 index 0000000..7f10c51 --- /dev/null +++ b/backend/src/main/java/com/nttdata/calender/errorhandling/ErrorTypes/NotFoundError.java @@ -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); + } +} diff --git a/backend/src/main/java/com/nttdata/calender/errorhandling/ErrorTypes/ValidationError.java b/backend/src/main/java/com/nttdata/calender/errorhandling/ErrorTypes/ValidationError.java new file mode 100644 index 0000000..ee2dfbe --- /dev/null +++ b/backend/src/main/java/com/nttdata/calender/errorhandling/ErrorTypes/ValidationError.java @@ -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); + } + +} diff --git a/backend/src/main/java/com/nttdata/calender/errorhandling/GlobalExceptionHandler.java b/backend/src/main/java/com/nttdata/calender/errorhandling/GlobalExceptionHandler.java new file mode 100644 index 0000000..bf6b213 --- /dev/null +++ b/backend/src/main/java/com/nttdata/calender/errorhandling/GlobalExceptionHandler.java @@ -0,0 +1,43 @@ +package com.nttdata.calender.errorhandling; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +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 { + private static final Logger errorLogger = LogManager.getLogger("error"); + + @ExceptionHandler(ARException.class) + public ResponseEntity handleARException(ARException e, HttpServletRequest request) { + var errorMessage = "Remedy server error: " + e.getMessage(); + return entityResponse(errorMessage, errorMessage, e, HttpStatus.INTERNAL_SERVER_ERROR); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity handleGenericException(Exception e, HttpServletRequest request) { + var userMessage = "Backend internal server error"; + return entityResponse(userMessage, e.getMessage(), e, HttpStatus.INTERNAL_SERVER_ERROR); + } + + @ExceptionHandler(BackendError.class) + public ResponseEntity handleBackendErrorException(BackendError e, HttpServletRequest request) { + var errorMessage = "Backend internal server error: " + e.getMessage(); + return entityResponse(errorMessage, errorMessage, e, e.getHttpStatus()); + } + + private ResponseEntity entityResponse(String userMessage, String errorMessage, Exception e, + HttpStatus status) { + var errorResponse = new ErrorResponse(userMessage, e.getClass().getSimpleName()); + errorLogger.error(errorMessage, e); + return new ResponseEntity<>(errorResponse, status); + } +} diff --git a/backend/src/main/java/com/nttdata/calender/states/State.java b/backend/src/main/java/com/nttdata/calender/states/State.java index 2ffccad..dc6172e 100644 --- a/backend/src/main/java/com/nttdata/calender/states/State.java +++ b/backend/src/main/java/com/nttdata/calender/states/State.java @@ -5,14 +5,11 @@ import java.util.HashMap; import java.util.List; import java.util.Optional; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - import com.bmc.arsys.api.ARException; import com.bmc.arsys.api.Entry; -import com.fasterxml.jackson.core.JsonProcessingException; import com.nttdata.calender.api.Query; import com.nttdata.calender.api.RemedyJavaAPI; +import com.nttdata.calender.errorhandling.ErrorTypes.NotFoundError; /** * The State class is a singleton class responsible for managing and querying @@ -23,7 +20,6 @@ import com.nttdata.calender.api.RemedyJavaAPI; public class State { private HashMap state; private static final State INSTANCE = new State(); - private static final Logger logger = LogManager.getLogger("logger"); /** * Initializes the state with an empty HashMap. @@ -69,15 +65,14 @@ public class State { * HashMap. * * @param api Remedy API object + * @throws ARException */ - public void queryState(RemedyJavaAPI api) { + public void queryState(RemedyJavaAPI api) throws ARException, NotFoundError { + queryStateNames(api); + queryPossibleStates(api); - try { - queryStateNames(api); - queryPossibleStates(api); - - } catch (Exception e) { - e.printStackTrace(); + if (state.isEmpty()) { + throw new NotFoundError("No States found in this context"); } } @@ -153,26 +148,21 @@ public class State { * @param nameQuery Query object of stateFields */ public void updateStateNames(List stateFields, Query nameQuery) { - try { - stateFields.stream() - .filter(entry -> Optional.ofNullable(entry.get(nameQuery.getFieldId("Locale"))) - .map(Object::toString) - .orElse("") - .equals("de")) - .forEach( - entry -> { - var selectionCode = nameQuery.getFieldId("SelectionCode"); - var englishName = nameQuery.getFieldId("englishName"); - var germanName = nameQuery.getFieldId("germanName"); + stateFields.stream() + .filter(entry -> Optional.ofNullable(entry.get(nameQuery.getFieldId("Locale"))) + .map(Object::toString) + .orElse("") + .equals("de")) + .forEach( + entry -> { + var selectionCode = nameQuery.getFieldId("SelectionCode"); + var englishName = nameQuery.getFieldId("englishName"); + var germanName = nameQuery.getFieldId("germanName"); - this.getState().put(entry.get(selectionCode).getIntValue(), - new StateInfo(entry.get(englishName).toString(), - entry.get(germanName).toString())); - }); - } catch (Exception e) { - logger.error("Database entries for stateName in english and german in bad state"); - e.printStackTrace(); - } + this.getState().put(entry.get(selectionCode).getIntValue(), + new StateInfo(entry.get(englishName).toString(), + entry.get(germanName).toString())); + }); } /** @@ -183,9 +173,8 @@ public class State { * * @return Array of JSON objects with integer representation of state and * {@link StateInfo} - * @throws JsonProcessingException if an error occurs during JSON processing */ - public ArrayList returnJson() throws JsonProcessingException { + public ArrayList get() { var response = new ArrayList(); this.state.forEach((key, value) -> { response.add(new StateResponse(key, value.possibleState, value.stateNameEN, value.stateNameDE)); diff --git a/backend/src/main/java/com/nttdata/calender/states/StateChange.java b/backend/src/main/java/com/nttdata/calender/states/StateChange.java index dbd5b04..f70b02f 100644 --- a/backend/src/main/java/com/nttdata/calender/states/StateChange.java +++ b/backend/src/main/java/com/nttdata/calender/states/StateChange.java @@ -1,7 +1,7 @@ package com.nttdata.calender.states; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; import com.bmc.arsys.api.ARException; import com.bmc.arsys.api.Value; @@ -13,7 +13,7 @@ import com.nttdata.calender.api.RemedyJavaAPI; * change entries on Remedy. It handles the logic of creating a new * entry with the required field values. */ -@Component +@Service public class StateChange { static final String ACTION = "STATUSCHANGE"; static final String formName = "ASF:CHG_CAL_Interactions"; @@ -39,7 +39,6 @@ public class StateChange { * @return String representing the created entry ID * @throws ARException when there's an error creating the entry */ - // TODO: implement changes from implementerChange public String createStateChange(StateChangeRequest request) throws ARException { var query = new Query.QueryBuilder(formName) .addFieldValue("ChangeNr", 666000002, new Value(request.getChangeNr())) diff --git a/backend/src/main/java/com/nttdata/calender/states/StateChangeRequest.java b/backend/src/main/java/com/nttdata/calender/states/StateChangeRequest.java index 4c5e94b..85096db 100644 --- a/backend/src/main/java/com/nttdata/calender/states/StateChangeRequest.java +++ b/backend/src/main/java/com/nttdata/calender/states/StateChangeRequest.java @@ -13,7 +13,7 @@ public class StateChangeRequest { /** * Sets the change number. * - * @param changeNr String to set representing the change number + * @param changeNr String to set representing the change number */ public void setChangeNr(String changeNr) { this.changeNr = changeNr; @@ -22,7 +22,7 @@ public class StateChangeRequest { /** * Sets the current state. * - * @param currentState an int to set representing the current state + * @param currentState an int to set representing the current state */ public void setCurrentState(int currentState) { this.currentState = currentState; diff --git a/backend/src/main/java/com/nttdata/calender/supportgroup/SupportGroup.java b/backend/src/main/java/com/nttdata/calender/supportgroup/SupportGroup.java index ef09d43..9207a68 100644 --- a/backend/src/main/java/com/nttdata/calender/supportgroup/SupportGroup.java +++ b/backend/src/main/java/com/nttdata/calender/supportgroup/SupportGroup.java @@ -3,12 +3,10 @@ package com.nttdata.calender.supportgroup; import java.util.ArrayList; import java.util.stream.Collectors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - import com.bmc.arsys.api.ARException; import com.nttdata.calender.api.Query; import com.nttdata.calender.api.RemedyJavaAPI; +import com.nttdata.calender.errorhandling.ErrorTypes.NotFoundError; /** * The SupportGroup class represents a singleton object that holds information @@ -18,7 +16,6 @@ import com.nttdata.calender.api.RemedyJavaAPI; public class SupportGroup { private static final String formName = "CTM:Support Group"; private static final SupportGroup INSTANCE = new SupportGroup(); - private static final Logger logger = LogManager.getLogger("logger"); private ArrayList supportGroups; private SupportGroupGetResponse userSupportGroup; @@ -44,26 +41,24 @@ public class SupportGroup { * * @param api RemedyJavaAPI object used to connect to the Remedy AR Server. */ - public void querySupportGroups(RemedyJavaAPI api) { - try { - var querySupportGroups = new Query.QueryBuilder(formName) - .addFieldId("SupportGroup", 1000000015) - .addFieldId("SupportGroupId", 1) - .build(); + public void querySupportGroups(RemedyJavaAPI api) throws ARException, NotFoundError { + var querySupportGroups = new Query.QueryBuilder(formName) + .addFieldId("SupportGroup", 1000000015) + .addFieldId("SupportGroupId", 1) + .build(); - this.supportGroups = api - .queryFieldsById("\'Support Group ID\' != \"\"", querySupportGroups.getFieldIds(), - querySupportGroups.getFormName(), null, 0, 0) - .stream() - .map(entry -> new SupportGroupGetResponse( - entry.get(querySupportGroups.getFieldId("SupportGroup")).toString(), - entry.get(querySupportGroups.getFieldId("SupportGroupId")).toString())) - .distinct() - .collect(Collectors.toCollection(ArrayList::new)); + this.supportGroups = api + .queryFieldsById("\'Support Group ID\' != \"\"", querySupportGroups.getFieldIds(), + querySupportGroups.getFormName(), null, 0, 0) + .stream() + .map(entry -> new SupportGroupGetResponse( + entry.get(querySupportGroups.getFieldId("SupportGroup")).toString(), + entry.get(querySupportGroups.getFieldId("SupportGroupId")).toString())) + .distinct() + .collect(Collectors.toCollection(ArrayList::new)); - } catch (ARException e) { - logger.error("An error occured while querying support groups: " + e.getMessage()); - e.printStackTrace(); + if (this.supportGroups.isEmpty()) { + throw new NotFoundError("No support groups found in this context"); } } diff --git a/backend/src/main/resources/log4j2.xml b/backend/src/main/resources/log4j2.xml index 42d8114..c742d29 100644 --- a/backend/src/main/resources/log4j2.xml +++ b/backend/src/main/resources/log4j2.xml @@ -2,30 +2,30 @@ + fileName="./backend/log/application.log" filePattern="./backend/log/application-%d{yyyy-MM-dd-HH-mm}-%i.log"> %d{yyyy-MM-dd-HH:mm:ss} %-5p %m%n%ex{full} - + + fileName="./backend/log/error.log" filePattern="./backend/log/error-%d{yyyy-MM-dd-HH-mm}-%i.log"> %d{yyyy-MM-dd-HH:mm:ss} %-5p %m%n%ex{full} - + + fileName="./backend/log/warn.log" filePattern="./backend/log/warn-%d{yyyy-MM-dd-HH-mm}-%i.log"> %d{yyyy-MM-dd-HH:mm:ss} %-5p %m%n - + @@ -33,13 +33,21 @@ - - - + + + + + + + + + - + + + \ No newline at end of file