com.google.firebase.database.core.Path Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of firebase-admin Show documentation
Show all versions of firebase-admin Show documentation
This is the official Firebase Admin Java SDK. Build extraordinary native JVM apps in
minutes with Firebase. The Firebase platform can power your app’s backend, user
authentication, static hosting, and more.
/*
* Copyright 2017 Google Inc.
*
* 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 com.google.firebase.database.core;
import com.google.firebase.database.DatabaseException;
import com.google.firebase.database.snapshot.ChildKey;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
public class Path implements Iterable, Comparable {
private static final Path EMPTY_PATH = new Path("");
private final ChildKey[] pieces;
private final int start;
private final int end;
public Path(ChildKey... segments) {
this.pieces = Arrays.copyOf(segments, segments.length);
this.start = 0;
this.end = segments.length;
for (ChildKey name : segments) {
assert name != null : "Can't construct a path with a null value!";
}
}
public Path(List segments) {
this.pieces = new ChildKey[segments.size()];
int i = 0;
for (String segment : segments) {
this.pieces[i++] = ChildKey.fromString(segment);
}
this.start = 0;
this.end = segments.size();
}
public Path(String pathString) {
String[] segments = pathString.split("/");
int count = 0;
for (String segment : segments) {
if (segment.length() > 0) {
count++;
}
}
pieces = new ChildKey[count];
int j = 0;
for (String segment : segments) {
if (segment.length() > 0) {
pieces[j++] = ChildKey.fromString(segment);
}
}
this.start = 0;
this.end = pieces.length;
}
private Path(ChildKey[] pieces, int start, int end) {
this.pieces = pieces;
this.start = start;
this.end = end;
}
public static Path getRelative(Path from, Path to) {
ChildKey outerFront = from.getFront();
ChildKey innerFront = to.getFront();
if (outerFront == null) {
return to;
} else if (outerFront.equals(innerFront)) {
return getRelative(from.popFront(), to.popFront());
} else {
throw new DatabaseException("INTERNAL ERROR: " + to + " is not contained in " + from);
}
}
public static Path getEmptyPath() {
return EMPTY_PATH;
}
public Path child(Path path) {
int newSize = this.size() + path.size();
ChildKey[] newPieces = new ChildKey[newSize];
System.arraycopy(this.pieces, this.start, newPieces, 0, this.size());
System.arraycopy(path.pieces, path.start, newPieces, this.size(), path.size());
return new Path(newPieces, 0, newSize);
}
public Path child(ChildKey child) {
int size = this.size();
ChildKey[] newPieces = new ChildKey[size + 1];
System.arraycopy(this.pieces, this.start, newPieces, 0, size);
newPieces[size] = child;
return new Path(newPieces, 0, size + 1);
}
@Override
public String toString() {
if (this.isEmpty()) {
return "/";
} else {
StringBuilder builder = new StringBuilder();
for (int i = this.start; i < this.end; i++) {
builder.append("/");
builder.append(pieces[i].asString());
}
return builder.toString();
}
}
public String wireFormat() {
if (this.isEmpty()) {
return "/";
} else {
StringBuilder builder = new StringBuilder();
for (int i = this.start; i < this.end; i++) {
if (i > this.start) {
builder.append("/");
}
builder.append(pieces[i].asString());
}
return builder.toString();
}
}
public List asList() {
List result = new ArrayList<>(this.size());
for (ChildKey key : this) {
result.add(key.asString());
}
return result;
}
public ChildKey getFront() {
if (this.isEmpty()) {
return null;
} else {
return pieces[this.start];
}
}
public Path popFront() {
int newStart = this.start;
if (!this.isEmpty()) {
newStart++;
}
return new Path(pieces, newStart, this.end);
}
public Path getParent() {
if (this.isEmpty()) {
return null;
} else {
return new Path(pieces, start, end - 1);
}
}
public ChildKey getBack() {
if (!this.isEmpty()) {
return pieces[end - 1];
} else {
return null;
}
}
public boolean isEmpty() {
return start >= end;
}
public int size() {
return this.end - this.start;
}
@Override
public Iterator iterator() {
return new Iterator() {
int offset = start;
@Override
public boolean hasNext() {
return offset < end;
}
@Override
public ChildKey next() {
if (!hasNext()) {
throw new NoSuchElementException("No more elements.");
}
ChildKey child = pieces[offset];
offset++;
return child;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Can't remove component from immutable Path!");
}
};
}
public boolean contains(Path other) {
if (this.size() > other.size()) {
return false;
}
int i = this.start;
int j = other.start;
while (i < this.end) {
if (!this.pieces[i].equals(other.pieces[j])) {
return false;
}
i++;
j++;
}
return true;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof Path)) {
return false;
}
if (this == other) {
return true;
}
Path otherPath = (Path) other;
if (size() != otherPath.size()) {
return false;
}
for (int i = start, j = otherPath.start; i < end && j < otherPath.end; i++, j++) {
if (!this.pieces[i].equals(otherPath.pieces[j])) {
return false;
}
}
return true;
}
@Override
public int hashCode() {
int hashCode = 0;
for (int i = start; i < end; i++) {
hashCode = hashCode * 37 + pieces[i].hashCode();
}
return hashCode;
}
@Override
public int compareTo(Path other) {
int i;
int j;
for (i = start, j = other.start; i < end && j < other.end; i++, j++) {
int comp = this.pieces[i].compareTo(other.pieces[j]);
if (comp != 0) {
return comp;
}
}
if (i == end && j == other.end) {
return 0;
} else if (i == end) {
return -1;
} else {
return 1;
}
}
}