swim.uri.UriPathMapping Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of swim-uri Show documentation
Show all versions of swim-uri Show documentation
Uploads all artifacts belonging to configuration ':swim-uri:archives'
// Copyright 2015-2019 SWIM.AI 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 swim.uri;
import java.util.Iterator;
import java.util.Map;
import swim.collections.HashTrieMap;
import swim.util.Murmur3;
final class UriPathMapping extends UriPathMapper {
final HashTrieMap> table;
final UriPathMapper wildcard;
final UriQueryMapper terminal;
UriPathMapping(HashTrieMap> table, UriPathMapper wildcard, UriQueryMapper terminal) {
this.table = table;
this.wildcard = wildcard;
this.terminal = terminal;
}
@Override
public boolean isEmpty() {
return this.table.isEmpty() && this.wildcard.isEmpty() && this.terminal.isEmpty();
}
@Override
public int size() {
int size = 0;
final Iterator> routes = this.table.valueIterator();
while (routes.hasNext()) {
size += routes.next().size();
}
size += this.wildcard.size();
size += this.terminal.size();
return size;
}
@Override
public boolean containsValue(Object value) {
final Iterator> routes = this.table.valueIterator();
while (routes.hasNext()) {
if (routes.next().containsValue(value)) {
return true;
}
}
return this.wildcard.containsValue(value) || this.terminal.containsValue(value);
}
@Override
T get(UriPath path, UriQuery query, UriFragment fragment) {
if (!path.isEmpty()) {
UriPathMapper mapping = this.table.get(path.head());
if (mapping == null) {
mapping = this.wildcard;
}
return mapping.get(path.tail(), query, fragment);
} else {
return this.terminal.get(query, fragment);
}
}
UriPathMapping merged(UriPathMapping that) {
HashTrieMap> table = this.table;
final Iterator>> routes = that.table.iterator();
while (routes.hasNext()) {
final Map.Entry> route = routes.next();
final String segment = route.getKey();
UriPathMapper mapping = this.table.get(segment);
if (mapping != null) {
mapping = mapping.merged(route.getValue());
} else {
mapping = route.getValue();
}
table = table.updated(segment, mapping);
}
final UriPathMapper wildcard = this.wildcard.merged(that.wildcard);
final UriQueryMapper terminal = this.terminal.merged(that.terminal);
return new UriPathMapping(table, wildcard, terminal);
}
@Override
UriPathMapper merged(UriPathMapper that) {
if (that instanceof UriPathMapping>) {
return merged((UriPathMapping) that);
} else {
return that;
}
}
@SuppressWarnings("unchecked")
@Override
UriPathMapper removed(UriPath path, UriQuery query, UriFragment fragment) {
if (!path.isEmpty()) {
final String segment = path.head();
if (!segment.isEmpty() && segment.charAt(0) == ':') {
final UriPathMapper oldWildcard = this.wildcard;
if (oldWildcard != null) {
final UriPathMapper newWildcard = oldWildcard.removed(path.tail(), query, fragment);
if (oldWildcard != newWildcard) {
if (!this.table.isEmpty() || !newWildcard.isEmpty() || !this.terminal.isEmpty()) {
return new UriPathMapping(this.table, newWildcard, this.terminal);
} else {
return (UriPathMapper) empty();
}
}
}
} else {
final HashTrieMap> oldTable = this.table;
final UriPathMapper oldMapping = oldTable.get(segment);
if (oldMapping != null) {
final UriPathMapper newMapping = oldMapping.removed(path.tail(), query, fragment);
if (oldMapping != newMapping) {
final HashTrieMap> newTable;
if (!newMapping.isEmpty()) {
newTable = oldTable.updated(segment, newMapping);
} else {
newTable = oldTable.removed(segment);
}
if (!newTable.isEmpty() || !this.wildcard.isEmpty() || !this.terminal.isEmpty()) {
return new UriPathMapping(newTable, this.wildcard, this.terminal);
} else {
return (UriPathMapper) empty();
}
}
}
}
} else {
final UriQueryMapper oldTerminal = terminal;
if (oldTerminal != null) {
final UriQueryMapper newTerminal = oldTerminal.removed(query, fragment);
if (oldTerminal != newTerminal) {
if (!this.table.isEmpty() || !this.wildcard.isEmpty() || !newTerminal.isEmpty()) {
return new UriPathMapping(this.table, this.wildcard, newTerminal);
} else {
return (UriPathMapper) empty();
}
}
}
}
return this;
}
@SuppressWarnings("unchecked")
UriPathMapper unmerged(UriPathMapping that) {
HashTrieMap> table = this.table;
final Iterator>> routes = that.table.iterator();
while (routes.hasNext()) {
final Map.Entry> route = routes.next();
final String segment = route.getKey();
UriPathMapper mapping = this.table.get(segment);
if (mapping != null) {
mapping = mapping.unmerged(route.getValue());
if (!mapping.isEmpty()) {
table = table.updated(segment, mapping);
} else {
table = table.removed(segment);
}
}
}
final UriPathMapper wildcard = this.wildcard.unmerged(that.wildcard);
final UriQueryMapper terminal = this.terminal.unmerged(that.terminal);
if (!table.isEmpty() || !wildcard.isEmpty() || !terminal.isEmpty()) {
return new UriPathMapping(table, wildcard, terminal);
} else {
return (UriPathMapper) empty();
}
}
@Override
UriPathMapper unmerged(UriPathMapper that) {
if (that instanceof UriPathMapping>) {
return unmerged((UriPathMapping) that);
} else {
return this;
}
}
@Override
public Iterator> iterator() {
final Iterator> tableIterator = new UriPathMappingEntryIterator(this.table.valueIterator());
return new UriPathMappingIterator>(tableIterator, this.wildcard.iterator(), this.terminal.iterator());
}
@Override
public Iterator keyIterator() {
final Iterator tableIterator = new UriPathMappingKeyIterator(this.table.valueIterator());
return new UriPathMappingIterator(tableIterator, this.wildcard.keyIterator(), this.terminal.keyIterator());
}
@Override
public Iterator valueIterator() {
final Iterator tableIterator = new UriPathMappingValueIterator(this.table.valueIterator());
return new UriPathMappingIterator(tableIterator, this.wildcard.valueIterator(), this.terminal.valueIterator());
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
} else if (other instanceof UriPathMapping>) {
final UriPathMapping> that = (UriPathMapping>) other;
return this.table.equals(that.table) && this.wildcard.equals(that.wildcard)
&& this.terminal.equals(that.terminal);
}
return false;
}
@Override
public int hashCode() {
if (hashSeed == 0) {
hashSeed = Murmur3.seed(UriPathMapping.class);
}
return Murmur3.mash(Murmur3.mix(Murmur3.mix(Murmur3.mix(hashSeed,
this.table.hashCode()), this.wildcard.hashCode()), terminal.hashCode()));
}
private static int hashSeed;
}
final class UriPathMappingIterator implements Iterator {
final Iterator tableIterator;
final Iterator wildcardIterator;
final Iterator terminalIterator;
UriPathMappingIterator(Iterator tableIterator, Iterator wildcardIterator, Iterator terminalIterator) {
this.tableIterator = tableIterator;
this.wildcardIterator = wildcardIterator;
this.terminalIterator = terminalIterator;
}
@Override
public boolean hasNext() {
return this.tableIterator.hasNext() || this.wildcardIterator.hasNext() || this.terminalIterator.hasNext();
}
@Override
public T next() {
if (this.tableIterator.hasNext()) {
return this.tableIterator.next();
} else if (this.wildcardIterator.hasNext()) {
return this.wildcardIterator.next();
} else {
return this.terminalIterator.next();
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
final class UriPathMappingEntryIterator extends FlatteningIterator, Map.Entry> {
UriPathMappingEntryIterator(Iterator> outer) {
super(outer);
}
@Override
protected Iterator> childIterator(UriPathMapper parent) {
return parent.iterator();
}
}
final class UriPathMappingKeyIterator extends FlatteningIterator, Uri> {
UriPathMappingKeyIterator(Iterator> outer) {
super(outer);
}
@Override
protected Iterator childIterator(UriPathMapper parent) {
return parent.keyIterator();
}
}
final class UriPathMappingValueIterator extends FlatteningIterator, T> {
UriPathMappingValueIterator(Iterator> outer) {
super(outer);
}
@Override
protected Iterator childIterator(UriPathMapper parent) {
return parent.valueIterator();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy