org.conqat.lib.commons.uniformpath.RelativeUniformPath Maven / Gradle / Ivy
/*-------------------------------------------------------------------------+
| |
| Copyright (c) 2005-2018 The ConQAT Project |
| |
| 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. |
| |
+-------------------------------------------------------------------------*/
package org.conqat.lib.commons.uniformpath;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import org.conqat.lib.commons.collections.CollectionUtils;
import org.conqat.lib.commons.string.StringUtils;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
/**
* A relative uniform path that can be resolved against an absolute uniform
* path. In contrast to absolute uniform paths, relative paths are not typed.
*/
public final class RelativeUniformPath {
/**
* The constituent segments of this uniform path, e.g. for the path
* {@code src/main} this would be the array {@code [src, main]}. Segments may
* consist of dots or be empty.
*/
private final String[] segments;
private RelativeUniformPath(String... pathSegments) {
this(Arrays.asList(pathSegments));
}
private RelativeUniformPath(Iterable pathSegments) {
this.segments = Iterables.toArray(pathSegments, String.class);
}
/**
* Creates a relative uniform path from the given segments. No resolution of
* relative segments (such as {@code ../src}) is attempted at this stage.
*
* @see #of(List)
*/
public static RelativeUniformPath of(String... segments) {
Preconditions.checkNotNull(segments, UniformPath.SEGMENTS_LIST_MAY_NOT_BE_NULL);
return of(Arrays.asList(segments));
}
/**
* Creates a relative uniform path from the given segments. No resolution of
* relative segments (such as {@code ../src}) is attempted at this stage.
*/
public static RelativeUniformPath of(List segments) {
Preconditions.checkNotNull(segments, UniformPath.SEGMENTS_LIST_MAY_NOT_BE_NULL);
for (String segment : segments) {
UniformPath.checkSegmentValidity(segment, segments, s -> s == null, "empty segment");
UniformPath.checkSegmentValidity(segment, segments,
s -> StringUtils.splitWithEscapeCharacter(s, "/").size() > 1, "contains unescaped slash");
}
if (segments.isEmpty()) {
return new RelativeUniformPath(new String[0]);
}
return new RelativeUniformPath(segments);
}
/**
* Resolves relative path segments such as (such as {@code src/main/../java}) to
* the absolute segments of the path (e.g. {@code [src, java]}).
*/
/* package */ static List resolveRelativeSegments(List pathSegments) {
List canonicalSegments = CollectionUtils.filter(pathSegments,
segment -> !(StringUtils.isEmpty(segment) || segment.equals(".")));
ListIterator canonicalSegmentsIterator = canonicalSegments.listIterator();
while (canonicalSegmentsIterator.hasNext()) {
if (canonicalSegmentsIterator.next().equals("..")) {
// Remove both previous element and the ".." item
canonicalSegmentsIterator.previous();
canonicalSegmentsIterator.remove();
if (!canonicalSegmentsIterator.hasPrevious()) {
throw new IllegalArgumentException(
"Invalid path (refers outside the root folder): " + String.join("/", pathSegments));
}
canonicalSegmentsIterator.previous();
canonicalSegmentsIterator.remove();
}
}
return canonicalSegments;
}
/** Returns a read-only view of the segments of this relative uniform path. */
/* package */ List getSegments() {
return Collections.unmodifiableList(Arrays.asList(segments));
}
/** Returns the name of the last segment of this path. */
public String getLastSegment() {
if (segments.length == 0) {
throw new IllegalArgumentException("Cannot get the last segment of the root path");
}
return segments[segments.length - 1];
}
/**
* Creates a new {@link RelativeUniformPath} by prepending the given suffixes to
* the relative uniform path.
*/
public RelativeUniformPath addSuffix(String... suffix) {
String[] newSegments = Arrays.copyOf(this.segments, this.segments.length + suffix.length);
System.arraycopy(suffix, 0, newSegments, this.segments.length, suffix.length);
return RelativeUniformPath.of(newSegments);
}
/**
* Resolves this relative path against the given absolute path, performing path
* canonicalization in the process (i.e. ".." will be resolved to parent
* segment).
*/
public UniformPath resolveAgainstAbsolutePath(UniformPath uniformPath) {
return uniformPath.resolve(this);
}
@Override
public String toString() {
return String.join("/", segments);
}
@Override
public int hashCode() {
return Arrays.hashCode(segments);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof RelativeUniformPath)) {
return false;
}
RelativeUniformPath other = (RelativeUniformPath) obj;
return Arrays.equals(segments, other.segments);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy