com.sap.cds.services.EventContext Maven / Gradle / Ivy
/**************************************************************************
* (C) 2019-2024 SAP SE or an SAP affiliate company. All rights reserved. *
**************************************************************************/
package com.sap.cds.services;
import java.util.Set;
import com.sap.cds.reflect.CdsEntity;
import com.sap.cds.reflect.CdsModel;
import com.sap.cds.services.authentication.AuthenticationInfo;
import com.sap.cds.services.cds.CdsCreateEventContext;
import com.sap.cds.services.cds.CdsReadEventContext;
import com.sap.cds.services.changeset.ChangeSetContext;
import com.sap.cds.services.handler.Handler;
import com.sap.cds.services.messages.Messages;
import com.sap.cds.services.request.FeatureTogglesInfo;
import com.sap.cds.services.request.ParameterInfo;
import com.sap.cds.services.request.UserInfo;
import com.sap.cds.services.runtime.CdsRuntime;
/**
* The {@link EventContext} provides information about the event that is emitted via {@link Service#emit(EventContext)}.
* It summarizes all information required by the {@link Handler handlers} implementing the event and required by the framework to process the emitting of the event.
*
* It gives access to objects defined by the global context of the event, for example the {@link CdsModel} or the {@link ServiceCatalog}.
* Furthermore it gives access to objects which are request-bound, like for example the {@link UserInfo}.
*
* Most importantly it gives access to the information about the actual event ({@link #getEvent()}) and the targeted service ({@link #getService()}) and entity ({@link #getTarget()}).
*
* The {@link EventContext} interface is the super-interface of more specialized {@link EventContext} interfaces. Examples for these are {@link CdsReadEventContext} or {@link CdsCreateEventContext}.
* The generic interface provides access to all input and output parameters of an event via the {@link #get(String)} and {@link #put(String, Object)} methods.
* However the key and type of these parameters has to be known by the implementation. When using the specialized interfaces this is taken care of.
* The {@link #as(Class)} method can be used to overlay an existing generic {@link EventContext} with a more specialized {@link EventContext}.
*/
@EventName("*")
public interface EventContext {
/**
* Creates a new {@link EventContext}
*
* @param event the name of the event
* @param entityName the name of the entity
* @return the {@link EventContext}
*/
static EventContext create(String event, String entityName) {
return CoreFactory.INSTANCE.createEventContext(event, entityName);
}
/**
* Creates a new specialized {@link EventContext} of concrete type {@code T}
*
* @param the specialized {@link EventContext} type
* @param clazz the {@link Class} of the specialized {@link EventContext} type
* @param entityName the name of the entity
* @return the specialized {@link EventContext}
*/
static T create(Class clazz, String entityName) {
return create(clazz.getAnnotation(EventName.class).value(), entityName).as(clazz);
}
// GLOBAL CONTEXT: Access to CdsRuntime, CdsModel and Service Consumption APIs
/**
* Returns the underlying {@link CdsRuntime}.
*
* @return The {@link CdsRuntime} instance.
*/
CdsRuntime getCdsRuntime();
/**
* Returns the tenant-specific {@link CdsModel}.
* The tenant is determined based on the request-context and the tenant information available in {@link UserInfo}.
* If no tenant is specified, or if no tenant-specific model exists, the base model is returned.
*
* @return the (tenant-specific) {@link CdsModel}
*/
CdsModel getModel();
/**
* Returns the {@link ServiceCatalog}, populated with all available {@link Service} instances.
*
* @return the {@link ServiceCatalog}
*/
ServiceCatalog getServiceCatalog();
// REQUEST CONTEXT: Access to request information & transaction state
/**
* @return the request-dependent {@link ParameterInfo}
*/
ParameterInfo getParameterInfo();
/**
* @return the request-dependent {@link UserInfo}
*/
UserInfo getUserInfo();
/**
* @return the request-dependent {@link AuthenticationInfo}
*/
AuthenticationInfo getAuthenticationInfo();
/**
* @return the request-dependent {@link FeatureTogglesInfo}
*/
FeatureTogglesInfo getFeatureTogglesInfo();
/**
* @return the {@link Messages} container for this request
*/
Messages getMessages();
/**
* @return the currently active {@link ChangeSetContext}
*/
ChangeSetContext getChangeSetContext();
// LOCAL CONTEXT: Current service, event and entity
/**
* Returns the {@link Service} (Consumption API) of the service, targeted by the {@link EventContext}.
* This is the service, on which the {@link Service#emit(EventContext)} method (or specialized Consumption API) was called.
*
* @return the {@link Service} (Consumption API) of the service, targeted by the {@link EventContext}.
*/
Service getService();
/**
* @return the name of the emitted event
*/
String getEvent();
/**
* Returns the Reflection API {@link CdsEntity}, for which the {@link EventContext} was created.
* If the {@link EventContext} was created without any entity information from the {@link CdsModel}, null
will be returned.
*
* @return the {@link CdsEntity}, or null
if the {@link EventContext} was created without entity information.
*/
CdsEntity getTarget();
// PARAMETERS: Generic map of parameters, specialized getters/setters in other EventContext interfaces
/**
* Overlays an existing {@link EventContext} with a specialized EventContext interface (for example {@link CdsReadEventContext} or {@link CdsCreateEventContext})
* The specialized EventContext provides typed access to the input and output parameters of the event.
* It operates directly on the original {@link EventContext}. Therefore changes performed on the specialized EventContext instance, returned by this method, are written through to the original instance.
* In the same way changes to the original {@link EventContext} affect the specialized EventContext instance, returned by this method.
*
* @param the type of the specialized EventContext
* @param clazz The interface representing the specialized EventContext
* @return an instance of the specialized EventContext, providing typed access to this {@link EventContext} instance
*/
T as(Class clazz);
/**
* Returns an input or output parameter, which was stored under the given key.
* Whenever possible it is preferred to use specialized EventContext interfaces to guarantee correct and typed access.
*
* @param key the key of the parameter
* @return the parameter, null
if there was no value stored under the given key.
*/
Object get(String key);
/**
* Stores an input or output parameter under a given key
* Whenever possible it is preferred to use specialized EventContext interfaces to guarantee correct and typed access.
*
* @param key the key of the parameter
* @param value the parameter value
*/
void put(String key, Object value);
/**
* Returns an unmodifiable {@link Set set} containing the keys of all parameters.
*
* @return an unmodifiable {@link Set set} containing the keys of all parameters.
* @see #get(String)
* @see #put(String, Object)
* @since 1.17.0
*/
Set keySet();
/**
* Marks the {@link EventContext} as completed.
* As soon as a {@link EventContext} is completed, the {@link Service#emit(EventContext)} processing phases BEFORE and ON are finished.
* Setting an {@link EventContext} to completed, which is already completed has no effect.
*/
void setCompleted();
/**
* @return true, if {@link #setCompleted()} was called at least once.
*/
boolean isCompleted();
/**
* Proceeds with explicit execution of the {@code On} handler execution chain.
* It is typically used to:
*
* - Catch and handle exceptions thrown by underlying {@code On} handlers.
*
* - Combine semantics of a {@code Before} and {@code After} handler into a single method, without overwriting the effective {@code On} handler.
*
* Note, that executed next {@code On} handlers will most likely modify the {@link EventContext} and call {@link #setCompleted()} internally.
* Triggering this method after the context has been completed already is a noop.
* Triggering this method from an {@code Before} or {@code After} handler throws a {@link ServiceException}.
*/
void proceed();
}