enrichment schema
This commit is contained in:
102
plan-extended-anaylis/implementation_details.md
Normal file
102
plan-extended-anaylis/implementation_details.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Implementation Details: Trigger Detection with JDT
|
||||
|
||||
## 1. Finding `sendEvent` Calls
|
||||
We can use an `ASTVisitor` to find all `MethodInvocation` nodes.
|
||||
|
||||
```java
|
||||
public class SendEventVisitor extends ASTVisitor {
|
||||
@Override
|
||||
public boolean visit(MethodInvocation node) {
|
||||
if ("sendEvent".equals(node.getName().getIdentifier())) {
|
||||
// Found a call!
|
||||
// 1. Extract event (first argument)
|
||||
// 2. Identify the enclosing method and class
|
||||
}
|
||||
return super.visit(node);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Challenges in Event Extraction
|
||||
Events can be:
|
||||
- Enum constants: `Events.SUBMIT`
|
||||
- Strings: `"SUBMIT"`
|
||||
- Variables: `sm.sendEvent(eventFromPayload)` (Hard to resolve statically)
|
||||
|
||||
We should reuse `CodebaseContext.resolveState` logic (which is basically resolving an expression to a value/fqn).
|
||||
|
||||
## 2. Identifying Enclosing Context
|
||||
Once a `sendEvent` is found, we can traverse up the AST to find the `MethodDeclaration` and `TypeDeclaration`.
|
||||
|
||||
```java
|
||||
ASTNode parent = node.getParent();
|
||||
while (parent != null && !(parent instanceof MethodDeclaration)) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
// parent is now the MethodDeclaration
|
||||
```
|
||||
|
||||
### 2. Extracting Annotations
|
||||
From `MethodDeclaration`, we can check for mappings:
|
||||
- `@PostMapping`, `@GetMapping`, etc.
|
||||
- `@KafkaListener`: Extract `topics`, `groupId`.
|
||||
- `@RabbitListener`: Extract `queues`, `bindings` (Exchange/RoutingKey).
|
||||
|
||||
From `TypeDeclaration`, we can check for:
|
||||
- `@RestController`, `@Controller`
|
||||
- `@RequestMapping` at class level (to get base path)
|
||||
|
||||
## 3. Specialized WebFlux Analysis
|
||||
|
||||
### Annotation-based WebFlux
|
||||
This is largely identical to Spring MVC. The challenge is if the `sendEvent` is wrapped in a reactive operator.
|
||||
```java
|
||||
public Mono<Void> submit(Order order) {
|
||||
return service.save(order)
|
||||
.doOnNext(o -> stateMachine.sendEvent(Events.SUBMIT))
|
||||
.then();
|
||||
}
|
||||
```
|
||||
**Static Strategy**: We need to look inside `LambdaExpression` nodes passed to reactive operators (`doOnNext`, `flatMap`, `map`, `subscribe`). The `ASTVisitor` should traverse into these lambdas.
|
||||
|
||||
### Functional WebFlux (RouterFunctions)
|
||||
Functional endpoints are often defined as Beans returning `RouterFunction`.
|
||||
```java
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> route(OrderHandler handler) {
|
||||
return RouterFunctions.route(POST("/orders"), handler::submitOrder);
|
||||
}
|
||||
```
|
||||
**Static Strategy**:
|
||||
1. Find methods returning `RouterFunction`.
|
||||
2. Analyze the `MethodInvocation` chain (`route`, `andRoute`, `nest`).
|
||||
3. Extract the URI pattern and the `HandlerFunction` reference.
|
||||
4. If the handler is a method reference (`handler::submitOrder`), link it to the corresponding `MethodDeclaration`.
|
||||
|
||||
## 4. Specialized RabbitMQ Analysis
|
||||
`@RabbitListener` can be complex:
|
||||
```java
|
||||
@RabbitListener(bindings = @QueueBinding(
|
||||
value = @Queue(value = "orderQueue", durable = "true"),
|
||||
exchange = @Exchange(value = "orderExchange"),
|
||||
key = "order.created"
|
||||
))
|
||||
public void onOrder(Order order) { ... }
|
||||
```
|
||||
**Static Strategy**:
|
||||
1. Find `@RabbitListener`.
|
||||
2. If it has `bindings`, drill down into `@QueueBinding`, `@Queue`, `@Exchange` to extract the topology.
|
||||
3. If it only has `queues`, resolve the queue name (might be a SpEL expression or property placeholder, which we can try to resolve or just keep as-is).
|
||||
|
||||
## 5. Indirect Flow Detection (The "Service Link")
|
||||
If the project has multiple state machines, we need to know which one is being targeted.
|
||||
Usually, this is done via:
|
||||
- Autowiring by type: `StateMachine<States, Events> sm;`
|
||||
- Autowiring by name: `@Qualifier("mySm") StateMachine sm;`
|
||||
|
||||
We can look at the fields of the class where `sendEvent` is called.
|
||||
|
||||
## 6. Output Enhancement
|
||||
The `Exporter` should be modified to:
|
||||
- In DOT: Add nodes for Endpoints/Listeners and link them to the Events/Transitions.
|
||||
- In SCXML: Add metadata to transitions.
|
||||
Reference in New Issue
Block a user