org.wildfly.naming.client.SimpleName Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source.
* Copyright 2017 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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.wildfly.naming.client;
import static java.lang.Integer.signum;
import static java.lang.Math.min;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import javax.naming.CompoundName;
import javax.naming.InvalidNameException;
import javax.naming.Name;
import org.wildfly.common.Assert;
import org.wildfly.naming.client._private.Messages;
/**
* A simple compound name which uses left-to-right parsing, {@code /} separators, and simple quoting rules. This class
* is designed to perform better and have lower overhead than {@link CompoundName}.
*
* @author David M. Lloyd
*/
public class SimpleName implements Name, Serializable {
private static final long serialVersionUID = - 91630190623885257L;
private final ArrayList segments;
public SimpleName() {
segments = new ArrayList<>();
}
public SimpleName(String name) throws InvalidNameException {
this(parse(name));
}
public SimpleName(final Collection segments) {
this(new ArrayList<>(segments));
}
public SimpleName(final Name name) {
this(name.getAll());
}
private SimpleName(final ArrayList literalSegments) {
for (int i = 0; i < literalSegments.size(); i++) {
if (literalSegments.get(i) == null) {
throw Messages.log.invalidNullSegment(i);
}
}
this.segments = literalSegments;
}
public SimpleName(final Enumeration enumeration) {
this();
if (enumeration.hasMoreElements()) {
final ArrayList segments = this.segments;
int idx = 0;
String item;
do {
item = enumeration.nextElement();
if (item == null) {
throw Messages.log.invalidNullSegment(idx);
}
segments.add(item);
idx ++;
} while (enumeration.hasMoreElements());
}
}
private static ArrayList parse(String name) throws InvalidNameException {
final ArrayList segments = new ArrayList<>();
final int length = name.length();
final StringBuilder b = new StringBuilder();
int ch = -1;
boolean q = false, e = false, sq = false;
for (int i = 0; i < length; i = name.offsetByCodePoints(i, 1)) {
ch = name.codePointAt(i);
if (e) {
e = false;
b.appendCodePoint(ch);
} else if (q) {
if (sq && ch == '\'') {
q = false;
} else if (! sq && ch == '"') {
q = false;
} else if (ch == '\\') {
e = true;
} else {
b.appendCodePoint(ch);
}
} else if (ch == '/') {
segments.add(b.toString());
b.setLength(0);
} else if (ch == '"') {
q = true;
sq = false;
} else if (ch == '\'') {
q = true;
sq = true;
} else if (ch == '\\') {
e = true;
} else {
b.appendCodePoint(ch);
}
}
if (b.length() > 0 || ch == '/') {
segments.add(b.toString());
}
if (q) {
throw Messages.log.missingCloseQuote(sq ? '\'' : '"', name);
} else if (e) {
throw Messages.log.missingEscape(name);
}
return segments;
}
public int compareTo(final Object obj) {
return compareTo((SimpleName) obj);
}
public int compareTo(final SimpleName simpleName) {
int result;
final ArrayList segments = this.segments;
final ArrayList theirSegments = simpleName.segments;
final int theirSize = theirSegments.size();
final int ourSize = segments.size();
for (int i = 0; i < min(ourSize, theirSize); i ++) {
result = segments.get(i).compareTo(theirSegments.get(i));
if (result != 0) {
return result;
}
}
return signum(ourSize - theirSize);
}
public boolean equals(final Object obj) {
return obj != null && obj.getClass() == getClass() && equals((SimpleName) obj);
}
public boolean equals(final SimpleName simpleName) {
return simpleName != null && simpleName.getClass() == getClass() && segments.equals(simpleName.segments);
}
public int hashCode() {
return segments.hashCode();
}
public int size() {
return segments.size();
}
public boolean isEmpty() {
return segments.isEmpty();
}
public Enumeration getAll() {
return Collections.enumeration(segments);
}
public String toString() {
final Iterator iterator = segments.iterator();
if (iterator.hasNext()) {
StringBuilder b = new StringBuilder();
appendSegment(b, iterator.next());
while (iterator.hasNext()) {
b.append('/');
appendSegment(b, iterator.next());
}
return b.toString();
} else {
return "";
}
}
private static void appendSegment(final StringBuilder b, final String segment) {
int cp;
for (int i = 0; i < segment.length(); i = segment.offsetByCodePoints(i, 1)) {
cp = segment.codePointAt(i);
if (cp == '/' || cp == '\'' || cp == '"') {
b.append('\\');
}
b.appendCodePoint(cp);
}
}
public String get(final int pos) {
final ArrayList segments = this.segments;
if (pos < 0 || pos >= segments.size()) {
throw Messages.log.nameIndexOutOfBounds(pos);
}
return segments.get(pos);
}
public Collection getRange(final int start, final int end) {
return segments.subList(start, end);
}
public SimpleName getPrefix(final int pos) {
return new SimpleName(getRange(0, pos));
}
public SimpleName getSuffix(final int pos) {
return new SimpleName(getRange(pos, size()));
}
public boolean startsWith(final Name name) {
final ArrayList segments = this.segments;
final int size = name.size();
if (size > segments.size()) {
return false;
}
for (int i = 0; i < size; i ++) {
if (! segments.get(i).equals(name.get(i))) {
return false;
}
}
return true;
}
public boolean endsWith(final Name name) {
final ArrayList segments = this.segments;
final int size = name.size();
final int ourSize = segments.size();
if (size > ourSize) {
return false;
}
final int offs = ourSize - size;
for (int i = 0; i < size; i ++) {
if (! segments.get(i + offs).equals(name.get(i))) {
return false;
}
}
return true;
}
public SimpleName addAll(final Name suffix) {
if (suffix instanceof SimpleName) {
segments.addAll(((SimpleName) suffix).segments);
return this;
}
final ArrayList segments = this.segments;
final int size = suffix.size();
final int ourSize = segments.size();
segments.ensureCapacity(ourSize + size);
for (int i = 0; i < size; i ++) {
add(suffix.get(i));
}
return this;
}
public SimpleName addAll(final int pos, final Name name) {
if (name instanceof SimpleName) {
segments.addAll(pos, ((SimpleName) name).segments);
return this;
}
final ArrayList segments = this.segments;
final int size = name.size();
final int ourSize = segments.size();
segments.ensureCapacity(ourSize + size);
for (int i = 0; i < size; i ++) {
add(pos + i, name.get(i));
}
return this;
}
public SimpleName add(final String comp) {
Assert.checkNotNullParam("comp", comp);
segments.add(comp);
return this;
}
public SimpleName add(final int pos, final String comp) {
Assert.checkNotNullParam("comp", comp);
segments.add(pos, comp);
return this;
}
public String remove(final int pos) {
return segments.remove(pos);
}
public SimpleName clone() {
return new SimpleName((Collection) segments);
}
public static SimpleName of(final Name name) {
if (name instanceof SimpleName) {
return (SimpleName) name;
}
return new SimpleName(name);
}
}