Skip to content

Commit

Permalink
docs: add more javadocs to core API
Browse files Browse the repository at this point in the history
  • Loading branch information
Silthus committed Feb 21, 2022
1 parent 86bfbf4 commit d67a33b
Show file tree
Hide file tree
Showing 27 changed files with 630 additions and 71 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ jobs:

javadoc:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v2
- name: Set up JDK 17
Expand All @@ -90,6 +91,7 @@ jobs:
with:
branch: javadocs
folder: core/build/docs/javadoc

release:
needs: [ build, test ]
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/release' || github.ref == 'refs/heads/next'
Expand Down
6 changes: 5 additions & 1 deletion build-logic/src/main/kotlin/schat.api.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,8 @@ tasks {
jacocoTestReport {
dependsOn(test)
}
}
}

if (project.hasProperty("local_script")) {
apply(file("${project.property("local_script")}/build.local.gradle"))
}
188 changes: 163 additions & 25 deletions core/src/main/java/net/silthus/schat/channel/Channel.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@
*/
package net.silthus.schat.channel;

import java.io.Serial;
import java.util.Optional;
import lombok.NonNull;
import net.kyori.adventure.text.Component;
import net.silthus.schat.chatter.Chatter;
import net.silthus.schat.commands.JoinChannelCommand;
import net.silthus.schat.commands.LeaveChannelCommand;
import net.silthus.schat.events.message.SendChannelMessageEvent;
import net.silthus.schat.message.MessageTarget;
import net.silthus.schat.message.Messages;
import net.silthus.schat.message.Targets;
Expand All @@ -34,7 +39,6 @@
import net.silthus.schat.pointer.Pointer;
import net.silthus.schat.pointer.Setting;
import net.silthus.schat.pointer.Settings;
import net.silthus.schat.policies.ChannelPolicy;
import net.silthus.schat.policies.JoinChannelPolicy;
import net.silthus.schat.policies.LeaveChannelPolicy;
import net.silthus.schat.policies.Policy;
Expand All @@ -44,74 +48,208 @@
import org.jetbrains.annotations.Unmodifiable;

import static net.silthus.schat.pointer.Setting.setting;
import static net.silthus.schat.policies.JoinChannelPolicy.JOIN_CHANNEL_POLICY;
import static net.silthus.schat.policies.LeaveChannelPolicy.LEAVE_CHANNEL_POLICY;
import static net.silthus.schat.policies.SendChannelMessagePolicy.SEND_CHANNEL_MESSAGE_POLICY;

/**
* The channel is a message target that forwards messages sent to it to all joined targets.
*
* <p>The behaviour of a channel is controlled by the {@link ChannelSettings} and the use of channel events.
* Create your own {@link Setting}s and set them using the {@link Builder#set(Setting, Object)} or at runtime
* with {@link #set(Setting, Object)}.</p>
*
* <br><p>{@link Chatter}s can join channels using the {@link JoinChannelCommand} which checks the {@link JoinChannelPolicy}.
* The policy can be overwritten per channel using the {@link Builder}.
* The same is applicable for the {@link LeaveChannelCommand} and {@link LeaveChannelPolicy}.</p>
*
* <p>When a channel receives a message, the {@link SendChannelMessageEvent} is fired and tested against the {@link SendChannelMessagePolicy}.</p>
*
* <p><br>Every channel that is created must also be registered with the {@link ChannelRepository} for it to be accessible by other features.</p>
*
* <p>Use the static {@link #createChannel(String)} and {@link #channel(String)} methods to create a new channel.</p>
* <pre>{@code
* Channel channel = Channel.channel("my_channel")
* .set(ChannelSettings.GLOBAL, true) // creates the channel as a global channel sending the messages to all servers
* .policy(JoinChannelPolicy.class, ALLOW) // overrides the join policy and allows everyone to join the channel
* .create();
* sChat.channelRepository().add(channel); // registers the channel in the repository
* }</pre>
*
* @since next
*/
public sealed interface Channel extends Entity<String>, Configurable<Channel>, MessageTarget, AutoCloseable permits ChannelImpl {

/**
* This is a pointer to the {@link #key()} of the channel.
*
* @since next
*/
Pointer<String> KEY = Pointer.pointer(String.class, "key");
/**
* The display name of the channel as it is shown in messages and the view.
*
* <p>Default: {@link Channel#key()}</p>
*
* @since next
*/
Setting<Component> DISPLAY_NAME = setting(Component.class, "name", Component.empty());

/**
* Creates a new channel using the given key.
*
* <p>The key must match the following pattern: {@code ^[a-zA-Z0-9_-]+$}.</p>
*
* @param key the key of the channel
* @return the created channel
* @since next
*/
static @NotNull Channel createChannel(String key) {
return channel(key).create();
}

/**
* Creates a new channel builder that can be used to customize the new channel.
*
* <p>The key must match the following pattern: {@code ^[a-zA-Z0-9_-]+$}.</p>
*
* @param key the key of the channel
* @return the builder of the channel
* @since next
*/
static @NotNull Builder channel(String key) {
return ChannelImpl.builder(key);
}

/**
* The key of the channel.
*
* @return the key
* @since next
*/
@NotNull String key();

/**
* The display name of the channel.
*
* @return the display name
* @since next
*/
default @NotNull Component displayName() {
return get(DISPLAY_NAME);
}

/**
* Replaces all settings of the channel with the given settings.
*
* @param settings the new settings
* @return this channel
* @since next
*/
@NotNull Channel settings(@NonNull Settings settings);

/**
* Gets all messages this channel received.
*
* @return a list of received messages
* @since next
*/
@NotNull @Unmodifiable Messages messages();

<P extends Policy> @NotNull Optional<P> policy(@NonNull Class<P> policy);

default @NotNull ChannelPolicy joinPolicy() {
return policy(JoinChannelPolicy.class).orElse(JOIN_CHANNEL_POLICY);
}

default @NotNull ChannelPolicy leavePolicy() {
return policy(LeaveChannelPolicy.class).orElse(LEAVE_CHANNEL_POLICY);
}

default @NotNull SendChannelMessagePolicy sendMessagePolicy() {
return policy(SendChannelMessagePolicy.class).orElse(SEND_CHANNEL_MESSAGE_POLICY);
}

/**
* Gets all targets of this channel.
*
* @return a list unmodifiable of targets
* @since next
*/
@NotNull @Unmodifiable Targets targets();

/**
* Adds a target to this channel without performing any checks.
*
* <p>Use the {@link JoinChannelCommand} to join a {@link Chatter} testing all policies.</p>
*
* @param target the target to add
* @since next
*/
void addTarget(@NonNull MessageTarget target);

/**
* Removes a target from this channel without performing any checks.
*
* <p>Use the {@link LeaveChannelCommand} to join a {@link Chatter} testing all policies.</p>
*
* @param target the target to remove
* @since next
*/
void removeTarget(@NonNull MessageTarget target);

void updateTargets();
/**
* Tries to find a policy attached to this channel.
*
* @param policy the policy to find
* @param <P> the policy type
* @return the policy if the channel has one
* @since next
*/
<P extends Policy> @NotNull Optional<P> policy(@NonNull Class<P> policy);

/**
* Closes this channel and removes all targets from it.
*/
@Override
void close();

/**
* The builder of a {@link Channel}.
*
* @since next
*/
interface Builder extends Configured.Builder<Builder> {

Builder name(@NonNull Component displayName);

Builder targets(@NonNull Targets targets);

<P extends Policy> Builder policy(@NonNull Class<P> type, @NonNull P policy);

/**
* Sets the display name of the channel.
*
* @param displayName the name
* @return this builder
* @since next
*/
@NotNull Builder name(@NonNull Component displayName);

/**
* Sets the targets of the channel.
*
* @param targets the targets
* @return this builder
* @since next
*/
@NotNull Builder targets(@NonNull Targets targets);

/**
* Assigns a policy to the channel.
*
* @param type the class of the policy type
* @param policy the policy
* @param <P> the type of the policy
* @return this builder
* @since next
*/
@NotNull <P extends Policy> Builder policy(@NonNull Class<P> type, @NonNull P policy);

/**
* Creates a new instance of the channel using this builder.
*
* @return the new channel
* @since next
*/
@NotNull Channel create();
}

/**
* The exception is thrown if a channel with an invalid key is created.
*
* <p>A valid key must match the following pattern: {@code ^[a-zA-Z0-9_-]+$}</p>
*
* @since next
*/
final class InvalidKey extends RuntimeException {
@Serial private static final long serialVersionUID = 4355995383300553731L;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,6 @@ public void removeTarget(@NonNull MessageTarget target) {
targets.remove(target);
}

@Override
public void updateTargets() {
for (MessageTarget target : targets())
if (target instanceof Chatter chatter)
chatter.join(this);
}

@Override
public SendMessageResult sendMessage(@NonNull Message message) {
if (messages.add(message))
Expand All @@ -146,7 +139,7 @@ public void close() {
}

private SendMessageResult processMessage(Message message) {
SendChannelMessageEvent event = eventBus.post(new SendChannelMessageEvent(this, message, sendMessagePolicy()));
SendChannelMessageEvent event = eventBus.post(new SendChannelMessageEvent(this, message, policy(SendChannelMessagePolicy.class).orElse(SEND_CHANNEL_MESSAGE_POLICY)));
if (event.isNotCancelled() && event.policy().test(this, message))
return event.targets().sendMessage(event.message());
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,67 @@
*/
package net.silthus.schat.channel;

import java.io.Serial;
import lombok.Getter;
import lombok.experimental.Accessors;
import net.silthus.schat.repository.Repository;
import org.jetbrains.annotations.NotNull;

/**
* Holds all channels registered on the server.
*
* @since next
*/
public interface ChannelRepository extends Repository<String, Channel> {

/**
* Creates a new in memory channel repository.
*
* @return the new in memory repository
* @since next
*/
static ChannelRepository createInMemoryChannelRepository() {
return createInMemoryChannelRepository(false);
}

/**
* Creates a new in memory channel repository.
*
* @param debug true to print all operations into the log
* @return the new in memory repository
* @since next
*/
static ChannelRepository createInMemoryChannelRepository(boolean debug) {
if (debug)
return new InMemoryChannelRepository.Logging();
else
return new InMemoryChannelRepository();
}

/**
* Adds the given channel to the repository if it does not exist.
*
* @param channel the channel to add
* @throws DuplicateChannel if a channel with the same key exists
*/
@Override
void add(@NotNull Channel channel);

/**
* The exception is thrown if someone tries to add a channel with the same key to the repository.
*
* @since next
*/
@Getter
@Accessors(fluent = true)
final class DuplicateChannel extends RuntimeException {
public DuplicateChannel(Channel channel) {
@Serial private static final long serialVersionUID = 365583451304114504L;

private final Channel channel;

DuplicateChannel(Channel channel) {
super("A channel with the key '" + channel.key() + "' already exists.");
this.channel = channel;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@

import static net.silthus.schat.pointer.Setting.setting;

/**
* Holds references to all common settings of a {@link Channel}.
*
* @since next
*/
public final class ChannelSettings {

/**
Expand Down
Loading

0 comments on commit d67a33b

Please sign in to comment.