PL-7485 Support for identity and composite primary keys

This commit is contained in:
Konstantin Krivopustov 2016-07-06 15:11:02 +04:00
parent 9f1bc3fc00
commit aeca10d4c8
77 changed files with 1543 additions and 438 deletions

View File

@ -23,7 +23,6 @@ import com.haulmont.chile.core.model.MetaProperty;
import com.haulmont.chile.core.model.MetaPropertyPath;
import com.haulmont.chile.core.model.Range;
import com.haulmont.chile.core.model.utils.InstanceUtils;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.EmbeddableEntity;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.EntitySnapshot;
@ -33,8 +32,8 @@ import com.haulmont.cuba.core.sys.ViewHelper;
import org.apache.commons.lang.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.Nullable;
import javax.inject.Inject;
import java.util.*;
@ -102,8 +101,8 @@ public class EntityDiffManager {
result.setAfterSnapshot(second);
if (!diffView.getProperties().isEmpty()) {
BaseEntity firstEntity = first != null ? snapshotAPI.extractEntity(first) : null;
BaseEntity secondEntity = snapshotAPI.extractEntity(second);
Entity firstEntity = first != null ? snapshotAPI.extractEntity(first) : null;
Entity secondEntity = snapshotAPI.extractEntity(second);
result.setBeforeEntity(firstEntity);
result.setAfterEntity(secondEntity);

View File

@ -18,7 +18,7 @@
package com.haulmont.cuba.core.app;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.EntitySnapshot;
import com.haulmont.cuba.core.entity.diff.EntityDiff;
import com.haulmont.cuba.core.global.View;
@ -63,7 +63,7 @@ public interface EntitySnapshotAPI {
* @param view View
* @return Snapshot
*/
EntitySnapshot createSnapshot(BaseEntity entity, View view);
EntitySnapshot createSnapshot(Entity entity, View view);
/**
* Create snapshot for Entity with specific date and store it to database
@ -73,7 +73,7 @@ public interface EntitySnapshotAPI {
* @param snapshotDate Date
* @return Snapshot
*/
EntitySnapshot createSnapshot(BaseEntity entity, View view, Date snapshotDate);
EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate);
/**
* Create snapshot for Entity with specific date and author and store it to database
@ -84,7 +84,7 @@ public interface EntitySnapshotAPI {
* @param author Author
* @return Snapshot
*/
EntitySnapshot createSnapshot(BaseEntity entity, View view, Date snapshotDate, User author);
EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate, User author);
/**
* Restore entity by snapshot
@ -92,7 +92,7 @@ public interface EntitySnapshotAPI {
* @param snapshot Snapshot
* @return Entity instance
*/
BaseEntity extractEntity(EntitySnapshot snapshot);
Entity extractEntity(EntitySnapshot snapshot);
/**
* Restore view from snapshot

View File

@ -20,9 +20,10 @@ package com.haulmont.cuba.core.app;
import com.haulmont.bali.util.Preconditions;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.cuba.core.*;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.BaseUuidEntity;
import com.haulmont.cuba.core.entity.EntitySnapshot;
import com.haulmont.cuba.core.entity.HasUuid;
import com.haulmont.cuba.core.entity.diff.EntityDiff;
import com.haulmont.cuba.core.global.*;
import com.haulmont.cuba.security.entity.User;
@ -193,18 +194,21 @@ public class EntitySnapshotManager implements EntitySnapshotAPI {
}
@Override
public EntitySnapshot createSnapshot(BaseEntity entity, View view) {
public EntitySnapshot createSnapshot(Entity entity, View view) {
return createSnapshot(entity, view, timeSource.currentTimestamp());
}
@Override
public EntitySnapshot createSnapshot(BaseEntity entity, View view, Date snapshotDate) {
public EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate) {
User user = userSessionSource.getUserSession().getUser();
return createSnapshot(entity, view, snapshotDate, user);
}
@Override
public EntitySnapshot createSnapshot(BaseEntity entity, View view, Date snapshotDate, User author) {
public EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate, User author) {
if (!(entity instanceof HasUuid))
throw new UnsupportedOperationException("Entity " + entity + " has no persistent UUID attribute");
Preconditions.checkNotNullArgument(entity);
Preconditions.checkNotNullArgument(view);
Preconditions.checkNotNullArgument(snapshotDate);
@ -217,7 +221,7 @@ public class EntitySnapshotManager implements EntitySnapshotAPI {
}
EntitySnapshot snapshot = metadata.create(EntitySnapshot.class);
snapshot.setEntityId(entity.getUuid());
snapshot.setEntityId(((HasUuid) entity).getUuid());
MetaClass metaClass = getOriginalOrCurrentMetaClass(entity.getClass());
@ -242,7 +246,7 @@ public class EntitySnapshotManager implements EntitySnapshotAPI {
}
@Override
public BaseEntity extractEntity(EntitySnapshot snapshot) {
public Entity extractEntity(EntitySnapshot snapshot) {
String xml = snapshot.getSnapshotXml();
return (BaseUuidEntity) fromXML(xml);
}

View File

@ -18,7 +18,7 @@
package com.haulmont.cuba.core.app;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.EntitySnapshot;
import com.haulmont.cuba.core.entity.diff.EntityDiff;
import com.haulmont.cuba.core.global.View;
@ -44,22 +44,22 @@ public class EntitySnapshotServiceBean implements EntitySnapshotService {
}
@Override
public EntitySnapshot createSnapshot(BaseEntity entity, View view) {
public EntitySnapshot createSnapshot(Entity entity, View view) {
return snapshotAPI.createSnapshot(entity, view);
}
@Override
public EntitySnapshot createSnapshot(BaseEntity entity, View view, Date snapshotDate) {
public EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate) {
return snapshotAPI.createSnapshot(entity, view, snapshotDate);
}
@Override
public EntitySnapshot createSnapshot(BaseEntity entity, View view, Date snapshotDate, User author) {
public EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate, User author) {
return snapshotAPI.createSnapshot(entity, view, snapshotDate, author);
}
@Override
public BaseEntity extractEntity(EntitySnapshot snapshot) {
public Entity extractEntity(EntitySnapshot snapshot) {
return snapshotAPI.extractEntity(snapshot);
}

View File

@ -16,7 +16,7 @@
*/
package com.haulmont.cuba.core.app;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.FtsChangeType;
import java.util.UUID;
@ -30,7 +30,7 @@ public interface FtsSender {
String NAME = "cuba_FtsSender";
void enqueue(BaseEntity<UUID> entity, FtsChangeType changeType);
void enqueue(Entity<UUID> entity, FtsChangeType changeType);
void enqueue(String entityName, UUID entityId, FtsChangeType changeType);

View File

@ -43,6 +43,7 @@ import javax.inject.Inject;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
@Component(DynamicAttributesManagerAPI.NAME)
public class DynamicAttributesManager implements DynamicAttributesManagerAPI {
@ -184,6 +185,8 @@ public class DynamicAttributesManager implements DynamicAttributesManagerAPI {
@Override
public void storeDynamicAttributes(BaseGenericIdEntity entity) {
if (!(entity instanceof HasUuid))
return;
if (persistence.isInTransaction()) {
doStoreDynamicAttributes(entity);
} else {
@ -199,12 +202,15 @@ public class DynamicAttributesManager implements DynamicAttributesManagerAPI {
@Override
public <E extends BaseGenericIdEntity> void fetchDynamicAttributes(List<E> entities) {
List<E> supportedEntities = entities.stream().filter(e -> e instanceof HasUuid).collect(Collectors.toList());
if (supportedEntities.isEmpty())
return;
if (persistence.isInTransaction()) {
doFetchDynamicAttributes(entities);
doFetchDynamicAttributes(supportedEntities);
} else {
Transaction tx = persistence.createTransaction();
try {
doFetchDynamicAttributes(entities);
doFetchDynamicAttributes(supportedEntities);
tx.commit();
} finally {
tx.end();
@ -247,7 +253,7 @@ public class DynamicAttributesManager implements DynamicAttributesManagerAPI {
@Nullable
@Override
public UUID apply(@Nullable Entity input) {
return input != null ? input.getUuid() : null;
return input != null ? ((HasUuid) input).getUuid() : null;
}
});
@ -264,7 +270,7 @@ public class DynamicAttributesManager implements DynamicAttributesManagerAPI {
handleAttributeValuesForIds(currentIds, attributeValuesForEntity);
for (BaseGenericIdEntity entity : entities) {
Collection<CategoryAttributeValue> theEntityAttributeValues = attributeValuesForEntity.get(entity.getUuid());
Collection<CategoryAttributeValue> theEntityAttributeValues = attributeValuesForEntity.get(((HasUuid) entity).getUuid());
Map<String, CategoryAttributeValue> map = new HashMap<>();
entity.setDynamicAttributes(map);
if (CollectionUtils.isNotEmpty(theEntityAttributeValues)) {

View File

@ -16,7 +16,7 @@
*/
package com.haulmont.cuba.core.listener;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
/**
* Defines the contract for handling of entities after they have been deleted or
@ -24,7 +24,7 @@ import com.haulmont.cuba.core.entity.BaseEntity;
* Any updates through the EntityManager are impossible!
*
*/
public interface AfterDeleteEntityListener<T extends BaseEntity> {
public interface AfterDeleteEntityListener<T extends Entity> {
/**
* Executes after the object has been deleted or marked as deleted in DB.

View File

@ -16,14 +16,14 @@
*/
package com.haulmont.cuba.core.listener;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
/**
* Defines the contract for handling entities after they have been inserted into DB.<br>
* Any updates through the EntityManager are impossible!
*
*/
public interface AfterInsertEntityListener<T extends BaseEntity> {
public interface AfterInsertEntityListener<T extends Entity> {
/**
* Executes after the object has been inserted into DB.

View File

@ -16,14 +16,14 @@
*/
package com.haulmont.cuba.core.listener;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
/**
* Defines the contract for handling of entities after they have been updated in DB.<br>
* Any updates through the EntityManager are impossible!
*
*/
public interface AfterUpdateEntityListener<T extends BaseEntity> {
public interface AfterUpdateEntityListener<T extends Entity> {
/**
* Executes after the object has been updated in DB.

View File

@ -16,13 +16,13 @@
*/
package com.haulmont.cuba.core.listener;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
/**
* Defines the contract for handling entities right before they are attached to an EntityManager on merge operation.
*
*/
public interface BeforeAttachEntityListener<T extends BaseEntity> {
public interface BeforeAttachEntityListener<T extends Entity> {
/**
* Executes before the object is attached to an EntityManager on merge operation.

View File

@ -16,14 +16,14 @@
*/
package com.haulmont.cuba.core.listener;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
/**
* Defines the contract for handling of entities before they have been deleted or
* marked as deleted in DB.
*
*/
public interface BeforeDeleteEntityListener<T extends BaseEntity> {
public interface BeforeDeleteEntityListener<T extends Entity> {
/**
* Executes before the object has been deleted or marked as deleted in DB.

View File

@ -17,14 +17,14 @@
package com.haulmont.cuba.core.listener;
import com.haulmont.cuba.core.EntityManager;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
/**
* Defines the contract for handling entities right before they are detached from an EntityManager
* on transaction commit.
*
*/
public interface BeforeDetachEntityListener<T extends BaseEntity> {
public interface BeforeDetachEntityListener<T extends Entity> {
/**
* Executes before the object is detached from an EntityManager on transaction commit.

View File

@ -16,13 +16,13 @@
*/
package com.haulmont.cuba.core.listener;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
/**
* Defines the contract for handling entities before they have been inserted into DB.
*
*/
public interface BeforeInsertEntityListener<T extends BaseEntity> {
public interface BeforeInsertEntityListener<T extends Entity> {
/**
* Executes before the object has been inserted into DB.

View File

@ -16,13 +16,13 @@
*/
package com.haulmont.cuba.core.listener;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
/**
* Defines the contract for handling of entities before they have been updated in DB.
*
*/
public interface BeforeUpdateEntityListener<T extends BaseEntity> {
public interface BeforeUpdateEntityListener<T extends Entity> {
/**
* Executes before the object has been updated in DB.

View File

@ -35,9 +35,7 @@ import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import javax.persistence.EntityNotFoundException;
import java.sql.Connection;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.*;
public class EntityManagerImpl implements EntityManager {
@ -89,11 +87,9 @@ public class EntityManagerImpl implements EntityManager {
if (PersistenceHelper.isManaged(entity))
return entity;
if (entity instanceof BaseEntity) {
entityListenerMgr.fireListener((BaseEntity) entity, EntityListenerType.BEFORE_ATTACH);
}
entityListenerMgr.fireListener(entity, EntityListenerType.BEFORE_ATTACH);
if (PersistenceHelper.isNew(entity)) {
if (PersistenceHelper.isNew(entity) && entity.getId() != null) {
// if a new instance is passed to merge(), we suppose it is persistent but "not detached"
Entity destEntity = findOrCreate(entity.getClass(), entity.getId());
deepCopyIgnoringNulls(entity, destEntity);
@ -149,11 +145,12 @@ public class EntityManagerImpl implements EntityManager {
Preconditions.checkNotNullArgument(entityClass, "entityClass is null");
Preconditions.checkNotNullArgument(id, "id is null");
log.debug("find {} by id={}", entityClass.getSimpleName(), id);
Object realId = getRealId(id);
log.debug("find {} by id={}", entityClass.getSimpleName(), realId);
MetaClass metaClass = metadata.getExtendedEntities().getEffectiveMetaClass(entityClass);
Class<T> javaClass = metaClass.getJavaClass();
return delegate.find(javaClass, id);
return delegate.find(javaClass, realId);
}
@Nullable
@ -176,11 +173,12 @@ public class EntityManagerImpl implements EntityManager {
return find(entityClass, id, viewArray);
}
private <T extends Entity> T findWithViews(MetaClass metaClass, Object key, List<View> views) {
log.debug("find {} by id={}, views={}", metaClass.getJavaClass().getSimpleName(), key, views);
private <T extends Entity> T findWithViews(MetaClass metaClass, Object id, List<View> views) {
Object realId = getRealId(id);
log.debug("find {} by id={}, views={}", metaClass.getJavaClass().getSimpleName(), realId, views);
Query query = createQuery("select e from " + metaClass.getName() + " e where e.id = ?1");
((QueryImpl) query).setSingleResultExpected(true);
query.setParameter(1, key);
query.setParameter(1, realId);
for (View view : views) {
query.addView(view);
}
@ -192,7 +190,7 @@ public class EntityManagerImpl implements EntityManager {
public <T extends Entity<K>, K> T getReference(Class<T> clazz, K id) {
Class<T> effectiveClass = metadata.getExtendedEntities().getEffectiveClass(clazz);
T reference = delegate.getReference(effectiveClass, id);
T reference = delegate.getReference(effectiveClass, getRealId(id));
BaseEntityInternalAccess.setNew((BaseGenericIdEntity) reference, false);
return reference;
}
@ -369,7 +367,20 @@ public class EntityManagerImpl implements EntityManager {
protected <T extends Entity> T internalMerge(T entity) {
try {
disableSoftDelete(true);
return delegate.merge(entity);
UUID uuid = null;
if (entity.getId() instanceof IdProxy) {
uuid = ((IdProxy) entity.getId()).getUuid();
}
T merged = delegate.merge(entity);
if (entity.getId() instanceof IdProxy
&& uuid != null
&& !uuid.equals(((IdProxy) merged.getId()).getUuid())) {
((IdProxy) merged.getId()).setUuid(uuid);
}
return merged;
} finally {
disableSoftDelete(!softDeletion);
}
@ -378,4 +389,8 @@ public class EntityManagerImpl implements EntityManager {
protected void disableSoftDelete(boolean disable) {
delegate.setProperty("cuba.disableSoftDelete", disable);
}
private Object getRealId(Object id) {
return id instanceof IdProxy ? ((IdProxy) id).getNN() : id;
}
}

View File

@ -21,7 +21,6 @@ import com.haulmont.bali.util.Preconditions;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.chile.core.model.MetaProperty;
import com.haulmont.chile.core.model.MetaPropertyPath;
import com.haulmont.chile.core.model.Range;
import com.haulmont.cuba.core.entity.*;
import com.haulmont.cuba.core.global.*;
import org.apache.commons.lang.StringUtils;
@ -299,7 +298,10 @@ public class FetchGroupManager {
// Always add uuid property if the entity has primary key not of type UUID
if (!BaseUuidEntity.class.isAssignableFrom(entityClass)
&& !EmbeddableEntity.class.isAssignableFrom(entityClass)) {
fetchGroupFields.add(createFetchGroupField(entityClass, parentField, "uuid"));
MetaProperty uuidProp = metadata.getClassNN(entityClass).getProperty("uuid");
if (uuidProp != null && metadataTools.isPersistent(uuidProp)) {
fetchGroupFields.add(createFetchGroupField(entityClass, parentField, "uuid"));
}
}
}
@ -331,25 +333,6 @@ public class FetchGroupManager {
}
}
private void includeSystemProperties(View view, FetchGroupField parentField, Set<FetchGroupField> fetchGroupFields) {
Class<? extends Entity> entityClass = view.getEntityClass();
MetaClass metaClass = metadata.getClassNN(entityClass);
if (BaseEntity.class.isAssignableFrom(entityClass)) {
for (String property : getInterfaceProperties(BaseEntity.class)) {
if (metadataTools.isPersistent(metaClass.getPropertyNN(property))) {
fetchGroupFields.add(createFetchGroupField(entityClass, parentField, property));
}
}
}
if (Updatable.class.isAssignableFrom(entityClass)) {
for (String property : getInterfaceProperties(Updatable.class)) {
if (metadataTools.isPersistent(metaClass.getPropertyNN(property))) {
fetchGroupFields.add(createFetchGroupField(entityClass, parentField, property));
}
}
}
}
private List<String> getInterfaceProperties(Class<?> intf) {
List<String> result = new ArrayList<>();
for (Method method : intf.getDeclaredMethods()) {

View File

@ -27,6 +27,7 @@ import com.haulmont.cuba.core.Query;
import com.haulmont.cuba.core.entity.BaseEntityInternalAccess;
import com.haulmont.cuba.core.entity.BaseGenericIdEntity;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.HasUuid;
import com.haulmont.cuba.core.global.*;
import com.haulmont.cuba.core.sys.jpql.JpqlSyntaxException;
import com.haulmont.cuba.security.entity.ConstraintOperationType;
@ -40,6 +41,7 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
import static java.lang.String.format;
@ -116,11 +118,14 @@ public class PersistenceSecurityImpl extends SecurityImpl implements Persistence
@Override
public void applyConstraints(Collection<Entity> entities) {
internalApplyConstraints(entities, new HashSet<>());
List<Entity> supportedEntities = entities.stream().filter(e -> e instanceof HasUuid).collect(Collectors.toList());
internalApplyConstraints(supportedEntities, new HashSet<>());
}
@Override
public boolean applyConstraints(Entity entity) {
if (!(entity instanceof HasUuid))
return false;
return internalApplyConstraints(entity, new HashSet<>());
}
@ -206,7 +211,7 @@ public class PersistenceSecurityImpl extends SecurityImpl implements Persistence
for (Iterator<Entity> iterator = entities.iterator(); iterator.hasNext(); ) {
Entity next = iterator.next();
if (internalApplyConstraints(next, handled)) {
filtered.add(next.getUuid());
filtered.add(((HasUuid) next).getUuid());
//we ignore situations when the collection is immutable
iterator.remove();
}
@ -226,8 +231,8 @@ public class PersistenceSecurityImpl extends SecurityImpl implements Persistence
return true;
}
if (handled.contains(entity.getUuid())) return false;
handled.add(entity.getUuid());
if (handled.contains(((HasUuid) entity).getUuid())) return false;
handled.add(((HasUuid) entity).getUuid());
for (MetaProperty property : metaClass.getProperties()) {
if (metadataTools.isPersistent(property) && PersistenceHelper.isLoaded(entity, property.getName())) {
@ -237,13 +242,13 @@ public class PersistenceSecurityImpl extends SecurityImpl implements Persistence
if (entity instanceof BaseGenericIdEntity) {
securityTokenManager.addFiltered((BaseGenericIdEntity) entity, property.getName(), filtered);
}
} else if (value instanceof Entity) {
} else if (value instanceof Entity && value instanceof HasUuid) {
Entity valueEntity = (Entity) value;
if (internalApplyConstraints(valueEntity, handled)) {
//we ignore the situation when the field is read-only
entity.setValue(property.getName(), null);
if (entity instanceof BaseGenericIdEntity) {
securityTokenManager.addFiltered((BaseGenericIdEntity) entity, property.getName(), valueEntity.getUuid());
securityTokenManager.addFiltered((BaseGenericIdEntity) entity, property.getName(), ((HasUuid) valueEntity).getUuid());
}
}
}

View File

@ -21,6 +21,7 @@ import com.haulmont.chile.core.datatypes.impl.EnumClass;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.cuba.core.TypedQuery;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.IdProxy;
import com.haulmont.cuba.core.global.*;
import com.haulmont.cuba.core.sys.persistence.DbmsFeatures;
import com.haulmont.cuba.core.sys.persistence.DbmsSpecificFactory;
@ -345,7 +346,9 @@ public class QueryImpl<T> implements TypedQuery<T> {
public TypedQuery<T> setParameter(String name, Object value, boolean implicitConversions) {
checkState();
if (implicitConversions) {
if (value instanceof IdProxy) {
value = ((IdProxy) value).getNN();
} else if (implicitConversions) {
value = handleImplicitConversions(value);
}
params.add(new Param(name, value));
@ -390,6 +393,8 @@ public class QueryImpl<T> implements TypedQuery<T> {
} catch (NoSuchMethodException e) {
throw new RuntimeException("Error setting parameter value", e);
}
} else if (value instanceof IdProxy) {
value = ((IdProxy) value).getNN();
} else if (implicitConversions) {
value = handleImplicitConversions(value);
}

View File

@ -17,7 +17,7 @@
package com.haulmont.cuba.core.sys.listener;
import com.haulmont.cuba.core.Persistence;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.annotation.Listeners;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.listener.*;
@ -84,7 +84,7 @@ public class EntityListenerManager {
protected Map<Key, List> cache = new ConcurrentHashMap<>();
protected Map<Class<? extends BaseEntity>, Set<String>> dynamicListeners = new ConcurrentHashMap<>();
protected Map<Class<? extends Entity>, Set<String>> dynamicListeners = new ConcurrentHashMap<>();
protected ReadWriteLock lock = new ReentrantReadWriteLock();
@ -96,7 +96,7 @@ public class EntityListenerManager {
* @param entityClass entity
* @param listenerClass listener class
*/
public void addListener(Class<? extends BaseEntity> entityClass, Class<?> listenerClass) {
public void addListener(Class<? extends Entity> entityClass, Class<?> listenerClass) {
lock.writeLock().lock();
try {
Set<String> set = dynamicListeners.get(entityClass);
@ -118,7 +118,7 @@ public class EntityListenerManager {
* @param entityClass entity
* @param listenerClass listener class
*/
public void removeListener(Class<? extends BaseEntity> entityClass, Class<?> listenerClass) {
public void removeListener(Class<? extends Entity> entityClass, Class<?> listenerClass) {
lock.writeLock().lock();
try {
Set<String> set = dynamicListeners.get(entityClass);
@ -138,7 +138,7 @@ public class EntityListenerManager {
* @param entityClass entity
* @param listenerBeanName listener bean name
*/
public void addListener(Class<? extends BaseEntity> entityClass, String listenerBeanName) {
public void addListener(Class<? extends Entity> entityClass, String listenerBeanName) {
lock.writeLock().lock();
try {
Set<String> set = dynamicListeners.get(entityClass);
@ -160,7 +160,7 @@ public class EntityListenerManager {
* @param entityClass entity
* @param listenerBeanName listener bean name
*/
public void removeListener(Class<? extends BaseEntity> entityClass, String listenerBeanName) {
public void removeListener(Class<? extends Entity> entityClass, String listenerBeanName) {
lock.writeLock().lock();
try {
Set<String> set = dynamicListeners.get(entityClass);
@ -175,7 +175,7 @@ public class EntityListenerManager {
}
@SuppressWarnings("unchecked")
public void fireListener(BaseEntity entity, EntityListenerType type) {
public void fireListener(Entity entity, EntityListenerType type) {
if (!enabled)
return;
@ -238,7 +238,7 @@ public class EntityListenerManager {
this.enabled = enable;
}
protected void logExecution(EntityListenerType type, BaseEntity entity) {
protected void logExecution(EntityListenerType type, Entity entity) {
if (log.isDebugEnabled()) {
StringBuilder sb = new StringBuilder();
sb.append("Executing ").append(type).append(" entity listener for ")
@ -259,7 +259,7 @@ public class EntityListenerManager {
}
}
protected List<?> getListener(Class<? extends BaseEntity> entityClass, EntityListenerType type) {
protected List<?> getListener(Class<? extends Entity> entityClass, EntityListenerType type) {
Key key = new Key(entityClass, type);
lock.readLock().lock();
@ -276,7 +276,7 @@ public class EntityListenerManager {
}
}
protected List<?> findListener(Class<? extends BaseEntity> entityClass, EntityListenerType type) {
protected List<?> findListener(Class<? extends Entity> entityClass, EntityListenerType type) {
log.trace("get listener " + type + " for class " + entityClass.getName());
List<String> names = getDeclaredListeners(entityClass);
if (names.isEmpty()) {
@ -318,7 +318,7 @@ public class EntityListenerManager {
return result;
}
protected List<String> getDeclaredListeners(Class<? extends BaseEntity> entityClass) {
protected List<String> getDeclaredListeners(Class<? extends Entity> entityClass) {
List<String> listeners = new ArrayList<>();
List<Class> superclasses = ClassUtils.getAllSuperclasses(entityClass);

View File

@ -22,7 +22,6 @@ import com.haulmont.chile.core.model.MetaProperty;
import com.haulmont.cuba.core.EntityManager;
import com.haulmont.cuba.core.Persistence;
import com.haulmont.cuba.core.Query;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.SoftDelete;
import com.haulmont.cuba.core.entity.annotation.OnDelete;
@ -46,7 +45,7 @@ public class DeletePolicyProcessor {
protected Logger log = LoggerFactory.getLogger(getClass());
protected BaseEntity entity;
protected Entity entity;
protected MetaClass metaClass;
protected Persistence persistence;
@ -62,11 +61,11 @@ public class DeletePolicyProcessor {
this.entityManager = persistence.getEntityManager();
}
public BaseEntity getEntity() {
public Entity getEntity() {
return entity;
}
public void setEntity(BaseEntity entity) {
public void setEntity(Entity entity) {
this.entity = entity;
this.metaClass = metadata.getSession().getClass(entity.getClass());
primaryKeyName = metadata.getTools().getPrimaryKeyName(metaClass);
@ -153,7 +152,7 @@ public class DeletePolicyProcessor {
}
}
} else {
BaseEntity value = getReference(entity, property);
Entity value = getReference(entity, property);
if (value != null && checkIfEntityBelongsToMaster(property, value)) {
if (!(value instanceof SoftDelete)) {
if (PersistenceHelper.isLoaded(entity, property.getName())) {
@ -179,7 +178,7 @@ public class DeletePolicyProcessor {
}
}
protected void hardDeleteNotLoadedReference(BaseEntity entity, MetaProperty property, BaseEntity reference) {
protected void hardDeleteNotLoadedReference(Entity entity, MetaProperty property, Entity reference) {
List<Runnable> list = persistence.getEntityManagerContext().getAttribute(PersistenceImpl.RUN_BEFORE_COMMIT_ATTR);
if (list == null) {
list = new ArrayList<>();
@ -245,7 +244,7 @@ public class DeletePolicyProcessor {
}
}
protected BaseEntity getReference(Entity entity, MetaProperty property) {
protected Entity getReference(Entity entity, MetaProperty property) {
if (PersistenceHelper.isLoaded(entity, property.getName()))
return entity.getValue(property.getName());
else {
@ -253,11 +252,11 @@ public class DeletePolicyProcessor {
"select e." + property.getName() + " from " + entity.getMetaClass().getName() + " e where e." + primaryKeyName + " = ?1");
query.setParameter(1, entity.getId());
Object refEntity = query.getFirstResult();
return (BaseEntity) refEntity;
return (Entity) refEntity;
}
}
protected boolean checkIfEntityBelongsToMaster(MetaProperty property, BaseEntity entityToRemove) {
protected boolean checkIfEntityBelongsToMaster(MetaProperty property, Entity entityToRemove) {
MetaProperty inverseProperty = property.getInverse();
if (inverseProperty != null) {
Entity master = entityToRemove.getValue(inverseProperty.getName());
@ -343,8 +342,8 @@ public class DeletePolicyProcessor {
String qstr = String.format(template, entityName, property.getName());
Query query = entityManager.createQuery(qstr);
query.setParameter(1, entity.getId());
List<BaseEntity> list = query.getResultList();
for (BaseEntity e : list) {
List<Entity> list = query.getResultList();
for (Entity e : list) {
entityManager.remove(e);
}
}
@ -357,8 +356,8 @@ public class DeletePolicyProcessor {
String qstr = String.format(template, entityName, property.getName());
Query query = entityManager.createQuery(qstr);
query.setParameter(1, entity.getId());
List<BaseEntity> list = query.getResultList();
for (BaseEntity e : list) {
List<Entity> list = query.getResultList();
for (Entity e : list) {
if (property.getRange().getCardinality().isMany()) {
Collection collection = e.getValue(property.getName());
if (collection != null) {

View File

@ -54,7 +54,7 @@ public class EclipseLinkDescriptorEventListener implements DescriptorEventListen
protected PersistenceImplSupport support;
protected boolean justDeleted(SoftDelete entity) {
return entity.isDeleted() && persistence.getTools().getDirtyFields((BaseEntity) entity).contains("deleteTs");
return entity.isDeleted() && persistence.getTools().getDirtyFields((Entity) entity).contains("deleteTs");
}
@Override
@ -105,12 +105,12 @@ public class EclipseLinkDescriptorEventListener implements DescriptorEventListen
@Override
public void postDelete(DescriptorEvent event) {
manager.fireListener((BaseEntity) event.getSource(), EntityListenerType.AFTER_DELETE);
manager.fireListener((Entity) event.getSource(), EntityListenerType.AFTER_DELETE);
}
@Override
public void postInsert(DescriptorEvent event) {
manager.fireListener((BaseEntity) event.getSource(), EntityListenerType.AFTER_INSERT);
manager.fireListener((Entity) event.getSource(), EntityListenerType.AFTER_INSERT);
}
@Override
@ -129,7 +129,7 @@ public class EclipseLinkDescriptorEventListener implements DescriptorEventListen
@Override
public void postUpdate(DescriptorEvent event) {
manager.fireListener((BaseEntity) event.getSource(), EntityListenerType.AFTER_UPDATE);
manager.fireListener((Entity) event.getSource(), EntityListenerType.AFTER_UPDATE);
}
@Override
@ -146,11 +146,13 @@ public class EclipseLinkDescriptorEventListener implements DescriptorEventListen
@Override
public void prePersist(DescriptorEvent event) {
BaseEntity entity = (BaseEntity) event.getObject();
entity.setCreatedBy(userSessionSource.getUserSession().getUser().getLogin());
Entity entity = (Entity) event.getObject();
Date ts = timeSource.currentTimestamp();
entity.setCreateTs(ts);
if (entity instanceof Creatable) {
((Creatable) entity).setCreatedBy(userSessionSource.getUserSession().getUser().getLogin());
((Creatable) entity).setCreateTs(ts);
}
if (entity instanceof Updatable) {
((Updatable) entity).setUpdateTs(ts);
}
@ -162,7 +164,7 @@ public class EclipseLinkDescriptorEventListener implements DescriptorEventListen
@Override
public void preUpdate(DescriptorEvent event) {
BaseEntity entity = (BaseEntity) event.getObject();
Entity entity = (Entity) event.getObject();
if (!((entity instanceof SoftDelete) && justDeleted((SoftDelete) entity)) && (entity instanceof Updatable)) {
Updatable updatable = (Updatable) event.getObject();
updatable.setUpdatedBy(userSessionSource.getUserSession().getUser().getLogin());

View File

@ -19,7 +19,7 @@ package com.haulmont.cuba.core.sys.persistence;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.chile.core.model.MetaProperty;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.SoftDelete;
import com.haulmont.cuba.core.entity.annotation.EmbeddedParameters;
import com.haulmont.cuba.core.global.AppBeans;
@ -62,7 +62,7 @@ public class EclipseLinkSessionEventListener extends SessionEventAdapter {
setCacheable(metaClass, desc, session);
if (BaseEntity.class.isAssignableFrom(desc.getJavaClass())) {
if (Entity.class.isAssignableFrom(desc.getJavaClass())) {
desc.getEventManager().addListener(descriptorEventListener);
}

View File

@ -214,7 +214,7 @@ public class PersistenceImplSupport {
Collection<Object> instances = container.getAllInstances();
for (Object instance : instances) {
if (instance instanceof BaseEntity) {
if (instance instanceof Entity) {
// if cache is enabled, the entity can have EntityFetchGroup instead of CubaEntityFetchGroup
if (instance instanceof FetchGroupTracker) {
FetchGroupTracker entity = (FetchGroupTracker) instance;
@ -223,7 +223,7 @@ public class PersistenceImplSupport {
entity._persistence_setFetchGroup(new CubaEntityFetchGroup(fetchGroup));
}
entityListenerManager.fireListener((BaseEntity) instance, EntityListenerType.BEFORE_DETACH);
entityListenerManager.fireListener((Entity) instance, EntityListenerType.BEFORE_DETACH);
}
}
}
@ -294,7 +294,7 @@ public class PersistenceImplSupport {
return false;
}
protected void enqueueForFts(BaseEntity entity, FtsChangeType changeType) {
protected void enqueueForFts(Entity entity, FtsChangeType changeType) {
if (!FtsConfigHelper.getEnabled())
return;
try {
@ -312,7 +312,7 @@ public class PersistenceImplSupport {
}
}
protected void processDeletePolicy(BaseEntity entity) {
protected void processDeletePolicy(Entity entity) {
DeletePolicyProcessor processor = AppBeans.get(DeletePolicyProcessor.NAME); // prototype
processor.setEntity(entity);
processor.process();

View File

@ -24,8 +24,8 @@ import com.haulmont.cuba.core.EntityManager;
import com.haulmont.cuba.core.Persistence;
import com.haulmont.cuba.core.Transaction;
import com.haulmont.cuba.core.TypedQuery;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.HasUuid;
import com.haulmont.cuba.core.global.*;
import com.haulmont.cuba.core.sys.AppContext;
import com.haulmont.cuba.core.sys.persistence.EntityAttributeChanges;
@ -171,25 +171,25 @@ public class EntityLog implements EntityLogAPI {
log.debug("Loaded: entitiesAuto=" + entitiesAuto.size() + ", entitiesManual=" + entitiesManual.size());
}
private String getEntityName(BaseEntity entity) {
private String getEntityName(Entity entity) {
MetaClass metaClass = metadata.getSession().getClassNN(entity.getClass());
MetaClass originalMetaClass = metadata.getExtendedEntities().getOriginalMetaClass(metaClass);
return originalMetaClass != null ? originalMetaClass.getName() : metaClass.getName();
}
protected boolean doNotRegister(BaseEntity entity) {
return entity == null || entity instanceof EntityLogItem || !isEnabled();
protected boolean doNotRegister(Entity entity) {
return entity == null || !(entity instanceof HasUuid) || entity instanceof EntityLogItem || !isEnabled();
}
@Override
public void registerCreate(BaseEntity entity) {
public void registerCreate(Entity entity) {
if (entity == null)
return;
registerCreate(entity, false);
}
@Override
public void registerCreate(BaseEntity entity, boolean auto) {
public void registerCreate(Entity entity, boolean auto) {
if (doNotRegister(entity))
return;
@ -210,7 +210,7 @@ public class EntityLog implements EntityLogAPI {
item.setUser(findUser(em));
item.setType(EntityLogItem.Type.CREATE);
item.setEntity(entityName);
item.setEntityId(entity.getUuid());
item.setEntityId(((HasUuid) entity).getUuid());
Properties properties = new Properties();
for (String attr : attributes) {
@ -241,17 +241,17 @@ public class EntityLog implements EntityLogAPI {
}
@Override
public void registerModify(BaseEntity entity) {
public void registerModify(Entity entity) {
registerModify(entity, false);
}
@Override
public void registerModify(BaseEntity entity, boolean auto) {
public void registerModify(Entity entity, boolean auto) {
registerModify(entity, auto, null);
}
@Override
public void registerModify(BaseEntity entity, boolean auto, @Nullable EntityAttributeChanges changes) {
public void registerModify(Entity entity, boolean auto, @Nullable EntityAttributeChanges changes) {
if (doNotRegister(entity))
return;
@ -286,7 +286,7 @@ public class EntityLog implements EntityLogAPI {
item.setUser(findUser(em));
item.setType(EntityLogItem.Type.MODIFY);
item.setEntity(entityName);
item.setEntityId(entity.getUuid());
item.setEntityId(((HasUuid) entity).getUuid());
item.setChanges(getChanges(properties));
em.persist(item);
@ -306,7 +306,7 @@ public class EntityLog implements EntityLogAPI {
return changes;
}
protected void writeAttribute(Properties properties, BaseEntity entity, String attr) {
protected void writeAttribute(Properties properties, Entity entity, String attr) {
if (!PersistenceHelper.isLoaded(entity, attr))
return;
@ -324,12 +324,12 @@ public class EntityLog implements EntityLogAPI {
}
@Override
public void registerDelete(BaseEntity entity) {
public void registerDelete(Entity entity) {
registerDelete(entity, false);
}
@Override
public void registerDelete(BaseEntity entity, boolean auto) {
public void registerDelete(Entity entity, boolean auto) {
if (doNotRegister(entity))
return;
@ -350,7 +350,7 @@ public class EntityLog implements EntityLogAPI {
item.setUser(findUser(em));
item.setType(EntityLogItem.Type.DELETE);
item.setEntity(entityName);
item.setEntityId(entity.getUuid());
item.setEntityId(((HasUuid) entity).getUuid());
Properties properties = new Properties();
for (String attr : attributes) {

View File

@ -16,7 +16,7 @@
*/
package com.haulmont.cuba.security.app;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.sys.persistence.EntityAttributeChanges;
import javax.annotation.Nullable;
@ -39,24 +39,24 @@ public interface EntityLogAPI {
/**
* Logs creation of an entity which is configured for manual logging (LoggedEntity.auto == false).
*/
void registerCreate(BaseEntity entity);
void registerCreate(Entity entity);
/**
* Logs creation of an entity which is configured for auto or manual logging
* (depending on the {@code auto} parameter).
*/
void registerCreate(BaseEntity entity, boolean auto);
void registerCreate(Entity entity, boolean auto);
/**
* Logs modification of an entity which is configured for manual logging (LoggedEntity.auto == false).
*/
void registerModify(BaseEntity entity);
void registerModify(Entity entity);
/**
* Logs modification of an entity which is configured for auto or manual logging
* (depending on the {@code auto} parameter).
*/
void registerModify(BaseEntity entity, boolean auto);
void registerModify(Entity entity, boolean auto);
/**
@ -64,18 +64,18 @@ public interface EntityLogAPI {
* (depending on the {@code auto} parameter).
* @param changes attribute changes provided by caller
*/
void registerModify(BaseEntity entity, boolean auto, @Nullable EntityAttributeChanges changes);
void registerModify(Entity entity, boolean auto, @Nullable EntityAttributeChanges changes);
/**
* Logs deletion of an entity which is configured for manual logging (LoggedEntity.auto == false).
*/
void registerDelete(BaseEntity entity);
void registerDelete(Entity entity);
/**
* Logs deletion of an entity which is configured for auto or manual logging
* (depending on the {@code auto} parameter).
*/
void registerDelete(BaseEntity entity, boolean auto);
void registerDelete(Entity entity, boolean auto);
/**
* Invalidates configuration cache.

View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.haulmont.cuba.primary_keys;
import com.haulmont.bali.db.QueryRunner;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.chile.core.model.MetaProperty;
import com.haulmont.cuba.core.Persistence;
import com.haulmont.cuba.core.Transaction;
import com.haulmont.cuba.core.entity.BaseEntityInternalAccess;
import com.haulmont.cuba.core.global.Metadata;
import com.haulmont.cuba.testmodel.primary_keys.CompositeKeyEntity;
import com.haulmont.cuba.testmodel.primary_keys.EntityKey;
import com.haulmont.cuba.testsupport.TestContainer;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import java.sql.SQLException;
import static org.junit.Assert.*;
public class CompositeKeyTest {
@ClassRule
public static TestContainer cont = TestContainer.Common.INSTANCE;
private Metadata metadata;
private Persistence persistence;
@Before
public void setUp() throws Exception {
QueryRunner runner = new QueryRunner(cont.persistence().getDataSource());
runner.update("delete from TEST_COMPOSITE_KEY");
metadata = cont.metadata();
persistence = cont.persistence();
}
@Test
public void testOperations() throws Exception {
CompositeKeyEntity foo = metadata.create(CompositeKeyEntity.class);
EntityKey entityKey = metadata.create(EntityKey.class);
entityKey.setTenant(1);
entityKey.setEntityId(10L);
foo.setId(entityKey);
foo.setName("foo");
foo.setEmail("foo@mail.com");
try (Transaction tx = persistence.createTransaction()) {
persistence.getEntityManager().persist(foo);
tx.commit();
}
CompositeKeyEntity loadedFoo;
try (Transaction tx = persistence.createTransaction()) {
loadedFoo = persistence.getEntityManager().find(CompositeKeyEntity.class, entityKey);
tx.commit();
}
assertNotNull(loadedFoo);
assertEquals(foo, loadedFoo);
loadedFoo.setName("bar");
CompositeKeyEntity bar;
try (Transaction tx = persistence.createTransaction()) {
bar = persistence.getEntityManager().merge(loadedFoo);
tx.commit();
}
assertEquals(foo, bar);
CompositeKeyEntity loadedBar;
try (Transaction tx = persistence.createTransaction()) {
loadedBar = persistence.getEntityManager().find(CompositeKeyEntity.class, entityKey);
tx.commit();
}
assertNotNull(loadedBar);
assertEquals("bar", loadedBar.getName());
try (Transaction tx = persistence.createTransaction()) {
loadedBar = persistence.getEntityManager().find(CompositeKeyEntity.class, entityKey);
persistence.getEntityManager().remove(loadedBar);
tx.commit();
}
assertTrue(BaseEntityInternalAccess.isRemoved(loadedBar));
try (Transaction tx = persistence.createTransaction()) {
loadedBar = persistence.getEntityManager().find(CompositeKeyEntity.class, entityKey);
assertNull(loadedBar);
tx.commit();
}
}
@Test
public void testMetadata() throws Exception {
MetaClass metaClass = metadata.getClassNN(CompositeKeyEntity.class);
String primaryKeyName = metadata.getTools().getPrimaryKeyName(metaClass);
assertEquals("id", primaryKeyName);
MetaProperty primaryKeyProperty = metadata.getTools().getPrimaryKeyProperty(metaClass);
assertNotNull(primaryKeyProperty);
assertEquals("id", primaryKeyProperty.getName());
assertTrue(metadata.getTools().isEmbedded(metaClass.getPropertyNN("id")));
}
}

View File

@ -0,0 +1,225 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.haulmont.cuba.primary_keys;
import com.haulmont.bali.db.QueryRunner;
import com.haulmont.cuba.core.Persistence;
import com.haulmont.cuba.core.Query;
import com.haulmont.cuba.core.Transaction;
import com.haulmont.cuba.core.TypedQuery;
import com.haulmont.cuba.core.entity.BaseEntityInternalAccess;
import com.haulmont.cuba.core.entity.BaseIdentityIdEntity;
import com.haulmont.cuba.core.entity.IdProxy;
import com.haulmont.cuba.core.global.Metadata;
import com.haulmont.cuba.testmodel.primary_keys.IdentityEntity;
import com.haulmont.cuba.testsupport.TestContainer;
import com.haulmont.cuba.testsupport.TestSupport;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import java.lang.reflect.Field;
import java.util.UUID;
import static org.junit.Assert.*;
public class IdentityTest {
@ClassRule
public static TestContainer cont = TestContainer.Common.INSTANCE;
private Metadata metadata;
private Persistence persistence;
@Before
public void setUp() throws Exception {
QueryRunner runner = new QueryRunner(cont.persistence().getDataSource());
runner.update("delete from TEST_IDENTITY");
metadata = cont.metadata();
persistence = cont.persistence();
}
@Test
public void testEquality() throws Exception {
IdentityEntity e1 = metadata.create(IdentityEntity.class);
assertNotNull(e1.getId());
assertNotNull(e1.getId().getUuid());
IdentityEntity e2 = metadata.create(IdentityEntity.class);
assertNotEquals(e1, e2);
// e2.setUuid(e1.getUuid());
// assertEquals(e1, e2);
// assertTrue(e1.hashCode() == e2.hashCode());
Field idField = BaseIdentityIdEntity.class.getDeclaredField("id");
idField.setAccessible(true);
// e1 & e3 are different instances with the same UUID
IdentityEntity e3 = TestSupport.reserialize(e1);
// one of them has an Id, other has not - this is the case when a newly committed instance returns from
// middleware to the client
idField.set(e3, 100L);
// they should be equal and with the same hashCode
assertEquals(e1, e3);
assertTrue(e1.hashCode() == e3.hashCode());
// e1 & e3 are different instances with the same Id
e1 = metadata.create(IdentityEntity.class);
idField.set(e1, 100L);
e2 = metadata.create(IdentityEntity.class);
idField.set(e2, 100L);
// they should be equal and with the same hashCode
assertEquals(e1, e2);
assertTrue(e1.hashCode() == e2.hashCode());
}
@Test
public void testPersistAndMerge() throws Exception {
IdentityEntity foo = metadata.create(IdentityEntity.class);
foo.setName("foo");
foo.setEmail("foo@mail.com");
UUID uuid = foo.getId().getUuid();
try (Transaction tx = persistence.createTransaction()) {
persistence.getEntityManager().persist(foo);
tx.commit();
}
assertNotNull(foo.getId().get());
assertEquals(uuid, foo.getId().getUuid());
foo.setName("bar");
IdentityEntity bar;
try (Transaction tx = persistence.createTransaction()) {
bar = persistence.getEntityManager().merge(foo);
tx.commit();
}
assertEquals(uuid, foo.getId().getUuid());
assertEquals(foo, bar);
bar.setName("baz");
IdentityEntity baz;
try (Transaction tx = persistence.createTransaction()) {
baz = persistence.getEntityManager().merge(foo);
tx.commit();
}
assertEquals(uuid, foo.getId().getUuid());
assertEquals(foo, baz);
}
@Test
public void testFindAndDelete() throws Exception {
IdentityEntity foo = metadata.create(IdentityEntity.class);
foo.setName("foo");
foo.setEmail("foo@mail.com");
try (Transaction tx = persistence.createTransaction()) {
persistence.getEntityManager().persist(foo);
tx.commit();
}
IdentityEntity loaded;
try (Transaction tx = persistence.createTransaction()) {
loaded = persistence.getEntityManager().find(IdentityEntity.class, foo.getId());
tx.commit();
}
assertEquals(foo, loaded);
try (Transaction tx = persistence.createTransaction()) {
loaded = persistence.getEntityManager().find(IdentityEntity.class, loaded.getId());
persistence.getEntityManager().remove(loaded);
tx.commit();
}
assertTrue(BaseEntityInternalAccess.isRemoved(loaded));
try (Transaction tx = persistence.createTransaction()) {
loaded = persistence.getEntityManager().find(IdentityEntity.class, loaded.getId());
assertNull(loaded);
tx.commit();
}
}
@Test
public void testQueryById() throws Exception {
IdentityEntity foo = metadata.create(IdentityEntity.class);
foo.setName("foo");
foo.setEmail("foo@mail.com");
try (Transaction tx = persistence.createTransaction()) {
persistence.getEntityManager().persist(foo);
tx.commit();
}
IdentityEntity loaded;
try (Transaction tx = persistence.createTransaction()) {
TypedQuery<IdentityEntity> query = persistence.getEntityManager().createQuery(
"select e from test$IdentityEntity e where e.id = ?1", IdentityEntity.class);
query.setParameter(1, foo.getId());
loaded = query.getSingleResult();
tx.commit();
}
assertEquals(foo, loaded);
try (Transaction tx = persistence.createTransaction()) {
TypedQuery<IdentityEntity> query = persistence.getEntityManager().createQuery(
"select e from test$IdentityEntity e where e.id = :id", IdentityEntity.class);
query.setParameter("id", foo.getId());
loaded = query.getSingleResult();
tx.commit();
}
assertEquals(foo, loaded);
}
@Test
public void testLoadByIdValue() throws Exception {
IdentityEntity foo = metadata.create(IdentityEntity.class);
foo.setName("foo");
foo.setEmail("foo@mail.com");
try (Transaction tx = persistence.createTransaction()) {
persistence.getEntityManager().persist(foo);
tx.commit();
}
Long idVal = foo.getId().get();
IdentityEntity loaded;
try (Transaction tx = persistence.createTransaction()) {
loaded = persistence.getEntityManager().find(IdentityEntity.class, IdProxy.of(idVal));
tx.commit();
}
assertEquals(foo, loaded);
try (Transaction tx = persistence.createTransaction()) {
TypedQuery<IdentityEntity> query = persistence.getEntityManager().createQuery(
"select e from test$IdentityEntity e where e.id = :id", IdentityEntity.class);
query.setParameter("id", idVal);
loaded = query.getSingleResult();
tx.commit();
}
assertEquals(foo, loaded);
try (Transaction tx = persistence.createTransaction()) {
TypedQuery<IdentityEntity> query = persistence.getEntityManager().createQuery(
"select e from test$IdentityEntity e where e.id = :id", IdentityEntity.class);
query.setParameter("id", IdProxy.of(idVal));
loaded = query.getSingleResult();
tx.commit();
}
assertEquals(foo, loaded);
}
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.haulmont.cuba.primary_keys;
import com.haulmont.bali.db.QueryRunner;
import com.haulmont.cuba.core.Persistence;
import com.haulmont.cuba.core.Transaction;
import com.haulmont.cuba.core.global.Metadata;
import com.haulmont.cuba.testmodel.primary_keys.IdentityUuidEntity;
import com.haulmont.cuba.testsupport.TestContainer;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import java.util.UUID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public class IdentityUuidTest {
@ClassRule
public static TestContainer cont = TestContainer.Common.INSTANCE;
private Metadata metadata;
private Persistence persistence;
@Before
public void setUp() throws Exception {
QueryRunner runner = new QueryRunner(cont.persistence().getDataSource());
runner.update("delete from TEST_IDENTITY_UUID");
metadata = cont.metadata();
persistence = cont.persistence();
}
@Test
public void test() throws Exception {
IdentityUuidEntity foo = metadata.create(IdentityUuidEntity.class);
foo.setName("foo");
UUID uuid = foo.getUuid();
assertEquals(uuid, foo.getId().getUuid());
try (Transaction tx = persistence.createTransaction()) {
persistence.getEntityManager().persist(foo);
tx.commit();
}
assertNotNull(foo.getId().get());
assertEquals(uuid, foo.getUuid());
IdentityUuidEntity loaded;
try (Transaction tx = persistence.createTransaction()) {
loaded = persistence.getEntityManager().find(IdentityUuidEntity.class, foo.getId());
tx.commit();
}
assertNotNull(loaded);
assertEquals(foo, loaded);
assertEquals(uuid, loaded.getUuid());
assertEquals(uuid, loaded.getId().getUuid());
loaded.setName("bar");
IdentityUuidEntity merged;
try (Transaction tx = persistence.createTransaction()) {
merged = persistence.getEntityManager().merge(loaded);
tx.commit();
}
assertEquals("bar", merged.getName());
assertEquals(foo, merged);
assertEquals(uuid, merged.getUuid());
assertEquals(uuid, merged.getId().getUuid());
}
}

View File

@ -46,3 +46,29 @@ create table TEST_MANY2MANY_AB_LINK2 (
constraint TEST_MANY2MANY_AB_LINK2_A foreign key (A_ID) references TEST_MANY2MANY_A(ID),
constraint TEST_MANY2MANY_AB_LINK2_B foreign key (B_ID) references TEST_MANY2MANY_B(ID)
)^
------------------------------------------------------------------------------------------------------------
create table TEST_IDENTITY (
ID bigint identity,
NAME varchar(50),
EMAIL varchar(100)
)^
------------------------------------------------------------------------------------------------------------
create table TEST_IDENTITY_UUID (
ID bigint identity,
UUID varchar(36),
NAME varchar(50)
)^
------------------------------------------------------------------------------------------------------------
create table TEST_COMPOSITE_KEY (
TENANT integer not null,
ENTITY_ID bigint not null,
NAME varchar(50),
EMAIL varchar(100),
primary key (TENANT, ENTITY_ID)
)^

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.haulmont.cuba.testmodel.primary_keys;
import com.haulmont.cuba.core.entity.BaseGenericIdEntity;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity(name = "test$CompositeKeyEntity")
@Table(name = "TEST_COMPOSITE_KEY")
public class CompositeKeyEntity extends BaseGenericIdEntity<EntityKey> {
private static final long serialVersionUID = -2538345720324624741L;
@EmbeddedId
private EntityKey id;
@Column(name = "NAME")
private String name;
@Column(name = "EMAIL")
private String email;
@Override
public void setId(EntityKey id) {
this.id = id;
}
@Override
public EntityKey getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.haulmont.cuba.testmodel.primary_keys;
import com.haulmont.cuba.core.entity.EmbeddableEntity;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import java.util.Objects;
@Embeddable
public class EntityKey extends EmbeddableEntity {
@Column(name = "TENANT")
private Integer tenant;
@Column(name = "ENTITY_ID")
private Long entityId;
public Integer getTenant() {
return tenant;
}
public void setTenant(Integer tenant) {
this.tenant = tenant;
}
public Long getEntityId() {
return entityId;
}
public void setEntityId(Long entityId) {
this.entityId = entityId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof EntityKey)) return false;
EntityKey entityKey = (EntityKey) o;
return Objects.equals(tenant, entityKey.tenant) &&
Objects.equals(entityId, entityKey.entityId);
}
@Override
public int hashCode() {
return Objects.hash(tenant, entityId);
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.haulmont.cuba.testmodel.primary_keys;
import com.haulmont.cuba.core.entity.BaseIdentityIdEntity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity(name = "test$IdentityEntity")
@Table(name = "TEST_IDENTITY")
public class IdentityEntity extends BaseIdentityIdEntity {
@Column(name = "NAME")
private String name;
@Column(name = "EMAIL")
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.haulmont.cuba.testmodel.primary_keys;
import com.haulmont.cuba.core.entity.BaseIdentityIdEntity;
import com.haulmont.cuba.core.entity.HasUuid;
import com.haulmont.cuba.core.global.UuidProvider;
import javax.persistence.AttributeOverride;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.util.UUID;
@Entity(name = "test$IdentityUuidEntity")
@Table(name = "TEST_IDENTITY_UUID")
@AttributeOverride(name = "uuid", column = @Column(name = "UUID"))
public class IdentityUuidEntity extends BaseIdentityIdEntity implements HasUuid {
private static final long serialVersionUID = 3005691784646391098L;
@Column(name = "UUID")
private UUID uuid = UuidProvider.createUuid();
@Column(name = "NAME")
private String name;
@Override
public UUID getUuid() {
return uuid;
}
@Override
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -22,5 +22,9 @@
<persistence-unit name="cuba" transaction-type="RESOURCE_LOCAL">
<class>com.haulmont.cuba.testmodel.many2many.Many2ManyA</class>
<class>com.haulmont.cuba.testmodel.many2many.Many2ManyB</class>
<class>com.haulmont.cuba.testmodel.primary_keys.IdentityEntity</class>
<class>com.haulmont.cuba.testmodel.primary_keys.IdentityUuidEntity</class>
<class>com.haulmont.cuba.testmodel.primary_keys.EntityKey</class>
<class>com.haulmont.cuba.testmodel.primary_keys.CompositeKeyEntity</class>
</persistence-unit>
</persistence>

View File

@ -20,18 +20,12 @@ import com.haulmont.chile.core.common.ValueListener;
import javax.annotation.Nullable;
import java.io.Serializable;
import java.util.UUID;
/**
* Interface to be implemented by data model objects.
*/
public interface Instance extends Serializable {
/**
* @return globally unique identifier of this instance
*/
UUID getUuid();
/**
* @return metaclass of this object. Throws exception if the metaclass is not found.
*/

View File

@ -137,28 +137,4 @@ public abstract class AbstractInstance implements Instance {
public void setValueEx(String name, Object value) {
InstanceUtils.setValueEx(this, name, value);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AbstractInstance that = (AbstractInstance) o;
return !(getUuid() != null ? !getUuid().equals(that.getUuid()) : that.getUuid() != null);
}
@Override
public int hashCode() {
return getUuid() != null ? getUuid().hashCode() : 0;
}
@Override
public String toString() {
return getClass().getName() + "-" + getUuid();
}
}

View File

@ -93,6 +93,7 @@ public class JPAAnnotationsLoader extends ChileAnnotationsLoader {
|| field.isAnnotationPresent(ManyToMany.class)
|| field.isAnnotationPresent(OneToOne.class)
|| field.isAnnotationPresent(Embedded.class)
|| field.isAnnotationPresent(EmbeddedId.class)
|| super.isMetaPropertyField(field);
}
@ -229,7 +230,9 @@ public class JPAAnnotationsLoader extends ChileAnnotationsLoader {
if (isPrimaryKey(field)) {
metaProperty.getAnnotations().put("primaryKey", true);
metaProperty.getDomain().getAnnotations().put("primaryKey", metaProperty.getName());
} else if (isEmbedded(field)) {
}
if (isEmbedded(field)) {
metaProperty.getAnnotations().put("embedded", true);
}
@ -247,11 +250,11 @@ public class JPAAnnotationsLoader extends ChileAnnotationsLoader {
}
protected boolean isPrimaryKey(Field field) {
return field.isAnnotationPresent(Id.class);
return field.isAnnotationPresent(Id.class) || field.isAnnotationPresent(EmbeddedId.class);
}
protected boolean isEmbedded(Field field) {
return field.isAnnotationPresent(Embedded.class);
return field.isAnnotationPresent(Embedded.class) || field.isAnnotationPresent(EmbeddedId.class);
}
protected boolean isPersistent(Field field) {
@ -260,6 +263,7 @@ public class JPAAnnotationsLoader extends ChileAnnotationsLoader {
|| field.isAnnotationPresent(OneToMany.class)
|| field.isAnnotationPresent(ManyToMany.class)
|| field.isAnnotationPresent(OneToOne.class)
|| field.isAnnotationPresent(Embedded.class);
|| field.isAnnotationPresent(Embedded.class)
|| field.isAnnotationPresent(EmbeddedId.class);
}
}

View File

@ -18,7 +18,7 @@
package com.haulmont.cuba.core.app;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.EntitySnapshot;
import com.haulmont.cuba.core.entity.diff.EntityDiff;
import com.haulmont.cuba.core.global.View;
@ -52,7 +52,7 @@ public interface EntitySnapshotService {
* @param view View
* @return Snapshot
*/
EntitySnapshot createSnapshot(BaseEntity entity, View view);
EntitySnapshot createSnapshot(Entity entity, View view);
/**
* Create snapshot for Entity with specific date and store it to database
@ -62,7 +62,7 @@ public interface EntitySnapshotService {
* @param snapshotDate Date
* @return Snapshot
*/
EntitySnapshot createSnapshot(BaseEntity entity, View view, Date snapshotDate);
EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate);
/**
* Create snapshot for Entity with specific date and author and store it to database
@ -73,14 +73,14 @@ public interface EntitySnapshotService {
* @param author Author
* @return Snapshot
*/
EntitySnapshot createSnapshot(BaseEntity entity, View view, Date snapshotDate, User author);
EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate, User author);
/**
* Get entity from snapshot
* @param snapshot Snapshot
* @return Entity
*/
BaseEntity extractEntity(EntitySnapshot snapshot);
Entity extractEntity(EntitySnapshot snapshot);
/**
* Get Diff for snapshots

View File

@ -33,7 +33,9 @@ import java.util.UUID;
*
*/
@com.haulmont.chile.core.annotations.MetaClass(name = "AbstractNotPersistentEntity")
public abstract class AbstractNotPersistentEntity extends AbstractInstance implements Entity<UUID>, CubaEnhancingDisabled {
public abstract class AbstractNotPersistentEntity
extends AbstractInstance
implements Entity<UUID>, HasUuid, CubaEnhancingDisabled {
private static final long serialVersionUID = -2846020822531467401L;
@ -48,6 +50,11 @@ public abstract class AbstractNotPersistentEntity extends AbstractInstance imple
return id;
}
@Override
public void setUuid(UUID uuid) {
id = uuid;
}
@Override
public MetaClass getMetaClass() {
Metadata metadata = AppBeans.get(Metadata.NAME);
@ -74,4 +81,28 @@ public abstract class AbstractNotPersistentEntity extends AbstractInstance imple
}
}
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AbstractNotPersistentEntity that = (AbstractNotPersistentEntity) o;
return !(getUuid() != null ? !getUuid().equals(that.getUuid()) : that.getUuid() != null);
}
@Override
public int hashCode() {
return getUuid() != null ? getUuid().hashCode() : 0;
}
@Override
public String toString() {
return getClass().getName() + "-" + getUuid();
}
}

View File

@ -16,22 +16,9 @@
*/
package com.haulmont.cuba.core.entity;
import java.util.Date;
/**
* Base interface for persistent entities.
* @param <T> identifier type
*
* DEPRECATED. Use {@link Entity}.
*/
@Deprecated
public interface BaseEntity<T> extends Entity<T> {
int LOGIN_FIELD_LEN = 50;
Date getCreateTs();
void setCreateTs(Date date);
String getCreatedBy();
void setCreatedBy(String createdBy);
}

View File

@ -29,13 +29,12 @@ import com.haulmont.cuba.core.global.TimeSource;
import org.apache.commons.lang.ObjectUtils;
import javax.annotation.Nullable;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
/**
@ -51,7 +50,7 @@ import java.util.UUID;
* </p>
*/
@MappedSuperclass
public abstract class BaseGenericIdEntity<T> extends AbstractInstance implements BaseEntity<T> {
public abstract class BaseGenericIdEntity<T> extends AbstractInstance implements Entity<T> {
private static final long serialVersionUID = -8400641366148656528L;
@ -81,12 +80,6 @@ public abstract class BaseGenericIdEntity<T> extends AbstractInstance implements
@Transient
protected Map<String, CategoryAttributeValue> dynamicAttributes = null;
@Column(name = "CREATE_TS")
protected Date createTs;
@Column(name = "CREATED_BY", length = LOGIN_FIELD_LEN)
protected String createdBy;
public abstract void setId(T id);
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
@ -101,29 +94,9 @@ public abstract class BaseGenericIdEntity<T> extends AbstractInstance implements
return metadata.getSession().getClassNN(getClass());
}
@Override
public Date getCreateTs() {
return createTs;
}
@Override
public void setCreateTs(Date createTs) {
this.createTs = createTs;
}
@Override
public String getCreatedBy() {
return createdBy;
}
@Override
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
@Override
public void setValue(String property, Object newValue, boolean checkEquals) {
if (DynamicAttributesUtils.isDynamicAttribute(property)) {
if (this instanceof HasUuid && DynamicAttributesUtils.isDynamicAttribute(property)) {
Preconditions.checkState(dynamicAttributes != null, "Dynamic attributes should be loaded explicitly");
String attributeCode = DynamicAttributesUtils.decodeAttributeCode(property);
CategoryAttributeValue categoryAttributeValue = dynamicAttributes.get(attributeCode);
@ -144,7 +117,7 @@ public abstract class BaseGenericIdEntity<T> extends AbstractInstance implements
categoryAttributeValue = metadata.create(CategoryAttributeValue.class);
categoryAttributeValue.setValue(newValue);
categoryAttributeValue.setEntityId(getUuid());
categoryAttributeValue.setEntityId(((HasUuid) this).getUuid());
categoryAttributeValue.setCode(attributeCode);
DynamicAttributes dynamicAttributesBean = AppBeans.get(DynamicAttributes.NAME);
categoryAttributeValue.setCategoryAttribute(
@ -187,6 +160,22 @@ public abstract class BaseGenericIdEntity<T> extends AbstractInstance implements
return dynamicAttributes;
}
@Override
public boolean equals(Object other) {
if (this == other)
return true;
if (other == null || getClass() != other.getClass())
return false;
return Objects.equals(getId(), ((BaseGenericIdEntity) other).getId());
}
@Override
public int hashCode() {
return getId() != null ? getId().hashCode() : 0;
}
@Override
public String toString() {
String state = "";
@ -200,6 +189,6 @@ public abstract class BaseGenericIdEntity<T> extends AbstractInstance implements
state += "removed,";
if (state.length() > 0)
state = state.substring(0, state.length() - 1);
return super.toString() + " [" + state + "]";
return getClass().getName() + "-" + getId() + " [" + state + "]";
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.haulmont.cuba.core.entity;
import javax.persistence.*;
/**
* Base class for persistent entities with Identity identifier.
*/
@MappedSuperclass
public abstract class BaseIdentityIdEntity extends BaseGenericIdEntity<IdProxy> {
private static final long serialVersionUID = 3083677558630811496L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
protected Long id;
@Transient
protected IdProxy idProxy;
@Override
public IdProxy getId() {
if (idProxy == null) {
idProxy = new IdProxy(this);
}
return idProxy;
}
@Override
public void setId(IdProxy idProxy) {
this.id = idProxy.get();
}
}

View File

@ -16,16 +16,12 @@
*/
package com.haulmont.cuba.core.entity;
import com.haulmont.cuba.core.global.UuidProvider;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import java.util.UUID;
/**
* Base class for persistent entities with Integer identifier.
*
*/
@MappedSuperclass
public abstract class BaseIntegerIdEntity extends BaseGenericIdEntity<Integer> {
@ -36,13 +32,6 @@ public abstract class BaseIntegerIdEntity extends BaseGenericIdEntity<Integer> {
@Column(name = "ID")
protected Integer id;
@Column(name = "UUID", nullable = false)
protected UUID uuid;
protected BaseIntegerIdEntity() {
uuid = UuidProvider.createUuid();
}
@Override
public Integer getId() {
return id;
@ -52,13 +41,4 @@ public abstract class BaseIntegerIdEntity extends BaseGenericIdEntity<Integer> {
public void setId(Integer id) {
this.id = id;
}
@Override
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
}

View File

@ -16,16 +16,12 @@
*/
package com.haulmont.cuba.core.entity;
import com.haulmont.cuba.core.global.UuidProvider;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import java.util.UUID;
/**
* Base class for persistent entities with Long identifier.
*
*/
@MappedSuperclass
public abstract class BaseLongIdEntity extends BaseGenericIdEntity<Long> {
@ -36,13 +32,6 @@ public abstract class BaseLongIdEntity extends BaseGenericIdEntity<Long> {
@Column(name = "ID")
protected Long id;
@Column(name = "UUID", nullable = false)
protected UUID uuid;
protected BaseLongIdEntity() {
uuid = UuidProvider.createUuid();
}
@Override
public Long getId() {
return id;
@ -52,13 +41,4 @@ public abstract class BaseLongIdEntity extends BaseGenericIdEntity<Long> {
public void setId(Long id) {
this.id = id;
}
@Override
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
}

View File

@ -17,11 +17,7 @@
package com.haulmont.cuba.core.entity;
import com.haulmont.cuba.core.global.UuidProvider;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import java.util.UUID;
/**
* Base class for persistent entities with String identifier.
@ -40,22 +36,6 @@ public abstract class BaseStringIdEntity extends BaseGenericIdEntity<String> {
private static final long serialVersionUID = -1887225952123433245L;
@Column(name = "UUID", nullable = false)
protected UUID uuid;
protected BaseStringIdEntity() {
uuid = UuidProvider.createUuid();
}
@Override
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
@Override
public abstract String getId();
}

View File

@ -24,12 +24,12 @@ import javax.persistence.MappedSuperclass;
import java.util.UUID;
/**
* Base class for persistent entities with UUID identifier.<br>
* Inherit from it if you need an entity without optimistic locking, update and soft deletion info.
*
* Base class for persistent entities with UUID identifier.
* <p>
* Inherit from it if you need an entity without optimistic locking, create, update and soft deletion info.
*/
@MappedSuperclass
public abstract class BaseUuidEntity extends BaseGenericIdEntity<UUID> {
public abstract class BaseUuidEntity extends BaseGenericIdEntity<UUID> implements HasUuid {
private static final long serialVersionUID = -2217624132287086972L;
@ -55,4 +55,8 @@ public abstract class BaseUuidEntity extends BaseGenericIdEntity<UUID> {
public UUID getUuid() {
return id;
}
public void setUuid(UUID uuid) {
this.id = uuid;
}
}

View File

@ -153,8 +153,8 @@ public class CategoryAttributeValue extends StandardEntity {
setBooleanValue((Boolean) value);
} else if (value instanceof UUID) {
setEntityValue((UUID) value);
} else if (value instanceof Entity) {
setEntityValue(((Entity) value).getUuid());
} else if (value instanceof HasUuid) {
setEntityValue(((HasUuid) value).getUuid());
} else if (value instanceof String) {
setStringValue((String) value);
} else {

View File

@ -31,13 +31,19 @@ import java.util.Date;
@Entity(name = "sys$Config")
@Table(name = "SYS_CONFIG")
@SystemLevel
public class Config extends BaseUuidEntity implements Versioned, Updatable {
public class Config extends BaseUuidEntity implements Versioned, Creatable, Updatable {
private static final long serialVersionUID = -2103060811330948816L;
@Version
@Column(name = "VERSION")
private Integer version;
@Column(name = "CREATE_TS")
protected Date createTs;
@Column(name = "CREATED_BY", length = LOGIN_FIELD_LEN)
protected String createdBy;
@Column(name = "UPDATE_TS")
private Date updateTs;
@ -60,6 +66,26 @@ public class Config extends BaseUuidEntity implements Versioned, Updatable {
this.version = version;
}
@Override
public Date getCreateTs() {
return createTs;
}
@Override
public void setCreateTs(Date createTs) {
this.createTs = createTs;
}
@Override
public String getCreatedBy() {
return createdBy;
}
@Override
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
@Override
public Date getUpdateTs() {
return updateTs;

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.haulmont.cuba.core.entity;
import java.util.Date;
/**
* Interface to be implemented by entities that contain information about who created them and when.
*/
public interface Creatable {
int LOGIN_FIELD_LEN = 50;
Date getCreateTs();
void setCreateTs(Date date);
String getCreatedBy();
void setCreatedBy(String createdBy);
}

View File

@ -20,41 +20,26 @@ import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.chile.core.model.impl.AbstractInstance;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.global.Metadata;
import com.haulmont.cuba.core.global.UuidProvider;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import java.util.UUID;
/**
* Base class for persistent embeddable entities.
*
*/
@MappedSuperclass
public abstract class EmbeddableEntity extends AbstractInstance implements Entity<UUID> {
public abstract class EmbeddableEntity extends AbstractInstance implements Entity<Object> {
private static final long serialVersionUID = 266201862280559076L;
@Transient
private UUID id;
@Override
public UUID getId() {
return id;
}
public EmbeddableEntity() {
id = UuidProvider.createUuid();
public Object getId() {
return this;
}
@Override
public MetaClass getMetaClass() {
Metadata metadata = AppBeans.get(Metadata.NAME);
return metadata.getSession().getClass(getClass());
}
@Override
public UUID getUuid() {
return id;
return metadata.getSession().getClassNN(getClass());
}
}

View File

@ -39,10 +39,16 @@ import java.util.UUID;
@Entity(name = "sys$EntitySnapshot")
@Table(name = "SYS_ENTITY_SNAPSHOT")
@SystemLevel
public class EntitySnapshot extends BaseUuidEntity {
public class EntitySnapshot extends BaseUuidEntity implements Creatable {
private static final long serialVersionUID = 4835363127711391591L;
@Column(name = "CREATE_TS")
protected Date createTs;
@Column(name = "CREATED_BY", length = LOGIN_FIELD_LEN)
protected String createdBy;
@Column(name = "VIEW_XML")
private String viewXml;
@ -62,6 +68,26 @@ public class EntitySnapshot extends BaseUuidEntity {
@Column(name = "ENTITY_ID")
private UUID entityId;
@Override
public Date getCreateTs() {
return createTs;
}
@Override
public void setCreateTs(Date createTs) {
this.createTs = createTs;
}
@Override
public String getCreatedBy() {
return createdBy;
}
@Override
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public String getViewXml() {
return viewXml;
}

View File

@ -19,18 +19,24 @@ package com.haulmont.cuba.core.entity;
import com.haulmont.cuba.core.entity.annotation.SystemLevel;
import org.apache.commons.lang.StringUtils;
import javax.persistence.Entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.util.Date;
@Entity(name = "sys$EntityStatistics")
@Table(name = "SYS_ENTITY_STATISTICS")
@SystemLevel
public class EntityStatistics extends BaseUuidEntity implements Updatable {
public class EntityStatistics extends BaseUuidEntity implements Creatable, Updatable {
private static final long serialVersionUID = -1734840995849860033L;
@Column(name = "CREATE_TS")
protected Date createTs;
@Column(name = "CREATED_BY", length = LOGIN_FIELD_LEN)
protected String createdBy;
@Column(name = "UPDATE_TS")
private Date updateTs;
@ -55,6 +61,26 @@ public class EntityStatistics extends BaseUuidEntity implements Updatable {
@Column(name = "LOOKUP_SCREEN_THRESHOLD")
private Integer lookupScreenThreshold;
@Override
public Date getCreateTs() {
return createTs;
}
@Override
public void setCreateTs(Date createTs) {
this.createTs = createTs;
}
@Override
public String getCreatedBy() {
return createdBy;
}
@Override
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
@Override
public String getUpdatedBy() {
return updatedBy;

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.haulmont.cuba.core.entity;
import java.util.UUID;
/**
* Interface to be implemented by entities that have a persistent attribute of {@link UUID} type.
*/
public interface HasUuid {
UUID getUuid();
void setUuid(UUID uuid);
}

View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.haulmont.cuba.core.entity;
import com.haulmont.bali.util.Preconditions;
import com.haulmont.cuba.core.global.UuidProvider;
import javax.annotation.Nullable;
import java.io.Serializable;
import java.util.Objects;
import java.util.UUID;
/**
* Class that is used as an entity ID when an actual identifier value is not available until the object is persisted
* to the database, which is the case for {@link BaseIdentityIdEntity}.
* <p>
* If you need to create a proxy for an existing ID, use {@link #of(Long)} method.
*/
public class IdProxy implements Serializable {
private static final long serialVersionUID = 1591247506604691467L;
private BaseIdentityIdEntity entity;
private UUID uuid;
private int hashCode;
private Long value;
IdProxy(BaseIdentityIdEntity entity) {
Preconditions.checkNotNullArgument(entity, "entity is null");
this.entity = entity;
if (entity instanceof HasUuid) {
this.uuid = ((HasUuid) entity).getUuid();
this.hashCode = this.uuid.hashCode();
} else {
this.uuid = UuidProvider.createUuid();
this.hashCode = 0; // trade-off, see com.haulmont.cuba.primary_keys.IdentityTest.testEquality
}
}
IdProxy(Long value) {
Preconditions.checkNotNullArgument(value, "value is null");
this.value = value;
}
/**
* Create proxy for the specified ID value. You might need it for providing ID to the {@code EntityManager.find()}
* method.
* @param value real ID value
*/
public static IdProxy of(Long value) {
return new IdProxy(value);
}
/**
* @return real ID value or null if it is not assigned yet
*/
@Nullable
public Long get() {
return value != null ? value : entity.id;
}
/**
* @return real ID value
* @throws IllegalStateException if it is not assigned yet
*/
public Long getNN() {
if (value != null)
return value;
if (entity.id == null)
throw new IllegalStateException("ID is not assigned for entity " + entity);
return entity.id;
}
/**
* INTERNAL
*/
public UUID getUuid() {
return uuid;
}
/**
* INTERNAL
*/
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
@Override
public boolean equals(Object other) {
if (this == other)
return true;
if (other == null || getClass() != other.getClass())
return false;
IdProxy that = (IdProxy) other;
if (value != null)
return value.equals(that.value);
if (entity.id == null || that.entity.id == null)
return Objects.equals(uuid, that.uuid);
return Objects.equals(entity.id, that.entity.id);
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public String toString() {
if (value != null)
return value.toString();
if (entity.id != null)
return entity.id.toString();
else
return "?(" + uuid + ")";
}
}

View File

@ -18,7 +18,6 @@
package com.haulmont.cuba.core.entity;
import com.haulmont.bali.util.Dom4j;
import com.haulmont.bali.util.ReflectionHelper;
import com.haulmont.chile.core.annotations.MetaProperty;
import com.haulmont.chile.core.annotations.NamePattern;
import com.haulmont.cuba.core.app.scheduled.MethodParameterInfo;
@ -46,7 +45,7 @@ import java.util.List;
@Table(name = "SYS_SCHEDULED_TASK")
@NamePattern("#name|beanName,methodName,className,scriptName")
@SystemLevel
public class ScheduledTask extends BaseUuidEntity implements Updatable, SoftDelete {
public class ScheduledTask extends BaseUuidEntity implements Creatable, Updatable, SoftDelete {
private static final long serialVersionUID = -2330884126746644884L;
@ -54,16 +53,22 @@ public class ScheduledTask extends BaseUuidEntity implements Updatable, SoftDele
// Moreover unfortunately OpenJPA issues a lot of unnecessary "select version from ..." when loads versioned
// objects with PESSIMISTIC lock type.
@Column(name = "CREATE_TS")
protected Date createTs;
@Column(name = "CREATED_BY", length = LOGIN_FIELD_LEN)
protected String createdBy;
@Column(name = "UPDATE_TS")
protected Date updateTs;
@Column(name = "UPDATED_BY", length = LOGIN_FIELD_LEN)
@Column(name = "UPDATED_BY", length = 50)
protected String updatedBy;
@Column(name = "DELETE_TS")
protected Date deleteTs;
@Column(name = "DELETED_BY", length = LOGIN_FIELD_LEN)
@Column(name = "DELETED_BY", length = 50)
protected String deletedBy;
@Column(name = "DEFINED_BY")
@ -136,6 +141,26 @@ public class ScheduledTask extends BaseUuidEntity implements Updatable, SoftDele
@Transient
protected volatile long currentStartTimestamp;
@Override
public Date getCreateTs() {
return createTs;
}
@Override
public void setCreateTs(Date createTs) {
this.createTs = createTs;
}
@Override
public String getCreatedBy() {
return createdBy;
}
@Override
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
@Override
public Date getUpdateTs() {
return updateTs;

View File

@ -19,19 +19,25 @@ package com.haulmont.cuba.core.entity;
import com.haulmont.chile.core.annotations.NamePattern;
import com.haulmont.cuba.core.entity.annotation.SystemLevel;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Column;
import java.util.Date;
@Entity(name = "sys$Server")
@Table(name = "SYS_SERVER")
@NamePattern("%s|name")
@SystemLevel
public class Server extends BaseUuidEntity implements Updatable {
public class Server extends BaseUuidEntity implements Creatable, Updatable {
private static final long serialVersionUID = 1892335683693067357L;
@Column(name = "CREATE_TS")
protected Date createTs;
@Column(name = "CREATED_BY", length = LOGIN_FIELD_LEN)
protected String createdBy;
@Column(name = "UPDATE_TS")
protected Date updateTs;
@ -47,6 +53,26 @@ public class Server extends BaseUuidEntity implements Updatable {
@Column(name = "DATA")
private String data;
@Override
public Date getCreateTs() {
return createTs;
}
@Override
public void setCreateTs(Date createTs) {
this.createTs = createTs;
}
@Override
public String getCreatedBy() {
return createdBy;
}
@Override
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
@Override
public Date getUpdateTs() {
return updateTs;

View File

@ -26,13 +26,19 @@ import java.util.Date;
* <p/>Optimistically locked, implements Updatable and SoftDelete.
*/
@MappedSuperclass
public class StandardEntity extends BaseUuidEntity implements Versioned, Updatable, SoftDelete {
public class StandardEntity extends BaseUuidEntity implements Versioned, Creatable, Updatable, SoftDelete {
private static final long serialVersionUID = 5642226839555253331L;
@Version
@Column(name = "VERSION", nullable = false)
protected Integer version;
@Column(name = "CREATE_TS")
protected Date createTs;
@Column(name = "CREATED_BY", length = LOGIN_FIELD_LEN)
protected String createdBy;
@Column(name = "UPDATE_TS")
protected Date updateTs;
@ -55,6 +61,26 @@ public class StandardEntity extends BaseUuidEntity implements Versioned, Updatab
this.version = version;
}
@Override
public Date getCreateTs() {
return createTs;
}
@Override
public void setCreateTs(Date createTs) {
this.createTs = createTs;
}
@Override
public String getCreatedBy() {
return createdBy;
}
@Override
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
@Override
public Date getUpdateTs() {
return updateTs;

View File

@ -19,8 +19,7 @@ package com.haulmont.cuba.core.entity;
import java.util.Date;
/**
* Interface to be implemented by entities that support update information saving.
*
* Interface to be implemented by entities that contain information about who updated them and when.
*/
public interface Updatable {

View File

@ -20,7 +20,7 @@ package com.haulmont.cuba.core.entity.diff;
import com.haulmont.chile.core.annotations.MetaClass;
import com.haulmont.chile.core.annotations.MetaProperty;
import com.haulmont.cuba.core.entity.AbstractNotPersistentEntity;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.EntitySnapshot;
import com.haulmont.cuba.core.entity.annotation.SystemLevel;
import com.haulmont.cuba.core.global.View;
@ -45,9 +45,9 @@ public class EntityDiff extends AbstractNotPersistentEntity implements Serializa
private EntitySnapshot afterSnapshot;
private BaseEntity beforeEntity;
private Entity beforeEntity;
private BaseEntity afterEntity;
private Entity afterEntity;
private List<EntityPropertyDiff> propertyDiffs = new ArrayList<>();
@ -79,19 +79,19 @@ public class EntityDiff extends AbstractNotPersistentEntity implements Serializa
this.afterSnapshot = afterSnapshot;
}
public BaseEntity getBeforeEntity() {
public Entity getBeforeEntity() {
return beforeEntity;
}
public void setBeforeEntity(BaseEntity beforeEntity) {
public void setBeforeEntity(Entity beforeEntity) {
this.beforeEntity = beforeEntity;
}
public BaseEntity getAfterEntity() {
public Entity getAfterEntity() {
return afterEntity;
}
public void setAfterEntity(BaseEntity afterEntity) {
public void setAfterEntity(Entity afterEntity) {
this.afterEntity = afterEntity;
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.haulmont.cuba.core.entity.dummy;
import com.haulmont.cuba.core.entity.EmbeddableEntity;
import com.haulmont.cuba.core.entity.annotation.SystemLevel;
import javax.persistence.Embeddable;
@Embeddable
@SystemLevel
public class DummyEmbeddableEntity extends EmbeddableEntity {
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.haulmont.cuba.core.entity.dummy;
import com.haulmont.cuba.core.entity.BaseIdentityIdEntity;
import com.haulmont.cuba.core.entity.BaseLongIdEntity;
import com.haulmont.cuba.core.entity.annotation.SystemLevel;
import javax.persistence.Entity;
@Entity(name = "sys$DummyIdentityIdEntity")
@SystemLevel
public class DummyIdentityIdEntity extends BaseIdentityIdEntity {
}

View File

@ -18,14 +18,11 @@
BaseUuidEntity.id=ID
BaseIntegerIdEntity.id=ID
BaseLongIdEntity.id=ID
BaseGenericIdEntity.createTs=Created At
BaseGenericIdEntity.createdBy=Created By
# keys for BaseUuidEntity, only for backward compatibility
BaseUuidEntity.createTs=Created At
BaseUuidEntity.createdBy=Created By
BaseIdentityIdEntity.id=ID
StandardEntity.version=Version
StandardEntity.createTs=Created At
StandardEntity.createdBy=Created By
StandardEntity.updateTs=Updated At
StandardEntity.updatedBy=Updated By
StandardEntity.deleteTs=Deleted At

View File

@ -197,7 +197,7 @@ public class MetadataTools {
/**
* Determine whether the given property is system-level. A property is considered system if it is defined not
* in an entity class but in one of its base interfaces:
* {@link BaseEntity}, {@link Updatable}, {@link SoftDelete}, {@link Versioned}
* {@link Entity}, {@link Creatable}, {@link Updatable}, {@link SoftDelete}, {@link Versioned}
*/
public boolean isSystem(MetaProperty metaProperty) {
Objects.requireNonNull(metaProperty, "metaProperty is null");
@ -257,7 +257,7 @@ public class MetadataTools {
*/
public boolean isEmbedded(MetaProperty metaProperty) {
Objects.requireNonNull(metaProperty, "metaProperty is null");
return metaProperty.getAnnotatedElement().isAnnotationPresent(Embedded.class);
return Boolean.TRUE.equals(metaProperty.getAnnotations().get("embedded"));
}
/**

View File

@ -18,7 +18,7 @@ package com.haulmont.cuba.core.global;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.chile.core.model.MetaProperty;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Creatable;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.SoftDelete;
import com.haulmont.cuba.core.entity.Updatable;
@ -299,7 +299,7 @@ public class View implements Serializable {
result.add(pkName);
}
addSystemPropertiesFrom(BaseEntity.class, entityClass, metaClass, metadata, result);
addSystemPropertiesFrom(Creatable.class, entityClass, metaClass, metadata, result);
addSystemPropertiesFrom(Updatable.class, entityClass, metaClass, metadata, result);
addSystemPropertiesFrom(SoftDelete.class, entityClass, metaClass, metadata, result);

View File

@ -35,11 +35,12 @@ public class CubaAnnotationsLoader extends JPAAnnotationsLoader {
private static final List<Class> SYSTEM_INTERFACES = Arrays.<Class>asList(
Instance.class,
Entity.class,
BaseEntity.class,
BaseGenericIdEntity.class,
Versioned.class,
Creatable.class,
Updatable.class,
SoftDelete.class
SoftDelete.class,
HasUuid.class
);
public CubaAnnotationsLoader(Session session) {

View File

@ -18,6 +18,7 @@ package com.haulmont.cuba.security.entity;
import com.haulmont.chile.core.annotations.NamePattern;
import com.haulmont.cuba.core.entity.BaseUuidEntity;
import com.haulmont.cuba.core.entity.Creatable;
import com.haulmont.cuba.core.entity.Updatable;
import com.haulmont.cuba.core.entity.annotation.SystemLevel;
@ -31,7 +32,13 @@ import java.util.Date;
@Table(name = "SEC_PRESENTATION")
@NamePattern("%s|name")
@SystemLevel
public class Presentation extends BaseUuidEntity implements Updatable {
public class Presentation extends BaseUuidEntity implements Creatable, Updatable {
@Column(name = "CREATE_TS")
protected Date createTs;
@Column(name = "CREATED_BY", length = LOGIN_FIELD_LEN)
protected String createdBy;
@Column(name = "COMPONENT")
private String componentId;
@ -60,6 +67,26 @@ public class Presentation extends BaseUuidEntity implements Updatable {
private static final long serialVersionUID = -3151934186797540532L;
@Override
public Date getCreateTs() {
return createTs;
}
@Override
public void setCreateTs(Date createTs) {
this.createTs = createTs;
}
@Override
public String getCreatedBy() {
return createdBy;
}
@Override
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Boolean getAutoSave() {
return autoSave;
}

View File

@ -18,6 +18,7 @@ package com.haulmont.cuba.security.entity;
import com.haulmont.chile.core.annotations.MetaProperty;
import com.haulmont.cuba.core.entity.BaseUuidEntity;
import com.haulmont.cuba.core.entity.Creatable;
import com.haulmont.cuba.core.entity.annotation.SystemLevel;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.global.UserFormatTools;
@ -26,6 +27,7 @@ import com.haulmont.cuba.security.global.UserSession;
import javax.annotation.PostConstruct;
import javax.persistence.*;
import java.util.Date;
import java.util.UUID;
/**
@ -35,7 +37,7 @@ import java.util.UUID;
@Entity(name = "sec$ScreenHistory")
@Table(name = "SEC_SCREEN_HISTORY")
@SystemLevel
public class ScreenHistoryEntity extends BaseUuidEntity {
public class ScreenHistoryEntity extends BaseUuidEntity implements Creatable {
private static final long serialVersionUID = 1L;
@ -46,6 +48,12 @@ public class ScreenHistoryEntity extends BaseUuidEntity {
setSubstitutedUser(userSession.getSubstitutedUser());
}
@Column(name = "CREATE_TS")
protected Date createTs;
@Column(name = "CREATED_BY", length = LOGIN_FIELD_LEN)
protected String createdBy;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "USER_ID")
protected User user;
@ -63,6 +71,26 @@ public class ScreenHistoryEntity extends BaseUuidEntity {
@Column(name = "ENTITY_ID")
protected UUID entityId;
@Override
public Date getCreateTs() {
return createTs;
}
@Override
public void setCreateTs(Date createTs) {
this.createTs = createTs;
}
@Override
public String getCreatedBy() {
return createdBy;
}
@Override
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public User getUser() {
return user;
}

View File

@ -26,6 +26,7 @@
<class>com.haulmont.cuba.core.entity.BaseLongIdEntity</class>
<class>com.haulmont.cuba.core.entity.BaseIntegerIdEntity</class>
<class>com.haulmont.cuba.core.entity.BaseStringIdEntity</class>
<class>com.haulmont.cuba.core.entity.BaseIdentityIdEntity</class>
<class>com.haulmont.cuba.core.entity.StandardEntity</class>
<class>com.haulmont.cuba.core.entity.Server</class>
<class>com.haulmont.cuba.core.entity.Config</class>
@ -74,7 +75,9 @@
<class>com.haulmont.cuba.core.entity.dummy.DummyStringIdEntity</class>
<class>com.haulmont.cuba.core.entity.dummy.DummyIntegerIdEntity</class>
<class>com.haulmont.cuba.core.entity.dummy.DummyLongIdEntity</class>
<class>com.haulmont.cuba.core.entity.dummy.DummyIdentityIdEntity</class>
<class>com.haulmont.cuba.core.entity.dummy.DummyCategorizedEntity</class>
<class>com.haulmont.cuba.core.entity.dummy.DummyEmbeddableEntity</class>
<properties>
<property name="eclipselink.weaving"

View File

@ -21,9 +21,9 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.cuba.core.app.dynamicattributes.PropertyType;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.BaseUuidEntity;
import com.haulmont.cuba.core.entity.CategoryAttribute;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.global.*;
import com.haulmont.cuba.gui.ScreensHelper;
import com.haulmont.cuba.gui.components.*;
@ -293,12 +293,12 @@ public class AttributeEditor extends AbstractEditor<CategoryAttribute> {
protected void fillDefaultEntities(Class entityClass) {
String entityClassName = metadata.getClassNN(entityClass).getName();
if (attribute.getDefaultEntityId() != null) {
LoadContext<BaseEntity> entityContext = new LoadContext<>(entityClass);
LoadContext<Entity> entityContext = new LoadContext<>(entityClass);
LoadContext.Query query2 = entityContext.setQueryString("select a from " + entityClassName + " a where a.id =:e");
query2.setParameter("e", attribute.getDefaultEntityId());
entityContext.setView("_minimal");
BaseEntity entity = dataSupplier.load(entityContext);
Entity entity = dataSupplier.load(entityContext);
if (entity != null) {
defaultEntityField.setValue(entity);
} else {

View File

@ -17,7 +17,7 @@
package com.haulmont.cuba.gui.app.core.entitydiff;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.EntitySnapshot;
import com.haulmont.cuba.core.entity.diff.EntityDiff;
import com.haulmont.cuba.core.entity.diff.EntityPropertyDiff;
@ -113,7 +113,7 @@ public class EntityDiffViewer extends AbstractFrame {
diffTable.expandAll();
}
public void loadVersions(BaseEntity entity) {
public void loadVersions(Entity entity) {
snapshotsDs.setEntity(entity);
snapshotsDs.refresh();

View File

@ -18,8 +18,9 @@
package com.haulmont.cuba.gui.app.core.entitydiff;
import com.haulmont.cuba.core.app.EntitySnapshotService;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.EntitySnapshot;
import com.haulmont.cuba.core.entity.HasUuid;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.gui.data.impl.CustomCollectionDatasource;
@ -27,7 +28,7 @@ import java.util.*;
public class EntitySnapshotsDatasource extends CustomCollectionDatasource<EntitySnapshot, UUID> {
protected BaseEntity entity;
protected Entity entity;
protected List<EntitySnapshot> snapshots;
@Override
@ -35,19 +36,19 @@ public class EntitySnapshotsDatasource extends CustomCollectionDatasource<Entity
return false;
}
public BaseEntity getEntity() {
public Entity getEntity() {
return entity;
}
public void setEntity(BaseEntity entity) {
public void setEntity(Entity entity) {
this.entity = entity;
}
@Override
protected Collection<EntitySnapshot> getEntities(Map<String, Object> params) {
if (entity != null) {
if (entity != null && entity instanceof HasUuid) {
EntitySnapshotService snapshotService = AppBeans.get(EntitySnapshotService.NAME);
snapshots = snapshotService.getSnapshots(entity.getMetaClass(), entity.getUuid());
snapshots = snapshotService.getSnapshots(entity.getMetaClass(), ((HasUuid) entity).getUuid());
return snapshots;
}
return Collections.emptyList();

View File

@ -92,13 +92,13 @@ public class EntityParamsDatasource extends CollectionDatasourceImpl<InfoParamEn
includeParam("table.showInfoAction.version", version.toString());
}
if (instance instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) instance;
if (baseEntity.getCreateTs() != null) {
includeParam("table.showInfoAction.createTs", df.format(((BaseEntity) instance).getCreateTs()));
if (instance instanceof Creatable) {
Creatable creatableEntity = (Creatable) instance;
if (creatableEntity.getCreateTs() != null) {
includeParam("table.showInfoAction.createTs", df.format(((Creatable) instance).getCreateTs()));
}
if (baseEntity.getCreatedBy() != null) {
includeParam("table.showInfoAction.createdBy", baseEntity.getCreatedBy());
if (creatableEntity.getCreatedBy() != null) {
includeParam("table.showInfoAction.createdBy", creatableEntity.getCreatedBy());
}
}
@ -127,8 +127,9 @@ public class EntityParamsDatasource extends CollectionDatasourceImpl<InfoParamEn
protected Entity reloadInstance(Entity instance) {
View reloadView = new View(instance.getMetaClass().getJavaClass(), true);
if (instance instanceof BaseEntity) {
reloadView.addProperty("id");
reloadView.addProperty("id");
if (instance instanceof Creatable) {
reloadView.addProperty("createTs");
reloadView.addProperty("createdBy");
}

View File

@ -24,9 +24,6 @@ import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.annotation.SystemLevel;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.global.Metadata;
import com.haulmont.cuba.core.global.UuidProvider;
import java.util.UUID;
@com.haulmont.chile.core.annotations.MetaClass(name = "sec$AbstractTarget")
@SystemLevel
@ -42,8 +39,6 @@ public class AbstractPermissionTarget extends AbstractInstance
@MetaProperty(mandatory = true)
protected String permissionValue;
private UUID uuid = UuidProvider.createUuid();
public AbstractPermissionTarget(String id, String caption) {
this.id = id;
this.caption = caption;
@ -54,11 +49,6 @@ public class AbstractPermissionTarget extends AbstractInstance
return id;
}
@Override
public UUID getUuid() {
return uuid;
}
@Override
public MetaClass getMetaClass() {
return AppBeans.get(Metadata.class).getSession().getClass(getClass());

View File

@ -24,17 +24,12 @@ import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.annotation.SystemLevel;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.global.Metadata;
import com.haulmont.cuba.core.global.UuidProvider;
import java.util.UUID;
@com.haulmont.chile.core.annotations.MetaClass(name = "sec$AttributeTarget")
@SystemLevel
public class AttributeTarget extends AbstractInstance
implements Entity<String> {
private UUID uuid = UuidProvider.createUuid();
@MetaProperty(mandatory = true)
private String id;
@ -50,11 +45,6 @@ public class AttributeTarget extends AbstractInstance
return id;
}
@Override
public UUID getUuid() {
return uuid;
}
@Override
public MetaClass getMetaClass() {
return AppBeans.get(Metadata.class).getSession().getClass(getClass());

View File

@ -17,16 +17,18 @@
package com.haulmont.cuba.gui.data;
import com.haulmont.chile.core.common.ValueListener;
import com.haulmont.chile.core.model.Instance;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesUtils;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.BaseGenericIdEntity;
import com.haulmont.cuba.core.entity.CategoryAttribute;
import com.haulmont.cuba.core.entity.CategoryAttributeValue;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.global.UuidProvider;
import java.util.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* Specific entity, delegating all calls to internal BaseGenericIdEntity.
@ -34,7 +36,7 @@ import java.util.*;
* Obsolete. Will be removed in future releases.
*
*/
public class DynamicAttributesEntity implements BaseEntity {
public class DynamicAttributesEntity implements Entity {
private static final long serialVersionUID = -8091230910619941201L;
protected BaseGenericIdEntity mainItem;
protected UUID id;
@ -53,29 +55,6 @@ public class DynamicAttributesEntity implements BaseEntity {
return id;
}
@Override
public UUID getUuid() {
return id;
}
@Override
public Date getCreateTs() {
return null;
}
@Override
public void setCreateTs(Date date) {
}
@Override
public String getCreatedBy() {
return null;
}
@Override
public void setCreatedBy(String createdBy) {
}
@Override
public MetaClass getMetaClass() {
return mainItem.getMetaClass();

View File

@ -138,19 +138,15 @@ public class CollectionPropertyDatasourceImpl<T extends Entity<K>, K>
public T getItem(K id) {
backgroundWorker.checkUIAccess();
if (id instanceof Entity) {
return (T) id;
} else {
Collection<T> collection = __getCollection();
if (collection != null) {
for (T t : collection) {
if (t.getId().equals(id)) {
return t;
}
Collection<T> collection = __getCollection();
if (collection != null) {
for (T t : collection) {
if (t.getId().equals(id)) {
return t;
}
}
return null;
}
return null;
}
@Override
@ -579,16 +575,12 @@ public class CollectionPropertyDatasourceImpl<T extends Entity<K>, K>
return false;
}
if (itemId instanceof Entity) {
return collection.contains(itemId);
} else {
for (T item : collection) {
if (item.getId().equals(itemId)) {
return true;
}
for (T item : collection) {
if (item.getId().equals(itemId)) {
return true;
}
return false;
}
return false;
}
@Override

View File

@ -22,6 +22,7 @@ import com.haulmont.cuba.client.sys.cache.ClientCacheManager;
import com.haulmont.cuba.core.app.DataService;
import com.haulmont.cuba.core.app.DomainDescriptionService;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.entity.HasUuid;
import com.haulmont.cuba.core.global.*;
import com.haulmont.cuba.core.sys.AbstractViewRepository;
import com.haulmont.cuba.security.entity.EntityOp;
@ -315,9 +316,11 @@ public class DataServiceController {
for (Object id : newInstanceIds) {
for (Object instance : commitInstances) {
Entity entity = (Entity) instance;
String entityFullId = EntityLoadInfo.create(entity).toString();
if (entityFullId.equals(id) && entity.getUuid() == null) {
entity.setValue("uuid", UuidProvider.createUuid());
if (entity instanceof HasUuid) {
String entityFullId = EntityLoadInfo.create(entity).toString();
if (entityFullId.equals(id) && ((HasUuid) entity).getUuid() == null) {
((HasUuid) entity).setUuid(UuidProvider.createUuid());
}
}
}
}