All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feilong.lib.xstream.io.path.Path Maven / Gradle / Ivy

Go to download

feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.

There is a newer version: 4.0.8
Show newest version
/*
 * Copyright (C) 2004, 2005 Joe Walnes.
 * Copyright (C) 2006, 2007, 2009, 2013 XStream Committers.
 * All rights reserved.
 *
 * The software in this package is published under the terms of the BSD
 * style license a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 * 
 * Created on 02. September 2004 by Joe Walnes
 */
package com.feilong.lib.xstream.io.path;

import java.util.ArrayList;
import java.util.List;

import com.feilong.lib.xstream.core.util.FastStack;

/**
 * Represents a path to a single node in the tree.
 *
 * 

* Two absolute paths can also be compared to calculate the relative path between them. * A relative path can be applied to an absolute path to calculate another absolute path. *

* *

* Note that the paths are normally XPath compliant, so can be read by other XPath engines. * However, {@link #toString()} will select a node list while {@link #explicit()} will always select * an individual node. If the return type of the XPath evaluation is a node, the result will be the same, * because XPath will then use the first element of the list. The following are examples of path * expressions that the Path object supports: *

* *

* Note that the implementation does not take care if the paths are XPath compliant, it simply * manages the values between the path separator. However, it normalizes the path if a path element * ends with a selector for the first element (i.e. "[1]"). Those will be handled transparent i.e. two Paths * are treated equal if one was created with path elements containing this selector and the other one * without. *

* *

* The following are examples of path expressions that the Path object supports: *

*
    *
  • /
  • *
  • /some/node
  • *
  • /a/b/c/b/a
  • *
  • /a/b[1]/c[1]/b[1]/a[1]
  • *
  • /some[3]/node[2]/a
  • *
  • ../../../another[3]/node
  • *
* *

Example

* *
 * 
 * Path a = new Path("/html/body/div[1]/table[2]/tr[3]/td/div");
 * 
 * Path b = new Path("/html/body/div/table[2]/tr[6]/td/form");
 *
 * Path relativePath = a.relativeTo(b); // produces: "../../../tr[6]/td/form"
 * 
 * Path c = a.apply(relativePath); // same as Path b.
 * 
* * @see PathTracker * * @author Joe Walnes */ public class Path{ private final String[] chunks; private transient String pathAsString; private transient String pathExplicit; private static final Path DOT = new Path(new String[] { "." }); public Path(String pathAsString){ // String.split() too slow. StringTokenizer too crappy. List result = new ArrayList(); int currentIndex = 0; int nextSeparator; this.pathAsString = pathAsString; while ((nextSeparator = pathAsString.indexOf('/', currentIndex)) != -1){ // normalize explicit paths result.add(normalize(pathAsString, currentIndex, nextSeparator)); currentIndex = nextSeparator + 1; } result.add(normalize(pathAsString, currentIndex, pathAsString.length())); String[] arr = new String[result.size()]; result.toArray(arr); chunks = arr; } private String normalize(String s,int start,int end){ if (end - start > 3 && s.charAt(end - 3) == '[' && s.charAt(end - 2) == '1' && s.charAt(end - 1) == ']'){ this.pathAsString = null; return s.substring(start, end - 3); }else{ return s.substring(start, end); } } public Path(String[] chunks){ this.chunks = chunks; } @Override public String toString(){ if (pathAsString == null){ StringBuffer buffer = new StringBuffer(); for (int i = 0; i < chunks.length; i++){ if (i > 0){ buffer.append('/'); } buffer.append(chunks[i]); } pathAsString = buffer.toString(); } return pathAsString; } public String explicit(){ if (pathExplicit == null){ StringBuffer buffer = new StringBuffer(); for (int i = 0; i < chunks.length; i++){ if (i > 0){ buffer.append('/'); } String chunk = chunks[i]; buffer.append(chunk); int length = chunk.length(); if (length > 0){ char c = chunk.charAt(length - 1); if (c != ']' && c != '.'){ buffer.append("[1]"); } } } pathExplicit = buffer.toString(); } return pathExplicit; } @Override public boolean equals(Object o){ if (this == o){ return true; } if (!(o instanceof Path)){ return false; } final Path other = (Path) o; if (chunks.length != other.chunks.length){ return false; } for (int i = 0; i < chunks.length; i++){ if (!chunks[i].equals(other.chunks[i])){ return false; } } return true; } @Override public int hashCode(){ int result = 543645643; for (String chunk : chunks){ result = 29 * result + chunk.hashCode(); } return result; } public Path relativeTo(Path that){ int depthOfPathDivergence = depthOfPathDivergence(chunks, that.chunks); String[] result = new String[chunks.length + that.chunks.length - 2 * depthOfPathDivergence]; int count = 0; for (int i = depthOfPathDivergence; i < chunks.length; i++){ result[count++] = ".."; } for (int j = depthOfPathDivergence; j < that.chunks.length; j++){ result[count++] = that.chunks[j]; } if (count == 0){ return DOT; }else{ return new Path(result); } } private int depthOfPathDivergence(String[] path1,String[] path2){ int minLength = Math.min(path1.length, path2.length); for (int i = 0; i < minLength; i++){ if (!path1[i].equals(path2[i])){ return i; } } return minLength; } public Path apply(Path relativePath){ FastStack absoluteStack = new FastStack(16); for (String chunk : chunks){ absoluteStack.push(chunk); } for (String relativeChunk : relativePath.chunks){ if (relativeChunk.equals("..")){ absoluteStack.pop(); }else if (!relativeChunk.equals(".")){ absoluteStack.push(relativeChunk); } } String[] result = new String[absoluteStack.size()]; for (int i = 0; i < result.length; i++){ result[i] = (String) absoluteStack.get(i); } return new Path(result); } public boolean isAncestor(Path child){ if (child == null || child.chunks.length < chunks.length){ return false; } for (int i = 0; i < chunks.length; i++){ if (!chunks[i].equals(child.chunks[i])){ return false; } } return true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy