Line data Source code
1 1 : /** 2 : 3 : @file CalculatorApp.java 4 : @brief This file serves as the main application file for the Calculator App. 5 : @details This file contains the entry point of the application, which is the main method. It initializes the necessary components and executes the Calculator App. 6 : */ 7 : /** 8 : 9 : @package com.ucoruh.calculator 10 : @brief The com.ucoruh.calculator package contains all the classes and files related to the Calculator App. 11 : */ 12 : package com.ucoruh.calculator; 13 : 14 : import org.slf4j.LoggerFactory; 15 : 16 : import ch.qos.logback.classic.Logger; 17 : 18 : /** 19 : * 20 : * @class CalculatorApp 21 : * @brief This class represents the main application class for the Calculator 22 : * App. 23 : * @details The CalculatorApp class provides the entry point for the Calculator 24 : * App. It parses three command-line arguments (operand, operator, 25 : * operand), computes the result with {@link Calculator} and prints 26 : * it. It never reads from standard input, so it is safe to run from 27 : * a non-interactive script and to unit test directly. 28 : * @author ugur.coruh 29 : */ 30 1 : public class CalculatorApp { 31 : /** 32 : * @brief Logger for the CalculatorApp class. 33 : */ 34 1 : private static final Logger logger = (Logger) LoggerFactory.getLogger(CalculatorApp.class); 35 : 36 : /** 37 : * @brief Usage message shown when the arguments do not describe a single 38 : * binary operation. 39 : */ 40 : static final String USAGE = "Usage: CalculatorApp <number> <+|-|*|/> <number>"; 41 : 42 0 : private CalculatorApp() { 43 : // Utility/entry-point class: not meant to be instantiated. 44 : } 45 : 46 : /** 47 : * @brief The main entry point of the Calculator App. 48 : * 49 : * @details Delegates all the work to {@link #run(String[])} and prints its 50 : * result. Kept deliberately thin so that the parsing/calculation 51 : * logic in `run` can be unit tested without touching the console. 52 : * 53 : * @param args The command-line arguments passed to the application: 54 : * `<number> <operator> <number>`. 55 : */ 56 1 : public static void main(String[] args) { 57 : System.out.println(run(args)); 58 : } 59 : 60 : /** 61 : * @brief Parses `args` as `<number> <operator> <number>` and computes the 62 : * result. 63 : * 64 : * @details This is the testable core of the application: it performs no 65 : * I/O (it neither reads from `System.in` nor writes to 66 : * `System.out`) and never blocks, so it can be called directly 67 : * from tests and from scripts alike. Recognized operators are 68 : * `+`, `-`, `*` and `/`. Invalid input (wrong argument count, 69 : * non-numeric operand, unknown operator, division by zero) is 70 : * reported as a descriptive `"Error: ..."` string instead of an 71 : * uncaught exception, so the process always exits cleanly with a 72 : * printable message. 73 : * 74 : * @param args The command-line arguments. 75 : * @return A human-readable result or error message. 76 : */ 77 : static String run(String[] args) { 78 : if (args == null || args.length != 3) { 79 : logger.warn("Expected 3 arguments, got {}", args == null ? 0 : args.length); 80 : return USAGE; 81 : } 82 : 83 : final int left; 84 : final int right; 85 : 86 : try { 87 : left = Integer.parseInt(args[0]); 88 : right = Integer.parseInt(args[2]); 89 : } catch (NumberFormatException e) { 90 : logger.error("Invalid operand: {}", e.toString()); 91 : return "Error: operands must be integers. " + USAGE; 92 : } 93 : 94 : String operator = args[1]; 95 : Calculator calculator = new Calculator(); 96 : 97 : switch (operator) { 98 : case "+": 99 : return String.valueOf(calculator.add(left, right)); 100 : 101 : case "-": 102 : return String.valueOf(calculator.subtract(left, right)); 103 : 104 : case "*": 105 : return String.valueOf(calculator.multiply(left, right)); 106 : 107 : case "/": 108 : try { 109 : return String.valueOf(calculator.divide(left, right)); 110 : } catch (ArithmeticException e) { 111 : logger.error("Division by zero requested"); 112 : return "Error: division by zero"; 113 : } 114 : 115 : default: 116 : logger.warn("Unknown operator: {}", operator); 117 : return "Error: unknown operator '" + operator + "'. " + USAGE; 118 : } 119 : } 120 : }