77import org .springframework .cache .annotation .CacheEvict ;
88import org .springframework .cache .annotation .CachePut ;
99import org .springframework .cache .annotation .Cacheable ;
10- import org .springframework .http .HttpStatus ;
1110import org .springframework .stereotype .Service ;
11+ import org .springframework .transaction .annotation .Transactional ;
1212import smartpot .com .api .Commands .Mapper .MCommand ;
1313import smartpot .com .api .Commands .Model .DTO .CommandDTO ;
14- import smartpot .com .api .Commands .Model .Entity .Command ;
1514import smartpot .com .api .Commands .Repository .RCommand ;
1615import smartpot .com .api .Crops .Service .SCropI ;
17- import smartpot .com .api .Exception .ApiException ;
18- import smartpot .com .api .Exception .ApiResponse ;
1916
2017import java .text .SimpleDateFormat ;
2118import java .util .Date ;
2219import java .util .List ;
2320import java .util .Optional ;
24-
21+ import java .util .stream .Collectors ;
22+
23+ /**
24+ * Service implementation for managing commands.
25+ *
26+ * <p>
27+ * This class provides the business logic for managing commands, including
28+ * CRUD operations and execution logic. It interacts with the repository,
29+ * a mapper, and additional services to fulfill its responsibilities.
30+ * </p>
31+ *
32+ * <h3>Annotations:</h3>
33+ * <ul>
34+ * <li>{@code @Data} - Generates boilerplate code such as getters, setters, and toString.</li>
35+ * <li>{@code @Builder} - Enables the builder pattern for constructing instances of this class.</li>
36+ * <li>{@code @Service} - Marks this class as a Spring-managed service component.</li>
37+ * </ul>
38+ *
39+ * <h3>Dependencies:</h3>
40+ * <ul>
41+ * <li>{@code RCommand} - Repository for accessing and persisting command entities.</li>
42+ * <li>{@code SCropI} - Service for managing crops, used for operations involving crop data.</li>
43+ * <li>{@code MCommand} - Mapper for converting between entity and DTO representations of commands.</li>
44+ * </ul>
45+ *
46+ * <h3>Responsibilities:</h3>
47+ * <ul>
48+ * <li>Provides methods for creating, retrieving, updating, and deleting commands.</li>
49+ * <li>Implements caching for frequently accessed commands to improve performance.</li>
50+ * <li>Validates and processes business logic for commands before interacting with the repository.</li>
51+ * </ul>
52+ *
53+ * <h3>Usage:</h3>
54+ * <p>
55+ * This service is typically used by controllers to handle HTTP requests related to commands,
56+ * or by other services that depend on command-related operations.
57+ * </p>
58+ *
59+ * @see SCommandI
60+ * @see RCommand
61+ * @see SCropI
62+ * @see MCommand
63+ */
2564@ Data
2665@ Builder
2766@ Service
@@ -31,18 +70,52 @@ public class SCommand implements SCommandI {
3170 private final SCropI serviceCrop ;
3271 private final MCommand mapperCommand ;
3372
73+ /**
74+ * Constructs an instance of {@code SCommand} with the required dependencies.
75+ *
76+ * @param repositoryCommand the repository for command-related database operations
77+ * @param serviceCrop the service responsible for crop-related logic
78+ * @param mapperCommand the mapper for converting entities to DTOs and vice versa
79+ */
3480 @ Autowired
3581 public SCommand (RCommand repositoryCommand , SCropI serviceCrop , MCommand mapperCommand ) {
3682 this .repositoryCommand = repositoryCommand ;
3783 this .serviceCrop = serviceCrop ;
3884 this .mapperCommand = mapperCommand ;
3985 }
4086
87+ /**
88+ * Retrieves all commands from the repository and maps them to DTOs.
89+ * <p>
90+ * This method is cached to improve performance when retrieving the list of commands.
91+ * The cache is identified by the key 'all_commands' under the 'commands' cache.
92+ * </p>
93+ *
94+ * @return a list of {@code CommandDTO} objects representing all commands
95+ * @throws Exception if no commands exist in the repository
96+ */
4197 @ Override
42- public List <Command > getAllCommands () {
43- return repositoryCommand .findAll ();
98+ @ Cacheable (value = "commands" , key = "'all_commands'" )
99+ public List <CommandDTO > getAllCommands () throws Exception {
100+ return Optional .of (repositoryCommand .findAll ())
101+ .filter (commands -> !commands .isEmpty ())
102+ .map (crops -> crops .stream ()
103+ .map (mapperCommand ::toDTO )
104+ .collect (Collectors .toList ()))
105+ .orElseThrow (() -> new Exception ("No existe ningún comando" ));
44106 }
45107
108+ /**
109+ * Retrieves a command by its unique identifier and maps it to a DTO.
110+ * <p>
111+ * This method is cached to improve performance for retrieving individual commands.
112+ * The cache is identified by the key pattern 'id_{id}' under the 'commands' cache.
113+ * </p>
114+ *
115+ * @param id the unique identifier of the command to retrieve
116+ * @return a {@code CommandDTO} representing the command with the specified ID
117+ * @throws Exception if the command with the specified ID does not exist
118+ */
46119 @ Override
47120 @ Cacheable (value = "commands" , key = "'id_'+#id" )
48121 public CommandDTO getCommandById (String id ) throws Exception {
@@ -55,7 +128,21 @@ public CommandDTO getCommandById(String id) throws Exception {
55128 .orElseThrow (() -> new Exception ("El Comando no existe" ));
56129 }
57130
131+ /**
132+ * Creates a new command based on the provided DTO, sets its creation date and status,
133+ * and persists it in the repository.
134+ *
135+ * <p>
136+ * This method assigns a default status of "PENDING" and records the current timestamp
137+ * as the creation date in the format "yyyy-MM-dd HH:mm:ss".
138+ * </p>
139+ *
140+ * @param commandDTO the {@code CommandDTO} containing the details of the command to create
141+ * @return a {@code CommandDTO} representing the created command
142+ * @throws IllegalStateException if a command with the same details already exists
143+ */
58144 @ Override
145+ @ Transactional
59146 public CommandDTO createCommand (CommandDTO commandDTO ) throws IllegalStateException {
60147 return Optional .of (commandDTO )
61148 .map (dto -> {
@@ -70,84 +157,22 @@ public CommandDTO createCommand(CommandDTO commandDTO) throws IllegalStateExcept
70157 .orElseThrow (() -> new IllegalStateException ("El Comando ya existe" ));
71158 }
72159
73- @ Override
74- public Command updateCommand (String id , Command upCommand ) throws Exception {
75- if (!ObjectId .isValid (id )) {
76- throw new ApiException (new ApiResponse (
77- "El ID '" + id + "' no es válido. Asegúrate de que tiene 24 caracteres y solo incluye dígitos hexadecimales (0-9, a-f, A-F)." ,
78- HttpStatus .BAD_REQUEST .value ()
79- ));
80- }
81- Command exCommand = repositoryCommand .findById (new ObjectId (id )).orElseThrow (() -> new ApiException (
82- new ApiResponse ("El Comando con ID '" + id + "' no fue encontrado." ,
83- HttpStatus .NOT_FOUND .value ())
84- ));
85-
86- if (upCommand == null ) {
87- throw new IllegalArgumentException ("El comando de actualización no puede ser nulo" );
88- }
89-
90- if (upCommand .getCrop () == null && serviceCrop .getCropById (upCommand .getCrop ().toString ()) != null ) {
91- throw new IllegalArgumentException ("El campo 'crop' no puede ser nulo" );
92- }
93-
94- if (upCommand .getDateCreated () == null ) {
95- throw new IllegalArgumentException ("El campo 'dateCreated' no puede ser nulo" );
96- }
97-
98- // Validar y convertir commandType a mayúsculas
99- if (upCommand .getCommandType () == null || upCommand .getCommandType ().isEmpty ()) {
100- throw new IllegalArgumentException ("El campo 'commandType' no puede estar vacío" );
101- } else {
102- exCommand .setCommandType (upCommand .getCommandType ().toUpperCase ());
103- }
104-
105- // Validar y convertir status a mayúsculas
106- if (upCommand .getStatus () == null || upCommand .getStatus ().isEmpty ()) {
107- throw new IllegalArgumentException ("El campo 'status' no puede estar vacío" );
108- } else {
109- exCommand .setStatus (upCommand .getStatus ().toUpperCase ());
110- }
111-
112- // Si se cumplen todas las validaciones, se procede a actualizar el comando
113- if (exCommand != null ) {
114- exCommand .setCrop (upCommand .getCrop ());
115- exCommand .setResponse (upCommand .getResponse ());
116- exCommand .setDateCreated (upCommand .getDateCreated ());
117- return repositoryCommand .save (exCommand );
118- } else {
119- return null ;
120- }
121- /*
122-
123-
124- if (!upCommand.getCommandType().matches(exCommand.getCommandType())) {
125- throw new Exception(new ErrorResponse(
126- "El nombre '" + upCommand.getCommandType() + "' no es válido.",
127- HttpStatus.BAD_REQUEST.value()
128- ));
129- }
130- if (!upCommand.ge) {
131- }
132- */
133-
134-
135- }
136-
137- @ Override
138- @ CacheEvict (value = "commands" , key = "'id_'+#id" )
139- public String deleteCommand (String id ) throws Exception {
140- return Optional .of (getCommandById (id ))
141- .map (command -> {
142- repositoryCommand .deleteById (new ObjectId (command .getId ()));
143- return "El Comando con ID '" + id + "' fue eliminado." ;
144- })
145- .orElseThrow (() -> new Exception ("El Comando no existe." ));
146- }
147-
160+ /**
161+ * Executes a command by updating its status to "EXECUTED" and setting a response message.
162+ *
163+ * <p>
164+ * This method updates the specified command with the current timestamp, sets its status to
165+ * "EXECUTED", and records the provided response message.
166+ * </p>
167+ *
168+ * @param id the ID of the command to execute
169+ * @param response the response message to associate with the executed command
170+ * @return a {@code CommandDTO} representing the updated command
171+ * @throws Exception if the command cannot be found or updated
172+ */
148173 @ Override
149174 @ CachePut (value = "commands" , key = "'id:'+#id" )
150- public CommandDTO excuteCommand (String id , String response ) throws Exception {
175+ public CommandDTO executeCommand (String id , String response ) throws Exception {
151176 return Optional .of (getCommandById (id ))
152177 .map (commandDTO -> {
153178 SimpleDateFormat formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss" );
@@ -162,31 +187,59 @@ public CommandDTO excuteCommand(String id, String response) throws Exception {
162187 .orElseThrow (() -> new Exception ("El Comando no se pudo actualizar" ));
163188 }
164189
165- /*
166-
167-
168-
169-
170- public Command executeCommand(String id, String response) {
171- Command command = repositoryCommand.findById(id).orElse(null);
172- if (command != null) {
173- command.setStatus("EXECUTED");
174- command.setDateExecuted(new Date());
175- command.setResponse(response);
176- return repositoryCommand.save(command);
177- }
178- return null;
190+ /**
191+ * Updates the specified command with new details provided in the update DTO.
192+ *
193+ * <p>
194+ * This method updates fields in the command only if the corresponding fields in the
195+ * update DTO are non-null. The existing values are retained for fields that are null in the update DTO.
196+ * </p>
197+ *
198+ * @param id the ID of the command to update
199+ * @param updateCommand the {@code CommandDTO} containing the updated details
200+ * @return a {@code CommandDTO} representing the updated command
201+ * @throws Exception if the command cannot be found or updated
202+ */
203+ @ Override
204+ @ Transactional
205+ @ CachePut (value = "commands" , key = "'id_'+#id" )
206+ public CommandDTO updateCommand (String id , CommandDTO updateCommand ) throws Exception {
207+ CommandDTO existingCommand = getCommandById (id );
208+ return Optional .of (updateCommand )
209+ .map (dto -> {
210+ existingCommand .setId (dto .getCommandType () != null ? dto .getCommandType () : existingCommand .getCommandType ());
211+ existingCommand .setResponse (dto .getResponse () != null ? dto .getResponse () : existingCommand .getResponse ());
212+ existingCommand .setCrop (dto .getCrop () != null ? dto .getCrop () : existingCommand .getCrop ());
213+ return existingCommand ;
214+ })
215+ .map (mapperCommand ::toEntity )
216+ .map (repositoryCommand ::save )
217+ .map (mapperCommand ::toDTO )
218+ .orElseThrow (() -> new Exception ("El Comando no se pudo actualizar" ));
179219 }
180220
181-
182-
183- public List<Command> getCommandsByStatus(String status) {
184- return repositoryCommand.findByStatus(status);
221+ /**
222+ * Deletes the specified command by its ID.
223+ *
224+ * <p>
225+ * This method removes the command from the repository and evicts the corresponding cache entry.
226+ * </p>
227+ *
228+ * @param id the ID of the command to delete
229+ * @return a confirmation message indicating the successful deletion
230+ * @throws Exception if the command cannot be found
231+ */
232+ @ Override
233+ @ Transactional
234+ @ CacheEvict (value = "commands" , key = "'id_'+#id" )
235+ public String deleteCommand (String id ) throws Exception {
236+ return Optional .of (getCommandById (id ))
237+ .map (command -> {
238+ repositoryCommand .deleteById (new ObjectId (command .getId ()));
239+ return "El Comando con ID '" + id + "' fue eliminado." ;
240+ })
241+ .orElseThrow (() -> new Exception ("El Comando no existe." ));
185242 }
186243
187- public List<Command> getCommandsByCropId(String cropId) {
188- return repositoryCommand.findByCrop_Id(cropId);
189- }
190244
191- */
192245}
0 commit comments