/******************************************************************************** | |
* 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); | |
}; | |
} |