package org.itsnat.droid.impl.browser.serveritsnat;
import android.view.View;
import android.view.ViewGroup;
import org.itsnat.droid.ItsNatDroidException;
import org.itsnat.droid.impl.xmlinflated.layout.InflatedXMLLayoutPageImpl;
/**
* Created by jmarranz on 13/06/14.
*/
public class DOMPathResolverImpl implements DOMPathResolver
{
protected ItsNatDocItsNatImpl itsNatDoc;
public DOMPathResolverImpl(ItsNatDocItsNatImpl itsNatDoc)
{
this.itsNatDoc = itsNatDoc;
}
private View getRootView()
{
InflatedXMLLayoutPageImpl layout = itsNatDoc.getPageImpl().getInflatedXMLLayoutPageImpl();
return layout.getRootView();
}
private View getParentNode(View node)
{
return (View)node.getParent();
}
public Node getNodeFromPath(String pathStr,Node topParent)
{
String[] path = getArrayPathFromString(pathStr);
if (path == null) return null;
return NodeImpl.create(getNodeFromArrayPath(path,NodeImpl.getView(topParent)));
}
private String[] getArrayPathFromString(String pathStr)
{
if (pathStr == null) return null;
return pathStr.split(",");
}
private View getNodeFromArrayPath(String[] arrayPath,View topParent)
{
View viewRoot = getRootView();
if (arrayPath.length == 1)
{
String firstPos = arrayPath[0];
if (firstPos.equals("window")) throw new ItsNatDroidException("Unexpected window");
else if (firstPos.equals("document")) throw new ItsNatDroidException("Unexpected document node");
else if (firstPos.equals("doctype")) throw new ItsNatDroidException("Unexpected doctype node");
else if (firstPos.indexOf("eid:") == 0)
{
InflatedXMLLayoutPageImpl layout = itsNatDoc.getPageImpl().getInflatedXMLLayoutPageImpl();
String id = firstPos.substring("eid:".length());
View viewRes = layout.findViewByXMLId(id);
return viewRes;
}
}
if (topParent == null) topParent = viewRoot;
View viewRes = topParent;
int len = arrayPath.length;
for(int i = 0; i < len; i++)
{
String posStr = arrayPath[i];
viewRes = getChildNodeFromStrPos(viewRes,posStr);
}
return viewRes;
}
private View getChildNodeFromStrPos(View parentNode,String posStr)
{
if (posStr.equals("de")) return getRootView();
int posBracket = posStr.indexOf('[');
if (posBracket == -1)
{
int pos = Integer.parseInt(posStr);
return getChildNodeFromPos(parentNode,pos,false);
}
else
{
return null; // Ni atributo ni nodo de texto son válidos en este contexto
}
}
private View getChildNodeFromPos(View parentNode,int pos,boolean isTextNode)
{
if (!(parentNode instanceof ViewGroup)) return null;
return ((ViewGroup)parentNode).getChildAt(pos);
}
private boolean isFiltered(View node)
{
return false;
}
public String getStringPathFromNode(Node node,Node topParent)
{
if (node == null) return null;
String[] path = getNodePathArray(NodeImpl.getView(node),NodeImpl.getView(topParent));
if (path == null) return null;
return getStringPathFromArray(path);
}
private int getNodeDeep(View node,View topParent)
{
int i = 0;
while(node != topParent)
{
i++;
node = getParentNode(node);
if (node == null) return -1; // el nodo no esta bajo topParent
}
return i;
}
private String[] getNodePathArray(View nodeLeaf,View topParent)
{
if (nodeLeaf == null) return null;
if (topParent == null) topParent = getRootView();
// No usamos el locById porque los atributos especiales itsnat deberían de desaparecer en el cliente, no es imprescindible y en stateless por aquí no pasamos
View node = nodeLeaf;
int len = getNodeDeep(node,topParent);
if (len < 0) return null;
String[] path = new String[len];
for(int i = len - 1; i >= 0; i--)
{
String pos = getNodeChildPosition(node);
path[i] = pos;
node = getParentNode(node);
}
// path[len - 1] += this.getSuffix(nodeLeaf);
return path;
}
private String getNodeChildPosition(View node)
{
if (node == getRootView()) return "de";
ViewGroup parentNode = (ViewGroup)getParentNode(node);
if (parentNode == null) throw new ItsNatDroidException("Unexpected error");
int size = parentNode.getChildCount();
int pos = 0;
for(int i = 0; i < size; i++)
{
if (parentNode.getChildAt(i) == node) return "" + pos;
pos++;
}
return "-1";
}
private String getStringPathFromArray(String[] path)
{
String code = "";
int len = path.length;
for(int i = 0; i < len; i++)
{
if (i != 0) code += ",";
code += path[i];
}
return code;
}
}