Java tutorial
/* * MIT License * * Copyright (c) 2016 Altisource * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package org.ecloudmanager.web.faces; import com.google.common.collect.Sets; import org.apache.commons.lang3.StringUtils; import org.bson.types.ObjectId; import org.ecloudmanager.components.cytoscape.model.CyModel; import org.ecloudmanager.components.cytoscape.model.CyNode; import org.ecloudmanager.deployment.app.ApplicationDeployment; import org.ecloudmanager.deployment.core.Deployable; import org.ecloudmanager.deployment.history.DeploymentAttempt; import org.ecloudmanager.domain.LoggingEventEntity; import org.ecloudmanager.jeecore.web.faces.Controller; import org.ecloudmanager.jeecore.web.faces.FacesSupport; import org.ecloudmanager.repository.deployment.DeploymentAttemptRepository; import org.ecloudmanager.repository.deployment.LoggingEventRepository; import org.ecloudmanager.service.deployment.ApplicationDeploymentService; import org.ecloudmanager.service.execution.Action; import org.ecloudmanager.service.execution.ActionGroup; import org.ecloudmanager.service.execution.SingleAction; import org.jetbrains.annotations.NotNull; import org.omnifaces.cdi.Param; import org.primefaces.event.SelectEvent; import org.primefaces.event.ToggleEvent; import org.primefaces.event.UnselectEvent; import org.primefaces.model.Visibility; import javax.annotation.PostConstruct; import javax.inject.Inject; import java.io.Serializable; import java.util.*; import java.util.stream.Collectors; import static org.ecloudmanager.deployment.history.DeploymentAttempt.Type; @Controller public class DeploymentActionController extends FacesSupport implements Serializable { private static final long serialVersionUID = 1219058684206564494L; private static final String GRAPH_STYLE = "node {" + "content: data(label);" + "shape: data(shape);" + "background-color: #FFFFFC;" + // "background-color: data(color);" + "width: label;" + "height: label;" + "border-color: black;" + "border-width: 1;" + "text-halign: center;" + "text-valign: center;" + "padding-left: 10;" + "padding-right: 10;" + "padding-top: 4;" + "padding-bottom: 4;" + "font-size: 10;" + "compound-sizing-wrt-labels: include;" + "} " + ":parent {" + "text-halign: center;" + "text-valign: top;" + "width: data(size);" + "height: data(size);" + "padding-left: 4;" + "padding-right: 4;" + "padding-top: 4;" + "padding-bottom: 4;" + "background-color: #F7F7FA;" + "} " + ":selected {" + "border-color: yellow;" + "line-color: yellow;" + "border-width: 1;" + "source-arrow-color: #000;" + "target-arrow-color: #000;" + "} " + "edge {" + "content: data(label);" + "line-color: data(color);" + "target-arrow-color: data(color);" + "target-arrow-shape: data(shape);" + "width: data(width);" + // "curve-style: bezier;" + // "control-point-step-size: 40;" + // "curve-style: segments;" + // "segment-distances: 40;" + // "segment-weights: 0.5;" + "} " + "node.hidden {" + "display: none;" + "visibility: hidden;" + "} " + "node.labelHolder:active {" + "overlay-padding: 20;" + "} " + "node.labelHolder {" + "background-opacity: 0;" + "border-width: 0;" + "border-opacity: 0;" + "padding-top: 8;" + "} " + /////////////// Action statuses /////////////// // pending - render as default // rollback_running - now irrelevant "node.running {" + "background-color: #FFFF77;" + "} " + "node.running:parent {" + "background-color: #F7F7FA;" + "} " + "node.successful {" + "background-color: #5DFF5D;" + "} " + "node.successful:parent {" + "background-color: #4DEE4D;" + "} " + "node.not_run {" + "background-color: #FFFFFF;" + "} " + "node.not_run:parent {" + "background-color: #FFFFFF;" + "} " + "node.failed {" + "background-color: #FF9999;" + "} " + "node.failed:parent {" + "background-color: #cccccc;" + //#ffbfbf "}" ///////////////////////////////////////////////// ; @SuppressWarnings("CdiInjectionPointsInspection") @Inject @Param(converter = "topLevelDeployableConverter") private ApplicationDeployment deployment; @SuppressWarnings("CdiInjectionPointsInspection") @Inject @Param private Type actionType; @SuppressWarnings("CdiInjectionPointsInspection") @Inject @Param(converter = "deploymentAttemptConverter") private DeploymentAttempt deploymentAttempt; @Inject private transient ApplicationDeploymentService applicationDeploymentService; @Inject private transient DeploymentAttemptRepository deploymentAttemptRepository; // @Inject // private transient DeploymentLogsRepository deploymentLogsRepository; @Inject private transient LoggingEventRepository deploymentLogsRepository; private CyModel cyModel; private DeploymentAttempt attempt; private HashMap<Action, CyNode> action2cyNode; private Set<ObjectId> expandedRows = new HashSet<>(); @PostConstruct public void init() { if (deploymentAttempt == null) { switch (actionType) { case CREATE: case UPDATE: attempt = applicationDeploymentService.getDeployAction(deployment); actionType = attempt.getType(); break; case DELETE: attempt = new DeploymentAttempt(deployment, deployment.getDeployer().getDeleteAction(deployment), actionType); break; } } else { deployment = (ApplicationDeployment) deploymentAttempt.getDeployment(); attempt = deploymentAttempt; attempt.getAction().restoreDependencies(); } cyModel = generateGraphModel(); loadActionStatuses(); } public Deployable getDeployment() { return deployment; } public void setDeployment(ApplicationDeployment deployment) { this.deployment = deployment; } public Type getActionType() { return actionType; } public void setActionType(Type actionType) { this.actionType = actionType; } public DeploymentAttempt getDeploymentAttempt() { return deploymentAttempt; } public CyModel getGraphModel() { return cyModel; } @NotNull private CyModel generateGraphModel() { CyModel graphModel = new CyModel(); graphModel.setStyle(GRAPH_STYLE); generateGraphModel(graphModel); //graphModel.setLayout("{name: 'breadthfirst', directed: true }"); graphModel.setLayout("{name: 'dagre', rankDir: 'TB', nodeSep: 60, rankSep: 25, edgeSep: 3, padding: 8 }"); return graphModel; } private void generateGraphModel(CyModel graphModel) { action2cyNode = new HashMap<>(); generateActionNodes(graphModel, attempt.getAction(), null, action2cyNode); generateDependencyEdges(graphModel, attempt.getAction(), action2cyNode); } private void generateActionNodes(CyModel graphModel, Action action, CyNode parent, Map<Action, CyNode> action2node) { boolean hasChildren = action instanceof ActionGroup; CyNode node = graphModel.addNode(action.getId(), hasChildren ? "" : action.getLabel()); CyNode node2 = node; if (hasChildren) { node2 = graphModel.addNode(action.getId() + "labelHolder", action.getLabel()); node2.setClasses("labelHolder"); node2.setParent(node); } final CyNode parentForChildren = node2; action2node.put(action, node); if (parent != null) { node.setParent(parent); } if (hasChildren) { ((ActionGroup) action).getActions().forEach( childAction -> generateActionNodes(graphModel, childAction, parentForChildren, action2node)); } } private void generateDependencyEdges(CyModel graphModel, Action rootAction, Map<Action, CyNode> action2node) { rootAction.stream().forEach(action -> action.getDependencies(rootAction).stream() .forEach(dependency -> graphModel.addEdge(action2node.get(dependency), action2node.get(action)))); } public boolean canExecuteAction() { return attempt.getAction().getStatus() == Action.Status.PENDING; } public void executeAction() { if (canExecuteAction()) { applicationDeploymentService.execute(attempt, null); } } public void loadActionStatuses() { attempt.getAction().stream().forEach(action -> { CyNode node = action2cyNode.get(action); setStatusClass(node, action.getStatus()); }); } private void setStatusClass(CyNode node, Action.Status status) { String statusClass = status.name().toLowerCase(); HashSet<String> classes = Sets.newHashSet(node.getClasses().split(" ")); if (classes.contains(statusClass)) { return; } HashSet<Action.Status> classesToRemove = Sets.newHashSet(Action.Status.values()); classesToRemove.remove(status); classes.removeAll( classesToRemove.stream().map(Enum::name).map(String::toLowerCase).collect(Collectors.toSet())); classes.add(statusClass); node.setClasses(StringUtils.join(classes, " ").trim()); } public List<LoggingEventEntity> getLogs() { Action selectedAction = getSelectedAction(); if (selectedAction != null) { Set<SingleAction> actions = selectedAction.stream().flatMap(Action::stream) .filter(SingleAction.class::isInstance).map(SingleAction.class::cast) .collect(Collectors.toSet()); return deploymentLogsRepository.findForActions(actions); } return Collections.emptyList(); } private Action getSelectedAction() { Collection<CyNode> selectedNodes = cyModel.getSelectedNodes(); return attempt.getAction().stream().filter((action) -> selectedNodes.contains(action2cyNode.get(action))) .findAny().orElseGet(() -> null); } public String getSelectedActionLabel() { Action selectedAction = getSelectedAction(); return selectedAction == null ? "no action is selected" : selectedAction.getLabel(); } public void onSelectNode(SelectEvent event) { expandedRows.clear(); } public void onUnselectNode(UnselectEvent event) { } public void onRowToggle(ToggleEvent event) { if (event.getVisibility() == Visibility.VISIBLE) { expandedRows.add(((LoggingEventEntity) event.getData()).getId()); } else { expandedRows.remove(((LoggingEventEntity) event.getData()).getId()); } } public boolean isLogMessageExpanded(LoggingEventEntity logMessage) { return expandedRows.contains(logMessage.getId()); } }