use of org.springframework.webflow.engine.State in project cas by apereo.
the class BaseMultifactorWebflowConfigurerTests method ensureAllTransitionDestinationsExistInFlow.
/**
* Ensures that, for every transition within this MFA flow, the target
* state is present within the flow.
*/
@Test
public void ensureAllTransitionDestinationsExistInFlow() {
val registry = getMultifactorFlowDefinitionRegistry();
assertTrue(registry.containsFlowDefinition(getMultifactorEventId()));
val flow = (Flow) registry.getFlowDefinition(getMultifactorEventId());
val states = Arrays.asList(flow.getStateIds());
states.forEach(stateId -> {
val state = (State) flow.getState(stateId);
if (state instanceof TransitionableState) {
((TransitionableState) state).getTransitionSet().forEach(t -> {
assertTrue(flow.containsState(t.getTargetStateId()), () -> String.format("Destination of transition [%s]-%s->[%s] must be in flow definition", stateId, t.getId(), t.getTargetStateId()));
});
}
});
}
use of org.springframework.webflow.engine.State in project cas by apereo.
the class SpringWebflowEndpoint method getStateDetails.
private static Map<String, Object> getStateDetails(final Flow flowDefinition, final String st) {
val state = (State) flowDefinition.getState(st);
val stateMap = new LinkedHashMap<String, Object>();
if (!state.getAttributes().asMap().isEmpty()) {
stateMap.put("attributes", CollectionUtils.wrap(state.getAttributes()));
}
if (StringUtils.isNotBlank(state.getCaption())) {
stateMap.put("caption", state.getCaption());
}
var acts = StreamSupport.stream(state.getEntryActionList().spliterator(), false).map(SpringWebflowEndpoint::convertActionToString).collect(Collectors.toList());
if (!acts.isEmpty()) {
stateMap.put("entryActions", acts);
}
if (state instanceof ActionState) {
acts = StreamSupport.stream(((ActionState) state).getActionList().spliterator(), false).map(SpringWebflowEndpoint::convertActionToString).collect(Collectors.toList());
if (!acts.isEmpty()) {
stateMap.put("actionList", acts);
}
}
if (state instanceof EndState) {
stateMap.put("isEndState", Boolean.TRUE);
}
if (state.isViewState()) {
val viewState = (ViewState) state;
stateMap.put("isViewState", state.isViewState());
stateMap.put("isRedirect", viewState.getRedirect());
acts = StreamSupport.stream(state.getEntryActionList().spliterator(), false).map(Object::toString).collect(Collectors.toList());
if (!acts.isEmpty()) {
stateMap.put("renderActions", viewState.getRenderActionList());
}
acts = Arrays.stream(viewState.getVariables()).map(variable -> variable.getName() + " -> " + variable.getValueFactory().toString()).collect(Collectors.toList());
if (!acts.isEmpty()) {
stateMap.put("viewVariables", acts);
}
val field = ReflectionUtils.findField(viewState.getViewFactory().getClass(), "viewId");
if (field != null) {
ReflectionUtils.makeAccessible(field);
val exp = (Expression) ReflectionUtils.getField(field, viewState.getViewFactory());
stateMap.put("viewId", StringUtils.defaultIfBlank(Objects.requireNonNull(exp).getExpressionString(), exp.getValue(null).toString()));
} else if (viewState.getViewFactory() instanceof ActionExecutingViewFactory) {
val factory = (ActionExecutingViewFactory) viewState.getViewFactory();
if (factory.getAction() instanceof ExternalRedirectAction) {
val redirect = (ExternalRedirectAction) factory.getAction();
val uri = ReflectionUtils.findField(redirect.getClass(), "resourceUri");
ReflectionUtils.makeAccessible(Objects.requireNonNull(uri));
val exp = (Expression) ReflectionUtils.getField(uri, redirect);
stateMap.put("viewId", "externalRedirect -> #{" + Objects.requireNonNull(exp).getExpressionString() + '}');
} else {
stateMap.put("viewId", factory.getAction().toString());
}
} else {
LOGGER.info("Field viewId cannot be located on view state [{}]", state);
}
}
if (state instanceof TransitionableState) {
val stDef = (TransitionableState) state;
acts = StreamSupport.stream(stDef.getExitActionList().spliterator(), false).map(Object::toString).collect(Collectors.toList());
if (!acts.isEmpty()) {
stateMap.put("exitActions", acts);
}
acts = Arrays.stream(stDef.getTransitions()).map(tr -> tr.getId() + " -> " + tr.getTargetStateId()).collect(Collectors.toList());
if (!acts.isEmpty()) {
stateMap.put("transitions", acts);
}
}
return stateMap;
}
use of org.springframework.webflow.engine.State in project cas by apereo.
the class SpringWebflowEndpoint method getReport.
/**
* Get SWF report.
*
* @param flowId the flow id
* @param stateId the state id
* @return JSON representing the current state of SWF.
*/
@ReadOperation
@Operation(summary = "Get Spring webflow report using an optional flow id", parameters = { @Parameter(name = "flowId"), @Parameter(name = "stateId") })
public Map<?, ?> getReport(@Nullable final String flowId, @Nullable final String stateId) {
val jsonMap = new LinkedHashMap<String, Object>();
val executionPlan = applicationContext.getBean(CasWebflowExecutionPlan.BEAN_NAME, CasWebflowExecutionPlan.class);
executionPlan.execute();
val map = applicationContext.getBeansOfType(FlowDefinitionRegistry.class);
map.forEach((k, value) -> Arrays.stream(value.getFlowDefinitionIds()).filter(currentId -> StringUtils.isBlank(flowId) || flowId.equalsIgnoreCase(currentId)).forEach(id -> {
val flowDefinition = (Flow) value.getFlowDefinition(id);
val flowDetails = new LinkedHashMap<String, Object>();
flowDetails.put("startState", flowDefinition.getStartState().getId());
val startActions = StreamSupport.stream(flowDefinition.getStartActionList().spliterator(), false).map(SpringWebflowEndpoint::convertActionToString).collect(Collectors.toList());
if (!startActions.isEmpty()) {
flowDetails.put("startActions", startActions);
}
val states = new LinkedHashMap<String, Map>();
Arrays.stream(flowDefinition.getStateIds()).filter(st -> StringUtils.isBlank(stateId) || RegexUtils.find(stateId, st)).forEach(st -> {
val stateMap = getStateDetails(flowDefinition, st);
states.put(st, stateMap);
});
flowDetails.put("states", states);
flowDetails.put("possibleOutcomes", flowDefinition.getPossibleOutcomes());
flowDetails.put("stateCount", flowDefinition.getStateCount());
var acts = StreamSupport.stream(flowDefinition.getEndActionList().spliterator(), false).map(SpringWebflowEndpoint::convertActionToString).collect(Collectors.toList());
if (!acts.isEmpty()) {
flowDetails.put("endActions", acts);
}
acts = StreamSupport.stream(flowDefinition.getGlobalTransitionSet().spliterator(), false).map(tr -> tr.getId() + " -> " + tr.getTargetStateId() + " @ " + tr.getExecutionCriteria().toString()).collect(Collectors.toList());
if (!acts.isEmpty()) {
flowDetails.put("globalTransitions", acts);
}
acts = Arrays.stream(flowDefinition.getExceptionHandlerSet().toArray()).map(Object::toString).collect(Collectors.toList());
if (!acts.isEmpty()) {
flowDetails.put("exceptionHandlers", acts);
}
val vars = Arrays.stream(flowDefinition.getVariables()).map(FlowVariable::getName).collect(Collectors.joining(","));
if (StringUtils.isNotBlank(vars)) {
flowDetails.put("variables", vars);
}
jsonMap.put(id, flowDetails);
}));
return jsonMap;
}
Aggregations