CalculatorApp.java

/**

@file CalculatorApp.java
@brief This file serves as the main application file for the Calculator App.
@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.
*/
/**

@package com.ucoruh.calculator
@brief The com.ucoruh.calculator package contains all the classes and files related to the Calculator App.
*/
package com.ucoruh.calculator;

import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.Logger;

/**
 *
 * @class CalculatorApp
 * @brief This class represents the main application class for the Calculator
 *        App.
 * @details The CalculatorApp class provides the entry point for the Calculator
 *          App. It parses three command-line arguments (operand, operator,
 *          operand), computes the result with {@link Calculator} and prints
 *          it. It never reads from standard input, so it is safe to run from
 *          a non-interactive script and to unit test directly.
 * @author ugur.coruh
 */
public class CalculatorApp {
  /**
   * @brief Logger for the CalculatorApp class.
   */
  private static final Logger logger = (Logger) LoggerFactory.getLogger(CalculatorApp.class);

  /**
   * @brief Usage message shown when the arguments do not describe a single
   *        binary operation.
   */
  static final String USAGE = "Usage: CalculatorApp <number> <+|-|*|/> <number>";

  private CalculatorApp() {
    // Utility/entry-point class: not meant to be instantiated.
  }

  /**
   * @brief The main entry point of the Calculator App.
   *
   * @details Delegates all the work to {@link #run(String[])} and prints its
   *          result. Kept deliberately thin so that the parsing/calculation
   *          logic in `run` can be unit tested without touching the console.
   *
   * @param args The command-line arguments passed to the application:
   *             `<number> <operator> <number>`.
   */
  public static void main(String[] args) {
    System.out.println(run(args));
  }

  /**
   * @brief Parses `args` as `<number> <operator> <number>` and computes the
   *        result.
   *
   * @details This is the testable core of the application: it performs no
   *          I/O (it neither reads from `System.in` nor writes to
   *          `System.out`) and never blocks, so it can be called directly
   *          from tests and from scripts alike. Recognized operators are
   *          `+`, `-`, `*` and `/`. Invalid input (wrong argument count,
   *          non-numeric operand, unknown operator, division by zero) is
   *          reported as a descriptive `"Error: ..."` string instead of an
   *          uncaught exception, so the process always exits cleanly with a
   *          printable message.
   *
   * @param args The command-line arguments.
   * @return A human-readable result or error message.
   */
  static String run(String[] args) {
    if (args == null || args.length != 3) {
      logger.warn("Expected 3 arguments, got {}", args == null ? 0 : args.length);
      return USAGE;
    }

    final int left;
    final int right;

    try {
      left = Integer.parseInt(args[0]);
      right = Integer.parseInt(args[2]);
    } catch (NumberFormatException e) {
      logger.error("Invalid operand: {}", e.toString());
      return "Error: operands must be integers. " + USAGE;
    }

    String operator = args[1];
    Calculator calculator = new Calculator();

    switch (operator) {
      case "+":
        return String.valueOf(calculator.add(left, right));

      case "-":
        return String.valueOf(calculator.subtract(left, right));

      case "*":
        return String.valueOf(calculator.multiply(left, right));

      case "/":
        try {
          return String.valueOf(calculator.divide(left, right));
        } catch (ArithmeticException e) {
          logger.error("Division by zero requested");
          return "Error: division by zero";
        }

      default:
        logger.warn("Unknown operator: {}", operator);
        return "Error: unknown operator '" + operator + "'. " + USAGE;
    }
  }
}