-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
31 changed files
with
1,575 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
pojos/src/main/java/dev/qixils/crowdcontrol/fields/CommonFields.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package dev.qixils.crowdcontrol.fields; | ||
|
||
import com.google.gson.reflect.TypeToken; | ||
import dev.qixils.crowdcontrol.socket.Field; | ||
import dev.qixils.crowdcontrol.socket.ObjectTypes; | ||
import dev.qixils.crowdcontrol.socket.SocketManager; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
public class CommonFields { | ||
private CommonFields() { | ||
} | ||
|
||
public static <T> Field.Builder<T> packet(@NotNull TypeToken<T> type) { | ||
return new Field.Builder<>(type).addSupports(ObjectTypes.REQUEST.id(), ObjectTypes.RESPONSE.id()); | ||
} | ||
|
||
public static <T> Field.Builder<T> packet(@NotNull Class<T> type) { | ||
return new Field.Builder<>(type).addSupports(ObjectTypes.REQUEST.id(), ObjectTypes.RESPONSE.id()); | ||
} | ||
|
||
/** | ||
* The ID of the packet. Corresponds to a unique transaction. | ||
* | ||
* @since 4.0.0 | ||
*/ | ||
public static final Field<Integer> ID = packet(Integer.class).addId("id").build(); | ||
|
||
/** | ||
* The message describing or explaining the packet. | ||
* | ||
* @since 4.0.0 | ||
*/ | ||
public static final Field<String> MESSAGE = packet(String.class).addId("message").build(); | ||
|
||
/** | ||
* The socket from which a packet was received from or will be sent to. | ||
* | ||
* @since 4.0.0 | ||
*/ | ||
public static final Field<SocketManager> SOCKET = packet(SocketManager.class).addId("socket").isTransient(true).build(); | ||
|
||
// TODO: `LOGIN` (request, request target, request source) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
pojos/src/main/java/dev/qixils/crowdcontrol/socket/CCAdapterFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package dev.qixils.crowdcontrol.socket; | ||
|
||
import com.google.gson.Gson; | ||
import com.google.gson.JsonObject; | ||
import com.google.gson.TypeAdapter; | ||
import com.google.gson.TypeAdapterFactory; | ||
import com.google.gson.reflect.TypeToken; | ||
import com.google.gson.stream.JsonReader; | ||
import com.google.gson.stream.JsonWriter; | ||
import dev.qixils.crowdcontrol.util.PostProcessable; | ||
import org.jetbrains.annotations.ApiStatus; | ||
|
||
import java.io.IOException; | ||
|
||
@ApiStatus.Internal | ||
public class CCAdapterFactory implements TypeAdapterFactory { | ||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { | ||
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type); | ||
final TypeAdapter<JsonObject> objectDelegate = gson.getDelegateAdapter(this, new TypeToken<JsonObject>(){}); | ||
|
||
return new TypeAdapter<T>() { | ||
public void write(JsonWriter out, T value) throws IOException { | ||
delegate.write(out, value); | ||
} | ||
|
||
public T read(JsonReader in) throws IOException { | ||
final T obj; | ||
|
||
// handle | ||
if (TypeToken.get(JsonHolder.class).isAssignableFrom(type)) { | ||
try { | ||
JsonObject jsonObject = objectDelegate.read(in); | ||
obj = (T) type.getRawType().getConstructor(JsonObject.class).newInstance(jsonObject); | ||
} catch (Exception e) { | ||
throw new IllegalStateException("Failed to instantiate JsonHolder", e); | ||
} | ||
} else { | ||
obj = delegate.read(in); | ||
} | ||
|
||
if (obj instanceof PostProcessable) { | ||
((PostProcessable)obj).postProcess(); | ||
} | ||
|
||
return obj; | ||
} | ||
}; | ||
} | ||
} |
118 changes: 118 additions & 0 deletions
118
pojos/src/main/java/dev/qixils/crowdcontrol/socket/Field.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package dev.qixils.crowdcontrol.socket; | ||
|
||
import com.google.gson.reflect.TypeToken; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
import java.util.*; | ||
|
||
public class Field<T> { | ||
|
||
private final List<String> ids; | ||
private final boolean isTransient; | ||
private final TypeToken<T> type; | ||
private final Set<String> supports; | ||
|
||
private Field(Collection<String> ids, Collection<String> supports, TypeToken<T> type, boolean isTransient) { | ||
this.ids = Collections.unmodifiableList(new ArrayList<>(new LinkedHashSet<>(ids))); | ||
this.supports = Collections.unmodifiableSet(new HashSet<>(supports)); | ||
this.type = type; | ||
this.isTransient = isTransient; | ||
|
||
assert !this.ids.isEmpty(); | ||
assert !this.supports.isEmpty(); | ||
} | ||
|
||
public String id() { | ||
return ids.get(0); | ||
} | ||
|
||
public List<String> ids() { | ||
return ids; | ||
} | ||
|
||
public boolean isTransient() { | ||
return isTransient; | ||
} | ||
|
||
public TypeToken<T> type() { | ||
return type; | ||
} | ||
|
||
public boolean supports(String objectType) { | ||
return supports.contains(objectType); | ||
} | ||
|
||
public boolean supports(ObjectType<?> objectType) { | ||
return supports(objectType.id()); | ||
} | ||
|
||
public static final class Builder<T> { | ||
// TODO: this feels counter to the point of JsonHolder but i think making a dynamic builder here might be too meta, or maybe not IDK i guess i could detach dynamic building from json | ||
private final List<String> ids = new ArrayList<>(); | ||
private boolean isTransient; | ||
private final TypeToken<T> type; | ||
private final Set<String> supports = new HashSet<>(); | ||
|
||
public Builder(TypeToken<T> type) { | ||
this.type = type; | ||
} | ||
|
||
public Builder(Class<T> clazz) { | ||
this.type = TypeToken.get(clazz); | ||
} | ||
|
||
public Builder<T> addId(@NotNull String id) { | ||
this.ids.add(id); | ||
return this; | ||
} | ||
|
||
public Builder<T> addIds(@NotNull String @NotNull ... ids) { | ||
this.ids.addAll(Arrays.asList(ids)); | ||
return this; | ||
} | ||
|
||
public Builder<T> setId(@NotNull String id) { | ||
this.ids.clear(); | ||
return addId(id); | ||
} | ||
|
||
public Builder<T> setIds(@NotNull String @NotNull ... ids) { | ||
this.ids.clear(); | ||
return addIds(ids); | ||
} | ||
|
||
public Builder<T> isTransient(boolean isTransient) { | ||
this.isTransient = isTransient; | ||
return this; | ||
} | ||
|
||
public Builder<T> setTransient() { | ||
return isTransient(true); | ||
} | ||
|
||
public Builder<T> addSupport(String objectType) { | ||
this.supports.add(objectType); | ||
return this; | ||
} | ||
|
||
public Builder<T> addSupports(String... objectTypes) { | ||
this.supports.addAll(Arrays.asList(objectTypes)); | ||
return this; | ||
} | ||
|
||
public Builder<T> setSupport(String objectType) { | ||
this.supports.clear(); | ||
return addSupport(objectType); | ||
} | ||
|
||
public Builder<T> setSupport(String... objectTypes) { | ||
this.supports.clear(); | ||
return addSupports(objectTypes); | ||
} | ||
|
||
public Field<T> build() { | ||
return new Field<>(ids, supports, type, isTransient); | ||
} | ||
} | ||
|
||
} |
73 changes: 73 additions & 0 deletions
73
pojos/src/main/java/dev/qixils/crowdcontrol/socket/IHolder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package dev.qixils.crowdcontrol.socket; | ||
|
||
import org.jetbrains.annotations.Contract; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
import org.jetbrains.annotations.UnknownNullability; | ||
|
||
import java.util.Optional; | ||
import java.util.function.Supplier; | ||
|
||
/** | ||
* A holder of {@link Field}s. | ||
* | ||
* @since 4.0.0 | ||
*/ | ||
public interface IHolder { | ||
|
||
/** | ||
* Attempts to get a field from this object. | ||
* May return empty if the field is {@link Field#supports(ObjectType) unsupported} | ||
* or undefined. | ||
* | ||
* @param field the field to get | ||
* @param <T> the type of the field | ||
* @return the deserialized field | ||
* @since 4.0.0 | ||
*/ | ||
<T> @NotNull Optional<T> get(@NotNull Field<T> field); | ||
|
||
/** | ||
* Attempts to get a field from this object. | ||
* Returns the default if the field is {@link Field#supports(ObjectType) unsupported} | ||
* or undefined. | ||
* | ||
* @param field the field to get | ||
* @param <T> the type of the field | ||
* @return the deserialized field | ||
* @since 4.0.0 | ||
*/ | ||
@Contract(value = "_, !null -> !null", pure = true) | ||
default <T> @Nullable T getOrDef(@NotNull Field<T> field, @Nullable T def) { | ||
return get(field).orElse(def); | ||
} | ||
|
||
/** | ||
* Attempts to get a field from this object. | ||
* Returns the default if the field is {@link Field#supports(ObjectType) unsupported} | ||
* or undefined. | ||
* | ||
* @param field the field to get | ||
* @param <T> the type of the field | ||
* @return the deserialized field | ||
* @since 4.0.0 | ||
*/ | ||
@UnknownNullability("May be null if the supplier produces a null value") | ||
default <T> T getOrSupply(@NotNull Field<T> field, @NotNull Supplier<@Nullable T> def) { | ||
return get(field).orElseGet(def); | ||
} | ||
|
||
/** | ||
* Attempts to get a field from this object. | ||
* Returns null if the field is {@link Field#supports(ObjectType) unsupported} | ||
* or undefined. | ||
* | ||
* @param field the field to get | ||
* @param <T> the type of the field | ||
* @return the deserialized field | ||
* @since 4.0.0 | ||
*/ | ||
default <T> @Nullable T getOrNull(@NotNull Field<T> field) { | ||
return getOrDef(field, null); | ||
} | ||
} |
Oops, something went wrong.