package org.develnext.jphp.ext.xml.classes;
import org.develnext.jphp.ext.xml.XmlExtension;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import php.runtime.Memory;
import php.runtime.annotation.Reflection;
import php.runtime.annotation.Reflection.Name;
import php.runtime.annotation.Reflection.Signature;
import php.runtime.env.Environment;
import php.runtime.lang.BaseWrapper;
import php.runtime.lang.IObject;
import php.runtime.memory.ArrayMemory;
import php.runtime.memory.ReferenceMemory;
import php.runtime.memory.StringMemory;
import php.runtime.reflection.ClassEntity;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
@Name(XmlExtension.NAMESPACE + "DomNode")
@Reflection.WrapInterface(WrapDomNode.Methods.class)
public class WrapDomNode extends BaseWrapper<Node> {
interface Methods {
String getBaseURI();
String getNamespaceURI();
String getLocalName();
String getNodeName();
String getNodeValue();
short getNodeType();
String getPrefix();
String getTextContent();
Node getFirstChild();
Node getLastChild();
Node getNextSibling();
Node getPreviousSibling();
Node getParentNode();
boolean hasAttributes();
boolean hasChildNodes();
boolean isDefaultNamespace(String namespace);
boolean isEqualNode(Node node);
boolean isSameNode(Node node);
boolean isSupported(String feature, String version);
String lookupNamespaceURI(String prefix);
String lookupPrefix(String namespaceURI);
void normalize();
void setTextContent(String textContent);
void setPrefix(String prefix);
Node cloneNode(boolean deep);
Node appendChild(Node node);
Node removeChild(Node oldChild);
Node replaceChild(Node newChild, Node oldChild);
Node insertBefore(Node newChild, Node refChild);
}
protected XPath xPath = null;
public WrapDomNode(Environment env, Node wrappedObject) {
super(env, wrappedObject);
}
public WrapDomNode(Environment env, ClassEntity clazz) {
super(env, clazz);
}
protected XPath getXPath() {
if (xPath == null) {
xPath = XPathFactory.newInstance().newXPath();
}
return xPath;
}
@Signature
private void __construct() {}
@Signature
public WrapDomDocument getOwnerDocument(Environment env) {
return new WrapDomDocument(env, getWrappedObject().getOwnerDocument());
}
@Signature
public String get(String expression) throws XPathExpressionException {
return (String) getXPath().evaluate(expression, getWrappedObject(), XPathConstants.STRING);
}
@Signature
public IObject find(Environment env, String expression) throws XPathExpressionException {
Node node = (Node) getXPath().evaluate(expression, getWrappedObject(), XPathConstants.NODE);
if (node == null) {
return null;
}
if (node instanceof Element) {
return new WrapDomElement(env, (Element) node);
}
return new WrapDomNode(env, node);
}
@Signature
public NodeList findAll(String expression) throws XPathExpressionException {
return (NodeList) getXPath().evaluate(expression, getWrappedObject(), XPathConstants.NODESET);
}
@Signature
public NodeList getChildNodes() {
return getWrappedObject().getChildNodes();
}
@Signature
public String __toString() {
return getWrappedObject().getTextContent();
}
@Signature
public Memory toModel() {
return toModel(getWrappedObject());
}
protected static Memory toModel(Node node) {
if (node.getNodeType() == Node.TEXT_NODE) {
return StringMemory.valueOf(node.getTextContent());
}
ArrayMemory result = new ArrayMemory(true);
NamedNodeMap attrs = node.getAttributes();
for (int i = 0; i < attrs.getLength(); i++) {
Node attr = attrs.item(i);
result.refOfIndex("@" + attr.getNodeName()).assign(attr.getNodeValue());
}
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node el = children.item(i);
if (el.getNodeType() == Node.TEXT_NODE) {
continue;
}
if (el.hasAttributes() || el.hasChildNodes()) {
if (el.getChildNodes().getLength() == 1 && el.getFirstChild().getNodeType() == Node.TEXT_NODE) {
ReferenceMemory one = result.getByScalar(el.getNodeName());
if (one != null) {
if (!one.isArray()) {
ArrayMemory tmp = new ArrayMemory();
tmp.refOfPush().assign(one.toValue());
one.assign(tmp);
}
one.refOfPush().assign(el.getFirstChild().getTextContent());
result.refOfIndex(el.getNodeName()).assignRef(one.toValue());
} else {
result.refOfIndex(el.getNodeName()).assign(el.getFirstChild().getTextContent());
}
} else {
result.refOfIndex(el.getNodeName()).assign(toModel(el).toImmutable());
}
} else {
result.refOfIndex(el.getNodeName()).assign(el.getTextContent());
}
}
if (result.size() == 1) {
Memory tmp = result.getByScalar("item");
if (tmp != null) {
if (tmp.isArray()) {
return tmp.toValue(ArrayMemory.class).toConstant();
} else {
ArrayMemory m = new ArrayMemory();
m.add(tmp.toValue());
return m.toConstant();
}
}
}
return result.toConstant();
}
}