Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (C) the original author or authors.
*
* 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 net.derquinse.common.jaxrs;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import com.google.common.base.CharMatcher;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.collect.ForwardingList;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
/**
* List of non-encoded URI path segments.
* @author Andres Rodriguez.
*/
@Immutable
public final class PathSegments extends ForwardingList {
private static final PathSegments EMPTY = new PathSegments(ImmutableList. of());
/**
* Returns an empty list of segments.
* @return An empty list of segments.
*/
public static PathSegments of() {
return EMPTY;
}
/**
* Turns a single segment into a list of decoded segments.
* @param segment Segment.
* @param encoded If the segment is encoded.
* @return The never {@code null} list of segments.
*/
public static PathSegments segment(@Nullable String segment, boolean encoded) {
if (segment == null || segment.length() == 0) {
return EMPTY;
}
String s = segment;
if (encoded) {
try {
s = URLDecoder.decode(s, "UTF-8");
} catch (UnsupportedEncodingException e) {
}
}
return new PathSegments(ImmutableList.of(s));
}
/**
* Turns a path string into a list of decoded segments.
* @param path Path to split.
* @param encoded If the path is encoded.
* @return The never {@code null} list of segments.
*/
public static PathSegments of(@Nullable String path, boolean encoded) {
if (path == null || path.length() == 0) {
return EMPTY;
}
ImmutableList.Builder builder = ImmutableList.builder();
for (String s : path.split("/")) {
if (s != null && s.length() > 0) {
if (encoded) {
try {
s = URLDecoder.decode(s, "UTF-8");
} catch (UnsupportedEncodingException e) {
}
}
builder.add(s);
}
}
return new PathSegments(builder.build());
}
/**
* Turns a collection of string into a list of decoded segments.
* @param encoded If the segments are encoded.
* @param segments String segments.
* @return The never {@code null} list of segments.
*/
public static PathSegments of(boolean encoded, @Nullable Iterable segments) {
if (segments == null) {
return EMPTY;
}
if (!encoded) {
return new PathSegments(ImmutableList.copyOf(segments));
}
ImmutableList.Builder builder = ImmutableList.builder();
for (String s : segments) {
if (s != null && s.length() > 0) {
if (encoded) {
try {
s = URLDecoder.decode(s, "UTF-8");
} catch (UnsupportedEncodingException e) {
}
}
builder.add(s);
}
}
ImmutableList list = builder.build();
if (list.isEmpty()) {
return EMPTY;
}
return new PathSegments(builder.build());
}
/**
* Turns an array of strings into a list of decoded segments.
* @param encoded If the segments are encoded.
* @param segments String segments.
* @return The never {@code null} list of segments.
*/
public static PathSegments of(boolean encoded, String... segments) {
if (segments == null) {
return EMPTY;
}
return of(encoded, Arrays.asList(segments));
}
/**
* Extracts the path from an URI.
* @param uri URI.
* @return The never {@code null} list of segments.
*/
public static PathSegments segment(@Nullable URI uri) {
if (uri == null) {
return EMPTY;
}
return PathSegments.of(uri.getPath(), false);
}
/**
* Extracts the extension from a segment.
* @param segment Segment.
* @return The extension or {@code null} if no extension is found.
*/
public static String getSegmentExtension(String segment) {
if (segment == null) {
return null;
}
int li = segment.lastIndexOf('.');
if (li >= 0 && li < (segment.length() - 1)) {
return segment.substring(li + 1);
}
return null;
}
/**
* Removes the extension from a segment.
* @param segment Segment.
* @return The segment without the extension (and without the dot) or the same segment if no
* extension is found.
*/
public static String removeSegmentExtension(String segment) {
if (segment == null) {
return null;
}
int li = segment.lastIndexOf('.');
if (li >= 0 && li < (segment.length() - 1)) {
return segment.substring(0, li);
}
return segment;
}
/** Path segments. */
private final ImmutableList segments;
/** Constructor. */
private PathSegments(ImmutableList segments) {
this.segments = segments;
}
@Override
protected List delegate() {
return segments;
}
public PathSegments consume(int n) {
if (n == 0) {
return this;
}
return new PathSegments(segments.subList(n, segments.size()));
}
public PathSegments consumeLast(int n) {
if (n == 0) {
return this;
}
return new PathSegments(segments.subList(0, segments.size() - n));
}
public String head() {
return get(0);
}
public String last() {
return get(size() - 1);
}
public PathSegments consume() {
return consume(1);
}
public PathSegments consumeLast() {
return consumeLast(1);
}
/**
* Extracts the extension from the last segment.
* @return The extension or {@code null} if no extension is found or the object is empty.
*/
public String getExtension() {
if (isEmpty()) {
return null;
}
return getSegmentExtension(last());
}
/**
* Appends an extension to the last segment. If this object is empty no operation is performed.
* @param extension Extension to add. If {@code null} or only whitespace no operation is
* performed.
* @return The modified segments.
*/
public PathSegments appendExtension(@Nullable String extension) {
if (isEmpty() || extension == null) {
return this;
}
extension = CharMatcher.WHITESPACE.trimFrom(extension);
if (extension.isEmpty()) {
return this;
}
String last = new StringBuilder(last()).append('.').append(extension).toString();
if (size() == 1) {
return segment(last, false);
}
return PathSegments.of(false, Iterables.concat(consumeLast(), ImmutableList.of(last)));
}
/**
* Removes the extension from the last segment.
* @return The modified segments.
*/
public PathSegments removeExtension() {
if (isEmpty()) {
return this;
}
final String last = last();
final String removed = removeSegmentExtension(last);
if (last.equals(removed)) {
return this;
}
if (size() == 1) {
return segment(removed, false);
}
return new PathSegments(ImmutableList.copyOf(Iterables.concat(segments.subList(0, segments.size() - 1),
ImmutableList.of(removed))));
}
public String join() {
return Joiner.on("/").skipNulls().join(this);
}
/**
* Appends some segments after this list.
* @param other Segments to add.
* @return The resulting segments.
*/
public PathSegments append(@Nullable PathSegments other) {
if (other == null || other.isEmpty()) {
return this;
}
if (isEmpty()) {
return other;
}
return new PathSegments(ImmutableList.copyOf(Iterables.concat(segments, other.segments)));
}
/**
* Returns a new transformer that inserts this segments at the beginning of the provided path.
* @return The requested transformer.
*/
public Function inserter() {
if (isEmpty()) {
return Functions.identity();
}
return new Inserter();
}
/** Transformer. */
private abstract class Transformer implements Function {
@Override
public int hashCode() {
return getClass().hashCode();
}
final ImmutableList segments() {
return segments;
}
}
/** Inserter transformer. */
private class Inserter extends Transformer {
public PathSegments apply(PathSegments input) {
if (input == null || input.isEmpty()) {
return PathSegments.this;
}
return append(input);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Inserter) {
return segments.equals(((Inserter) obj).segments());
}
return false;
}
public String toString() {
return String.format("Inserter transformer: %s", segments);
}
}
/**
* Returns a new transformer that appends this segments to the provided path.
* @return The requested transformer.
*/
public Function appender() {
if (isEmpty()) {
return Functions.identity();
}
return new Appender();
}
/** Appender transformer. */
private class Appender extends Transformer {
public PathSegments apply(PathSegments input) {
if (input == null || input.isEmpty()) {
return PathSegments.this;
}
return input.append(PathSegments.this);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Appender) {
return segments.equals(((Appender) obj).segments());
}
return false;
}
public String toString() {
return String.format("Appender transformer: %s", segments);
}
}
@Override
public int hashCode() {
return segments.hashCode();
}
@Override
public boolean equals(Object object) {
if (object instanceof PathSegments) {
return Objects.equal(segments, ((PathSegments) object).segments);
}
return false;
}
@Override
public String toString() {
return String.format("[%d, %s]", size(), join());
}
}