package ca.ucalgary.seahawk.util;

import java.util.logging.*;
import org.w3c.dom.*;

/**
 * Retrieves XML DOM Nodes form a document using XPointer locators such as /1/1/2/3/1/67.
 */

public class XPointerResolver{
    
    private static Logger logger = Logger.getLogger(XPointerResolver.class.getName());

    /**
     * Note, this currently only works for stuff like /1/1/2/3/1/67, 
     * not all XPointers, which includes functions, etc.
     */
    public static Node getNodeFromXPointer(Node rootNode, String xptr){
        if(rootNode == null || xptr == null || xptr.length() < 2){
	    return null;
        }
	Node currentNode = rootNode;
	if(currentNode == null){
	    return null;
	}
	if(rootNode instanceof Document){
	    currentNode = ((Document) rootNode).getDocumentElement();
	    if(xptr.equals("/1")){
		return currentNode;
	    }
        
	    // Get rid of leading "/1/"
	    xptr = xptr.substring(3);
	}
	String[] ordinal_steps = xptr.split("/");
	if(ordinal_steps.length == 0){
	    return currentNode;
	}    
	boolean first = true;
	for(String step: ordinal_steps){
	    int which = Integer.parseInt(step);
	    NodeList children = currentNode.getChildNodes();
	    int length = children.getLength();
	    int elementCount = 0;
	    int i = 0;
	    for(; i < length; i++){
		Node n = children.item(i);
		if(n instanceof Element && ++elementCount == which){
		    currentNode = n;
		    break;
		}
	    }
	    if(i == length){
		//warn of failed xpointer retrieval?
		logger.log(Level.WARNING, "Could not resolve XPointer "+xptr+
			   ", last matching node was " + currentNode.getLocalName());
		return null;
	    }
	}

	return currentNode;
    }
}
