blob: 6a82f67b26de2f9036297aef55b15eeb1becfffb [file] [log] [blame]
/********************************************************************************
* Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
package org.eclipse.mdm.businessobjects.service;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.function.Consumer;
import org.eclipse.mdm.api.base.Transaction;
import org.eclipse.mdm.api.base.model.Deletable;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.dflt.EntityManager;
import org.eclipse.mdm.businessobjects.control.MDMEntityAccessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.vavr.CheckedFunction2;
import io.vavr.Tuple2;
/**
* Helper class providing functions to realize transactional data operations
*
* @author Alexander Nehmer, science+computing AG Tuebingen (Atos SE)
*
*/
public final class DataAccessHelper {
private static final Logger LOG = LoggerFactory.getLogger(DataAccessHelper.class);
/**
* Just hide the default constructor
*/
private DataAccessHelper() {
}
/**
* Returns a set of entities which where manipulated over different operations
* within one transaction
*
* @param em
* {@link EntityManager} where the operations belong to
* @param operations
* operations which shall be executed within one transaction
* @return a set of manipulated entities
*/
@SuppressWarnings("unchecked")
public static <T extends Entity> Set<T> execute(EntityManager em,
Tuple2<T, CheckedFunction2<Transaction, T, T>>... operations) {
Transaction t = null;
Set<T> processedEntityList = new LinkedHashSet<>();
try {
// start transaction to persist ValueList
t = em.startTransaction();
// perform the transactional operation
for (Tuple2<T, CheckedFunction2<Transaction, T, T>> operation : operations) {
processedEntityList.add((T) operation._2().apply(t, operation._1()));
}
// commit the transaction
t.commit();
// return the set of processed entities
return processedEntityList;
} catch (Throwable e) {
if (t != null) {
t.abort();
}
throw new MDMEntityAccessException(e.getMessage(), e);
}
}
/**
* Function that creates an {@link Entity} and returns it.
*/
public static final CheckedFunction2<Transaction, Entity, Entity> DELETE = (transaction, entity) -> {
if (entity instanceof Deletable) {
transaction.delete(Arrays.asList((Deletable) entity));
}
// if entity cannot be deleted
else {
throw new MDMEntityAccessException("Entity to delete is no Deletable");
}
return entity;
};
/**
* Function that creates the given {@link Entity} and returns the updated
* entity.
*/
public static final CheckedFunction2<Transaction, Entity, Entity> CREATE = (transaction, entity) -> {
transaction.create(Arrays.asList(entity));
return entity;
};
/**
* Function that updates the given {@link Entity} it is executed upon and
* returns the updated entity.
*/
public static final CheckedFunction2<Transaction, Entity, Entity> UPDATE = (transaction, entity) -> {
transaction.update(Arrays.asList(entity));
return entity;
};
/**
* Handles a {@link Throwable} by loggging the exception message and rethrowing
* a {@link MDMEntityAccessException}
*/
// TODO should be replaced in Resources by buildErrorResponse()
public static final Consumer<? super Throwable> rethrowAsMDMEntityAccessException = e -> {
// TODO anehmer on 2017-11-09: check if logging is necessary depending on how we
// handle error logging and client response in general
LOG.error(e.getMessage(), e);
throw new MDMEntityAccessException(e.getMessage(), e);
};
/**
* Function that handles an occurred exception without rethrowing it
*/
// TODO anehmer on 2017-11-22: remove method and logger
public static final Consumer<? super Throwable> handleException = e -> {
LOG.error(e.getMessage(), e);
};
}