From 307b3427e8a7ae6bd23157ce257aa325f5b73ba5 Mon Sep 17 00:00:00 2001 From: zontreck Date: Wed, 9 Oct 2024 22:21:30 -0700 Subject: [PATCH] Don't jarjar anymore. --- build.gradle | 15 - .../dev/zontreck/ariaslib/args/Argument.java | 106 + .../zontreck/ariaslib/args/ArgumentType.java | 25 + .../dev/zontreck/ariaslib/args/Arguments.java | 63 + .../ariaslib/args/ArgumentsBuilder.java | 20 + .../ariaslib/args/ArgumentsParser.java | 99 + .../ariaslib/args/BooleanArgument.java | 35 + .../ariaslib/args/IntegerArgument.java | 30 + .../zontreck/ariaslib/args/LongArgument.java | 30 + .../ariaslib/args/StringArgument.java | 30 + .../EventRegistrationException.java | 7 + .../WrongArgumentTypeException.java | 7 + .../dev/zontreck/ariaslib/file/AriaIO.java | 34 + .../dev/zontreck/ariaslib/file/Entry.java | 281 +++ .../dev/zontreck/ariaslib/file/EntryType.java | 36 + .../zontreck/ariaslib/file/EntryUtils.java | 118 + .../dev/zontreck/ariaslib/file/Folder.java | 42 + .../dev/zontreck/ariaslib/html/Bootstrap.java | 283 +++ .../ariaslib/html/ClassAttribute.java | 8 + .../java/dev/zontreck/ariaslib/html/DOM.java | 55 + .../zontreck/ariaslib/html/HTMLAttribute.java | 24 + .../zontreck/ariaslib/html/HTMLElement.java | 72 + .../ariaslib/html/HTMLElementBuilder.java | 118 + .../ariaslib/html/bootstrap/Color.java | 46 + .../ariaslib/html/bootstrap/Icons.java | 1969 +++++++++++++++++ .../ariaslib/html/bootstrap/Size.java | 25 + .../zontreck/ariaslib/http/HTTPMethod.java | 9 + .../zontreck/ariaslib/http/HTTPRequest.java | 15 + .../ariaslib/http/HTTPRequestBuilder.java | 134 ++ .../zontreck/ariaslib/http/HTTPResponse.java | 33 + .../dev/zontreck/ariaslib/json/Completed.java | 15 + .../dev/zontreck/ariaslib/json/DynSerial.java | 11 + .../ariaslib/json/DynamicDeserializer.java | 119 + .../ariaslib/json/DynamicSerializer.java | 115 + .../ariaslib/json/IgnoreSerialization.java | 12 + .../zontreck/ariaslib/json/JsonObject.java | 183 ++ .../dev/zontreck/ariaslib/json/ListOrMap.java | 8 + .../zontreck/ariaslib/json/PreSerialize.java | 13 + .../zontreck/ariaslib/terminal/Banners.java | 47 + .../dev/zontreck/ariaslib/terminal/Task.java | 88 + .../terminal/TaskCompletionToken.java | 20 + .../zontreck/ariaslib/terminal/Terminal.java | 35 + .../ariaslib/util/DelayedExecutorService.java | 17 + .../ariaslib/util/EnvironmentUtils.java | 19 + .../dev/zontreck/ariaslib/util/FileIO.java | 51 + .../dev/zontreck/ariaslib/util/Hashing.java | 120 + .../dev/zontreck/ariaslib/util/Lists.java | 94 + .../java/dev/zontreck/ariaslib/util/Maps.java | 49 + .../dev/zontreck/ariaslib/util/MathUtil.java | 18 + .../dev/zontreck/ariaslib/util/Percent.java | 23 + .../dev/zontreck/ariaslib/util/Progress.java | 56 + .../zontreck/ariaslib/util/ProgressBar.java | 66 + .../zontreck/ariaslib/util/TimeNotation.java | 161 ++ .../dev/zontreck/ariaslib/util/TimeUtil.java | 96 + .../zontreck/ariaslib/xmlrpc/MethodCall.java | 32 + .../ariaslib/xmlrpc/MethodResponse.java | 26 + .../dev/zontreck/ariaslib/xmlrpc/README.md | 7 + .../ariaslib/xmlrpc/XmlRpcDeserializer.java | 44 + .../ariaslib/xmlrpc/XmlRpcException.java | 24 + .../ariaslib/xmlrpc/XmlRpcSerializer.java | 26 + .../ariaslib/xmlrpc/XmlRpcStreamReader.java | 206 ++ .../ariaslib/xmlrpc/XmlRpcStreamWriter.java | 166 ++ .../ariaslib/xmlrpc/XmlRpcTokens.java | 48 + src/main/java/dev/zontreck/eventsbus/Bus.java | 166 ++ .../dev/zontreck/eventsbus/ClassScanner.java | 95 + .../java/dev/zontreck/eventsbus/Event.java | 46 + .../zontreck/eventsbus/EventContainer.java | 45 + .../zontreck/eventsbus/EventDispatcher.java | 124 ++ .../dev/zontreck/eventsbus/PriorityLevel.java | 15 + .../eventsbus/annotations/Cancellable.java | 11 + .../annotations/EventSubscriber.java | 11 + .../eventsbus/annotations/Priority.java | 14 + .../annotations/SingleshotEvent.java | 11 + .../eventsbus/annotations/Subscribe.java | 18 + .../eventsbus/events/EventBusReadyEvent.java | 11 + .../eventsbus/events/ResetEventBusEvent.java | 17 + .../zontreck/eventsbus/events/TickEvent.java | 6 + 77 files changed, 6359 insertions(+), 15 deletions(-) create mode 100644 src/main/java/dev/zontreck/ariaslib/args/Argument.java create mode 100644 src/main/java/dev/zontreck/ariaslib/args/ArgumentType.java create mode 100644 src/main/java/dev/zontreck/ariaslib/args/Arguments.java create mode 100644 src/main/java/dev/zontreck/ariaslib/args/ArgumentsBuilder.java create mode 100644 src/main/java/dev/zontreck/ariaslib/args/ArgumentsParser.java create mode 100644 src/main/java/dev/zontreck/ariaslib/args/BooleanArgument.java create mode 100644 src/main/java/dev/zontreck/ariaslib/args/IntegerArgument.java create mode 100644 src/main/java/dev/zontreck/ariaslib/args/LongArgument.java create mode 100644 src/main/java/dev/zontreck/ariaslib/args/StringArgument.java create mode 100644 src/main/java/dev/zontreck/ariaslib/exceptions/EventRegistrationException.java create mode 100644 src/main/java/dev/zontreck/ariaslib/exceptions/WrongArgumentTypeException.java create mode 100644 src/main/java/dev/zontreck/ariaslib/file/AriaIO.java create mode 100644 src/main/java/dev/zontreck/ariaslib/file/Entry.java create mode 100644 src/main/java/dev/zontreck/ariaslib/file/EntryType.java create mode 100644 src/main/java/dev/zontreck/ariaslib/file/EntryUtils.java create mode 100644 src/main/java/dev/zontreck/ariaslib/file/Folder.java create mode 100644 src/main/java/dev/zontreck/ariaslib/html/Bootstrap.java create mode 100644 src/main/java/dev/zontreck/ariaslib/html/ClassAttribute.java create mode 100644 src/main/java/dev/zontreck/ariaslib/html/DOM.java create mode 100644 src/main/java/dev/zontreck/ariaslib/html/HTMLAttribute.java create mode 100644 src/main/java/dev/zontreck/ariaslib/html/HTMLElement.java create mode 100644 src/main/java/dev/zontreck/ariaslib/html/HTMLElementBuilder.java create mode 100644 src/main/java/dev/zontreck/ariaslib/html/bootstrap/Color.java create mode 100644 src/main/java/dev/zontreck/ariaslib/html/bootstrap/Icons.java create mode 100644 src/main/java/dev/zontreck/ariaslib/html/bootstrap/Size.java create mode 100644 src/main/java/dev/zontreck/ariaslib/http/HTTPMethod.java create mode 100644 src/main/java/dev/zontreck/ariaslib/http/HTTPRequest.java create mode 100644 src/main/java/dev/zontreck/ariaslib/http/HTTPRequestBuilder.java create mode 100644 src/main/java/dev/zontreck/ariaslib/http/HTTPResponse.java create mode 100644 src/main/java/dev/zontreck/ariaslib/json/Completed.java create mode 100644 src/main/java/dev/zontreck/ariaslib/json/DynSerial.java create mode 100644 src/main/java/dev/zontreck/ariaslib/json/DynamicDeserializer.java create mode 100644 src/main/java/dev/zontreck/ariaslib/json/DynamicSerializer.java create mode 100644 src/main/java/dev/zontreck/ariaslib/json/IgnoreSerialization.java create mode 100644 src/main/java/dev/zontreck/ariaslib/json/JsonObject.java create mode 100644 src/main/java/dev/zontreck/ariaslib/json/ListOrMap.java create mode 100644 src/main/java/dev/zontreck/ariaslib/json/PreSerialize.java create mode 100644 src/main/java/dev/zontreck/ariaslib/terminal/Banners.java create mode 100644 src/main/java/dev/zontreck/ariaslib/terminal/Task.java create mode 100644 src/main/java/dev/zontreck/ariaslib/terminal/TaskCompletionToken.java create mode 100644 src/main/java/dev/zontreck/ariaslib/terminal/Terminal.java create mode 100644 src/main/java/dev/zontreck/ariaslib/util/DelayedExecutorService.java create mode 100644 src/main/java/dev/zontreck/ariaslib/util/EnvironmentUtils.java create mode 100644 src/main/java/dev/zontreck/ariaslib/util/FileIO.java create mode 100644 src/main/java/dev/zontreck/ariaslib/util/Hashing.java create mode 100644 src/main/java/dev/zontreck/ariaslib/util/Lists.java create mode 100644 src/main/java/dev/zontreck/ariaslib/util/Maps.java create mode 100644 src/main/java/dev/zontreck/ariaslib/util/MathUtil.java create mode 100644 src/main/java/dev/zontreck/ariaslib/util/Percent.java create mode 100644 src/main/java/dev/zontreck/ariaslib/util/Progress.java create mode 100644 src/main/java/dev/zontreck/ariaslib/util/ProgressBar.java create mode 100644 src/main/java/dev/zontreck/ariaslib/util/TimeNotation.java create mode 100644 src/main/java/dev/zontreck/ariaslib/util/TimeUtil.java create mode 100644 src/main/java/dev/zontreck/ariaslib/xmlrpc/MethodCall.java create mode 100644 src/main/java/dev/zontreck/ariaslib/xmlrpc/MethodResponse.java create mode 100644 src/main/java/dev/zontreck/ariaslib/xmlrpc/README.md create mode 100644 src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcDeserializer.java create mode 100644 src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcException.java create mode 100644 src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcSerializer.java create mode 100644 src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcStreamReader.java create mode 100644 src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcStreamWriter.java create mode 100644 src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcTokens.java create mode 100644 src/main/java/dev/zontreck/eventsbus/Bus.java create mode 100644 src/main/java/dev/zontreck/eventsbus/ClassScanner.java create mode 100644 src/main/java/dev/zontreck/eventsbus/Event.java create mode 100644 src/main/java/dev/zontreck/eventsbus/EventContainer.java create mode 100644 src/main/java/dev/zontreck/eventsbus/EventDispatcher.java create mode 100644 src/main/java/dev/zontreck/eventsbus/PriorityLevel.java create mode 100644 src/main/java/dev/zontreck/eventsbus/annotations/Cancellable.java create mode 100644 src/main/java/dev/zontreck/eventsbus/annotations/EventSubscriber.java create mode 100644 src/main/java/dev/zontreck/eventsbus/annotations/Priority.java create mode 100644 src/main/java/dev/zontreck/eventsbus/annotations/SingleshotEvent.java create mode 100644 src/main/java/dev/zontreck/eventsbus/annotations/Subscribe.java create mode 100644 src/main/java/dev/zontreck/eventsbus/events/EventBusReadyEvent.java create mode 100644 src/main/java/dev/zontreck/eventsbus/events/ResetEventBusEvent.java create mode 100644 src/main/java/dev/zontreck/eventsbus/events/TickEvent.java diff --git a/build.gradle b/build.gradle index fb26e77..8ab7578 100644 --- a/build.gradle +++ b/build.gradle @@ -11,13 +11,6 @@ base { archivesName = project.archives_name } -configurations { - provided - compile.extendsFrom(provided) - implementation.extendsFrom(provided) - minecraftLibrary.extendsFrom(provided) -} - loom { silentMojangMappingsLicense() @@ -43,10 +36,6 @@ dependencies { minecraft "net.minecraft:minecraft:$project.minecraft_version" mappings loom.officialMojangMappings() forge "net.minecraftforge:forge:$project.forge_version" - - - provided "dev.zontreck:LibAC:${libac}" - provided "dev.zontreck:EventsBus:${eventsbus}" } processResources { @@ -72,10 +61,6 @@ tasks.withType(JavaCompile).configureEach { it.options.release = 17 } tasks.named('jar', Jar).configure { - from { - configurations.provided.asFileTree.collect { zipTree(it) } - } - duplicatesStrategy = DuplicatesStrategy.EXCLUDE manifest { attributes([ diff --git a/src/main/java/dev/zontreck/ariaslib/args/Argument.java b/src/main/java/dev/zontreck/ariaslib/args/Argument.java new file mode 100644 index 0000000..64463d8 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/args/Argument.java @@ -0,0 +1,106 @@ +package dev.zontreck.ariaslib.args; + +import dev.zontreck.ariaslib.exceptions.WrongArgumentTypeException; + +public abstract class Argument implements Cloneable +{ + public boolean hasValue = false; + public String name; + + + /** + * Initializes a boolean only command line toggle + * + * @param name The option name + */ + public Argument(String name) { + this.name = name; + } + + /** + * Retrieves the current argument's type + * + * @return The argument type! + */ + public abstract ArgumentType getType(); + + + /** + * Retrieves the value. + * + * @return The value + * @throws IllegalArgumentException When there is no value + */ + public T getValue() throws IllegalArgumentException { + throw new IllegalArgumentException("No value"); + } + + /** + * Directly cast to the Argument type Long + * @return + * @throws WrongArgumentTypeException Throws when type does not match + */ + public LongArgument getAsLong() throws WrongArgumentTypeException { + if(this instanceof LongArgument) + { + return (LongArgument) this; + } + + throw new WrongArgumentTypeException(); + } + + + /** + * Directly cast to the Argument type String + * @return + * @throws WrongArgumentTypeException Throws when type does not match + */ + public StringArgument getAsString() throws WrongArgumentTypeException { + if(this instanceof StringArgument) + { + return (StringArgument) this; + } + + throw new WrongArgumentTypeException(); + } + + + /** + * Directly cast to the Argument type Integer + * @return + * @throws WrongArgumentTypeException Throws when type does not match + */ + public IntegerArgument getAsInteger() throws WrongArgumentTypeException + { + if(this instanceof IntegerArgument) + { + return (IntegerArgument) this; + } + + throw new WrongArgumentTypeException(); + } + + @Override + public Argument clone() { + Argument arg = null; + try{ + + if(getType() == ArgumentType.LONG) + { + arg = (Argument) new LongArgument(name, getAsLong().getValue()); + } else if(getType() == ArgumentType.STRING) + { + arg = (Argument) new StringArgument(name, getAsString().getValue()); + } else if(getType() == ArgumentType.BOOLEAN) { + arg = (Argument) new BooleanArgument(name); + } else if(getType() == ArgumentType.INTEGER){ + arg = (Argument) new IntegerArgument(name, getAsInteger().getValue()); + } + }catch (WrongArgumentTypeException ex) + { + ex.printStackTrace(); + } + + return arg; + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/args/ArgumentType.java b/src/main/java/dev/zontreck/ariaslib/args/ArgumentType.java new file mode 100644 index 0000000..82c310b --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/args/ArgumentType.java @@ -0,0 +1,25 @@ +package dev.zontreck.ariaslib.args; + +public enum ArgumentType { + /** + * This indicates a string. It may possibly have a default value + */ + STRING, + /** + * This indicates a boolean + *

+ * This may have a default value, which initiates a BooleanArgument + */ + BOOLEAN, + + /** + * This indicates a data type of integer + * The type of integer arg is determined by the length of the integer. + */ + INTEGER, + + /** + * This is a long value, which can hold larger values than a integer. The type of integer arg is determined by the length of the integer. + */ + LONG +} diff --git a/src/main/java/dev/zontreck/ariaslib/args/Arguments.java b/src/main/java/dev/zontreck/ariaslib/args/Arguments.java new file mode 100644 index 0000000..3499274 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/args/Arguments.java @@ -0,0 +1,63 @@ +package dev.zontreck.ariaslib.args; + +import java.util.HashMap; +import java.util.Map; + +public class Arguments implements Cloneable +{ + private Map> args = new HashMap<>(); + + /** + * Set the argument in the args list + * @param arg + */ + public void setArg(Argument arg) { + args.put(arg.name, arg); + } + + /** + * Checks for and returns the argument + * + * @param argName The argument's name + * @return The argument instance, or null if not found + */ + public Argument getArg(String argName) { + if (hasArg(argName)) + return args.get(argName); + else return null; + } + + /** + * Checks if the argument is set. + * + * @param argName The argument's name to check for + * @return True if the argument is present. This does not indicate if the argument has a value + */ + public boolean hasArg(String argName) { + return args.containsKey(argName); + } + + /** + * Checks the argument (if it exists), for whether a value is set + * + * @param argName This is the argument name + * @return True if a value is set + * @throws IllegalArgumentException If there is no such argument + */ + public boolean argHasValue(String argName) throws IllegalArgumentException { + if (hasArg(argName)) { + return getArg(argName).hasValue; + } else throw new IllegalArgumentException(("No such argument")); + } + + @Override + public Arguments clone() { + Arguments arg = new Arguments(); + for(Map.Entry> entry : args.entrySet()) + { + arg.setArg(entry.getValue().clone()); + } + + return arg; + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/args/ArgumentsBuilder.java b/src/main/java/dev/zontreck/ariaslib/args/ArgumentsBuilder.java new file mode 100644 index 0000000..cf414bd --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/args/ArgumentsBuilder.java @@ -0,0 +1,20 @@ +package dev.zontreck.ariaslib.args; + +public class ArgumentsBuilder { + private Arguments args = new Arguments(); + + public static ArgumentsBuilder builder() { + return new ArgumentsBuilder(); + } + + public ArgumentsBuilder withArgument(Argument arg) { + args.setArg(arg); + return this; + } + + public Arguments build() + { + return args; + } + +} diff --git a/src/main/java/dev/zontreck/ariaslib/args/ArgumentsParser.java b/src/main/java/dev/zontreck/ariaslib/args/ArgumentsParser.java new file mode 100644 index 0000000..8f6bbf5 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/args/ArgumentsParser.java @@ -0,0 +1,99 @@ +package dev.zontreck.ariaslib.args; + +public class ArgumentsParser { + + /** + * Parses and returns the arguments list with keeping defaults in mind + * @param args + * @param defaults + * @return Arguments with defaults set + */ + public static Arguments parseArguments(String[] args, Arguments defaults) { + Arguments arguments = defaults.clone(); + for (int i = 0; i < args.length; i++) { + Argument arg = parseArgument(args[i]); + if (arg != null) { + Argument defaultArg = null; + if (defaults.hasArg(arg.name)) { + defaultArg = defaults.getArg(arg.name); + } + + if (!arg.hasValue) { + if (defaultArg != null) { + arg = defaultArg; + } + } + + arguments.setArg(arg); + } + } + return arguments; + } + + /** + * Parses and returns an argument with a type set + * @param arg The argument to parse with double tack + * @return Typed Argument + * @throws IllegalArgumentException when no type matches and the input is malformed in some way + */ + public static Argument parseArgument(String arg) { + if (arg.startsWith("--")) { + String[] parts = arg.split("="); + String name = getNamePart(parts[0]); + if (parts.length == 1) { + return new BooleanArgument(name); + + } else if (parts.length == 2) { + String value = getValuePart(parts[1]); + ArgumentType typeOfArg = getArgumentType(value); + switch(typeOfArg) + { + case INTEGER: + { + return new IntegerArgument(name, Integer.parseInt(value)); + } + case LONG: + { + return new LongArgument(name, Long.parseLong(value)); + } + case BOOLEAN: + { + return new BooleanArgument(name); + } + default: + { + return new StringArgument(name, value); + } + } + } else throw new IllegalArgumentException("The argument is malformed. Remember to use --arg=val, or --toggle"); + } else { + throw new IllegalArgumentException("Not a valid argument format"); + } + } + + protected static String getNamePart(String entry) { + return entry.substring(2); + } + + protected static String getValuePart(String entry) { + return entry; + } + + protected static ArgumentType getArgumentType(String input) { + try { + Integer.parseInt(input); + return ArgumentType.INTEGER; + }catch(Exception e){} + try{ + Long.parseLong(input); + return ArgumentType.LONG; + }catch(Exception E){ + + } + + if(input.isEmpty()) + return ArgumentType.BOOLEAN; + else return ArgumentType.STRING; + } +} + diff --git a/src/main/java/dev/zontreck/ariaslib/args/BooleanArgument.java b/src/main/java/dev/zontreck/ariaslib/args/BooleanArgument.java new file mode 100644 index 0000000..cad4620 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/args/BooleanArgument.java @@ -0,0 +1,35 @@ +package dev.zontreck.ariaslib.args; + +public class BooleanArgument extends Argument { + private boolean value; + + /** + * Initializes a boolean only command line toggle + * + * @param name The option name + */ + public BooleanArgument(String name) { + super(name); + + this.hasValue = true; + this.value = true; + } + + @Override + public Boolean getValue() { + return value; + } + + @Override + public ArgumentType getType() { + return ArgumentType.BOOLEAN; + } + + + @Override + public String toString() { + return "BooleanArgument{" + + name + "=true" + + '}'; + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/args/IntegerArgument.java b/src/main/java/dev/zontreck/ariaslib/args/IntegerArgument.java new file mode 100644 index 0000000..9c7430f --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/args/IntegerArgument.java @@ -0,0 +1,30 @@ +package dev.zontreck.ariaslib.args; + +public class IntegerArgument extends Argument { + private int value; + + public IntegerArgument(String name, int value) { + super(name); + this.hasValue = true; + this.value = value; + } + + @Override + public ArgumentType getType() { + return ArgumentType.INTEGER; + } + + @Override + public Integer getValue() { + return value; + } + + + @Override + public String toString() { + return "IntegerArgument{" + + name + "=" + + value + + '}'; + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/args/LongArgument.java b/src/main/java/dev/zontreck/ariaslib/args/LongArgument.java new file mode 100644 index 0000000..2541d59 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/args/LongArgument.java @@ -0,0 +1,30 @@ +package dev.zontreck.ariaslib.args; + +public class LongArgument extends Argument { + private long value; + + public LongArgument(String name, long value) { + super(name); + this.hasValue = true; + this.value = value; + } + + @Override + public ArgumentType getType() { + return ArgumentType.LONG; + } + + @Override + public Long getValue() { + return value; + } + + + @Override + public String toString() { + return "LongArgument{" + + name + "=" + + value + + '}'; + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/args/StringArgument.java b/src/main/java/dev/zontreck/ariaslib/args/StringArgument.java new file mode 100644 index 0000000..8c17782 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/args/StringArgument.java @@ -0,0 +1,30 @@ +package dev.zontreck.ariaslib.args; + +public class StringArgument extends Argument { + + private String value; + + public StringArgument(String name, String value) { + super(name); + this.value = value; + this.hasValue = true; + } + + @Override + public String getValue() { + return value; + } + + @Override + public ArgumentType getType() { + return ArgumentType.STRING; + } + + @Override + public String toString() { + return "StringArgument{" + + name + "=" + + value + + '}'; + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/exceptions/EventRegistrationException.java b/src/main/java/dev/zontreck/ariaslib/exceptions/EventRegistrationException.java new file mode 100644 index 0000000..7446137 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/exceptions/EventRegistrationException.java @@ -0,0 +1,7 @@ +package dev.zontreck.ariaslib.exceptions; + +public class EventRegistrationException extends Exception{ + public EventRegistrationException(String message){ + super(message); + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/exceptions/WrongArgumentTypeException.java b/src/main/java/dev/zontreck/ariaslib/exceptions/WrongArgumentTypeException.java new file mode 100644 index 0000000..4ab8f8a --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/exceptions/WrongArgumentTypeException.java @@ -0,0 +1,7 @@ +package dev.zontreck.ariaslib.exceptions; + + +public class WrongArgumentTypeException extends Exception +{ + +} diff --git a/src/main/java/dev/zontreck/ariaslib/file/AriaIO.java b/src/main/java/dev/zontreck/ariaslib/file/AriaIO.java new file mode 100644 index 0000000..7cefb9a --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/file/AriaIO.java @@ -0,0 +1,34 @@ +package dev.zontreck.ariaslib.file; + +import java.io.*; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class AriaIO { + public static void write(Path fileName, Entry folder) { + try { + DataOutputStream dos = new DataOutputStream(new FileOutputStream(fileName.toFile())); + folder.write(dos); + dos.close(); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static Entry read(Path fileName) { + try { + DataInputStream dis = new DataInputStream(new FileInputStream(fileName.toFile())); + return Entry.read(dis); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static Path resolveDataFile(String main) { + return Paths.get(main + ".aria"); + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/file/Entry.java b/src/main/java/dev/zontreck/ariaslib/file/Entry.java new file mode 100644 index 0000000..8eaba86 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/file/Entry.java @@ -0,0 +1,281 @@ +package dev.zontreck.ariaslib.file; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * An entry in the serialized file + */ +public class Entry { + public static final byte YES = 1; + public static final byte NO = 0; + + public EntryType type; + public String name; + public K value; + + public Entry(K v, String name) { + value = v; + this.name = name; + if (v instanceof String) { + type = EntryType.STRING; + } else if (v instanceof Integer) { + type = EntryType.INT; + } else if (v instanceof List) { + type = EntryType.FOLDER; + } else if (v instanceof Boolean) { + type = EntryType.BOOL; + } else if (v instanceof Long) { + type = EntryType.LONG; + } else if (v instanceof Short) { + type = EntryType.SHORT; + } else if (v instanceof Byte) { + type = EntryType.BYTE; + } else if (v instanceof Double) { + type = EntryType.DOUBLE; + } else if (v instanceof Float) { + type = EntryType.FLOAT; + } else if (v instanceof int[]) { + type = EntryType.INT_ARRAY; + } else if (v instanceof String[]) { + type = EntryType.STRING_ARRAY; + } else if (v instanceof byte[]) { + type = EntryType.BYTE_ARRAY; + } else if (v instanceof long[]) { + type = EntryType.LONG_ARRAY; + } else { + type = EntryType.INVALID; + } + } + + private Entry() { + } + + public static Entry read(DataInputStream dis) throws IOException { + EntryType et = EntryType.of(dis.readByte()); + int nameLen = dis.readInt(); + byte[] nm = new byte[nameLen]; + for (int i = 0; i < nameLen; i++) { + nm[i] = dis.readByte(); + } + Entry work = new Entry<>(); + work.type = et; + work.name = new String(nm); + //System.out.println("Read start: " + work.name + " [ " + work.type.toString() + " ]"); + + switch (et) { + case FOLDER: { + Entry> entries = (Entry>) work; + entries.value = new ArrayList<>(); + + int numEntries = dis.readInt(); + for (int i = 0; i < numEntries; i++) { + entries.value.add(Entry.read(dis)); + } + + break; + } + case STRING: { + Entry w = (Entry) work; + int vLen = dis.readInt(); + byte[] x = new byte[vLen]; + for (int i = 0; i < vLen; i++) { + x[i] = dis.readByte(); + } + w.value = new String(x); + break; + } + case INT: { + Entry w = (Entry) work; + w.value = dis.readInt(); + break; + } + case BOOL: { + Entry w = (Entry) work; + byte b = dis.readByte(); + if (b == YES) w.value = true; + else w.value = false; + + break; + } + case LONG: { + Entry w = (Entry) work; + w.value = dis.readLong(); + + break; + } + case SHORT: { + Entry w = (Entry) work; + w.value = dis.readShort(); + + break; + } + + case BYTE: { + Entry w = (Entry) work; + w.value = dis.readByte(); + break; + } + case DOUBLE: { + Entry w = (Entry) work; + w.value = dis.readDouble(); + break; + } + case FLOAT: { + Entry w = (Entry) work; + w.value = dis.readFloat(); + break; + } + case INT_ARRAY: { + Entry w = (Entry) work; + int num = dis.readInt(); + w.value = new int[num]; + + for (int i = 0; i < num; i++) { + w.value[i] = dis.readInt(); + } + break; + } + case STRING_ARRAY: { + Entry w = (Entry) work; + int num = dis.readInt(); + w.value = new String[num]; + for (int i = 0; i < num; i++) { + int len = dis.readInt(); + byte[] bStr = new byte[len]; + for (int j = 0; j < len; j++) { + bStr[j] = dis.readByte(); + } + w.value[i] = new String(bStr); + } + break; + } + case BYTE_ARRAY: { + Entry w = (Entry) work; + int num = dis.readInt(); + w.value = new byte[num]; + for (int i = 0; i < num; i++) { + w.value[i] = dis.readByte(); + } + break; + } + case LONG_ARRAY: { + Entry w = (Entry) work; + int num = dis.readInt(); + w.value = new long[num]; + for (int i = 0; i < num; i++) { + w.value[i] = dis.readLong(); + } + break; + } + } + + //System.out.println("Read finished: " + work.name + " [ " + work.type.toString() + " ]"); + + return work; + } + + public void write(DataOutputStream dos) throws IOException { + + dos.writeByte((int) type.value); + byte[] nameBytes = name.getBytes(); + dos.writeInt(nameBytes.length); + dos.write(nameBytes); + + switch (type) { + case FOLDER: { + List> entries = (List>) value; + dos.writeInt(entries.size()); + for (Entry x : + entries) { + x.write(dos); + } + + break; + } + case STRING: { + String s = (String) value; + byte[] bS = s.getBytes(); + dos.writeInt(bS.length); + dos.write(bS); + + break; + } + case INT: { + dos.writeInt((Integer) value); + + break; + } + case BOOL: { + boolean x = (Boolean) value; + + if (x) dos.writeByte(YES); + else dos.writeByte(NO); + + break; + } + case LONG: { + dos.writeLong((Long) value); + + break; + } + case SHORT: { + dos.writeShort((Short) value); + + break; + } + case BYTE: { + dos.write((Byte) value); + break; + } + case DOUBLE: { + dos.writeDouble((Double) value); + break; + } + case FLOAT: { + dos.writeFloat((Float) value); + break; + } + case INT_ARRAY: { + int[] arr = (int[]) value; + dos.writeInt(arr.length); + for (int x : arr + ) { + dos.writeInt(x); + } + break; + } + case STRING_ARRAY: { + String[] arr = (String[]) value; + dos.writeInt(arr.length); + for (String s : arr) { + byte[] bArr = s.getBytes(); + dos.writeInt(bArr.length); + dos.write(bArr); + } + break; + } + case BYTE_ARRAY: { + byte[] arr = (byte[]) value; + dos.writeInt(arr.length); + for (byte b : arr) { + dos.write(b); + } + break; + } + case LONG_ARRAY: { + long[] arr = (long[]) value; + dos.writeInt(arr.length); + for (long L : arr) { + dos.writeLong(L); + } + + break; + } + } + } + +} \ No newline at end of file diff --git a/src/main/java/dev/zontreck/ariaslib/file/EntryType.java b/src/main/java/dev/zontreck/ariaslib/file/EntryType.java new file mode 100644 index 0000000..4ddcdae --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/file/EntryType.java @@ -0,0 +1,36 @@ +package dev.zontreck.ariaslib.file; + +import java.util.Arrays; +import java.util.stream.Collectors; + +public enum EntryType { + FOLDER(0), + STRING(1), + INT(2), + BOOL(3), + LONG(4), + SHORT(5), + BYTE(6), + DOUBLE(7), + FLOAT(8), + INT_ARRAY(9), + STRING_ARRAY(10), + BYTE_ARRAY(11), + LONG_ARRAY(12), + + INVALID(255); + + public byte value; + EntryType(int v) + { + value = (byte)v; + } + + public static EntryType of(byte b) + { + return Arrays.stream(values()) + .filter(c->c.value == b) + .collect(Collectors.toList()) + .get(0); + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/file/EntryUtils.java b/src/main/java/dev/zontreck/ariaslib/file/EntryUtils.java new file mode 100644 index 0000000..3be4678 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/file/EntryUtils.java @@ -0,0 +1,118 @@ +package dev.zontreck.ariaslib.file; + +import java.util.UUID; + +public class EntryUtils { + public static Entry mkStr(String name, String value) + { + return new Entry(value, name); + } + public static String getStr(Entry e) + { + Entry eS = (Entry) e; + return eS.value; + } + public static Entry mkInt(String name, int value) + { + return new Entry(value, name); + } + public static int getInt(Entry e) + { + Entry eS = (Entry) e; + return eS.value; + } + public static Entry mkBool(String name, boolean value) + { + return new Entry(value, name); + } + public static boolean getBool(Entry e) + { + Entry eS = (Entry) e; + return eS.value; + } + public static Entry mkLong(String name, long value) + { + return new Entry(value, name); + } + public static long getLong(Entry e) + { + Entry eS = (Entry) e; + return eS.value; + } + public static Entry mkShort(String name, short value) + { + return new Entry(value, name); + } + public static short getShort(Entry e) + { + Entry eS = (Entry) e; + return eS.value; + } + public static Entry mkByte(String name, byte value) + { + return new Entry(value, name); + } + public static byte getByte(Entry e) + { + Entry eS = (Entry) e; + return eS.value; + } + public static Entry mkDouble(String name, double value) + { + return new Entry(value, name); + } + public static double getDouble(Entry e) + { + Entry eS = (Entry) e; + return eS.value; + } + public static Entry mkFloat(String name, float value) + { + return new Entry(value, name); + } + public static float getFloat(Entry e) + { + Entry eS = (Entry) e; + return eS.value; + } + public static Entry mkIntArray(String name, int[] value) + { + return new Entry(value, name); + } + public static int[] getIntArray(Entry e) + { + Entry eS = (Entry) e; + return eS.value; + } + public static Entry mkStringArray(String name, String[] value) + { + return new Entry(value, name); + } + public static String[] getStringArray(Entry e) + { + Entry eS = (Entry) e; + return eS.value; + } + public static Entry mkByteArray(String name, byte[] value) + { + return new Entry(value, name); + } + public static byte[] getByteArray(Entry e) + { + Entry eS = (Entry) e; + return eS.value; + } + public static Entry mkUUID(String name, UUID ID) + { + long[] uid = new long[2]; + uid[0] = ID.getLeastSignificantBits(); + uid[1] = ID.getMostSignificantBits(); + return new Entry(uid, name); + } + + public static UUID getUUID(Entry e) + { + Entry uid = (Entry) e; + return new UUID(uid.value[1], uid.value[0]); + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/file/Folder.java b/src/main/java/dev/zontreck/ariaslib/file/Folder.java new file mode 100644 index 0000000..d295e87 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/file/Folder.java @@ -0,0 +1,42 @@ +package dev.zontreck.ariaslib.file; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Folder +{ + + public static void add(Entry e, Entry item) + { + ((Entry>)e).value.add(item); + } + + public static void remove(Entry e, Entry item) + { + ((Entry>)e).value.remove(item); + } + + public static Entry getEntry(Entry item, String name) + { + List ret = ((Entry>)item).value; + if(ret.size()>0) + { + for (Entry ent : + ret) { + if(ent.name.equals(name))return ent; + } + } + return null; + } + + public static int size(Entry e) + { + return ((Entry>)e).value.size(); + } + + public static Entry> getNew(String name) + { + return new Entry<>(new ArrayList(), name); + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/html/Bootstrap.java b/src/main/java/dev/zontreck/ariaslib/html/Bootstrap.java new file mode 100644 index 0000000..0fdb0b2 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/html/Bootstrap.java @@ -0,0 +1,283 @@ +package dev.zontreck.ariaslib.html; + +import dev.zontreck.ariaslib.html.bootstrap.Color; +import dev.zontreck.ariaslib.html.bootstrap.Icons; +import dev.zontreck.ariaslib.html.bootstrap.Size; +import dev.zontreck.ariaslib.util.Percent; + +public class Bootstrap { + public static class Border { + public Side side; + public int width = 1; + public boolean usesSides = false; + public Colors colors; + public boolean invert; + + public static Border make() { + return new Border(); + } + + public Border withColor(Colors color) { + this.colors = color.withPrefix("border"); + return this; + } + + public Border widthSide(Side side) { + this.side = side; + usesSides = true; + return this; + } + + public Border withWidth(int width) { + this.width = width; + return this; + } + + /** + * Removes borders instead of adding + */ + public Border setInverted() { + invert = true; + return this; + } + + public void apply(HTMLElementBuilder elem) { + elem.addClass("border"); + + colors.apply(elem); + + if (usesSides) { + elem.addClass("border-" + side.name().toLowerCase() + (invert ? "-0" : "")); + } else { + if (invert) elem.addClass("border-0"); + } + } + + + public enum Side { + Start, + End, + Top, + Bottom + } + } + + public static class Opacity { + public Percent value; + public String prefix; + + public static Opacity make() { + return new Opacity(); + } + + public Opacity withPercent(Percent val) { + value = val; + return this; + } + + public Opacity withPrefix(String pref) { + this.prefix = pref; + return this; + } + + public void apply(HTMLElementBuilder builder) { + builder.addClass((prefix != "" ? prefix + "-" : "") + "opacity-" + value.get()); + } + } + + public static class Colors { + public Color color; + public boolean emphasis; + public boolean subtle; + public String prefix; + + public static Colors make() { + return new Colors(); + } + + public Colors withColor(Color color) { + this.color = color; + return this; + } + + public Colors setEmphasis() { + emphasis = true; + return this; + } + + public Colors setSubtle() { + subtle = true; + return this; + } + + public Colors withPrefix(String prefix) { + this.prefix = prefix; + return this; + } + + public void apply(HTMLElementBuilder builder) { + builder.addClass(((prefix != "") ? prefix + "-" : "") + color.name().toLowerCase() + (emphasis ? "-emphasis" : "") + (subtle ? "-subtle" : "")); + } + } + + public static class Background { + public Colors color; + public Opacity opacity; + public boolean gradient; + + public static Background make() { + return new Background(); + } + + public Background withColor(Colors color) { + this.color = color.withPrefix("bg"); + return this; + } + + public Background withOpacity(Opacity op) { + this.opacity = op.withPrefix("bg"); + return this; + } + + public Background setGradient() { + gradient = true; + return this; + } + + + public void apply(HTMLElementBuilder builder) { + color.apply(builder); + opacity.apply(builder); + if (gradient) + builder.addClass(".bg-gradient"); + } + } + + public static class Shadow { + public Size size; + + public static Shadow make() { + return new Shadow(); + } + + public Shadow withSize(Size size) { + this.size = size; + return this; + } + + public void apply(HTMLElementBuilder builder) { + builder.addClass("shadow" + size.sizeText()); + } + } + + public static class FocusRing { + public Colors color; + + public static FocusRing make() { + return new FocusRing(); + } + + public FocusRing withColor(Colors color) { + this.color = color.withPrefix("focus-ring"); + return this; + } + + public void apply(HTMLElementBuilder builder) { + builder.addClass("focus-ring"); + color.apply(builder); + } + } + + public static class Link { + public Colors color; + + public static Link make() { + return new Link(); + } + + public Link withColor(Colors color) { + this.color = color.withPrefix("link"); + return this; + } + + public void apply(HTMLElementBuilder builder) { + color.apply(builder); + } + } + + public static class Toast { + public Icons icon; + public HTMLElementBuilder toastHeader; + public HTMLElementBuilder toastBody; + + public Toast() { + toastHeader = new HTMLElementBuilder("div").addClass("toast-header"); + toastHeader.addChild("svg").addClass("bi").addClass(icon.getClassName()).addClass("rounded"); + toastHeader.addChild("strong").addClass("me-auto"); + toastHeader.addChild("small").withText("Text?"); + toastHeader.addChild("button").withAttribute("type", "button").addClass("btn-close").withAttribute("data-bs-dismiss", "toast").withAttribute("aria-label", "Close"); + + toastBody = new HTMLElementBuilder("div").addClass("toast-body"); + } + + public static Toast make() { + return new Toast(); + } + + public Toast withIcon(Icons icon) { + this.icon = icon; + return this; + } + + public void apply(HTMLElementBuilder builder) { + HTMLElementBuilder toast = builder.addChild("div").addClass("toast").withAttribute("role", "alert").withAttribute("aria-live", "assertive").withAttribute("aria-atomic", "true"); + toast.addChild(toastHeader); + toast.addChild(toastBody); + } + } + + public static class Button { + public Colors color; + public boolean outline; + public Size size; + + public static Button make() { + return new Button(); + } + + public Button withColor(Colors color) { + this.color = color; + return this; + } + + public Button setOutline() { + outline = true; + return this; + } + + public Button withSize(Size size) { + this.size = size; + return this; + } + + + public void apply(HTMLElementBuilder builder) { + builder.addClass("btn"); + + if (outline) { + color.withPrefix("btn-outline"); + } else color.withPrefix("btn"); + + color.apply(builder); + if (size != Size.Regular) + builder.addClass("btn" + size.sizeText()); + } + + } + + public static class Disabled { + public static void setDisabled(HTMLElementBuilder builder) { + builder.withAttribute("disabled"); + } + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/html/ClassAttribute.java b/src/main/java/dev/zontreck/ariaslib/html/ClassAttribute.java new file mode 100644 index 0000000..6d17d0e --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/html/ClassAttribute.java @@ -0,0 +1,8 @@ +package dev.zontreck.ariaslib.html; + +// Class attribute class for HTML element classes +class ClassAttribute extends HTMLAttribute { + public ClassAttribute(String value) { + super("class", value); + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/html/DOM.java b/src/main/java/dev/zontreck/ariaslib/html/DOM.java new file mode 100644 index 0000000..aa32b54 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/html/DOM.java @@ -0,0 +1,55 @@ +package dev.zontreck.ariaslib.html; + +public class DOM { + + + public static HTMLElementBuilder beginBootstrapDOM(String pageTitle) { + HTMLElementBuilder builder = new HTMLElementBuilder("!doctype").withText("html"); + + HTMLElementBuilder html = builder.getOrCreate("html"); + + HTMLElementBuilder head = html.getOrCreate("head"); + + head.addChild("meta").withAttribute("charset", "utf-8"); + + head.addChild("meta").withAttribute("name", "viewport").withAttribute("content", "width=device-width, initial-scale=1"); + + head.getOrCreate("link").withAttribute("href", "https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css").withAttribute("integrity", "sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM").withAttribute("crossorigin", "anonymous").withAttribute("rel", "stylesheet"); + + head.addClass("link").withAttribute("rel", "stylesheet").withAttribute("href", "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css"); + + head.getOrCreate("title").withText(pageTitle); + + HTMLElementBuilder body = html.getOrCreate("body"); + body.addChild("script").withAttribute("src", "https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js").withAttribute("integrity", "sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz").withAttribute("crossorigin", "anonymous").withText(" "); + + body.addChild("script").withAttribute("src", "https://code.jquery.com/jquery-3.7.0.min.js").withAttribute("crossorigin", "anonymous").withText(" "); + + body.addChild("style").withText("\n" + + " .command-popover{\n" + + " --bs-popover-header-bg: var(--bs-info);\n" + + " --bs-popover-header-color: var(--bs-dark);\n" + + " --bs-popover-bg: var(--bs-dark);\n" + + " --bs-popover-body-color: var(--bs-light);\n" + + " }\n"); + + + return builder; + + } + + public static void addPopOverScan(HTMLElementBuilder builder) { + builder.getChildByTagName("html").getChildByTagName("body").addChild("script").withText("" + + "function scanPopOver()" + + "{" + + "var popoverTriggerList = document.querySelectorAll('[data-bs-toggle=\"popover\"]');\n" + + "var popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl));" + + "" + + "}"); + } + + + public static String closeHTML() { + return ""; + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/html/HTMLAttribute.java b/src/main/java/dev/zontreck/ariaslib/html/HTMLAttribute.java new file mode 100644 index 0000000..73c1eca --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/html/HTMLAttribute.java @@ -0,0 +1,24 @@ +package dev.zontreck.ariaslib.html; + +// Attribute class for HTML element attributes +class HTMLAttribute { + private String name; + private String value; + + public HTMLAttribute(String name, String value) { + this.name = name; + this.value = value; + } + + public HTMLAttribute(String name) { + this(name, null); + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } +} \ No newline at end of file diff --git a/src/main/java/dev/zontreck/ariaslib/html/HTMLElement.java b/src/main/java/dev/zontreck/ariaslib/html/HTMLElement.java new file mode 100644 index 0000000..2950483 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/html/HTMLElement.java @@ -0,0 +1,72 @@ +package dev.zontreck.ariaslib.html; + +import java.util.List; + + +// HTML element class supporting tag attributes +public class HTMLElement { + private String tagName; + private String text; + private List attributes; + private List children; + private boolean isEmptyElement; + + public HTMLElement ( String tagName , String text , List attributes , List children , boolean isEmptyElement ) { + this.tagName = tagName; + this.text = text; + this.attributes = attributes; + this.children = children; + this.isEmptyElement = isEmptyElement; + } + + public String getTagName ( ) { + return tagName; + } + + public String generateHTML ( ) { + StringBuilder builder = new StringBuilder ( ); + + if ( "!doctype".equalsIgnoreCase ( tagName ) ) { + builder.append ( "<" ).append ( tagName ).append ( " " ).append ( text ).append ( ">\n" ); + for ( HTMLElement child : children ) { + builder.append ( child.generateHTML ( ) ); + } + return builder.toString ( ); + } + + builder.append ( "<" ).append ( tagName ); + + for ( HTMLAttribute attribute : attributes ) { + builder.append ( " " ) + .append ( attribute.getName ( ) ); + + String value = attribute.getValue ( ); + if ( value != null ) { + builder.append ( "=\"" ).append ( value ).append ( "\"" ); + } + } + + /* + if ( isEmptyElement ) { + builder.append ( " />\n" ); + return builder.toString ( ); + }*/ + + builder.append ( ">" ); + + if ( text != null ) { + builder.append ( text ); + } + + if ( ! isEmptyElement ) { + for ( HTMLElement child : children ) { + builder.append ( child.generateHTML ( ) ); + } + } + + + builder.append ( "\n" ); + + return builder.toString ( ); + } +} \ No newline at end of file diff --git a/src/main/java/dev/zontreck/ariaslib/html/HTMLElementBuilder.java b/src/main/java/dev/zontreck/ariaslib/html/HTMLElementBuilder.java new file mode 100644 index 0000000..461adba --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/html/HTMLElementBuilder.java @@ -0,0 +1,118 @@ +package dev.zontreck.ariaslib.html; + +import java.util.ArrayList; +import java.util.List; + +// Builder class for building HTML elements +public class HTMLElementBuilder { + private String tagName; + private String text; + private List attributes; + private List childElementBuilders; + + public HTMLElementBuilder ( String tagName ) { + this.tagName = tagName; + this.attributes = new ArrayList<> ( ); + this.childElementBuilders = new ArrayList<> ( ); + } + + public HTMLElementBuilder withText ( String text ) { + this.text = text; + return this; + } + + public HTMLElementBuilder withAttribute ( String name , String value ) { + HTMLAttribute attribute = new HTMLAttribute ( name , value ); + this.attributes.add ( attribute ); + return this; + } + + public HTMLElementBuilder withAttribute ( String name ) { + HTMLAttribute attribute = new HTMLAttribute ( name ); + this.attributes.add ( attribute ); + return this; + } + + public HTMLElementBuilder addClass ( String className ) { + ClassAttribute classAttribute = getClassAttribute ( ); + if ( classAttribute == null ) { + classAttribute = new ClassAttribute ( className ); + this.attributes.add ( classAttribute ); + } + else { + String existingValue = classAttribute.getValue ( ); + classAttribute = new ClassAttribute ( existingValue + " " + className ); + this.attributes.removeIf ( attr -> attr.getName ( ).equalsIgnoreCase ( "class" ) ); + this.attributes.add ( classAttribute ); + } + return this; + } + + private ClassAttribute getClassAttribute ( ) { + for ( HTMLAttribute attribute : attributes ) { + if ( attribute instanceof ClassAttribute ) { + return ( ClassAttribute ) attribute; + } + } + return null; + } + + public HTMLElementBuilder addChild ( HTMLElementBuilder childBuilder ) { + childElementBuilders.add ( childBuilder ); + return this; + } + + public HTMLElementBuilder addChild ( String tagName ) { + HTMLElementBuilder childBuilder = new HTMLElementBuilder ( tagName ); + childElementBuilders.add ( childBuilder ); + return childBuilder; + } + + public HTMLElementBuilder getOrCreate ( String tagName ) { + HTMLElementBuilder childBuilder = getChildByTagName ( tagName ); + if ( childBuilder == null ) { + childBuilder = addChild ( tagName ); + } + return childBuilder; + } + + public HTMLElementBuilder getChildByTagName ( String tagName ) { + return getChildByTagName ( tagName , 0 ); + } + + public HTMLElementBuilder getChildByTagName ( String tagName , int index ) { + List matchingChildBuilders = new ArrayList<> ( ); + + for ( HTMLElementBuilder builder : childElementBuilders ) { + if ( builder.tagName.equalsIgnoreCase ( tagName ) ) { + matchingChildBuilders.add ( builder ); + } + } + + if ( matchingChildBuilders.size ( ) > index ) { + return matchingChildBuilders.get ( index ); + } + + return null; + } + + private boolean hasTextOrChildren ( ) { + return text != null || ! childElementBuilders.isEmpty ( ); + } + + public HTMLElement build ( ) { + List children = buildChildren ( ); + boolean isEmptyElement = ! hasTextOrChildren ( ); + return new HTMLElement ( tagName , text , attributes , children , isEmptyElement ); + } + + private List buildChildren ( ) { + List children = new ArrayList<> ( ); + + for ( HTMLElementBuilder builder : childElementBuilders ) { + children.add ( builder.build ( ) ); + } + + return children; + } +} \ No newline at end of file diff --git a/src/main/java/dev/zontreck/ariaslib/html/bootstrap/Color.java b/src/main/java/dev/zontreck/ariaslib/html/bootstrap/Color.java new file mode 100644 index 0000000..2949cda --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/html/bootstrap/Color.java @@ -0,0 +1,46 @@ +package dev.zontreck.ariaslib.html.bootstrap; + +public enum Color +{ + /** + * Dark Blue + */ + Primary, + + /** + * Dark Gray + */ + Secondary, + + /** + * Dark Green + */ + Success, + + /** + * Dark Red + */ + Danger, + + /** + * Yellow + */ + Warning, + + /** + * Light Blue + */ + Info, + + /** + * Black + */ + Dark, + + /** + * Semi-gray + */ + Light, + Black, + White +} diff --git a/src/main/java/dev/zontreck/ariaslib/html/bootstrap/Icons.java b/src/main/java/dev/zontreck/ariaslib/html/bootstrap/Icons.java new file mode 100644 index 0000000..174c4f2 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/html/bootstrap/Icons.java @@ -0,0 +1,1969 @@ +package dev.zontreck.ariaslib.html.bootstrap; + +/** + * Bootstrap Icons Enumerable + */ +@SuppressWarnings ( "unused" ) +public enum Icons { + + Icon_123, + Icon_alarm_fill, + Icon_alarm, + Icon_align_bottom, + Icon_align_center, + Icon_align_end, + Icon_align_middle, + Icon_align_start, //before { content: "\f107"; } + Icon_align_top, //before { content: "\f108"; } + Icon_alt, //before { content: "\f109"; } + Icon_app_indicator, //before { content: "\f10a"; } + Icon_app, //before { content: "\f10b"; } + Icon_archive_fill, //before { content: "\f10c"; } + Icon_archive, //before { content: "\f10d"; } + Icon_arrow_90deg_down, //before { content: "\f10e"; } + Icon_arrow_90deg_left, //before { content: "\f10f"; } + Icon_arrow_90deg_right, //before { content: "\f110"; } + Icon_arrow_90deg_up, //before { content: "\f111"; } + Icon_arrow_bar_down, //before { content: "\f112"; } + Icon_arrow_bar_left, //before { content: "\f113"; } + Icon_arrow_bar_right, //before { content: "\f114"; } + Icon_arrow_bar_up, //before { content: "\f115"; } + Icon_arrow_clockwise, //before { content: "\f116"; } + Icon_arrow_counterclockwise, //before { content: "\f117"; } + Icon_arrow_down_circle_fill, //before { content: "\f118"; } + Icon_arrow_down_circle, //before { content: "\f119"; } + Icon_arrow_down_left_circle_fill, //before { content: "\f11a"; } + Icon_arrow_down_left_circle, //before { content: "\f11b"; } + Icon_arrow_down_left_square_fill, //before { content: "\f11c"; } + Icon_arrow_down_left_square, //before { content: "\f11d"; } + Icon_arrow_down_left, //before { content: "\f11e"; } + Icon_arrow_down_right_circle_fill, //before { content: "\f11f"; } + Icon_arrow_down_right_circle, //before { content: "\f120"; } + Icon_arrow_down_right_square_fill, //before { content: "\f121"; } + Icon_arrow_down_right_square, //before { content: "\f122"; } + Icon_arrow_down_right, //before { content: "\f123"; } + Icon_arrow_down_short, //before { content: "\f124"; } + Icon_arrow_down_square_fill, //before { content: "\f125"; } + Icon_arrow_down_square, //before { content: "\f126"; } + Icon_arrow_down_up, //before { content: "\f127"; } + Icon_arrow_down, //before { content: "\f128"; } + Icon_arrow_left_circle_fill, //before { content: "\f129"; } + Icon_arrow_left_circle, //before { content: "\f12a"; } + Icon_arrow_left_right, //before { content: "\f12b"; } + Icon_arrow_left_short, //before { content: "\f12c"; } + Icon_arrow_left_square_fill, //before { content: "\f12d"; } + Icon_arrow_left_square, //before { content: "\f12e"; } + Icon_arrow_left, //before { content: "\f12f"; } + Icon_arrow_repeat, //before { content: "\f130"; } + Icon_arrow_return_left, //before { content: "\f131"; } + Icon_arrow_return_right, //before { content: "\f132"; } + Icon_arrow_right_circle_fill, //before { content: "\f133"; } + Icon_arrow_right_circle, //before { content: "\f134"; } + Icon_arrow_right_short, //before { content: "\f135"; } + Icon_arrow_right_square_fill, //before { content: "\f136"; } + Icon_arrow_right_square, //before { content: "\f137"; } + Icon_arrow_right, //before { content: "\f138"; } + Icon_arrow_up_circle_fill, //before { content: "\f139"; } + Icon_arrow_up_circle, //before { content: "\f13a"; } + Icon_arrow_up_left_circle_fill, //before { content: "\f13b"; } + Icon_arrow_up_left_circle, //before { content: "\f13c"; } + Icon_arrow_up_left_square_fill, //before { content: "\f13d"; } + Icon_arrow_up_left_square, //before { content: "\f13e"; } + Icon_arrow_up_left, //before { content: "\f13f"; } + Icon_arrow_up_right_circle_fill, //before { content: "\f140"; } + Icon_arrow_up_right_circle, //before { content: "\f141"; } + Icon_arrow_up_right_square_fill, //before { content: "\f142"; } + Icon_arrow_up_right_square, //before { content: "\f143"; } + Icon_arrow_up_right, //before { content: "\f144"; } + Icon_arrow_up_short, //before { content: "\f145"; } + Icon_arrow_up_square_fill, //before { content: "\f146"; } + Icon_arrow_up_square, //before { content: "\f147"; } + Icon_arrow_up, //before { content: "\f148"; } + Icon_arrows_angle_contract, //before { content: "\f149"; } + Icon_arrows_angle_expand, //before { content: "\f14a"; } + Icon_arrows_collapse, //before { content: "\f14b"; } + Icon_arrows_expand, //before { content: "\f14c"; } + Icon_arrows_fullscreen, //before { content: "\f14d"; } + Icon_arrows_move, //before { content: "\f14e"; } + Icon_aspect_ratio_fill, //before { content: "\f14f"; } + Icon_aspect_ratio, //before { content: "\f150"; } + Icon_asterisk, //before { content: "\f151"; } + Icon_at, //before { content: "\f152"; } + Icon_award_fill, //before { content: "\f153"; } + Icon_award, //before { content: "\f154"; } + Icon_back, //before { content: "\f155"; } + Icon_backspace_fill, //before { content: "\f156"; } + Icon_backspace_reverse_fill, //before { content: "\f157"; } + Icon_backspace_reverse, //before { content: "\f158"; } + Icon_backspace, //before { content: "\f159"; } + Icon_badge_3d_fill, //before { content: "\f15a"; } + Icon_badge_3d, //before { content: "\f15b"; } + Icon_badge_4k_fill, //before { content: "\f15c"; } + Icon_badge_4k, //before { content: "\f15d"; } + Icon_badge_8k_fill, //before { content: "\f15e"; } + Icon_badge_8k, //before { content: "\f15f"; } + Icon_badge_ad_fill, //before { content: "\f160"; } + Icon_badge_ad, //before { content: "\f161"; } + Icon_badge_ar_fill, //before { content: "\f162"; } + Icon_badge_ar, //before { content: "\f163"; } + Icon_badge_cc_fill, //before { content: "\f164"; } + Icon_badge_cc, //before { content: "\f165"; } + Icon_badge_hd_fill, //before { content: "\f166"; } + Icon_badge_hd, //before { content: "\f167"; } + Icon_badge_tm_fill, //before { content: "\f168"; } + Icon_badge_tm, //before { content: "\f169"; } + Icon_badge_vo_fill, //before { content: "\f16a"; } + Icon_badge_vo, //before { content: "\f16b"; } + Icon_badge_vr_fill, //before { content: "\f16c"; } + Icon_badge_vr, //before { content: "\f16d"; } + Icon_badge_wc_fill, //before { content: "\f16e"; } + Icon_badge_wc, //before { content: "\f16f"; } + Icon_bag_check_fill, //before { content: "\f170"; } + Icon_bag_check, //before { content: "\f171"; } + Icon_bag_dash_fill, //before { content: "\f172"; } + Icon_bag_dash, //before { content: "\f173"; } + Icon_bag_fill, //before { content: "\f174"; } + Icon_bag_plus_fill, //before { content: "\f175"; } + Icon_bag_plus, //before { content: "\f176"; } + Icon_bag_x_fill, //before { content: "\f177"; } + Icon_bag_x, //before { content: "\f178"; } + Icon_bag, //before { content: "\f179"; } + Icon_bar_chart_fill, //before { content: "\f17a"; } + Icon_bar_chart_line_fill, //before { content: "\f17b"; } + Icon_bar_chart_line, //before { content: "\f17c"; } + Icon_bar_chart_steps, //before { content: "\f17d"; } + Icon_bar_chart, //before { content: "\f17e"; } + Icon_basket_fill, //before { content: "\f17f"; } + Icon_basket, //before { content: "\f180"; } + Icon_basket2_fill, //before { content: "\f181"; } + Icon_basket2, //before { content: "\f182"; } + Icon_basket3_fill, //before { content: "\f183"; } + Icon_basket3, //before { content: "\f184"; } + Icon_battery_charging, //before { content: "\f185"; } + Icon_battery_full, //before { content: "\f186"; } + Icon_battery_half, //before { content: "\f187"; } + Icon_battery, //before { content: "\f188"; } + Icon_bell_fill, //before { content: "\f189"; } + Icon_bell, //before { content: "\f18a"; } + Icon_bezier, //before { content: "\f18b"; } + Icon_bezier2, //before { content: "\f18c"; } + Icon_bicycle, //before { content: "\f18d"; } + Icon_binoculars_fill, //before { content: "\f18e"; } + Icon_binoculars, //before { content: "\f18f"; } + Icon_blockquote_left, //before { content: "\f190"; } + Icon_blockquote_right, //before { content: "\f191"; } + Icon_book_fill, //before { content: "\f192"; } + Icon_book_half, //before { content: "\f193"; } + Icon_book, //before { content: "\f194"; } + Icon_bookmark_check_fill, //before { content: "\f195"; } + Icon_bookmark_check, //before { content: "\f196"; } + Icon_bookmark_dash_fill, //before { content: "\f197"; } + Icon_bookmark_dash, //before { content: "\f198"; } + Icon_bookmark_fill, //before { content: "\f199"; } + Icon_bookmark_heart_fill, //before { content: "\f19a"; } + Icon_bookmark_heart, //before { content: "\f19b"; } + Icon_bookmark_plus_fill, //before { content: "\f19c"; } + Icon_bookmark_plus, //before { content: "\f19d"; } + Icon_bookmark_star_fill, //before { content: "\f19e"; } + Icon_bookmark_star, //before { content: "\f19f"; } + Icon_bookmark_x_fill, //before { content: "\f1a0"; } + Icon_bookmark_x, //before { content: "\f1a1"; } + Icon_bookmark, //before { content: "\f1a2"; } + Icon_bookmarks_fill, //before { content: "\f1a3"; } + Icon_bookmarks, //before { content: "\f1a4"; } + Icon_bookshelf, //before { content: "\f1a5"; } + Icon_bootstrap_fill, //before { content: "\f1a6"; } + Icon_bootstrap_reboot, //before { content: "\f1a7"; } + Icon_bootstrap, //before { content: "\f1a8"; } + Icon_border_all, //before { content: "\f1a9"; } + Icon_border_bottom, //before { content: "\f1aa"; } + Icon_border_center, //before { content: "\f1ab"; } + Icon_border_inner, //before { content: "\f1ac"; } + Icon_border_left, //before { content: "\f1ad"; } + Icon_border_middle, //before { content: "\f1ae"; } + Icon_border_outer, //before { content: "\f1af"; } + Icon_border_right, //before { content: "\f1b0"; } + Icon_border_style, //before { content: "\f1b1"; } + Icon_border_top, //before { content: "\f1b2"; } + Icon_border_width, //before { content: "\f1b3"; } + Icon_border, //before { content: "\f1b4"; } + Icon_bounding_box_circles, //before { content: "\f1b5"; } + Icon_bounding_box, //before { content: "\f1b6"; } + Icon_box_arrow_down_left, //before { content: "\f1b7"; } + Icon_box_arrow_down_right, //before { content: "\f1b8"; } + Icon_box_arrow_down, //before { content: "\f1b9"; } + Icon_box_arrow_in_down_left, //before { content: "\f1ba"; } + Icon_box_arrow_in_down_right, //before { content: "\f1bb"; } + Icon_box_arrow_in_down, //before { content: "\f1bc"; } + Icon_box_arrow_in_left, //before { content: "\f1bd"; } + Icon_box_arrow_in_right, //before { content: "\f1be"; } + Icon_box_arrow_in_up_left, //before { content: "\f1bf"; } + Icon_box_arrow_in_up_right, //before { content: "\f1c0"; } + Icon_box_arrow_in_up, //before { content: "\f1c1"; } + Icon_box_arrow_left, //before { content: "\f1c2"; } + Icon_box_arrow_right, //before { content: "\f1c3"; } + Icon_box_arrow_up_left, //before { content: "\f1c4"; } + Icon_box_arrow_up_right, //before { content: "\f1c5"; } + Icon_box_arrow_up, //before { content: "\f1c6"; } + Icon_box_seam, //before { content: "\f1c7"; } + Icon_box, //before { content: "\f1c8"; } + Icon_braces, //before { content: "\f1c9"; } + Icon_bricks, //before { content: "\f1ca"; } + Icon_briefcase_fill, //before { content: "\f1cb"; } + Icon_briefcase, //before { content: "\f1cc"; } + Icon_brightness_alt_high_fill, //before { content: "\f1cd"; } + Icon_brightness_alt_high, //before { content: "\f1ce"; } + Icon_brightness_alt_low_fill, //before { content: "\f1cf"; } + Icon_brightness_alt_low, //before { content: "\f1d0"; } + Icon_brightness_high_fill, //before { content: "\f1d1"; } + Icon_brightness_high, //before { content: "\f1d2"; } + Icon_brightness_low_fill, //before { content: "\f1d3"; } + Icon_brightness_low, //before { content: "\f1d4"; } + Icon_broadcast_pin, //before { content: "\f1d5"; } + Icon_broadcast, //before { content: "\f1d6"; } + Icon_brush_fill, //before { content: "\f1d7"; } + Icon_brush, //before { content: "\f1d8"; } + Icon_bucket_fill, //before { content: "\f1d9"; } + Icon_bucket, //before { content: "\f1da"; } + Icon_bug_fill, //before { content: "\f1db"; } + Icon_bug, //before { content: "\f1dc"; } + Icon_building, //before { content: "\f1dd"; } + Icon_bullseye, //before { content: "\f1de"; } + Icon_calculator_fill, //before { content: "\f1df"; } + Icon_calculator, //before { content: "\f1e0"; } + Icon_calendar_check_fill, //before { content: "\f1e1"; } + Icon_calendar_check, //before { content: "\f1e2"; } + Icon_calendar_date_fill, //before { content: "\f1e3"; } + Icon_calendar_date, //before { content: "\f1e4"; } + Icon_calendar_day_fill, //before { content: "\f1e5"; } + Icon_calendar_day, //before { content: "\f1e6"; } + Icon_calendar_event_fill, //before { content: "\f1e7"; } + Icon_calendar_event, //before { content: "\f1e8"; } + Icon_calendar_fill, //before { content: "\f1e9"; } + Icon_calendar_minus_fill, //before { content: "\f1ea"; } + Icon_calendar_minus, //before { content: "\f1eb"; } + Icon_calendar_month_fill, //before { content: "\f1ec"; } + Icon_calendar_month, //before { content: "\f1ed"; } + Icon_calendar_plus_fill, //before { content: "\f1ee"; } + Icon_calendar_plus, //before { content: "\f1ef"; } + Icon_calendar_range_fill, //before { content: "\f1f0"; } + Icon_calendar_range, //before { content: "\f1f1"; } + Icon_calendar_week_fill, //before { content: "\f1f2"; } + Icon_calendar_week, //before { content: "\f1f3"; } + Icon_calendar_x_fill, //before { content: "\f1f4"; } + Icon_calendar_x, //before { content: "\f1f5"; } + Icon_calendar, //before { content: "\f1f6"; } + Icon_calendar2_check_fill, //before { content: "\f1f7"; } + Icon_calendar2_check, //before { content: "\f1f8"; } + Icon_calendar2_date_fill, //before { content: "\f1f9"; } + Icon_calendar2_date, //before { content: "\f1fa"; } + Icon_calendar2_day_fill, //before { content: "\f1fb"; } + Icon_calendar2_day, //before { content: "\f1fc"; } + Icon_calendar2_event_fill, //before { content: "\f1fd"; } + Icon_calendar2_event, //before { content: "\f1fe"; } + Icon_calendar2_fill, //before { content: "\f1ff"; } + Icon_calendar2_minus_fill, //before { content: "\f200"; } + Icon_calendar2_minus, //before { content: "\f201"; } + Icon_calendar2_month_fill, //before { content: "\f202"; } + Icon_calendar2_month, //before { content: "\f203"; } + Icon_calendar2_plus_fill, //before { content: "\f204"; } + Icon_calendar2_plus, //before { content: "\f205"; } + Icon_calendar2_range_fill, //before { content: "\f206"; } + Icon_calendar2_range, //before { content: "\f207"; } + Icon_calendar2_week_fill, //before { content: "\f208"; } + Icon_calendar2_week, //before { content: "\f209"; } + Icon_calendar2_x_fill, //before { content: "\f20a"; } + Icon_calendar2_x, //before { content: "\f20b"; } + Icon_calendar2, //before { content: "\f20c"; } + Icon_calendar3_event_fill, //before { content: "\f20d"; } + Icon_calendar3_event, //before { content: "\f20e"; } + Icon_calendar3_fill, //before { content: "\f20f"; } + Icon_calendar3_range_fill, //before { content: "\f210"; } + Icon_calendar3_range, //before { content: "\f211"; } + Icon_calendar3_week_fill, //before { content: "\f212"; } + Icon_calendar3_week, //before { content: "\f213"; } + Icon_calendar3, //before { content: "\f214"; } + Icon_calendar4_event, //before { content: "\f215"; } + Icon_calendar4_range, //before { content: "\f216"; } + Icon_calendar4_week, //before { content: "\f217"; } + Icon_calendar4, //before { content: "\f218"; } + Icon_camera_fill, //before { content: "\f219"; } + Icon_camera_reels_fill, //before { content: "\f21a"; } + Icon_camera_reels, //before { content: "\f21b"; } + Icon_camera_video_fill, //before { content: "\f21c"; } + Icon_camera_video_off_fill, //before { content: "\f21d"; } + Icon_camera_video_off, //before { content: "\f21e"; } + Icon_camera_video, //before { content: "\f21f"; } + Icon_camera, //before { content: "\f220"; } + Icon_camera2, //before { content: "\f221"; } + Icon_capslock_fill, //before { content: "\f222"; } + Icon_capslock, //before { content: "\f223"; } + Icon_card_checklist, //before { content: "\f224"; } + Icon_card_heading, //before { content: "\f225"; } + Icon_card_image, //before { content: "\f226"; } + Icon_card_list, //before { content: "\f227"; } + Icon_card_text, //before { content: "\f228"; } + Icon_caret_down_fill, //before { content: "\f229"; } + Icon_caret_down_square_fill, //before { content: "\f22a"; } + Icon_caret_down_square, //before { content: "\f22b"; } + Icon_caret_down, //before { content: "\f22c"; } + Icon_caret_left_fill, //before { content: "\f22d"; } + Icon_caret_left_square_fill, //before { content: "\f22e"; } + Icon_caret_left_square, //before { content: "\f22f"; } + Icon_caret_left, //before { content: "\f230"; } + Icon_caret_right_fill, //before { content: "\f231"; } + Icon_caret_right_square_fill, //before { content: "\f232"; } + Icon_caret_right_square, //before { content: "\f233"; } + Icon_caret_right, //before { content: "\f234"; } + Icon_caret_up_fill, //before { content: "\f235"; } + Icon_caret_up_square_fill, //before { content: "\f236"; } + Icon_caret_up_square, //before { content: "\f237"; } + Icon_caret_up, //before { content: "\f238"; } + Icon_cart_check_fill, //before { content: "\f239"; } + Icon_cart_check, //before { content: "\f23a"; } + Icon_cart_dash_fill, //before { content: "\f23b"; } + Icon_cart_dash, //before { content: "\f23c"; } + Icon_cart_fill, //before { content: "\f23d"; } + Icon_cart_plus_fill, //before { content: "\f23e"; } + Icon_cart_plus, //before { content: "\f23f"; } + Icon_cart_x_fill, //before { content: "\f240"; } + Icon_cart_x, //before { content: "\f241"; } + Icon_cart, //before { content: "\f242"; } + Icon_cart2, //before { content: "\f243"; } + Icon_cart3, //before { content: "\f244"; } + Icon_cart4, //before { content: "\f245"; } + Icon_cash_stack, //before { content: "\f246"; } + Icon_cash, //before { content: "\f247"; } + Icon_cast, //before { content: "\f248"; } + Icon_chat_dots_fill, //before { content: "\f249"; } + Icon_chat_dots, //before { content: "\f24a"; } + Icon_chat_fill, //before { content: "\f24b"; } + Icon_chat_left_dots_fill, //before { content: "\f24c"; } + Icon_chat_left_dots, //before { content: "\f24d"; } + Icon_chat_left_fill, //before { content: "\f24e"; } + Icon_chat_left_quote_fill, //before { content: "\f24f"; } + Icon_chat_left_quote, //before { content: "\f250"; } + Icon_chat_left_text_fill, //before { content: "\f251"; } + Icon_chat_left_text, //before { content: "\f252"; } + Icon_chat_left, //before { content: "\f253"; } + Icon_chat_quote_fill, //before { content: "\f254"; } + Icon_chat_quote, //before { content: "\f255"; } + Icon_chat_right_dots_fill, //before { content: "\f256"; } + Icon_chat_right_dots, //before { content: "\f257"; } + Icon_chat_right_fill, //before { content: "\f258"; } + Icon_chat_right_quote_fill, //before { content: "\f259"; } + Icon_chat_right_quote, //before { content: "\f25a"; } + Icon_chat_right_text_fill, //before { content: "\f25b"; } + Icon_chat_right_text, //before { content: "\f25c"; } + Icon_chat_right, //before { content: "\f25d"; } + Icon_chat_square_dots_fill, //before { content: "\f25e"; } + Icon_chat_square_dots, //before { content: "\f25f"; } + Icon_chat_square_fill, //before { content: "\f260"; } + Icon_chat_square_quote_fill, //before { content: "\f261"; } + Icon_chat_square_quote, //before { content: "\f262"; } + Icon_chat_square_text_fill, //before { content: "\f263"; } + Icon_chat_square_text, //before { content: "\f264"; } + Icon_chat_square, //before { content: "\f265"; } + Icon_chat_text_fill, //before { content: "\f266"; } + Icon_chat_text, //before { content: "\f267"; } + Icon_chat, //before { content: "\f268"; } + Icon_check_all, //before { content: "\f269"; } + Icon_check_circle_fill, //before { content: "\f26a"; } + Icon_check_circle, //before { content: "\f26b"; } + Icon_check_square_fill, //before { content: "\f26c"; } + Icon_check_square, //before { content: "\f26d"; } + Icon_check, //before { content: "\f26e"; } + Icon_check2_all, //before { content: "\f26f"; } + Icon_check2_circle, //before { content: "\f270"; } + Icon_check2_square, //before { content: "\f271"; } + Icon_check2, //before { content: "\f272"; } + Icon_chevron_bar_contract, //before { content: "\f273"; } + Icon_chevron_bar_down, //before { content: "\f274"; } + Icon_chevron_bar_expand, //before { content: "\f275"; } + Icon_chevron_bar_left, //before { content: "\f276"; } + Icon_chevron_bar_right, //before { content: "\f277"; } + Icon_chevron_bar_up, //before { content: "\f278"; } + Icon_chevron_compact_down, //before { content: "\f279"; } + Icon_chevron_compact_left, //before { content: "\f27a"; } + Icon_chevron_compact_right, //before { content: "\f27b"; } + Icon_chevron_compact_up, //before { content: "\f27c"; } + Icon_chevron_contract, //before { content: "\f27d"; } + Icon_chevron_double_down, //before { content: "\f27e"; } + Icon_chevron_double_left, //before { content: "\f27f"; } + Icon_chevron_double_right, //before { content: "\f280"; } + Icon_chevron_double_up, //before { content: "\f281"; } + Icon_chevron_down, //before { content: "\f282"; } + Icon_chevron_expand, //before { content: "\f283"; } + Icon_chevron_left, //before { content: "\f284"; } + Icon_chevron_right, //before { content: "\f285"; } + Icon_chevron_up, //before { content: "\f286"; } + Icon_circle_fill, //before { content: "\f287"; } + Icon_circle_half, //before { content: "\f288"; } + Icon_circle_square, //before { content: "\f289"; } + Icon_circle, //before { content: "\f28a"; } + Icon_clipboard_check, //before { content: "\f28b"; } + Icon_clipboard_data, //before { content: "\f28c"; } + Icon_clipboard_minus, //before { content: "\f28d"; } + Icon_clipboard_plus, //before { content: "\f28e"; } + Icon_clipboard_x, //before { content: "\f28f"; } + Icon_clipboard, //before { content: "\f290"; } + Icon_clock_fill, //before { content: "\f291"; } + Icon_clock_history, //before { content: "\f292"; } + Icon_clock, //before { content: "\f293"; } + Icon_cloud_arrow_down_fill, //before { content: "\f294"; } + Icon_cloud_arrow_down, //before { content: "\f295"; } + Icon_cloud_arrow_up_fill, //before { content: "\f296"; } + Icon_cloud_arrow_up, //before { content: "\f297"; } + Icon_cloud_check_fill, //before { content: "\f298"; } + Icon_cloud_check, //before { content: "\f299"; } + Icon_cloud_download_fill, //before { content: "\f29a"; } + Icon_cloud_download, //before { content: "\f29b"; } + Icon_cloud_drizzle_fill, //before { content: "\f29c"; } + Icon_cloud_drizzle, //before { content: "\f29d"; } + Icon_cloud_fill, //before { content: "\f29e"; } + Icon_cloud_fog_fill, //before { content: "\f29f"; } + Icon_cloud_fog, //before { content: "\f2a0"; } + Icon_cloud_fog2_fill, //before { content: "\f2a1"; } + Icon_cloud_fog2, //before { content: "\f2a2"; } + Icon_cloud_hail_fill, //before { content: "\f2a3"; } + Icon_cloud_hail, //before { content: "\f2a4"; } + Icon_cloud_haze_fill, //before { content: "\f2a6"; } + Icon_cloud_haze, //before { content: "\f2a7"; } + Icon_cloud_haze2_fill, //before { content: "\f2a8"; } + Icon_cloud_lightning_fill, //before { content: "\f2a9"; } + Icon_cloud_lightning_rain_fill, //before { content: "\f2aa"; } + Icon_cloud_lightning_rain, //before { content: "\f2ab"; } + Icon_cloud_lightning, //before { content: "\f2ac"; } + Icon_cloud_minus_fill, //before { content: "\f2ad"; } + Icon_cloud_minus, //before { content: "\f2ae"; } + Icon_cloud_moon_fill, //before { content: "\f2af"; } + Icon_cloud_moon, //before { content: "\f2b0"; } + Icon_cloud_plus_fill, //before { content: "\f2b1"; } + Icon_cloud_plus, //before { content: "\f2b2"; } + Icon_cloud_rain_fill, //before { content: "\f2b3"; } + Icon_cloud_rain_heavy_fill, //before { content: "\f2b4"; } + Icon_cloud_rain_heavy, //before { content: "\f2b5"; } + Icon_cloud_rain, //before { content: "\f2b6"; } + Icon_cloud_slash_fill, //before { content: "\f2b7"; } + Icon_cloud_slash, //before { content: "\f2b8"; } + Icon_cloud_sleet_fill, //before { content: "\f2b9"; } + Icon_cloud_sleet, //before { content: "\f2ba"; } + Icon_cloud_snow_fill, //before { content: "\f2bb"; } + Icon_cloud_snow, //before { content: "\f2bc"; } + Icon_cloud_sun_fill, //before { content: "\f2bd"; } + Icon_cloud_sun, //before { content: "\f2be"; } + Icon_cloud_upload_fill, //before { content: "\f2bf"; } + Icon_cloud_upload, //before { content: "\f2c0"; } + Icon_cloud, //before { content: "\f2c1"; } + Icon_clouds_fill, //before { content: "\f2c2"; } + Icon_clouds, //before { content: "\f2c3"; } + Icon_cloudy_fill, //before { content: "\f2c4"; } + Icon_cloudy, //before { content: "\f2c5"; } + Icon_code_slash, //before { content: "\f2c6"; } + Icon_code_square, //before { content: "\f2c7"; } + Icon_code, //before { content: "\f2c8"; } + Icon_collection_fill, //before { content: "\f2c9"; } + Icon_collection_play_fill, //before { content: "\f2ca"; } + Icon_collection_play, //before { content: "\f2cb"; } + Icon_collection, //before { content: "\f2cc"; } + Icon_columns_gap, //before { content: "\f2cd"; } + Icon_columns, //before { content: "\f2ce"; } + Icon_command, //before { content: "\f2cf"; } + Icon_compass_fill, //before { content: "\f2d0"; } + Icon_compass, //before { content: "\f2d1"; } + Icon_cone_striped, //before { content: "\f2d2"; } + Icon_cone, //before { content: "\f2d3"; } + Icon_controller, //before { content: "\f2d4"; } + Icon_cpu_fill, //before { content: "\f2d5"; } + Icon_cpu, //before { content: "\f2d6"; } + Icon_credit_card_2_back_fill, //before { content: "\f2d7"; } + Icon_credit_card_2_back, //before { content: "\f2d8"; } + Icon_credit_card_2_front_fill, //before { content: "\f2d9"; } + Icon_credit_card_2_front, //before { content: "\f2da"; } + Icon_credit_card_fill, //before { content: "\f2db"; } + Icon_credit_card, //before { content: "\f2dc"; } + Icon_crop, //before { content: "\f2dd"; } + Icon_cup_fill, //before { content: "\f2de"; } + Icon_cup_straw, //before { content: "\f2df"; } + Icon_cup, //before { content: "\f2e0"; } + Icon_cursor_fill, //before { content: "\f2e1"; } + Icon_cursor_text, //before { content: "\f2e2"; } + Icon_cursor, //before { content: "\f2e3"; } + Icon_dash_circle_dotted, //before { content: "\f2e4"; } + Icon_dash_circle_fill, //before { content: "\f2e5"; } + Icon_dash_circle, //before { content: "\f2e6"; } + Icon_dash_square_dotted, //before { content: "\f2e7"; } + Icon_dash_square_fill, //before { content: "\f2e8"; } + Icon_dash_square, //before { content: "\f2e9"; } + Icon_dash, //before { content: "\f2ea"; } + Icon_diagram_2_fill, //before { content: "\f2eb"; } + Icon_diagram_2, //before { content: "\f2ec"; } + Icon_diagram_3_fill, //before { content: "\f2ed"; } + Icon_diagram_3, //before { content: "\f2ee"; } + Icon_diamond_fill, //before { content: "\f2ef"; } + Icon_diamond_half, //before { content: "\f2f0"; } + Icon_diamond, //before { content: "\f2f1"; } + Icon_dice_1_fill, //before { content: "\f2f2"; } + Icon_dice_1, //before { content: "\f2f3"; } + Icon_dice_2_fill, //before { content: "\f2f4"; } + Icon_dice_2, //before { content: "\f2f5"; } + Icon_dice_3_fill, //before { content: "\f2f6"; } + Icon_dice_3, //before { content: "\f2f7"; } + Icon_dice_4_fill, //before { content: "\f2f8"; } + Icon_dice_4, //before { content: "\f2f9"; } + Icon_dice_5_fill, //before { content: "\f2fa"; } + Icon_dice_5, //before { content: "\f2fb"; } + Icon_dice_6_fill, //before { content: "\f2fc"; } + Icon_dice_6, //before { content: "\f2fd"; } + Icon_disc_fill, //before { content: "\f2fe"; } + Icon_disc, //before { content: "\f2ff"; } + Icon_discord, //before { content: "\f300"; } + Icon_display_fill, //before { content: "\f301"; } + Icon_display, //before { content: "\f302"; } + Icon_distribute_horizontal, //before { content: "\f303"; } + Icon_distribute_vertical, //before { content: "\f304"; } + Icon_door_closed_fill, //before { content: "\f305"; } + Icon_door_closed, //before { content: "\f306"; } + Icon_door_open_fill, //before { content: "\f307"; } + Icon_door_open, //before { content: "\f308"; } + Icon_dot, //before { content: "\f309"; } + Icon_download, //before { content: "\f30a"; } + Icon_droplet_fill, //before { content: "\f30b"; } + Icon_droplet_half, //before { content: "\f30c"; } + Icon_droplet, //before { content: "\f30d"; } + Icon_earbuds, //before { content: "\f30e"; } + Icon_easel_fill, //before { content: "\f30f"; } + Icon_easel, //before { content: "\f310"; } + Icon_egg_fill, //before { content: "\f311"; } + Icon_egg_fried, //before { content: "\f312"; } + Icon_egg, //before { content: "\f313"; } + Icon_eject_fill, //before { content: "\f314"; } + Icon_eject, //before { content: "\f315"; } + Icon_emoji_angry_fill, //before { content: "\f316"; } + Icon_emoji_angry, //before { content: "\f317"; } + Icon_emoji_dizzy_fill, //before { content: "\f318"; } + Icon_emoji_dizzy, //before { content: "\f319"; } + Icon_emoji_expressionless_fill, //before { content: "\f31a"; } + Icon_emoji_expressionless, //before { content: "\f31b"; } + Icon_emoji_frown_fill, //before { content: "\f31c"; } + Icon_emoji_frown, //before { content: "\f31d"; } + Icon_emoji_heart_eyes_fill, //before { content: "\f31e"; } + Icon_emoji_heart_eyes, //before { content: "\f31f"; } + Icon_emoji_laughing_fill, //before { content: "\f320"; } + Icon_emoji_laughing, //before { content: "\f321"; } + Icon_emoji_neutral_fill, //before { content: "\f322"; } + Icon_emoji_neutral, //before { content: "\f323"; } + Icon_emoji_smile_fill, //before { content: "\f324"; } + Icon_emoji_smile_upside_down_fill, //before { content: "\f325"; } + Icon_emoji_smile_upside_down, //before { content: "\f326"; } + Icon_emoji_smile, //before { content: "\f327"; } + Icon_emoji_sunglasses_fill, //before { content: "\f328"; } + Icon_emoji_sunglasses, //before { content: "\f329"; } + Icon_emoji_wink_fill, //before { content: "\f32a"; } + Icon_emoji_wink, //before { content: "\f32b"; } + Icon_envelope_fill, //before { content: "\f32c"; } + Icon_envelope_open_fill, //before { content: "\f32d"; } + Icon_envelope_open, //before { content: "\f32e"; } + Icon_envelope, //before { content: "\f32f"; } + Icon_eraser_fill, //before { content: "\f330"; } + Icon_eraser, //before { content: "\f331"; } + Icon_exclamation_circle_fill, //before { content: "\f332"; } + Icon_exclamation_circle, //before { content: "\f333"; } + Icon_exclamation_diamond_fill, //before { content: "\f334"; } + Icon_exclamation_diamond, //before { content: "\f335"; } + Icon_exclamation_octagon_fill, //before { content: "\f336"; } + Icon_exclamation_octagon, //before { content: "\f337"; } + Icon_exclamation_square_fill, //before { content: "\f338"; } + Icon_exclamation_square, //before { content: "\f339"; } + Icon_exclamation_triangle_fill, //before { content: "\f33a"; } + Icon_exclamation_triangle, //before { content: "\f33b"; } + Icon_exclamation, //before { content: "\f33c"; } + Icon_exclude, //before { content: "\f33d"; } + Icon_eye_fill, //before { content: "\f33e"; } + Icon_eye_slash_fill, //before { content: "\f33f"; } + Icon_eye_slash, //before { content: "\f340"; } + Icon_eye, //before { content: "\f341"; } + Icon_eyedropper, //before { content: "\f342"; } + Icon_eyeglasses, //before { content: "\f343"; } + Icon_facebook, //before { content: "\f344"; } + Icon_file_arrow_down_fill, //before { content: "\f345"; } + Icon_file_arrow_down, //before { content: "\f346"; } + Icon_file_arrow_up_fill, //before { content: "\f347"; } + Icon_file_arrow_up, //before { content: "\f348"; } + Icon_file_bar_graph_fill, //before { content: "\f349"; } + Icon_file_bar_graph, //before { content: "\f34a"; } + Icon_file_binary_fill, //before { content: "\f34b"; } + Icon_file_binary, //before { content: "\f34c"; } + Icon_file_break_fill, //before { content: "\f34d"; } + Icon_file_break, //before { content: "\f34e"; } + Icon_file_check_fill, //before { content: "\f34f"; } + Icon_file_check, //before { content: "\f350"; } + Icon_file_code_fill, //before { content: "\f351"; } + Icon_file_code, //before { content: "\f352"; } + Icon_file_diff_fill, //before { content: "\f353"; } + Icon_file_diff, //before { content: "\f354"; } + Icon_file_earmark_arrow_down_fill, //before { content: "\f355"; } + Icon_file_earmark_arrow_down, //before { content: "\f356"; } + Icon_file_earmark_arrow_up_fill, //before { content: "\f357"; } + Icon_file_earmark_arrow_up, //before { content: "\f358"; } + Icon_file_earmark_bar_graph_fill, //before { content: "\f359"; } + Icon_file_earmark_bar_graph, //before { content: "\f35a"; } + Icon_file_earmark_binary_fill, //before { content: "\f35b"; } + Icon_file_earmark_binary, //before { content: "\f35c"; } + Icon_file_earmark_break_fill, //before { content: "\f35d"; } + Icon_file_earmark_break, //before { content: "\f35e"; } + Icon_file_earmark_check_fill, //before { content: "\f35f"; } + Icon_file_earmark_check, //before { content: "\f360"; } + Icon_file_earmark_code_fill, //before { content: "\f361"; } + Icon_file_earmark_code, //before { content: "\f362"; } + Icon_file_earmark_diff_fill, //before { content: "\f363"; } + Icon_file_earmark_diff, //before { content: "\f364"; } + Icon_file_earmark_easel_fill, //before { content: "\f365"; } + Icon_file_earmark_easel, //before { content: "\f366"; } + Icon_file_earmark_excel_fill, //before { content: "\f367"; } + Icon_file_earmark_excel, //before { content: "\f368"; } + Icon_file_earmark_fill, //before { content: "\f369"; } + Icon_file_earmark_font_fill, //before { content: "\f36a"; } + Icon_file_earmark_font, //before { content: "\f36b"; } + Icon_file_earmark_image_fill, //before { content: "\f36c"; } + Icon_file_earmark_image, //before { content: "\f36d"; } + Icon_file_earmark_lock_fill, //before { content: "\f36e"; } + Icon_file_earmark_lock, //before { content: "\f36f"; } + Icon_file_earmark_lock2_fill, //before { content: "\f370"; } + Icon_file_earmark_lock2, //before { content: "\f371"; } + Icon_file_earmark_medical_fill, //before { content: "\f372"; } + Icon_file_earmark_medical, //before { content: "\f373"; } + Icon_file_earmark_minus_fill, //before { content: "\f374"; } + Icon_file_earmark_minus, //before { content: "\f375"; } + Icon_file_earmark_music_fill, //before { content: "\f376"; } + Icon_file_earmark_music, //before { content: "\f377"; } + Icon_file_earmark_person_fill, //before { content: "\f378"; } + Icon_file_earmark_person, //before { content: "\f379"; } + Icon_file_earmark_play_fill, //before { content: "\f37a"; } + Icon_file_earmark_play, //before { content: "\f37b"; } + Icon_file_earmark_plus_fill, //before { content: "\f37c"; } + Icon_file_earmark_plus, //before { content: "\f37d"; } + Icon_file_earmark_post_fill, //before { content: "\f37e"; } + Icon_file_earmark_post, //before { content: "\f37f"; } + Icon_file_earmark_ppt_fill, //before { content: "\f380"; } + Icon_file_earmark_ppt, //before { content: "\f381"; } + Icon_file_earmark_richtext_fill, //before { content: "\f382"; } + Icon_file_earmark_richtext, //before { content: "\f383"; } + Icon_file_earmark_ruled_fill, //before { content: "\f384"; } + Icon_file_earmark_ruled, //before { content: "\f385"; } + Icon_file_earmark_slides_fill, //before { content: "\f386"; } + Icon_file_earmark_slides, //before { content: "\f387"; } + Icon_file_earmark_spreadsheet_fill, //before { content: "\f388"; } + Icon_file_earmark_spreadsheet, //before { content: "\f389"; } + Icon_file_earmark_text_fill, //before { content: "\f38a"; } + Icon_file_earmark_text, //before { content: "\f38b"; } + Icon_file_earmark_word_fill, //before { content: "\f38c"; } + Icon_file_earmark_word, //before { content: "\f38d"; } + Icon_file_earmark_x_fill, //before { content: "\f38e"; } + Icon_file_earmark_x, //before { content: "\f38f"; } + Icon_file_earmark_zip_fill, //before { content: "\f390"; } + Icon_file_earmark_zip, //before { content: "\f391"; } + Icon_file_earmark, //before { content: "\f392"; } + Icon_file_easel_fill, //before { content: "\f393"; } + Icon_file_easel, //before { content: "\f394"; } + Icon_file_excel_fill, //before { content: "\f395"; } + Icon_file_excel, //before { content: "\f396"; } + Icon_file_fill, //before { content: "\f397"; } + Icon_file_font_fill, //before { content: "\f398"; } + Icon_file_font, //before { content: "\f399"; } + Icon_file_image_fill, //before { content: "\f39a"; } + Icon_file_image, //before { content: "\f39b"; } + Icon_file_lock_fill, //before { content: "\f39c"; } + Icon_file_lock, //before { content: "\f39d"; } + Icon_file_lock2_fill, //before { content: "\f39e"; } + Icon_file_lock2, //before { content: "\f39f"; } + Icon_file_medical_fill, //before { content: "\f3a0"; } + Icon_file_medical, //before { content: "\f3a1"; } + Icon_file_minus_fill, //before { content: "\f3a2"; } + Icon_file_minus, //before { content: "\f3a3"; } + Icon_file_music_fill, //before { content: "\f3a4"; } + Icon_file_music, //before { content: "\f3a5"; } + Icon_file_person_fill, //before { content: "\f3a6"; } + Icon_file_person, //before { content: "\f3a7"; } + Icon_file_play_fill, //before { content: "\f3a8"; } + Icon_file_play, //before { content: "\f3a9"; } + Icon_file_plus_fill, //before { content: "\f3aa"; } + Icon_file_plus, //before { content: "\f3ab"; } + Icon_file_post_fill, //before { content: "\f3ac"; } + Icon_file_post, //before { content: "\f3ad"; } + Icon_file_ppt_fill, //before { content: "\f3ae"; } + Icon_file_ppt, //before { content: "\f3af"; } + Icon_file_richtext_fill, //before { content: "\f3b0"; } + Icon_file_richtext, //before { content: "\f3b1"; } + Icon_file_ruled_fill, //before { content: "\f3b2"; } + Icon_file_ruled, //before { content: "\f3b3"; } + Icon_file_slides_fill, //before { content: "\f3b4"; } + Icon_file_slides, //before { content: "\f3b5"; } + Icon_file_spreadsheet_fill, //before { content: "\f3b6"; } + Icon_file_spreadsheet, //before { content: "\f3b7"; } + Icon_file_text_fill, //before { content: "\f3b8"; } + Icon_file_text, //before { content: "\f3b9"; } + Icon_file_word_fill, //before { content: "\f3ba"; } + Icon_file_word, //before { content: "\f3bb"; } + Icon_file_x_fill, //before { content: "\f3bc"; } + Icon_file_x, //before { content: "\f3bd"; } + Icon_file_zip_fill, //before { content: "\f3be"; } + Icon_file_zip, //before { content: "\f3bf"; } + Icon_file, //before { content: "\f3c0"; } + Icon_files_alt, //before { content: "\f3c1"; } + Icon_files, //before { content: "\f3c2"; } + Icon_film, //before { content: "\f3c3"; } + Icon_filter_circle_fill, //before { content: "\f3c4"; } + Icon_filter_circle, //before { content: "\f3c5"; } + Icon_filter_left, //before { content: "\f3c6"; } + Icon_filter_right, //before { content: "\f3c7"; } + Icon_filter_square_fill, //before { content: "\f3c8"; } + Icon_filter_square, //before { content: "\f3c9"; } + Icon_filter, //before { content: "\f3ca"; } + Icon_flag_fill, //before { content: "\f3cb"; } + Icon_flag, //before { content: "\f3cc"; } + Icon_flower1, //before { content: "\f3cd"; } + Icon_flower2, //before { content: "\f3ce"; } + Icon_flower3, //before { content: "\f3cf"; } + Icon_folder_check, //before { content: "\f3d0"; } + Icon_folder_fill, //before { content: "\f3d1"; } + Icon_folder_minus, //before { content: "\f3d2"; } + Icon_folder_plus, //before { content: "\f3d3"; } + Icon_folder_symlink_fill, //before { content: "\f3d4"; } + Icon_folder_symlink, //before { content: "\f3d5"; } + Icon_folder_x, //before { content: "\f3d6"; } + Icon_folder, //before { content: "\f3d7"; } + Icon_folder2_open, //before { content: "\f3d8"; } + Icon_folder2, //before { content: "\f3d9"; } + Icon_fonts, //before { content: "\f3da"; } + Icon_forward_fill, //before { content: "\f3db"; } + Icon_forward, //before { content: "\f3dc"; } + Icon_front, //before { content: "\f3dd"; } + Icon_fullscreen_exit, //before { content: "\f3de"; } + Icon_fullscreen, //before { content: "\f3df"; } + Icon_funnel_fill, //before { content: "\f3e0"; } + Icon_funnel, //before { content: "\f3e1"; } + Icon_gear_fill, //before { content: "\f3e2"; } + Icon_gear_wide_connected, //before { content: "\f3e3"; } + Icon_gear_wide, //before { content: "\f3e4"; } + Icon_gear, //before { content: "\f3e5"; } + Icon_gem, //before { content: "\f3e6"; } + Icon_geo_alt_fill, //before { content: "\f3e7"; } + Icon_geo_alt, //before { content: "\f3e8"; } + Icon_geo_fill, //before { content: "\f3e9"; } + Icon_geo, //before { content: "\f3ea"; } + Icon_gift_fill, //before { content: "\f3eb"; } + Icon_gift, //before { content: "\f3ec"; } + Icon_github, //before { content: "\f3ed"; } + Icon_globe, //before { content: "\f3ee"; } + Icon_globe2, //before { content: "\f3ef"; } + Icon_google, //before { content: "\f3f0"; } + Icon_graph_down, //before { content: "\f3f1"; } + Icon_graph_up, //before { content: "\f3f2"; } + Icon_grid_1x2_fill, //before { content: "\f3f3"; } + Icon_grid_1x2, //before { content: "\f3f4"; } + Icon_grid_3x2_gap_fill, //before { content: "\f3f5"; } + Icon_grid_3x2_gap, //before { content: "\f3f6"; } + Icon_grid_3x2, //before { content: "\f3f7"; } + Icon_grid_3x3_gap_fill, //before { content: "\f3f8"; } + Icon_grid_3x3_gap, //before { content: "\f3f9"; } + Icon_grid_3x3, //before { content: "\f3fa"; } + Icon_grid_fill, //before { content: "\f3fb"; } + Icon_grid, //before { content: "\f3fc"; } + Icon_grip_horizontal, //before { content: "\f3fd"; } + Icon_grip_vertical, //before { content: "\f3fe"; } + Icon_hammer, //before { content: "\f3ff"; } + Icon_hand_index_fill, //before { content: "\f400"; } + Icon_hand_index_thumb_fill, //before { content: "\f401"; } + Icon_hand_index_thumb, //before { content: "\f402"; } + Icon_hand_index, //before { content: "\f403"; } + Icon_hand_thumbs_down_fill, //before { content: "\f404"; } + Icon_hand_thumbs_down, //before { content: "\f405"; } + Icon_hand_thumbs_up_fill, //before { content: "\f406"; } + Icon_hand_thumbs_up, //before { content: "\f407"; } + Icon_handbag_fill, //before { content: "\f408"; } + Icon_handbag, //before { content: "\f409"; } + Icon_hash, //before { content: "\f40a"; } + Icon_hdd_fill, //before { content: "\f40b"; } + Icon_hdd_network_fill, //before { content: "\f40c"; } + Icon_hdd_network, //before { content: "\f40d"; } + Icon_hdd_rack_fill, //before { content: "\f40e"; } + Icon_hdd_rack, //before { content: "\f40f"; } + Icon_hdd_stack_fill, //before { content: "\f410"; } + Icon_hdd_stack, //before { content: "\f411"; } + Icon_hdd, //before { content: "\f412"; } + Icon_headphones, //before { content: "\f413"; } + Icon_headset, //before { content: "\f414"; } + Icon_heart_fill, //before { content: "\f415"; } + Icon_heart_half, //before { content: "\f416"; } + Icon_heart, //before { content: "\f417"; } + Icon_heptagon_fill, //before { content: "\f418"; } + Icon_heptagon_half, //before { content: "\f419"; } + Icon_heptagon, //before { content: "\f41a"; } + Icon_hexagon_fill, //before { content: "\f41b"; } + Icon_hexagon_half, //before { content: "\f41c"; } + Icon_hexagon, //before { content: "\f41d"; } + Icon_hourglass_bottom, //before { content: "\f41e"; } + Icon_hourglass_split, //before { content: "\f41f"; } + Icon_hourglass_top, //before { content: "\f420"; } + Icon_hourglass, //before { content: "\f421"; } + Icon_house_door_fill, //before { content: "\f422"; } + Icon_house_door, //before { content: "\f423"; } + Icon_house_fill, //before { content: "\f424"; } + Icon_house, //before { content: "\f425"; } + Icon_hr, //before { content: "\f426"; } + Icon_hurricane, //before { content: "\f427"; } + Icon_image_alt, //before { content: "\f428"; } + Icon_image_fill, //before { content: "\f429"; } + Icon_image, //before { content: "\f42a"; } + Icon_images, //before { content: "\f42b"; } + Icon_inbox_fill, //before { content: "\f42c"; } + Icon_inbox, //before { content: "\f42d"; } + Icon_inboxes_fill, //before { content: "\f42e"; } + Icon_inboxes, //before { content: "\f42f"; } + Icon_info_circle_fill, //before { content: "\f430"; } + Icon_info_circle, //before { content: "\f431"; } + Icon_info_square_fill, //before { content: "\f432"; } + Icon_info_square, //before { content: "\f433"; } + Icon_info, //before { content: "\f434"; } + Icon_input_cursor_text, //before { content: "\f435"; } + Icon_input_cursor, //before { content: "\f436"; } + Icon_instagram, //before { content: "\f437"; } + Icon_intersect, //before { content: "\f438"; } + Icon_journal_album, //before { content: "\f439"; } + Icon_journal_arrow_down, //before { content: "\f43a"; } + Icon_journal_arrow_up, //before { content: "\f43b"; } + Icon_journal_bookmark_fill, //before { content: "\f43c"; } + Icon_journal_bookmark, //before { content: "\f43d"; } + Icon_journal_check, //before { content: "\f43e"; } + Icon_journal_code, //before { content: "\f43f"; } + Icon_journal_medical, //before { content: "\f440"; } + Icon_journal_minus, //before { content: "\f441"; } + Icon_journal_plus, //before { content: "\f442"; } + Icon_journal_richtext, //before { content: "\f443"; } + Icon_journal_text, //before { content: "\f444"; } + Icon_journal_x, //before { content: "\f445"; } + Icon_journal, //before { content: "\f446"; } + Icon_journals, //before { content: "\f447"; } + Icon_joystick, //before { content: "\f448"; } + Icon_justify_left, //before { content: "\f449"; } + Icon_justify_right, //before { content: "\f44a"; } + Icon_justify, //before { content: "\f44b"; } + Icon_kanban_fill, //before { content: "\f44c"; } + Icon_kanban, //before { content: "\f44d"; } + Icon_key_fill, //before { content: "\f44e"; } + Icon_key, //before { content: "\f44f"; } + Icon_keyboard_fill, //before { content: "\f450"; } + Icon_keyboard, //before { content: "\f451"; } + Icon_ladder, //before { content: "\f452"; } + Icon_lamp_fill, //before { content: "\f453"; } + Icon_lamp, //before { content: "\f454"; } + Icon_laptop_fill, //before { content: "\f455"; } + Icon_laptop, //before { content: "\f456"; } + Icon_layer_backward, //before { content: "\f457"; } + Icon_layer_forward, //before { content: "\f458"; } + Icon_layers_fill, //before { content: "\f459"; } + Icon_layers_half, //before { content: "\f45a"; } + Icon_layers, //before { content: "\f45b"; } + Icon_layout_sidebar_inset_reverse, //before { content: "\f45c"; } + Icon_layout_sidebar_inset, //before { content: "\f45d"; } + Icon_layout_sidebar_reverse, //before { content: "\f45e"; } + Icon_layout_sidebar, //before { content: "\f45f"; } + Icon_layout_split, //before { content: "\f460"; } + Icon_layout_text_sidebar_reverse, //before { content: "\f461"; } + Icon_layout_text_sidebar, //before { content: "\f462"; } + Icon_layout_text_window_reverse, //before { content: "\f463"; } + Icon_layout_text_window, //before { content: "\f464"; } + Icon_layout_three_columns, //before { content: "\f465"; } + Icon_layout_wtf, //before { content: "\f466"; } + Icon_life_preserver, //before { content: "\f467"; } + Icon_lightbulb_fill, //before { content: "\f468"; } + Icon_lightbulb_off_fill, //before { content: "\f469"; } + Icon_lightbulb_off, //before { content: "\f46a"; } + Icon_lightbulb, //before { content: "\f46b"; } + Icon_lightning_charge_fill, //before { content: "\f46c"; } + Icon_lightning_charge, //before { content: "\f46d"; } + Icon_lightning_fill, //before { content: "\f46e"; } + Icon_lightning, //before { content: "\f46f"; } + Icon_link_45deg, //before { content: "\f470"; } + Icon_link, //before { content: "\f471"; } + Icon_linkedin, //before { content: "\f472"; } + Icon_list_check, //before { content: "\f473"; } + Icon_list_nested, //before { content: "\f474"; } + Icon_list_ol, //before { content: "\f475"; } + Icon_list_stars, //before { content: "\f476"; } + Icon_list_task, //before { content: "\f477"; } + Icon_list_ul, //before { content: "\f478"; } + Icon_list, //before { content: "\f479"; } + Icon_lock_fill, //before { content: "\f47a"; } + Icon_lock, //before { content: "\f47b"; } + Icon_mailbox, //before { content: "\f47c"; } + Icon_mailbox2, //before { content: "\f47d"; } + Icon_map_fill, //before { content: "\f47e"; } + Icon_map, //before { content: "\f47f"; } + Icon_markdown_fill, //before { content: "\f480"; } + Icon_markdown, //before { content: "\f481"; } + Icon_mask, //before { content: "\f482"; } + Icon_megaphone_fill, //before { content: "\f483"; } + Icon_megaphone, //before { content: "\f484"; } + Icon_menu_app_fill, //before { content: "\f485"; } + Icon_menu_app, //before { content: "\f486"; } + Icon_menu_button_fill, //before { content: "\f487"; } + Icon_menu_button_wide_fill, //before { content: "\f488"; } + Icon_menu_button_wide, //before { content: "\f489"; } + Icon_menu_button, //before { content: "\f48a"; } + Icon_menu_down, //before { content: "\f48b"; } + Icon_menu_up, //before { content: "\f48c"; } + Icon_mic_fill, //before { content: "\f48d"; } + Icon_mic_mute_fill, //before { content: "\f48e"; } + Icon_mic_mute, //before { content: "\f48f"; } + Icon_mic, //before { content: "\f490"; } + Icon_minecart_loaded, //before { content: "\f491"; } + Icon_minecart, //before { content: "\f492"; } + Icon_moisture, //before { content: "\f493"; } + Icon_moon_fill, //before { content: "\f494"; } + Icon_moon_stars_fill, //before { content: "\f495"; } + Icon_moon_stars, //before { content: "\f496"; } + Icon_moon, //before { content: "\f497"; } + Icon_mouse_fill, //before { content: "\f498"; } + Icon_mouse, //before { content: "\f499"; } + Icon_mouse2_fill, //before { content: "\f49a"; } + Icon_mouse2, //before { content: "\f49b"; } + Icon_mouse3_fill, //before { content: "\f49c"; } + Icon_mouse3, //before { content: "\f49d"; } + Icon_music_note_beamed, //before { content: "\f49e"; } + Icon_music_note_list, //before { content: "\f49f"; } + Icon_music_note, //before { content: "\f4a0"; } + Icon_music_player_fill, //before { content: "\f4a1"; } + Icon_music_player, //before { content: "\f4a2"; } + Icon_newspaper, //before { content: "\f4a3"; } + Icon_node_minus_fill, //before { content: "\f4a4"; } + Icon_node_minus, //before { content: "\f4a5"; } + Icon_node_plus_fill, //before { content: "\f4a6"; } + Icon_node_plus, //before { content: "\f4a7"; } + Icon_nut_fill, //before { content: "\f4a8"; } + Icon_nut, //before { content: "\f4a9"; } + Icon_octagon_fill, //before { content: "\f4aa"; } + Icon_octagon_half, //before { content: "\f4ab"; } + Icon_octagon, //before { content: "\f4ac"; } + Icon_option, //before { content: "\f4ad"; } + Icon_outlet, //before { content: "\f4ae"; } + Icon_paint_bucket, //before { content: "\f4af"; } + Icon_palette_fill, //before { content: "\f4b0"; } + Icon_palette, //before { content: "\f4b1"; } + Icon_palette2, //before { content: "\f4b2"; } + Icon_paperclip, //before { content: "\f4b3"; } + Icon_paragraph, //before { content: "\f4b4"; } + Icon_patch_check_fill, //before { content: "\f4b5"; } + Icon_patch_check, //before { content: "\f4b6"; } + Icon_patch_exclamation_fill, //before { content: "\f4b7"; } + Icon_patch_exclamation, //before { content: "\f4b8"; } + Icon_patch_minus_fill, //before { content: "\f4b9"; } + Icon_patch_minus, //before { content: "\f4ba"; } + Icon_patch_plus_fill, //before { content: "\f4bb"; } + Icon_patch_plus, //before { content: "\f4bc"; } + Icon_patch_question_fill, //before { content: "\f4bd"; } + Icon_patch_question, //before { content: "\f4be"; } + Icon_pause_btn_fill, //before { content: "\f4bf"; } + Icon_pause_btn, //before { content: "\f4c0"; } + Icon_pause_circle_fill, //before { content: "\f4c1"; } + Icon_pause_circle, //before { content: "\f4c2"; } + Icon_pause_fill, //before { content: "\f4c3"; } + Icon_pause, //before { content: "\f4c4"; } + Icon_peace_fill, //before { content: "\f4c5"; } + Icon_peace, //before { content: "\f4c6"; } + Icon_pen_fill, //before { content: "\f4c7"; } + Icon_pen, //before { content: "\f4c8"; } + Icon_pencil_fill, //before { content: "\f4c9"; } + Icon_pencil_square, //before { content: "\f4ca"; } + Icon_pencil, //before { content: "\f4cb"; } + Icon_pentagon_fill, //before { content: "\f4cc"; } + Icon_pentagon_half, //before { content: "\f4cd"; } + Icon_pentagon, //before { content: "\f4ce"; } + Icon_people_fill, //before { content: "\f4cf"; } + Icon_people, //before { content: "\f4d0"; } + Icon_percent, //before { content: "\f4d1"; } + Icon_person_badge_fill, //before { content: "\f4d2"; } + Icon_person_badge, //before { content: "\f4d3"; } + Icon_person_bounding_box, //before { content: "\f4d4"; } + Icon_person_check_fill, //before { content: "\f4d5"; } + Icon_person_check, //before { content: "\f4d6"; } + Icon_person_circle, //before { content: "\f4d7"; } + Icon_person_dash_fill, //before { content: "\f4d8"; } + Icon_person_dash, //before { content: "\f4d9"; } + Icon_person_fill, //before { content: "\f4da"; } + Icon_person_lines_fill, //before { content: "\f4db"; } + Icon_person_plus_fill, //before { content: "\f4dc"; } + Icon_person_plus, //before { content: "\f4dd"; } + Icon_person_square, //before { content: "\f4de"; } + Icon_person_x_fill, //before { content: "\f4df"; } + Icon_person_x, //before { content: "\f4e0"; } + Icon_person, //before { content: "\f4e1"; } + Icon_phone_fill, //before { content: "\f4e2"; } + Icon_phone_landscape_fill, //before { content: "\f4e3"; } + Icon_phone_landscape, //before { content: "\f4e4"; } + Icon_phone_vibrate_fill, //before { content: "\f4e5"; } + Icon_phone_vibrate, //before { content: "\f4e6"; } + Icon_phone, //before { content: "\f4e7"; } + Icon_pie_chart_fill, //before { content: "\f4e8"; } + Icon_pie_chart, //before { content: "\f4e9"; } + Icon_pin_angle_fill, //before { content: "\f4ea"; } + Icon_pin_angle, //before { content: "\f4eb"; } + Icon_pin_fill, //before { content: "\f4ec"; } + Icon_pin, //before { content: "\f4ed"; } + Icon_pip_fill, //before { content: "\f4ee"; } + Icon_pip, //before { content: "\f4ef"; } + Icon_play_btn_fill, //before { content: "\f4f0"; } + Icon_play_btn, //before { content: "\f4f1"; } + Icon_play_circle_fill, //before { content: "\f4f2"; } + Icon_play_circle, //before { content: "\f4f3"; } + Icon_play_fill, //before { content: "\f4f4"; } + Icon_play, //before { content: "\f4f5"; } + Icon_plug_fill, //before { content: "\f4f6"; } + Icon_plug, //before { content: "\f4f7"; } + Icon_plus_circle_dotted, //before { content: "\f4f8"; } + Icon_plus_circle_fill, //before { content: "\f4f9"; } + Icon_plus_circle, //before { content: "\f4fa"; } + Icon_plus_square_dotted, //before { content: "\f4fb"; } + Icon_plus_square_fill, //before { content: "\f4fc"; } + Icon_plus_square, //before { content: "\f4fd"; } + Icon_plus, //before { content: "\f4fe"; } + Icon_power, //before { content: "\f4ff"; } + Icon_printer_fill, //before { content: "\f500"; } + Icon_printer, //before { content: "\f501"; } + Icon_puzzle_fill, //before { content: "\f502"; } + Icon_puzzle, //before { content: "\f503"; } + Icon_question_circle_fill, //before { content: "\f504"; } + Icon_question_circle, //before { content: "\f505"; } + Icon_question_diamond_fill, //before { content: "\f506"; } + Icon_question_diamond, //before { content: "\f507"; } + Icon_question_octagon_fill, //before { content: "\f508"; } + Icon_question_octagon, //before { content: "\f509"; } + Icon_question_square_fill, //before { content: "\f50a"; } + Icon_question_square, //before { content: "\f50b"; } + Icon_question, //before { content: "\f50c"; } + Icon_rainbow, //before { content: "\f50d"; } + Icon_receipt_cutoff, //before { content: "\f50e"; } + Icon_receipt, //before { content: "\f50f"; } + Icon_reception_0, //before { content: "\f510"; } + Icon_reception_1, //before { content: "\f511"; } + Icon_reception_2, //before { content: "\f512"; } + Icon_reception_3, //before { content: "\f513"; } + Icon_reception_4, //before { content: "\f514"; } + Icon_record_btn_fill, //before { content: "\f515"; } + Icon_record_btn, //before { content: "\f516"; } + Icon_record_circle_fill, //before { content: "\f517"; } + Icon_record_circle, //before { content: "\f518"; } + Icon_record_fill, //before { content: "\f519"; } + Icon_record, //before { content: "\f51a"; } + Icon_record2_fill, //before { content: "\f51b"; } + Icon_record2, //before { content: "\f51c"; } + Icon_reply_all_fill, //before { content: "\f51d"; } + Icon_reply_all, //before { content: "\f51e"; } + Icon_reply_fill, //before { content: "\f51f"; } + Icon_reply, //before { content: "\f520"; } + Icon_rss_fill, //before { content: "\f521"; } + Icon_rss, //before { content: "\f522"; } + Icon_rulers, //before { content: "\f523"; } + Icon_save_fill, //before { content: "\f524"; } + Icon_save, //before { content: "\f525"; } + Icon_save2_fill, //before { content: "\f526"; } + Icon_save2, //before { content: "\f527"; } + Icon_scissors, //before { content: "\f528"; } + Icon_screwdriver, //before { content: "\f529"; } + Icon_search, //before { content: "\f52a"; } + Icon_segmented_nav, //before { content: "\f52b"; } + Icon_server, //before { content: "\f52c"; } + Icon_share_fill, //before { content: "\f52d"; } + Icon_share, //before { content: "\f52e"; } + Icon_shield_check, //before { content: "\f52f"; } + Icon_shield_exclamation, //before { content: "\f530"; } + Icon_shield_fill_check, //before { content: "\f531"; } + Icon_shield_fill_exclamation, //before { content: "\f532"; } + Icon_shield_fill_minus, //before { content: "\f533"; } + Icon_shield_fill_plus, //before { content: "\f534"; } + Icon_shield_fill_x, //before { content: "\f535"; } + Icon_shield_fill, //before { content: "\f536"; } + Icon_shield_lock_fill, //before { content: "\f537"; } + Icon_shield_lock, //before { content: "\f538"; } + Icon_shield_minus, //before { content: "\f539"; } + Icon_shield_plus, //before { content: "\f53a"; } + Icon_shield_shaded, //before { content: "\f53b"; } + Icon_shield_slash_fill, //before { content: "\f53c"; } + Icon_shield_slash, //before { content: "\f53d"; } + Icon_shield_x, //before { content: "\f53e"; } + Icon_shield, //before { content: "\f53f"; } + Icon_shift_fill, //before { content: "\f540"; } + Icon_shift, //before { content: "\f541"; } + Icon_shop_window, //before { content: "\f542"; } + Icon_shop, //before { content: "\f543"; } + Icon_shuffle, //before { content: "\f544"; } + Icon_signpost_2_fill, //before { content: "\f545"; } + Icon_signpost_2, //before { content: "\f546"; } + Icon_signpost_fill, //before { content: "\f547"; } + Icon_signpost_split_fill, //before { content: "\f548"; } + Icon_signpost_split, //before { content: "\f549"; } + Icon_signpost, //before { content: "\f54a"; } + Icon_sim_fill, //before { content: "\f54b"; } + Icon_sim, //before { content: "\f54c"; } + Icon_skip_backward_btn_fill, //before { content: "\f54d"; } + Icon_skip_backward_btn, //before { content: "\f54e"; } + Icon_skip_backward_circle_fill, //before { content: "\f54f"; } + Icon_skip_backward_circle, //before { content: "\f550"; } + Icon_skip_backward_fill, //before { content: "\f551"; } + Icon_skip_backward, //before { content: "\f552"; } + Icon_skip_end_btn_fill, //before { content: "\f553"; } + Icon_skip_end_btn, //before { content: "\f554"; } + Icon_skip_end_circle_fill, //before { content: "\f555"; } + Icon_skip_end_circle, //before { content: "\f556"; } + Icon_skip_end_fill, //before { content: "\f557"; } + Icon_skip_end, //before { content: "\f558"; } + Icon_skip_forward_btn_fill, //before { content: "\f559"; } + Icon_skip_forward_btn, //before { content: "\f55a"; } + Icon_skip_forward_circle_fill, //before { content: "\f55b"; } + Icon_skip_forward_circle, //before { content: "\f55c"; } + Icon_skip_forward_fill, //before { content: "\f55d"; } + Icon_skip_forward, //before { content: "\f55e"; } + Icon_skip_start_btn_fill, //before { content: "\f55f"; } + Icon_skip_start_btn, //before { content: "\f560"; } + Icon_skip_start_circle_fill, //before { content: "\f561"; } + Icon_skip_start_circle, //before { content: "\f562"; } + Icon_skip_start_fill, //before { content: "\f563"; } + Icon_skip_start, //before { content: "\f564"; } + Icon_slack, //before { content: "\f565"; } + Icon_slash_circle_fill, //before { content: "\f566"; } + Icon_slash_circle, //before { content: "\f567"; } + Icon_slash_square_fill, //before { content: "\f568"; } + Icon_slash_square, //before { content: "\f569"; } + Icon_slash, //before { content: "\f56a"; } + Icon_sliders, //before { content: "\f56b"; } + Icon_smartwatch, //before { content: "\f56c"; } + Icon_snow, //before { content: "\f56d"; } + Icon_snow2, //before { content: "\f56e"; } + Icon_snow3, //before { content: "\f56f"; } + Icon_sort_alpha_down_alt, //before { content: "\f570"; } + Icon_sort_alpha_down, //before { content: "\f571"; } + Icon_sort_alpha_up_alt, //before { content: "\f572"; } + Icon_sort_alpha_up, //before { content: "\f573"; } + Icon_sort_down_alt, //before { content: "\f574"; } + Icon_sort_down, //before { content: "\f575"; } + Icon_sort_numeric_down_alt, //before { content: "\f576"; } + Icon_sort_numeric_down, //before { content: "\f577"; } + Icon_sort_numeric_up_alt, //before { content: "\f578"; } + Icon_sort_numeric_up, //before { content: "\f579"; } + Icon_sort_up_alt, //before { content: "\f57a"; } + Icon_sort_up, //before { content: "\f57b"; } + Icon_soundwave, //before { content: "\f57c"; } + Icon_speaker_fill, //before { content: "\f57d"; } + Icon_speaker, //before { content: "\f57e"; } + Icon_speedometer, //before { content: "\f57f"; } + Icon_speedometer2, //before { content: "\f580"; } + Icon_spellcheck, //before { content: "\f581"; } + Icon_square_fill, //before { content: "\f582"; } + Icon_square_half, //before { content: "\f583"; } + Icon_square, //before { content: "\f584"; } + Icon_stack, //before { content: "\f585"; } + Icon_star_fill, //before { content: "\f586"; } + Icon_star_half, //before { content: "\f587"; } + Icon_star, //before { content: "\f588"; } + Icon_stars, //before { content: "\f589"; } + Icon_stickies_fill, //before { content: "\f58a"; } + Icon_stickies, //before { content: "\f58b"; } + Icon_sticky_fill, //before { content: "\f58c"; } + Icon_sticky, //before { content: "\f58d"; } + Icon_stop_btn_fill, //before { content: "\f58e"; } + Icon_stop_btn, //before { content: "\f58f"; } + Icon_stop_circle_fill, //before { content: "\f590"; } + Icon_stop_circle, //before { content: "\f591"; } + Icon_stop_fill, //before { content: "\f592"; } + Icon_stop, //before { content: "\f593"; } + Icon_stoplights_fill, //before { content: "\f594"; } + Icon_stoplights, //before { content: "\f595"; } + Icon_stopwatch_fill, //before { content: "\f596"; } + Icon_stopwatch, //before { content: "\f597"; } + Icon_subtract, //before { content: "\f598"; } + Icon_suit_club_fill, //before { content: "\f599"; } + Icon_suit_club, //before { content: "\f59a"; } + Icon_suit_diamond_fill, //before { content: "\f59b"; } + Icon_suit_diamond, //before { content: "\f59c"; } + Icon_suit_heart_fill, //before { content: "\f59d"; } + Icon_suit_heart, //before { content: "\f59e"; } + Icon_suit_spade_fill, //before { content: "\f59f"; } + Icon_suit_spade, //before { content: "\f5a0"; } + Icon_sun_fill, //before { content: "\f5a1"; } + Icon_sun, //before { content: "\f5a2"; } + Icon_sunglasses, //before { content: "\f5a3"; } + Icon_sunrise_fill, //before { content: "\f5a4"; } + Icon_sunrise, //before { content: "\f5a5"; } + Icon_sunset_fill, //before { content: "\f5a6"; } + Icon_sunset, //before { content: "\f5a7"; } + Icon_symmetry_horizontal, //before { content: "\f5a8"; } + Icon_symmetry_vertical, //before { content: "\f5a9"; } + Icon_table, //before { content: "\f5aa"; } + Icon_tablet_fill, //before { content: "\f5ab"; } + Icon_tablet_landscape_fill, //before { content: "\f5ac"; } + Icon_tablet_landscape, //before { content: "\f5ad"; } + Icon_tablet, //before { content: "\f5ae"; } + Icon_tag_fill, //before { content: "\f5af"; } + Icon_tag, //before { content: "\f5b0"; } + Icon_tags_fill, //before { content: "\f5b1"; } + Icon_tags, //before { content: "\f5b2"; } + Icon_telegram, //before { content: "\f5b3"; } + Icon_telephone_fill, //before { content: "\f5b4"; } + Icon_telephone_forward_fill, //before { content: "\f5b5"; } + Icon_telephone_forward, //before { content: "\f5b6"; } + Icon_telephone_inbound_fill, //before { content: "\f5b7"; } + Icon_telephone_inbound, //before { content: "\f5b8"; } + Icon_telephone_minus_fill, //before { content: "\f5b9"; } + Icon_telephone_minus, //before { content: "\f5ba"; } + Icon_telephone_outbound_fill, //before { content: "\f5bb"; } + Icon_telephone_outbound, //before { content: "\f5bc"; } + Icon_telephone_plus_fill, //before { content: "\f5bd"; } + Icon_telephone_plus, //before { content: "\f5be"; } + Icon_telephone_x_fill, //before { content: "\f5bf"; } + Icon_telephone_x, //before { content: "\f5c0"; } + Icon_telephone, //before { content: "\f5c1"; } + Icon_terminal_fill, //before { content: "\f5c2"; } + Icon_terminal, //before { content: "\f5c3"; } + Icon_text_center, //before { content: "\f5c4"; } + Icon_text_indent_left, //before { content: "\f5c5"; } + Icon_text_indent_right, //before { content: "\f5c6"; } + Icon_text_left, //before { content: "\f5c7"; } + Icon_text_paragraph, //before { content: "\f5c8"; } + Icon_text_right, //before { content: "\f5c9"; } + Icon_textarea_resize, //before { content: "\f5ca"; } + Icon_textarea_t, //before { content: "\f5cb"; } + Icon_textarea, //before { content: "\f5cc"; } + Icon_thermometer_half, //before { content: "\f5cd"; } + Icon_thermometer_high, //before { content: "\f5ce"; } + Icon_thermometer_low, //before { content: "\f5cf"; } + Icon_thermometer_snow, //before { content: "\f5d0"; } + Icon_thermometer_sun, //before { content: "\f5d1"; } + Icon_thermometer, //before { content: "\f5d2"; } + Icon_three_dots_vertical, //before { content: "\f5d3"; } + Icon_three_dots, //before { content: "\f5d4"; } + Icon_toggle_off, //before { content: "\f5d5"; } + Icon_toggle_on, //before { content: "\f5d6"; } + Icon_toggle2_off, //before { content: "\f5d7"; } + Icon_toggle2_on, //before { content: "\f5d8"; } + Icon_toggles, //before { content: "\f5d9"; } + Icon_toggles2, //before { content: "\f5da"; } + Icon_tools, //before { content: "\f5db"; } + Icon_tornado, //before { content: "\f5dc"; } + Icon_trash_fill, //before { content: "\f5dd"; } + Icon_trash, //before { content: "\f5de"; } + Icon_trash2_fill, //before { content: "\f5df"; } + Icon_trash2, //before { content: "\f5e0"; } + Icon_tree_fill, //before { content: "\f5e1"; } + Icon_tree, //before { content: "\f5e2"; } + Icon_triangle_fill, //before { content: "\f5e3"; } + Icon_triangle_half, //before { content: "\f5e4"; } + Icon_triangle, //before { content: "\f5e5"; } + Icon_trophy_fill, //before { content: "\f5e6"; } + Icon_trophy, //before { content: "\f5e7"; } + Icon_tropical_storm, //before { content: "\f5e8"; } + Icon_truck_flatbed, //before { content: "\f5e9"; } + Icon_truck, //before { content: "\f5ea"; } + Icon_tsunami, //before { content: "\f5eb"; } + Icon_tv_fill, //before { content: "\f5ec"; } + Icon_tv, //before { content: "\f5ed"; } + Icon_twitch, //before { content: "\f5ee"; } + Icon_twitter, //before { content: "\f5ef"; } + Icon_type_bold, //before { content: "\f5f0"; } + Icon_type_h1, //before { content: "\f5f1"; } + Icon_type_h2, //before { content: "\f5f2"; } + Icon_type_h3, //before { content: "\f5f3"; } + Icon_type_italic, //before { content: "\f5f4"; } + Icon_type_strikethrough, //before { content: "\f5f5"; } + Icon_type_underline, //before { content: "\f5f6"; } + Icon_type, //before { content: "\f5f7"; } + Icon_ui_checks_grid, //before { content: "\f5f8"; } + Icon_ui_checks, //before { content: "\f5f9"; } + Icon_ui_radios_grid, //before { content: "\f5fa"; } + Icon_ui_radios, //before { content: "\f5fb"; } + Icon_umbrella_fill, //before { content: "\f5fc"; } + Icon_umbrella, //before { content: "\f5fd"; } + Icon_union, //before { content: "\f5fe"; } + Icon_unlock_fill, //before { content: "\f5ff"; } + Icon_unlock, //before { content: "\f600"; } + Icon_upc_scan, //before { content: "\f601"; } + Icon_upc, //before { content: "\f602"; } + Icon_upload, //before { content: "\f603"; } + Icon_vector_pen, //before { content: "\f604"; } + Icon_view_list, //before { content: "\f605"; } + Icon_view_stacked, //before { content: "\f606"; } + Icon_vinyl_fill, //before { content: "\f607"; } + Icon_vinyl, //before { content: "\f608"; } + Icon_voicemail, //before { content: "\f609"; } + Icon_volume_down_fill, //before { content: "\f60a"; } + Icon_volume_down, //before { content: "\f60b"; } + Icon_volume_mute_fill, //before { content: "\f60c"; } + Icon_volume_mute, //before { content: "\f60d"; } + Icon_volume_off_fill, //before { content: "\f60e"; } + Icon_volume_off, //before { content: "\f60f"; } + Icon_volume_up_fill, //before { content: "\f610"; } + Icon_volume_up, //before { content: "\f611"; } + Icon_vr, //before { content: "\f612"; } + Icon_wallet_fill, //before { content: "\f613"; } + Icon_wallet, //before { content: "\f614"; } + Icon_wallet2, //before { content: "\f615"; } + Icon_watch, //before { content: "\f616"; } + Icon_water, //before { content: "\f617"; } + Icon_whatsapp, //before { content: "\f618"; } + Icon_wifi_1, //before { content: "\f619"; } + Icon_wifi_2, //before { content: "\f61a"; } + Icon_wifi_off, //before { content: "\f61b"; } + Icon_wifi, //before { content: "\f61c"; } + Icon_wind, //before { content: "\f61d"; } + Icon_window_dock, //before { content: "\f61e"; } + Icon_window_sidebar, //before { content: "\f61f"; } + Icon_window, //before { content: "\f620"; } + Icon_wrench, //before { content: "\f621"; } + Icon_x_circle_fill, //before { content: "\f622"; } + Icon_x_circle, //before { content: "\f623"; } + Icon_x_diamond_fill, //before { content: "\f624"; } + Icon_x_diamond, //before { content: "\f625"; } + Icon_x_octagon_fill, //before { content: "\f626"; } + Icon_x_octagon, //before { content: "\f627"; } + Icon_x_square_fill, //before { content: "\f628"; } + Icon_x_square, //before { content: "\f629"; } + Icon_x, //before { content: "\f62a"; } + Icon_youtube, //before { content: "\f62b"; } + Icon_zoom_in, //before { content: "\f62c"; } + Icon_zoom_out, //before { content: "\f62d"; } + Icon_bank, //before { content: "\f62e"; } + Icon_bank2, //before { content: "\f62f"; } + Icon_bell_slash_fill, //before { content: "\f630"; } + Icon_bell_slash, //before { content: "\f631"; } + Icon_cash_coin, //before { content: "\f632"; } + Icon_check_lg, //before { content: "\f633"; } + Icon_coin, //before { content: "\f634"; } + Icon_currency_bitcoin, //before { content: "\f635"; } + Icon_currency_dollar, //before { content: "\f636"; } + Icon_currency_euro, //before { content: "\f637"; } + Icon_currency_exchange, //before { content: "\f638"; } + Icon_currency_pound, //before { content: "\f639"; } + Icon_currency_yen, //before { content: "\f63a"; } + Icon_dash_lg, //before { content: "\f63b"; } + Icon_exclamation_lg, //before { content: "\f63c"; } + Icon_file_earmark_pdf_fill, //before { content: "\f63d"; } + Icon_file_earmark_pdf, //before { content: "\f63e"; } + Icon_file_pdf_fill, //before { content: "\f63f"; } + Icon_file_pdf, //before { content: "\f640"; } + Icon_gender_ambiguous, //before { content: "\f641"; } + Icon_gender_female, //before { content: "\f642"; } + Icon_gender_male, //before { content: "\f643"; } + Icon_gender_trans, //before { content: "\f644"; } + Icon_headset_vr, //before { content: "\f645"; } + Icon_info_lg, //before { content: "\f646"; } + Icon_mastodon, //before { content: "\f647"; } + Icon_messenger, //before { content: "\f648"; } + Icon_piggy_bank_fill, //before { content: "\f649"; } + Icon_piggy_bank, //before { content: "\f64a"; } + Icon_pin_map_fill, //before { content: "\f64b"; } + Icon_pin_map, //before { content: "\f64c"; } + Icon_plus_lg, //before { content: "\f64d"; } + Icon_question_lg, //before { content: "\f64e"; } + Icon_recycle, //before { content: "\f64f"; } + Icon_reddit, //before { content: "\f650"; } + Icon_safe_fill, //before { content: "\f651"; } + Icon_safe2_fill, //before { content: "\f652"; } + Icon_safe2, //before { content: "\f653"; } + Icon_sd_card_fill, //before { content: "\f654"; } + Icon_sd_card, //before { content: "\f655"; } + Icon_skype, //before { content: "\f656"; } + Icon_slash_lg, //before { content: "\f657"; } + Icon_translate, //before { content: "\f658"; } + Icon_x_lg, //before { content: "\f659"; } + Icon_safe, //before { content: "\f65a"; } + Icon_apple, //before { content: "\f65b"; } + Icon_microsoft, //before { content: "\f65d"; } + Icon_windows, //before { content: "\f65e"; } + Icon_behance, //before { content: "\f65c"; } + Icon_dribbble, //before { content: "\f65f"; } + Icon_line, //before { content: "\f660"; } + Icon_medium, //before { content: "\f661"; } + Icon_paypal, //before { content: "\f662"; } + Icon_pinterest, //before { content: "\f663"; } + Icon_signal, //before { content: "\f664"; } + Icon_snapchat, //before { content: "\f665"; } + Icon_spotify, //before { content: "\f666"; } + Icon_stack_overflow, //before { content: "\f667"; } + Icon_strava, //before { content: "\f668"; } + Icon_wordpress, //before { content: "\f669"; } + Icon_vimeo, //before { content: "\f66a"; } + Icon_activity, //before { content: "\f66b"; } + Icon_easel2_fill, //before { content: "\f66c"; } + Icon_easel2, //before { content: "\f66d"; } + Icon_easel3_fill, //before { content: "\f66e"; } + Icon_easel3, //before { content: "\f66f"; } + Icon_fan, //before { content: "\f670"; } + Icon_fingerprint, //before { content: "\f671"; } + Icon_graph_down_arrow, //before { content: "\f672"; } + Icon_graph_up_arrow, //before { content: "\f673"; } + Icon_hypnotize, //before { content: "\f674"; } + Icon_magic, //before { content: "\f675"; } + Icon_person_rolodex, //before { content: "\f676"; } + Icon_person_video, //before { content: "\f677"; } + Icon_person_video2, //before { content: "\f678"; } + Icon_person_video3, //before { content: "\f679"; } + Icon_person_workspace, //before { content: "\f67a"; } + Icon_radioactive, //before { content: "\f67b"; } + Icon_webcam_fill, //before { content: "\f67c"; } + Icon_webcam, //before { content: "\f67d"; } + Icon_yin_yang, //before { content: "\f67e"; } + Icon_bandaid_fill, //before { content: "\f680"; } + Icon_bandaid, //before { content: "\f681"; } + Icon_bluetooth, //before { content: "\f682"; } + Icon_body_text, //before { content: "\f683"; } + Icon_boombox, //before { content: "\f684"; } + Icon_boxes, //before { content: "\f685"; } + Icon_dpad_fill, //before { content: "\f686"; } + Icon_dpad, //before { content: "\f687"; } + Icon_ear_fill, //before { content: "\f688"; } + Icon_ear, //before { content: "\f689"; } + Icon_envelope_check_fill, //before { content: "\f68b"; } + Icon_envelope_check, //before { content: "\f68c"; } + Icon_envelope_dash_fill, //before { content: "\f68e"; } + Icon_envelope_dash, //before { content: "\f68f"; } + Icon_envelope_exclamation_fill, //before { content: "\f691"; } + Icon_envelope_exclamation, //before { content: "\f692"; } + Icon_envelope_plus_fill, //before { content: "\f693"; } + Icon_envelope_plus, //before { content: "\f694"; } + Icon_envelope_slash_fill, //before { content: "\f696"; } + Icon_envelope_slash, //before { content: "\f697"; } + Icon_envelope_x_fill, //before { content: "\f699"; } + Icon_envelope_x, //before { content: "\f69a"; } + Icon_explicit_fill, //before { content: "\f69b"; } + Icon_explicit, //before { content: "\f69c"; } + Icon_git, //before { content: "\f69d"; } + Icon_infinity, //before { content: "\f69e"; } + Icon_list_columns_reverse, //before { content: "\f69f"; } + Icon_list_columns, //before { content: "\f6a0"; } + Icon_meta, //before { content: "\f6a1"; } + Icon_nintendo_switch, //before { content: "\f6a4"; } + Icon_pc_display_horizontal, //before { content: "\f6a5"; } + Icon_pc_display, //before { content: "\f6a6"; } + Icon_pc_horizontal, //before { content: "\f6a7"; } + Icon_pc, //before { content: "\f6a8"; } + Icon_playstation, //before { content: "\f6a9"; } + Icon_plus_slash_minus, //before { content: "\f6aa"; } + Icon_projector_fill, //before { content: "\f6ab"; } + Icon_projector, //before { content: "\f6ac"; } + Icon_qr_code_scan, //before { content: "\f6ad"; } + Icon_qr_code, //before { content: "\f6ae"; } + Icon_quora, //before { content: "\f6af"; } + Icon_quote, //before { content: "\f6b0"; } + Icon_robot, //before { content: "\f6b1"; } + Icon_send_check_fill, //before { content: "\f6b2"; } + Icon_send_check, //before { content: "\f6b3"; } + Icon_send_dash_fill, //before { content: "\f6b4"; } + Icon_send_dash, //before { content: "\f6b5"; } + Icon_send_exclamation_fill, //before { content: "\f6b7"; } + Icon_send_exclamation, //before { content: "\f6b8"; } + Icon_send_fill, //before { content: "\f6b9"; } + Icon_send_plus_fill, //before { content: "\f6ba"; } + Icon_send_plus, //before { content: "\f6bb"; } + Icon_send_slash_fill, //before { content: "\f6bc"; } + Icon_send_slash, //before { content: "\f6bd"; } + Icon_send_x_fill, //before { content: "\f6be"; } + Icon_send_x, //before { content: "\f6bf"; } + Icon_send, //before { content: "\f6c0"; } + Icon_steam, //before { content: "\f6c1"; } + Icon_terminal_dash, //before { content: "\f6c3"; } + Icon_terminal_plus, //before { content: "\f6c4"; } + Icon_terminal_split, //before { content: "\f6c5"; } + Icon_ticket_detailed_fill, //before { content: "\f6c6"; } + Icon_ticket_detailed, //before { content: "\f6c7"; } + Icon_ticket_fill, //before { content: "\f6c8"; } + Icon_ticket_perforated_fill, //before { content: "\f6c9"; } + Icon_ticket_perforated, //before { content: "\f6ca"; } + Icon_ticket, //before { content: "\f6cb"; } + Icon_tiktok, //before { content: "\f6cc"; } + Icon_window_dash, //before { content: "\f6cd"; } + Icon_window_desktop, //before { content: "\f6ce"; } + Icon_window_fullscreen, //before { content: "\f6cf"; } + Icon_window_plus, //before { content: "\f6d0"; } + Icon_window_split, //before { content: "\f6d1"; } + Icon_window_stack, //before { content: "\f6d2"; } + Icon_window_x, //before { content: "\f6d3"; } + Icon_xbox, //before { content: "\f6d4"; } + Icon_ethernet, //before { content: "\f6d5"; } + Icon_hdmi_fill, //before { content: "\f6d6"; } + Icon_hdmi, //before { content: "\f6d7"; } + Icon_usb_c_fill, //before { content: "\f6d8"; } + Icon_usb_c, //before { content: "\f6d9"; } + Icon_usb_fill, //before { content: "\f6da"; } + Icon_usb_plug_fill, //before { content: "\f6db"; } + Icon_usb_plug, //before { content: "\f6dc"; } + Icon_usb_symbol, //before { content: "\f6dd"; } + Icon_usb, //before { content: "\f6de"; } + Icon_boombox_fill, //before { content: "\f6df"; } + Icon_displayport, //before { content: "\f6e1"; } + Icon_gpu_card, //before { content: "\f6e2"; } + Icon_memory, //before { content: "\f6e3"; } + Icon_modem_fill, //before { content: "\f6e4"; } + Icon_modem, //before { content: "\f6e5"; } + Icon_motherboard_fill, //before { content: "\f6e6"; } + Icon_motherboard, //before { content: "\f6e7"; } + Icon_optical_audio_fill, //before { content: "\f6e8"; } + Icon_optical_audio, //before { content: "\f6e9"; } + Icon_pci_card, //before { content: "\f6ea"; } + Icon_router_fill, //before { content: "\f6eb"; } + Icon_router, //before { content: "\f6ec"; } + Icon_thunderbolt_fill, //before { content: "\f6ef"; } + Icon_thunderbolt, //before { content: "\f6f0"; } + Icon_usb_drive_fill, //before { content: "\f6f1"; } + Icon_usb_drive, //before { content: "\f6f2"; } + Icon_usb_micro_fill, //before { content: "\f6f3"; } + Icon_usb_micro, //before { content: "\f6f4"; } + Icon_usb_mini_fill, //before { content: "\f6f5"; } + Icon_usb_mini, //before { content: "\f6f6"; } + Icon_cloud_haze2, //before { content: "\f6f7"; } + Icon_device_hdd_fill, //before { content: "\f6f8"; } + Icon_device_hdd, //before { content: "\f6f9"; } + Icon_device_ssd_fill, //before { content: "\f6fa"; } + Icon_device_ssd, //before { content: "\f6fb"; } + Icon_displayport_fill, //before { content: "\f6fc"; } + Icon_mortarboard_fill, //before { content: "\f6fd"; } + Icon_mortarboard, //before { content: "\f6fe"; } + Icon_terminal_x, //before { content: "\f6ff"; } + Icon_arrow_through_heart_fill, //before { content: "\f700"; } + Icon_arrow_through_heart, //before { content: "\f701"; } + Icon_badge_sd_fill, //before { content: "\f702"; } + Icon_badge_sd, //before { content: "\f703"; } + Icon_bag_heart_fill, //before { content: "\f704"; } + Icon_bag_heart, //before { content: "\f705"; } + Icon_balloon_fill, //before { content: "\f706"; } + Icon_balloon_heart_fill, //before { content: "\f707"; } + Icon_balloon_heart, //before { content: "\f708"; } + Icon_balloon, //before { content: "\f709"; } + Icon_box2_fill, //before { content: "\f70a"; } + Icon_box2_heart_fill, //before { content: "\f70b"; } + Icon_box2_heart, //before { content: "\f70c"; } + Icon_box2, //before { content: "\f70d"; } + Icon_braces_asterisk, //before { content: "\f70e"; } + Icon_calendar_heart_fill, //before { content: "\f70f"; } + Icon_calendar_heart, //before { content: "\f710"; } + Icon_calendar2_heart_fill, //before { content: "\f711"; } + Icon_calendar2_heart, //before { content: "\f712"; } + Icon_chat_heart_fill, //before { content: "\f713"; } + Icon_chat_heart, //before { content: "\f714"; } + Icon_chat_left_heart_fill, //before { content: "\f715"; } + Icon_chat_left_heart, //before { content: "\f716"; } + Icon_chat_right_heart_fill, //before { content: "\f717"; } + Icon_chat_right_heart, //before { content: "\f718"; } + Icon_chat_square_heart_fill, //before { content: "\f719"; } + Icon_chat_square_heart, //before { content: "\f71a"; } + Icon_clipboard_check_fill, //before { content: "\f71b"; } + Icon_clipboard_data_fill, //before { content: "\f71c"; } + Icon_clipboard_fill, //before { content: "\f71d"; } + Icon_clipboard_heart_fill, //before { content: "\f71e"; } + Icon_clipboard_heart, //before { content: "\f71f"; } + Icon_clipboard_minus_fill, //before { content: "\f720"; } + Icon_clipboard_plus_fill, //before { content: "\f721"; } + Icon_clipboard_pulse, //before { content: "\f722"; } + Icon_clipboard_x_fill, //before { content: "\f723"; } + Icon_clipboard2_check_fill, //before { content: "\f724"; } + Icon_clipboard2_check, //before { content: "\f725"; } + Icon_clipboard2_data_fill, //before { content: "\f726"; } + Icon_clipboard2_data, //before { content: "\f727"; } + Icon_clipboard2_fill, //before { content: "\f728"; } + Icon_clipboard2_heart_fill, //before { content: "\f729"; } + Icon_clipboard2_heart, //before { content: "\f72a"; } + Icon_clipboard2_minus_fill, //before { content: "\f72b"; } + Icon_clipboard2_minus, //before { content: "\f72c"; } + Icon_clipboard2_plus_fill, //before { content: "\f72d"; } + Icon_clipboard2_plus, //before { content: "\f72e"; } + Icon_clipboard2_pulse_fill, //before { content: "\f72f"; } + Icon_clipboard2_pulse, //before { content: "\f730"; } + Icon_clipboard2_x_fill, //before { content: "\f731"; } + Icon_clipboard2_x, //before { content: "\f732"; } + Icon_clipboard2, //before { content: "\f733"; } + Icon_emoji_kiss_fill, //before { content: "\f734"; } + Icon_emoji_kiss, //before { content: "\f735"; } + Icon_envelope_heart_fill, //before { content: "\f736"; } + Icon_envelope_heart, //before { content: "\f737"; } + Icon_envelope_open_heart_fill, //before { content: "\f738"; } + Icon_envelope_open_heart, //before { content: "\f739"; } + Icon_envelope_paper_fill, //before { content: "\f73a"; } + Icon_envelope_paper_heart_fill, //before { content: "\f73b"; } + Icon_envelope_paper_heart, //before { content: "\f73c"; } + Icon_envelope_paper, //before { content: "\f73d"; } + Icon_filetype_aac, //before { content: "\f73e"; } + Icon_filetype_ai, //before { content: "\f73f"; } + Icon_filetype_bmp, //before { content: "\f740"; } + Icon_filetype_cs, //before { content: "\f741"; } + Icon_filetype_css, //before { content: "\f742"; } + Icon_filetype_csv, //before { content: "\f743"; } + Icon_filetype_doc, //before { content: "\f744"; } + Icon_filetype_docx, //before { content: "\f745"; } + Icon_filetype_exe, //before { content: "\f746"; } + Icon_filetype_gif, //before { content: "\f747"; } + Icon_filetype_heic, //before { content: "\f748"; } + Icon_filetype_html, //before { content: "\f749"; } + Icon_filetype_java, //before { content: "\f74a"; } + Icon_filetype_jpg, //before { content: "\f74b"; } + Icon_filetype_js, //before { content: "\f74c"; } + Icon_filetype_jsx, //before { content: "\f74d"; } + Icon_filetype_key, //before { content: "\f74e"; } + Icon_filetype_m4p, //before { content: "\f74f"; } + Icon_filetype_md, //before { content: "\f750"; } + Icon_filetype_mdx, //before { content: "\f751"; } + Icon_filetype_mov, //before { content: "\f752"; } + Icon_filetype_mp3, //before { content: "\f753"; } + Icon_filetype_mp4, //before { content: "\f754"; } + Icon_filetype_otf, //before { content: "\f755"; } + Icon_filetype_pdf, //before { content: "\f756"; } + Icon_filetype_php, //before { content: "\f757"; } + Icon_filetype_png, //before { content: "\f758"; } + Icon_filetype_ppt, //before { content: "\f75a"; } + Icon_filetype_psd, //before { content: "\f75b"; } + Icon_filetype_py, //before { content: "\f75c"; } + Icon_filetype_raw, //before { content: "\f75d"; } + Icon_filetype_rb, //before { content: "\f75e"; } + Icon_filetype_sass, //before { content: "\f75f"; } + Icon_filetype_scss, //before { content: "\f760"; } + Icon_filetype_sh, //before { content: "\f761"; } + Icon_filetype_svg, //before { content: "\f762"; } + Icon_filetype_tiff, //before { content: "\f763"; } + Icon_filetype_tsx, //before { content: "\f764"; } + Icon_filetype_ttf, //before { content: "\f765"; } + Icon_filetype_txt, //before { content: "\f766"; } + Icon_filetype_wav, //before { content: "\f767"; } + Icon_filetype_woff, //before { content: "\f768"; } + Icon_filetype_xls, //before { content: "\f76a"; } + Icon_filetype_xml, //before { content: "\f76b"; } + Icon_filetype_yml, //before { content: "\f76c"; } + Icon_heart_arrow, //before { content: "\f76d"; } + Icon_heart_pulse_fill, //before { content: "\f76e"; } + Icon_heart_pulse, //before { content: "\f76f"; } + Icon_heartbreak_fill, //before { content: "\f770"; } + Icon_heartbreak, //before { content: "\f771"; } + Icon_hearts, //before { content: "\f772"; } + Icon_hospital_fill, //before { content: "\f773"; } + Icon_hospital, //before { content: "\f774"; } + Icon_house_heart_fill, //before { content: "\f775"; } + Icon_house_heart, //before { content: "\f776"; } + Icon_incognito, //before { content: "\f777"; } + Icon_magnet_fill, //before { content: "\f778"; } + Icon_magnet, //before { content: "\f779"; } + Icon_person_heart, //before { content: "\f77a"; } + Icon_person_hearts, //before { content: "\f77b"; } + Icon_phone_flip, //before { content: "\f77c"; } + Icon_plugin, //before { content: "\f77d"; } + Icon_postage_fill, //before { content: "\f77e"; } + Icon_postage_heart_fill, //before { content: "\f77f"; } + Icon_postage_heart, //before { content: "\f780"; } + Icon_postage, //before { content: "\f781"; } + Icon_postcard_fill, //before { content: "\f782"; } + Icon_postcard_heart_fill, //before { content: "\f783"; } + Icon_postcard_heart, //before { content: "\f784"; } + Icon_postcard, //before { content: "\f785"; } + Icon_search_heart_fill, //before { content: "\f786"; } + Icon_search_heart, //before { content: "\f787"; } + Icon_sliders2_vertical, //before { content: "\f788"; } + Icon_sliders2, //before { content: "\f789"; } + Icon_trash3_fill, //before { content: "\f78a"; } + Icon_trash3, //before { content: "\f78b"; } + Icon_valentine, //before { content: "\f78c"; } + Icon_valentine2, //before { content: "\f78d"; } + Icon_wrench_adjustable_circle_fill, //before { content: "\f78e"; } + Icon_wrench_adjustable_circle, //before { content: "\f78f"; } + Icon_wrench_adjustable, //before { content: "\f790"; } + Icon_filetype_json, //before { content: "\f791"; } + Icon_filetype_pptx, //before { content: "\f792"; } + Icon_filetype_xlsx, //before { content: "\f793"; } + Icon_1_circle_fill, //before { content: "\f796"; } + Icon_1_circle, //before { content: "\f797"; } + Icon_1_square_fill, //before { content: "\f798"; } + Icon_1_square, //before { content: "\f799"; } + Icon_2_circle_fill, //before { content: "\f79c"; } + Icon_2_circle, //before { content: "\f79d"; } + Icon_2_square_fill, //before { content: "\f79e"; } + Icon_2_square, //before { content: "\f79f"; } + Icon_3_circle_fill, //before { content: "\f7a2"; } + Icon_3_circle, //before { content: "\f7a3"; } + Icon_3_square_fill, //before { content: "\f7a4"; } + Icon_3_square, //before { content: "\f7a5"; } + Icon_4_circle_fill, //before { content: "\f7a8"; } + Icon_4_circle, //before { content: "\f7a9"; } + Icon_4_square_fill, //before { content: "\f7aa"; } + Icon_4_square, //before { content: "\f7ab"; } + Icon_5_circle_fill, //before { content: "\f7ae"; } + Icon_5_circle, //before { content: "\f7af"; } + Icon_5_square_fill, //before { content: "\f7b0"; } + Icon_5_square, //before { content: "\f7b1"; } + Icon_6_circle_fill, //before { content: "\f7b4"; } + Icon_6_circle, //before { content: "\f7b5"; } + Icon_6_square_fill, //before { content: "\f7b6"; } + Icon_6_square, //before { content: "\f7b7"; } + Icon_7_circle_fill, //before { content: "\f7ba"; } + Icon_7_circle, //before { content: "\f7bb"; } + Icon_7_square_fill, //before { content: "\f7bc"; } + Icon_7_square, //before { content: "\f7bd"; } + Icon_8_circle_fill, //before { content: "\f7c0"; } + Icon_8_circle, //before { content: "\f7c1"; } + Icon_8_square_fill, //before { content: "\f7c2"; } + Icon_8_square, //before { content: "\f7c3"; } + Icon_9_circle_fill, //before { content: "\f7c6"; } + Icon_9_circle, //before { content: "\f7c7"; } + Icon_9_square_fill, //before { content: "\f7c8"; } + Icon_9_square, //before { content: "\f7c9"; } + Icon_airplane_engines_fill, //before { content: "\f7ca"; } + Icon_airplane_engines, //before { content: "\f7cb"; } + Icon_airplane_fill, //before { content: "\f7cc"; } + Icon_airplane, //before { content: "\f7cd"; } + Icon_alexa, //before { content: "\f7ce"; } + Icon_alipay, //before { content: "\f7cf"; } + Icon_android, //before { content: "\f7d0"; } + Icon_android2, //before { content: "\f7d1"; } + Icon_box_fill, //before { content: "\f7d2"; } + Icon_box_seam_fill, //before { content: "\f7d3"; } + Icon_browser_chrome, //before { content: "\f7d4"; } + Icon_browser_edge, //before { content: "\f7d5"; } + Icon_browser_firefox, //before { content: "\f7d6"; } + Icon_browser_safari, //before { content: "\f7d7"; } + Icon_c_circle_fill, //before { content: "\f7da"; } + Icon_c_circle, //before { content: "\f7db"; } + Icon_c_square_fill, //before { content: "\f7dc"; } + Icon_c_square, //before { content: "\f7dd"; } + Icon_capsule_pill, //before { content: "\f7de"; } + Icon_capsule, //before { content: "\f7df"; } + Icon_car_front_fill, //before { content: "\f7e0"; } + Icon_car_front, //before { content: "\f7e1"; } + Icon_cassette_fill, //before { content: "\f7e2"; } + Icon_cassette, //before { content: "\f7e3"; } + Icon_cc_circle_fill, //before { content: "\f7e6"; } + Icon_cc_circle, //before { content: "\f7e7"; } + Icon_cc_square_fill, //before { content: "\f7e8"; } + Icon_cc_square, //before { content: "\f7e9"; } + Icon_cup_hot_fill, //before { content: "\f7ea"; } + Icon_cup_hot, //before { content: "\f7eb"; } + Icon_currency_rupee, //before { content: "\f7ec"; } + Icon_dropbox, //before { content: "\f7ed"; } + Icon_escape, //before { content: "\f7ee"; } + Icon_fast_forward_btn_fill, //before { content: "\f7ef"; } + Icon_fast_forward_btn, //before { content: "\f7f0"; } + Icon_fast_forward_circle_fill, //before { content: "\f7f1"; } + Icon_fast_forward_circle, //before { content: "\f7f2"; } + Icon_fast_forward_fill, //before { content: "\f7f3"; } + Icon_fast_forward, //before { content: "\f7f4"; } + Icon_filetype_sql, //before { content: "\f7f5"; } + Icon_fire, //before { content: "\f7f6"; } + Icon_google_play, //before { content: "\f7f7"; } + Icon_h_circle_fill, //before { content: "\f7fa"; } + Icon_h_circle, //before { content: "\f7fb"; } + Icon_h_square_fill, //before { content: "\f7fc"; } + Icon_h_square, //before { content: "\f7fd"; } + Icon_indent, //before { content: "\f7fe"; } + Icon_lungs_fill, //before { content: "\f7ff"; } + Icon_lungs, //before { content: "\f800"; } + Icon_microsoft_teams, //before { content: "\f801"; } + Icon_p_circle_fill, //before { content: "\f804"; } + Icon_p_circle, //before { content: "\f805"; } + Icon_p_square_fill, //before { content: "\f806"; } + Icon_p_square, //before { content: "\f807"; } + Icon_pass_fill, //before { content: "\f808"; } + Icon_pass, //before { content: "\f809"; } + Icon_prescription, //before { content: "\f80a"; } + Icon_prescription2, //before { content: "\f80b"; } + Icon_r_circle_fill, //before { content: "\f80e"; } + Icon_r_circle, //before { content: "\f80f"; } + Icon_r_square_fill, //before { content: "\f810"; } + Icon_r_square, //before { content: "\f811"; } + Icon_repeat_1, //before { content: "\f812"; } + Icon_repeat, //before { content: "\f813"; } + Icon_rewind_btn_fill, //before { content: "\f814"; } + Icon_rewind_btn, //before { content: "\f815"; } + Icon_rewind_circle_fill, //before { content: "\f816"; } + Icon_rewind_circle, //before { content: "\f817"; } + Icon_rewind_fill, //before { content: "\f818"; } + Icon_rewind, //before { content: "\f819"; } + Icon_train_freight_front_fill, //before { content: "\f81a"; } + Icon_train_freight_front, //before { content: "\f81b"; } + Icon_train_front_fill, //before { content: "\f81c"; } + Icon_train_front, //before { content: "\f81d"; } + Icon_train_lightrail_front_fill, //before { content: "\f81e"; } + Icon_train_lightrail_front, //before { content: "\f81f"; } + Icon_truck_front_fill, //before { content: "\f820"; } + Icon_truck_front, //before { content: "\f821"; } + Icon_ubuntu, //before { content: "\f822"; } + Icon_unindent, //before { content: "\f823"; } + Icon_unity, //before { content: "\f824"; } + Icon_universal_access_circle, //before { content: "\f825"; } + Icon_universal_access, //before { content: "\f826"; } + Icon_virus, //before { content: "\f827"; } + Icon_virus2, //before { content: "\f828"; } + Icon_wechat, //before { content: "\f829"; } + Icon_yelp, //before { content: "\f82a"; } + Icon_sign_stop_fill, //before { content: "\f82b"; } + Icon_sign_stop_lights_fill, //before { content: "\f82c"; } + Icon_sign_stop_lights, //before { content: "\f82d"; } + Icon_sign_stop, //before { content: "\f82e"; } + Icon_sign_turn_left_fill, //before { content: "\f82f"; } + Icon_sign_turn_left, //before { content: "\f830"; } + Icon_sign_turn_right_fill, //before { content: "\f831"; } + Icon_sign_turn_right, //before { content: "\f832"; } + Icon_sign_turn_slight_left_fill, //before { content: "\f833"; } + Icon_sign_turn_slight_left, //before { content: "\f834"; } + Icon_sign_turn_slight_right_fill, //before { content: "\f835"; } + Icon_sign_turn_slight_right, //before { content: "\f836"; } + Icon_sign_yield_fill, //before { content: "\f837"; } + Icon_sign_yield, //before { content: "\f838"; } + Icon_ev_station_fill, //before { content: "\f839"; } + Icon_ev_station, //before { content: "\f83a"; } + Icon_fuel_pump_diesel_fill, //before { content: "\f83b"; } + Icon_fuel_pump_diesel, //before { content: "\f83c"; } + Icon_fuel_pump_fill, //before { content: "\f83d"; } + Icon_fuel_pump, //before { content: "\f83e"; } + Icon_0_circle_fill, //before { content: "\f83f"; } + Icon_0_circle, //before { content: "\f840"; } + Icon_0_square_fill, //before { content: "\f841"; } + Icon_0_square, //before { content: "\f842"; } + Icon_rocket_fill, //before { content: "\f843"; } + Icon_rocket_takeoff_fill, //before { content: "\f844"; } + Icon_rocket_takeoff, //before { content: "\f845"; } + Icon_rocket, //before { content: "\f846"; } + Icon_stripe, //before { content: "\f847"; } + Icon_subscript, //before { content: "\f848"; } + Icon_superscript, //before { content: "\f849"; } + Icon_trello, //before { content: "\f84a"; } + Icon_envelope_at_fill, //before { content: "\f84b"; } + Icon_envelope_at, //before { content: "\f84c"; } + Icon_regex, //before { content: "\f84d"; } + Icon_text_wrap, //before { content: "\f84e"; } + Icon_sign_dead_end_fill, //before { content: "\f84f"; } + Icon_sign_dead_end, //before { content: "\f850"; } + Icon_sign_do_not_enter_fill, //before { content: "\f851"; } + Icon_sign_do_not_enter, //before { content: "\f852"; } + Icon_sign_intersection_fill, //before { content: "\f853"; } + Icon_sign_intersection_side_fill, //before { content: "\f854"; } + Icon_sign_intersection_side, //before { content: "\f855"; } + Icon_sign_intersection_t_fill, //before { content: "\f856"; } + Icon_sign_intersection_t, //before { content: "\f857"; } + Icon_sign_intersection_y_fill, //before { content: "\f858"; } + Icon_sign_intersection_y, //before { content: "\f859"; } + Icon_sign_intersection, //before { content: "\f85a"; } + Icon_sign_merge_left_fill, //before { content: "\f85b"; } + Icon_sign_merge_left, //before { content: "\f85c"; } + Icon_sign_merge_right_fill, //before { content: "\f85d"; } + Icon_sign_merge_right, //before { content: "\f85e"; } + Icon_sign_no_left_turn_fill, //before { content: "\f85f"; } + Icon_sign_no_left_turn, //before { content: "\f860"; } + Icon_sign_no_parking_fill, //before { content: "\f861"; } + Icon_sign_no_parking, //before { content: "\f862"; } + Icon_sign_no_right_turn_fill, //before { content: "\f863"; } + Icon_sign_no_right_turn, //before { content: "\f864"; } + Icon_sign_railroad_fill, //before { content: "\f865"; } + Icon_sign_railroad, //before { content: "\f866"; } + Icon_building_add, //before { content: "\f867"; } + Icon_building_check, //before { content: "\f868"; } + Icon_building_dash, //before { content: "\f869"; } + Icon_building_down, //before { content: "\f86a"; } + Icon_building_exclamation, //before { content: "\f86b"; } + Icon_building_fill_add, //before { content: "\f86c"; } + Icon_building_fill_check, //before { content: "\f86d"; } + Icon_building_fill_dash, //before { content: "\f86e"; } + Icon_building_fill_down, //before { content: "\f86f"; } + Icon_building_fill_exclamation, //before { content: "\f870"; } + Icon_building_fill_gear, //before { content: "\f871"; } + Icon_building_fill_lock, //before { content: "\f872"; } + Icon_building_fill_slash, //before { content: "\f873"; } + Icon_building_fill_up, //before { content: "\f874"; } + Icon_building_fill_x, //before { content: "\f875"; } + Icon_building_fill, //before { content: "\f876"; } + Icon_building_gear, //before { content: "\f877"; } + Icon_building_lock, //before { content: "\f878"; } + Icon_building_slash, //before { content: "\f879"; } + Icon_building_up, //before { content: "\f87a"; } + Icon_building_x, //before { content: "\f87b"; } + Icon_buildings_fill, //before { content: "\f87c"; } + Icon_buildings, //before { content: "\f87d"; } + Icon_bus_front_fill, //before { content: "\f87e"; } + Icon_bus_front, //before { content: "\f87f"; } + Icon_ev_front_fill, //before { content: "\f880"; } + Icon_ev_front, //before { content: "\f881"; } + Icon_globe_americas, //before { content: "\f882"; } + Icon_globe_asia_australia, //before { content: "\f883"; } + Icon_globe_central_south_asia, //before { content: "\f884"; } + Icon_globe_europe_africa, //before { content: "\f885"; } + Icon_house_add_fill, //before { content: "\f886"; } + Icon_house_add, //before { content: "\f887"; } + Icon_house_check_fill, //before { content: "\f888"; } + Icon_house_check, //before { content: "\f889"; } + Icon_house_dash_fill, //before { content: "\f88a"; } + Icon_house_dash, //before { content: "\f88b"; } + Icon_house_down_fill, //before { content: "\f88c"; } + Icon_house_down, //before { content: "\f88d"; } + Icon_house_exclamation_fill, //before { content: "\f88e"; } + Icon_house_exclamation, //before { content: "\f88f"; } + Icon_house_gear_fill, //before { content: "\f890"; } + Icon_house_gear, //before { content: "\f891"; } + Icon_house_lock_fill, //before { content: "\f892"; } + Icon_house_lock, //before { content: "\f893"; } + Icon_house_slash_fill, //before { content: "\f894"; } + Icon_house_slash, //before { content: "\f895"; } + Icon_house_up_fill, //before { content: "\f896"; } + Icon_house_up, //before { content: "\f897"; } + Icon_house_x_fill, //before { content: "\f898"; } + Icon_house_x, //before { content: "\f899"; } + Icon_person_add, //before { content: "\f89a"; } + Icon_person_down, //before { content: "\f89b"; } + Icon_person_exclamation, //before { content: "\f89c"; } + Icon_person_fill_add, //before { content: "\f89d"; } + Icon_person_fill_check, //before { content: "\f89e"; } + Icon_person_fill_dash, //before { content: "\f89f"; } + Icon_person_fill_down, //before { content: "\f8a0"; } + Icon_person_fill_exclamation, //before { content: "\f8a1"; } + Icon_person_fill_gear, //before { content: "\f8a2"; } + Icon_person_fill_lock, //before { content: "\f8a3"; } + Icon_person_fill_slash, //before { content: "\f8a4"; } + Icon_person_fill_up, //before { content: "\f8a5"; } + Icon_person_fill_x, //before { content: "\f8a6"; } + Icon_person_gear, //before { content: "\f8a7"; } + Icon_person_lock, //before { content: "\f8a8"; } + Icon_person_slash, //before { content: "\f8a9"; } + Icon_person_up, //before { content: "\f8aa"; } + Icon_scooter, //before { content: "\f8ab"; } + Icon_taxi_front_fill, //before { content: "\f8ac"; } + Icon_taxi_front, //before { content: "\f8ad"; } + Icon_amd, //before { content: "\f8ae"; } + Icon_database_add, //before { content: "\f8af"; } + Icon_database_check, //before { content: "\f8b0"; } + Icon_database_dash, //before { content: "\f8b1"; } + Icon_database_down, //before { content: "\f8b2"; } + Icon_database_exclamation, //before { content: "\f8b3"; } + Icon_database_fill_add, //before { content: "\f8b4"; } + Icon_database_fill_check, //before { content: "\f8b5"; } + Icon_database_fill_dash, //before { content: "\f8b6"; } + Icon_database_fill_down, //before { content: "\f8b7"; } + Icon_database_fill_exclamation, //before { content: "\f8b8"; } + Icon_database_fill_gear, //before { content: "\f8b9"; } + Icon_database_fill_lock, + Icon_database_fill_slash, + Icon_database_fill_up, + Icon_database_fill_x, + Icon_database_fill, + Icon_database_gear, + Icon_database_lock, + Icon_database_slash, + Icon_database_up, + Icon_database_x, + Icon_database, + Icon_houses_fill, + Icon_houses, + Icon_nvidia, + Icon_person_vcard_fill, + Icon_person_vcard, + Icon_sina_weibo, + Icon_tencent_qq, + Icon_wikipedia; + + + public String getClassName() + { + return name().toLowerCase ().replace ( "icon_", "" ).replace ( "_", "-" ); + } + +} diff --git a/src/main/java/dev/zontreck/ariaslib/html/bootstrap/Size.java b/src/main/java/dev/zontreck/ariaslib/html/bootstrap/Size.java new file mode 100644 index 0000000..b537205 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/html/bootstrap/Size.java @@ -0,0 +1,25 @@ +package dev.zontreck.ariaslib.html.bootstrap; + +public enum Size { + Small, + Regular, + Large, + None; + + public String sizeText() { + switch (this) { + case Small: + return "-sm"; + + case None: + return "-none"; + + case Large: + return "-lg"; + + default: + return ""; + + } + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/http/HTTPMethod.java b/src/main/java/dev/zontreck/ariaslib/http/HTTPMethod.java new file mode 100644 index 0000000..162477a --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/http/HTTPMethod.java @@ -0,0 +1,9 @@ +package dev.zontreck.ariaslib.http; + +public enum HTTPMethod +{ + GET, + POST, + PUT, + DELETE +} diff --git a/src/main/java/dev/zontreck/ariaslib/http/HTTPRequest.java b/src/main/java/dev/zontreck/ariaslib/http/HTTPRequest.java new file mode 100644 index 0000000..158d92a --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/http/HTTPRequest.java @@ -0,0 +1,15 @@ +package dev.zontreck.ariaslib.http; + +public class HTTPRequest +{ + + public String url; + + public String method; + public String body; + public String contentType; + + protected HTTPRequest(){ + + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/http/HTTPRequestBuilder.java b/src/main/java/dev/zontreck/ariaslib/http/HTTPRequestBuilder.java new file mode 100644 index 0000000..4e062d5 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/http/HTTPRequestBuilder.java @@ -0,0 +1,134 @@ +package dev.zontreck.ariaslib.http; + + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; + +public class HTTPRequestBuilder +{ + + private HttpURLConnection connection; + private URL url; + private HTTPRequest request = new HTTPRequest(); + + public static HTTPRequestBuilder builder() + { + return new HTTPRequestBuilder(); + } + + protected HTTPRequestBuilder() + { + + } + + /** + * Sets the url in this request to the one supplied + * @param url The url to connect to + * @return Builder instance + * @throws MalformedURLException If the URL supplied was invalid + */ + public HTTPRequestBuilder withURL( String url) throws MalformedURLException { + request.url = url; + this.url = new URL(url); + + return this; + } + + /** + * Sets the HTTP Request method + * @param method The method you want to use + * @see HTTPMethod + * @return Builder instance + */ + public HTTPRequestBuilder withMethod(HTTPMethod method) + { + switch(method) + { + case GET: + { + request.method = "GET"; + break; + } + case POST: { + request.method = "POST"; + if(request.contentType.isEmpty()) request.contentType = "application/x-www-form-urlencoded"; + break; + } + case DELETE:{ + request.method = "DELETE"; + break; + } + case PUT:{ + request.method = "PUT"; + if(request.contentType.isEmpty()) request.contentType = "application/x-www-form-urlencoded"; + break; + } + } + + return this; + } + + /** + * Sets the request body. This may only be processed by the server when using POST or PUT, depending on the server's setup + * @param body The body to upload + * @return Builder Instance + */ + public HTTPRequestBuilder withBody(String body) + { + request.body = body; + return this; + } + + /** + * Sets the content type header + * Default: application/x-www-form-urlencoded for POST/PUT, and null/not present for GET + * @param type + * @return + */ + public HTTPRequestBuilder withContentType(String type) + { + request.contentType = type; + return this; + } + + public HTTPResponse build() + { + try { + connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod(request.method); + byte[] array = request.body.getBytes("UTF-8"); + connection.setRequestProperty("Content-Length" , "" + array.length); + connection.setRequestProperty("Content-Type", request.contentType); + connection.setDoInput(true); + connection.setUseCaches(false); + connection.setDoOutput(true); + DataOutputStream dos = new DataOutputStream(connection.getOutputStream()); + dos.write(array); + dos.flush(); + dos.close(); + + + // Get the response body + InputStream inputStream = connection.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + StringBuilder response = new StringBuilder(); + String line; + + while ((line = reader.readLine()) != null) { + response.append(line); + } + reader.close(); + inputStream.close(); + + String responseBody = response.toString(); + + return new HTTPResponse(connection.getContentType(), connection.getResponseCode(), responseBody, request); + } catch (IOException e) { + throw new RuntimeException(e); + }finally { + connection.disconnect(); + } + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/http/HTTPResponse.java b/src/main/java/dev/zontreck/ariaslib/http/HTTPResponse.java new file mode 100644 index 0000000..bd9bdfb --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/http/HTTPResponse.java @@ -0,0 +1,33 @@ +package dev.zontreck.ariaslib.http; + +public class HTTPResponse +{ + private String ContentType; + private int ResponseCode; + private String ResponseBody; + private HTTPRequest OriginalRequest; + + protected HTTPResponse(String contentType, int code, String body, HTTPRequest request){ + this.ContentType = contentType; + this.ResponseCode = code; + this.ResponseBody = body; + this.OriginalRequest = request; + + } + + public String getContentType() { + return ContentType; + } + + public int getResponseCode() { + return ResponseCode; + } + + public String getResponseBody() { + return ResponseBody; + } + + public HTTPRequest getOriginalRequest() { + return OriginalRequest; + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/json/Completed.java b/src/main/java/dev/zontreck/ariaslib/json/Completed.java new file mode 100644 index 0000000..c55b0b4 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/json/Completed.java @@ -0,0 +1,15 @@ +package dev.zontreck.ariaslib.json; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Serialization or Deserialization has completed. + * + * The method takes 1 argument. + * + * Boolean: True for deserialization. + */ +@Retention ( RetentionPolicy.RUNTIME ) +public @interface Completed { +} diff --git a/src/main/java/dev/zontreck/ariaslib/json/DynSerial.java b/src/main/java/dev/zontreck/ariaslib/json/DynSerial.java new file mode 100644 index 0000000..ac00eaa --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/json/DynSerial.java @@ -0,0 +1,11 @@ +package dev.zontreck.ariaslib.json; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Used on a class to indicate that it is serializable by the dynamic serializer. + */ +@Retention ( RetentionPolicy.RUNTIME ) +public @interface DynSerial { +} diff --git a/src/main/java/dev/zontreck/ariaslib/json/DynamicDeserializer.java b/src/main/java/dev/zontreck/ariaslib/json/DynamicDeserializer.java new file mode 100644 index 0000000..2315866 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/json/DynamicDeserializer.java @@ -0,0 +1,119 @@ +package dev.zontreck.ariaslib.json; + +import java.io.ByteArrayInputStream; +import java.lang.reflect.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Deserializes objects! + *

+ * YOU MUST HAVE A NO-PARAMETER CONSTRUCTOR + */ +public class DynamicDeserializer { + /** + * Constructs and deserializes an object from serialized data + */ + public static T doDeserialize ( Class clazz , byte[] data ) throws Exception { + ByteArrayInputStream BAIS = new ByteArrayInputStream ( data ); + return deserialize ( ( Map ) JsonObject.parseJSON ( BAIS ).getMap ( ) , clazz ); + } + + private static T deserialize ( Map map , Class clazz ) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { + if ( ! clazz.isAnnotationPresent ( DynSerial.class ) ) + return null; + + T object = clazz.getDeclaredConstructor ( ).newInstance ( ); + + Field[] fields = clazz.getDeclaredFields ( ); + for ( Field field : fields ) { + field.setAccessible ( true ); + + if ( field.isAnnotationPresent ( IgnoreSerialization.class ) ) + continue; + + try { + if ( List.class.isAssignableFrom ( field.getType ( ) ) ) { + Class listType = getListType ( field ); + List list = new ArrayList<> ( ); + List serializedList = ( List ) map.get ( field.getName ( ) ); + if ( serializedList != null ) { + for ( Object listItem : serializedList ) { + if ( listType.isAnnotationPresent ( DynSerial.class ) ) { + Object deserializedItem = deserialize ( ( Map ) listItem , listType ); + list.add ( deserializedItem ); + } + else { + list.add ( listItem ); + } + } + } + field.set ( object , list ); + } + else if ( Map.class.isAssignableFrom ( field.getType ( ) ) ) { + Class valueType = getMapValueType ( field ); + Map serializedMap = ( Map ) map.get ( field.getName ( ) ); + if ( serializedMap != null ) { + Map mapValue = new HashMap<> ( ); + for ( Map.Entry entry : serializedMap.entrySet ( ) ) { + Object deserializedValue; + if ( valueType.isAnnotationPresent ( DynSerial.class ) ) { + deserializedValue = deserialize ( ( Map ) entry.getValue ( ) , valueType ); + } + else { + deserializedValue = entry.getValue ( ); + } + mapValue.put ( entry.getKey ( ) , deserializedValue ); + } + field.set ( object , mapValue ); + } + } + else if ( ! field.getType ( ).isAnnotationPresent ( DynSerial.class ) ) { + field.set ( object , map.get ( field.getName ( ) ) ); + } + else { + Object tmp = deserialize ( ( Map ) map.get ( field.getName ( ) ) , field.getType ( ) ); + field.set ( object , tmp ); + } + } catch ( Exception e ) { + // Handle any exceptions during deserialization + } + } + + Method[] methods = clazz.getDeclaredMethods ( ); + for ( Method method : methods ) { + if ( method.isAnnotationPresent ( Completed.class ) ) { + method.invoke ( object , true ); + } + } + + return object; + } + + + private static Class getListType ( Field field ) { + Type genericType = field.getGenericType ( ); + if ( genericType instanceof ParameterizedType ) { + ParameterizedType paramType = ( ParameterizedType ) genericType; + Type[] actualTypeArgs = paramType.getActualTypeArguments ( ); + if ( actualTypeArgs.length > 0 ) { + return ( Class ) actualTypeArgs[ 0 ]; + } + } + return Object.class; + } + + private static Class getMapValueType ( Field field ) { + Type genericType = field.getGenericType ( ); + if ( genericType instanceof ParameterizedType ) { + ParameterizedType paramType = ( ParameterizedType ) genericType; + Type[] actualTypeArgs = paramType.getActualTypeArguments ( ); + if ( actualTypeArgs.length > 1 ) { + return ( Class ) actualTypeArgs[ 1 ]; + } + } + return Object.class; + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/json/DynamicSerializer.java b/src/main/java/dev/zontreck/ariaslib/json/DynamicSerializer.java new file mode 100644 index 0000000..1d93591 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/json/DynamicSerializer.java @@ -0,0 +1,115 @@ +package dev.zontreck.ariaslib.json; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class DynamicSerializer { + /** + * Serializes the object instance + * + * @param inst The class object to serialize + * @return A byte array of serialized data + */ + public static byte[] doSerialize(Object inst) throws InvocationTargetException, IllegalAccessException { + Map ret = serialize(inst); + + JsonObject js = new JsonObject(ret); + + return js.toJSONString().getBytes(); + } + + private static Map serialize(Object inst) throws InvocationTargetException, IllegalAccessException { + Class clazz = inst.getClass(); + if (!clazz.isAnnotationPresent(DynSerial.class)) + return null; + Method[] mth = clazz.getDeclaredMethods(); + Method onComplete = null; + for ( + Method mt : + mth + ) { + if (mt.isAnnotationPresent(PreSerialize.class)) { + mt.invoke(inst); + } + + if (mt.isAnnotationPresent(Completed.class)) + onComplete = mt; + } + + Field[] fields = clazz.getDeclaredFields(); + Map ret = new HashMap<>(); + for ( + Field field : + fields + ) { + field.setAccessible(true); + if (field.isAnnotationPresent(IgnoreSerialization.class)) + continue; + + Object fieldVal = field.get(inst); + if (fieldVal == null) continue; + + String fieldName = field.getName(); + + if (field.isAnnotationPresent(ListOrMap.class)) { + // Special handling for List and Map types + ret.put(fieldName, serializeCollectionOrMap(fieldVal)); + continue; + } + if (!(fieldVal.getClass().isAnnotationPresent(DynSerial.class))) { + // Special handler for List and Map is needed right here. + if (fieldVal instanceof List || fieldVal instanceof Map) continue; + + ret.put(fieldName, fieldVal); + } else { + Map TMP = serialize(fieldVal); + ret.put(fieldName, TMP); + } + } + + + if (onComplete != null) + onComplete.invoke(inst, false); + + return ret; + + + } + + @SuppressWarnings("unchecked") + private static Object serializeCollectionOrMap(Object collectionOrMap) throws InvocationTargetException, IllegalAccessException { + if (collectionOrMap instanceof List) { + List list = (List) collectionOrMap; + List serializedList = new ArrayList<>(); + for (Object item : list) { + if (item.getClass().isAnnotationPresent(DynSerial.class)) { + serializedList.add(serialize(item)); + } else { + serializedList.add(item); + } + } + return serializedList; + } else if (collectionOrMap instanceof Map) { + Map mp = (Map) collectionOrMap; + Map map = (Map) mp; + Map serializedMap = new HashMap<>(); + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + if (value.getClass().isAnnotationPresent(DynSerial.class)) { + value = serialize(value); + } + serializedMap.put(key, value); + } + return serializedMap; + } + return collectionOrMap; + } + + +} diff --git a/src/main/java/dev/zontreck/ariaslib/json/IgnoreSerialization.java b/src/main/java/dev/zontreck/ariaslib/json/IgnoreSerialization.java new file mode 100644 index 0000000..aef019d --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/json/IgnoreSerialization.java @@ -0,0 +1,12 @@ +package dev.zontreck.ariaslib.json; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Marks an element to be ignored completely by the serializer or deserializer. + */ +@Retention ( RetentionPolicy.RUNTIME ) +public @interface IgnoreSerialization +{ +} diff --git a/src/main/java/dev/zontreck/ariaslib/json/JsonObject.java b/src/main/java/dev/zontreck/ariaslib/json/JsonObject.java new file mode 100644 index 0000000..df78a2d --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/json/JsonObject.java @@ -0,0 +1,183 @@ +package dev.zontreck.ariaslib.json; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class JsonObject { + private Map data; + + public JsonObject() { + data = new HashMap<>(); + } + + public JsonObject(Map dat) { + data = new HashMap<>(dat); + } + + public static JsonObject parseJSON(InputStream inputStream) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + StringBuilder jsonString = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + jsonString.append(line); + } + return parseJsonObject(jsonString.toString()); + } + + private static JsonObject parseJsonObject(String jsonString) { + JsonObject jsonObject = new JsonObject(); + jsonString = jsonString.trim(); + if (jsonString.startsWith("{") && jsonString.endsWith("}")) { + jsonString = jsonString.substring(1, jsonString.length() - 1); + String[] keyValuePairs = jsonString.split(","); + for (String pair : keyValuePairs) { + String[] keyValue = pair.split(":"); + if (keyValue.length == 2) { + String key = keyValue[0].trim().replace("\"", ""); + String value = keyValue[1].trim(); + jsonObject.put(key, parseValue(value)); + } + } + } + return jsonObject; + } + + private static Object parseValue(String value) { + if (value.startsWith("{") && value.endsWith("}")) { + return parseJsonObject(value); + } else if (value.startsWith("[") && value.endsWith("]")) { + return parseJSONArray(value); + } else if (value.startsWith("\"") && value.endsWith("\"")) { + return value.substring(1, value.length() - 1); + } else if (value.equalsIgnoreCase("true")) { + return true; + } else if (value.equalsIgnoreCase("false")) { + return false; + } else if (value.equalsIgnoreCase("null")) { + return null; + } else { + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + try { + return Double.parseDouble(value); + } catch (NumberFormatException ex) { + return value; + } + } + } + } + + private static List parseJSONArray(String jsonArray) { + List list = new ArrayList<>(); + jsonArray = jsonArray.trim(); + if (jsonArray.startsWith("[") && jsonArray.endsWith("]")) { + jsonArray = jsonArray.substring(1, jsonArray.length() - 1); + String[] elements = jsonArray.split(","); + for (String element : elements) { + list.add(parseValue(element.trim())); + } + } + return list; + } + + public void put(String key, Object value) { + data.put(key, value); + } + + public Object get(String key) { + return data.get(key); + } + + public void merge(Map ret) { + data.putAll(ret); + } + + public Map getMap() { + return new HashMap<>(data); + } + + public void add(String key, Object value) { + if (data.containsKey(key)) { + Object existingValue = data.get(key); + if (existingValue instanceof List) { + ((List) existingValue).add(value); + } else { + List list = new ArrayList<>(); + list.add(existingValue); + list.add(value); + data.put(key, list); + } + } else { + data.put(key, value); + } + } + + public String toJSONString() { + StringBuilder sb = new StringBuilder(); + sb.append("{"); + + boolean first = true; + for (Map.Entry entry : data.entrySet()) { + if (!first) { + sb.append(","); + } + first = false; + + sb.append("\""); + sb.append(escape(entry.getKey())); + sb.append("\":"); + sb.append(toJSONValue(entry.getValue())); + } + + sb.append("}"); + return sb.toString(); + } + + private String escape(String str) { + if (str == null) return ""; + // Add necessary escape characters (e.g., double quotes, backslashes) + // You can implement this method based on your specific requirements. + // This is a simplified version for demonstration purposes. + return str.replace("\"", "\\\""); + } + + private String toJSONValue(Object value) { + if (value instanceof String) { + return "\"" + escape(value.toString()) + "\""; + } else if (value instanceof JsonObject) { + return ((JsonObject) value).toJSONString(); + } else if (value instanceof List) { + return toJSONList((List) value); + } else if (value instanceof Map) { + return new JsonObject((Map) ((Map) value)).toJSONString(); + } else { + return value.toString(); + } + } + + private String toJSONList(List list) { + StringBuilder sb = new StringBuilder(); + sb.append("["); + + boolean first = true; + for (Object item : list) { + if (!first) { + sb.append(","); + } + first = false; + + sb.append(toJSONValue(item)); + } + + sb.append("]"); + return sb.toString(); + } +} + diff --git a/src/main/java/dev/zontreck/ariaslib/json/ListOrMap.java b/src/main/java/dev/zontreck/ariaslib/json/ListOrMap.java new file mode 100644 index 0000000..ceb9895 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/json/ListOrMap.java @@ -0,0 +1,8 @@ +package dev.zontreck.ariaslib.json; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention ( RetentionPolicy.RUNTIME ) +public @interface ListOrMap { +} diff --git a/src/main/java/dev/zontreck/ariaslib/json/PreSerialize.java b/src/main/java/dev/zontreck/ariaslib/json/PreSerialize.java new file mode 100644 index 0000000..7562bae --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/json/PreSerialize.java @@ -0,0 +1,13 @@ +package dev.zontreck.ariaslib.json; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * To be set on a method, and will invoke that method prior to serialization beginning. + * + * Preparations should be made here + */ +@Retention ( RetentionPolicy.RUNTIME ) +public @interface PreSerialize { +} diff --git a/src/main/java/dev/zontreck/ariaslib/terminal/Banners.java b/src/main/java/dev/zontreck/ariaslib/terminal/Banners.java new file mode 100644 index 0000000..bf28d89 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/terminal/Banners.java @@ -0,0 +1,47 @@ +package dev.zontreck.ariaslib.terminal; + +import java.util.ArrayList; +import java.util.List; + +public class Banners +{ + + public static String generateBanner(String text) { + int maxLength = calculateMaxLength(text); + List bannerLines = new ArrayList<>(); + StringBuilder border = new StringBuilder(); + for (int i = 0; i < maxLength + 4; i++) { + border.append("*"); + } + bannerLines.add(border.toString()); + bannerLines.add("* " + centerText(text, maxLength) + " *"); + bannerLines.add(border.toString()); + return String.join("\n", bannerLines); + } + + private static String centerText(String text, int maxLength) { + StringBuilder centeredText = new StringBuilder(); + int spacesToAdd = (maxLength - text.length()) / 2; + for (int i = 0; i < spacesToAdd; i++) { + centeredText.append(" "); + } + centeredText.append(text); + for (int i = 0; i < spacesToAdd; i++) { + centeredText.append(" "); + } + if (centeredText.length() < maxLength) { + centeredText.append(" "); + } + return centeredText.toString(); + } + + private static int calculateMaxLength(String text) { + int maxLength = 0; + for (String line : text.split("\n")) { + if (line.length() > maxLength) { + maxLength = line.length(); + } + } + return maxLength; + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/terminal/Task.java b/src/main/java/dev/zontreck/ariaslib/terminal/Task.java new file mode 100644 index 0000000..6f7efe0 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/terminal/Task.java @@ -0,0 +1,88 @@ +package dev.zontreck.ariaslib.terminal; + +import dev.zontreck.ariaslib.util.DelayedExecutorService; +import dev.zontreck.ariaslib.util.EnvironmentUtils; +import dev.zontreck.ariaslib.util.Progress; + +import java.util.TimerTask; + +public abstract class Task extends TimerTask implements Runnable { + public final String TASK_NAME; + private TaskCompletionToken token = new TaskCompletionToken ( ); + + public static final String CHECK = "P"; + public static final String FAIL = "F"; + // Else use the progress spinner from the Progress class + private boolean isSilent = false; + + public Task ( String name ) { + TASK_NAME = name; + } + + /** + * This constructor is meant to be used to create silent tasks that do not output to the console. (Example usage: DelayedExecutionService) + * + * @param name Task name + * @param silent Whether to print to the terminal + */ + public Task ( String name , boolean silent ) { + this ( name ); + isSilent = silent; + } + + + public boolean isComplete ( ) { + return token.get ( ); + } + + public void startTask ( ) { + Thread tx = new Thread(this); + tx.start(); + + if(! isSilent && !EnvironmentUtils.isRunningInsideDocker()) + { + Thread tx2 = new Thread(new SpinnerTask(token, this)); + tx2.start(); + } + } + + public void stopTask ( ) { + if ( token.get ( ) && ! isSilent ) { + System.out.printf ( "\r" + TASK_NAME + "\t\t[" + token.status + "]\n" ); + } + } + + public void setSuccess ( ) { + token.completed ( CHECK ); + } + + public void setFail ( ) { + token.completed ( FAIL ); + } + + public class SpinnerTask extends Task { + public final Task task; + public final TaskCompletionToken token; + private final Progress spinner = new Progress ( 100 ); + + public SpinnerTask ( TaskCompletionToken token , Task parent ) { + super ( "spinner" , true ); + this.token = token; + this.task = parent; + } + + @Override + public void run ( ) { + while ( ! task.isComplete ( ) ) { + try { + Thread.sleep ( 50L ); + + if ( ! task.isSilent && ! task.isComplete ( ) && ! EnvironmentUtils.isRunningInsideDocker ( ) ) + System.out.printf ( "\r" + task.TASK_NAME + "\t\t" + spinner.getSpinnerTick ( ) + "\r" ); + } catch ( Exception e ) { + e.printStackTrace ( ); + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/dev/zontreck/ariaslib/terminal/TaskCompletionToken.java b/src/main/java/dev/zontreck/ariaslib/terminal/TaskCompletionToken.java new file mode 100644 index 0000000..37457f7 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/terminal/TaskCompletionToken.java @@ -0,0 +1,20 @@ +package dev.zontreck.ariaslib.terminal; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Should not be re-used for multiple tasks!!! + */ +public class TaskCompletionToken +{ + private AtomicBoolean complete = new AtomicBoolean(false); + public String status = ""; + public void completed(String reason){ + status=reason; + complete.set(true); + } + + public boolean get(){ + return complete.get(); + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/terminal/Terminal.java b/src/main/java/dev/zontreck/ariaslib/terminal/Terminal.java new file mode 100644 index 0000000..eed0500 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/terminal/Terminal.java @@ -0,0 +1,35 @@ +package dev.zontreck.ariaslib.terminal; + +import dev.zontreck.ariaslib.util.EnvironmentUtils; + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +public class Terminal { + private static final AtomicInteger ID = new AtomicInteger ( 0 ); + private static final AtomicBoolean running = new AtomicBoolean ( true ); + public static String PREFIX = ""; + + /** + * This starts a terminal instance + * + * @return The terminal ID + */ + public static int startTerminal ( ) { + if ( EnvironmentUtils.isRunningInsideDocker ( ) ) + return 0; + running.set ( true ); + //DelayedExecutorService.getInstance ( ).schedule ( new ConsolePrompt ( ) , 1 ); + + + return ID.getAndIncrement ( ); + } + + public static boolean isRunning ( ) { + return running.get ( ); + } + + public static void setRunning ( boolean running ) { + Terminal.running.set ( running ); + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/util/DelayedExecutorService.java b/src/main/java/dev/zontreck/ariaslib/util/DelayedExecutorService.java new file mode 100644 index 0000000..d18b493 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/util/DelayedExecutorService.java @@ -0,0 +1,17 @@ +package dev.zontreck.ariaslib.util; + +import java.time.Instant; +import java.util.*; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import dev.zontreck.ariaslib.terminal.Task; +import dev.zontreck.ariaslib.terminal.Terminal; + +@Deprecated +public class DelayedExecutorService { + +} diff --git a/src/main/java/dev/zontreck/ariaslib/util/EnvironmentUtils.java b/src/main/java/dev/zontreck/ariaslib/util/EnvironmentUtils.java new file mode 100644 index 0000000..fa729bf --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/util/EnvironmentUtils.java @@ -0,0 +1,19 @@ +package dev.zontreck.ariaslib.util; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.stream.Stream; + +public class EnvironmentUtils { + public static boolean isRunningInsideDocker ( ) { + if ( Files.exists ( Paths.get ( "/.dockerenv" ) ) ) + return true; + try { + Stream str = Files.lines ( Paths.get ( "/proc/1/cgroup" ) ); + return str.anyMatch ( ln -> ln.contains ( "/docker" ) ); + } catch ( IOException e ) { + return false; + } + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/util/FileIO.java b/src/main/java/dev/zontreck/ariaslib/util/FileIO.java new file mode 100644 index 0000000..a0b8184 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/util/FileIO.java @@ -0,0 +1,51 @@ +package dev.zontreck.ariaslib.util; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class FileIO +{ + + public static String readFile(String filePath) { + try { + byte[] fileBytes = Files.readAllBytes(Paths.get(filePath)); + return new String(fileBytes); + } catch (IOException e) { + return "An error occurred: " + e.getMessage(); + } + } + public static void writeFile(String filePath, String newContent) { + try { + Files.write(Paths.get(filePath), newContent.getBytes()); + } catch (IOException e) { + } + } + + + /** + * Recursively delete a directory + * @param directory The folder to delete + */ + public static void deleteDirectory(File directory) { + if (directory.exists()) { + File[] files = directory.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + deleteDirectory(file); + } else { + file.delete(); + } + } + } + // Now directory is empty, so delete it + directory.delete(); + System.out.println("Directory deleted: " + directory.getAbsolutePath()); + } else { + System.out.println("Directory does not exist: " + directory.getAbsolutePath()); + } + } +} + diff --git a/src/main/java/dev/zontreck/ariaslib/util/Hashing.java b/src/main/java/dev/zontreck/ariaslib/util/Hashing.java new file mode 100644 index 0000000..78cd5e0 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/util/Hashing.java @@ -0,0 +1,120 @@ +package dev.zontreck.ariaslib.util; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class Hashing +{ + + + /** + * A md5 hashing function that is compatible with literally every other hashing function out there + * @param input The string to hash + * @return The hash + */ + public static String md5(String input) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(input.getBytes()); + + byte[] byteData = md.digest(); + + // Convert the byte array to a hexadecimal string + StringBuilder hexString = new StringBuilder(); + for (byte aByteData : byteData) { + String hex = Integer.toHexString(0xff & aByteData); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } + } + /** + * A md5 hashing function that is compatible with literally every other hashing function out there + * @param input The bytes to hash + * @return The hash + */ + public static String md5(byte[] input) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(input); + + byte[] byteData = md.digest(); + + // Convert the byte array to a hexadecimal string + StringBuilder hexString = new StringBuilder(); + for (byte aByteData : byteData) { + String hex = Integer.toHexString(0xff & aByteData); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } + } + + + /** + * A sha256 hashing function that is compatible with literally every other hashing function out there + * @param input The string to hash + * @return The hash + */ + public static String sha256(String input) { + try { + MessageDigest md = MessageDigest.getInstance("SHA256"); + md.update(input.getBytes()); + + byte[] byteData = md.digest(); + + // Convert the byte array to a hexadecimal string + StringBuilder hexString = new StringBuilder(); + for (byte aByteData : byteData) { + String hex = Integer.toHexString(0xff & aByteData); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } + } + /** + * A sha256 hashing function that is compatible with literally every other hashing function out there + * @param input The bytes to hash + * @return The hash + */ + public static String sha256(byte[] input) { + try { + MessageDigest md = MessageDigest.getInstance("SHA256"); + md.update(input); + + byte[] byteData = md.digest(); + + // Convert the byte array to a hexadecimal string + StringBuilder hexString = new StringBuilder(); + for (byte aByteData : byteData) { + String hex = Integer.toHexString(0xff & aByteData); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/util/Lists.java b/src/main/java/dev/zontreck/ariaslib/util/Lists.java new file mode 100644 index 0000000..e243545 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/util/Lists.java @@ -0,0 +1,94 @@ +package dev.zontreck.ariaslib.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Lists +{ + /** + * Programatically constructs a list + * @param values The list of values + * @return The new list + * @param An arbitrary type parameter + */ + public static List of(T... values) + { + List arr = new ArrayList<>(); + for(T value : values) + { + arr.add(value); + } + + return arr; + } + + + /** + * Splits a string into a list + * @param input The string to split + * @param delimiters The list of delimiters + * @return A non-strided list + */ + public static List split(String input, String... delimiters) { + List result = new ArrayList<>(); + StringBuilder regex = new StringBuilder("("); + + // Constructing the regular expression pattern with provided delimiters + for (String delimiter : delimiters) { + regex.append(delimiter).append("|"); + } + regex.deleteCharAt(regex.length() - 1); // Remove the extra '|' character + regex.append(")"); + + String[] tokens = input.split(regex.toString()); + + // Add non-empty tokens to the result list + for (String token : tokens) { + if (!token.isEmpty()) { + result.add(token); + } + } + + return result; + } + + /** + * Split a string, and keep the delimiters + * @param input The string to be parsed and split + * @param delimiters A list of delimiters + * @return A strided list containing the parsed options, and the delimiters + */ + public static List splitWithDelim(String input, String... delimiters) { + List result = new ArrayList<>(); + StringBuilder regex = new StringBuilder("("); + + // Constructing the regular expression pattern with provided delimiters + for (String delimiter : delimiters) { + regex.append(delimiter).append("|"); + } + regex.deleteCharAt(regex.length() - 1); // Remove the extra '|' character + regex.append(")"); + + // Splitting the input string using the regex pattern + String[] tokens = input.split(regex.toString()); + + // Adding tokens and delimiters to the result list in a strided manner + for (int i = 0; i < tokens.length; i++) { + if (!tokens[i].isEmpty()) { + result.add(tokens[i]); + } + // Adding delimiter if it exists and it's not the last token + if (i < tokens.length - 1) { + result.add(input.substring(input.indexOf(tokens[i]) + tokens[i].length(), input.indexOf(tokens[i + 1]))); + } + } + + return result; + } + + + private Lists(){ + + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/util/Maps.java b/src/main/java/dev/zontreck/ariaslib/util/Maps.java new file mode 100644 index 0000000..ed063be --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/util/Maps.java @@ -0,0 +1,49 @@ +package dev.zontreck.ariaslib.util; + +import java.util.HashMap; +import java.util.Map; + +/** + * Utility class to assist in creating a dictionary programmatically in one line of code. + */ +public class Maps +{ + /** + * This takes a list of entries and returns a HashMap + * @param entries The entries you want in your hashmap + * @return The map itself + * @param Any typed parameter + * @param Any typed parameter + */ + public static Map of(Entry... entries) { + Map map = new HashMap<>(); + for(Entry E : entries) + { + map.put(E.key, E.value); + } + + return map; + } + + /** + * A virtual entry used only by the Maps#of function. + * @see Maps#of(Entry[]) + * @param Any typed parameter + * @param Any typed parameter + */ + public static class Entry { + public final A key; + public final B value; + + /** + * Initializes the readonly entry + * @param a The dictionary key + * @param b The value + */ + public Entry(A a, B b) + { + this.key=a; + this.value=b; + } + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/util/MathUtil.java b/src/main/java/dev/zontreck/ariaslib/util/MathUtil.java new file mode 100644 index 0000000..63df89f --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/util/MathUtil.java @@ -0,0 +1,18 @@ +package dev.zontreck.ariaslib.util; + +/** + * This class will be used to house math helper functions + */ +public class MathUtil +{ + /** + * A newer helper function to get the percentage with large number support + * @param current Min value + * @param max Maximum value for progress + * @return Percentage + */ + public static int getPercent(long current, long max) + { + return Math.round(current*100/max); + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/util/Percent.java b/src/main/java/dev/zontreck/ariaslib/util/Percent.java new file mode 100644 index 0000000..3b51a2b --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/util/Percent.java @@ -0,0 +1,23 @@ +package dev.zontreck.ariaslib.util; + +import java.io.PrintStream; + +public class Percent +{ + int current; + int maximum; + + public Percent(int cur, int max) + { + current=cur; + maximum=max; + } + + + public int get() + { + return ((current * 100) / maximum); + } + + +} diff --git a/src/main/java/dev/zontreck/ariaslib/util/Progress.java b/src/main/java/dev/zontreck/ariaslib/util/Progress.java new file mode 100644 index 0000000..a0d6670 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/util/Progress.java @@ -0,0 +1,56 @@ +package dev.zontreck.ariaslib.util; + +import java.util.concurrent.atomic.AtomicInteger; + +public class Progress +{ + private int maximum; + private int current; + private AtomicInteger tickNum = new AtomicInteger(0); + private static final String TICKS="-\\|/"; + + public String getSpinnerTick() + { + if(tickNum.get()>=TICKS.length()) tickNum.set(0); + + return "[" + TICKS.substring(tickNum.getAndIncrement(), tickNum.get()) + "]"; + } + + public Progress(int maximum) + { + current=0; + this.maximum=maximum; + } + + public int getPercent(){ + return (current*100/maximum); + } + + public String getPercentStr() + { + return (getPercent()+"%"); + } + + public static int getPercentOf(int current, int max) + { + return (current*100/max); + } + + public void increment(){ + current++; + sanity(); + } + private void sanity(){ + if(current > maximum) current = maximum; + if(current < 0)current = 0; + } + public void decrement(){ + current--; + sanity(); + } + + public void setCurrent(int cur) + { + current=cur; + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/util/ProgressBar.java b/src/main/java/dev/zontreck/ariaslib/util/ProgressBar.java new file mode 100644 index 0000000..fc7da66 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/util/ProgressBar.java @@ -0,0 +1,66 @@ +package dev.zontreck.ariaslib.util; + +import java.io.PrintStream; + +/** + * Utility to create an ascii progress bar + */ +public class ProgressBar +{ + + private static final int DEFAULT_BAR_WIDTH = 50; + + /** + * Reserved spaces for the brackets, and the carrot, and the percent value. + */ + private static final int PROGRESS_BAR_RESERVED=5; + + /** + * Always will return 80 + * @return 80 + */ + private static int getConsoleWidth() { + return 80; // Default console width, can be adjusted for different consoles + } + + /** + * Build a progress bar + *

+ * your text here [========= ] 40% your text here + * @param percent The percentage + * @param beforeText + * @param afterText + * @return ProgressBar as a String + */ + public static String printProgressBar(int percent, String beforeText, String afterText) { + StringBuilder sb = new StringBuilder(); + int consoleWidth = getConsoleWidth(); + int barWidth = Math.min(consoleWidth - beforeText.length() - afterText.length() - PROGRESS_BAR_RESERVED, DEFAULT_BAR_WIDTH); + + // Calculate progress + int progressBarLength = (int) ((double) percent / 100 * barWidth); + + // Print before text + sb.append(beforeText); + + // Print progress bar + sb.append("["); + for (int i = 0; i < barWidth; i++) { + if (i < progressBarLength) { + sb.append("="); + }else if(i==progressBarLength) sb.append(">"); + else { + sb.append(" "); + } + } + sb.append("]"); + + // Print percentage + sb.append(" " + percent + "%"); + + // Print after text + sb.append(afterText); + + return sb.toString(); + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/util/TimeNotation.java b/src/main/java/dev/zontreck/ariaslib/util/TimeNotation.java new file mode 100644 index 0000000..b3d04b9 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/util/TimeNotation.java @@ -0,0 +1,161 @@ +package dev.zontreck.ariaslib.util; + +import java.util.List; + +/** + * Contains useful structures and functions for dealing with, and manipulation of, time. + */ +public class TimeNotation +{ + public int Years; + public int Months; + public int Weeks; + public int Days; + public int Hours; + public int Minutes; + public int Seconds; + + public TimeNotation(int years, int months, int weeks, int days, int hours, int minutes, int seconds) + { + Years=years; + Months=months; + Weeks=weeks; + Days=days; + Hours=hours; + Minutes=minutes; + Seconds = seconds; + } + + private TimeNotation(){} + + + @Override + public String toString() { + String str = + someOrNone(Years,Pluralize(Years, "year") + ", ") + + someOrNone(Months, Pluralize(Months, "month") + ", ") + + someOrNone(Weeks, Pluralize(Weeks, "week") + ", ") + + someOrNone(Days, Pluralize(Days, "day") + ", ") + + someOrNone(Hours, Pluralize(Hours, "hour") + ", ") + + someOrNone(Minutes, Pluralize(Minutes, "minute") + ", ") + + someOrNone(Seconds, Pluralize(Seconds, "second")); + + if(str == ""){ + return "No Seconds"; + } else return str; + } + + /** + * Create a plural version for a number + * @param num The number to prefix + * @param str The singular form of the string + * @return Combined string, num + str in plural form if necessary + */ + private String Pluralize(int num, String str) + { + return num + " " + ((num > 1) ? str+"s" : str); + } + + /** + * A simple function to test a number, return a string, or return nothing at all. + * @param num The number to check + * @param str The string to return if the number is greater than zero + * @return Str if num >1, or empty string + */ + private String someOrNone(int num, String str) + { + if(num > 0) return str; + else return ""; + } + /** + * A simple function to test a number, return a string, or return something else. + * @param num The number to check + * @param str The string to return if the number is greater than zero + * @return Str if num >1, or other string + */ + private String someOrOther(int num, String str, String other) + { + if(num > 0) return str; + else return other; + } + + /** + * Encodes time notation! + * @return A program readable string that can be decoded back to a time notation + */ + public String toNotation() + { + return Years + "Y" + Months + "M" + Weeks + "W" + Days + "d" + Hours + "h" + Minutes + "m" + Seconds + "s"; + } + + /** + * Parses a time notation string + * @param notation Serialized time notation + * @return The deserialized time notation object + */ + public static TimeNotation fromNotation(String notation) + { + TimeNotation notationX = new TimeNotation(); + String[] delims = new String[]{"Y", "M", "W", "d", "h", "m", "s"}; + List opts = Lists.split(notation, delims); + + + int index = 0; + for(String dlim : delims) + { + if(notation.contains(dlim)) + { + switch (dlim) + { + case "Y": + { + notationX.Years = Integer.parseInt(opts.get(index)); + + break; + } + case "M": + { + notationX.Months = Integer.parseInt(opts.get(index)); + + break; + } + case "W": + { + notationX.Weeks = Integer.parseInt(opts.get(index)); + + break; + } + case "d": + { + notationX.Days = Integer.parseInt(opts.get(index)); + + break; + } + case "h": + { + notationX.Hours = Integer.parseInt(opts.get(index)); + + break; + } + case "m": + { + notationX.Minutes = Integer.parseInt(opts.get(index)); + + break; + } + case "s": + { + notationX.Seconds = Integer.parseInt(opts.get(index)); + + break; + } + } + + index++; + } + } + + return notationX; + + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/util/TimeUtil.java b/src/main/java/dev/zontreck/ariaslib/util/TimeUtil.java new file mode 100644 index 0000000..d8f5b8e --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/util/TimeUtil.java @@ -0,0 +1,96 @@ +package dev.zontreck.ariaslib.util; + +/** + * This class is a helper with some minecraft specific functions + */ +public class TimeUtil +{ + /** + * Converts seconds to ticks. (seconds*ticks) + * @param seconds Number of seconds + * @param ticks Number of ticks in a single second + * @return Number of ticks + */ + public static int secondsToTicks(int seconds, int ticks) + { + return seconds*ticks; + } + + /** + * Converts the number of ticks to seconds + * @param ticks The number of ticks to convert + * @param ticksInASecond The number of ticks in a single second + * @return Number of seconds + */ + public static int ticksToSeconds(int ticks, int ticksInASecond) + { + return ticks / ticksInASecond; + } + + /** + * Encodes a LibAC Time Notation + * @param seconds Number of seconds to convert + * @return Time Notation + */ + public static TimeNotation secondsToTimeNotation(int seconds) + { + int years = seconds / YEAR; + if(years > 0) seconds -= YEAR * years; + + int month = seconds / MONTH; + if(month > 0) seconds -= MONTH * month; + + int week = seconds / WEEK; + if(week > 0) seconds -= WEEK * week; + + int day = seconds / DAY; + if(day > 0) seconds -= DAY * day; + + int hour = seconds / HOUR; + if(hour > 0) seconds -= HOUR * hour; + + int minute = seconds / MINUTE; + if(minute > 0) seconds -= MINUTE * minute; + + return new TimeNotation(years, month, week, day, hour, minute, seconds); + } + + /** + * Convert a time notation to seconds + * @param notation Notation to convert + * @return Total seconds + */ + public static int notationToSeconds(TimeNotation notation) + { + int seconds = 0; + + seconds += (notation.Years * YEAR); + seconds += (notation.Months * MONTH); + seconds += (notation.Weeks * WEEK); + seconds += (notation.Days * DAY); + seconds += (notation.Hours * HOUR); + seconds += (notation.Minutes * MINUTE); + seconds += (notation.Seconds); + + return seconds; + } + + + public static final int SECOND; + public static final int MINUTE; + public static final int HOUR; + public static final int DAY; + public static final int WEEK; + public static final int MONTH; + public static final int YEAR; + + static { + SECOND = 1; + MINUTE = SECOND * 60; + HOUR = MINUTE * 60; + DAY = HOUR*24; + WEEK = DAY*7; + MONTH = WEEK*4; + YEAR = DAY*365; + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/xmlrpc/MethodCall.java b/src/main/java/dev/zontreck/ariaslib/xmlrpc/MethodCall.java new file mode 100644 index 0000000..178bf84 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/xmlrpc/MethodCall.java @@ -0,0 +1,32 @@ +package dev.zontreck.ariaslib.xmlrpc; + + +import java.util.Map; + +public class MethodCall { + private String methodName; + private Object[] params; + public Map parameters; + + + public MethodCall ( String methodName , Object[] params , Map p ) { + this.methodName = methodName; + this.params = params; + this.parameters = p; + } + + public String getMethodName ( ) { + return methodName; + } + + public Object[] getParams ( ) { + return params; + } + + public static MethodCall fromDeserializer ( XmlRpcDeserializer deserializer ) throws Exception { + String methodName = deserializer.readMethodName ( ); + Object[] params = deserializer.readMethodParams ( ); + Map parameters = ( Map ) params[ 0 ]; + return new MethodCall ( methodName , params , parameters ); + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/xmlrpc/MethodResponse.java b/src/main/java/dev/zontreck/ariaslib/xmlrpc/MethodResponse.java new file mode 100644 index 0000000..ddef840 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/xmlrpc/MethodResponse.java @@ -0,0 +1,26 @@ +package dev.zontreck.ariaslib.xmlrpc; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class MethodResponse { + public Map parameters = new HashMap<> ( ); + + public MethodResponse ( ) { + } + + + public String toXml ( ) { + ByteArrayOutputStream baos = new ByteArrayOutputStream ( ); + XmlRpcStreamWriter streamWriter = new XmlRpcStreamWriter ( baos ); + + try { + streamWriter.writeMethodResponse ( parameters ); + return new String ( baos.toByteArray ( ) ); + } catch ( IOException e ) { + throw new RuntimeException ( e ); + } + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/xmlrpc/README.md b/src/main/java/dev/zontreck/ariaslib/xmlrpc/README.md new file mode 100644 index 0000000..7addc3b --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/xmlrpc/README.md @@ -0,0 +1,7 @@ +XMLRPC +====== +----------- + + + +This code is heavily auto-generated from ChatGPT, however, it contains a lot of modifications to make it actually work. \ No newline at end of file diff --git a/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcDeserializer.java b/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcDeserializer.java new file mode 100644 index 0000000..78c1000 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcDeserializer.java @@ -0,0 +1,44 @@ +package dev.zontreck.ariaslib.xmlrpc; + + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +public class XmlRpcDeserializer { + private XmlRpcStreamReader xmlStreamReader; + + public XmlRpcDeserializer ( InputStream inputStream ) throws Exception { + xmlStreamReader = new XmlRpcStreamReader ( inputStream ); + } + public String skipXmlHeader(String xml) { + int startIndex = xml.indexOf("= 0) { + int endIndex = xml.indexOf("?>", startIndex); + if (endIndex >= 0) { + return xml.substring(endIndex + 2); + } + } + return xml; + } + public XmlRpcDeserializer ( String xml ) throws Exception { + byte[] xmlBytes = xml.getBytes ( ); + ByteArrayInputStream inputStream = new ByteArrayInputStream ( xmlBytes ); + xmlStreamReader = new XmlRpcStreamReader ( inputStream ); + } + + public String readMethodName ( ) throws Exception { + return xmlStreamReader.readMethodCallMethodName ( ); + } + + public Object[] readMethodParams ( ) throws Exception { + return xmlStreamReader.readMethodCallParams ( ); + } + + public Object readMethodResponse ( ) throws Exception { + return xmlStreamReader.readMethodResponseResult ( ); + } + + public void close ( ) throws Exception { + xmlStreamReader.close ( ); + } +} \ No newline at end of file diff --git a/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcException.java b/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcException.java new file mode 100644 index 0000000..513a7de --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcException.java @@ -0,0 +1,24 @@ +package dev.zontreck.ariaslib.xmlrpc; + + +public class XmlRpcException extends Exception { + public XmlRpcException ( int code , String message ) { + super ( message ); + FaultCode = code; + FaultString = message; + + } + + public final String FaultString; + public final int FaultCode; + + @Override + public String toString ( ) { + StringBuilder sb = new StringBuilder ( ); + sb.append ( "Code: " +FaultCode); + sb.append ( "\nMessage: " +FaultString); + sb.append ( "\n\n" ); + + return sb.toString (); + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcSerializer.java b/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcSerializer.java new file mode 100644 index 0000000..dbb44e0 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcSerializer.java @@ -0,0 +1,26 @@ +package dev.zontreck.ariaslib.xmlrpc; + + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +public class XmlRpcSerializer { + private XmlRpcStreamWriter writer; + + public XmlRpcSerializer ( OutputStream outputStream ) { + this.writer = new XmlRpcStreamWriter ( outputStream ); + } + + public void serializeMethodCall ( String methodName , List params ) throws IOException { + writer.writeMethodCall ( methodName , params ); + } + + public void serializeMethodResponse ( Object value ) throws IOException { + writer.writeMethodResponse ( value ); + } + + public void close ( ) throws IOException { + writer.close ( ); + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcStreamReader.java b/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcStreamReader.java new file mode 100644 index 0000000..453b058 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcStreamReader.java @@ -0,0 +1,206 @@ +package dev.zontreck.ariaslib.xmlrpc; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class XmlRpcStreamReader { + private XMLStreamReader xmlStreamReader; + + public XmlRpcStreamReader ( InputStream inputStream ) throws XMLStreamException { + XMLInputFactory inputFactory = XMLInputFactory.newInstance ( ); + xmlStreamReader = inputFactory.createXMLStreamReader ( inputStream ); + } + + private String CURRENT_TAG_NAME; + private int ELEM_TYPE; + + public boolean nextTag ( ) throws XMLStreamException { + while ( xmlStreamReader.hasNext ( ) ) { + int eventType = xmlStreamReader.next ( ); + if ( eventType == XMLStreamConstants.START_ELEMENT || eventType == XMLStreamConstants.END_ELEMENT ) { + CURRENT_TAG_NAME = getLocalName ( ); + ELEM_TYPE = xmlStreamReader.getEventType ( ); + return true; + } + } + return false; + } + + public String getLocalName ( ) { + return xmlStreamReader.getLocalName ( ); + } + + public String getElementText ( ) throws XMLStreamException { + return xmlStreamReader.getElementText ( ); + } + + public void require ( int type , String namespaceURI , String localName ) throws XMLStreamException { + xmlStreamReader.require ( type , namespaceURI , localName ); + } + + public String readMethodCallMethodName ( ) throws XMLStreamException { + nextTag ( ); + require ( XMLStreamConstants.START_ELEMENT , null , "methodCall" ); + nextTag ( ); + require ( XMLStreamConstants.START_ELEMENT , null , "methodName" ); + return getElementText ( ); + } + + public Object[] readMethodCallParams ( ) throws XMLStreamException { + nextTag ( ); + require ( XMLStreamConstants.START_ELEMENT , null , "params" ); + return deserializeParams ( ); + } + + private Object[] deserializeParams ( ) throws XMLStreamException { + List paramsList = new ArrayList<> ( ); + + while ( xmlStreamReader.hasNext ( ) ) { + int event = xmlStreamReader.next ( ); + if ( event == XMLStreamConstants.START_ELEMENT ) { + String elementName = xmlStreamReader.getLocalName ( ); + if ( elementName.equals ( "param" ) ) { + nextTag ( ); + require ( XMLStreamConstants.START_ELEMENT , null , "value" ); + + + Object value = deserializeValue ( ); + paramsList.add ( value ); + } + } + } + + return paramsList.toArray ( ); + } + + public Object readMethodResponseResult ( ) throws XMLStreamException { + nextTag ( ); + require ( XMLStreamConstants.START_ELEMENT , null , "methodResponse" ); + nextTag ( ); + require ( XMLStreamConstants.START_ELEMENT , null , "params" ); + nextTag ( ); + require ( XMLStreamConstants.START_ELEMENT , null , "param" ); + return deserializeValue ( ); + } + + private Object deserializeValue ( ) throws XMLStreamException { + nextTag ( ); + + + int eventType = xmlStreamReader.getEventType ( ); + if ( eventType == XMLStreamConstants.CHARACTERS || eventType == XMLStreamConstants.CDATA ) { + return xmlStreamReader.getText ( ); + } + else if ( eventType == XMLStreamConstants.START_ELEMENT ) { + String localName = xmlStreamReader.getLocalName ( ); + switch ( localName ) { + case "string": + return deserializeString ( ); + case "i4": + case "int": + return deserializeInt ( ); + case "double": + return deserializeDouble ( ); + case "boolean": + return deserializeBoolean ( ); + case "array": + return deserializeArray ( ); + case "struct": + return deserializeStruct ( ); + case "nil": + return null; + case "i8": + return deserializeLong ( ); + default: + throw new IllegalArgumentException ( "Unsupported element: " + localName ); + } + } + else { + throw new IllegalArgumentException ( "Unexpected event type: " + eventType ); + } + } + + private String deserializeString ( ) throws XMLStreamException { + return getElementText ( ); + } + + private int deserializeInt ( ) throws XMLStreamException { + return Integer.parseInt ( getElementText ( ) ); + } + + private byte deserializeByte ( ) throws XMLStreamException { + return Byte.parseByte ( getElementText ( ) ); + } + + private long deserializeLong ( ) throws XMLStreamException { + return Long.parseLong ( getElementText ( ) ); + } + + private double deserializeDouble ( ) throws XMLStreamException { + return Double.parseDouble ( getElementText ( ) ); + } + + private boolean deserializeBoolean ( ) throws XMLStreamException { + return Boolean.parseBoolean ( getElementText ( ) ); + } + + private Object[] deserializeArray ( ) throws XMLStreamException { + List arr = new ArrayList<> ( ); + while ( nextTag ( ) ) { + if ( CURRENT_TAG_NAME.equals ( "data" ) && ELEM_TYPE == XMLStreamConstants.END_ELEMENT ) { + break; + } + else if ( CURRENT_TAG_NAME.equals ( "value" ) && ELEM_TYPE == XMLStreamConstants.START_ELEMENT ) { + arr.add ( deserializeValue ( ) ); + } + } + + return arr.toArray ( ); + } + + private Map deserializeStruct ( ) throws XMLStreamException { + Map struct = new HashMap<> ( ); + String name = null; + while ( nextTag ( ) ) { + if ( xmlStreamReader.getLocalName ( ).equals ( "member" ) ) { + name = null; + } + else if ( xmlStreamReader.getLocalName ( ).equals ( "name" ) ) { + name = getElementText ( ); + } + else if ( xmlStreamReader.getLocalName ( ).equals ( "value" ) && xmlStreamReader.getEventType ( ) == XMLStreamConstants.START_ELEMENT ) { + if ( name != null ) { + Object value = deserializeValue ( ); + struct.put ( name , value ); + } + } + else if ( CURRENT_TAG_NAME.equals ( "struct" ) && xmlStreamReader.getEventType ( ) == XMLStreamConstants.END_ELEMENT ) { + break; + } + } + return struct; + } + + public static String skipXmlHeader ( String xml ) { + int startIndex = xml.indexOf ( "= 0 ) { + int endIndex = xml.indexOf ( "?>" , startIndex ); + if ( endIndex >= 0 ) { + return xml.substring ( endIndex + 2 ); + } + } + return xml; + } + + + public void close ( ) throws XMLStreamException { + xmlStreamReader.close ( ); + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcStreamWriter.java b/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcStreamWriter.java new file mode 100644 index 0000000..eaa45fd --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcStreamWriter.java @@ -0,0 +1,166 @@ +package dev.zontreck.ariaslib.xmlrpc; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.List; +import java.util.Map; + +public class XmlRpcStreamWriter { + private static final String XML_VERSION = ""; + private static final String METHOD_CALL_START_TAG = ""; + private static final String METHOD_CALL_END_TAG = "\n"; + private static final String METHOD_NAME_START_TAG = ""; + private static final String METHOD_NAME_END_TAG = "\n"; + private static final String METHOD_RESPONSE_START_TAG = ""; + private static final String METHOD_RESPONSE_END_TAG = "\n"; + private static final String PARAMS_START_TAG = ""; + private static final String PARAMS_END_TAG = "\n"; + private static final String PARAM_START_TAG = ""; + private static final String PARAM_END_TAG = "\n"; + private static final String VALUE_START_TAG = ""; + private static final String VALUE_END_TAG = "\n"; + private static final String ARRAY_START_TAG = ""; + private static final String ARRAY_END_TAG = "\n"; + private static final String DATA_START_TAG = ""; + private static final String DATA_END_TAG = "\n"; + private static final String STRUCT_START_TAG = ""; + private static final String STRUCT_END_TAG = "\n"; + private static final String MEMBER_START_TAG = ""; + private static final String MEMBER_END_TAG = "\n"; + private static final String NAME_START_TAG = ""; + private static final String NAME_END_TAG = "\n"; + + private Writer writer; + + public XmlRpcStreamWriter ( OutputStream outputStream ) { + this.writer = new OutputStreamWriter ( outputStream ); + } + + public void writeMethodCall ( String methodName , List params ) throws IOException { + writer.write ( XML_VERSION ); + writer.write ( METHOD_CALL_START_TAG ); + writer.write ( METHOD_NAME_START_TAG ); + writer.write ( methodName ); + writer.write ( METHOD_NAME_END_TAG ); + writer.write ( PARAMS_START_TAG ); + + if ( params != null ) { + for ( Object param : params ) { + writer.write ( PARAM_START_TAG ); + writeValue ( param ); + writer.write ( PARAM_END_TAG ); + } + } + writer.write ( PARAMS_END_TAG ); + writer.write ( METHOD_CALL_END_TAG ); + writer.flush ( ); + } + + public void writeMethodResponse ( Object value ) throws IOException { + writer.write ( XML_VERSION ); + writer.write ( METHOD_RESPONSE_START_TAG ); + writer.write ( PARAMS_START_TAG ); + writer.write ( PARAM_START_TAG ); + writeValue ( value ); + writer.write ( PARAM_END_TAG ); + writer.write ( PARAMS_END_TAG ); + writer.write ( METHOD_RESPONSE_END_TAG ); + writer.flush ( ); + } + + private void writeValue ( Object value ) throws IOException { + if ( value == null ) { + writer.write ( VALUE_START_TAG ); + writer.write ( "" ); + writer.write ( VALUE_END_TAG ); + } + else if ( value instanceof String ) { + writer.write ( VALUE_START_TAG ); + writer.write ( "" ); + writer.write ( escapeXml ( ( String ) value ) ); + writer.write ( "\n" ); + writer.write ( VALUE_END_TAG ); + } + else if ( value instanceof Integer ) { + writer.write ( VALUE_START_TAG ); + writer.write ( "" ); + writer.write ( value.toString ( ) ); + writer.write ( "\n" ); + writer.write ( VALUE_END_TAG ); + } else if(value instanceof Long) + { + writer.write ( VALUE_START_TAG ); + writer.write ( "" ); + writer.write ( value.toString () ); // Save it as a int for now due to unclear handling + writer.write ( "\n" ); + writer.write ( VALUE_END_TAG ); + } + else if ( value instanceof Double ) { + writer.write ( VALUE_START_TAG ); + writer.write ( "" ); + writer.write ( value.toString ( ) ); + writer.write ( "\n" ); + writer.write ( VALUE_END_TAG ); + } + else if ( value instanceof Boolean ) { + writer.write ( VALUE_START_TAG ); + writer.write ( "" ); + writer.write ( value.toString ( ) ); + writer.write ( "\n" ); + writer.write ( VALUE_END_TAG ); + } + else if ( value instanceof List ) { + writer.write ( VALUE_START_TAG ); + writer.write ( ARRAY_START_TAG ); + writer.write ( DATA_START_TAG ); + List list = ( List ) value; + for ( Object item : list ) { + writeValue ( item ); + } + writer.write ( DATA_END_TAG ); + writer.write ( ARRAY_END_TAG ); + writer.write ( VALUE_END_TAG ); + } + else if ( value instanceof Map ) { + writer.write ( VALUE_START_TAG ); + writer.write ( STRUCT_START_TAG ); + Map map = ( Map ) value; + for ( Map.Entry entry : map.entrySet ( ) ) { + writer.write ( MEMBER_START_TAG ); + writer.write ( NAME_START_TAG ); + writer.write ( escapeXml ( entry.getKey ( ).toString ( ) ) ); + writer.write ( NAME_END_TAG ); + writeValue ( entry.getValue ( ) ); + writer.write ( MEMBER_END_TAG ); + } + writer.write ( STRUCT_END_TAG ); + writer.write ( VALUE_END_TAG ); + } + else if(value instanceof Byte) + { + writer.write ( VALUE_START_TAG ); + writer.write ( "" ); + writer.write ( value.toString () ); // Treat as a integer for now + writer.write ( "\n" ); + writer.write ( VALUE_END_TAG ); + } + else { + throw new IllegalArgumentException ( "Unsupported data type: " + value.getClass ( ).getName ( ) ); + } + } + + private String escapeXml ( String value ) { + return value + .replace ( "&" , "&" ) + .replace ( "<" , "<" ) + .replace ( ">" , ">" ) + .replace ( "\"" , """ ) + .replace ( "'" , "'" ); + } + + public void close ( ) throws IOException { + writer.close ( ); + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcTokens.java b/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcTokens.java new file mode 100644 index 0000000..db9d9fc --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/xmlrpc/XmlRpcTokens.java @@ -0,0 +1,48 @@ +package dev.zontreck.ariaslib.xmlrpc; + +public class XmlRpcTokens +{ + public final String ISO_DATETIME = "yyyyMMdd\\THH\\:mm\\:ss"; + + public final String BASE64 = "base64"; + + public final String STRING = "string"; + + public final String INT = "i4"; + + public final String ALT_INT = "int"; + + public final String DATETIME = "dateTime.iso8601"; + + public final String BOOLEAN = "boolean"; + + public final String VALUE = "value"; + + public final String NAME = "name"; + + public final String ARRAY = "array"; + + public final String DATA = "data"; + + public final String MEMBER = "member"; + + public final String STRUCT = "struct"; + + public final String DOUBLE = "double"; + + public final String PARAM = "param"; + + public final String PARAMS = "params"; + + public final String METHOD_CALL = "methodCall"; + + public final String METHOD_NAME = "methodName"; + + public final String METHOD_RESPONSE = "methodResponse"; + + public final String FAULT = "fault"; + + public final String FAULT_CODE = "faultCode"; + + public final String FAULT_STRING = "faultString"; +} diff --git a/src/main/java/dev/zontreck/eventsbus/Bus.java b/src/main/java/dev/zontreck/eventsbus/Bus.java new file mode 100644 index 0000000..9bc744a --- /dev/null +++ b/src/main/java/dev/zontreck/eventsbus/Bus.java @@ -0,0 +1,166 @@ +package dev.zontreck.eventsbus; + +import dev.zontreck.eventsbus.annotations.Priority; +import dev.zontreck.eventsbus.annotations.SingleshotEvent; +import dev.zontreck.eventsbus.annotations.Subscribe; +import dev.zontreck.eventsbus.events.EventBusReadyEvent; +import dev.zontreck.eventsbus.events.ResetEventBusEvent; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.*; +import java.util.stream.Collectors; + +/** + * To be removed + *
+ * Use {EventDispatcher} instead + */ +@Deprecated() +public class Bus { + /** + * The main event bus! + */ + private static Bus Main; + + static { + if(Main == null) + { + Main = new Bus("Main Event Bus", false); + } + } + + public static boolean debug = false; + public final String BusName; + public final boolean UsesInstances; + + public Bus(String name, boolean useInstances) { + BusName = name; + UsesInstances = useInstances; + + Post(new EventBusReadyEvent()); + } + + public Map, List> static_events = new HashMap, List>(); + public Map, List> instanced_events = new HashMap, List>(); + + public static void Register(Class clazz, T instance) { + + List nonStaticMethods = Arrays.stream(clazz.getMethods()) + .filter(x -> x.isAnnotationPresent(Subscribe.class)) + .filter(x -> (x.getModifiers() & Modifier.STATIC) != Modifier.STATIC) + .collect(Collectors.toList()); + + List staticMethods = Arrays.stream(clazz.getMethods()) + .filter(x -> x.isAnnotationPresent(Subscribe.class)) + .filter(x -> (x.getModifiers() & Modifier.STATIC) == Modifier.STATIC) + .collect(Collectors.toList()); + + // Register the non-static methods if applicable + if (instance != null) { + for (Method m : + nonStaticMethods) { + EventContainer container = new EventContainer(); + container.instance = instance; + container.method = m; + container.clazz = clazz; + if (m.isAnnotationPresent(Priority.class)) + container.Level = m.getAnnotation(Priority.class).Level(); + else container.Level = PriorityLevel.LOWEST; + + Class clz = m.getParameters()[0].getType(); + + container.IsSingleshot = m.isAnnotationPresent(SingleshotEvent.class); + + if (Main.instanced_events.containsKey(clz)) + Main.instanced_events.get(clz).add(container); + else { + Main.instanced_events.put(clz, new ArrayList<>()); + Main.instanced_events.get(clz).add(container); + } + } + } + + for (Method m : staticMethods) { + EventContainer container = new EventContainer(); + container.instance = null; + container.method = m; + container.clazz = clazz; + if (m.isAnnotationPresent((Priority.class))) + container.Level = m.getAnnotation(Priority.class).Level(); + else container.Level = PriorityLevel.LOWEST; + + Class clz = m.getParameters()[0].getType(); + container.IsSingleshot = m.isAnnotationPresent(SingleshotEvent.class); + + if (Main.static_events.containsKey(clz)) + Main.static_events.get(clz).add(container); + else { + Main.static_events.put(clz, new ArrayList<>()); + Main.static_events.get(clz).add(container); + } + } + } + + /** + * Posts an event to the bus. + * + * @param event The event you wish to post + * @return True if the event was cancelled. + */ + public static boolean Post(Event event) { + for (PriorityLevel level : + PriorityLevel.values()) { + // Call each priority level in order of declaration + // Static first, then instanced + // At the end, this method will return the cancellation result. + try { + + if (Main.static_events.containsKey(event.getClass())) { + EventContainer[] tempArray = (EventContainer[]) Main.static_events.get(event.getClass()).toArray(); + + for (EventContainer container : tempArray) { + if (container.invoke(event, level)) { + Main.static_events.get(event.getClass()).remove(container); + } + } + } + + if (Main.instanced_events.containsKey(event.getClass())) { + EventContainer[] tempArray = (EventContainer[]) Main.instanced_events.get(event.getClass()).toArray(); + + for (EventContainer container : tempArray) { + if (container.invoke(event, level)) { + Main.instanced_events.get(event.getClass()).remove(container); + } + } + } + } catch (Exception e) { + + } + } + + return event.isCancelled(); + } + + /** + * Attempts to reset the Event Bus + * + * @return True if the bus was successfully reset (If not interrupts!) + * @see dev.zontreck.eventsbus.events.ResetEventBusEvent + */ + public static boolean Reset() { + if (!Post(new ResetEventBusEvent())) { + + Main.static_events = new HashMap<>(); + Main.instanced_events = new HashMap<>(); + + Post(new EventBusReadyEvent()); + + return true; + } + + return false; + + } +} diff --git a/src/main/java/dev/zontreck/eventsbus/ClassScanner.java b/src/main/java/dev/zontreck/eventsbus/ClassScanner.java new file mode 100644 index 0000000..4e2deab --- /dev/null +++ b/src/main/java/dev/zontreck/eventsbus/ClassScanner.java @@ -0,0 +1,95 @@ +package dev.zontreck.eventsbus; + + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + + +@Deprecated +/** + * Used internally. Do not directly invoke + *
+ * Accessor is set Protected intentionally!!!!!!!!! + */ +class ClassScanner { + /** + * Start the process of scanning the classes and forcing them to load in + *
+ * This is used by the event dispatcher + */ + protected static void DoScan() { + // Scan all classes in the classpath + Set> scannedClasses = scanClasses(); + + // Force loading of all scanned classes + for (Class clazz : scannedClasses) { + try { + // Load the class + Class.forName(clazz.getName()); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + } + + private static Set> scanClasses() { + String classpath = System.getProperty("java.class.path"); + String[] classpathEntries = classpath.split(File.pathSeparator); + + Set> scannedClasses = new HashSet<>(); + for (String classpathEntry : classpathEntries) { + File file = new File(classpathEntry); + if (file.isDirectory()) { + scanClassesInDirectory(file, "", scannedClasses); + } else if (file.isFile() && classpathEntry.endsWith(".jar")) { + scanClassesInJar(file, scannedClasses); + } + } + + return scannedClasses; + } + + private static void scanClassesInDirectory(File directory, String packageName, Set> scannedClasses) { + File[] files = directory.listFiles(); + if (files == null) { + return; + } + + for (File file : files) { + if (file.isDirectory()) { + scanClassesInDirectory(file, packageName + "." + file.getName(), scannedClasses); + } else if (file.getName().endsWith(".class")) { + String className = packageName + "." + file.getName().substring(0, file.getName().length() - 6); + try { + Class clazz = Class.forName(className); + scannedClasses.add(clazz); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + } + } + + private static void scanClassesInJar(File jarFile, Set> scannedClasses) { + try (JarFile jf = new JarFile(jarFile)) { + for (JarEntry entry : Collections.list(jf.entries())) { + if (entry.getName().endsWith(".class")) { + String className = entry.getName().replace("/", ".").substring(0, entry.getName().length() - 6); + try { + Class clazz = Class.forName(className); + scannedClasses.add(clazz); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/dev/zontreck/eventsbus/Event.java b/src/main/java/dev/zontreck/eventsbus/Event.java new file mode 100644 index 0000000..1053644 --- /dev/null +++ b/src/main/java/dev/zontreck/eventsbus/Event.java @@ -0,0 +1,46 @@ +package dev.zontreck.eventsbus; + + +import dev.zontreck.eventsbus.annotations.Cancellable; +import dev.zontreck.eventsbus.annotations.Priority; + +public class Event { + private boolean cancelled = false; + + /** + * Checks if the event can be cancelled. + * + * @return True if the cancellation annotation is present. + * @see Cancellable + */ + public boolean IsCancellable() { + Class Current = this.getClass(); + return Current.isAnnotationPresent(Cancellable.class); + } + + /** + * Checks if the event is cancelled. + * + * @return False if the event cannot be cancelled; or + * The current cancellation status for the event + */ + public boolean isCancelled() { + if (!IsCancellable()) + return false; + return cancelled; + } + + /** + * Sets the cancelled status for the event + * + * @param cancel Whether the event should be marked as cancelled or not. + */ + public void setCancelled(boolean cancel) { + cancelled = cancel; + } + + public PriorityLevel getPriorityLevel() { + Class Current = this.getClass(); + return Current.getAnnotation(Priority.class).Level(); + } +} \ No newline at end of file diff --git a/src/main/java/dev/zontreck/eventsbus/EventContainer.java b/src/main/java/dev/zontreck/eventsbus/EventContainer.java new file mode 100644 index 0000000..e49162c --- /dev/null +++ b/src/main/java/dev/zontreck/eventsbus/EventContainer.java @@ -0,0 +1,45 @@ +package dev.zontreck.eventsbus; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class EventContainer { + public Class clazz; + public Object instance; + + /** + * The method that gets invoked, either statically, or via the instance. + */ + public Method method; + + /** + * Indicates whether an event gets removed from the register after being invoked once. + */ + public boolean IsSingleshot; + + /** + * The current method's priority level + */ + public PriorityLevel Level; + + /** + * Invokes the event + * + * @param EventArg The event instance to pass to the subscribed function + * @param level Current priority level on the call loop. Will refuse to invoke if the priority level mismatches. + * @return True if the event was single shot and should be deregistered + * @throws InvocationTargetException + * @throws IllegalAccessException + */ + public boolean invoke(Event EventArg, PriorityLevel level) throws InvocationTargetException, IllegalAccessException { + if (Level != level) return false; + + if (instance == null) { + method.invoke(null, EventArg); + } else { + method.invoke(instance, EventArg); + } + + return IsSingleshot; + } +} diff --git a/src/main/java/dev/zontreck/eventsbus/EventDispatcher.java b/src/main/java/dev/zontreck/eventsbus/EventDispatcher.java new file mode 100644 index 0000000..b1c670f --- /dev/null +++ b/src/main/java/dev/zontreck/eventsbus/EventDispatcher.java @@ -0,0 +1,124 @@ +package dev.zontreck.eventsbus; + +import dev.zontreck.eventsbus.annotations.EventSubscriber; +import dev.zontreck.eventsbus.annotations.Priority; +import dev.zontreck.eventsbus.annotations.SingleshotEvent; +import dev.zontreck.eventsbus.annotations.Subscribe; +import dev.zontreck.eventsbus.events.EventBusReadyEvent; +import dev.zontreck.eventsbus.events.ResetEventBusEvent; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class EventDispatcher +{ + private static List singleshot = new ArrayList<>(); + private static List> subscribers = new ArrayList<>(); + + /** + * Scans every Java class that is currently loaded. It then checks for Subscribe, and a proper parameter before posting the Event. + * The Event will only be posted if not cancelled using {@link Event#setCancelled(boolean)} and that {@link Subscribe#allowCancelled()} allows. + * @param event The event to post + * @return True if cancelled. + */ + + public static boolean Post(Event event) + { + for(PriorityLevel level : PriorityLevel.values()) + { + + for(Class clazz : subscribers) + { + for(Method M :clazz.getMethods()) + { + if(!M.isAnnotationPresent(Subscribe.class)) continue; + + Subscribe subscriber = M.getAnnotation(Subscribe.class); + + + boolean canPost=true; + Class param = M.getParameterTypes()[0]; + if(param == event.getClass()) + { + if(M.isAnnotationPresent(SingleshotEvent.class)) + { + if(singleshot.contains(M)) + { + canPost=false; + } + } + } else canPost=false; + + PriorityLevel eventPriotityLevel= PriorityLevel.HIGH; // Default + + if(M.isAnnotationPresent(Priority.class)) + { + Priority prio = M.getAnnotation(Priority.class); + eventPriotityLevel=prio.Level(); + } + + if(level != eventPriotityLevel) + { + canPost=false; + } + + + // Dispatch the event now + + if(!canPost) continue; + + if(!M.canAccess(null)) + { + canPost=false; + System.out.println("ERROR: Even subscriber methods must be static and public"); + } + + try { + if(event.isCancelled() && !subscriber.allowCancelled()) + continue; + else + M.invoke(null, event); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + + } + } + } + + return event.isCancelled(); + } + + + /** + * Register a class + */ + public static void Register(Class clazz) + { + if(clazz.isAnnotationPresent(EventSubscriber.class)) + subscribers.add(clazz); + } + + /** + * Resets the events system. + *
+ * This action clears the Singleshot list for the events that should only be invoked once. And rescans all classes incase new classes were dynamically loaded. + */ + public static void Reset() + { + Post(new ResetEventBusEvent()); + + subscribers.clear(); + singleshot.clear(); + + Post(new EventBusReadyEvent()); + } +} diff --git a/src/main/java/dev/zontreck/eventsbus/PriorityLevel.java b/src/main/java/dev/zontreck/eventsbus/PriorityLevel.java new file mode 100644 index 0000000..be93823 --- /dev/null +++ b/src/main/java/dev/zontreck/eventsbus/PriorityLevel.java @@ -0,0 +1,15 @@ +package dev.zontreck.eventsbus; + +/** + * Event priority level. + *

+ * The higher the priority, the sooner it gets executed. High is executed after + * Highest. + */ +public enum PriorityLevel { + HIGHEST, + HIGH, + MEDIUM, + LOW, + LOWEST +} diff --git a/src/main/java/dev/zontreck/eventsbus/annotations/Cancellable.java b/src/main/java/dev/zontreck/eventsbus/annotations/Cancellable.java new file mode 100644 index 0000000..34be386 --- /dev/null +++ b/src/main/java/dev/zontreck/eventsbus/annotations/Cancellable.java @@ -0,0 +1,11 @@ +package dev.zontreck.eventsbus.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value = RetentionPolicy.RUNTIME) +@Target(value = ElementType.TYPE) +public @interface Cancellable { +} diff --git a/src/main/java/dev/zontreck/eventsbus/annotations/EventSubscriber.java b/src/main/java/dev/zontreck/eventsbus/annotations/EventSubscriber.java new file mode 100644 index 0000000..0ee5023 --- /dev/null +++ b/src/main/java/dev/zontreck/eventsbus/annotations/EventSubscriber.java @@ -0,0 +1,11 @@ +package dev.zontreck.eventsbus.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value = RetentionPolicy.RUNTIME) +@Target(value = ElementType.TYPE) +public @interface EventSubscriber { +} diff --git a/src/main/java/dev/zontreck/eventsbus/annotations/Priority.java b/src/main/java/dev/zontreck/eventsbus/annotations/Priority.java new file mode 100644 index 0000000..88a4276 --- /dev/null +++ b/src/main/java/dev/zontreck/eventsbus/annotations/Priority.java @@ -0,0 +1,14 @@ +package dev.zontreck.eventsbus.annotations; + +import dev.zontreck.eventsbus.PriorityLevel; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value = RetentionPolicy.RUNTIME) +@Target(value = ElementType.METHOD) +public @interface Priority { + PriorityLevel Level(); +} diff --git a/src/main/java/dev/zontreck/eventsbus/annotations/SingleshotEvent.java b/src/main/java/dev/zontreck/eventsbus/annotations/SingleshotEvent.java new file mode 100644 index 0000000..6e8d612 --- /dev/null +++ b/src/main/java/dev/zontreck/eventsbus/annotations/SingleshotEvent.java @@ -0,0 +1,11 @@ +package dev.zontreck.eventsbus.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value = RetentionPolicy.RUNTIME) +@Target(value = ElementType.METHOD) +public @interface SingleshotEvent { +} diff --git a/src/main/java/dev/zontreck/eventsbus/annotations/Subscribe.java b/src/main/java/dev/zontreck/eventsbus/annotations/Subscribe.java new file mode 100644 index 0000000..9facb6e --- /dev/null +++ b/src/main/java/dev/zontreck/eventsbus/annotations/Subscribe.java @@ -0,0 +1,18 @@ +package dev.zontreck.eventsbus.annotations; + +import dev.zontreck.eventsbus.Event; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value = RetentionPolicy.RUNTIME) +@Target(value = ElementType.METHOD) + +public @interface Subscribe { + /** + * Marks that the subscribed method will not receive the signal if the event was cancelled with {@link Event#setCancelled(boolean)} + */ + boolean allowCancelled(); +} diff --git a/src/main/java/dev/zontreck/eventsbus/events/EventBusReadyEvent.java b/src/main/java/dev/zontreck/eventsbus/events/EventBusReadyEvent.java new file mode 100644 index 0000000..50370b7 --- /dev/null +++ b/src/main/java/dev/zontreck/eventsbus/events/EventBusReadyEvent.java @@ -0,0 +1,11 @@ +package dev.zontreck.eventsbus.events; + +import dev.zontreck.eventsbus.Event; + +/** + * This event is sent out when the Event Bus is ready. + *

+ * This is also dispatched when a reset occurs, prior to clearing the lists. + */ +public class EventBusReadyEvent extends Event { +} diff --git a/src/main/java/dev/zontreck/eventsbus/events/ResetEventBusEvent.java b/src/main/java/dev/zontreck/eventsbus/events/ResetEventBusEvent.java new file mode 100644 index 0000000..20f2e74 --- /dev/null +++ b/src/main/java/dev/zontreck/eventsbus/events/ResetEventBusEvent.java @@ -0,0 +1,17 @@ +package dev.zontreck.eventsbus.events; + +import dev.zontreck.eventsbus.annotations.Cancellable; +import dev.zontreck.eventsbus.Event; + +/** + * Posted when the event bus is about to be reset. + *

+ * This event can be cancelled to prevent the reset. + *

+ * The default behavior is: Allow Reset. + *

+ * Recommended that handlers be implemented to re-register instances, and classes when a reset occurs. + */ +@Cancellable +public class ResetEventBusEvent extends Event { +} diff --git a/src/main/java/dev/zontreck/eventsbus/events/TickEvent.java b/src/main/java/dev/zontreck/eventsbus/events/TickEvent.java new file mode 100644 index 0000000..52d1d6b --- /dev/null +++ b/src/main/java/dev/zontreck/eventsbus/events/TickEvent.java @@ -0,0 +1,6 @@ +package dev.zontreck.eventsbus.events; + +import dev.zontreck.eventsbus.Event; + +public class TickEvent extends Event { +}