📄 formulatree.java
字号:
package cn.myapps.core.formula;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Stack;
import java.util.TreeMap;
import antlr.RecognitionException;
import antlr.TokenStreamException;
import antlr.collections.AST;
import cn.myapps.core.dynaform.document.dql.DqlBaseLexer;
import cn.myapps.core.dynaform.document.dql.DqlBaseParser;
import cn.myapps.util.sequence.Sequence;
import cn.myapps.util.sequence.SequenceException;
public class FormulaTree {
private static final double SEMICIRCLE = 180;
private static final double DESCENDING = 20;
public FormulaTree() {
}
public Map parse(String text) { // 解析
DqlBaseLexer lexer = new DqlBaseLexer(new StringReader(text));
DqlBaseParser parser = new DqlBaseParser(lexer);
Map nodeMap = new TreeMap();
try {
parser.exprList();
AST parent = parser.getAST();
if (parent != null) {
FormulaNode root = new FormulaNode();
root.setId(Sequence.getSequence());
root.setText(parent.getText());
nodeMap.put(root.getId(), root);
parse(nodeMap, parent, root);
}
} catch (Exception e) {
System.out.println("Formula parse ERROR");
e.printStackTrace();
}
return nodeMap;
}
private void parse(Map nodeMap, AST ast, FormulaNode parent)
throws SequenceException {
AST lchild = ast.getFirstChild(); // 左节点
AST rchild = null;
if (lchild != null) {
rchild = lchild.getNextSibling(); // 右节点
}
if (lchild != null) {
FormulaNode lnode = addToParent(nodeMap, parent, lchild);
if (lchild.getFirstChild() != null) {
parse(nodeMap, lchild, lnode);
}
}
if (rchild != null) {
FormulaNode rnode = addToParent(nodeMap, parent, rchild);
if (rchild.getFirstChild() != null) {
parse(nodeMap, rchild, rnode);
}
}
}
public String dparse(Map nodeMap) { // 反解析
StringBuffer formula = new StringBuffer();
/* search root node */
FormulaNode root = getRoot(nodeMap);
if (root != null) {
Stack stack = new Stack();
stack.push(root);
formula = dparse(formula, root, stack);
}
return formula.toString();
}
private StringBuffer dparse(StringBuffer formula, FormulaNode parent,
Stack stack) {
if (parent.getChildren() != null) {
Collection colls = parent.getChildren();
boolean isLeft = true;
for (Iterator iter = colls.iterator(); iter.hasNext();) {
FormulaNode node = (FormulaNode) iter.next();
stack.push(node);
if (node.getChildren() != null && node.getChildren().size() > 0) {
formula.append(" (");
dparse(formula, node, stack);
if (isLeft) {
formula.append(") ");
formula.append(((FormulaNode) stack.pop()).getText() + " ");
isLeft = false;
} else {
formula.append(") ");
}
} else {
if (isLeft) {
formula.append(((FormulaNode) stack.pop()).getText() + " ");
isLeft = false;
}
formula.append(((FormulaNode) stack.pop()).getText() + " ");
}
}
}
return formula;
}
private FormulaNode addToParent(Map nodeMap, FormulaNode parent, AST child)
throws SequenceException {// 添加到父节点
FormulaNode node = new FormulaNode();
node.setId(Sequence.getSequence());
node.setText(child.getText());
node.setParent(parent);
nodeMap.put(node.getId(), node);
parent.addChild(node);
return node;
}
public String toTreeHtml(Map nodeMap, double ovalWidth, double ovalHeight,
double startLeft, double startTop, double lineLength, double space,
double angle) throws SequenceException {
StringBuffer treeHtml = new StringBuffer();
treeHtml.append("");
String text = "";
/* search root node */
FormulaNode root = getRoot(nodeMap);
if (root != null) {
treeHtml
.append("<v:oval id='"
+ root.getId()
+ "'strokecolor='red' fillcolor='yellow' style='position:absolute;left:"
+ startLeft + ";top:" + startTop + ";width:"
+ ovalWidth + ";height:" + ovalHeight + "'");
treeHtml
.append(" oncontextmenu='showmenuie5(this);return false;'>");
treeHtml
.append("<v:textbox style='bottom : -0px;valign:center;align:center;Z-INDEX:1;position:ralative;left:"
+ startLeft + ";top:" + startTop + "'>");
treeHtml.append("<div align='center'>" + root.getText() + "</div>");
treeHtml.append("</v:textbox>");
treeHtml.append("</v:oval>");
if (root.getChildren() != null) {
treeHtml.append(toTreeHtml(root, new StringBuffer(), ovalWidth,
ovalHeight, startLeft, startTop, lineLength, space,
angle));
}
}
text = "document.all('treeDiv').innerHTML=\"" + treeHtml.toString()
+ "\";";
return text;
}
private FormulaNode getRoot(Map nodeMap) { // 获取根节点
if (nodeMap != null && nodeMap.size() > 0) {
for (Iterator iter = nodeMap.values().iterator(); iter.hasNext();) {
FormulaNode node = (FormulaNode) iter.next();
if (node.getParent() == null) {
return node;
}
}
}
return null;
}
private String toTreeHtml(FormulaNode parent, StringBuffer html,
double ovalWidth, double ovalHeight, double startLeft,
double startTop, double lineLength, double space, double angle)
throws SequenceException {
Collection colls = parent.getChildren();
boolean isLeft = true; // 是否为左节点
double radius = ovalWidth / 2; // 半径
double halfSpace = space / 2; // 线段两起始之间的距离的一半
for (Iterator iter = colls.iterator(); iter.hasNext();) {
FormulaNode element = (FormulaNode) iter.next();
/** 计算 * */
double fromX;
double fromY = startTop
+ (ovalHeight - (radius - Math.sqrt(Math.pow(radius, 2)
- Math.pow(halfSpace, 2))));
double toX;
double toY = fromY
+ (Math.cos(Math.PI * (angle / SEMICIRCLE)) * lineLength);
if (isLeft) { // 左节点
fromX = startLeft + radius - halfSpace;
toX = fromX
- (Math.sin(Math.PI * (angle / SEMICIRCLE)) * lineLength);
isLeft = false;
} else { // 右节点
fromX = startLeft + 2 * radius - (radius - halfSpace);
toX = fromX
+ (Math.sin(Math.PI * (angle / SEMICIRCLE)) * lineLength);
}
double tmpStartLeft = toX - ovalWidth / 2;
double tmpStartTop = toY;
html.append(toChildHtml(element, ovalWidth, ovalHeight,
tmpStartLeft, tmpStartTop, fromX, fromY, toX, toY));
if (element.getChildren() != null) {
toTreeHtml(element, html, ovalWidth, ovalHeight, tmpStartLeft,
tmpStartTop, lineLength - DESCENDING, space
- DESCENDING / 2, angle - DESCENDING / 2);
}
}
return html.toString();
}
private String toChildHtml(FormulaNode child, double ovalWidth,
double ovalHeight, double startLeft, double startTop, double fromX,
double fromY, double toX, double toY) throws SequenceException {
StringBuffer html = new StringBuffer();
html.append("<v:line style='position:absolute;' from='" + fromX + ","
+ fromY + "' to='" + toX + "," + toY + "' />");
html
.append("<v:oval id='"
+ child.getId()
+ "'strokecolor='red' fillcolor='yellow' style='position:absolute;left:"
+ startLeft + ";top:" + startTop + ";width:"
+ ovalWidth + ";height:" + ovalHeight + "'");
html.append(" oncontextmenu='showmenuie5(this);return false;'>");
html
.append("<v:textbox style='bottom : -0px;valign:center;align:center;Z-INDEX:1;position:ralative;left:"
+ startLeft + ";top:" + startTop + "'>");
html.append("<div align='center'>" + child.getText() + "</div>");
html.append("</v:textbox>");
html.append("</v:oval>");
return html.toString();
}
public Map delNode(Map nodeMap, String currId) {// 删除子节点
FormulaNode currnode = (FormulaNode) nodeMap.get(currId);
return delNode(nodeMap, currnode);
}
private Map delNode(Map nodeMap, FormulaNode currnode) {// 递归删除子节点
if (currnode.getChildren() != null && currnode.getChildren().size() > 0) {
Collection tmp = currnode.getChildren();
Collection colls = new ArrayList();
for (Iterator iter = tmp.iterator(); iter.hasNext();) {
colls.add(iter.next());
}
for (Iterator iter = colls.iterator(); iter.hasNext();) {
FormulaNode node = (FormulaNode) iter.next();
delNode(nodeMap, node);
}
}
if (currnode.getParent() != null) {
currnode.getParent().delChild(currnode);
}
nodeMap.remove(currnode.getId());
return nodeMap;
}
public Map addNode(Map nodeMap, String parentId, String text,
String valuetype) throws Exception {// 添加节点
FormulaNode parent = null;
if (parentId != null && parentId.trim().length() > 0) {
parent = (FormulaNode) nodeMap.get(parentId);
}
if (parent != null) {// add
if (parent.getChildren().size() < 2) {
FormulaNode child = new FormulaNode();
child.setId(Sequence.getSequence());
child.setParent(parent);
child.setText(text);
child.setValuetype(valuetype);
parent.addChild(child);
nodeMap.put(child.getId(), child);
}
} else { // create
nodeMap = new TreeMap();
FormulaNode node = new FormulaNode();
node.setId(Sequence.getSequence());
node.setText(text);
nodeMap.put(node.getId(), node);
}
return nodeMap;
}
public String[] getNodeInfo(Map nodeMap, String parentId) {
String[] info = new String[2];
FormulaNode parent = (FormulaNode) nodeMap.get(parentId);
Object[] objs = parent.getChildren().toArray();
info[0] = ((FormulaNode) objs[0]).getValuetype();
info[1] = ((FormulaNode) objs[0]).getText();
return info;
}
public String refreshMenu(Map nodeMap, String id) {
StringBuffer fun = new StringBuffer();
FormulaNode node = (FormulaNode) nodeMap.get(id);
int symbolType = MenubarType.MENUBAR_TYPE_NOTSYMBOL;
int[] disableType = new int[1];
symbolType = MenubarType.getType(node.getText());
if (symbolType == MenubarType.MENUBAR_TYPE_RELATION) { // 根据不同的类型disable
disableType = new int[] { 3, 4 };
} else if (symbolType == MenubarType.MENUBAR_TYPE_OPERATOR
|| symbolType == MenubarType.MENUBAR_TYPE_COMPARE) {
if (node.getChildren().size() == 0) {
disableType = new int[] { 0, 1, 2, 4 };
} else {
disableType = new int[] { 0, 1, 2, 3 };
}
}
if (node.getChildren().size() == 2 || symbolType == Integer.MAX_VALUE) {
disableType = MenubarType.TYPES;
}
StringBuffer innerHtml = new StringBuffer();
for (int i = 0; i < MenubarType.NAMES.length; i++) {
innerHtml
.append("<div class='link' onMouseOver=this.className='overlink' onMouseOut=this.className='link'");
innerHtml
.append(" style='padding-top:2;padding-bottom:2;text-align: left'");
boolean isDisable = false;
for (int j = 0; j < disableType.length; j++) {
if (MenubarType.TYPES[i] == disableType[j]) {
innerHtml.append(" disabled");
isDisable = true;
}
}
if (!isDisable) {
innerHtml.append(" onclick='addTreeElement(this,"
+ MenubarType.TYPES[i] + ");'");
}
innerHtml.append(">");
innerHtml.append("{*[New " + MenubarType.NAMES[i] + "]*}");
innerHtml.append("</div>");
}
innerHtml.append("<table width=100%>");
innerHtml
.append("<tr height=4><td width=100% BACKGROUND='/images/line.png'></td></tr>");
innerHtml.append("</table>");
innerHtml
.append("<div class='link' onMouseOver=this.className='overlink' onMouseOut=this.className='link'");
innerHtml
.append(" style='padding-top:2;padding-bottom:2;text-align: left'");
innerHtml.append(" onclick='deleteSel();'");
innerHtml.append(">");
innerHtml.append(" {*[Delete]*} ");
innerHtml.append("</div>");
fun.append("document.all('ie5menu').innerHTML=\""
+ innerHtml.toString() + "\";");
return fun.toString();
}
public static void main(String[] args) throws RecognitionException,
TokenStreamException {
String text = "1+(2*3+5)*10+6";
FormulaTree tree = new FormulaTree();
Map map = tree.parse(text);
String formula = tree.dparse(map);
{
DqlBaseLexer lexer = new DqlBaseLexer(new StringReader(formula));
DqlBaseParser parser = new DqlBaseParser(lexer);
parser.exprList();
System.out.println("AST1->" + parser.getAST().toStringTree());
}
{
DqlBaseLexer lexer = new DqlBaseLexer(new StringReader(text));
DqlBaseParser parser = new DqlBaseParser(lexer);
parser.exprList();
System.out.println("AST2->" + parser.getAST().toStringTree());
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -