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}