diff --git a/emailslicer-dkasargod-java/.mvn/wrapper/maven-wrapper.properties b/emailslicer-dkasargod-java/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..e70e7bc --- /dev/null +++ b/emailslicer-dkasargod-java/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/emailslicer-dkasargod-java/mvnw b/emailslicer-dkasargod-java/mvnw new file mode 100755 index 0000000..2f4b09c --- /dev/null +++ b/emailslicer-dkasargod-java/mvnw @@ -0,0 +1,71 @@ +#!/bin/sh +# Maven Wrapper script — downloads Maven if not already cached, then runs it. +# Based on https://github.com/apache/maven-wrapper + +set -e + +# Determine the project base directory +if [ -z "$MAVEN_PROJECTBASEDIR" ]; then + MAVEN_PROJECTBASEDIR=$(cd "$(dirname "$0")" && pwd) + export MAVEN_PROJECTBASEDIR +fi + +WRAPPER_PROPERTIES="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + +if [ ! -f "$WRAPPER_PROPERTIES" ]; then + echo "Error: Could not find $WRAPPER_PROPERTIES" >&2 + exit 1 +fi + +# Read distributionUrl from properties file +distributionUrl=$(grep 'distributionUrl' "$WRAPPER_PROPERTIES" | cut -d'=' -f2- | tr -d '[:space:]') + +if [ -z "$distributionUrl" ]; then + echo "Error: Could not read distributionUrl from $WRAPPER_PROPERTIES" >&2 + exit 1 +fi + +# Set up Maven home in user's local cache +MAVEN_USER_HOME="${MAVEN_USER_HOME:-$HOME/.m2}" +WRAPPER_DIR="$MAVEN_USER_HOME/wrapper/dists" + +# Extract Maven version from URL for directory naming +DIST_NAME=$(basename "$distributionUrl" .zip) +# The zip may contain a directory without the '-bin' suffix +MAVEN_DIR_NAME=$(echo "$DIST_NAME" | sed 's/-bin$//') +MAVEN_HOME="$WRAPPER_DIR/$MAVEN_DIR_NAME" +MAVEN_CMD="$MAVEN_HOME/bin/mvn" + +if [ ! -x "$MAVEN_CMD" ]; then + echo "Downloading Maven from $distributionUrl ..." + mkdir -p "$WRAPPER_DIR" + DOWNLOAD_FILE="$WRAPPER_DIR/$DIST_NAME.zip" + + if command -v curl > /dev/null 2>&1; then + curl -fsSL -o "$DOWNLOAD_FILE" "$distributionUrl" + elif command -v wget > /dev/null 2>&1; then + wget -q -O "$DOWNLOAD_FILE" "$distributionUrl" + else + echo "Error: Neither curl nor wget found. Cannot download Maven." >&2 + exit 1 + fi + + echo "Extracting Maven ..." + if command -v unzip > /dev/null 2>&1; then + unzip -q -o "$DOWNLOAD_FILE" -d "$WRAPPER_DIR" + elif command -v jar > /dev/null 2>&1; then + mkdir -p "$MAVEN_HOME" + cd "$WRAPPER_DIR" + jar xf "$DOWNLOAD_FILE" + cd "$MAVEN_PROJECTBASEDIR" + elif command -v python3 > /dev/null 2>&1; then + python3 -c "import zipfile,sys; zipfile.ZipFile(sys.argv[1]).extractall(sys.argv[2])" "$DOWNLOAD_FILE" "$WRAPPER_DIR" + else + echo "Error: No tool found to extract zip (tried unzip, jar, python3)." >&2 + exit 1 + fi + rm -f "$DOWNLOAD_FILE" + chmod +x "$MAVEN_CMD" +fi + +exec "$MAVEN_CMD" "$@" diff --git a/emailslicer-dkasargod-java/mvnw.cmd b/emailslicer-dkasargod-java/mvnw.cmd new file mode 100644 index 0000000..494f3f5 --- /dev/null +++ b/emailslicer-dkasargod-java/mvnw.cmd @@ -0,0 +1,37 @@ +@REM Maven Wrapper script for Windows +@REM Based on https://github.com/apache/maven-wrapper + +@echo off +setlocal + +set "MAVEN_PROJECTBASEDIR=%~dp0" +set "WRAPPER_PROPERTIES=%MAVEN_PROJECTBASEDIR%.mvn\wrapper\maven-wrapper.properties" + +if not exist "%WRAPPER_PROPERTIES%" ( + echo Error: Could not find %WRAPPER_PROPERTIES% >&2 + exit /b 1 +) + +for /f "tokens=1,* delims==" %%a in ('findstr "distributionUrl" "%WRAPPER_PROPERTIES%"') do set "distributionUrl=%%b" + +if "%distributionUrl%"=="" ( + echo Error: Could not read distributionUrl >&2 + exit /b 1 +) + +set "MAVEN_USER_HOME=%USERPROFILE%\.m2" +set "WRAPPER_DIR=%MAVEN_USER_HOME%\wrapper\dists" + +for %%i in ("%distributionUrl%") do set "DIST_NAME=%%~ni" +set "MAVEN_HOME=%WRAPPER_DIR%\%DIST_NAME%" +set "MAVEN_CMD=%MAVEN_HOME%\bin\mvn.cmd" + +if not exist "%MAVEN_CMD%" ( + echo Downloading Maven from %distributionUrl% ... + mkdir "%WRAPPER_DIR%" 2>nul + powershell -Command "Invoke-WebRequest -Uri '%distributionUrl%' -OutFile '%WRAPPER_DIR%\%DIST_NAME%.zip'" + powershell -Command "Expand-Archive -Path '%WRAPPER_DIR%\%DIST_NAME%.zip' -DestinationPath '%WRAPPER_DIR%' -Force" + del "%WRAPPER_DIR%\%DIST_NAME%.zip" +) + +"%MAVEN_CMD%" %* diff --git a/emailslicer-dkasargod-java/pom.xml b/emailslicer-dkasargod-java/pom.xml new file mode 100644 index 0000000..eeee4c1 --- /dev/null +++ b/emailslicer-dkasargod-java/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + com.emailslicer + email-slicer + 1.0.0 + jar + + Email Slicer + A CLI tool that parses an email address into its username and domain parts + + + 17 + 17 + UTF-8 + 5.10.2 + + + + + org.junit.jupiter + junit-jupiter + ${junit.version} + test + + + + + email-slicer + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + com.emailslicer.Main + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.5 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.12.1 + + 17 + 17 + + + + + diff --git a/emailslicer-dkasargod-java/src/main/java/com/emailslicer/EmailParts.java b/emailslicer-dkasargod-java/src/main/java/com/emailslicer/EmailParts.java new file mode 100644 index 0000000..a309d9a --- /dev/null +++ b/emailslicer-dkasargod-java/src/main/java/com/emailslicer/EmailParts.java @@ -0,0 +1,10 @@ +package com.emailslicer; + +/** + * Immutable value object holding the parsed username and domain parts of an email address. + * + * @param username the local part of the email address (before the {@code @} symbol) + * @param domain the domain part of the email address (after the {@code @} symbol) + */ +public record EmailParts(String username, String domain) { +} diff --git a/emailslicer-dkasargod-java/src/main/java/com/emailslicer/EmailSlicer.java b/emailslicer-dkasargod-java/src/main/java/com/emailslicer/EmailSlicer.java new file mode 100644 index 0000000..58bb48c --- /dev/null +++ b/emailslicer-dkasargod-java/src/main/java/com/emailslicer/EmailSlicer.java @@ -0,0 +1,55 @@ +package com.emailslicer; + +/** + * Parses an email address string into its username and domain components. + * + *

This class contains the core parsing logic, separated from I/O concerns + * to allow direct unit testing without mocking {@code System.in}/{@code System.out}. + */ +public final class EmailSlicer { + + private EmailSlicer() { + // Utility class — not instantiable + } + + /** + * Parses the given email string into an {@link EmailParts} record. + * + *

The input is trimmed before validation. Validation requires: + *

+ * + * @param email the raw email address string + * @return an {@link EmailParts} instance containing the username and domain + * @throws IllegalArgumentException if the input fails validation + */ + public static EmailParts parse(String email) { + if (email == null || email.isBlank()) { + throw new IllegalArgumentException(Messages.INVALID_EMAIL_MESSAGE); + } + + String trimmed = email.strip(); + + int atIndex = trimmed.indexOf('@'); + if (atIndex == -1) { + throw new IllegalArgumentException(Messages.INVALID_EMAIL_MESSAGE); + } + + // Reject multiple '@' characters + if (trimmed.indexOf('@', atIndex + 1) != -1) { + throw new IllegalArgumentException(Messages.INVALID_EMAIL_MESSAGE); + } + + String username = trimmed.substring(0, atIndex); + String domain = trimmed.substring(atIndex + 1); + + if (username.isEmpty() || domain.isEmpty()) { + throw new IllegalArgumentException(Messages.INVALID_EMAIL_MESSAGE); + } + + return new EmailParts(username, domain); + } +} diff --git a/emailslicer-dkasargod-java/src/main/java/com/emailslicer/Main.java b/emailslicer-dkasargod-java/src/main/java/com/emailslicer/Main.java new file mode 100644 index 0000000..8f057bd --- /dev/null +++ b/emailslicer-dkasargod-java/src/main/java/com/emailslicer/Main.java @@ -0,0 +1,34 @@ +package com.emailslicer; + +import java.util.Scanner; + +/** + * CLI entry point for the Email Slicer application. + * + *

Prompts the user for an email address, delegates parsing to + * {@link EmailSlicer#parse(String)}, and prints the result. Exits with + * code 1 when the input is invalid. + */ +public final class Main { + + private Main() { + // Entry-point class — not instantiable + } + + public static void main(String[] args) { + System.out.println(Messages.PROMPT_MESSAGE); + + try (Scanner scanner = new Scanner(System.in)) { + String email = scanner.nextLine().strip(); + + try { + EmailParts parts = EmailSlicer.parse(email); + System.out.println(Messages.USERNAME_PREFIX + parts.username()); + System.out.println(Messages.DOMAIN_PREFIX + parts.domain()); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + System.exit(1); + } + } + } +} diff --git a/emailslicer-dkasargod-java/src/main/java/com/emailslicer/Messages.java b/emailslicer-dkasargod-java/src/main/java/com/emailslicer/Messages.java new file mode 100644 index 0000000..66b5793 --- /dev/null +++ b/emailslicer-dkasargod-java/src/main/java/com/emailslicer/Messages.java @@ -0,0 +1,16 @@ +package com.emailslicer; + +/** + * Centralised store for user-facing messages. + */ +public final class Messages { + + public static final String PROMPT_MESSAGE = "Please enter your Email Id:"; + public static final String INVALID_EMAIL_MESSAGE = "Please enter a valid Email Id."; + public static final String USERNAME_PREFIX = "Your username is: "; + public static final String DOMAIN_PREFIX = "Your domain is: "; + + private Messages() { + // Utility class — not instantiable + } +} diff --git a/emailslicer-dkasargod-java/src/test/java/com/emailslicer/EmailSlicerTest.java b/emailslicer-dkasargod-java/src/test/java/com/emailslicer/EmailSlicerTest.java new file mode 100644 index 0000000..14de000 --- /dev/null +++ b/emailslicer-dkasargod-java/src/test/java/com/emailslicer/EmailSlicerTest.java @@ -0,0 +1,66 @@ +package com.emailslicer; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for {@link EmailSlicer#parse(String)}. + */ +class EmailSlicerTest { + + @Test + @DisplayName("Valid email is split into username and domain") + void validEmail() { + EmailParts result = EmailSlicer.parse("avimax37@gmail.com"); + assertEquals(new EmailParts("avimax37", "gmail.com"), result); + } + + @Test + @DisplayName("Leading and trailing whitespace is trimmed before parsing") + void leadingTrailingWhitespace() { + EmailParts result = EmailSlicer.parse(" user@example.org "); + assertEquals(new EmailParts("user", "example.org"), result); + } + + @Test + @DisplayName("Missing '@' throws IllegalArgumentException") + void missingAtSign() { + IllegalArgumentException ex = assertThrows( + IllegalArgumentException.class, + () -> EmailSlicer.parse("invalidemail") + ); + assertEquals(Messages.INVALID_EMAIL_MESSAGE, ex.getMessage()); + } + + @Test + @DisplayName("Empty string throws IllegalArgumentException") + void emptyString() { + assertThrows(IllegalArgumentException.class, () -> EmailSlicer.parse("")); + } + + @Test + @DisplayName("Null input throws IllegalArgumentException") + void nullInput() { + assertThrows(IllegalArgumentException.class, () -> EmailSlicer.parse(null)); + } + + @Test + @DisplayName("Multiple '@' signs throws IllegalArgumentException") + void multipleAtSigns() { + assertThrows(IllegalArgumentException.class, () -> EmailSlicer.parse("a@b@c.com")); + } + + @Test + @DisplayName("Empty username (@domain.com) throws IllegalArgumentException") + void emptyUsername() { + assertThrows(IllegalArgumentException.class, () -> EmailSlicer.parse("@domain.com")); + } + + @Test + @DisplayName("Empty domain (user@) throws IllegalArgumentException") + void emptyDomain() { + assertThrows(IllegalArgumentException.class, () -> EmailSlicer.parse("user@")); + } +}