/*
* Copyright 2012 The Solmix Project
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.gnu.org/licenses/
* or see the FSF site: http://www.fsf.org.
*/
package org.solmix.fmk.util;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.solmix.api.exception.SlxException;
import org.solmix.api.jaxb.Tobject;
import org.solmix.api.serialize.XMLParser;
import org.solmix.api.serialize.XMLParserFactory;
import org.solmix.api.types.Texception;
import org.solmix.api.types.Tmodule;
import org.solmix.commons.util.DataUtils;
import org.solmix.fmk.serialize.XMLParserFactoryImpl;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
/**
*
* @author solmix.f@gmail.com
* @version 110035 2011-4-18
*/
@SuppressWarnings("unchecked")
public class XMLUtil
{
public static Set<String> ignoreNamespaceAttributes = new HashSet<String>();
static {
ignoreNamespaceAttributes.add("http://www.w3.org/2000/10/XMLSchema-instance");
ignoreNamespaceAttributes.add("http://www.solmix.org/xmlns/requestdata/v");
}
/**
* @param element
* @return
*/
public static Map attributesToMap(Element element) {
return addAttributesToMap(element, null);
}
public static boolean isIgnoreNS(String nameSpace) {
for (String ns : ignoreNamespaceAttributes) {
if (nameSpace.startsWith(ns))
return true;
}
return false;
}
/**
* @param element the giving Element
* @param valueMap the return Map
*/
public static Map<String, String> addAttributesToMap(Element element, Map<String, String> map) {
if (map == null)
map = new HashMap<String, String>();
if (element.hasAttributes()) {
NamedNodeMap attrs = element.getAttributes();
for (int i = 0; i < attrs.getLength(); i++) {
Node attr = attrs.item(i);
String namespace = attr.getNamespaceURI();
if (namespace != null && isIgnoreNS(namespace))
continue;
String attrName = attr.getLocalName();
if (attrName == null)
attrName = attr.getNodeName();
if (attrName.equals("_BLANK_"))
attrName = "";
if (!map.containsKey(attrName))
map.put(attrName, attr.getNodeValue());
}
}
return map;
}
public static Map getElementChildrenMap(Element element) {
Map elementChildren = new HashMap();
NodeList children = element.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child instanceof Element) {
Element childElement = (Element) child;
DataUtils.putMultiple(elementChildren, childElement.getTagName(), childElement);
}
}
return elementChildren;
}
public static List<Element> getElementChildren(Element element) {
return getElementChildren(element, (Map) null);
}
public static List<Element> getElementChildren(Element element, String tagName) {
return getElementChildren(element, DataUtils.buildMap(tagName, new Object()));
}
public static List<Element> getElementChildren(Element element, Map tags) {
List<Element> elementChildren = new ArrayList<Element>();
NodeList children = element.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (!(child instanceof Element))
continue;
Element childElement = (Element) child;
if (tags == null || tags.containsKey(childElement.getTagName()))
elementChildren.add(childElement);
}
return elementChildren;
}
public static String toSimpleValue(Element element) {
if (!element.hasChildNodes())
return getAttribute(element, "value");
Writer out = new StringWriter();
NodeList children = element.getChildNodes();
for (int i = 0; i < children.getLength(); i++)
try {
Node child = children.item(i);
if (child instanceof Text) {
out.write(((Text) child).getData());
continue;
}
} catch (IOException impossible) {
}
return out.toString();
}
/**
* @param element
* @param string
* @return
*/
public static String getAttribute(Element element, String eleName) {
return element.getAttribute(eleName);
}
public static void toFile(String location, String fileName, Object jaxbObject) throws SlxException {
XMLParserFactory factory = XMLParserFactoryImpl.getInstance();
XMLParser parser = factory.get();
String absolutePath = null;
if (location != null) {
absolutePath = location.endsWith("/") ? location : location + "/";
File dir = new File(absolutePath);
if (!dir.exists() && !dir.isDirectory())
dir.mkdirs();
absolutePath = DataUtils.isNullOrEmpty(fileName) ? absolutePath : absolutePath + fileName;
} else {
absolutePath = fileName;
}
Writer out = null;
FileOutputStream outStream = null;
try {
File f = new File(absolutePath);
try {
if (!f.exists()) {
f.createNewFile();
}
outStream = new FileOutputStream(f);
out = new BufferedWriter(new OutputStreamWriter(outStream));
} catch (Exception e) {
throw new SlxException(Tmodule.XML, Texception.IO_EXCEPTION, e);
}
parser.marshalDS(out, jaxbObject);
} finally {
try {
out.close();
outStream.close();
} catch (IOException e) {
}
}
}
public static void toFile(String fileName, Object jaxbObject) throws SlxException {
toFile(null, fileName, jaxbObject);
}
/**
* convert xml to map ,the {@link Tobject} is a list of Element object,and the element must like this
* <code><key>value</key></code> and no like this <code><key a="value"></key> </code>
*
* @param to
* @return
*/
public static Map<String, Object> toMap(Tobject to) {
if (to == null) {
return Collections.emptyMap();
}
List<Object> objs = to.getAny();
return toMap(objs);
}
public static Map<String, Object> element2Map(List<Element> objs) {
Map<String, Object> _return = new HashMap<String, Object>();
for (Element obj : objs) {
Object value = getValue(obj);
_return.put(obj.getNodeName(), value);
}
return _return;
}
public static Map<String, Object> toMap(List<Object> objs) {
Map<String, Object> _return = new HashMap<String, Object>();
for (Object obj : objs) {
if (obj instanceof Element) {
Element e = (Element) obj;
Object value = getValue(e);
_return.put(e.getNodeName(), value);
}
}
return _return;
}
public static Object getValue(Element e) {
if (e.getChildNodes() == null)
return null;
if (e.getChildNodes().getLength() == 1 && e.getFirstChild().getNodeType() != Node.ELEMENT_NODE) {
return e.getFirstChild().getNodeValue();
} else {
Object _return = null;
Node node = e.getFirstChild();
String tempName = null;
Object tempValue = null;
int i = 0;
boolean sure = false;
List<Object> re = null;
Map<String, Object> rem = null;
for (; node != null; node = node.getNextSibling()) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
if (i == 0) {
tempName = node.getNodeName();
tempValue = getValue((Element) node);
} else {
if (node.getNodeName().equals(tempName)) {
if (!sure) {
rem = new HashMap<String, Object>();
re = new ArrayList<Object>();
rem.put(tempName, re);
re.add(tempValue);
_return = rem;
}
re.add(getValue((Element) node));
sure = true;
} else {
if (!sure) {
rem = new HashMap<String, Object>();
rem.put(tempName, tempValue);
_return = rem;
}
rem.put(node.getNodeName(), getValue((Element) node));
sure = true;
}
}
i++;
}
}
if (i == 1) {
Map<String, Object> _r = new HashMap<String, Object>();
_r.put(tempName, tempValue);
return _r;
}
return _return;
}
}
public static Element toElement(String key, Object value, boolean mapAsAttribute) throws SlxException {
Document doc = null;
Element element = null;
try {
doc = getTempDocument();
element = doc.createElement(key);
if (value instanceof Map) {
_buildMap(element, (Map) value, mapAsAttribute);
} else if (value instanceof List) {
_buildList(element, (List) value, mapAsAttribute);
} else {
element.setTextContent(value.toString());
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
throw new SlxException(Tmodule.XML, Texception.XML_CREATE_DOCUMENT, e);
}
return element;
}
/**
* @param element
* @param value
* @param mapAsAttribute
* @throws ParserConfigurationException
*/
private static void _buildList(Element element, List value, boolean mapAsAttribute) throws ParserConfigurationException {
for (Object _v : value) {
if (_v instanceof Map) {
_buildMap(element, (Map) _v, mapAsAttribute);
} else if (_v instanceof List) {
_buildList(element, (List) _v, mapAsAttribute);
} else {
Document doc = getTempDocument();
Element child = doc.createElement(autoBuildTags(element.getNodeName()));
child.setTextContent(_v.toString());
element.appendChild(child);
}
}
}
public static Element toElement(String key, Object value) throws SlxException {
return toElement(key, value, false);
}
private static void _buildMap(Element element, Map mvalue, boolean mapAsAttribute) throws ParserConfigurationException {
for (Object _key : mvalue.keySet()) {
Document doc = getTempDocument();
Element child = doc.createElement(_key.toString());
Object _value = mvalue.get(_key);
element.appendChild(child);
if (_value instanceof Map) {
_buildMap(child, (Map) _value, mapAsAttribute);
} else if (_value instanceof List) {
_buildList(child, (List) _value, mapAsAttribute);
} else {
if (mapAsAttribute)
child.setAttribute((String) _key, _value!=null?_value.toString():"");
else
child.setTextContent(_value!=null?_value.toString():"");
}
}
}
private static String autoBuildTags(String parent) {
if (parent.endsWith("s") || parent.endsWith("S")) {
parent.subSequence(0, parent.length() - 1);
}
return parent;
}
private static Document getTempDocument() throws ParserConfigurationException {
if (tempDoc == null) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
tempDoc = builder.newDocument();
}
return tempDoc;
}
private static Document tempDoc;
}