001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package gov.nist.secauto.metaschema.cli.processor.command;
007
008import gov.nist.secauto.metaschema.core.util.ObjectUtils;
009
010import java.util.List;
011import java.util.ServiceLoader;
012import java.util.ServiceLoader.Provider;
013import java.util.stream.Collectors;
014
015import edu.umd.cs.findbugs.annotations.NonNull;
016import nl.talsmasoftware.lazy4j.Lazy;
017
018/**
019 * A service that loads commands using SPI.
020 * <p>
021 * This class implements the singleton pattern to ensure a single instance of
022 * the command service is used throughout the application.
023 *
024 * @see ServiceLoader for more information
025 */
026public final class CommandService {
027  private static final Lazy<CommandService> INSTANCE = Lazy.lazy(CommandService::new);
028  @NonNull
029  private final ServiceLoader<ICommand> loader;
030
031  /**
032   * Get the singleton instance of the function service.
033   *
034   * @return the service instance
035   */
036  public static CommandService getInstance() {
037    return INSTANCE.get();
038  }
039
040  /**
041   * Construct a new service.
042   * <p>
043   * Initializes the ServiceLoader for ICommand implementations.
044   * <p>
045   * This constructor is private to enforce the singleton pattern.
046   */
047  private CommandService() {
048    ServiceLoader<ICommand> loader = ServiceLoader.load(ICommand.class);
049    assert loader != null;
050    this.loader = loader;
051  }
052
053  /**
054   * Get the function service loader instance.
055   *
056   * @return the service loader instance.
057   */
058  @NonNull
059  private ServiceLoader<ICommand> getLoader() {
060    return loader;
061  }
062
063  /**
064   * Get the loaded commands.
065   *
066   * @return the list of loaded commands
067   */
068  @NonNull
069  public List<ICommand> getCommands() {
070    return ObjectUtils.notNull(getLoader().stream()
071        .map(Provider<ICommand>::get)
072        .collect(Collectors.toUnmodifiableList()));
073  }
074}