| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| */ |
| |
| /* |
| * PositionFinderVisitor.java |
| * |
| * Created on October 26, 2005, 3:02 PM |
| * |
| * To change this template, choose Tools | Template Manager |
| * and open the template in the editor. |
| */ |
| |
| package org.netbeans.modules.xml.xdm.visitor; |
| |
| import java.util.List; |
| import org.netbeans.modules.xml.xdm.nodes.Attribute; |
| import org.netbeans.modules.xml.xdm.nodes.Document; |
| import org.netbeans.modules.xml.xdm.nodes.Element; |
| import org.netbeans.modules.xml.xdm.nodes.Node; |
| import org.netbeans.modules.xml.xdm.nodes.NodeImpl; |
| import org.netbeans.modules.xml.xdm.nodes.Text; |
| import org.netbeans.modules.xml.xdm.nodes.Token; |
| import org.netbeans.modules.xml.xdm.nodes.TokenType; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.NodeList; |
| /** |
| * |
| * @author rico |
| */ |
| public class PositionFinderVisitor implements XMLNodeVisitor{ |
| |
| int position = 0; |
| Node node; |
| boolean found; |
| |
| public int findPosition(Node rootNode, Node node){ |
| reset(); |
| this.node = node; |
| rootNode.accept(this); |
| |
| return position; |
| } |
| |
| public void reset(){ |
| position = 0; |
| found = false; |
| } |
| |
| public void visit(Document doc) { |
| //xml processing instruction |
| position += getLengthOfTokens(doc); |
| NodeList nodes = doc.getChildNodes(); |
| for(int i = 0; i < nodes.getLength(); i++){ |
| Node n = (Node)nodes.item(i); |
| n.accept(this); |
| if(found) return; |
| } |
| } |
| |
| public void visit(Element e) { |
| if(e.getId() == node.getId()){ |
| found = true; |
| } else{ |
| position += getElementStartTokenLength(e, true); //open start tag |
| NamedNodeMap attrs = e.getAttributes(); |
| for(int i = 0; i < attrs.getLength(); i++){ |
| Node attr = (Node)attrs.item(i); |
| attr.accept(this); |
| if(found) return; |
| } |
| position += getStartTagWhiteSpaceTokensLength(e); //all whitespaces |
| position++; //close of start tag |
| NodeList children = e.getChildNodes(); |
| for(int i = 0; i < children.getLength(); i++){ |
| Node n = (Node)children.item(i); |
| n.accept(this); |
| if(found) return; |
| } |
| position += getElementStartTokenLength(e, false); //open end tag |
| position += getEndTagWhiteSpaceTokensLength(e); //all whitespaces |
| position++; //close of end tag |
| } |
| } |
| |
| public void visit(Text txt) { |
| if(txt.getId() == node.getId()){ |
| found = true; |
| } else{ |
| int txtLen = getLength(txt); |
| if(txtLen > 0) |
| position += txtLen; |
| } |
| } |
| |
| public void visit(Attribute attr) { |
| if(attr.getId() == node.getId()){ |
| //add preceding white spaces |
| position += getLeadingWhiteSpaces(attr); |
| found = true; |
| } else{ |
| position += getLengthOfTokens(attr); |
| } |
| } |
| |
| private int getLength(Text n) { |
| int len = 0; |
| for(Token token:((NodeImpl)n).getTokens()) |
| len += token.getValue().length(); |
| return len; |
| } |
| |
| /** |
| * Obtains the length of a start token of elements, e.g., "<", or "<elementname", |
| * "</", or "</elementname". |
| * @param node The element being queried |
| * @param beginTag Is this for the start tag (<) or end tag (</)? |
| * @return length of start element |
| */ |
| private int getElementStartTokenLength(Element element, boolean beginTag){ |
| String value = ""; |
| List<Token> tokens = element.getTokens(); |
| for(Token token : tokens){ |
| if(token.getType() != TokenType.TOKEN_ELEMENT_START_TAG){ |
| continue; |
| } |
| String tokenValue = token.getValue(); |
| if(beginTag){ |
| if(!tokenValue.startsWith("</")){ |
| value = tokenValue; |
| } |
| } else{ //end tag |
| if(tokenValue.startsWith("</")){ |
| value = tokenValue; |
| } |
| } |
| } |
| return value.length(); |
| } |
| |
| private int getStartTagWhiteSpaceTokensLength(NodeImpl node){ |
| StringBuilder buf = new StringBuilder(); |
| List<Token> tokens = node.getTokens(); |
| for(Token token : tokens){ |
| if (token.getType() == TokenType.TOKEN_ELEMENT_END_TAG){ |
| break; // only count whitspace before first tag end |
| } |
| if (token.getType() == TokenType.TOKEN_WHITESPACE) { |
| buf.append(token.getValue()); |
| } |
| } |
| return buf.toString().length(); |
| } |
| |
| private int getEndTagWhiteSpaceTokensLength(NodeImpl node){ |
| StringBuilder buf = new StringBuilder(); |
| List<Token> tokens = node.getTokens(); |
| boolean counting = false; |
| for(Token token : tokens){ |
| if (token.getType() == TokenType.TOKEN_ELEMENT_START_TAG){ |
| if (token.getValue().startsWith("</")) { |
| counting = true; |
| } |
| } |
| if (! counting) continue; |
| if (token.getType() == TokenType.TOKEN_WHITESPACE) { |
| buf.append(token.getValue()); |
| } |
| } |
| return buf.toString().length(); |
| } |
| |
| private int getLeadingWhiteSpaces(Attribute attr){ |
| Token firstToken = attr.getTokens().get(0); //get the first token |
| if(firstToken.getType() == TokenType.TOKEN_WHITESPACE){ |
| return firstToken.getValue().length(); |
| } |
| return 0; |
| } |
| |
| private int getLengthOfTokens(NodeImpl node){ |
| StringBuilder buf = new StringBuilder(); |
| List<Token> tokens = node.getTokens(); |
| for(Token token : tokens){ |
| buf.append(token.getValue()); |
| } |
| return buf.length(); |
| } |
| |
| } |