1 package fr.ifremer.tutti.persistence.service;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import com.google.common.base.Preconditions;
26 import com.google.common.collect.Lists;
27 import fr.ifremer.adagio.core.dao.data.measure.file.MeasurementFile;
28 import fr.ifremer.adagio.core.dao.data.measure.file.MeasurementFileDao;
29 import fr.ifremer.adagio.core.dao.referential.ObjectTypeCode;
30 import fr.ifremer.adagio.core.dao.referential.ObjectTypeImpl;
31 import fr.ifremer.adagio.core.dao.referential.QualityFlagCode;
32 import fr.ifremer.adagio.core.dao.referential.QualityFlagImpl;
33 import fr.ifremer.tutti.persistence.entities.data.Attachment;
34 import fr.ifremer.tutti.persistence.entities.data.Attachments;
35 import org.apache.commons.lang3.ObjectUtils;
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38 import org.hibernate.type.IntegerType;
39 import org.hibernate.type.StringType;
40 import org.nuiton.jaxx.application.ApplicationIOUtil;
41 import org.springframework.dao.DataRetrievalFailureException;
42 import org.springframework.dao.InvalidDataAccessResourceUsageException;
43 import org.springframework.stereotype.Service;
44
45 import javax.annotation.Resource;
46 import java.io.File;
47 import java.util.Collections;
48 import java.util.Iterator;
49 import java.util.List;
50 import java.util.Set;
51
52 import static org.nuiton.i18n.I18n.t;
53
54
55
56
57
58
59
60 @Service("attachmentPersistenceService")
61 public class AttachmentPersistenceServiceImpl extends AbstractPersistenceService implements AttachmentPersistenceService {
62
63
64 private static final Log log =
65 LogFactory.getLog(AttachmentPersistenceServiceImpl.class);
66
67 protected static final String ATTACHMENT_PATH_FORMAT = "%1$s/OBJ%2$s/%1$s-OBJ%2$s-%3$s.%4$s";
68
69 @Resource(name = "measurementFileDao")
70 protected MeasurementFileDao measurementFileDao;
71
72 protected File dbAttachmentDirectory;
73
74 @Override
75 public void init() {
76 super.init();
77 dbAttachmentDirectory = config.getDbAttachmentDirectory();
78
79 if (log.isDebugEnabled()) {
80 log.debug("Db Attachment storage: " + dbAttachmentDirectory);
81 }
82 }
83
84
85
86
87
88 @Override
89 public List<Attachment> getAllAttachments(ObjectTypeCode objectType,
90 Integer objectId) {
91 Iterator<Object[]> list = queryList(
92 "allAttachment",
93 "objectId", IntegerType.INSTANCE, objectId,
94 "objectTypeCode", StringType.INSTANCE, objectType.getValue()
95 );
96
97 List<Attachment> result = Lists.newArrayList();
98 while (list.hasNext()) {
99 Object[] source = list.next();
100 Attachment target = Attachments.newAttachment();
101 loadAttachment(source, target);
102 result.add(target);
103 }
104 return Collections.unmodifiableList(result);
105 }
106
107 @Override
108 public File getAttachmentFile(String attachmentId) {
109 Object[] source = queryUnique(
110 "attachment",
111 "attachmentId", IntegerType.INSTANCE, Integer.valueOf(attachmentId));
112
113 if (source == null) {
114 throw new DataRetrievalFailureException(
115 "Could not retrieve Attachment with id=" + attachmentId);
116 }
117 Attachment target = Attachments.newAttachment();
118 loadAttachment(source, target);
119
120 return getFile(target);
121 }
122
123 @Override
124 public Attachment createAttachment(Attachment attachment, File file) {
125 Preconditions.checkNotNull(attachment);
126 Preconditions.checkNotNull(attachment.getObjectType());
127 Preconditions.checkNotNull(attachment.getObjectId());
128 Preconditions.checkArgument(
129 attachment.getId() == null,
130 "Attachment 'id' must be null to call createAttachment().");
131 Preconditions.checkNotNull(file);
132
133
134 MeasurementFile measurementFile = MeasurementFile.Factory.newInstance();
135
136
137 measurementFile.setPmfm(null);
138
139
140 measurementFile.setQualityFlag(load(QualityFlagImpl.class, QualityFlagCode.NOTQUALIFIED.getValue()));
141
142
143 measurementFile.setObjectType(load(ObjectTypeImpl.class, attachment.getObjectType().getValue()));
144
145
146 measurementFile.setObjectId(attachment.getObjectId());
147
148
149 measurementFile.setPath("FAKE-" + System.nanoTime());
150
151
152 attachmentToEntity(attachment, measurementFile);
153 measurementFileDao.create(measurementFile);
154
155
156 attachment.setId(String.valueOf(measurementFile.getId()));
157
158
159 String filePath = String.format(ATTACHMENT_PATH_FORMAT,
160 measurementFile.getObjectType().getCode(),
161 measurementFile.getObjectId(),
162 measurementFile.getId(),
163 ApplicationIOUtil.getExtension(file.getName()));
164
165
166 attachment.setPath(filePath);
167 measurementFile.setPath(filePath);
168
169 if (log.isDebugEnabled()) {
170 log.debug("Created attachment: " + attachment.getId() +
171 ", path: " + filePath);
172 }
173
174
175 measurementFileDao.update(measurementFile);
176
177
178 File targetFile = getFile(attachment);
179
180 ApplicationIOUtil.copyFile(
181 file, targetFile,
182 t("tutti.persistence.attachment.copyFile.error", file, targetFile));
183
184 return attachment;
185 }
186
187 @Override
188 public Attachment saveAttachment(Attachment attachment) {
189 Preconditions.checkNotNull(attachment);
190 Preconditions.checkNotNull(attachment.getObjectType());
191 Preconditions.checkNotNull(attachment.getObjectId());
192 Preconditions.checkNotNull(
193 attachment.getId(),
194 "Attachment 'id' must not be null or empty to be saved.");
195
196 MeasurementFile measurementFile = measurementFileDao.load(Integer.valueOf(attachment.getId()));
197 if (measurementFile == null) {
198 throw new DataRetrievalFailureException("Could not retrieve Attachment with id=" + attachment.getId());
199 }
200
201
202 String oldObjectTypeCode = measurementFile.getObjectType().getCode();
203 if (ObjectUtils.notEqual(attachment.getObjectType().getValue(),
204 oldObjectTypeCode)) {
205 throw new InvalidDataAccessResourceUsageException(
206 "Can't change objectType, was before " + oldObjectTypeCode);
207 }
208
209
210 Integer oldObjectId = measurementFile.getObjectId();
211 if (ObjectUtils.notEqual(attachment.getObjectId(),
212 oldObjectId)) {
213 throw new InvalidDataAccessResourceUsageException(
214 "Can't change objectId, was before " + oldObjectId);
215 }
216
217 attachmentToEntity(attachment, measurementFile);
218 measurementFileDao.update(measurementFile);
219 return attachment;
220 }
221
222 @Override
223 public void deleteAttachment(String attachmentId) {
224 Integer id = Integer.valueOf(attachmentId);
225 Object[] source = queryUnique(
226 "attachment",
227 "attachmentId", IntegerType.INSTANCE, id);
228
229 if (source == null) {
230 throw new DataRetrievalFailureException(
231 "Could not retrieve Attachment with id=" + attachmentId);
232 }
233 Attachment target = Attachments.newAttachment();
234 loadAttachment(source, target);
235
236 delete(target);
237
238 getCurrentSession().flush();
239 }
240
241 @Override
242 public void deleteAllAttachment(ObjectTypeCode objectType, Integer objectId) {
243
244 List<Attachment> attachments = getAllAttachments(objectType, objectId);
245 attachments.forEach(this::delete);
246
247 }
248
249 @Override
250 public void deleteAllAttachment(ObjectTypeCode objectType, Set<Integer> objectIds) {
251
252 for (Integer objectId : objectIds) {
253 List<Attachment> attachments = getAllAttachments(objectType, objectId);
254 attachments.forEach(this::delete);
255 }
256
257 }
258
259
260
261
262
263 protected void loadAttachment(Object[] source,
264 Attachment target) {
265
266 target.setObjectType(ObjectTypeCode.valueOf((String) source[0]));
267 target.setObjectId((Integer) source[1]);
268 target.setId(String.valueOf(source[2]));
269 target.setPath((String) source[3]);
270 target.setName((String) source[4]);
271 target.setComment((String) source[5]);
272 }
273
274 protected void attachmentToEntity(Attachment attachment,
275 MeasurementFile measurementFile) {
276 measurementFile.setName(attachment.getName());
277 measurementFile.setComments(attachment.getComment());
278 }
279
280 protected File getFile(Attachment attachment) {
281 return new File(dbAttachmentDirectory, attachment.getPath());
282 }
283
284 protected void delete(Attachment target) {
285
286 File file = getFile(target);
287
288 if (log.isDebugEnabled()) {
289 log.debug("Will delete attachment: " + target.getName() + " -- " + file);
290 }
291 measurementFileDao.remove(target.getIdAsInt());
292
293 if (file.exists()) {
294 ApplicationIOUtil.deleteFile(file, t("tutti.persistence.attachment.deleteFile.error", file));
295 } else {
296 if (log.isWarnEnabled()) {
297 log.warn("COULD NOT FIND Attachement at " + file);
298 }
299 }
300
301 File parentFile = file.getParentFile();
302 while (!parentFile.equals(dbAttachmentDirectory)) {
303
304 File[] files = parentFile.listFiles();
305 if (files != null && files.length == 0) {
306
307
308 if (log.isDebugEnabled()) {
309 log.debug("Remove empty directory: " + parentFile);
310 }
311 ApplicationIOUtil.deleteDirectory(parentFile, "Could not clean directory");
312 parentFile = parentFile.getParentFile();
313 } else {
314 break;
315 }
316
317 }
318
319 }
320 }