dev.orne.beans.AbstractComposedIdentity Maven / Gradle / Ivy
package dev.orne.beans;
/*-
* #%L
* Orne Beans
* %%
* Copyright (C) 2023 Orne Developments
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import javax.validation.constraints.NotNull;
import org.apache.commons.lang3.StringUtils;
/**
* Abstract implementation for {@code Identity} for identities composed
* of a multiple inner values.
*
* @author (w) Iker Hernaez
* @version 1.0, 2023-05
* @since 0.5
*/
public abstract class AbstractComposedIdentity
extends AbstractIdentity {
/** The serial version UID. */
private static final long serialVersionUID = 1L;
/** Default identity token body parts separator. */
public static final String DEFAULT_SEPARATOR = ",";
/** The default placeholder for null identity token parts. */
public static final String DEFAULT_NULL_PLACEHOLDER = "\0";
/**
* {@inheritDoc}
*/
@Override
protected String getIdentityTokenBody() {
final String[] parts = getIdentityTokenBodyParts();
if (parts == null) {
return null;
}
final String placeholder = getIdentityTokenBodyPartsNullPlaceholder();
for (int i = 0; i < parts.length; i++) {
if (parts[i] == null) {
parts[i] = placeholder;
}
}
return StringUtils.join(
parts,
getIdentityTokenBodyPartsSeparator());
}
/**
* Returns the identity token body composed from the values of this
* identity. Equal instances must return equal identity token body.
*
* @return The identity token body for this instance
*/
protected abstract String[] getIdentityTokenBodyParts();
/**
* Return the identity token body parts separator.
* Must return same value for instances of the same class.
*
* @return The identity token body parts separator.
*/
protected @NotNull String getIdentityTokenBodyPartsSeparator() {
return DEFAULT_SEPARATOR;
}
/**
* Return the placeholder for null identity token parts.
* Must return same value for instances of the same class.
*
* @return The placeholder for null identity token parts.
*/
protected @NotNull String getIdentityTokenBodyPartsNullPlaceholder() {
return DEFAULT_NULL_PLACEHOLDER;
}
/**
* Extracts the {@code String} value of a token generated by
* {@code StringIdentity}.
*
* @param prefix The expected identity token prefix.
* @param token The identity token.
* @return The extracted identity token body parts.
* @throws NullPointerException If any argument is {@code null}
* @throws UnrecognizedIdentityTokenException If the identity token is not
* a valid simple identity token or if it doesn't start with the expected
* prefix.
* @see #extractTokenBodyParts(String, String, String, String)
*/
public static String[] extractTokenBodyParts(
final @NotNull String prefix,
final @NotNull String token) {
return extractTokenBodyParts(prefix, token, DEFAULT_SEPARATOR);
}
/**
* Extracts the {@code String} value of a token generated by
* {@code StringIdentity}.
*
* @param prefix The expected identity token prefix.
* @param token The identity token.
* @param separator The identity token body parts separator.
* @return The extracted identity token body parts.
* @throws NullPointerException If any argument is {@code null}
* @throws UnrecognizedIdentityTokenException If the identity token is not
* a valid simple identity token or if it doesn't start with the expected
* prefix.
* @see #extractTokenBodyParts(String, String, String, String)
*/
public static String[] extractTokenBodyParts(
final @NotNull String prefix,
final @NotNull String token,
final @NotNull String separator) {
return extractTokenBodyParts(prefix, token, separator, DEFAULT_NULL_PLACEHOLDER);
}
/**
* Extracts the {@code String} value of a token generated by
* {@code StringIdentity}.
*
* @param prefix The expected identity token prefix.
* @param token The identity token.
* @param separator The identity token body parts separator.
* @param placeholder The {@code null} identity token body part placeholder.
* @return The extracted identity token body parts.
* @throws NullPointerException If any argument is {@code null}
* @throws UnrecognizedIdentityTokenException If the identity token is not
* a valid simple identity token or if it doesn't start with the expected
* prefix.
*/
public static String[] extractTokenBodyParts(
final @NotNull String prefix,
final @NotNull String token,
final @NotNull String separator,
final @NotNull String placeholder) {
final String body = IdentityTokenFormatter.parse(prefix, token);
final String[] result;
if (body == null) {
result = null;
} else {
result = body.split(separator);
for (int i = 0; i < result.length; i++) {
if (placeholder.equals(result[i])) {
result[i] = null;
}
}
}
return result;
}
/**
* Extracts the body parts of a token generated by
* {@code AbstractComposedIdentity}.
*
* If the resulting value is {@code null} or the body parts count is not
* the expected one an exception is thrown.
*
* @param prefix The expected identity token prefix.
* @param token The identity token.
* @param expectedParts The expected identity token body parts count.
* @return The extracted identity token body parts.
* @throws NullPointerException If any argument is {@code null}
* @throws UnrecognizedIdentityTokenException If the identity token is not
* a valid identity token, if it doesn't start with the expected prefix,
* if the extracted body is null or the extracted body parts count does not
* match the expected parts count.
* @see #extractTokenBodyParts(String, String)
*/
public static @NotNull String[] extractRequiredTokenBodyParts(
final @NotNull String prefix,
final @NotNull String token,
final int expectedParts) {
final String[] result = extractTokenBodyParts(prefix, token);
validateTokenBodyParts(token, result, expectedParts);
return result;
}
/**
* Extracts the body parts of a token generated by
* {@code AbstractComposedIdentity}.
*
* If the resulting value is {@code null} or the body parts count is not
* the expected one an exception is thrown.
*
* @param prefix The expected identity token prefix.
* @param token The identity token.
* @param separator The identity token body parts separator.
* @param expectedParts The expected identity token body parts count.
* @return The extracted identity token body parts.
* @throws NullPointerException If any argument is {@code null}
* @throws UnrecognizedIdentityTokenException If the identity token is not
* a valid identity token, if it doesn't start with the expected prefix,
* if the extracted body is null or the extracted body parts count does not
* match the expected parts count.
* @see #extractTokenBodyParts(String, String, String)
*/
public static @NotNull String[] extractRequiredTokenBodyParts(
final @NotNull String prefix,
final @NotNull String token,
final @NotNull String separator,
final int expectedParts) {
final String[] result = extractTokenBodyParts(prefix, token, separator);
validateTokenBodyParts(token, result, expectedParts);
return result;
}
/**
* Extracts the body parts of a token generated by
* {@code AbstractComposedIdentity}.
*
* If the resulting value is {@code null} or the body parts count is not
* the expected one an exception is thrown.
*
* @param prefix The expected identity token prefix.
* @param token The identity token.
* @param separator The identity token body parts separator.
* @param placeholder The {@code null} identity token body part placeholder.
* @param expectedParts The expected identity token body parts count.
* @return The extracted identity token body parts.
* @throws NullPointerException If any argument is {@code null}
* @throws UnrecognizedIdentityTokenException If the identity token is not
* a valid identity token, if it doesn't start with the expected prefix,
* if the extracted body is null or the extracted body parts count does not
* match the expected parts count.
* @see #extractTokenBodyParts(String, String, String)
*/
public static @NotNull String[] extractRequiredTokenBodyParts(
final @NotNull String prefix,
final @NotNull String token,
final @NotNull String separator,
final @NotNull String placeholder,
final int expectedParts) {
final String[] result = extractTokenBodyParts(prefix, token, separator);
validateTokenBodyParts(token, result, expectedParts);
return result;
}
/**
* Validates that the specified identity token body parts is not null and
* has the expected number of parts.
*
* @param token The identity token.
* @param parts The extracted identity token body parts.
* @param expectedParts The expected identity token body parts count.
* @throws UnrecognizedIdentityTokenException If the extracted body is
* {@code null} or the extracted body parts count does not match the
* expected parts count.
*/
private static void validateTokenBodyParts(
final @NotNull String token,
final String[] parts,
final int expectedParts) {
if (parts == null || parts.length != expectedParts) {
throw new UnrecognizedIdentityTokenException(
"Unrecognized identity token: " + token);
}
}
}