package com.nttdata.calender.api; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.stereotype.Service; import com.bmc.arsys.api.ARException; import com.bmc.arsys.api.ARServerUser; import com.bmc.arsys.api.Constants; import com.bmc.arsys.api.Entry; 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.states.State; import com.nttdata.calender.supportgroup.SupportGroup; /** * Java API for Remedy */ @Service public class RemedyJavaAPI { private ARServerUser server; private String formName = "ASF:WI_TAS_Paket"; private static Logger logger = LogManager.getLogger("logger"); // 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() { server = new ARServerUser(); server.setServer("itsm-app-dev.asfinag.at"); server.setUser("changecalender_integration"); server.setPassword("VXrvLm4q#8P#MXthfZNc"); server.setPort(50000); this.connect(); // TODO: move to APIApplication.java or State.java - see where it fits State.getInstance().queryState(this); SupportGroup.getInstance().querySupportGroups(this); Contract.getInstance().queryContracts(this); } public ARServerUser getServer() { return this.server; } /** * 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 " + server.getServer()); } /** * Calls to impersonate a user with the provided username. * * @param userName the username * @throws ARException when the user is unknown */ public void impersonateUser(String userName) throws ARException { server.impersonateUser(userName); } /** * Frees up the impersonated user and sets it to null. */ public void freeImpersonatedUser() { server.setImpersonatedUser(null); } /** * Returns the currently impersonated user. * * @return the impersonated user */ public String getUser() { return server.getImpersonatedUser(); } /** * Retrieves the name of the field in the database for the provided field ID and * form name. * This is necessary for the filters used in the `get` method of {@link Change}. * * @param formName the form name * @param fieldId the field ID * @return the database name * @throws ARException when an ARException occurs */ public String getFieldDatabaseName(String formName, int fieldId) throws ARException { return server.getField(formName, fieldId).getName(); } /** * Creates an entry in a form using the given field values. * * @param query the query * @return the message indicating the entry has been created * @throws ARException when an ARException occurs */ public String createEntry(Query query) throws ARException { var formName = query.getFormName(); var values = query.getFieldValues(); var entry = new Entry(); values.forEach(value -> { entry.put(value.getFieldId(), value.getValue()); }); var entryIdOut = server.createEntry(formName, entry); logger.info("Entry created. The id # is " + entryIdOut); var lastStatus = server.getLastStatus(); if (!server.getLastStatus().isEmpty()) { logger.info("Warning: " + lastStatus); return lastStatus.toString(); } return "Entry created successfully. ID: " + entryIdOut; } /** * Takes an entry ID and a {@link Query} object with values and updates the * selected entry with the values provided in the query. * * @param entryId the entry ID * @param updates the updates * @throws ARException when an ARException occurs */ public void modifyEntry(String entryId, Query updates) throws ARException { var values = updates.getFieldValues(); var entry = server.getEntry(updates.getFormName(), entryId, updates.getFieldIds()); values.forEach(value -> { entry.put(value.getFieldId(), value.getValue()); }); server.setEntry(updates.getFormName(), entryId, entry, null, 0); } /** * Returns an entry given an entry ID with the fields specified in the * {@link Query} object. * * @param entryId the entry ID * @param query the query * @return the entry * @throws ARException when an ARException occurs */ public Entry getEntry(String entryId, Query query) throws ARException { return server.getEntry(query.getFormName(), entryId, query.getFieldIds()); } /** * Retrieves a list of {@link Entry} objects that match the specified qualifier, * field IDs, and form name. * * @param qualStr the qualifier passed as a string * @param fieldIds an array of integers representing the field IDs * @param formName the name of the form to query from * @param sorting the sort info * @return list of {@link Entry} objects that match the criteria * @throws ARException when an ARException occurs */ public List queryFieldsById(String qualStr, int[] fieldIds, String formName, SortInfo sorting, int sliceStart, int sliceEnd) throws ARException { if (qualStr.isEmpty()) qualStr = QUALSTR; logger.info("Retrieving entries from Form :" + formName + " with qualification " + qualStr); // Retrieve the detail info of all fields from the form. List fields = server.getListFieldObjects(formName); // Create the search qualifier. QualifierInfo qual = server.parseQualification(qualStr, fields, null, Constants.AR_QUALCONTEXT_DEFAULT); OutputInteger nMatches = new OutputInteger(); List sortOrder = new ArrayList(); if (sorting == null) { sortOrder.add(new SortInfo(2, Constants.AR_SORT_DESCENDING)); } else { sortOrder.add(sorting); } // Retrieve entries from the form using the given // qualification. var settingMaxEntries = new int[] { Constants.AR_SERVER_INFO_MAX_ENTRIES }; var serverSettings = server.getServerInfo(settingMaxEntries); var maxEntriesNumber = serverSettings.get(Constants.AR_SERVER_INFO_MAX_ENTRIES).getIntValue(); if (sliceEnd == 0) { return getAllListEntryObjects(qual, formName, sortOrder, fieldIds, nMatches, maxEntriesNumber); } return getSomeListEntryObjects(sliceStart, sliceEnd, qual, formName, sortOrder, fieldIds, nMatches, maxEntriesNumber); } private List getAllListEntryObjects(QualifierInfo qual, String formName, List sortOrder, int[] fieldIds, OutputInteger nMatches, int maxEntriesNumber) throws ARException { List entries = new ArrayList(); List fetched = new ArrayList(); var sliceStart = 0; do { fetched = server.getListEntryObjects( formName, qual, sliceStart, 0, sortOrder, fieldIds, true, nMatches); sliceStart += fetched.size(); entries.addAll(fetched); } while (fetched.size() == maxEntriesNumber); return entries; } private List getSomeListEntryObjects(int sliceStart, int sliceEnd, QualifierInfo qual, String formName, List sortOrder, int[] fieldIds, OutputInteger nMatches, int maxEntriesNumber) throws ARException { List entries = new ArrayList(); List fetched = new ArrayList(); var remainder = sliceEnd % maxEntriesNumber; var loop = sliceEnd / maxEntriesNumber; for (int i = 0; i < loop; i++) { fetched = server.getListEntryObjects( formName, qual, sliceStart, 0, sortOrder, fieldIds, true, nMatches); entries.addAll(fetched); sliceStart += fetched.size(); } entries.addAll(server.getListEntryObjects( formName, qual, sliceStart, remainder, sortOrder, fieldIds, true, nMatches)); return entries; } public int getFormSize(String qualStr, String formName) throws ARException { List fields = server.getListFieldObjects(formName); QualifierInfo qual = server.parseQualification(qualStr, fields, null, Constants.AR_QUALCONTEXT_DEFAULT); var statistics = server.getEntryStatistics(server.getForm(formName).getKey(), qual, null, Constants.AR_STAT_OP_COUNT, null); 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. * * @param entryId the ID of the entry * @param date the new date to be modified * @param fieldId the ID of the field */ void modifyEntryForReset(String entryId, Date date, int fieldId) { 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. "); } } }