View Javadoc
1   package org.imageconverter.application;
2   
3   import static org.apache.commons.lang3.StringUtils.substringBetween;
4   import static org.apache.commons.lang3.exception.ExceptionUtils.getRootCauseMessage;
5   
6   import java.util.List;
7   
8   import javax.validation.Valid;
9   import javax.validation.constraints.NotNull;
10  
11  import org.imageconverter.domain.imagetype.ImageType;
12  import org.imageconverter.domain.imagetype.ImageTypeRespository;
13  import org.imageconverter.infra.exception.ElementAlreadyExistsException;
14  import org.imageconverter.infra.exception.ElementConflictException;
15  import org.imageconverter.infra.exception.ElementInvalidException;
16  import org.imageconverter.infra.exception.ElementNotFoundException;
17  import org.imageconverter.infra.exception.ElementWithIdNotFoundException;
18  import org.imageconverter.util.controllers.imagetype.CreateImageTypeRequest;
19  import org.imageconverter.util.controllers.imagetype.ImageTypeResponse;
20  import org.imageconverter.util.controllers.imagetype.UpdateImageTypeRequest;
21  import org.imageconverter.util.logging.Loggable;
22  import org.springframework.boot.logging.LogLevel;
23  import org.springframework.dao.DataIntegrityViolationException;
24  import org.springframework.dao.InvalidDataAccessApiUsageException;
25  import org.springframework.data.domain.Page;
26  import org.springframework.data.domain.Pageable;
27  import org.springframework.data.jpa.domain.Specification;
28  import org.springframework.stereotype.Service;
29  import org.springframework.transaction.annotation.Transactional;
30  
31  /**
32   * Application service that manages (CRUD) image types.
33   * 
34   * @author Fernando Romulo da Silva
35   */
36  @Service
37  @Loggable(value = LogLevel.INFO)
38  public class ImageTypeService {
39  
40      private final ImageTypeRespository repository;
41      
42      /**
43       * Default constructor.
44       * 
45       * @param newRepository imageType repository
46       */
47      ImageTypeService(final ImageTypeRespository newRepository) {
48  	super();
49  	this.repository = newRepository;
50      }
51  
52      /**
53       * Create a image type.
54       * 
55       * @param request A image type ({@link CreateImageTypeRequest}) request to create
56       * @return A {@link ImageTypeResponse} with the conversion
57       * @exception ElementAlreadyExistsException if image type (file extension) has already exists
58       */
59      @Transactional
60      public ImageTypeResponse createImageType(@NotNull @Valid final CreateImageTypeRequest request) {
61  
62  	final var imageTypeOptional = repository.findByExtension(request.extension());
63  
64  	if (imageTypeOptional.isPresent()) {
65  	    final Object[] params = { "extension '" + request.extension() + "'" };
66  
67  	    throw new ElementAlreadyExistsException(ImageType.class, params);
68  	}
69  
70  	final var imageType = new ImageType(request.extension(), request.name(), request.description());
71  
72  	final var imageConversion = repository.save(imageType);
73  
74  	return new ImageTypeResponse(imageType.getId(), imageConversion.getExtension(), imageType.getName());
75      }
76  
77      /**
78       * Update a image type.
79       * 
80       * @param id      The image type's id
81       * @param request A image type ({@link UpdateImageTypeRequest}) requested to update
82       * @return A {@link ImageTypeResponse} with the update's result
83       * @exception ElementNotFoundException if image type (file extension) doesn't exists
84       */
85      @Transactional
86      public ImageTypeResponse updateImageType(@NotNull final Long id, @NotNull @Valid final UpdateImageTypeRequest request) {
87  
88  	final var imageType = repository.findById(id) //
89  			.orElseThrow(() -> new ElementWithIdNotFoundException(ImageType.class, id));
90  
91  	imageType.update(request.extension(), request.name(), request.description());
92  
93  	final var imageTypeNew = repository.save(imageType);
94  
95  	return new ImageTypeResponse(imageTypeNew.getId(), imageTypeNew.getExtension(), imageTypeNew.getName());
96      }
97  
98      /**
99       * Delete a image type.
100      * 
101      * @param id The image type's id
102      * @exception ElementNotFoundException if image type (file extension) doesn't exists
103      * @exception ElementConflictException if amage type already been used on image conversion
104      */
105     @Transactional
106     public void deleteImageType(@NotNull final Long id) {
107 
108 	final var imageType = repository.findById(id) //
109 			.orElseThrow(() -> new ElementWithIdNotFoundException(ImageType.class, id));
110 
111 	try {
112 
113 	    repository.delete(imageType);
114 
115 	    repository.flush();
116 
117 	} catch (final DataIntegrityViolationException ex) {
118 
119 	    throw new ElementConflictException("{exception.imageTypeDeleteDataIntegrityViolation}", ex, id.toString());
120 	}
121     }
122 
123     /**
124      * Find a image type by id.
125      * 
126      * @param id The image type's id
127      * @return A {@link ImageTypeResponse} object
128      * @exception ElementNotFoundException if a element with id not found
129      */
130     @Transactional(readOnly = true)
131     public ImageTypeResponse findById(@NotNull final Long id) {
132 
133 	final var imageType = repository.findById(id) //
134 			.orElseThrow(() -> new ElementWithIdNotFoundException(ImageType.class, id));
135 
136 	return new ImageTypeResponse(imageType.getId(), imageType.getExtension(), imageType.getName());
137     }
138 
139     /**
140      * Find all stored image types or a empty list.
141      * 
142      * @return A list of {@link ImageTypeResponse} or a empty list
143      */
144     @Transactional(readOnly = true)
145     public List<ImageTypeResponse> findAll() {
146 
147 	return repository.findAll() //
148 			.stream() //
149 			.map(imageType -> new ImageTypeResponse(imageType.getId(), imageType.getExtension(), imageType.getName())) //
150 			.toList();
151     }
152 
153     /**
154      * Find image types by spring specification.
155      * 
156      * @param spec     The query specification, a {@link Specification} object
157      * @param pageable The query page control, a {@link Pageable} object
158      * @return A {@link ImageTypeResponse}'s list with result or a empty list
159      * @exception ElementInvalidException if a specification is invalid
160      */
161     @Transactional(readOnly = true)
162     public Page<ImageTypeResponse> findBySpecification(final Specification<ImageType> spec, final Pageable pageable) {
163 
164 	try {
165 
166 	    return repository.findAll(spec, pageable) //
167 			    .map(imageType -> new ImageTypeResponse( //
168 					    imageType.getId(), //
169 					    imageType.getExtension(), //
170 					    imageType.getName() //
171 			    ));
172 
173 	} catch (final InvalidDataAccessApiUsageException ex) {
174 
175 	    final var msgException = getRootCauseMessage(ex);
176 
177 	    final Object[] params = { substringBetween(msgException, "[", "]"), ImageType.class.getSimpleName() };
178 
179 	    throw new ElementInvalidException("{exception.ElementInvalidDataSpecification}", ex, params);
180 	}
181     }
182 }