/* Copyright 2012-2013 the original author or authors.
*
* 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.snaker.designer.io.reader;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.snaker.designer.config.Component;
import org.snaker.designer.config.ConfigManager;
import org.snaker.designer.io.Environment;
import org.snaker.designer.model.Attr;
import org.snaker.designer.model.BaseElement;
import org.snaker.designer.model.NodeElement;
import org.snaker.designer.model.Transition;
import org.snaker.designer.utils.ClassUtils;
import org.snaker.designer.utils.XmlUtils;
import org.w3c.dom.Element;
/**
* 抽象dom节点解析类
* 完成通用的属性、变迁解析
* @author yuqs
* @version 1.0
*/
public abstract class AbstractXmlReader implements XmlReader {
/**
* 模型对象
*/
protected NodeElement model;
/**
* 实现NodeParser接口的parse函数
* 由子类产生各自的模型对象,设置常用的名称属性,并且解析子节点transition,构造TransitionModel模型对象
*/
public BaseElement parse(Element element) {
BaseElement model = newModel(element);
model.setName(element.getAttribute(Environment.ATTR_NAME));
model.setDisplayName(element.getAttribute(Environment.ATTR_DISPLAYNAME));
model.setLayout(getRectangle(element.getAttribute(Environment.ATTR_LAYOUT)));
if(model instanceof NodeElement) {
NodeElement node = (NodeElement)model;
List<Element> transitions = XmlUtils.elements(element, Environment.TRANSITION);
for(Element te : transitions) {
Transition transition = new Transition();
transition.setName(te.getAttribute(Environment.ATTR_NAME));
transition.setDisplayName(te.getAttribute(Environment.ATTR_DISPLAYNAME));
transition.setTo(te.getAttribute(Environment.ATTR_TO));
transition.setExpr(te.getAttribute(Environment.ATTR_EXPR));
transition.setOffset(buildLabelOffsetPoint(te.getAttribute(Environment.ATTR_OFFSET)));
transition.setBendpoints(buildBendPoints(te.getAttribute(Environment.ATTR_G)));
transition.setSource(node);
node.getOutputs().add(transition);
}
node.setPreInterceptors(element.getAttribute(Environment.ATTR_INTERCEPTORS_PRE));
node.setPostInterceptors(element.getAttribute(Environment.ATTR_INTERCEPTORS_POST));
}
List<Element> attrs = XmlUtils.elements(element, Environment.ATTR);
for(Element attrE : attrs) {
Attr attr = new Attr();
attr.setName(attrE.getAttribute(Environment.ATTR_NAME));
attr.setValue(attrE.getAttribute(Environment.ATTR_VALUE));
model.addAttr(attr);
}
parseNode(model, element);
return model;
}
private Point buildLabelOffsetPoint(String s)
{
if(s == null || s.trim().length() == 0) return null;
String[] xy = s.split(",");
return new Point(new Integer(xy[0]), new Integer(xy[1]));
}
private List<Point> buildBendPoints(String s)
{
List<Point> result = new ArrayList<Point>();
if (s == null || s.trim().length() == 0) {
return result;
}
String[] bendpoints = s.split(";");
for (String bendpoint: bendpoints) {
String[] xy = bendpoint.split(",");
result.add(new Point(new Integer(xy[0]), new Integer(xy[1])));
}
return result;
}
private Rectangle getRectangle(String v) {
if(v != null && v.trim().length() > 0)
{
String[] ps = v.split(",");
if(ps.length ==4)
{
int x = Integer.parseInt(ps[0]);
int y = Integer.parseInt(ps[1]);
int width = Integer.parseInt(ps[2]);
int height = Integer.parseInt(ps[3]);
return new Rectangle(x, y, width, height);
}
}
return new Rectangle(0, 0, 0, 0);
}
/**
* 子类可覆盖此方法,完成特定的解析
* @param model
* @param element
*/
protected void parseNode(BaseElement model, Element element) {
}
/**
* 抽象方法,由子类产生各自的模型对象
* @return
*/
protected BaseElement newModel(Element element) {
String nodeName = element.getNodeName();
Component component = ConfigManager.getComponentByName(nodeName);
return (BaseElement)ClassUtils.newInstance(component.getClazz());
}
}