Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.openflamingo.engine.dag; import org.apache.commons.lang.StringUtils; import org.jgrapht.graph.DefaultEdge; import org.jgrapht.graph.DirectedMultigraph; import org.jgrapht.traverse.TopologicalOrderIterator; import org.openflamingo.engine.util.WorkflowUtils; import org.openflamingo.model.workflow.ActionType; import org.openflamingo.model.workflow.BaseType; import org.openflamingo.model.workflow.NodeType; import org.openflamingo.model.workflow.Workflow; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; /** * Topological Sort Graph Algorithm Workflow Execution Planner. * * @author Byoung Gon, Kim * @since 0.2 */ public class TSWorkflowExecutionPlanner implements WorkflowExecutionPlanner { /** * SLF4J Logging */ private Logger logger = LoggerFactory.getLogger(TSWorkflowExecutionPlanner.class); /** * Workflow Action? ? JAXB Object */ private List<BaseType> orderedActions; /** * Workflow Action? ? Name */ private List<String> namesOfActions; /** * Workflow Action? JAXB Object */ private Map<String, String> nextOfAction; /** * ? ? Workflow Action */ private Map<String, String> reversedActions; /** * Workflow Action? JAXB Object */ private Map<String, Object> actionMap; /** * Workflow XML JAXB Object */ private Workflow workflow; /** * Topological Sort Iterator. ? Iterator? * Workflow XML? ?? ? from to? . */ private TopologicalOrderIterator iterator; /** * ??. ? ?? ? * ? ? ? ?. * * @param workflow Workflow XML JAXB Object * @throws Exception */ public TSWorkflowExecutionPlanner(Workflow workflow) throws Exception { this.workflow = workflow; this.namesOfActions = new LinkedList<String>(); this.orderedActions = new LinkedList<BaseType>(); this.actionMap = new HashMap<String, Object>(); this.reversedActions = new HashMap<String, String>(); this.nextOfAction = new HashMap<String, String>(); this.iterator = new TopologicalOrderIterator(createGraph()); // ? ? Action Name? ?. ? ? ?. while (iterator.hasNext()) { namesOfActions.add((String) iterator.next()); } // ? ? ? . for (String currentAction : namesOfActions) { if (actionMap.get(currentAction) instanceof NodeType) { // ?? ? . NodeType node = (NodeType) actionMap.get(currentAction); String[] tos = StringUtils.splitPreserveAllTokens(node.getTo(), ','); // ?? ? ? ? ? ? . for (String to : tos) { String reversedActions = buildReversedActions(this.reversedActions.get(to), currentAction); this.reversedActions.put(to, reversedActions); } // ? for ? ?. orderedActions.add((BaseType) actionMap.get(currentAction)); } else { // BaseType ? ? End ? . // ? for ? ?. orderedActions.add((BaseType) actionMap.get(currentAction)); } } } /** * ? ? ? ? ?? . * (node1) ?? ? node2? node2 ? . * ? ? node2? ? node1 ? ?? ?. * Hadoop Workflow? ? ? ? ? . * * @param predecessor ? ? * @param current * @return ? ? ? ? ? */ private String buildReversedActions(String predecessor, String current) { List<String> nodes = new ArrayList<String>(); if (predecessor != null) { String[] strings = StringUtils.splitPreserveAllTokens(predecessor, ','); Collections.addAll(nodes, strings); } nodes.add(current); return org.springframework.util.StringUtils.collectionToCommaDelimitedString(nodes); } /** * Topological Sort Graph Algorithm? ?. * * @return Topological Sort Graph */ private DirectedMultigraph<String, DefaultEdge> createGraph() { DirectedMultigraph<String, DefaultEdge> graph = new DirectedMultigraph<String, DefaultEdge>( DefaultEdge.class); // Add Action's Vertex List<ActionType> actions = workflow.getAction(); for (ActionType actionType : actions) { graph.addVertex(actionType.getName()); actionMap.put(actionType.getName(), actionType); } // Add Start's Vertex if (workflow.getStart() != null) { graph.addVertex(workflow.getStart().getName()); actionMap.put(workflow.getStart().getName(), workflow.getStart()); } // Add End's Vertex if (workflow.getEnd() != null) { graph.addVertex(workflow.getEnd().getName()); actionMap.put(workflow.getEnd().getName(), workflow.getEnd()); } // Add Action's Edge for (ActionType actionType : actions) { if (!StringUtils.isEmpty(actionType.getTo())) { nextOfAction.put(actionType.getName(), actionType.getTo()); String[] targets = StringUtils.splitPreserveAllTokens(actionType.getTo(), ","); for (String target : targets) { logger.trace("[Graph] {} => {}", actionType.getName(), target); graph.addEdge(actionType.getName(), target); } } } // Add Start's Edge if (workflow.getStart() != null) { if (!StringUtils.isEmpty(workflow.getStart().getTo())) { nextOfAction.put(workflow.getStart().getName(), workflow.getStart().getTo()); String[] targets = StringUtils.splitPreserveAllTokens(workflow.getStart().getTo(), ","); for (String target : targets) { logger.trace("[Graph] {} => {}", workflow.getStart().getName(), target); graph.addEdge(workflow.getStart().getName(), target); } } } return graph; } @Override public List<String> getNamesOfActions() { return namesOfActions; } @Override public Map<String, Object> getActionMap() { return actionMap; } @Override public Map<String, String> getGlobalVariables() { return WorkflowUtils.getGlobalVariables(workflow); } @Override public List<BaseType> getOrderedActions() { return orderedActions; } @Override public Map<String, String> getNextOfAction() { return nextOfAction; } @Override public Map<String, String> getReversedActions() { return reversedActions; } }