cdc.applic.expressions.literals.Name Maven / Gradle / Ivy
Show all versions of cdc-applic-expressions Show documentation
package cdc.applic.expressions.literals;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import cdc.util.lang.Checks;
public final class Name implements Comparable {
private final SName prefix;
private final SName local;
/**
* The prefix / local separator.
*/
public static final char SEP = '.';
/**
* Creates a Name from a prefix and a local name.
*
* @param prefix The optional prefix (possibly {@code null}).
* @param local The local name.
*/
private Name(SName prefix,
SName local) {
this.prefix = prefix;
this.local = Checks.isNotNull(local, "local");
}
/**
* Creates a name from a string.
*
* {@code text} is analyzed to see if it is a prefixed name or a local name.
*
* @param text The string.
*/
private Name(String text) {
final char[] chars = text.toCharArray();
final int sep = EscapingUtils.getPathSeparatorIndex(chars, 0);
if (sep < 0) {
this.prefix = null;
this.local = new SName(text, EscapingUtils.isProbablyDoubleQuotesEscaped(text));
} else {
final String p = text.substring(0, sep);
this.prefix = new SName(p, EscapingUtils.isProbablyDoubleQuotesEscaped(p));
final String l = text.substring(sep + 1);
this.local = new SName(l, EscapingUtils.isProbablyDoubleQuotesEscaped(l));
}
}
/**
* Creates a Name from an optional prefix and a local name.
*
* @param prefix The prefix.
* @param local The name.
* @return A new Name.
*/
public static Name of(SName prefix,
SName local) {
return new Name(prefix, local);
}
public static Name of(Optional prefix,
SName local) {
return of(prefix.orElse(null), local);
}
/**
* Creates a Name without prefix from a local name.
*
* @param local The name.
* @return A new Name.
*/
public static Name of(SName local) {
return of((SName) null, local);
}
/**
* Creates a name from a text.
*
* {@code text} is analyzed to see if it is a prefixed name or a local name.
*
* @param text The text.
* @return A new Name or {@code null} if {@code text} is {@code null}.
*/
public static Name of(String text) {
return text == null ? null : new Name(text);
}
public static Name of(String text,
boolean escaped) {
return text == null ? null : of(SName.of(text, escaped));
}
/**
* @return The optional prefix.
*/
public SName getPrefix() {
return prefix;
}
/**
* @return {@code true} if this name has a prefix.
*/
public boolean hasPrefix() {
return prefix != null;
}
/**
* @return The local part of this name.
*/
public SName getLocal() {
return local;
}
/**
* @return A Name that has the same local name and no prefix.
*/
public Name removePrefix() {
if (prefix == null) {
return this;
} else {
return new Name(null, local);
}
}
/**
* Returns this name with prefix removed if it matches a particular prefix.
*
* @param prefix The prefix to remove.
* @return This name with its prefix removed if it equals {@code prefix}, or this name unchanged.
*/
public Name removePrefix(SName prefix) {
if (Objects.equals(prefix, this.prefix)) {
return removePrefix();
} else {
return this;
}
}
public Name removePrefix(Optional prefix) {
return removePrefix(prefix.orElse(null));
}
/**
* @param prefix The new prefix.
* @return This name with its prefix set to {@code prefix}.
*/
public Name setPrefix(SName prefix) {
return new Name(prefix, this.local);
}
public Name setPrefix(Optional prefix) {
return new Name(prefix.orElse(null), this.local);
}
/**
* @param prefix The possibly new prefix.
* @return This name with its prefix set to {@code prefix} if it does
* not have any prefix, or this name unchanged.
*/
public Name setPrefixIfMissing(SName prefix) {
return hasPrefix() ? this : setPrefix(prefix);
}
public String getNonEscapedLiteral() {
return getLiteral(EscapingMode.NON_ESCAPED);
}
public String getProtectedLiteral() {
return getLiteral(EscapingMode.PROTECTED);
}
/**
* Returns a string representation of this name using different modes.
*
* If this name has no prefix, then result may be unescaped.
* Otherwise, it is either escaped or protected.
*
* For example, it would not be legal to generate {@code "A B.C D"}.
*
* @param mode The mode.
* @return The string representation of this name, according to {@code mode}.
*/
public String getLiteral(EscapingMode mode) {
if (hasPrefix()) {
final StringBuilder builder = new StringBuilder();
if (mode == EscapingMode.ESCAPED) {
builder.append(prefix.getEscapedLiteral());
builder.append(SEP);
builder.append(local.getEscapedLiteral());
} else {
builder.append(prefix.getProtectedLiteral());
builder.append(SEP);
builder.append(local.getProtectedLiteral());
}
return builder.toString();
} else {
return local.getLiteral(mode);
}
}
public String getSortingLiteral() {
return getNonEscapedLiteral();
}
@Override
public int compareTo(Name other) {
final int prefixCmp = SName.COMPARATOR.compare(prefix, other.prefix);
if (prefixCmp == 0) {
return local.compareTo(other.local);
} else {
return prefixCmp;
}
}
@Override
public int hashCode() {
return Objects.hash(prefix,
local);
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (!(object instanceof Name)) {
return false;
}
final Name other = (Name) object;
return Objects.equals(prefix, other.prefix)
&& Objects.equals(local, other.local);
}
@Override
public String toString() {
return getProtectedLiteral();
}
public static List toNames(String... names) {
final List list = new ArrayList<>();
for (final String name : names) {
list.add(Name.of(name));
}
return list;
}
}