in api/applib/src/main/java/org/apache/causeway/applib/services/bookmark/Bookmark.java [44:233]
public record Bookmark(
@NonNull String logicalTypeName,
@Nullable String identifier,
@Nullable String hintId,
int precalculatedHashCode) implements Oid {
// -- FACTORIES
public static Bookmark empty(
final @NonNull LogicalType logicalType) {
return emptyForLogicalTypeName(logicalType.logicalName());
}
public static Bookmark emptyForLogicalTypeName(
final @NonNull String logicalTypeName) {
return new Bookmark(
logicalTypeName,
/*identifier*/null,
/*hintId*/null);
}
public static Bookmark forLogicalTypeNameAndIdentifier(
final @NonNull String logicalTypeName,
final @NonNull String urlSafeIdentifier) {
return new Bookmark(
logicalTypeName,
urlSafeIdentifier,
/*hintId*/null);
}
public static Bookmark forLogicalTypeAndIdentifier(
final @NonNull LogicalType logicalType,
final @NonNull String urlSafeIdentifier) {
return Bookmark.forLogicalTypeNameAndIdentifier(
logicalType.logicalName(),
urlSafeIdentifier);
}
public static Bookmark forOidDto(final @NonNull OidDto oidDto) {
return Bookmark.forLogicalTypeNameAndIdentifier(
oidDto.getType(),
oidDto.getId());
}
// -- CONSTRUCTOR
private Bookmark(
final String logicalTypeName,
final String urlSafeIdentifier,
final String hintId) {
this(logicalTypeName, urlSafeIdentifier, hintId, Objects.hash(logicalTypeName, urlSafeIdentifier));
}
// -- WITHERS
public Bookmark withHintId(final @Nullable String hintId) {
return new Bookmark(this.logicalTypeName(), this.identifier(), hintId);
}
// -- PARSE
/**
* Round-trip with {@link #stringify()} representation.
*/
public static Optional<Bookmark> parse(final @Nullable String str) {
if(_Strings.isNullOrEmpty(str)) return Optional.empty();
var tokenizer = new StringTokenizer(str, SEPARATOR);
int tokenCount = tokenizer.countTokens();
if(tokenCount==1) {
return str.endsWith(SEPARATOR)
|| str.startsWith(SEPARATOR)
? Optional.empty() // invalid
: Optional.of(Bookmark.emptyForLogicalTypeName(
tokenizer.nextToken()));
}
if(tokenCount==2) {
return Optional.of(Bookmark.forLogicalTypeNameAndIdentifier(
tokenizer.nextToken(),
tokenizer.nextToken()));
}
if(tokenCount>2) {
return Optional.of(Bookmark.forLogicalTypeNameAndIdentifier(
tokenizer.nextToken(),
tokenizer.nextToken("").substring(1)));
}
return Optional.empty();
}
public static Bookmark parseElseFail(final @Nullable String input) {
return parse(input)
.orElseThrow(()->_Exceptions.illegalArgument("cannot parse Bookmark '%s'", input));
}
/**
* there is only one use-case, that is, if a bookmark itself needs to be encoded (eg. page params)
*/
public static Optional<Bookmark> parseUrlEncoded(final @Nullable String urlEncodedStr) {
return _Strings.isEmpty(urlEncodedStr)
? Optional.empty()
: parse(UrlUtils.urlDecodeUtf8(urlEncodedStr));
}
// -- TO DTO
public OidDto toOidDto() {
var oidDto = new OidDto();
oidDto.setType(logicalTypeName());
oidDto.setId(identifier());
return oidDto;
}
// -- STRINGIFY
@Override
public String stringify() {
return stringify(identifier);
}
// -- OBJECT CONTRACT // not considering any hintId
@Override
public boolean equals(final Object other) {
if (other == null) {
return false;
}
if (other == this) {
return true;
}
if (getClass() != other.getClass()) {
return false;
}
return equals((Bookmark) other);
}
public boolean equals(final Bookmark other) {
return Objects.equals(logicalTypeName, other.logicalTypeName())
&& Objects.equals(identifier, other.identifier());
}
@Override
public int hashCode() {
return precalculatedHashCode;
}
@Override
public String toString() {
return stringify();
}
/**
* Analogous to {@link #stringify()}, but replaces the {@code identifier} string with
* the {@code hintId} if present and not empty.
*/
public String stringifyHonoringHintIfAny() {
return _Strings.isNotEmpty(hintId)
? stringify(hintId)
: stringify(identifier);
}
/**
* Whether represents {@code null}.
*/
public boolean isEmpty() {
return identifier==null;
}
// -- UTILITY
public static class JaxbToStringAdapter extends XmlAdapter<String, Bookmark> {
@Override
public Bookmark unmarshal(final String literal) {
return Bookmark.parse(literal).orElse(null);
}
@Override
public String marshal(final Bookmark bookmark) {
return bookmark != null ? bookmark.stringify() : null;
}
}
// -- HELPER
private String stringify(final String id) {
return !isEmpty()
? logicalTypeName + SEPARATOR + id
: logicalTypeName;
}
}