/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.account.spi.jpa;
import com.google.inject.persist.Transactional;
import org.eclipse.che.account.spi.AccountDao;
import org.eclipse.che.account.spi.AccountImpl;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.core.db.jpa.DuplicateKeyException;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import java.util.Optional;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
/**
* JPA based implementation of {@link AccountDao}.
*
* @author Sergii Leschenko
*/
@Singleton
public class JpaAccountDao implements AccountDao {
private final Provider<EntityManager> managerProvider;
@Inject
public JpaAccountDao(Provider<EntityManager> managerProvider) {
this.managerProvider = managerProvider;
}
@Override
public void create(AccountImpl account) throws ConflictException, ServerException {
requireNonNull(account, "Required non-null account");
try {
doCreate(account);
} catch (DuplicateKeyException e) {
throw new ConflictException("Account with such id or name already exists");
} catch (RuntimeException e) {
throw new ServerException(e.getLocalizedMessage(), e);
}
}
@Override
public void update(AccountImpl account) throws NotFoundException, ConflictException, ServerException {
requireNonNull(account, "Required non-null account");
try {
doUpdate(account);
} catch (DuplicateKeyException x) {
throw new ConflictException("Account with such name already exists");
} catch (RuntimeException x) {
throw new ServerException(x.getLocalizedMessage(), x);
}
}
@Override
@Transactional
public AccountImpl getById(String id) throws NotFoundException, ServerException {
requireNonNull(id, "Required non-null account id");
final EntityManager manager = managerProvider.get();
try {
AccountImpl account = manager.find(AccountImpl.class, id);
if (account == null) {
throw new NotFoundException(format("Account with id '%s' was not found", id));
}
return account;
} catch (RuntimeException x) {
throw new ServerException(x.getLocalizedMessage(), x);
}
}
@Override
@Transactional
public AccountImpl getByName(String name) throws ServerException, NotFoundException {
requireNonNull(name, "Required non-null account name");
final EntityManager manager = managerProvider.get();
try {
return manager.createNamedQuery("Account.getByName",
AccountImpl.class)
.setParameter("name", name)
.getSingleResult();
} catch (NoResultException e) {
throw new NotFoundException(String.format("Account with name '%s' was not found", name));
} catch (RuntimeException e) {
throw new ServerException(e.getLocalizedMessage(), e);
}
}
@Override
public void remove(String id) throws ServerException {
requireNonNull(id, "Required non-null account id");
try {
doRemove(id);
} catch (RuntimeException e) {
throw new ServerException(e.getLocalizedMessage(), e);
}
}
@Transactional
protected void doCreate(AccountImpl account) {
managerProvider.get().persist(account);
}
@Transactional
protected void doUpdate(AccountImpl update) throws NotFoundException {
final EntityManager manager = managerProvider.get();
final AccountImpl account = manager.find(AccountImpl.class, update.getId());
if (account == null) {
throw new NotFoundException(format("Couldn't update account with id '%s' because it doesn't exist", update.getId()));
}
manager.merge(update);
manager.flush();
}
@Transactional
protected Optional<AccountImpl> doRemove(String id) {
final EntityManager manager = managerProvider.get();
final Optional<AccountImpl> account = Optional.ofNullable(manager.find(AccountImpl.class, id));
account.ifPresent(manager::remove);
return account;
}
}