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

convex.dlfs.DLPath Maven / Gradle / Ivy

The newest version!
package convex.dlfs;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.InvalidPathException;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchEvent.Modifier;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Arrays;
import java.util.Objects;
import java.util.regex.Pattern;

import convex.core.data.AString;
import convex.core.data.StringShort;
import convex.core.util.Utils;

/**
 * A DLFS Path
 * 
 * Path components are Strings, separated by "/"
 */
public final class DLPath implements Path {

	protected final DLFileSystem fileSystem;
	protected final AString[] names;
	protected final boolean absolute;
	protected final int count;
	
	private String pathString=null;
	
	static final StringShort DOT=StringShort.create(".");
	static final StringShort SLASHDOT=StringShort.create("/.");
	static final StringShort DOTDOT=StringShort.create("..");
	
	static final AString[] EMPTY_STRINGS = new AString[0];

	protected DLPath(DLFileSystem fs) {
		this(fs,EMPTY_STRINGS,false);
	}
	
	protected DLPath(DLFileSystem fs,AString[] names, boolean absolute) {
		this.fileSystem=fs;
		this.names=names;
		this.absolute=absolute;
		this.count=names.length;
	}

	static DLPath createRoot(DLFileSystem fileSystem) {
		return new DLPath(fileSystem,EMPTY_STRINGS,true);
	}
	
	static final Pattern endSlashes = Pattern.compile("/+$");
	
	static DLPath create(DLFileSystem fs, String fullPath) {
		String path=fullPath;
		String sep=DLFileSystem.SEP;
		if (path.isEmpty()) throw new InvalidPathException(fullPath,"Empty path name");
		
		boolean absolute=false;
		{
			int ix=0;
			while ((ix0) {
				absolute=true;
				path=path.substring(ix);
			}
		}
		
		// From POSIX 4.11 A pathname that contains at least one non-slash character and that ends with one or more trailing slashes shall be resolved as if a single dot character ( '.' ) were appended to the pathname.
		if (path.endsWith(sep)) {
			path=endSlashes.matcher(path).replaceAll("/.");
		}

		String[] names=path.isEmpty()?Utils.EMPTY_STRINGS:path.split(sep);
		int n=names.length;
		AString[] ns=new AString[n];
		for (int i=0; i=n)) throw new IllegalArgumentException("index out of range");
		if (!absolute&(count==1)) return this;
		return new DLPath(fileSystem,new AString[] {names[index]},false);
	}

	@Override
	public DLPath subpath(int beginIndex, int endIndex) {
		int n=getNameCount();
		if ((beginIndex<0)||(endIndex>n)) throw new IllegalArgumentException("index out of range");
		if (beginIndex>endIndex) throw new IllegalArgumentException("negative length");
		if (beginIndex==endIndex) return fileSystem.getEmptyPath();
		if (!absolute&&(beginIndex==0)&&(endIndex==n)) return this;
		return new DLPath(fileSystem,Arrays.copyOfRange(names, beginIndex, endIndex),false);
	}
	
	/**
	 * Return a subpath starting from the given index
	 * @param beginIndex Starting index
	 * @return Relative subpath in smae manner as {@link #subpath(int, int)}
	 */
	public DLPath subpath(int beginIndex) {
		return subpath(beginIndex,count);
	}

	@Override
	public boolean startsWith(Path other) {
		if (!(other instanceof DLPath)) return false;
		return startsWith((DLPath)other);
	}
	
	public boolean startsWith(DLPath other) {
		if (absolute!=other.absolute) return false;
		int n=other.getNameCount();
		if (n>count) return false; // can't start with a longer path!
		if (!fileSystem.equals(other.fileSystem)) return false; 
		return Utils.arrayEquals(names,other.names,n);
	}

	@Override
	public boolean endsWith(Path other) {
		if (!(other instanceof DLPath)) return false;
		return endsWith((DLPath)other);
	}
	
	public boolean endWith(DLPath other) {
		if (absolute!=other.absolute) return false;
		int n=other.getNameCount();
		if (n>count) return false; // can't start with a longer path!
		if (!fileSystem.equals(other.fileSystem)) return false; 
		return Utils.arrayEquals(names,other.names,n);
	}

	@Override
	public DLPath normalize() {
		if (count==0) return this;  // nothing to normalize
		
		int j=0; // new names
		AString[] dest=names;
		for (int i=0; i0)?-1:0; 
				} else {
					// we delete previous if it wasn't .. itself, otherwise keep
					strategy=((j>0)&&(!DOTDOT.equals(dest[j-1])))?-1:1;
				}
			} else {
				// copy element across iff we have dest, increment j always
				strategy=1;
			}
			switch (strategy) {
				case -1: if (dest==names) dest=names.clone(); if (j>0) j--; break;
				case 0: if (dest==names) dest=names.clone(); break; // skip by not incrementing j
				case 1: if (dest!=names) dest[j]=c; j++; break; // copy across
			}
		}
		if (j==count) return this; // nothing changed
		if (dest.length>j) dest=Arrays.copyOfRange(dest,0,j); // trim to length j if needed
		return new DLPath(fileSystem,dest,absolute);
	}

	@Override
	public Path resolve(Path other) {
		if (other.isAbsolute()) return other;
		if (other.getNameCount()==0) return this;
		AString[] newNames=Utils.concat(names, extractNames(other));
		return new DLPath(fileSystem,newNames,absolute);
	}
	
	public DLPath resolve(AString nameToAppend) {
		AString name=DLFS.checkName(nameToAppend);
		if (name==null) throw new InvalidPathException(nameToAppend.toString(),"Invalid path name: ");
		AString[] newNames=Arrays.copyOf(names, count+1);
		newNames[count]=name;
		return new DLPath(fileSystem,newNames,absolute);
	}

	/**
	 * Get CVM names from another path as an array
	 * @param other Other path (should be a {@link DLPath})
	 * @return CVM name array
	 */
	private static AString[] extractNames(Path other) {
		if (other instanceof DLPath) {
			return ((DLPath)other).names;
		}
		return null;
	}

	@Override
	public DLPath relativize(Path other) {
		if (!(other instanceof DLPath)) throw new IllegalArgumentException("Not a DLFS path");
		return relativize((DLPath) other);
	}
	
	public DLPath relativize(DLPath other) {
		// same path implies relative path is the empty path
		if (this.equals(other)) return fileSystem.getEmptyPath();
		
		// if only one is absolute, can't construct relative path
		if (absolute!=other.isAbsolute()) return null;
		
		// can't produce relative path backwards
		int extra = other.count-count;
		if (extra<0) return null;
		
		for (int i=0; i[] events, Modifier... modifiers) throws IOException {
		throw new UnsupportedOperationException();
	}

	@Override
	public int compareTo(Path other) {
		if (!(other instanceof DLPath)) throw new IllegalArgumentException("Not a data lattice path!");
		return compareTo((DLPath)other);
	}
	
	public int compareTo(DLPath other) {
		int n1=this.getNameCount();
		int n2=other.getNameCount(); 
		int n=Math.min(n1,n2);
		for (int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy