Skip to content

Commit

Permalink
feat: context builder
Browse files Browse the repository at this point in the history
  • Loading branch information
qixils committed Dec 22, 2023
1 parent 91befc3 commit 1ade314
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 223 deletions.
287 changes: 139 additions & 148 deletions src/main/java/dev/qixils/quasicord/locale/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

package dev.qixils.quasicord.locale;

import dev.qixils.quasicord.locale.impl.ImmutableContextImpl;
import dev.qixils.quasicord.locale.impl.MutableContextImpl;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
Expand All @@ -26,7 +24,6 @@
* Stores information about the author and location of a message to determine the {@link Locale}
* to use for localizing response messages.
*/
// TODO: the interface should not be pseudo-mutable... it should be immutable with a mutable builder.
public interface Context {

/**
Expand All @@ -39,13 +36,6 @@ public interface Context {
return localeProvider.forContext(this);
}

/**
* Determines if this context is mutable.
*
* @return true if this context is mutable
*/
boolean isMutable();

// getters

/**
Expand Down Expand Up @@ -83,149 +73,24 @@ public interface Context {
*/
@Nullable DiscordLocale guildLocale();

// user setter

/**
* Sets the user ID of this context.
*
* @param user the user ID
* @return this context
* @throws UnsupportedOperationException if this context is immutable
*/
@NonNull Context user(long user);

/**
* Sets the user ID of this context.
*
* @param user the user
* @return this context
* @throws UnsupportedOperationException if this context is immutable
*/
default @NonNull Context user(@NonNull User user) {
return user(Objects.requireNonNull(user, "user").getIdLong());
}

/**
* Sets the user ID of this context.
*
* @param member the member
* @return this context
* @throws UnsupportedOperationException if this context is immutable
*/
default @NonNull Context user(@NonNull Member member) {
return user(Objects.requireNonNull(member, "member").getIdLong());
}

// user locale setter

/**
* Sets the user locale of this context.
*
* @param locale the locale
* @return this context
* @throws UnsupportedOperationException if this context is immutable
*/
@NonNull Context userLocale(@Nullable DiscordLocale locale);

/**
* Sets the user locale of this context.
*
* @param interaction an interaction triggered by the user
* @return this context
* @throws UnsupportedOperationException if this context is immutable
*/
default @NonNull Context userLocale(@NonNull Interaction interaction) {
return userLocale(Objects.requireNonNull(interaction, "interaction").getUserLocale());
}

// channel setter

/**
* Sets the channel ID of this context.
*
* @param channel the channel ID
* @return this context
* @throws UnsupportedOperationException if this context is immutable
*/
@NonNull Context channel(long channel);

/**
* Sets the channel ID of this context.
*
* @param channel the channel
* @return this context
* @throws UnsupportedOperationException if this context is immutable
*/
default @NonNull Context channel(@NonNull MessageChannel channel) {
return channel(Objects.requireNonNull(channel, "channel").getIdLong());
}

// guild setter

/**
* Sets the guild ID of this context.
*
* @param guild the guild ID
* @return this context
* @throws UnsupportedOperationException if this context is immutable
*/
@NonNull Context guild(long guild);

/**
* Sets the guild ID of this context.
*
* @param guild the guild
* @return this context
* @throws UnsupportedOperationException if this context is immutable
*/
default @NonNull Context guild(@NonNull Guild guild) {
return guild(Objects.requireNonNull(guild, "guild").getIdLong());
}

// guild locale setter

/**
* Sets the guild locale of this context.
*
* @param locale the locale
* @return this context
* @throws UnsupportedOperationException if this context is immutable
*/
@NonNull Context guildLocale(@Nullable DiscordLocale locale);

/**
* Sets the guild locale of this context.
*
* @param guild the guild
* @return this context
* @throws UnsupportedOperationException if this context is immutable
*/
default @NonNull Context guildLocale(@NonNull Guild guild) {
Objects.requireNonNull(guild, "guild");
DiscordLocale locale = guild.getFeatures().contains("COMMUNITY")
? guild.getLocale()
: null;
return guildLocale(locale);
}

// copy

/**
* Creates a mutable copy of this context.
* Creates a {@link Builder} from this context.
*
* @return a mutable copy of this context
* @return a builder from this context
*/
default @NonNull Context mutableCopy() {
return new MutableContextImpl(user(), userLocale(), channel(), guild(), guildLocale());
default @NonNull Context toBuilder() {
return builder().user(user()).userLocale(userLocale()).channel(channel()).guild(guild()).guildLocale(guildLocale()).build();
}

/**
* Creates an immutable copy of this context.
* Creates a new {@link Builder}.
*
* @return an immutable copy of this context
* @return new builder
*/
default @NonNull Context immutableCopy() {
return new ImmutableContextImpl(user(), userLocale(), channel(), guild(), guildLocale());
static @NonNull Builder builder() {
return new ContextBuilderImpl();
}

/**
Expand All @@ -235,12 +100,12 @@ public interface Context {
* @return a context
*/
static @NonNull Context fromMessage(@NonNull Message message) {
Context context = new MutableContextImpl()
Builder context = builder()
.user(message.getAuthor())
.channel(message.getChannel());
if (message.isFromGuild())
context.guild(message.getGuild()).guildLocale(message.getGuild());
return context.immutableCopy();
return context.build();
}

/**
Expand All @@ -250,16 +115,142 @@ public interface Context {
* @return a context
*/
static @NonNull Context fromInteraction(@NonNull Interaction interaction) {
Context context = new MutableContextImpl().user(interaction.getUser());
Builder context = new ContextBuilderImpl().user(interaction.getUser());
if (interaction.getChannel() instanceof MessageChannel channel)
context.channel(channel);
if (interaction.getGuild() != null)
context.guild(interaction.getGuild()).guildLocale(interaction.getGuild());
return context.immutableCopy();
return context.build();
}

/**
* An empty context.
*/
@NonNull Context EMPTY = new ImmutableContextImpl(0, null, 0, 0, null);
@NonNull Context EMPTY = builder().build();

/**
* Builder for a {@link Context}.
*/
@SuppressWarnings("UnusedReturnValue")
interface Builder {

// user setter

/**
* Sets the user ID of this context.
*
* @param user the user ID
* @return this context
*/
@NonNull Builder user(long user);

/**
* Sets the user ID of this context.
*
* @param user the user
* @return this context
*/
default @NonNull Builder user(@NonNull User user) {
return user(Objects.requireNonNull(user, "user").getIdLong());
}

/**
* Sets the user ID of this context.
*
* @param member the member
* @return this context
*/
default @NonNull Builder user(@NonNull Member member) {
return user(Objects.requireNonNull(member, "member").getIdLong());
}

// user locale setter

/**
* Sets the user locale of this context.
*
* @param locale the locale
* @return this context
*/
@NonNull Builder userLocale(@Nullable DiscordLocale locale);

/**
* Sets the user locale of this context.
*
* @param interaction an interaction triggered by the user
* @return this context
*/
default @NonNull Builder userLocale(@NonNull Interaction interaction) {
return userLocale(Objects.requireNonNull(interaction, "interaction").getUserLocale());
}

// channel setter

/**
* Sets the channel ID of this context.
*
* @param channel the channel ID
* @return this context
*/
@NonNull Builder channel(long channel);

/**
* Sets the channel ID of this context.
*
* @param channel the channel
* @return this context
*/
default @NonNull Builder channel(@NonNull MessageChannel channel) {
return channel(Objects.requireNonNull(channel, "channel").getIdLong());
}

// guild setter

/**
* Sets the guild ID of this context.
*
* @param guild the guild ID
* @return this context
*/
@NonNull Builder guild(long guild);

/**
* Sets the guild ID of this context.
*
* @param guild the guild
* @return this context
*/
default @NonNull Builder guild(@NonNull Guild guild) {
return guild(Objects.requireNonNull(guild, "guild").getIdLong());
}

// guild locale setter

/**
* Sets the guild locale of this context.
*
* @param locale the locale
* @return this context
*/
@NonNull Builder guildLocale(@Nullable DiscordLocale locale);

/**
* Sets the guild locale of this context.
*
* @param guild the guild
* @return this context
*/
default @NonNull Builder guildLocale(@NonNull Guild guild) {
Objects.requireNonNull(guild, "guild");
DiscordLocale locale = guild.getFeatures().contains("COMMUNITY")
? guild.getLocale()
: null;
return guildLocale(locale);
}

/**
* Builds the {@link Context}.
*/
@NonNull Context build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,27 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

package dev.qixils.quasicord.locale.impl;
package dev.qixils.quasicord.locale;

import dev.qixils.quasicord.locale.Context;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import net.dv8tion.jda.api.interactions.DiscordLocale;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;

import java.util.Objects;

@Accessors(fluent = true, chain = true)
@AllArgsConstructor
@NoArgsConstructor
@Data
public final class MutableContextImpl implements Context {
final class ContextBuilderImpl implements Context.Builder {
private long user;
private @Nullable DiscordLocale userLocale;
private long channel;
private long guild;
private @Nullable DiscordLocale guildLocale;

@Override
public boolean isMutable() {
return true;
}

@Override
public int hashCode() {
return Objects.hash(user, userLocale, channel, guild, guildLocale);
}

public boolean equals(@Nullable Object obj) {
if (obj == null) return false;
if (!(obj instanceof Context other)) return false;
if (user != other.user()) return false;
if (channel != other.channel()) return false;
return guild == other.guild();
public @NonNull Context build() {
return new ContextImpl(user, userLocale, channel, guild, guildLocale);
}
}
Loading

0 comments on commit 1ade314

Please sign in to comment.