org.opencastproject.assetmanager.impl.persistence.Database Maven / Gradle / Ivy
/**
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License
* at:
*
* http://opensource.org/licenses/ecl2.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
*/
package org.opencastproject.assetmanager.impl.persistence;
import org.opencastproject.assetmanager.api.Availability;
import org.opencastproject.assetmanager.api.Property;
import org.opencastproject.assetmanager.api.PropertyId;
import org.opencastproject.assetmanager.api.Snapshot;
import org.opencastproject.assetmanager.impl.PartialMediaPackage;
import org.opencastproject.assetmanager.impl.VersionImpl;
import org.opencastproject.assetmanager.impl.persistence.AssetDtos.Full;
import org.opencastproject.assetmanager.impl.persistence.AssetDtos.Medium;
import org.opencastproject.mediapackage.MediaPackageElement;
import org.opencastproject.util.persistencefn.PersistenceEnv;
import org.opencastproject.util.persistencefn.PersistenceEnvs;
import org.opencastproject.util.persistencefn.Queries;
import com.entwinemedia.fn.Fn;
import com.entwinemedia.fn.Fx;
import com.entwinemedia.fn.data.Opt;
import com.mysema.query.Tuple;
import com.mysema.query.jpa.EclipseLinkTemplates;
import com.mysema.query.jpa.JPQLTemplates;
import com.mysema.query.jpa.impl.JPADeleteClause;
import com.mysema.query.jpa.impl.JPAQuery;
import com.mysema.query.jpa.impl.JPAQueryFactory;
import com.mysema.query.jpa.impl.JPAUpdateClause;
import com.mysema.query.types.expr.BooleanExpression;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.List;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.inject.Provider;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
/**
* Data access object.
*/
@ParametersAreNonnullByDefault
public class Database implements EntityPaths {
private static final Logger logger = LoggerFactory.getLogger(Database.class);
public static final JPQLTemplates TEMPLATES = EclipseLinkTemplates.DEFAULT;
private final PersistenceEnv penv;
private final EntityManagerFactory entityManagerFactory;
public Database(EntityManagerFactory emf, PersistenceEnv persistenceEnv) {
penv = persistenceEnv;
entityManagerFactory = emf;
}
public Database(EntityManagerFactory emf) {
penv = PersistenceEnvs.mk(emf);
entityManagerFactory = emf;
}
/**
* Run a Queryldsl query inside a persistence context/transaction.
*
* @param q the query function to run
*/
public A run(final Fn q) {
return penv.tx(new Fn() {
@Override public A apply(final EntityManager em) {
return q.apply(new JPAQueryFactory(TEMPLATES, new Provider() {
@Override public EntityManager get() {
return em;
}
}));
}
});
}
public void logQuery(JPAQuery q) {
logger.debug("\n---\nQUERY\n{}\n---", q);
}
public void logDelete(String queryName, JPADeleteClause q) {
logger.debug("\n---\nDELETE {}\n{}\n---", queryName, q);
}
/**
* Save a property to the database. This is either an insert or an update operation.
*/
public boolean saveProperty(final Property property) {
return penv.tx(new Fn() {
@Override public Boolean apply(EntityManager em) {
final PropertyId pId = property.getId();
// check the existence of both the media package and the property in one query
//
// either the property matches or it does not exist <- left outer join
final BooleanExpression eitherMatchOrNull =
Q_PROPERTY.namespace.eq(pId.getNamespace())
.and(Q_PROPERTY.propertyName.eq(pId.getName())).or(Q_PROPERTY.namespace.isNull());
final Tuple result = new JPAQuery(em, TEMPLATES)
.from(Q_SNAPSHOT)
.leftJoin(Q_PROPERTY).on(Q_SNAPSHOT.mediaPackageId.eq(Q_PROPERTY.mediaPackageId).and(eitherMatchOrNull))
.where(Q_SNAPSHOT.mediaPackageId.eq(pId.getMediaPackageId()))
// only one result is interesting, no need to fetch all versions of the media package
.singleResult(Q_SNAPSHOT.id, Q_PROPERTY);
if (result != null) {
// media package exists, now check if the property exists
final PropertyDto exists = result.get(Q_PROPERTY);
Queries.persistOrUpdate(em, exists == null
? PropertyDto.mk(property)
: exists.update(property.getValue()));
return true;
} else {
// media package does not exist
return false;
}
}
});
}
/**
* Claim a new version for media package mpId
.
*/
public VersionImpl claimVersion(final String mpId) {
return penv.tx(new Fn() {
@Override public VersionImpl apply(final EntityManager em) {
final Opt lastOpt = VersionClaimDto.findLast(em, mpId);
if (lastOpt.isSome()) {
final VersionImpl claim = VersionImpl.next(lastOpt.get().getLastClaimed());
VersionClaimDto.update(em, mpId, claim.value());
return claim;
} else {
final VersionImpl first = VersionImpl.FIRST;
em.persist(VersionClaimDto.mk(mpId, first.value()));
return first;
}
}
});
}
/**
* Save a snapshot and all of its assets.
*/
public SnapshotDto saveSnapshot(
final String orgId,
final PartialMediaPackage pmp,
final Date archivalDate,
final VersionImpl version,
final Availability availability,
final String storageId,
final String owner) {
final SnapshotDto snapshotDto = SnapshotDto.mk(
pmp.getMediaPackage(),
version,
orgId,
archivalDate,
availability,
storageId,
owner);
return penv.tx(new Fn() {
@Override public SnapshotDto apply(EntityManager em) {
// persist snapshot
em.persist(snapshotDto);
// persist assets
for (MediaPackageElement e : pmp.getElements()) {
final AssetDto a = AssetDto.mk(
e.getIdentifier(),
snapshotDto,
e.getChecksum().toString(),
Opt.nul(e.getMimeType()),
storageId,
e.getSize());
em.persist(a);
}
return snapshotDto;
}
});
}
public void setStorageLocation(Snapshot snapshot, final String storageId) {
setStorageLocation(
VersionImpl.mk(snapshot.getVersion()),
snapshot.getMediaPackage().getIdentifier().toString(),
storageId
);
}
public void setStorageLocation(final VersionImpl version, final String mpId, final String storageId) {
penv.tx(new Fx() {
@Override public void apply(EntityManager em) {
final QSnapshotDto q = QSnapshotDto.snapshotDto;
final QAssetDto a = QAssetDto.assetDto;
//Update the snapshot
new JPAUpdateClause(em, q, TEMPLATES)
.where(q.version.eq(version.value()).and(q.mediaPackageId.eq(mpId)))
.set(q.storageId, storageId)
.execute();
//Get the snapshot (to get its database ID)
Opt s = getSnapshot(version, mpId);
//Update the assets
new JPAUpdateClause(em, a, TEMPLATES)
.where(a.snapshot.id.eq(s.get().getSnapshotDto().getId()))
.set(a.storageId, storageId)
.execute();
}
}.toFn());
}
public void setAssetStorageLocation(final VersionImpl version, final String mpId, final String mpeId,
final String storageId) {
penv.tx(new Fx() {
@Override
public void apply(EntityManager em) {
final QAssetDto a = QAssetDto.assetDto;
Opt s = getSnapshot(version, mpId);
// Update the asset store id
new JPAUpdateClause(em, a, TEMPLATES)
.where(a.snapshot.id.eq(s.get().getSnapshotDto().getId()).and(a.mediaPackageElementId.eq(mpeId)))
.set(a.storageId, storageId).execute();
}
}.toFn());
}
public void setAvailability(final VersionImpl version, final String mpId, final Availability availability) {
penv.tx(new Fx() {
@Override public void apply(EntityManager em) {
final QSnapshotDto q = QSnapshotDto.snapshotDto;
new JPAUpdateClause(em, q, TEMPLATES)
.where(q.version.eq(version.value()).and(q.mediaPackageId.eq(mpId)))
.set(q.availability, availability.name())
.execute();
}
}.toFn());
}
/**
* Get an asset. If no version is specified return the latest version.
*
* @return the asset or none, if no asset can be found
*/
public Opt getAsset(final VersionImpl version, final String mpId, final String mpeId) {
return penv.tx(new Fn>() {
@Override public Opt apply(EntityManager em) {
final QAssetDto assetDto = QAssetDto.assetDto;
final Tuple result = AssetDtos.baseJoin(em)
.where(assetDto.snapshot.mediaPackageId.eq(mpId)
.and(assetDto.mediaPackageElementId.eq(mpeId))
.and(assetDto.snapshot.version.eq(version.value())))
// if no version has been specified make sure to get the latest by ordering
.orderBy(assetDto.snapshot.version.desc())
.uniqueResult(Medium.select);
return Opt.nul(result).map(AssetDtos.Medium.fromTuple);
}
});
}
public Opt getSnapshot(final VersionImpl version, final String mpId) {
return penv.tx(new Fn>() {
@Override public Opt apply(EntityManager em) {
final QSnapshotDto snapshotDto = QSnapshotDto.snapshotDto;
final Tuple result = SnapshotDtos.baseQuery(em)
.where(snapshotDto.mediaPackageId.eq(mpId)
.and(snapshotDto.version.eq(version.value())))
// if no version has been specified make sure to get the latest by ordering
.orderBy(snapshotDto.version.desc())
.uniqueResult(SnapshotDtos.Medium.select);
return Opt.nul(result).map(SnapshotDtos.Medium.fromTuple);
}
});
}
public Opt findAssetByChecksum(final String checksum) {
return penv.tx(new Fn>() {
@Override public Opt apply(EntityManager em) {
final Tuple result = AssetDtos.baseJoin(em)
.where(QAssetDto.assetDto.checksum.eq(checksum))
.singleResult(Full.select);
return Opt.nul(result).map(Full.fromTuple);
}
});
}
/**
* Delete all properties for a given media package identifier
*
* @param mediaPackageId
* Media package identifier
* @return Number of deleted rows
*/
public int deleteProperties(final String mediaPackageId) {
return PropertyDto.delete(entityManagerFactory.createEntityManager(), mediaPackageId);
}
/**
* Delete all properties for a given media package identifier and namespace.
*
* @param mediaPackageId
* Media package identifier
* @param namespace
* A namespace prefix to use for deletion
* @return Number of deleted rows
*/
public int deleteProperties(final String mediaPackageId, final String namespace) {
if (StringUtils.isBlank(namespace)) {
return PropertyDto.delete(entityManagerFactory.createEntityManager(), mediaPackageId);
}
return PropertyDto.delete(entityManagerFactory.createEntityManager(), mediaPackageId, namespace);
}
/**
* Check if any snapshot with the given media package identifier exists.
*
* @param mediaPackageId
* The media package identifier to check for
* @return If a snapshot exists for the given media package
*/
public boolean snapshotExists(final String mediaPackageId) {
return SnapshotDto.exists(entityManagerFactory.createEntityManager(), mediaPackageId);
}
/**
* Check if any snapshot with the given media package identifier exists.
*
* @param mediaPackageId
* The media package identifier to check for
* @param organization
* The organization to filter for
* @return If a snapshot exists for the given media package
*/
public boolean snapshotExists(final String mediaPackageId, final String organization) {
return SnapshotDto.exists(entityManagerFactory.createEntityManager(), mediaPackageId, organization);
}
/**
* Select all properties for a specific media package.
*
* @param mediaPackageId
* Media package identifier to check for
* @param namespace
* Namespace to limit the search to
* @return List of properties
*/
public List selectProperties(final String mediaPackageId, final String namespace) {
return PropertyDto.select(entityManagerFactory.createEntityManager(), mediaPackageId, namespace);
}
/**
* Count events with snapshots in the asset manager
*
* @param organization
* An organization to count in
* @return Number of events
*/
public long countEvents(final String organization) {
return SnapshotDto.countEvents(entityManagerFactory.createEntityManager(), organization);
}
public Opt findAssetByChecksumAndStore(final String checksum, final String storeId) {
return penv.tx(new Fn>() {
@Override
public Opt apply(EntityManager em) {
final Tuple result = AssetDtos.baseJoin(em)
.where(QAssetDto.assetDto.checksum.eq(checksum).and(QAssetDto.assetDto.storageId.eq(storeId)))
.singleResult(Full.select);
return Opt.nul(result).map(Full.fromTuple);
}
});
}
//
// Utility
//
public static A insidePersistenceContextCheck(A a) {
if (a != null) {
return a;
} else {
throw new RuntimeException(
"Used DTO outside of a persistence context or the DTO has not been assigned an ID yet.");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy