diff --git a/src/test/java/me/s3ns3iw00/jcommands/person/PersonCommand.java b/src/test/java/me/s3ns3iw00/jcommands/person/PersonCommand.java new file mode 100644 index 0000000..f7335be --- /dev/null +++ b/src/test/java/me/s3ns3iw00/jcommands/person/PersonCommand.java @@ -0,0 +1,61 @@ +package me.s3ns3iw00.jcommands.person; + +import me.s3ns3iw00.jcommands.CommandResponder; +import me.s3ns3iw00.jcommands.argument.ArgumentResult; +import me.s3ns3iw00.jcommands.argument.concatenation.type.StringConcatenator; +import me.s3ns3iw00.jcommands.argument.concatenation.type.TypeConcatenator; +import me.s3ns3iw00.jcommands.event.listener.CommandActionEventListener; +import me.s3ns3iw00.jcommands.event.type.CommandActionEvent; +import me.s3ns3iw00.jcommands.person.argument.AddArgument; +import me.s3ns3iw00.jcommands.person.model.Person; +import me.s3ns3iw00.jcommands.type.ServerCommand; + +/** + * A {@link ServerCommand} that is for to manage people, and a {@link CommandActionEventListener} to be able to listen for its usage + */ +public class PersonCommand extends ServerCommand implements CommandActionEventListener { + + /** + * Default constructor + */ + public PersonCommand() { + // Call super class's constructor with a name and a description + super("person", "A command to manage people"); + setOnAction(this); // set this class as action listener + + // Instantiate the sub command and adds it to the command + AddArgument addArgument = new AddArgument(); + addArgument(addArgument); + + // Add a concatenator to the command that concatenates the two parts of the name from the sub command into one String separated with a space + // This is needed because Person takes the name as one piece + addConcatenator(new StringConcatenator(" "), addArgument.getFirstNameArgument(), addArgument.getLastNameArgument()); + + // Add another concatenator that concatenates all the arguments in the sub command into an instance of Person + // The parameters' type, count and order is matter because it needs to match with one of the constructor of Person + // This could be wrong because there is no constructor that takes two String and a Date type of parameter but the first two parameters will be replaced by the result of the concatenator above, + // so it will be a String and a Date type of parameter and there is a constructor that takes these parameters + addConcatenator(new TypeConcatenator(Person.class), addArgument.getFirstNameArgument(), addArgument.getLastNameArgument(), addArgument.getDateOfBirthArgument()); + } + + /** + * The action listener + * + * @param event the event + */ + @Override + public void onAction(CommandActionEvent event) { + ArgumentResult[] args = event.getArguments(); + CommandResponder responder = event.getResponder(); + + String action = args[0].get(); + if (action.equalsIgnoreCase("add")) { + Person person = args[1].get(); + + responder.respondNow() + .setContent(person.getFullName() + " (" + person.getAge() + ")") + .respond(); + } + } + +} diff --git a/src/test/java/me/s3ns3iw00/jcommands/person/argument/AddArgument.java b/src/test/java/me/s3ns3iw00/jcommands/person/argument/AddArgument.java new file mode 100644 index 0000000..40d0998 --- /dev/null +++ b/src/test/java/me/s3ns3iw00/jcommands/person/argument/AddArgument.java @@ -0,0 +1,70 @@ +package me.s3ns3iw00.jcommands.person.argument; + +import me.s3ns3iw00.jcommands.argument.type.ConstantArgument; +import me.s3ns3iw00.jcommands.argument.type.StringArgument; +import me.s3ns3iw00.jcommands.argument.type.ValueArgument; +import org.javacord.api.interaction.SlashCommandOptionType; + +import java.util.Date; + +/** + * A {@link ConstantArgument} that gathers data for creating new {@link me.s3ns3iw00.jcommands.person.model.Person} + */ +public class AddArgument extends ConstantArgument { + + // The inputs of this argument + private final StringArgument firstNameArgument, lastNameArgument; + private final ValueArgument dateOfBirthArgument; + + /** + * Default constructor + */ + public AddArgument() { + // Call super class's constructor with a name and a description + super("add", "Adds a person to people"); + + // First name of the person with a maximum length validation + firstNameArgument = new StringArgument("firstname", "The first name of the person, maximum 16 character"); + firstNameArgument.setMaxLength(16); + firstNameArgument.setOnMismatch(event -> { + event.getResponder().respondNow() + .setContent("Firstname's maximum length is 16 characters") + .respond(); + }); + + // Last name of the person with a maximum length validation + lastNameArgument = new StringArgument("lastname", "The last name of the person, maximum 16 character"); + lastNameArgument.setMaxLength(16); + lastNameArgument.setOnMismatch(event -> { + event.getResponder().respondNow() + .setContent("Lastname's maximum length is 16 characters") + .respond(); + }); + + // Date of birth of the person that is a STRING input with regex validation that validates by a specific date format (optional) + dateOfBirthArgument = new ValueArgument("dateofbirth", "The date of birth of the person (YYYY-MM-DD)", SlashCommandOptionType.STRING, Date.class); + dateOfBirthArgument.validate("\\d{4}-\\d{2}-\\d{2}"); + dateOfBirthArgument.setOptional(); + dateOfBirthArgument.setOnMismatch(event -> { + event.getResponder().respondNow() + .setContent("Date must match to pattern YYYY-MM-DD") + .respond(); + }); + + // Add all the arguments to the argument + addArgument(firstNameArgument, lastNameArgument, dateOfBirthArgument); + } + + public StringArgument getFirstNameArgument() { + return firstNameArgument; + } + + public StringArgument getLastNameArgument() { + return lastNameArgument; + } + + public ValueArgument getDateOfBirthArgument() { + return dateOfBirthArgument; + } + +} diff --git a/src/test/java/me/s3ns3iw00/jcommands/person/converter/DateConverter.java b/src/test/java/me/s3ns3iw00/jcommands/person/converter/DateConverter.java new file mode 100644 index 0000000..f68da16 --- /dev/null +++ b/src/test/java/me/s3ns3iw00/jcommands/person/converter/DateConverter.java @@ -0,0 +1,28 @@ +package me.s3ns3iw00.jcommands.person.converter; + +import me.s3ns3iw00.jcommands.argument.converter.ArgumentResultConverter; + +import java.text.ParseException; +import java.text.SimpleDateFormat; + +/** + * An {@link ArgumentResultConverter} that converts {@link String} value formatted by {@code DATE_FORMAT} into {@link java.util.Date} + */ +public class DateConverter extends ArgumentResultConverter { + + // The date format + public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); + + @Override + public Object convertTo(Object value) { + /* Don't need to check anything, since + type and formatting is already validated by the argument itself + */ + try { + return DATE_FORMAT.parse(String.valueOf(value)); + } catch (ParseException e) { + return null; + } + } + +} diff --git a/src/test/java/me/s3ns3iw00/jcommands/person/model/Person.java b/src/test/java/me/s3ns3iw00/jcommands/person/model/Person.java new file mode 100644 index 0000000..dff4f33 --- /dev/null +++ b/src/test/java/me/s3ns3iw00/jcommands/person/model/Person.java @@ -0,0 +1,51 @@ +package me.s3ns3iw00.jcommands.person.model; + +import java.time.LocalDate; +import java.time.Period; +import java.time.ZoneId; +import java.util.Date; + +/** + * Represents a person + */ +public class Person { + + // Required fields + private final String fullName; + private final int age; + private final Date dateOfBirth; + + /** + * Default constructor + * + * @param fullName the name of the person + * @param dateOfBirth the date of birth of the person + */ + public Person(String fullName, Date dateOfBirth) { + this.fullName = fullName; + this.dateOfBirth = dateOfBirth; + this.age = Period.between(dateOfBirth.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), LocalDate.now()).getYears(); + } + + /** + * Newborn person constructor + * + * @param fullName the name of the person + */ + public Person(String fullName) { + this(fullName, new Date()); + } + + public String getFullName() { + return fullName; + } + + public int getAge() { + return age; + } + + public Date getDateOfBirth() { + return dateOfBirth; + } + +} \ No newline at end of file