Please wait. This can take some minutes ...
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.
org.ikasan.dashboard.ui.scheduler.component.SchedulerStatusWidget Maven / Gradle / Ivy
package org.ikasan.dashboard.ui.scheduler.component;
import com.vaadin.flow.component.*;
import com.vaadin.flow.component.html.Anchor;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.router.RouteConfiguration;
import com.vaadin.flow.shared.Registration;
import org.ikasan.dashboard.broadcast.FlowState;
import org.ikasan.dashboard.broadcast.FlowStateBroadcastListener;
import org.ikasan.dashboard.broadcast.FlowStateBroadcaster;
import org.ikasan.dashboard.broadcast.State;
import org.ikasan.dashboard.cache.CacheStateBroadcastListener;
import org.ikasan.dashboard.cache.CacheStateBroadcaster;
import org.ikasan.dashboard.cache.FlowStateCache;
import org.ikasan.dashboard.security.SecurityUtils;
import org.ikasan.dashboard.ui.util.SecurityConstants;
import org.ikasan.dashboard.ui.util.VaadimThreadFactory;
import org.ikasan.dashboard.ui.visualisation.component.FlowListFilteringGrid;
import org.ikasan.dashboard.ui.visualisation.component.filter.FlowSearchFilter;
import org.ikasan.dashboard.ui.visualisation.util.VisualisationType;
import org.ikasan.dashboard.ui.visualisation.view.GraphVisualisationDeepLinkView;
import org.ikasan.security.service.authentication.IkasanAuthentication;
import org.ikasan.spec.metadata.FlowMetaData;
import org.ikasan.spec.metadata.ModuleMetaData;
import org.ikasan.spec.metadata.ModuleMetaDataService;
import org.ikasan.spec.module.ModuleType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.context.SecurityContextHolder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
public class SchedulerStatusWidget extends Div implements FlowStateBroadcastListener, CacheStateBroadcastListener {
Logger logger = LoggerFactory.getLogger(SchedulerStatusWidget.class);
private FlowListFilteringGrid flowsGrid;
private ModuleMetaDataService moduleMetadataService;
private HashMap> stateMap;
private Div runningDiv;
private Icon runningIcon;
private Div stoppedDiv;
private Icon stoppedIcon;
private Div errorDiv;
private Icon errorIcon;
private Div recoveringDiv;
private Icon recoveringIcon;
private Div pausedDiv;
private Icon pausedDivIcon;
private Div unknownDiv;
private Icon unknownDivIcon;
private FlowSearchFilter flowSearchFilter;
private UI ui;
/**
* Constructor
*
* @param moduleMetadataService
* @param ui
*/
public SchedulerStatusWidget(ModuleMetaDataService moduleMetadataService, UI ui) {
this.moduleMetadataService = moduleMetadataService;
this.ui = ui;
this.createStatusView();
}
/**
* Create the view containing all the status icons.
*/
private void createStatusView() {
this.removeAll();
Div div = new Div();
div.addClassNames("card-counter");
div.setHeight("500px");
Icon icon = VaadinIcon.SEARCH.create();
icon.setSize("12pt");
Div layout = new Div();
layout.getElement().getStyle().set("margin-top", "20px");
layout.getElement().getStyle().set("margin-left", "10px");
layout.setHeight("50px");
Label flows = new Label(getTranslation("label.scheduler-agent-status", UI.getCurrent().getLocale()));
flows.getElement().getStyle().set("font-size", "16pt");
layout.add(flows);
this.runningDiv = new Div();
this.runningDiv.setId("runningDiv");
this.runningDiv.addClassNames("card-counter", "running");
this.runningDiv.setHeight("45px");
this.runningIcon = VaadinIcon.ARROW_CIRCLE_RIGHT.create();
this.runningIcon.setId("runningIcon");
this.runningIcon.getElement().getStyle().set("margin-left", "5px");
this.runningIcon.getElement().getStyle().set( "cursor", "pointer");
this.runningIcon.addClickListener((ComponentEventListener>) iconClickEvent -> {
this.createGrid(this.stateMap.get(State.RUNNING_STATE));
});
this.runningDiv.add(runningIcon);
this.stoppedDiv = new Div();
this.stoppedDiv.setId("stoppedDiv");
this.stoppedDiv.addClassNames("card-counter", "stopped");
this.stoppedDiv.setHeight("45px");
this.stoppedIcon = VaadinIcon.ARROW_CIRCLE_RIGHT.create();
this.stoppedIcon.setId("stoppedIcon");
this.stoppedIcon.getElement().getStyle().set("margin-left", "5px");
this.stoppedIcon.getElement().getStyle().set( "cursor", "pointer");
this.stoppedIcon.addClickListener((ComponentEventListener>) iconClickEvent -> {
this.createGrid(this.stateMap.get(State.STOPPED_STATE));
});
this.stoppedDiv.add(stoppedIcon);
this.errorDiv = new Div();
this.errorDiv.setId("errorDiv");
this.errorDiv.addClassNames("card-counter", "stoppedInError");
this.errorDiv.setHeight("45px");
this.errorIcon = VaadinIcon.ARROW_CIRCLE_RIGHT.create();
this.errorIcon.setId("errorIcon");
this.errorIcon.getElement().getStyle().set("margin-left", "5px");
this.errorIcon.getElement().getStyle().set( "cursor", "pointer");
this.errorIcon.addClickListener((ComponentEventListener>) iconClickEvent -> {
this.createGrid(this.stateMap.get(State.STOPPED_IN_ERROR_STATE));
});
this.errorDiv.add(errorIcon);
this.recoveringDiv = new Div();
this.recoveringDiv.setId("recoveringDiv");
this.recoveringDiv.addClassNames("card-counter", "recovering");
this.recoveringDiv.setHeight("45px");
this.recoveringIcon = VaadinIcon.ARROW_CIRCLE_RIGHT.create();
this.recoveringIcon.setId("recoveringIcon");
this.recoveringIcon.getElement().getStyle().set("margin-left", "5px");
this.recoveringIcon.getElement().getStyle().set( "cursor", "pointer");
this.recoveringIcon.addClickListener((ComponentEventListener>) iconClickEvent -> {
this.createGrid(this.stateMap.get(State.RECOVERING_STATE));
});
this.recoveringDiv.add(recoveringIcon);
this.pausedDiv = new Div();
this.pausedDiv.setId("pausedDiv");
this.pausedDiv.addClassNames("card-counter", "paused");
this.pausedDiv.setHeight("45px");
this.pausedDivIcon = VaadinIcon.ARROW_CIRCLE_RIGHT.create();
this.pausedDivIcon.setId("pausedDivIcon");
this.pausedDivIcon.getElement().getStyle().set("margin-left", "5px");
this.pausedDivIcon.getElement().getStyle().set( "cursor", "pointer");
this.pausedDivIcon.addClickListener((ComponentEventListener>) iconClickEvent -> {
this.createGrid(this.stateMap.get(State.PAUSED_STATE));
});
this.pausedDiv.add(pausedDivIcon);
this.unknownDiv = new Div();
this.unknownDiv.setId("unknownDiv");
this.unknownDiv.addClassNames("card-counter", "unknown");
this.unknownDiv.setHeight("45px");
this.unknownDivIcon = VaadinIcon.ARROW_CIRCLE_RIGHT.create();
this.unknownDivIcon.getElement().getStyle().set("margin-left", "5px");
this.unknownDivIcon.getElement().getStyle().set( "cursor", "pointer");
this.unknownDivIcon.addClickListener((ComponentEventListener>) iconClickEvent -> {
this.createGrid(this.stateMap.get(State.UNKNOWN_STATE));
});
unknownDiv.add(unknownDivIcon);
div.add(layout, runningDiv, stoppedDiv, errorDiv, recoveringDiv, pausedDiv, unknownDiv);
this.add(div);
ExecutorService executor = Executors.newSingleThreadExecutor(new VaadimThreadFactory("SchedulerStatusWidget"));
executor.execute(() -> this.recalculate());
}
/**
* Create the grid that allows the status drill down.
*
* @param flowsList
*/
private void createGrid(List flowsList) {
this.removeAll();
Div div = new Div();
div.addClassNames("card-counter");
div.setHeight("500px");
TextField filerTextField = new TextField();
filerTextField.setWidth("350px");
Icon icon = VaadinIcon.SEARCH.create();
icon.setSize("12pt");
filerTextField.setPrefixComponent(icon);
Div layout = new Div();
layout.getElement().getStyle().set("margin-top", "20px");
layout.getElement().getStyle().set("margin-left", "10px");
layout.setHeight("50px");
Label flows = new Label(getTranslation("label.scheduler-agent-status", UI.getCurrent().getLocale()));
flows.getElement().getStyle().set("font-size", "16pt");
Icon returnIcon = VaadinIcon.ARROW_CIRCLE_LEFT_O.create();
returnIcon.setId("returnIcon");
returnIcon.getElement().getStyle().set("margin-left", "5px");
returnIcon.getElement().getStyle().set( "cursor", "pointer");
returnIcon.addClickListener((ComponentEventListener>) iconClickEvent -> {
this.createStatusView();
});
filerTextField.getElement().getStyle().set("margin-left", "auto");
filerTextField.getElement().getStyle().set("float", "right");
layout.add(flows, returnIcon, filerTextField);
// Create a modulesGrid bound to the list
this.flowSearchFilter = new FlowSearchFilter();
this.flowsGrid = new FlowListFilteringGrid(flowsList, flowSearchFilter);
this.flowsGrid.setId("flowsGrid");
this.flowsGrid.removeAllColumns();
this.flowsGrid.setVisible(true);
this.flowsGrid.setWidthFull();
this.flowsGrid.setHeight("80%");
this.flowsGrid.addColumn(FlowMetaData::getName)
.setHeader(getTranslation("table-header.flow-name", UI.getCurrent().getLocale())).setKey("flowName")
.setFlexGrow(16);
this.flowsGrid.addColumn(new ComponentRenderer<>(moduleMetaData -> {
HorizontalLayout horizontalLayout = new HorizontalLayout();
String route = RouteConfiguration.forSessionScope()
.getUrl(GraphVisualisationDeepLinkView.class, VisualisationType.FLOW.name() + ":" + moduleMetaData.getName());
Anchor link = new Anchor(route, getTranslation("label.view", UI.getCurrent().getLocale()));
link.setTarget("_blank");
add(link);
horizontalLayout.add(link);
link.getStyle().set("color", "blue");
return horizontalLayout;
}));
div.add(layout, this.flowsGrid);
this.flowsGrid.addGridFiltering(filerTextField, this.flowSearchFilter::setFlowNameFilter);
this.flowsGrid.init();
this.add(div);
}
/**
* Helper method to recalculate the flow states and update the UI.
*/
public synchronized void recalculate() {
if(ui.isAttached()) {
this.initialiseStateMap();
List moduleMetaData = this.moduleMetadataService.findAll();
moduleMetaData = moduleMetaData.stream()
.filter(metadata -> metadata.getType() == ModuleType.SCHEDULER_AGENT)
.collect(Collectors.toList());
IkasanAuthentication authentication = (IkasanAuthentication) SecurityContextHolder.getContext().getAuthentication();
final Set accessibleModules = SecurityUtils.getAccessibleModules(authentication);
moduleMetaData.stream()
.filter(module -> {
if(authentication == null || authentication.hasGrantedAuthority(SecurityConstants.ALL_AUTHORITY)) {
return true;
}
else {
return accessibleModules.contains(module.getName());
}
})
.forEach(module -> module.getFlows().forEach(flow -> {
FlowState flowState = FlowStateCache.instance().get(module,flow.getName());
flow.setName(module.getName() + "." + flow.getName());
if(flowState == null) {
stateMap.get(State.UNKNOWN_STATE).add(flow);
}
else {
stateMap.get(flowState.getState()).add(flow);
}
}));
if(ui.isAttached()) {
ui.access(() -> {
if(this.stateMap == null) return;
this.runningDiv.removeAll();
this.runningDiv.setText(stateMap.get(State.RUNNING_STATE).size() + " "
+ getTranslation("status-label.running", UI.getCurrent().getLocale()));
if (stateMap.get(State.RUNNING_STATE) != null && stateMap.get(State.RUNNING_STATE).size() > 0) {
this.runningDiv.add(this.runningIcon);
}
this.stoppedDiv.removeAll();
this.stoppedDiv.setText(stateMap.get(State.STOPPED_STATE).size() + " "
+ getTranslation("status-label.stopped", UI.getCurrent().getLocale()));
if (stateMap.get(State.STOPPED_STATE).size() > 0) {
this.stoppedDiv.add(this.stoppedIcon);
}
this.errorDiv.removeAll();
this.errorDiv.setText(stateMap.get(State.STOPPED_IN_ERROR_STATE).size() + " "
+ getTranslation("status-label.stopped-in-error", UI.getCurrent().getLocale()));
if (stateMap.get(State.STOPPED_IN_ERROR_STATE) != null && stateMap.get(State.STOPPED_IN_ERROR_STATE).size() > 0) {
this.errorDiv.add(this.errorIcon);
}
this.recoveringDiv.removeAll();
this.recoveringDiv.setText(stateMap.get(State.RECOVERING_STATE).size() + " "
+ getTranslation("status-label.recovering", UI.getCurrent().getLocale()));
if (stateMap.get(State.RECOVERING_STATE) != null && stateMap.get(State.RECOVERING_STATE).size() > 0) {
this.recoveringDiv.add(this.recoveringIcon);
}
this.pausedDiv.removeAll();
this.pausedDiv.setText(stateMap.get(State.PAUSED_STATE).size() + " "
+ getTranslation("status-label.paused", UI.getCurrent().getLocale()));
if (stateMap.get(State.PAUSED_STATE) != null && stateMap.get(State.PAUSED_STATE).size() > 0) {
this.pausedDiv.add(this.pausedDivIcon);
}
this.unknownDiv.removeAll();
this.unknownDiv.setText(stateMap.get(State.UNKNOWN_STATE).size() + " "
+ getTranslation("status-label.unknown", UI.getCurrent().getLocale()));
if (stateMap.get(State.UNKNOWN_STATE) != null && stateMap.get(State.UNKNOWN_STATE).size() > 0) {
this.unknownDiv.add(this.unknownDivIcon);
}
});
}
}
}
/**
* Initialise the internal state map.
*/
private void initialiseStateMap() {
this.stateMap = new HashMap<>();
stateMap.put(State.RUNNING_STATE, new ArrayList<>());
stateMap.put(State.STOPPED_STATE, new ArrayList<>());
stateMap.put(State.STOPPED_IN_ERROR_STATE, new ArrayList<>());
stateMap.put(State.RECOVERING_STATE, new ArrayList<>());
stateMap.put(State.UNKNOWN_STATE, new ArrayList<>());
stateMap.put(State.PAUSED_STATE, new ArrayList<>());
}
@Override
protected void onAttach(AttachEvent attachEvent) {
this.recalculate();
FlowStateBroadcaster.register(this);
CacheStateBroadcaster.register(this);
}
@Override
protected void onDetach(DetachEvent detachEvent) {
FlowStateBroadcaster.unregister(this);
CacheStateBroadcaster.unregister(this);
}
@Override
public void receiveFlowStateBroadcast(FlowState flowState) {
this.recalculate();
logger.debug("Flow state update received!" + flowState);
}
@Override
public void receiveCacheStateBroadcast(FlowState flowState) {
this.recalculate();
logger.debug("Flow state update received!" + flowState);
}
}