/**
* Copyright (C) 2010-2017 Structr GmbH
*
* This file is part of Structr <http://structr.org>.
*
* Structr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Structr 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Structr. If not, see <http://www.gnu.org/licenses/>.
*/
package org.structr.web.function;
import java.util.LinkedList;
import java.util.List;
import org.structr.common.error.FrameworkException;
import org.structr.core.GraphObjectMap;
import org.structr.core.function.XmlFunction;
import org.structr.core.property.GenericProperty;
import org.structr.core.property.Property;
import org.structr.core.property.StringProperty;
import org.structr.schema.action.ActionContext;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
*
*/
public class FromXmlFunction extends UiFunction {
private static final Property<List> attributesProperty = new GenericProperty<>("attributes");
private static final Property<List> childrenProperty = new GenericProperty<>("children");
private static final Property<String> valueProperty = new StringProperty("value");
private static final Property<String> nameProperty = new StringProperty("name");
private static final Property<String> typeProperty = new StringProperty("type");
public static final String ERROR_MESSAGE_FROM_XML = "Usage: ${from_xml(source)}. Example: ${from_xml('<entry>0</entry>')}";
public static final String ERROR_MESSAGE_FROM_XML_JS = "Usage: ${{Structr.from_xml(src)}}. Example: ${{Structr.from_xml('<entry>0</entry>')}}";
@Override
public Object apply(final ActionContext ctx, final Object caller, Object[] sources) throws FrameworkException {
if (sources != null && sources.length > 0) {
if (sources[0] == null) {
return "";
}
try {
final GraphObjectMap result = new GraphObjectMap();
final XmlFunction xml = new XmlFunction();
final Document document = (Document)xml.apply(ctx, caller, sources);
if (document != null) {
convertNode(result, document);
return result;
} else {
logger.warn("Unable to parse XML document: {}", sources[0].toString());
}
} catch (Throwable t) {
logException(caller, t, sources);
}
return "";
} else {
logParameterError(caller, sources, ctx.isJavaScriptContext());
}
return usage(ctx.isJavaScriptContext());
}
@Override
public String usage(boolean inJavaScriptContext) {
return (inJavaScriptContext ? ERROR_MESSAGE_FROM_XML_JS : ERROR_MESSAGE_FROM_XML);
}
@Override
public String shortDescription() {
return "Parses the given XML and returns a list of objects.";
}
@Override
public String getName() {
return "from_xml";
}
// ----- private methods -----
private void convertNode(final GraphObjectMap map, final Node node) {
final NodeList nodeList = node.getChildNodes();
if (nodeList != null) {
final List<GraphObjectMap> children = new LinkedList<>();
final int length = nodeList.getLength();
for (int i=0; i<length; i++) {
final GraphObjectMap childMap = new GraphObjectMap();
final Node childNode = nodeList.item(i);
convertNode(childMap, childNode);
children.add(childMap);
}
map.put(childrenProperty, children);
}
final NamedNodeMap attributeList = node.getAttributes();
if (attributeList != null) {
final List<GraphObjectMap> attributes = new LinkedList<>();
final int length = attributeList.getLength();
for (int i=0; i<length; i++) {
final GraphObjectMap attributeMap = new GraphObjectMap();
final Node attributeNode = attributeList.item(i);
convertNode(attributeMap, attributeNode);
attributes.add(attributeMap);
}
map.put(attributesProperty, attributes);
}
map.put(typeProperty, node.getClass().getSimpleName());
final String nodeName = node.getNodeName();
if (nodeName != null) {
map.put(nameProperty, nodeName);
}
final String nodeValue = node.getNodeValue();
if (nodeValue != null) {
map.put(valueProperty, nodeValue);
}
}
}