/*
* Copyright 2008-2009 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 net.hasor.core.setting.xml;
import net.hasor.core.Settings;
import net.hasor.core.XmlNode;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* @version : 2013-7-13
* @author 赵永春 (zyc@byshell.org)
*/
public class SaxXmlParser extends DefaultHandler {
private Settings dataContainer = null;
private Map<String, StringBuilder> xmlText = new HashMap<String, StringBuilder>();
private Map<String, DefaultXmlNode> currentXmlPropert = new HashMap<String, DefaultXmlNode>();
//
public SaxXmlParser(final Settings dataContainer) {
this.dataContainer = dataContainer;
}
private StringBuilder getText(final String xmlns) {
if (!this.xmlText.containsKey(xmlns)) {
this.xmlText.put(xmlns, new StringBuilder(""));
}
return this.xmlText.get(xmlns);
}
private void cleanText(final String xmlns) {
this.xmlText.remove(xmlns);
}
private DefaultXmlNode getCurrentXmlPropert(final String xmlns) {
return this.currentXmlPropert.get(xmlns);
}
private void setCurrentXmlPropert(final String xmlns, final DefaultXmlNode xmlProperty) {
this.currentXmlPropert.put(xmlns, xmlProperty);
}
//
private String curXmlns = null;
public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) throws SAXException {
DefaultXmlNode xmlProperty = this.getCurrentXmlPropert(uri);
if (xmlProperty == null) {
xmlProperty = new DefaultXmlNode(null, "root");
this.setCurrentXmlPropert(uri, xmlProperty);
}
DefaultXmlNode thisXmlNode = new DefaultXmlNode(xmlProperty, localName);
xmlProperty.addChildren(thisXmlNode);
this.setCurrentXmlPropert(uri, thisXmlNode);
//
for (int i = 0; i < attributes.getLength(); i++) {
String attName = attributes.getLocalName(i);
String attValue = attributes.getValue(i);
this.getCurrentXmlPropert(uri).addAttribute(attName, attValue);
}
this.curXmlns = uri;
}
public void endElement(final String uri, final String localName, final String qName) throws SAXException {
StringBuilder strBuffer = this.getText(uri);
//
DefaultXmlNode currentNode = this.getCurrentXmlPropert(uri);
currentNode.setText(strBuffer.toString().trim());
this.setCurrentXmlPropert(uri, (DefaultXmlNode) currentNode.getParent());
//
this.cleanText(uri);
this.curXmlns = uri;
}
public void characters(final char[] ch, final int start, final int length) throws SAXException {
if (this.curXmlns == null) {
return;
}
StringBuilder strBuffer = this.getText(this.curXmlns);
String content = new String(ch, start, length);
strBuffer.append(content);
}
public void endDocument() throws SAXException {
for (Entry<String, DefaultXmlNode> ent : this.currentXmlPropert.entrySet()) {
String currentXmlns = ent.getKey();
DefaultXmlNode currentXml = ent.getValue();
// 1.将XmlTree转换为map映射
HashMap<String, List<Object>> dataMap = new HashMap<String, List<Object>>();
this.convertType(dataMap, currentXml.getChildren(), "");
// 2.弃掉转换过程中根节点名称
HashMap<String, List<Object>> finalReturnData = new HashMap<String, List<Object>>();
for (Entry<String, List<Object>> data : dataMap.entrySet()) {
String keyStr = data.getKey();
List<Object> valStr = data.getValue();
//
if (keyStr.indexOf(".") > 0) {
keyStr = keyStr.substring(keyStr.indexOf(".") + 1);
finalReturnData.put(keyStr.toLowerCase(), valStr);
} else {
finalReturnData.put(".", valStr);
}
}
dataMap = finalReturnData;
// 3.输出映射结果,多各值的话会按照顺序依次add到最终结果中。
for (String key : dataMap.keySet()) {
String $key = key.toLowerCase();
List<Object> $var = dataMap.get(key);
if ($var != null && $var.size() > 0) {
for (Object var : $var) {
this.dataContainer.addSetting($key, var, currentXmlns);
}
}
}
}
}
/** 转换成Key Value形式 */
protected void convertType(final Map<String, List<Object>> returnData, final List<XmlNode> xmlPropertyList, final String parentAttName) {
if (xmlPropertyList != null) {
for (XmlNode xmlNode : xmlPropertyList) {
DefaultXmlNode impl = (DefaultXmlNode) xmlNode;
// 1.put本级
String key = "".equals(parentAttName) ? impl.getName() : parentAttName + "." + impl.getName();
convertTypePut(returnData, key, impl);
// 2.put属性
for (Entry<String, String> ent : impl.getAttributeMap().entrySet()) {
String putKey = key + "." + ent.getKey();
convertTypePut(returnData, putKey, ent.getValue());
}
// 3.put孩子
this.convertType(returnData, xmlNode.getChildren(), key);
}
}
}
private void convertTypePut(final Map<String, List<Object>> returnData, String key, Object value) {
List<Object> dataList = null;
if (returnData.containsKey(key)) {
dataList = returnData.get(key);
} else {
dataList = new ArrayList<Object>();
returnData.put(key, dataList);
}
dataList.add(value);
}
}