Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package com.sap.ipe.ble.irp.handler;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.Optional;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Objects;
import java.util.stream.Stream;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.sap.cds.ql.Update;
import com.sap.cds.ql.cqn.CqnAnalyzer;
import com.sap.cds.ql.cqn.CqnSelect;
import com.sap.cds.ql.cqn.CqnUpdate;
import com.sap.cds.ql.cqn.CqnStatement;
import com.sap.cds.reflect.CdsAction;
import com.sap.cds.reflect.CdsAnnotation;
import com.sap.cds.reflect.CdsEntity;
import com.sap.cds.reflect.CdsType;
import com.sap.cds.services.authentication.JwtTokenAuthenticationInfo;
import com.sap.cds.services.persistence.PersistenceService;
import com.sap.ipe.ble.irp.exceptions.ExtensionException;
import com.sap.ipe.ble.irp.handler.configuration.SourceConfig;
import com.sap.ipe.ble.irp.handler.constants.Constants;
import com.sap.ipe.ble.irp.handler.services.DeepSelectionService;
import com.sap.ipe.ble.irp.handler.services.HttpDestinationService;
import com.sap.ipe.ble.irp.handler.services.MessageService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sap.ipe.ble.irp.handler.services.ResultService;
import com.sap.ipe.ble.irp.secuirty.auditlog.logger.AuditEventLogger;
import com.sap.ipe.ble.irp.utils.Translator;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import com.sap.cds.Result;
import com.sap.cds.Row;
import com.sap.cds.impl.parser.token.Jsonizer;
import com.sap.cds.services.EventContext;
import com.sap.cds.services.ServiceException;
import com.sap.cds.services.cds.ApplicationService;
import com.sap.cds.services.handler.EventHandler;
import com.sap.cds.services.handler.annotations.On;
import com.sap.cds.services.handler.annotations.ServiceName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
/***
* GenericHandler is used to call any custom specific events
* Based on the annotations defined, custom specific actions will be triggered.
*/
@Service
@ServiceName(value = "*", type = ApplicationService.class)
public class GenericHandler implements EventHandler {
@Autowired
DeepSelectionService deepSelection;
@Autowired
HttpDestinationService httpDestinationService;
@Autowired
MessageService messageService;
@Autowired
ResultService resultData;
@Autowired
SourceConfig sourceConfig;
@Autowired
PersistenceService db;
@Autowired
AuditEventLogger auditEventLogger;
private static final String CLASSNAME = "GenericHandler";
private final Logger log = LoggerFactory.getLogger(CLASSNAME);
private static final ObjectMapper objectMapper = new ObjectMapper ();
/***
* This method is called when any action is performed by the user
* Based on the annotation destination passed, the call is triggered for custom actions
* @param context event context called
*/
@On(entity = "*")
public void onHandler(EventContext context){
List elements = new ArrayList<>();
CdsAction actionName;
Optional> destination;
Optional> timeOutAnnotation;
CdsEntity targetEntity;
int timeOutConfig = 60000;
String payload;
String auditLogData;
Result result;
Row resultSet;
HttpResponse httpResponse;
targetEntity = context.getTarget();
try {
if (targetEntity != null) {
String entityName = targetEntity.getQualifiedName();
String targetName = targetEntity.getName();
String entitySetName = targetName.replace(targetName.charAt(0), targetName.toLowerCase().charAt(0));
String event = context.getEvent(); //actionName
if (targetEntity.findAction(event).isPresent()) {
actionName = targetEntity.getAction(event);
destination = actionName.findAnnotation(Constants.DESTINATION_NAME);
if (destination.isPresent()) {
Object cqn = context.get(Constants.CQN);
if (cqn instanceof CqnStatement) {
timeOutAnnotation = actionName.findAnnotation(Constants.TIME_OUT);
if (timeOutAnnotation.isPresent() && (Integer) timeOutAnnotation.get().getValue() < timeOutConfig) {
timeOutConfig = (Integer) timeOutAnnotation.get().getValue();
}
result = fetchResultFromCqn(context, actionName, targetEntity, cqn);
resultSet = result.single();
// Collect target elements from the select query result
result.rowType().elements().forEach(it -> elements.add(it.getName()));
//Create payload Data to pass to Remote Handler
payload = formRemoteExtensionPayload(context, resultSet, entityName, event, entitySetName);
//Audit Event Log before calling the remote handler
auditLogData = Constants.remoteActionTriggeredData + payload;
auditEventLogger.emitSecurityEvent(Constants.remoteActionTriggered,auditLogData);
//Fetch the response from Remote Handler
httpResponse = httpDestinationService.callRemoteExtension(timeOutConfig, payload, destination);
//Process the received response
processRemoteExtensionResponse(context, httpResponse, targetEntity, event, resultSet, entityName, elements);
}
}
}
}
}
catch(ExtensionException extensionException){
log.error(Constants.GENERIC_HANDLER_ERROR + extensionException.getLocalizedMessage());
throw new ServiceException(extensionException.getLocalizedMessage());
}
catch (Exception exception){
log.error(Constants.UNEXPECTED_ERROR + exception.getLocalizedMessage());
throw new ServiceException(Translator.toLocale(Constants.PROCESS_REQUEST_ERROR));
}
}
private Result selectQueryData(CqnSelect data){
return db.run(data);
}
private Result updateQueryData(CqnUpdate data){
return db.run(data);
}
private Result fetchResultFromCqn(EventContext context, CdsAction actionName, CdsEntity targetEntity, Object cqn){
CqnSelect query;
query = (CqnSelect) cqn;
Map contextParameters;
Optional> deepSelect;
deepSelect = actionName.findAnnotation(Constants.DEEP_SELECT_NAME);
if (deepSelect.isPresent() && deepSelect.get().getValue().equals(true)) {
// If deepSelect at entity is present & is marked to true, only then fetch the entire data
contextParameters = CqnAnalyzer.create(context.getModel()).analyze(query).targetKeyValues();
//Include only composition data and not association data during deep Select
query = deepSelection.getDeepSelectData(contextParameters,targetEntity);
}
return selectQueryData(query);
}
private String formRemoteExtensionPayload(EventContext context, Row resultSet, String entityName,String event, String entitySetName) throws ExtensionException {
try {
String token;
String payload;
Map resultMap = new HashMap<>();
Map dataPayload;
// Pass the JWT token to Remote Handler
token = ((JwtTokenAuthenticationInfo) context.getCdsRuntime().getProvidedAuthenticationInfo()).getToken();
payload = Jsonizer.object(Constants.DATA, resultSet).put(Constants.SERVICE, entityName)
.put(Constants.ENTITY, event).put(Constants.USER_CLAIM, token).toJson();
dataPayload = objectMapper.readValue(payload, Map.class);
resultMap.put(entitySetName, dataPayload.get(Constants.DATA));
// Read the additional parameters from dialog and add it to arguments
// So that it can be pass down as data map to the remote handler
Stream contextAdditionalParams = context.keySet().stream();
for (Iterator iterator = contextAdditionalParams.iterator(); iterator.hasNext(); ) {
String actionParameterName = iterator.next();
if (!Objects.equals(actionParameterName, Constants.CQN)
&& !actionParameterName.matches(entitySetName)) {
resultMap.put(actionParameterName, context.get(actionParameterName));
}
}
// final Payload data to send to Remote Handler
dataPayload.put(Constants.DATA, resultMap);
payload = objectMapper.writeValueAsString(dataPayload);
return payload;
}
catch (JsonProcessingException exception) {
log.error(Constants.PAYLOAD_ERROR + exception.getLocalizedMessage());
throw new ExtensionException(Translator.toLocale(Constants.FAIL_ON_UNKNOWN_PROPERTIES));
}
}
private void processRemoteExtensionResponse(EventContext context, HttpResponse httpResponse, CdsEntity targetEntity, String event, Row resultSet, String entityName, List elements ) throws ExtensionException {
int statusCode;
JSONObject response;
Optional entityReturnType;
statusCode = httpResponse.getStatusLine().getStatusCode();
try {
// Receive the data as response
InputStream responseEntityStream = httpResponse.getEntity().getContent();
response = new JSONObject(
IOUtils.toString(responseEntityStream, StandardCharsets.UTF_8));
}
catch (IOException | JSONException exception) {
log.error(Constants.RESPONSE_ERROR + exception.getLocalizedMessage());
throw new ExtensionException(Translator.toLocale(Constants.INTERNAL_SERVER_ERROR));
}
if ((statusCode >= Constants.STATUS_CODE_LOW && statusCode <= Constants.STATUS_CODE_HIGH)) {
if (response.has(Constants.DATA)) {
// get the return type of the event
entityReturnType = targetEntity.getAction(event).returnType();
// If "Data" is null, show the corresponding Messages from Remote Handler.
// If "Data" is not null, show the updated data and messages from Remote Handler
if (!response.get(Constants.DATA).equals(null)
&& entityReturnType.isPresent()) {
JSONObject data = resultData.getFinalData(elements,response);
//Put the extended field data to resultSet from the select Query
resultSet.putAll(data.toMap());
CqnUpdate update = Update.entity(entityName).entry(resultSet);
// Update the data back to the table
Result queryUpdate = updateQueryData(update);
context.put(Constants.RESULT, queryUpdate);
} else if (entityReturnType.isPresent()) {
//If return type is present and data is "null", set the same result fetched during select.
context.put(Constants.RESULT, resultSet);
}
//Show messages received from Remote Handler
messageService.showMessages(context, response);
// Set the context to complete.
context.setCompleted();
}
}
else{
//If response has error, get the code and show the corresponding service exception
JSONObject errorStatus = response.getJSONObject(Constants.ERROR);
throw new ExtensionException(Integer.valueOf(errorStatus.get(Constants.CODE).toString()),
(String) errorStatus.get(Constants.MESSAGE));
}
}
}