/* * Copyright 2017 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kie.workbench.common.stunner.cm.client.command.graph; import java.util.Collection; import java.util.List; import java.util.Optional; import org.kie.workbench.common.stunner.core.command.CommandResult; import org.kie.workbench.common.stunner.core.graph.Edge; import org.kie.workbench.common.stunner.core.graph.Node; import org.kie.workbench.common.stunner.core.graph.command.GraphCommandExecutionContext; import org.kie.workbench.common.stunner.core.graph.command.GraphCommandResultBuilder; import org.kie.workbench.common.stunner.core.graph.command.impl.AbstractGraphCommand; import org.kie.workbench.common.stunner.core.graph.content.relationship.Child; import org.kie.workbench.common.stunner.core.graph.impl.EdgeImpl; import org.kie.workbench.common.stunner.core.rule.RuleViolation; import org.kie.workbench.common.stunner.core.rule.context.impl.RuleContextBuilder; import org.kie.workbench.common.stunner.core.util.UUID; public class CaseManagementSetChildNodeGraphCommand extends AbstractGraphCommand { protected final Optional<Integer> index; protected final Optional<Node> originalParent; protected final Optional<Integer> originalIndex; private final Node parent; private final Node child; public CaseManagementSetChildNodeGraphCommand(final Node parent, final Node child, final Optional<Integer> index, final Optional<Node> originalParent, final Optional<Integer> originalIndex) { this.parent = parent; this.child = child; this.index = index; this.originalParent = originalParent; this.originalIndex = originalIndex; } @Override @SuppressWarnings("unchecked") public CommandResult<RuleViolation> execute(final GraphCommandExecutionContext context) { final CommandResult<RuleViolation> results = allow(context); if (results.getType().equals(CommandResult.Type.ERROR)) { return results; } //Remove existing relationship getEdgeForTarget(originalParent, child).ifPresent((e) -> removeRelationship(e, originalParent.get(), child, context)); //Add new relationship addRelationship(parent, child, index, context); return results; } @SuppressWarnings("unchecked") private Optional<Edge> getEdgeForTarget(final Optional<Node> parent, final Node child) { return parent.flatMap((p) -> { Edge edge = null; final List<Edge> outEdges = parent.get().getOutEdges(); if (!(outEdges == null || outEdges.isEmpty())) { for (Edge outEdge : outEdges) { if (outEdge.getContent() instanceof Child) { final Node targetNode = outEdge.getTargetNode(); if (child.equals(targetNode)) { edge = outEdge; break; } } } } return Optional.ofNullable(edge); }); } @SuppressWarnings("unchecked") private void removeRelationship(final Edge e, final Node parent, final Node child, final GraphCommandExecutionContext context) { e.setSourceNode(null); e.setTargetNode(null); parent.getOutEdges().remove(e); child.getInEdges().remove(e); getMutableIndex(context).removeEdge(e); } @SuppressWarnings("unchecked") private void addRelationship(final Node parent, final Node child, final Optional<Integer> index, final GraphCommandExecutionContext context) { final String uuid = UUID.uuid(); final Edge<Child, Node> edge = new EdgeImpl<>(uuid); edge.setContent(new Child()); edge.setSourceNode(parent); edge.setTargetNode(child); if (index.isPresent()) { parent.getOutEdges().add(index.get(), edge); } else { parent.getOutEdges().add(edge); } child.getInEdges().add(edge); getMutableIndex(context).addEdge(edge); } @SuppressWarnings("unchecked") protected CommandResult<RuleViolation> check(final GraphCommandExecutionContext context) { final Collection<RuleViolation> violations = doEvaluate(context, RuleContextBuilder.GraphContexts.containment(getGraph(context), parent, child)); return new GraphCommandResultBuilder(violations).build(); } @Override @SuppressWarnings("unchecked") public CommandResult<RuleViolation> undo(final GraphCommandExecutionContext context) { //Remove existing relationship getEdgeForTarget(Optional.of(parent), child).ifPresent((e) -> removeRelationship(e, parent, child, context)); //Add new relationship originalParent.ifPresent((p) -> addRelationship(originalParent.get(), child, originalIndex, context)); return GraphCommandResultBuilder.SUCCESS; } }