1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.opencastproject.assetmanager.impl.persistence;
22
23 import static org.opencastproject.db.Queries.namedQuery;
24
25 import org.opencastproject.assetmanager.api.Availability;
26 import org.opencastproject.assetmanager.api.Property;
27 import org.opencastproject.assetmanager.api.PropertyId;
28 import org.opencastproject.assetmanager.api.Snapshot;
29 import org.opencastproject.assetmanager.impl.PartialMediaPackage;
30 import org.opencastproject.assetmanager.impl.VersionImpl;
31 import org.opencastproject.assetmanager.impl.persistence.AssetDtos.Full;
32 import org.opencastproject.assetmanager.impl.persistence.AssetDtos.Medium;
33 import org.opencastproject.db.DBSession;
34 import org.opencastproject.mediapackage.MediaPackageElement;
35 import org.opencastproject.util.data.Function;
36
37 import com.entwinemedia.fn.data.Opt;
38 import com.mysema.query.Tuple;
39 import com.mysema.query.jpa.EclipseLinkTemplates;
40 import com.mysema.query.jpa.JPQLTemplates;
41 import com.mysema.query.jpa.impl.JPADeleteClause;
42 import com.mysema.query.jpa.impl.JPAQuery;
43 import com.mysema.query.jpa.impl.JPAQueryFactory;
44 import com.mysema.query.jpa.impl.JPAUpdateClause;
45 import com.mysema.query.types.expr.BooleanExpression;
46
47 import org.apache.commons.lang3.StringUtils;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 import java.util.Date;
52 import java.util.List;
53 import java.util.Optional;
54
55 import javax.annotation.ParametersAreNonnullByDefault;
56
57
58
59
60 @ParametersAreNonnullByDefault
61 public class Database implements EntityPaths {
62 private static final Logger logger = LoggerFactory.getLogger(Database.class);
63
64 public static final JPQLTemplates TEMPLATES = EclipseLinkTemplates.DEFAULT;
65
66 private final DBSession db;
67
68 public Database(DBSession db) {
69 this.db = db;
70 }
71
72
73
74
75
76
77 public <A> A run(final Function<JPAQueryFactory, A> q) {
78 return db.execTx(em -> {
79 return q.apply(new JPAQueryFactory(TEMPLATES, () -> em));
80 });
81 }
82
83 public void logQuery(JPAQuery q) {
84 logger.debug("\n---\nQUERY\n{}\n---", q);
85 }
86
87 public void logDelete(String queryName, JPADeleteClause q) {
88 logger.debug("\n---\nDELETE {}\n{}\n---", queryName, q);
89 }
90
91
92
93
94 public boolean saveProperty(final Property property) {
95 return db.execTx(em -> {
96 final PropertyId pId = property.getId();
97
98
99
100 final BooleanExpression eitherMatchOrNull =
101 Q_PROPERTY.namespace.eq(pId.getNamespace())
102 .and(Q_PROPERTY.propertyName.eq(pId.getName())).or(Q_PROPERTY.namespace.isNull());
103 final Tuple result = new JPAQuery(em, TEMPLATES)
104 .from(Q_SNAPSHOT)
105 .leftJoin(Q_PROPERTY).on(Q_SNAPSHOT.mediaPackageId.eq(Q_PROPERTY.mediaPackageId).and(eitherMatchOrNull))
106 .where(Q_SNAPSHOT.mediaPackageId.eq(pId.getMediaPackageId()))
107
108 .singleResult(Q_SNAPSHOT.id, Q_PROPERTY);
109 if (result != null) {
110
111 final PropertyDto exists = result.get(Q_PROPERTY);
112 namedQuery
113 .persistOrUpdate(exists == null
114 ? PropertyDto.mk(property)
115 : exists.update(property.getValue()))
116 .apply(em);
117 return true;
118 } else {
119
120 return false;
121 }
122 });
123 }
124
125
126
127
128 public VersionImpl claimVersion(final String mpId) {
129 return db.execTx(em -> {
130 final Optional<VersionClaimDto> lastOpt = VersionClaimDto.findLastQuery(mpId).apply(em);
131 if (lastOpt.isPresent()) {
132 final VersionImpl claim = VersionImpl.next(lastOpt.get().getLastClaimed());
133 VersionClaimDto.updateQuery(mpId, claim.value()).apply(em);
134 return claim;
135 } else {
136 final VersionImpl first = VersionImpl.FIRST;
137 em.persist(VersionClaimDto.mk(mpId, first.value()));
138 return first;
139 }
140 });
141 }
142
143
144
145
146 public SnapshotDto saveSnapshot(
147 final String orgId,
148 final PartialMediaPackage pmp,
149 final Date archivalDate,
150 final VersionImpl version,
151 final Availability availability,
152 final String storageId,
153 final String owner) {
154 final SnapshotDto snapshotDto = SnapshotDto.mk(
155 pmp.getMediaPackage(),
156 version,
157 orgId,
158 archivalDate,
159 availability,
160 storageId,
161 owner);
162 return db.execTx(em -> {
163
164 em.persist(snapshotDto);
165
166 for (MediaPackageElement e : pmp.getElements()) {
167 final AssetDto a = AssetDto.mk(
168 e.getIdentifier(),
169 snapshotDto,
170 e.getChecksum().toString(),
171 Optional.ofNullable(e.getMimeType()),
172 storageId,
173 e.getSize());
174 em.persist(a);
175 }
176 return snapshotDto;
177 });
178 }
179
180 public void setStorageLocation(Snapshot snapshot, final String storageId) {
181 setStorageLocation(
182 VersionImpl.mk(snapshot.getVersion()),
183 snapshot.getMediaPackage().getIdentifier().toString(),
184 storageId
185 );
186 }
187
188 public void setStorageLocation(final VersionImpl version, final String mpId, final String storageId) {
189 db.execTx(em -> {
190 final QSnapshotDto q = QSnapshotDto.snapshotDto;
191 final QAssetDto a = QAssetDto.assetDto;
192
193 new JPAUpdateClause(em, q, TEMPLATES)
194 .where(q.version.eq(version.value()).and(q.mediaPackageId.eq(mpId)))
195 .set(q.storageId, storageId)
196 .execute();
197
198 Optional<SnapshotDtos.Medium> s = getSnapshot(version, mpId);
199
200 new JPAUpdateClause(em, a, TEMPLATES)
201 .where(a.snapshot.id.eq(s.get().getSnapshotDto().getId()))
202 .set(a.storageId, storageId)
203 .execute();
204 return null;
205 });
206 }
207
208 public void setAssetStorageLocation(final VersionImpl version, final String mpId, final String mpeId,
209 final String storageId) {
210 db.execTx(em -> {
211 final QAssetDto a = QAssetDto.assetDto;
212 Optional<SnapshotDtos.Medium> s = getSnapshot(version, mpId);
213
214 new JPAUpdateClause(em, a, TEMPLATES)
215 .where(a.snapshot.id.eq(s.get().getSnapshotDto().getId()).and(a.mediaPackageElementId.eq(mpeId)))
216 .set(a.storageId, storageId).execute();
217 return null;
218 });
219 }
220
221 public void setAvailability(final VersionImpl version, final String mpId, final Availability availability) {
222 db.execTx(em -> {
223 final QSnapshotDto q = QSnapshotDto.snapshotDto;
224 new JPAUpdateClause(em, q, TEMPLATES)
225 .where(q.version.eq(version.value()).and(q.mediaPackageId.eq(mpId)))
226 .set(q.availability, availability.name())
227 .execute();
228 return null;
229 });
230 }
231
232
233
234
235
236
237 public Optional<AssetDtos.Medium> getAsset(final VersionImpl version, final String mpId, final String mpeId) {
238 return db.execTx(em -> {
239 final QAssetDto assetDto = QAssetDto.assetDto;
240 final Tuple result = AssetDtos.baseJoin(em)
241 .where(assetDto.snapshot.mediaPackageId.eq(mpId)
242 .and(assetDto.mediaPackageElementId.eq(mpeId))
243 .and(assetDto.snapshot.version.eq(version.value())))
244
245 .orderBy(assetDto.snapshot.version.desc())
246 .uniqueResult(Medium.select);
247 var dtoOpt = Opt.nul(result).map(AssetDtos.Medium.fromTuple);
248 return dtoOpt.isSome() ? Optional.of(dtoOpt.get()) : Optional.empty();
249 });
250 }
251
252 public Optional<SnapshotDtos.Medium> getSnapshot(final VersionImpl version, final String mpId) {
253 return db.execTx(em -> {
254 final QSnapshotDto snapshotDto = QSnapshotDto.snapshotDto;
255 final Tuple result = SnapshotDtos.baseQuery(em)
256 .where(snapshotDto.mediaPackageId.eq(mpId)
257 .and(snapshotDto.version.eq(version.value())))
258
259 .orderBy(snapshotDto.version.desc())
260 .uniqueResult(SnapshotDtos.Medium.select);
261 var dtoOpt = Opt.nul(result).map(SnapshotDtos.Medium.fromTuple);
262 return dtoOpt.isSome() ? Optional.of(dtoOpt.get()) : Optional.empty();
263 });
264 }
265
266 public Optional<AssetDtos.Full> findAssetByChecksum(final String checksum) {
267 return db.execTx(em -> {
268 final Tuple result = AssetDtos.baseJoin(em)
269 .where(QAssetDto.assetDto.checksum.eq(checksum))
270 .singleResult(Full.select);
271 var dtoOpt = Opt.nul(result).map(Full.fromTuple);
272 return dtoOpt.isSome() ? Optional.of(dtoOpt.get()) : Optional.empty();
273 });
274 }
275
276
277
278
279
280
281
282
283 public int deleteProperties(final String mediaPackageId) {
284 return db.execTx(PropertyDto.deleteQuery(mediaPackageId));
285 }
286
287
288
289
290
291
292
293
294
295
296 public int deleteProperties(final String mediaPackageId, final String namespace) {
297 if (StringUtils.isBlank(namespace)) {
298 return db.execTx(PropertyDto.deleteQuery(mediaPackageId));
299 }
300 return db.execTx(PropertyDto.deleteQuery(mediaPackageId, namespace));
301 }
302
303
304
305
306
307
308
309
310 public boolean snapshotExists(final String mediaPackageId) {
311 return db.execTx(SnapshotDto.existsQuery(mediaPackageId));
312 }
313
314
315
316
317
318
319
320
321
322
323 public boolean snapshotExists(final String mediaPackageId, final String organization) {
324 return db.exec(SnapshotDto.existsQuery(mediaPackageId, organization));
325 }
326
327
328
329
330
331
332
333
334
335
336 public List<Property> selectProperties(final String mediaPackageId, final String namespace) {
337 return db.exec(PropertyDto.selectQuery(mediaPackageId, namespace));
338 }
339
340
341
342
343
344
345
346
347 public long countEvents(final String organization) {
348 return db.exec(SnapshotDto.countEventsQuery(organization));
349 }
350
351 public Optional<AssetDtos.Full> findAssetByChecksumAndStoreAndOrg(final String checksum, final String storeId,
352 final String orgId) {
353 return db.execTx(em -> {
354 final Tuple result = AssetDtos.baseJoin(em)
355 .where(QAssetDto.assetDto.checksum.eq(checksum)
356 .and(QAssetDto.assetDto.storageId.eq(storeId))
357 .and(QAssetDto.assetDto.snapshot.organizationId.eq(orgId)))
358 .singleResult(Full.select);
359 var dtoOpt = Opt.nul(result).map(Full.fromTuple);
360 return dtoOpt.isSome() ? Optional.of(dtoOpt.get()) : Optional.empty();
361 });
362 }
363
364
365
366
367
368 public static <A> A insidePersistenceContextCheck(A a) {
369 if (a != null) {
370 return a;
371 } else {
372 throw new RuntimeException(
373 "Used DTO outside of a persistence context or the DTO has not been assigned an ID yet.");
374 }
375 }
376 }