/******************************************************************************* * 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.api.workspace.server.jpa; import com.google.inject.persist.Transactional; import org.eclipse.che.api.core.ApiException; 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.api.core.notification.EventService; import org.eclipse.che.api.workspace.server.event.BeforeStackRemovedEvent; import org.eclipse.che.api.workspace.server.event.StackPersistedEvent; import org.eclipse.che.api.workspace.server.model.impl.ProjectConfigImpl; import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl; import org.eclipse.che.api.workspace.server.spi.StackDao; import org.eclipse.che.commons.annotation.Nullable; 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.TypedQuery; import java.util.List; import java.util.stream.Collectors; import static java.lang.String.format; import static java.util.Objects.requireNonNull; /** * JPA based implementation of {@link StackDao}. * * @author Yevhenii Voevodin */ @Singleton public class JpaStackDao implements StackDao { @Inject private Provider<EntityManager> managerProvider; @Inject private EventService eventService; @Override public void create(StackImpl stack) throws ConflictException, ServerException { requireNonNull(stack, "Required non-null stack"); try { doCreate(stack); } catch (DuplicateKeyException x) { throw new ConflictException(format("Stack with id '%s' or name '%s' already exists", stack.getId(), stack.getName())); } catch (RuntimeException x) { throw new ServerException(x.getLocalizedMessage(), x); } } @Override @Transactional public StackImpl getById(String id) throws NotFoundException, ServerException { requireNonNull(id, "Required non-null id"); try { final StackImpl stack = managerProvider.get().find(StackImpl.class, id); if (stack == null) { throw new NotFoundException(format("Stack with id '%s' doesn't exist", id)); } return new StackImpl(stack); } catch (RuntimeException x) { throw new ServerException(x.getLocalizedMessage(), x); } } @Override public void remove(String id) throws ServerException { requireNonNull(id, "Required non-null id"); try { doRemove(id); } catch (RuntimeException x) { throw new ServerException(x.getLocalizedMessage(), x); } } @Override public StackImpl update(StackImpl update) throws NotFoundException, ServerException, ConflictException { requireNonNull(update, "Required non-null update"); try { return new StackImpl(doUpdate(update)); } catch (DuplicateKeyException x) { throw new ConflictException(format("Stack with name '%s' already exists", update.getName())); } catch (RuntimeException x) { throw new ServerException(x.getLocalizedMessage(), x); } } @Override @Transactional public List<StackImpl> searchStacks(@Nullable String user, @Nullable List<String> tags, int skipCount, int maxItems) throws ServerException { final TypedQuery<StackImpl> query; if (tags == null || tags.isEmpty()) { query = managerProvider.get().createNamedQuery("Stack.getAll", StackImpl.class); } else { query = managerProvider.get() .createNamedQuery("Stack.getByTags", StackImpl.class) .setParameter("tags", tags) .setParameter("tagsSize", tags.size()); } try { return query.setMaxResults(maxItems) .setFirstResult(skipCount) .getResultList() .stream() .map(StackImpl::new) .collect(Collectors.toList()); } catch (RuntimeException x) { throw new ServerException(x.getLocalizedMessage(), x); } } @Transactional(rollbackOn = {RuntimeException.class, ApiException.class}) protected void doCreate(StackImpl stack) throws ConflictException, ServerException { if (stack.getWorkspaceConfig() != null) { stack.getWorkspaceConfig().getProjects().forEach(ProjectConfigImpl::prePersistAttributes); } EntityManager manager = managerProvider.get(); manager.persist(stack); manager.flush(); eventService.publish(new StackPersistedEvent(stack)).propagateException(); } @Transactional(rollbackOn = {RuntimeException.class, ServerException.class}) protected void doRemove(String id) throws ServerException { final EntityManager manager = managerProvider.get(); final StackImpl stack = manager.find(StackImpl.class, id); if (stack != null) { eventService.publish(new BeforeStackRemovedEvent(new StackImpl(stack))).propagateException(); manager.remove(stack); manager.flush(); } } @Transactional protected StackImpl doUpdate(StackImpl update) throws NotFoundException { final EntityManager manager = managerProvider.get(); if (manager.find(StackImpl.class, update.getId()) == null) { throw new NotFoundException(format("Workspace with id '%s' doesn't exist", update.getId())); } if (update.getWorkspaceConfig() != null) { update.getWorkspaceConfig().getProjects().forEach(ProjectConfigImpl::prePersistAttributes); } StackImpl merged = manager.merge(update); manager.flush(); return merged; } }