Oozie workflow.xml 视图解析
最近半年多一直在做hive相关的开发工作,并且使用Oozie做为hive工作流的引擎,用于管理Hadoop任务。Oozie的任务流包括:croodinator、workflow。workflow用于描述任务的执行顺序,croodinator用于定义oozie的定时任务。workflow定义了两种结点:
- 控制流结点:主要包括start、end、fork、join等,其中fork、join成对出现,在fork展开。分支,最后在join结点汇聚。
- Action结点:包括Hadoop任务、SSH、HTTP、EMAIL、OOZIE子任务等。
- job的workflow.xml文件的读取、解析。
- 结点视图的绘制。
- svn job代码下载:svn主要的代码不定期的会从其分支合入新代码,需要写一个定时器,每天去全量的同步svn的代码。
- dom4j解析workflow.xml,抽象结点对象,视图数据准备阶段。
- 将视力数据利用Freemarker模板工具,解析到客户端,客户端根据结点数据,绘制结点。
结点横坐标=MAX(前结点的横坐标+结点宽度+1)
package com.lxr.oozie.workflow;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import org.dom4j.Document;
import org.dom4j.Element;public class OozieHelper {private Document document;private Element root = null;private List<WorkflowNode> workflowNodes = new ArrayList<WorkflowNode>();private Map<String, WorkflowNode> workflowNodeMap = new HashMap<String, WorkflowNode>();public OozieHelper(Document document) {this.document = document;}private Element getNode(String tag) {return root.element(tag);}private Element getNode(String attr, String value) {List<Element> nodes = root.elements();for (Element el : nodes) {if (value.equals(el.attributeValue(attr))) {return el;}}return null;}private Element getNodeByName(String name) {return getNode("name", name);}private String getNextNodeName(Element node) {String tagName = node.getName();if ("action".equals(tagName)) {Element element = node.element("ok");return element.attributeValue("to");} else {return node.attributeValue("to");}}private List<Element> getNextNodes(Element node) {if (null == node) {return null;}List<Element> nextNodes = new ArrayList<Element>();String nextNodeName = getNextNodeName(node);if (null != nextNodeName) {Element nextNode = getNodeByName(nextNodeName);String tagName = nextNode.getName();if ("fork".equalsIgnoreCase(tagName)) {List<Element> elements = nextNode.elements();for (Element el : elements) {nextNodeName = el.attributeValue("start");if (null != nextNodeName) {nextNode = getNodeByName(nextNodeName);if (null != nextNode) {nextNodes.add(nextNode);}}}} else if ("join".equals(tagName)) {nextNode = getNodeByName(nextNode.attributeValue("to"));nextNodes.add(nextNode);} else {nextNodes.add(nextNode);}}return nextNodes;}private void adjustToAddNode(WorkflowNode workflowNode) {for (WorkflowNode node : workflowNodes) {if (node.equals(workflowNode)) {return;}}workflowNodes.add(workflowNode);}private void genNextWorkflowNodes(WorkflowNode parent) {List<Element> nextNodes = getNextNodes(parent.getElement());if (0 != nextNodes.size()) {for (int i = 0, len = nextNodes.size(); i < len; i++) {Element el = nextNodes.get(i);String nodeName = el.attributeValue("name");WorkflowNode subWorkflowNode = workflowNodeMap.get(nodeName);int subX = parent.getX() + parent.getLength() + 1;int subY = parent.getY() + 2;if (null == subWorkflowNode) {subWorkflowNode = new WorkflowNode(el);subWorkflowNode.setName(nodeName);subWorkflowNode.setX(subX);subWorkflowNode.setY(subY);genNextWorkflowNodes(subWorkflowNode);workflowNodes.add(subWorkflowNode);// adjustToAddNode(subWorkflowNode);} else {subWorkflowNode.setX(Math.max(subX, subWorkflowNode.getX()));if (subY > subWorkflowNode.getY()) {subWorkflowNode.adjustNextNodesY(subY - subWorkflowNode.getY());subWorkflowNode.setY(subY);}}subWorkflowNode.previousNodes().add(parent);parent.nextNodes().add(subWorkflowNode);workflowNodeMap.put(nodeName, subWorkflowNode);}}}public List<WorkflowNode> parse() {root = document.getRootElement();Element startNode = getNode("start");if (null != startNode) {WorkflowNode start = new WorkflowNode(startNode);start.setName("start");start.setX(0);start.setY(0);workflowNodes.add(start);genNextWorkflowNodes(start);} else {System.out.println("未找到开始结点。");}return workflowNodes;}
}
view-workflow.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Oozie Workflow - ${jobName}</title>
<script type="text/javascript" src="../js/jquery.min.js"></script>
<script type="text/javascript" src="../js/raphael/raphael.min.js"></script>
<script type="text/javascript" src="../js/raphael/raphael.ext.js"></script>
<script type="text/javascript" src="../js/oozie.wf.draw.js"></script>
</head><body><label style="position: absolute;">job名称:${jobName}</label><div class="workflow-holder" id="${jobName}" margin-left="100"margin-top="100" grid-padding-left="15" grid-padding-top="10"grid-width="50" grid-height="25"><#list nodes as node><div id="${node.name}" class="branch-node workflow-node"xx="${node.x}" yy="${node.y}" length="${node.length}"next-node="${node.nextJobNames!}">${node.name}</div></#list></div>
</body>
</html>
oozie.wf.draw.js
jQuery.fn.attrn = function(attr) {return parseInt($(this).attr(attr));
}HTMLDivElement.prototype.$$ = function(attr) {return $(this).attr(attr);
}HTMLDivElement.prototype.$$n = function(attr) {return parseInt(this.$$(attr));
}$(function() {var $holder = $('.workflow-holder');var $nodes = $holder.find('.workflow-node');var nodes = [];$nodes.each(function(i, el) {nodes[i] = {id : $(el).attr('id'),index : i,xx : el.$$n('xx'),yy : el.$$n('yy'),length: el.$$n('length'),$instance : $(el)}});var workflowCfg = {id : $holder.attr('id'),margin : {left : $holder.attrn('margin-left'),top : $holder.attrn('margin-top')},grid : {paddingLeft : $holder.attrn('grid-padding-left'),paddingTop : $holder.attrn('grid-padding-top'),width : $holder.attrn('grid-width'),height : $holder.attrn('grid-height')},nodes : nodes,nodesMap : (function() {var map = {};for (var i = 0; i < nodes.length; i++) {var node = nodes[i];map[node.$instance.attr('id')] = node;}return map;})()};console.log(workflowCfg)// 用来存储节点的顺序var connections = [];// 拖动节点开始时的事件var dragger = function() {this.ox = this.attr('x');this.oy = this.attr('y');this.animate({'fill-opacity' : .2}, 500);};// 拖动事件var move = function(dx, dy) {var att = {x : this.ox + dx,y : this.oy + dy};this.attr(att);$holder.find("#" + this.id).offset({top : this.oy + dy + workflowCfg.grid.paddingTop,left : this.ox + dx + workflowCfg.grid.paddingLeft});for (var i = connections.length; i--;) {r.drawArr(connections[i]);}};// 拖动结束后的事件var up = function() {this.animate({'fill-opacity' : 0}, 500);};// 创建绘图对象var r = Raphael(workflowCfg.id, $(window).width(), $(window).height());// 绘制节点var shapes = [];var maxRight = 0;for (var i = 0, len = workflowCfg.nodes.length; i < len; i++) {var node = workflowCfg.nodes[i];node.left = workflowCfg.margin.left + node.xx * workflowCfg.grid.width;node.top = workflowCfg.margin.top + node.yy * workflowCfg.grid.height;node.width = workflowCfg.grid.width * node.length;node.height = workflowCfg.grid.height;shapes[i] = r.rect(node.left, node.top, node.width, node.height, 4);// 定位节点上的文字node.$instance.offset({top : node.top + workflowCfg.grid.paddingTop,left : node.left + workflowCfg.grid.paddingLeft});var right = node.$instance.offset().left + node.width;maxRight = maxRight > right? maxRight : right;}var $svg = $holder.find('svg');var svnWidth = maxRight + workflowCfg.grid.paddingLeft;var _svnWidth = $svg.attrn('width');$svg.attr('width', svnWidth > _svnWidth? svnWidth : _svnWidth);// 为节点添加样式和事件,并且绘制节点之间的箭头for (var i = 0, ii = shapes.length; i < ii; i++) {var color = Raphael.getColor();shapes[i].attr({fill : color,stroke : color,'fill-opacity' : 0,'stroke-width' : 2,cursor : 'move'});shapes[i].id = workflowCfg.nodes[i].id;shapes[i].drag(move, dragger, up);shapes[i].dblclick(function() {alert(this.id)})}// 节点连线for (var i = 0; i < workflowCfg.nodes.length; i++) {var node = workflowCfg.nodes[i];var nextNodeIds = node.$instance.attr('next-node');if (nextNodeIds) {var nextNodeIdArr = nextNodeIds.split(',');for (var j = 0; j < nextNodeIdArr.length; j++) {var nextNodeId = nextNodeIdArr[j];var nextNode = workflowCfg.nodesMap[nextNodeId];connections.push(r.drawArr({obj1 : shapes[node.index],obj2 : shapes[nextNode.index]}));}}}
});
Oozie workflow.xml 视图解析相关推荐
- 详解Spring MVC 4之ViewResolver视图解析器
所有的We MVC框架都有一套它自己的解析视图的机制,Spring MVC也不例外,它使用ViewResolver进行视图解析,让用户在浏览器中渲染模型.ViewResolver是一种开箱即用的技术, ...
- php xml expat,PHP XML Expat 解析器
PHP XML Expat 解析器 内建的 Expat 解析器使在 PHP 中处理 XML 文档成为可能. XML 是什么? XML 用于描述数据,其焦点是数据是什么.XML 文件描述了数据的结构. ...
- 几种常见的ViewResolver视图解析器
1.几种常见的ViewResolver视图解析器 在Spring MVC 4控制器中,所有的处理方法必须返回一个逻辑视图名称,无论是显式的(返回String,View或ModelAndView)还是隐 ...
- 基于XML配置的Spring MVC(所需jar包,web.xml配置,处理器配置,视图解析器配置)
1.添加jar 2.web.xml配置 <?xml version="1.0" encoding="UTF-8"?> <web-app ver ...
- Spring 视图解析
作为一个菜鸟的程序员,经常看到一些大神在使用Spring的,各种各样的配置文件,也不是很理解 视图解析器,一开始的时候我们也是跟着别人进行配置,比着葫芦画瓢,今天也算是对视图解析器有了一个小小的理解 ...
- 学习SpringMVC——说说视图解析器
各位前排的,后排的,都不要走,咱趁热打铁,就这一股劲我们今天来说说spring mvc的视图解析器(不要抢,都有位子~~~) 相信大家在昨天那篇如何获取请求参数篇中都已经领略到了spring mvc注 ...
- springmvc十六:视图解析
spring.xml配置视图解析器如下: <?xml version="1.0" encoding="UTF-8"?> <beans xmln ...
- 管理springmvc组件——前端控制器、控制器映射器和适配器、视图解析器、文件上传的、拦截器||消息转化
管理springmvc组件 概述 在使用springmvc时要配置哪些东西 前端控制器 控制器映射器和适配器 映射器 Map<Set<String>,Object> Set& ...
- SpringMVC 中整合JSON、XML视图一
SpringMVC中整合了JSON.XML的视图,可以通过这些视图完成Java对象到XML.JSON的转换.转换XML提供了MarshallingView,开发者只需用注入相应的marshaller. ...
最新文章
- html表格td宽度设置,table以及td宽度设置细节
- BCH两周年独立日已至,世界各地爱好者纷纷举办Meetup庆祝
- 配置Cisco ASA and Cisco *** Client 4.x with Windows 2003 IAS RADIUS Authentication
- 《零基础入门学习Python》学习过程笔记【013元组】
- 密码篇——对称加密—3DES
- javascript中 this 指向问题
- MATLAB作图方法与技巧(二)
- spring注解方式 idea报could not autowire
- 让Python中类的属性具有惰性求值的能力
- 3_6 CommandMode 命令模式
- linux进程看门狗使用方式,Linux系统中基于看门狗的精细化进程监控方法及系统的制作方法...
- 前端学习(2933):vue中的循环语句
- 安卓下设置系统字体大小影响H5页面布局
- 【数据结构】栈的基本操作
- 巴斯勒相机的ip掩码_相机IP和带宽设置
- 大数据集群监控体系架构
- 面试题:为什么说 Mybatis 是半自动ORM 映射工具?它与全自动的区别在哪里?
- 怎么看电脑支持多少兆网速_怎么看电脑网卡多少兆_如何查看网卡多少兆-系统城...
- android 日历动画的实现
- 河北官方:邯郸涉县致4死5伤煤气泄漏事故涉嫌瞒报