/*
* (C) Copyright 2006-2008 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Alexandre Russel
*
* $Id$
*/
package org.nuxeo.ecm.platform.annotations.gwt.client.util;
import java.util.ArrayList;
import java.util.List;
import org.nuxeo.ecm.platform.annotations.gwt.client.AnnotationConstant;
import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.SpanElement;
/**
* @author <a href="mailto:arussel@nuxeo.com">Alexandre Russel</a>
*/
public class XPathUtil {
public String getXPath(Node node) {
Log.debug("XPathUtil] node: " + node.getNodeName() + " parent node: " + node.getParentNode().getNodeName());
Document document = node.getOwnerDocument();
Node current = node;
StringBuilder xpath = new StringBuilder();
while (!current.equals(document)) {
int counter = 1;
String name = current.getNodeName();
while (current.getPreviousSibling() != null) {
if (current.getPreviousSibling().getNodeName().equalsIgnoreCase(name)
&& !isIgnored(current.getPreviousSibling())) {
counter++;
}
current = current.getPreviousSibling();
}
xpath.insert(0, "/" + name.toLowerCase() + "[" + counter + "]");
current = current.getParentNode();
}
Log.debug("XPathUtil] xpath: " + xpath);
return xpath.toString();
}
public String getSelectionXPointer(Range range) {
int start = range.getStartOffset();
Node clickedNode = range.getStartContainer();
Node parentNode = clickedNode.getParentNode();
if (clickedNode.getNodeType() == Node.TEXT_NODE) {
TextGrabberVisitor processor = new TextGrabberVisitor();
Visitor visitor = new Visitor(processor);
visitor.process(parentNode, clickedNode);
start += processor.getText().length();
}
Log.debug("getSelectionXPointer; start: " + start);
return "#xpointer(string-range(" + getXPath(parentNode) + ",\"\"," + start + ","
+ getShortLength(range.getSelectedText()) + "))";
}
public int getShortLength(String selectedText) {
for (String removed : new String[] { "\n", "\r" }) {
selectedText = selectedText.replace(removed, "");
}
return selectedText.length();
}
public List<Node> getNode(String xpath, Document document) {
List<Node> nodes = new ArrayList<Node>();
if (xpath.startsWith("//")) {
xpath = xpath.substring(2);
NodeList<Element> n = document.getElementsByTagName(xpath);
for (int x = 0; x < n.getLength(); x++) {
nodes.add(n.getItem(x));
}
return nodes;
}
Log.debug("XPathUtil#getNode -- xpath: " + xpath);
String[] paths = xpath.split("/");
Node result = document;
for (String path : paths) {
if ("".equals(path)) {
continue;
}
NodeList<Node> nodeList = result.getChildNodes();
String name = path.substring(0, path.indexOf("["));
int index = Integer.parseInt(path.substring(path.indexOf("[") + 1, path.indexOf("]")));
int counter = 1;
for (int x = 0; x < nodeList.getLength(); x++) {
Node node = nodeList.getItem(x);
if (node.getNodeName().equalsIgnoreCase(name)) {
if (isIgnored(node)) {// considered as text node
continue;
}
if (counter == index) {
result = node;
break;
}
counter++;
}
}
}
nodes.add(result);
Log.debug("XPathUtil#getNode -- end function: ");
return nodes;
}
private boolean isIgnored(Node node) {
int nodeType = node.getNodeType();
if (nodeType != Node.ELEMENT_NODE && nodeType != Node.TEXT_NODE) {
return true; // ignore non element and non text node
}
if (node.getNodeName().equalsIgnoreCase("span")) {
SpanElement spanElement = SpanElement.as(node).cast();
String name = spanElement.getClassName();
if (name == null) {
return false;
}
return name.contains(AnnotationConstant.IGNORED_ELEMENT);
} else if (node.getNodeName().equalsIgnoreCase("div")) {
DivElement divElement = DivElement.as(node).cast();
return divElement.getClassName().equals(AnnotationConstant.IGNORED_ELEMENT);
}
return false;
}
public boolean isChildOfIgnored(Node node) {
boolean ignored = false;
while (node != null && !ignored) {
ignored = isIgnored(node);
node = node.getParentNode();
}
return ignored;
}
public static String toIdableName(String xpath) {
xpath = "X" + xpath;
xpath = xpath.replace("/", "-");
xpath = xpath.replace("[", "_");
return xpath.replace("]", ":");
}
public static String fromIdableName(String xpath) {
xpath = xpath.substring(1);
xpath = xpath.replace("-", "/");
xpath = xpath.replace("_", "[");
return xpath.replace(":", "]");
}
}