I need to draw a UML Activity diagram for a school java software engineering project I’m required to do. I’m quite new to this and I’m not sure what should be shown and what should not be shown. For this question, I’m interested to show the activity diagram from user input till before the statistics feature produces the GUI elements back to the user. The project uses the Command Pattern and these are the 2 most actively involved classes.


 * Parses input arguments and creates a new StatsCommand object
public class StatsCommandParser implements Parser<StatsCommand> {

    public static final List<Prefix> REQUIRED_PREFIXES = Collections.unmodifiableList(List.of());

    public static final List<Prefix> OPTIONAL_PREFIXES = Collections.unmodifiableList(List.of(

     * Parses the given {@code String} of arguments in the context of the StatsCommand
     * and returns an StatsCommand object for execution.
     * @throws ParseException if the user input does not conform the expected format
    public StatsCommand parse(String args) throws ParseException {

        ArgumentMultimap argMultimap =
                ArgumentTokenizer.tokenize(args, PREFIX_START_DATE, PREFIX_END_DATE);
        if (!argMultimap.getPreamble().isEmpty()) {
            throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, StatsCommand.MESSAGE_USAGE));
        if (argMultimap.hasRepeatedPrefixes(PREFIX_START_DATE, PREFIX_END_DATE)) {
            throw new ParseException(MESSAGE_REPEATED_PREFIX_COMMAND);

        StatsDescriptor statsDescriptor = new StatsDescriptor();

        Timestamp startDate = null;
        Timestamp endDate = null;

        boolean isStartPresent = argMultimap.getValue(PREFIX_START_DATE).isPresent();
        boolean isEndPresent = argMultimap.getValue(PREFIX_END_DATE).isPresent();
        if (isStartPresent && isEndPresent) {
            startDate = ParserUtil.parseTimestamp(argMultimap.getValue(PREFIX_START_DATE).get());
            endDate = ParserUtil.parseTimestamp(argMultimap.getValue(PREFIX_END_DATE).get());
            if (!statsDescriptor.isStartBeforeEnd()) {
                throw new ParseException(Messages.MESSAGE_CONSTRAINTS_END_DATE);
        } else if (isStartPresent) {
            startDate = ParserUtil.parseTimestamp(argMultimap.getValue(PREFIX_START_DATE).get());
        } else if (isEndPresent) {
            endDate = ParserUtil.parseTimestamp(argMultimap.getValue(PREFIX_END_DATE).get());

        return new StatsCommand(statsDescriptor);


 * Represents a StatsCommand that is meant to output statistics using the visual
 * representation of a pie chart
public class StatsCommand extends Command {

    public static final String COMMAND_WORD = "statsbasic" + CommandGroup.GENERAL;

    public static final String MESSAGE_SUCCESS = "Pie Chart calculated!";

    public static final String MESSAGE_USAGE = COMMAND_WORD
            + ": Calculates statistics between the Start Date and End Date "
            + "Parameters: "
            + "[" + PREFIX_START_DATE + "START_DATE] "
            + "[" + PREFIX_END_DATE + "END_DATE] "
            + "\nExample: " + COMMAND_WORD + " "
            + PREFIX_START_DATE + "11-11-1111 "
            + PREFIX_END_DATE + "12-12-1212 ";

    private StatsDescriptor statsDescriptor;

     * Creates a StatsCommand to calculate statistics between 2 dates {@code Timestamp}
    public StatsCommand(StatsDescriptor statsDescriptor) {
        this.statsDescriptor = statsDescriptor;

    protected void validate(Model model) throws CommandException {
        if (!model.hasPrimaryBudget()) {
            throw new CommandException(MESSAGE_DISPLAY_STATISTICS_WITHOUT_BUDGET);

    public CommandResult execute(Model model) {

        Budget primaryBudget = model.getPrimaryBudget();
        Statistics statistics = createPieChartStatistics(primaryBudget, statsDescriptor);

        return new CommandResult(MESSAGE_SUCCESS, false, false, StatsPanel.PANEL_NAME);

    public boolean equals(Object other) {
        return other == this //short circuit if same object
                || (other instanceof StatsCommand // instance of handles nulls
                && statsDescriptor.equals(((StatsCommand) other).statsDescriptor));

     * Creates and returns a {@code Statistics} with the details of {@code statsDescriptor}
     * and {@code primaryBudget} where necessary.
    private Statistics createPieChartStatistics(Budget primaryBudget, StatsDescriptor statsDescriptor) {
        Optional<Timestamp> startDate = statsDescriptor.getStartDate();
        Optional<Timestamp> endDate = statsDescriptor.getEndDate();

        boolean isStartPresent = startDate.isPresent();
        boolean isEndPresent = endDate.isPresent();

        if (!isStartPresent && !isEndPresent) {
            startDate = Optional.of(primaryBudget.getWindowStartDate());
            endDate = Optional.of(primaryBudget.getWindowEndDate());
        } else if (isStartPresent && !isEndPresent) {
            endDate = Optional.of(startDate.get().createForwardTimestamp(primaryBudget.getBudgetPeriod()).minusDays(1));
        } else if (!isStartPresent) {
            startDate = Optional.of(endDate.get().createBackwardTimestamp(primaryBudget.getBudgetPeriod()).plusDays(1));

        PieChartStatistics statistics = new PieChartStatistics(primaryBudget.getExpenses(),
                startDate.get(), endDate.get());
        return statistics;



enter image description here

Can anyone give me some feedback about my Activity Diagram? Do inform me if more information and files are required.

2 Answers 2


Just looking at the diagram without looking at the code:

  • the text over edges outgoing from a decision node should always be [ between bracket ]
  • the decision making cascade with several [ none of the above ] and check for more cases seems seems weird. We should be able to make th choice not knowing the history of the flow:

    • use [ else ] guard instead of [ none of the above ]
    • clarify what you mean with check for more cases
    • an activity does not make a check for the decision afterwards. If check for more cases is meant as a placeholder for doing this, then change your diagram to have 4 outgoing branches from the first decision node after step5. The guards should allow to always chose the right one directly.
    • for more clarity, you could attach a « decisionInput » to the decision node, to clarify on what the decision will be made.
    • Alternatively you could also simplify all this cascade, with a single activity determinine the budget start and end date to be considered.
  • Step 7: Done seems useless: this sounds more like a state than an activity.

  • The 2 error flows at the beginning go right to the end, without informing the user of any problem:

    • Is is really intended like this ? Or should an information activitiy be added here before going to the end?
    • Some indeed prefer a single final activity node like you used. But (depending on your teacher's instruction and viewpoint on the question), you may also have two distinct final activity nodes: one for the normal end and one as error end point. THis can help to better grasp the whole picture.

Just some additional remarks to what Christophe said:

  • The "Step n" prefix seems weird since half of the actions don't have that.
  • throws means an exception. You'd put that in an interruptible region and exit with an InterruptFlow (that flashy arrow). See bottom of https://www.uml-diagrams.org/activity-diagrams.html

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.