📄 cast.java
字号:
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/*
* Classname Cast
*
* Version information 1.0
*
* Date 2008.1.18
*
* Author 熊小均
*
* Description 根据提供的XML Schema文件,生成相应的sql文件。sql文件中的内容主体为建表语句,根据sql文件在RDBMS中产生的表能够存储符合给定的XML Schema文件定义的合式的xml文档中的数据。
*/
public class Cast {
private String schemafile;// 待解析的xml模式文件的文件名
private String sql = "";// 生成的sql语句
private Element root;// schema文件的根元素
private HashMap<String, String> simpleType = new HashMap<String, String>();// 用于保存简单类型的类型名与类型实际的数据类型的映射关系的hash表。key为名称,值为类型
private HashMap<String, String> complexType = new HashMap<String, String>();// 用于保存元素名与其的数据类型的映射关系的hash表。key为名称,值为类型。
private HashMap<String, HashMap<String, String>> tableType = new HashMap<String, HashMap<String, String>>();// 用于保存元素数据类型与保存其属性内容的映射关系的hash表,键为类型名,值为属性表。
private HashMap<String, ArrayList<String>> key = new HashMap<String, ArrayList<String>>();// 保存主键信息的hash表,键为表名,值为主键名组成的字符串链表
private HashMap<String, ArrayList<String[]>> restriction = new HashMap<String, ArrayList<String[]>>();// 用于保存各种简单类型的约束条件的数据结构,键为表名,值为一个链表,链表的每一项为一个字符串数组,数组第一项为属性名,第二项为最小值,第三项为最大值,第四项为可选值,第五项为字符串的匹配模式
private HashMap<String, String> keyrefToTableName = new HashMap<String, String>();// 保存外键映射信息的hash表,键为外键名,值为表名
public Cast(String filename) throws Exception {
schemafile = filename;
root = getRoot(schemafile);// 获取dom树的根元素
castToTable();// 生成各种数据结构,填充用于保存结构信息的几张表
}
public String getSchemafile() {
return schemafile;
}
private Element getRoot(String filename) throws Exception {// 取得xml文件的dom树的根元素
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc = factory.newDocumentBuilder().parse(filename);
Element rootElement = doc.getDocumentElement();
if (rootElement == null) {// 如果根元素为空,向上抛出异常
throw new Exception();
}
return rootElement;
}
private void castToTable() throws Exception {
NodeList simple = castSimpleToTable();
// 处理复杂类型
NodeList complex = root.getElementsByTagName("complexType");
Element current;
NodeList element = null;// 子元素节点列表
Element currentelement = null;
String elementtype = null;// 当前子元素的数据类型
NodeList attri = null;// 属性节点列表
Element currentattri = null;
NodeList keynode = null;// 主键说明节点列表
NodeList currentkeynode = null;
NodeList keyref = null;// 外键说明节点列表
NodeList currentkeyref = null;
HashMap<String, String> attrimap = null;
for (int i = 0; i < complex.getLength(); i++) {
current = (Element) complex.item(i);// 取当前的complexType节点
element = current.getElementsByTagName("element");// 取当前complexType节点的子元素节点
attri = current.getElementsByTagName("attribute");// 取当前complexType节点的属性节点
keyref = current.getElementsByTagName("keyref");// 取当前complex节点的外键关系节点
keynode = current.getElementsByTagName("key");// 取当前complex节点的主键节点
attrimap = new HashMap<String, String>();// 该HashMap存储该complexType类型中的属性名与类型的映射关系
ArrayList<String[]> attrirest = new ArrayList<String[]>();
for (int j = 0; j < attri.getLength(); j++) {
currentattri = (Element) attri.item(j);
String attriname = currentattri.getAttribute("name");
String attritype = currentattri.getAttribute("type");
attrimap.put(attriname, simpleType.get(attritype));
if (attritype.equalsIgnoreCase("string")// 如果是基本数据类型不用处理其约束条件
|| attritype.equalsIgnoreCase("date")
|| attritype.equalsIgnoreCase("integer")
|| attritype.equalsIgnoreCase("float"))
continue;
String[] rest = castRestrictionToTable(simple, attriname,
attritype);
// 这步完成后,所有属性的数据类型均映射为基本数据类型并保存在HashMap中
if (rest[0] != null)// 如果没有往rest数组中添加内容,则不能添加
attrirest.add(rest);
}
for (int j = 0; j < element.getLength(); j++) {
currentelement = (Element) element.item(j);
elementtype = currentelement.getAttribute("type");
if (simpleType.containsKey(elementtype)) {// 如果子元素的类型属于简单类型,将该子元素映射为属性
String attriname = currentelement.getAttribute("name");
String attritype = currentelement.getAttribute("type");
String[] rest = castRestrictionToTable(simple, attriname,
attritype);
attrimap.put(attriname, simpleType.get(attritype));
if (rest[0] != null)
attrirest.add(rest);
} else {// 否则在保存元素名的hash表中保存该元素的名称与类型
complexType.put(currentelement.getAttribute("name"),
elementtype);
}
}
// 处理该节点的主键
ArrayList<String> keyname = new ArrayList<String>();
for (int j = 0; j < keynode.getLength(); j++) {
currentkeynode = ((Element) keynode.item(j))
.getElementsByTagName("field");
for (int k = 0; k < currentkeynode.getLength(); k++) {
String xpath = ((Element) currentkeynode.item(k))
.getAttribute("xpath");
if (xpath.startsWith("@"))
xpath = xpath.substring(1);
else if (xpath.startsWith("text(") && xpath.endsWith(")"))
xpath = xpath.substring(5, xpath.length());
keyname.add(xpath);
}
}
if (keyname.size() != 0)
key.put(current.getAttribute("name"), keyname);// 添加该表的主键信息
// 处理该节点的外键关系
for (int j = 0; j < keyref.getLength(); j++) {
currentkeyref = ((Element) keyref.item(j))
.getElementsByTagName("field");
HashMap<String, String> keyrefattri = new HashMap<String, String>();
ArrayList<String[]> refrest = new ArrayList<String[]>();
for (int k = 0; k < currentkeyref.getLength(); k++) {
String xpath = ((Element) currentkeyref.item(k))
.getAttribute("xpath");
if (xpath.startsWith("@"))
xpath = xpath.substring(1);
else if (xpath.startsWith("text(") && xpath.endsWith(")"))
xpath = xpath.substring(5, xpath.length() - 1);
if (!attrimap.containsKey(xpath))
throw new Exception();
keyrefattri.put(xpath, simpleType.get(attrimap.get(xpath)));// 将保存属性的hash表中的相关映射转移到另一张表中,用于表示外键引用
keyrefToTableName.put(xpath, ((Element) keyref.item(j))
.getAttribute("name"));
for (int l = 0; l < attrirest.size(); l++)
if (attrirest.get(l)[0].equals(xpath)) {// 将约束条件中的相关内容移动到新的表名下
refrest.add(attrirest.get(l));
attrirest.remove(l);
break;
}
attrimap.remove(xpath);
}
keyrefattri.put("ID", "integer");// 添加id项
keyrefattri.put("ParentID", "integer");// 添加父母节点的id项
String keyrefname = ((Element) keyref.item(j))
.getAttribute("name");
tableType.put(keyrefname, keyrefattri);// 在生成的最终表中添加这张表示外键引用关系的表
if (refrest.size() != 0) {
restriction.put(keyrefname, refrest);
}
// 为保障该表最终能用来生成SQL语句,需要在complexType中添加相关信息
complexType.put(keyrefname, keyrefname);
}
attrimap.put("ID", "integer");// 添加id属性
attrimap.put("ParentID", "integer");// 添加父母节点的id属性
attrimap.put("sequence", "integer");// 添加顺序属性
if (attrimap.size() > 3)// 如果只有上述添加的三个属性则为空表,不添加
tableType.put(current.getAttribute("name"), attrimap);// 添加该复杂数据类型生成的表
restriction.put(current.getAttribute("name"), attrirest);
}
// 到此,所有可用来生成的表的休息都放入tableType中
castElementToTable();
}
private String[] castRestrictionToTable(NodeList simple, String attriname,
String attritype) {// 检查attritype的约束,将所有的约束条件保存在字符串数组中返回
String[] rest = new String[5];
for (int k = 0; k < simple.getLength(); k++) {
Element currentsimple = (Element) simple.item(k);
if (!currentsimple.getAttribute("name").equalsIgnoreCase(attritype))// 要找到该属性的约束条件
continue;
// 以下为约束条件的记录过程
rest[0] = attriname;
NodeList min = currentsimple.getElementsByTagName("minInclusive");// 最小值
if (min.getLength() == 0)
rest[1] = "-1";
else
rest[1] = min.item(0).getAttributes().getNamedItem("value")
.getNodeValue();
NodeList max = currentsimple.getElementsByTagName("maxInclusive");// 最大值
if (max.getLength() == 0)
rest[2] = "-1";
else
rest[2] = max.item(0).getAttributes().getNamedItem("value")
.getNodeValue();
NodeList enu = currentsimple.getElementsByTagName("enumeration");// 可选的值
if (enu.getLength() == 0)
rest[3] = "-1";
else {
String choice = "(";
for (int l = 0; l < enu.getLength(); l++)
choice += "'"
+ enu.item(l).getAttributes().getNamedItem("value")
.getNodeValue() + "',";
rest[3] = choice.substring(0, choice.length() - 1) + ")";
}
rest[4] = "-1";//考虑到不同的数据库对字符串匹配约束格式的要求不太一致,去掉该约束
/*NodeList pat = currentsimple.getElementsByTagName("pattern");// 字符串需要符合的模式
if (pat.getLength() == 0)
rest[4] = "-1";
else
rest[4] = pat.item(0).getAttributes().getNamedItem("value")
.getNodeValue();*/
break;
}
return rest;
}
private void castElementToTable() {
// 处理元素类型,特别是根元素
NodeList rootelement = root.getChildNodes();
Node currentrootelement = null;
for (int j = 0; j < rootelement.getLength(); j++) {
currentrootelement = rootelement.item(j);
if (currentrootelement.getNodeName().equals("element"))
complexType.put("#"// 标记一下根元素
+ currentrootelement.getAttributes().getNamedItem(
"name").getNodeValue(), currentrootelement
.getAttributes().getNamedItem("type").getNodeValue());
}
}
private NodeList castSimpleToTable() {
// 取得简单类型的名称与数据类型的映射
NodeList simple = root.getElementsByTagName("simpleType");// 取得简单数据类型的链表
Element current = null;
Element currenttype = null;
for (int i = 0; i < simple.getLength(); i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -