blob: bb28deb7e4689d68bba2ae906c0cfcc88d26b1ca [file] [log] [blame]
/**
* 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();
}
}
}
}