| /** |
| * Copyright (c) 2011, 2015 - Lunifera GmbH (Gross Enzersdorf, Austria), Loetz GmbH&Co.KG (69115 Heidelberg, Germany) |
| * 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: |
| * Florian Pirchner - Initial implementation |
| */ |
| package org.eclipse.osbp.dsl.dto.lib.services.impl; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import javax.naming.InitialContext; |
| import javax.naming.NamingException; |
| import javax.persistence.EntityManager; |
| import javax.persistence.EntityManagerFactory; |
| import javax.persistence.EntityTransaction; |
| import javax.transaction.HeuristicMixedException; |
| import javax.transaction.HeuristicRollbackException; |
| import javax.transaction.NotSupportedException; |
| import javax.transaction.RollbackException; |
| import javax.transaction.SystemException; |
| import javax.transaction.UserTransaction; |
| |
| import org.eclipse.osbp.dsl.dto.lib.IMapper; |
| import org.eclipse.osbp.dsl.dto.lib.IMapperAccess; |
| import org.eclipse.osbp.dsl.dto.lib.MappingContext; |
| import org.eclipse.osbp.jpa.services.JPQL; |
| import org.eclipse.osbp.jpa.services.Query; |
| import org.eclipse.osbp.jpa.services.metadata.EntityDelegate; |
| import org.eclipse.osbp.runtime.common.annotations.DtoUtils; |
| import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent; |
| import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent.EventDispatcherCommand; |
| import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent.EventDispatcherDataTag; |
| import org.eclipse.osbp.runtime.common.event.IEventDispatcher; |
| import org.eclipse.osbp.runtime.common.filter.DtoServiceException; |
| import org.eclipse.osbp.runtime.common.filter.IFilterEnhancer; |
| import org.eclipse.osbp.runtime.common.filter.IJPQL; |
| import org.eclipse.osbp.runtime.common.filter.IQuery; |
| import org.eclipse.osbp.runtime.common.session.ISessionManager; |
| import org.eclipse.osbp.runtime.common.state.ISharedStateContext; |
| import org.eclipse.osbp.runtime.common.validation.IStatus; |
| import org.eclipse.osbp.runtime.common.validation.IValidationParticipant; |
| import org.eclipse.osbp.runtime.common.validation.ValidationKind; |
| import org.eclipse.persistence.internal.jpa.EntityManagerImpl; |
| import org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork; |
| import org.eclipse.persistence.sessions.SessionEvent; |
| import org.eclipse.persistence.sessions.SessionEventAdapter; |
| import org.eclipse.persistence.sessions.changesets.ObjectChangeSet; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * The Class AbstractDTOService. |
| * |
| * @param <DTO> |
| * the generic type |
| * @param <ENTITY> |
| * the generic type |
| */ |
| @SuppressWarnings("all") |
| public abstract class AbstractDTOService<DTO, ENTITY> |
| implements org.eclipse.osbp.runtime.common.filter.IDTOService<DTO> { |
| |
| private static Logger LOGGER = LoggerFactory.getLogger(AbstractDTOService.class); |
| |
| /** The emf. */ |
| private EntityManagerFactory emf; |
| |
| /** The mapper access. */ |
| protected IMapperAccess mapperAccess; |
| |
| protected ISessionManager sessionManager; |
| |
| /** The validators. */ |
| private HashSet<IValidationParticipant> validators = new HashSet<IValidationParticipant>(); |
| |
| /** The filter enhancers. */ |
| private HashSet<IFilterEnhancer> filterEnhancers = new HashSet<IFilterEnhancer>(); |
| |
| /** |
| * Returns a new instance of JPQL. |
| * |
| * @param lgpl |
| * @param params |
| * @return |
| */ |
| public static JPQL createJPQL(String lgpl, Map<String, Object> params) { |
| return JPQL.create(lgpl, params); |
| } |
| |
| /** |
| * Gets the dto class. |
| * |
| * @return the dto class |
| */ |
| protected abstract Class<DTO> getDtoClass(); |
| |
| /** |
| * Gets the entity class. |
| * |
| * @return the entity class |
| */ |
| protected abstract Class<ENTITY> getEntityClass(); |
| |
| /** |
| * Gets the id. |
| * |
| * @param dto |
| * the dto |
| * @return the id |
| */ |
| public abstract Object getId(DTO dto); |
| |
| /** |
| * Gets the DTO. |
| * |
| * @param id |
| * the id |
| * @return the dto |
| */ |
| public DTO get(final Object id) { |
| // if id is filtered - return null |
| if(!checkGet(getEntityClass(), id)) { |
| return null; |
| } |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, 1); |
| |
| boolean isJTA = isJTA(em); |
| |
| if (isJTA) { |
| |
| } |
| // find the entity |
| DTO result = null; |
| try { |
| ENTITY entity = delegate.getEntity(id); |
| if (entity != null) { |
| IMapper<DTO, ENTITY> mapper = findToDtoMapper(getDtoClass(), (Class<ENTITY>) entity.getClass()); |
| MappingContext mappingContext = createMappingContext(); |
| try { |
| mappingContext.increaseLevel(); |
| result = mapSingle(entity, mapper, mappingContext); |
| mappingContext.decreaseLevel(); |
| mappingContext.flush(); |
| } finally { |
| mappingContext.unmakeCurrent(); |
| } |
| } |
| } finally { |
| em.close(); |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Map single. |
| * |
| * @param entity |
| * the entity |
| * @param mapper |
| * the mapper |
| * @param context |
| * the context |
| * @return the dto |
| */ |
| protected DTO mapSingle(ENTITY entity, IMapper<DTO, ENTITY> mapper, MappingContext context) { |
| DTO result; |
| try { |
| context.increaseLevel(); |
| DTO cached = context.get(mapper.createDtoHash(entity)); |
| if (cached != null) { |
| result = cached; |
| } else { |
| DTO dto = mapper.createDto(); |
| mapper.mapToDTO(dto, entity, context); |
| result = dto; |
| } |
| } finally { |
| context.decreaseLevel(); |
| } |
| return result; |
| } |
| |
| /** |
| * See {@link IMapperAccess#getToDtoMapper(Class, Class)}. |
| * |
| * @param dtoClass |
| * the dto class |
| * @param entityClass |
| * the entity class |
| * @return the i mapper |
| */ |
| protected IMapper<DTO, ENTITY> findToDtoMapper(Class<DTO> dtoClass, Class<ENTITY> entityClass) { |
| return (IMapper<DTO, ENTITY>) mapperAccess.getToDtoMapper(dtoClass, entityClass); |
| } |
| |
| /** |
| * See {@link IMapperAccess#getToEntityMapper(Class, Class)}. |
| * |
| * @param dtoClass |
| * the dto class |
| * @param entityClass |
| * the entity class |
| * @return the i mapper |
| */ |
| protected IMapper<DTO, ENTITY> findToEntityMapper(Class<DTO> dtoClass, Class<ENTITY> entityClass) { |
| return (IMapper<DTO, ENTITY>) mapperAccess.getToEntityMapper(dtoClass, entityClass); |
| } |
| |
| /** |
| * {@inheritDoc}. |
| * |
| * @param query |
| * the query |
| * @return the collection |
| */ |
| public Collection<DTO> find(final IQuery query) { |
| enhanceFilter(query); |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, PROP_MAX_COLLECTION_CONTENT); |
| |
| List<DTO> result = new ArrayList<DTO>(); |
| try { |
| MappingContext mappingContext = createMappingContext(); |
| try { |
| mappingContext.increaseLevel(); |
| for (ENTITY entity : delegate.getAllEntities(query)) { |
| IMapper<DTO, ENTITY> mapper = findToDtoMapper(getDtoClass(), (Class<ENTITY>) entity.getClass()); |
| result.add(mapSingle(entity, mapper, mappingContext)); |
| } |
| mappingContext.decreaseLevel(); |
| mappingContext.flush(); |
| } finally { |
| mappingContext.unmakeCurrent(); |
| } |
| } finally { |
| em.close(); |
| } |
| |
| return result; |
| } |
| |
| /** |
| * {@inheritDoc}. |
| * |
| * @param query |
| * the query |
| * @param startindex |
| * the startindex |
| * @return the collection |
| */ |
| public Collection<DTO> find(final IQuery query, final int startindex) { |
| enhanceFilter(query); |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, PROP_MAX_COLLECTION_CONTENT); |
| |
| List<DTO> result = new ArrayList<DTO>(); |
| try { |
| MappingContext mappingContext = createMappingContext(); |
| try { |
| mappingContext.increaseLevel(); |
| for (ENTITY entity : delegate.getAllEntities(query, startindex)) { |
| IMapper<DTO, ENTITY> mapper = findToDtoMapper(getDtoClass(), (Class<ENTITY>) entity.getClass()); |
| result.add(mapSingle(entity, mapper, mappingContext)); |
| } |
| mappingContext.decreaseLevel(); |
| mappingContext.flush(); |
| } finally { |
| mappingContext.unmakeCurrent(); |
| } |
| } finally { |
| em.close(); |
| } |
| |
| return result; |
| } |
| |
| @Override |
| public Collection<DTO> findDtos(IJPQL jpql) { |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, PROP_MAX_COLLECTION_CONTENT); |
| |
| List<DTO> result = new ArrayList<DTO>(); |
| try { |
| MappingContext mappingContext = createMappingContext(); |
| try { |
| mappingContext.increaseLevel(); |
| for (ENTITY entity : delegate.getAllEntities(jpql)) { |
| IMapper<DTO, ENTITY> mapper = findToDtoMapper(getDtoClass(), (Class<ENTITY>) entity.getClass()); |
| result.add(mapSingle(entity, mapper, mappingContext)); |
| } |
| mappingContext.decreaseLevel(); |
| mappingContext.flush(); |
| } finally { |
| mappingContext.unmakeCurrent(); |
| } |
| } finally { |
| em.close(); |
| } |
| |
| return result; |
| } |
| |
| @Override |
| public List<?> findValues(IJPQL jpql) { |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, PROP_MAX_COLLECTION_CONTENT); |
| try { |
| return delegate.getAllValues(jpql); |
| } finally { |
| em.close(); |
| } |
| } |
| |
| /** |
| * {@inheritDoc}. |
| * |
| * @param dto |
| * the dto |
| */ |
| public void update(final DTO dto) { |
| EntityManager em = emf.createEntityManager(); |
| |
| // create a new transaction |
| Transaction txn = new Transaction(em); |
| |
| TransactionObserver entityTxnObserver = new TransactionObserver(TransactionObserver.UPDATE, em, sessionManager); |
| |
| try { |
| ENTITY entity = null; |
| MappingContext entityMappingContext = new MappingContext(); |
| entityMappingContext.makeCurrent(); |
| entityMappingContext.setEntityManager(em); |
| // do not resolve any dto-lazyloading-list during mapping |
| entityMappingContext.setNoCollectionResolving(true); |
| try { |
| txn.begin(); |
| /* |
| * Map the entity to the dto and merge the entity |
| */ |
| IMapper<DTO, ENTITY> toEntityMapper = findToEntityMapper((Class<DTO>) dto.getClass(), |
| (Class<ENTITY>) getEntityClass()); |
| |
| Object id = getId(dto); |
| if (!(id instanceof Integer) || ((Integer) id).intValue() != 0) { |
| entity = em.find(getEntityClass(), id); |
| if (entity == null) { |
| entity = toEntityMapper.createEntity(); |
| } |
| } else { |
| entity = toEntityMapper.createEntity(); |
| } |
| |
| // map dto to entity and persist |
| toEntityMapper.mapToEntity(dto, entity, entityMappingContext); |
| entity = em.merge(entity); |
| |
| if (entity != null && id instanceof Integer && ((Integer) id).intValue() == 0) { |
| Object newId = new EntityDelegate<ENTITY>(getEntityClass(), em, PROP_MAX_COLLECTION_CONTENT) |
| .getIdentifier(entity); |
| DtoUtils.setIdValue(dto, newId); |
| } |
| |
| } finally { |
| entityMappingContext.unmakeCurrent(); |
| } |
| |
| // no need for now. Everybody who wants refreshed dtos needs to call |
| // |
| // /* |
| // * Map the entity back to the dto since values may have changed in |
| // * entity during merge |
| // */ |
| // MappingContext dtoMappingContext = new MappingContext(); |
| // try { |
| // IMapper<DTO, ENTITY> toDtoMapper = findToDtoMapper( |
| // (Class<DTO>) dto.getClass(), |
| // (Class<ENTITY>) entity.getClass()); |
| // |
| // dtoMappingContext.increaseLevel(); |
| // toDtoMapper.mapToDTO(dto, entity, dtoMappingContext); |
| // } finally { |
| // dtoMappingContext.unmakeCurrent(); |
| // } |
| txn.commit(); |
| txn = null; |
| } catch (NamingException e) { |
| throw new ExceptionConverter().convertException(e); |
| } catch (NotSupportedException e) { |
| throw new ExceptionConverter().convertException(e); |
| } catch (SystemException e) { |
| throw new ExceptionConverter().convertException(e); |
| } catch (IllegalStateException e) { |
| throw new ExceptionConverter().convertException(e); |
| } catch (SecurityException e) { |
| throw new ExceptionConverter().convertException(e); |
| } catch (HeuristicMixedException e) { |
| throw new ExceptionConverter().convertException(e); |
| } catch (HeuristicRollbackException e) { |
| throw new ExceptionConverter().convertException(e); |
| } catch (RollbackException e) { |
| throw new ExceptionConverter().convertException(e); |
| } finally { |
| entityTxnObserver.dispose(); |
| em.close(); |
| } |
| } |
| |
| /** |
| * {@inheritDoc}. |
| * |
| * @param dto |
| * the dto |
| * @return the dto |
| */ |
| public DTO reload(final DTO dto) { |
| Object id = getId(dto); |
| return get(id); |
| } |
| |
| /** |
| * Removes the dto with the given key from the dirty state cache. |
| * |
| * @param dtoKey |
| * the dto key |
| * @param affectedDto |
| * the affected dto |
| * @param sharedState |
| * the shared state |
| */ |
| private void removeFromDirtyState(Object dtoKey, Object affectedDto, ISharedStateContext sharedState) { |
| sharedState.makeUndirty(dtoKey, affectedDto); |
| } |
| |
| /** |
| * Removes the dto with the given key from the dirty state cache. |
| * |
| * @param dtoKey |
| * the dto key |
| * @param affectedDto |
| * the affected dto |
| * @param sharedState |
| * the shared state |
| */ |
| private void removeFromSharedState(Object dtoKey, Object affectedDto, ISharedStateContext sharedState) { |
| // try to dispose the dto. Will remove it from caches automatically. |
| if (!DtoUtils.invokeDisposeMethod(affectedDto)) { |
| sharedState.getDirtyState().invalidate(dtoKey); |
| sharedState.getGlobalDataState().invalidate(dtoKey); |
| } |
| } |
| |
| /** |
| * {@inheritDoc}. |
| * |
| * @param dto |
| * the dto |
| * @throws DtoServiceException |
| * the dto service exception |
| */ |
| public void delete(final DTO dto) throws DtoServiceException { |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| |
| // create a new transaction |
| Transaction txn = new Transaction(em); |
| |
| // create a txn observer to get all deleted elements |
| MappingContext entityMappingContext = createMappingContext(); |
| // do not resolve any dto-lazyloading-list |
| entityMappingContext.setNoCollectionResolving(true); |
| try { |
| entityMappingContext.increaseLevel(); |
| entityMappingContext.setEntityManager(em); |
| |
| TransactionObserver entityTxnObserver = new TransactionObserver(TransactionObserver.DELETE, em, |
| sessionManager); |
| |
| try { |
| txn.begin(); |
| |
| // we need to do a mapping step first to get references from |
| // entity |
| // to DTOs |
| // then we know which dtos must be removed from shared context |
| IMapper<DTO, ENTITY> mapper = findToEntityMapper((Class<DTO>) dto.getClass(), |
| (Class<ENTITY>) getEntityClass()); |
| // map dto to entity and persist |
| ENTITY entity = mapper.createEntity(); |
| mapper.mapToEntity(dto, entity, entityMappingContext); |
| |
| entity = em.find(getEntityClass(), getId(dto)); |
| if (entity != null) { |
| em.remove(entity); |
| } |
| |
| try { |
| txn.commit(); |
| txn = null; |
| } catch (Exception e) { |
| throw new ExceptionConverter().convertException(e); |
| } |
| } catch (NamingException e) { |
| throw new ExceptionConverter().convertException(e); |
| } catch (NotSupportedException e) { |
| throw new ExceptionConverter().convertException(e); |
| } catch (SystemException e) { |
| throw new ExceptionConverter().convertException(e); |
| } finally { |
| entityTxnObserver.dispose(); |
| em.close(); |
| } |
| } finally { |
| entityMappingContext.unmakeCurrent(); |
| } |
| } |
| |
| /** |
| * Binds the service {@link IMapperAccess} to this component. <br> |
| * The cardinality is ONE_TO_ONE |
| * |
| * @param mapperAccess |
| * the mapper access |
| */ |
| protected void bindMapperAccess(final IMapperAccess mapperAccess) { |
| this.mapperAccess = mapperAccess; |
| } |
| |
| /** |
| * Unbinds the service from this component. <br> |
| * The cardinality is ONE_TO_ONE |
| * |
| * @param mapperAccess |
| * the mapper access |
| */ |
| protected void unbindMapperAccess(final IMapperAccess mapperAccess) { |
| this.mapperAccess = null; |
| } |
| |
| /** |
| * Binds the service {@link javax.persistence.EntityManagerFactory} to this |
| * component. <br> |
| * The cardinality is ONE_TO_ONE |
| * |
| * @param emf |
| * the service |
| */ |
| protected void bindEmf(final EntityManagerFactory emf) { |
| this.emf = emf; |
| } |
| |
| /** |
| * Unbinds the service from this component. <br> |
| * The cardinality is ONE_TO_ONE |
| * |
| * @param emf |
| * the service |
| */ |
| protected void unbindEmf(final EntityManagerFactory emf) { |
| this.emf = null; |
| } |
| |
| protected void bindSessionManager(final ISessionManager sessionManager) { |
| this.sessionManager = sessionManager; |
| } |
| |
| protected void unbindSessionManager(final ISessionManager sessionManager) { |
| this.sessionManager = null; |
| } |
| |
| /** |
| * Adds a new validation participant to the service. |
| * |
| * @param validator |
| * the validator |
| */ |
| protected void addValidationParticipant(IValidationParticipant validator) { |
| validators.add(validator); |
| } |
| |
| /** |
| * Removes a validation participant from the service. |
| * |
| * @param validator |
| * the validator |
| */ |
| protected void removeValidationParticipant(IValidationParticipant validator) { |
| validators.remove(validator); |
| } |
| |
| /** |
| * Gets the emf. |
| * |
| * @return the emf |
| */ |
| protected EntityManagerFactory getEmf() { |
| return emf; |
| } |
| |
| /** |
| * Returns true, if JTA is used. |
| * |
| * @param em |
| * the em |
| * @return true, if is jta |
| */ |
| public static boolean isJTA(EntityManager em) { |
| try { |
| em.getTransaction(); |
| } catch (Exception e) { |
| return true; |
| } |
| return false; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.dsl.dto.lib.services.IDTOService#size(org.eclipse.osbp |
| * .dsl.dto.lib.services.IQuery) |
| */ |
| @Override |
| public int size(IQuery query) { |
| enhanceFilter(query); |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, 1); |
| |
| int result = -1; |
| try { |
| result = delegate.getEntityCount(query); |
| } finally { |
| em.close(); |
| } |
| |
| return result; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.dsl.dto.lib.services.IDTOService#contains(java.lang. |
| * Object, org.eclipse.osbp.dsl.dto.lib.services.IQuery) |
| */ |
| @Override |
| public boolean contains(Object dto, IQuery query) { |
| enhanceFilter(query); |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, 1); |
| |
| boolean result = false; |
| try { |
| result = delegate.containsEntityIdentifier(dto, query); |
| } finally { |
| em.close(); |
| } |
| |
| return result; |
| } |
| |
| @Override |
| public boolean contains(IQuery query) { |
| |
| enhanceFilter(query); |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, 1); |
| |
| boolean result = false; |
| try { |
| result = delegate.getEntityCount(query) > 0; |
| } finally { |
| em.close(); |
| } |
| |
| return result; |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.dsl.dto.lib.services.IDTOService#getNext(java.lang. |
| * Object , org.eclipse.osbp.dsl.dto.lib.services.IQuery) |
| */ |
| @Override |
| public DTO getNext(DTO dto, IQuery query) { |
| enhanceFilter(query); |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, 1); |
| |
| DTO result = null; |
| try { |
| ENTITY entity = delegate.getNextEntity(getId(dto), query); |
| if (entity != null) { |
| IMapper<DTO, ENTITY> mapper = findToDtoMapper(getDtoClass(), (Class<ENTITY>) entity.getClass()); |
| MappingContext mappingContext = createMappingContext(); |
| try { |
| mappingContext.increaseLevel(); |
| result = mapSingle(entity, mapper, mappingContext); |
| mappingContext.decreaseLevel(); |
| mappingContext.flush(); |
| } finally { |
| mappingContext.unmakeCurrent(); |
| } |
| } |
| } finally { |
| em.close(); |
| } |
| |
| return result; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.dsl.dto.lib.services.IDTOService#getPrevious(java.lang |
| * .Object, org.eclipse.osbp.dsl.dto.lib.services.IQuery) |
| */ |
| @Override |
| public DTO getPrevious(DTO dto, IQuery query) { |
| enhanceFilter(query); |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, 1); |
| |
| DTO result = null; |
| try { |
| ENTITY entity = delegate.getPreviousEntity(getId(dto), query); |
| if (entity != null) { |
| IMapper<DTO, ENTITY> mapper = findToDtoMapper(getDtoClass(), (Class<ENTITY>) entity.getClass()); |
| MappingContext mappingContext = createMappingContext(); |
| try { |
| mappingContext.increaseLevel(); |
| result = mapSingle(entity, mapper, mappingContext); |
| mappingContext.decreaseLevel(); |
| mappingContext.flush(); |
| } finally { |
| mappingContext.unmakeCurrent(); |
| } |
| } |
| } finally { |
| em.close(); |
| } |
| |
| return result; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.dsl.dto.lib.services.IDTOService#getFirst(org.eclipse |
| * .osbp.dsl.dto.lib.services.IQuery) |
| */ |
| @Override |
| public DTO getFirst(IQuery query) { |
| enhanceFilter(query); |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, 1); |
| |
| DTO result = null; |
| try { |
| ENTITY entity = delegate.getFirstEntity(query); |
| if (entity != null) { |
| IMapper<DTO, ENTITY> mapper = findToDtoMapper(getDtoClass(), (Class<ENTITY>) entity.getClass()); |
| MappingContext mappingContext = createMappingContext(); |
| try { |
| mappingContext.increaseLevel(); |
| result = mapSingle(entity, mapper, mappingContext); |
| mappingContext.decreaseLevel(); |
| mappingContext.flush(); |
| } finally { |
| mappingContext.unmakeCurrent(); |
| } |
| } |
| } finally { |
| em.close(); |
| } |
| |
| return result; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.dsl.dto.lib.services.IDTOService#getLast(org.eclipse |
| * .osbp.dsl.dto.lib.services.IQuery) |
| */ |
| @Override |
| public DTO getLast(IQuery query) { |
| enhanceFilter(query); |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, 1); |
| |
| DTO result = null; |
| try { |
| ENTITY entity = delegate.getLastEntity(query); |
| if (entity != null) { |
| IMapper<DTO, ENTITY> mapper = findToDtoMapper(getDtoClass(), (Class<ENTITY>) entity.getClass()); |
| MappingContext mappingContext = createMappingContext(); |
| try { |
| mappingContext.increaseLevel(); |
| result = mapSingle(entity, mapper, mappingContext); |
| mappingContext.decreaseLevel(); |
| mappingContext.flush(); |
| } finally { |
| mappingContext.unmakeCurrent(); |
| } |
| } |
| } finally { |
| em.close(); |
| } |
| |
| return result; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.dsl.dto.lib.services.IDTOService#isFirst(java.lang. |
| * Object , org.eclipse.osbp.dsl.dto.lib.services.IQuery) |
| */ |
| @Override |
| public boolean isFirst(DTO dto, IQuery query) { |
| enhanceFilter(query); |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, 1); |
| |
| List<DTO> result = new ArrayList<DTO>(); |
| try { |
| String firstId = (String) delegate.getFirstEntityIdentifier(query); |
| if (firstId != null && firstId.equals(getId(dto))) { |
| return true; |
| } |
| } finally { |
| em.close(); |
| } |
| |
| return false; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.dsl.dto.lib.services.IDTOService#isLast(java.lang.Object |
| * , org.eclipse.osbp.dsl.dto.lib.services.IQuery) |
| */ |
| @Override |
| public boolean isLast(DTO dto, IQuery query) { |
| enhanceFilter(query); |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, 1); |
| |
| List<DTO> result = new ArrayList<DTO>(); |
| try { |
| String lastId = (String) delegate.getLastEntityIdentifier(query); |
| if (lastId != null && lastId.equals(getId(dto))) { |
| return true; |
| } |
| } finally { |
| em.close(); |
| } |
| |
| return false; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.dsl.dto.lib.services.IDTOService#indexOf(java.lang. |
| * Object , org.eclipse.osbp.dsl.dto.lib.services.IQuery) |
| */ |
| @Override |
| public int indexOf(DTO dto, IQuery query) { |
| return 1; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.dsl.dto.lib.services.IDTOService#getByIndex(int, |
| * org.eclipse.osbp.dsl.dto.lib.services.IQuery) |
| */ |
| @Override |
| public DTO getByIndex(int index, IQuery query) { |
| enhanceFilter(query); |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, 1); |
| |
| DTO result = null; |
| try { |
| MappingContext mappingContext = createMappingContext(); |
| try { |
| mappingContext.increaseLevel(); |
| for (ENTITY entity : delegate.getAllEntities(query, index)) { |
| IMapper<DTO, ENTITY> mapper = findToDtoMapper(getDtoClass(), (Class<ENTITY>) entity.getClass()); |
| result = mapSingle(entity, mapper, mappingContext); |
| break; |
| } |
| mappingContext.decreaseLevel(); |
| mappingContext.flush(); |
| } finally { |
| mappingContext.unmakeCurrent(); |
| } |
| } finally { |
| em.close(); |
| } |
| |
| return result; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.dsl.dto.lib.services.IDTOService#getByIndex(int, |
| * int, org.eclipse.osbp.dsl.dto.lib.services.IQuery) |
| */ |
| @Override |
| public List<DTO> getByIndex(int startIndex, int numberOfItems, IQuery query) { |
| enhanceFilter(query); |
| javax.persistence.EntityManager em = emf.createEntityManager(); |
| EntityDelegate<ENTITY> delegate = new EntityDelegate<ENTITY>(getEntityClass(), em, numberOfItems); |
| |
| List<DTO> result = new ArrayList<DTO>(); |
| try { |
| MappingContext mappingContext = createMappingContext(); |
| try { |
| mappingContext.increaseLevel(); |
| for (ENTITY entity : delegate.getAllEntities(query, startIndex)) { |
| IMapper<DTO, ENTITY> mapper = findToDtoMapper(getDtoClass(), (Class<ENTITY>) entity.getClass()); |
| result.add(mapSingle(entity, mapper, mappingContext)); |
| } |
| mappingContext.decreaseLevel(); |
| mappingContext.flush(); |
| } finally { |
| mappingContext.unmakeCurrent(); |
| } |
| } finally { |
| em.close(); |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Creates the mapping context. |
| * |
| * @return the mapping context |
| */ |
| protected MappingContext createMappingContext() { |
| if (MappingContext.getCurrent() != null) { |
| MappingContext current = MappingContext.getCurrent(); |
| // call make current to ensure mapping levels |
| current.makeCurrent(); |
| return current; |
| } |
| // call make current is internally done |
| MappingContext current = new MappingContext(); |
| current.makeCurrent(); |
| return current; |
| } |
| |
| /** |
| * Enhance filter. |
| * |
| * @param query |
| * the query |
| */ |
| private void enhanceFilter(IQuery query) { |
| Map<String, Object> queryMap = query.getMap(); |
| List<Class> entityClasses = (List<Class>) queryMap.get(Query.ENTITY_CLASSES_KEY); |
| entityClasses = ((entityClasses != null) ? entityClasses : new ArrayList<Class>()); |
| entityClasses.add(getEntityClass()); |
| queryMap.put(Query.ENTITY_CLASSES_KEY, entityClasses); |
| if (filterEnhancers != null) { |
| for (IFilterEnhancer filterEnhancer : filterEnhancers) { |
| filterEnhancer.enhanceQuery(query); |
| } |
| } |
| } |
| |
| /** |
| * Check if get is possible regarding the filters |
| * |
| * @param entityClass the entity class |
| * @param id the id |
| * @return true, if successful |
| */ |
| private boolean checkGet(Class<ENTITY> entityClass, Object id) { |
| if (filterEnhancers != null) { |
| for (IFilterEnhancer filterEnhancer : filterEnhancers) { |
| if(!filterEnhancer.checkGet(entityClass, id)) { |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.dsl.dto.lib.services.IDTOService#validate(java.lang. |
| * Object, org.eclipse.osbp.runtime.common.validation.ValidationKind, |
| * java.util.Map) |
| */ |
| @Override |
| public Set<IStatus> validate(DTO object, ValidationKind kind, Map<String, Object> properties) { |
| |
| if (validators == null) { |
| return Collections.emptySet(); |
| } |
| |
| Set<IStatus> result = new HashSet<IStatus>(); |
| for (IValidationParticipant val : validators) { |
| Set<IStatus> tempResult = val.validate(object, kind, properties); |
| if (tempResult != null) { |
| result.addAll(tempResult); |
| } |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Adds the filter enhancer |
| * {@link org.eclipse.osbp.runtime.common.filter.IFilterEnhancer} to this |
| * service. <br> |
| * |
| * @param filterEnhancer |
| * the filter enhancer |
| */ |
| protected synchronized void addFilterEnhancer(final IFilterEnhancer filterEnhancer) { |
| filterEnhancers.add(filterEnhancer); |
| } |
| |
| /** |
| * Removes the filter enhancer |
| * {@link org.eclipse.osbp.runtime.common.filter.IFilterEnhancer} from this |
| * service. <br> |
| * |
| * @param filterEnhancer |
| * the filter enhancer |
| */ |
| protected synchronized void removeFilterEnhancer(final IFilterEnhancer filterEnhancer) { |
| filterEnhancers.remove(filterEnhancer); |
| } |
| |
| /** |
| * An asynchronous update interface for receiving notifications about |
| * Transaction information as the Transaction is constructed. |
| */ |
| private static class TransactionObserver extends SessionEventAdapter { |
| |
| /** The Constant UPDATE. */ |
| private static final int UPDATE = 0; |
| |
| /** The Constant DELETE. */ |
| private static final int DELETE = 1; |
| |
| /** The affected. */ |
| private List<Object> affected = new ArrayList<Object>(); |
| |
| /** The em. */ |
| private EntityManager em; |
| |
| /** The type. */ |
| private int type; |
| |
| private final ISessionManager sessionManager; |
| |
| /** |
| * This method is called when information about an Transaction which was |
| * previously requested using an asynchronous interface becomes |
| * available. |
| * |
| * @param type |
| * the type |
| * @param em |
| * the em |
| */ |
| public TransactionObserver(int type, EntityManager em, ISessionManager sessionManager) { |
| this.type = type; |
| this.em = em; |
| this.sessionManager = sessionManager; |
| ((EntityManagerImpl) em).getActiveSession().getEventManager().addListener(this); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.persistence.sessions.SessionEventAdapter# |
| * postCommitUnitOfWork (org.eclipse.persistence.sessions.SessionEvent) |
| */ |
| @Override |
| public void postCommitUnitOfWork(SessionEvent event) { |
| RepeatableWriteUnitOfWork uow = (RepeatableWriteUnitOfWork) event.getSource(); |
| Map<ObjectChangeSet, ObjectChangeSet> changeSet = uow.getUnitOfWorkChangeSet().getAllChangeSets(); |
| processChangeSet(changeSet, EventDispatcherCommand.SAVE); |
| // delete |
| Map<ObjectChangeSet, ObjectChangeSet> deletedSet = uow.getUnitOfWorkChangeSet().getDeletedObjects(); |
| processChangeSet(deletedSet, EventDispatcherCommand.DELETE); |
| } |
| |
| private void processChangeSet(Map<ObjectChangeSet, ObjectChangeSet> changeSet, |
| EventDispatcherCommand eventCmd) { |
| for (ObjectChangeSet object : changeSet.values()) { |
| affected.add(object); |
| // insert or update |
| LOGGER.debug("affected:" + object.getClassName() + " id:" + object.getId()); |
| sessionManager.asyncAll((s) -> { |
| IEventDispatcher dispatcher = s.get(IEventDispatcher.class); |
| if (dispatcher != null) { |
| EventDispatcherEvent evnt; |
| if (object.isNew()) { |
| evnt = new EventDispatcherEvent(EventDispatcherCommand.REFRESH, object.getClassName(), |
| "DTOService"); |
| } else { |
| evnt = new EventDispatcherEvent(eventCmd, object.getClassName(), "DTOService"); |
| } |
| evnt.addItem(EventDispatcherDataTag.ID, object.getId()); |
| dispatcher.sendEvent(evnt); |
| } |
| return null; |
| }); |
| } |
| } |
| |
| /** |
| * This method is called when information about an Transaction which was |
| * previously requested using an asynchronous interface becomes |
| * available. |
| */ |
| public void dispose() { |
| ((EntityManagerImpl) em).getActiveSession().getEventManager().removeListener(this); |
| } |
| } |
| |
| /** |
| * The Class Transaction. |
| */ |
| protected static class Transaction { |
| |
| /** The em. */ |
| private final EntityManager em; |
| |
| /** The is jta. */ |
| private boolean isJTA; |
| |
| /** The ut. */ |
| private UserTransaction ut; |
| |
| /** The txn. */ |
| private EntityTransaction txn; |
| |
| /** |
| * Instantiates a new transaction. |
| * |
| * @param em |
| * the em |
| */ |
| public Transaction(EntityManager em) { |
| super(); |
| this.em = em; |
| |
| isJTA = isJTA(em); |
| } |
| |
| /** |
| * Begin. |
| * |
| * @throws NamingException |
| * the naming exception |
| * @throws NotSupportedException |
| * the not supported exception |
| * @throws SystemException |
| * the system exception |
| */ |
| public void begin() throws NamingException, NotSupportedException, SystemException { |
| if (isJTA) { |
| ut = (UserTransaction) new InitialContext().lookup("osgi:service/javax.transaction.UserTransaction"); |
| |
| // start the user transaction |
| ut.begin(); |
| em.joinTransaction(); |
| } else { |
| txn = em.getTransaction(); |
| txn.begin(); |
| } |
| } |
| |
| /** |
| * Commit. |
| * |
| * @throws IllegalStateException |
| * the illegal state exception |
| * @throws SecurityException |
| * the security exception |
| * @throws HeuristicMixedException |
| * the heuristic mixed exception |
| * @throws HeuristicRollbackException |
| * the heuristic rollback exception |
| * @throws RollbackException |
| * the rollback exception |
| * @throws SystemException |
| * the system exception |
| */ |
| public void commit() throws IllegalStateException, SecurityException, HeuristicMixedException, |
| HeuristicRollbackException, RollbackException, SystemException { |
| if (isJTA) { |
| ut.commit(); |
| } else { |
| txn.commit(); |
| } |
| } |
| |
| /** |
| * Rollback. |
| * |
| * @throws IllegalStateException |
| * the illegal state exception |
| * @throws SecurityException |
| * the security exception |
| * @throws SystemException |
| * the system exception |
| */ |
| public void rollback() throws IllegalStateException, SecurityException, SystemException { |
| if (isJTA) { |
| ut.rollback(); |
| } else { |
| txn.rollback(); |
| } |
| } |
| |
| } |
| } |