Merged from release 5_6 [24009] [24022] [24025] [24029] [24030]

PL-6271 RuntimePropertiesDatasource does not update attributes in DynamicAttributesEntity after main entity updated
#PL-6271
This commit is contained in:
Eugeny Degtyarjov 2015-11-09 06:11:21 +00:00
parent 53d24315dd
commit d5bb032088
6 changed files with 175 additions and 417 deletions

View File

@ -13,6 +13,7 @@ import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.global.Metadata;
import com.haulmont.cuba.core.global.PersistenceHelper;
import com.haulmont.cuba.core.global.TimeSource;
import org.apache.commons.lang.ObjectUtils;
import javax.annotation.Nullable;
import javax.persistence.Column;
@ -151,48 +152,52 @@ public abstract class BaseGenericIdEntity<T> extends AbstractInstance implements
}
@Override
public void setValue(String property, Object obj, boolean checkEquals) {
public void setValue(String property, Object newValue, boolean checkEquals) {
if (DynamicAttributesUtils.isDynamicAttribute(property)) {
Preconditions.checkState(dynamicAttributes != null, "Dynamic attributes should be loaded explicitly");
String attributeCode = DynamicAttributesUtils.decodeAttributeCode(property);
CategoryAttributeValue categoryAttributeValue = dynamicAttributes.get(attributeCode);
if (categoryAttributeValue != null) {
if (obj != null) {
categoryAttributeValue.setValue(obj);
categoryAttributeValue.setDeleteTs(null);
} else {
Object oldValue = categoryAttributeValue != null ? categoryAttributeValue.getValue() : null;
if (newValue == null) {
if (categoryAttributeValue != null) {
categoryAttributeValue.setValue(null);
categoryAttributeValue.setDeleteTs(AppBeans.get(TimeSource.class).currentTimestamp());
propertyChanged(property, oldValue, null);
}
} else if (obj != null) {
categoryAttributeValue = new CategoryAttributeValue();
categoryAttributeValue.setValue(obj);
categoryAttributeValue.setEntityId(getUuid());
categoryAttributeValue.setCode(attributeCode);
DynamicAttributes dynamicAttributesBean = AppBeans.get(DynamicAttributes.NAME);
categoryAttributeValue.setCategoryAttribute(
dynamicAttributesBean.getAttributeForMetaClass(getMetaClass(), attributeCode));
dynamicAttributes.put(attributeCode, categoryAttributeValue);
} else if (!ObjectUtils.equals(oldValue, newValue)) {
if (categoryAttributeValue != null) {
categoryAttributeValue.setValue(newValue);
categoryAttributeValue.setDeleteTs(null);
} else {
categoryAttributeValue = new CategoryAttributeValue();
categoryAttributeValue.setValue(newValue);
categoryAttributeValue.setEntityId(getUuid());
categoryAttributeValue.setCode(attributeCode);
DynamicAttributes dynamicAttributesBean = AppBeans.get(DynamicAttributes.NAME);
categoryAttributeValue.setCategoryAttribute(
dynamicAttributesBean.getAttributeForMetaClass(getMetaClass(), attributeCode));
dynamicAttributes.put(attributeCode, categoryAttributeValue);
}
propertyChanged(property, null, newValue);
}
propertyChanged(property, null, obj);
} else {
super.setValue(property, obj, checkEquals);
super.setValue(property, newValue, checkEquals);
}
}
@Override
@SuppressWarnings("unchecked")
public <V> V getValue(String property) {
public <T> T getValue(String property) {
if (DynamicAttributesUtils.isDynamicAttribute(property)) {
if (PersistenceHelper.isNew(this) && dynamicAttributes == null) {
dynamicAttributes = new HashMap<>();
dynamicAttributes = new HashMap<>();
}
Preconditions.checkState(dynamicAttributes != null, "Dynamic attributes should be loaded explicitly");
CategoryAttributeValue categoryAttributeValue = dynamicAttributes.get(DynamicAttributesUtils.decodeAttributeCode(property));
if (categoryAttributeValue != null) {
return (V) categoryAttributeValue.getValue();
return (T) categoryAttributeValue.getValue();
} else {
return null;
}
@ -209,20 +214,4 @@ public abstract class BaseGenericIdEntity<T> extends AbstractInstance implements
public Map<String, CategoryAttributeValue> getDynamicAttributes() {
return dynamicAttributes;
}
@Override
public String toString() {
String state = "";
if (__new)
state += "new,";
if (__managed)
state += "managed,";
if (__detached)
state += "detached,";
if (__removed)
state += "removed,";
if (state.length() > 0)
state = state.substring(0, state.length() - 1);
return super.toString() + " [" + state + "]";
}
}

View File

@ -12,10 +12,10 @@ 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.app.dynamicattributes.DynamicAttributes;
import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesMetaProperty;
import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesUtils;
import com.haulmont.cuba.core.app.dynamicattributes.PropertyType;
import com.haulmont.cuba.core.entity.CategoryAttribute;
import com.haulmont.cuba.core.entity.CategoryAttributeValue;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.global.DevelopmentException;
import com.haulmont.cuba.core.global.View;
@ -26,7 +26,10 @@ import com.haulmont.cuba.gui.components.validators.DoubleValidator;
import com.haulmont.cuba.gui.components.validators.IntegerValidator;
import com.haulmont.cuba.gui.components.validators.LongValidator;
import com.haulmont.cuba.gui.config.WindowConfig;
import com.haulmont.cuba.gui.data.*;
import com.haulmont.cuba.gui.data.CollectionDatasource;
import com.haulmont.cuba.gui.data.Datasource;
import com.haulmont.cuba.gui.data.DsBuilder;
import com.haulmont.cuba.gui.data.RuntimePropsDatasource;
import com.haulmont.cuba.gui.xml.layout.ComponentsFactory;
import org.apache.commons.lang.StringUtils;
@ -158,12 +161,11 @@ public class RuntimePropertiesFrame extends AbstractWindow {
protected java.util.List<FieldGroup.FieldConfig> createFieldsForAttributes() {
@SuppressWarnings("unchecked")
Collection<MetaProperty> metaProperties = rds.getPropertiesFilteredByCategory();
Collection<DynamicAttributesMetaProperty> metaProperties = rds.getPropertiesFilteredByCategory();
java.util.List<FieldGroup.FieldConfig> fields = new ArrayList<>();
for (MetaProperty property : metaProperties) {
for (DynamicAttributesMetaProperty property : metaProperties) {
FieldGroup.FieldConfig field = new FieldGroup.FieldConfig(property.getName());
CategoryAttribute attribute = dynamicAttributes
.getAttributeForMetaClass(rds.resolveCategorizedEntityClass(), property.getName());
CategoryAttribute attribute = property.getAttribute();
field.setCaption(attribute != null ? attribute.getName() : property.getName());
field.setWidth(fieldWidth);
fields.add(field);
@ -204,16 +206,15 @@ public class RuntimePropertiesFrame extends AbstractWindow {
protected void initCustomFields(FieldGroup component, java.util.List<FieldGroup.FieldConfig> fields, final Datasource ds) {
@SuppressWarnings("unchecked")
Collection<MetaProperty> metaProperties = rds.getPropertiesFilteredByCategory();
for (final MetaProperty metaProperty : metaProperties) {
Collection<DynamicAttributesMetaProperty> metaProperties = rds.getPropertiesFilteredByCategory();
for (final DynamicAttributesMetaProperty metaProperty : metaProperties) {
Range range = metaProperty.getRange();
if (!range.isDatatype()) {
component.addCustomField(metaProperty.getName(), new FieldGroup.CustomFieldGenerator() {
@Override
public Component generateField(Datasource datasource, String propertyId) {
final PickerField pickerField;
Boolean lookup = ((DynamicAttributesEntity) datasource.getItem())
.getCategoryValue(metaProperty.getName()).getCategoryAttribute().getLookup();
Boolean lookup = metaProperty.getAttribute().getLookup();
if (lookup != null && lookup) {
pickerField = componentsFactory.createComponent(LookupPickerField.class);
@ -236,16 +237,12 @@ public class RuntimePropertiesFrame extends AbstractWindow {
pickerField.setDatasource(ds, propertyId);
LookupAction lookupAction = (LookupAction) pickerField.getAction(LookupAction.NAME);
if (lookupAction != null) {
DynamicAttributesEntity dynamicAttributesEntity = (DynamicAttributesEntity) ds.getItem();
CategoryAttributeValue categoryAttributeValue = dynamicAttributesEntity.getCategoryValue(metaProperty.getName());
if (categoryAttributeValue != null) {
String screen = categoryAttributeValue.getCategoryAttribute().getScreen();
if (StringUtils.isBlank(screen)) {
WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME);
screen = windowConfig.getBrowseScreenId(pickerField.getMetaClass());
}
lookupAction.setLookupScreen(screen);
String screen = metaProperty.getAttribute().getScreen();
if (StringUtils.isBlank(screen)) {
WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME);
screen = windowConfig.getBrowseScreenId(pickerField.getMetaClass());
}
lookupAction.setLookupScreen(screen);
}
pickerField.addOpenAction();
pickerField.setWidth(fieldWidth);
@ -312,15 +309,16 @@ public class RuntimePropertiesFrame extends AbstractWindow {
}
protected void loadRequired(FieldGroup fieldGroup, FieldGroup.FieldConfig field) {
DynamicAttributesEntity dynamicAttributesEntity = (DynamicAttributesEntity) rds.getItem();
CategoryAttributeValue categoryAttributeValue = dynamicAttributesEntity.getCategoryValue(field.getId());
String requiredMessage = messages.formatMessage(
AppConfig.getMessagesPack(),
"validation.required.defaultMsg",
categoryAttributeValue.getCategoryAttribute().getName()
);
fieldGroup.setRequired(field,
Boolean.TRUE.equals(categoryAttributeValue.getCategoryAttribute().getRequired()) && requiredControlEnabled, requiredMessage);
CategoryAttribute attribute = dynamicAttributes.getAttributeForMetaClass(rds.getMainDs().getMetaClass(), field.getId());
if (attribute != null) {
String requiredMessage = messages.formatMessage(
AppConfig.getMessagesPack(),
"validation.required.defaultMsg",
attribute.getName()
);
fieldGroup.setRequired(field,
Boolean.TRUE.equals(attribute.getRequired()) && requiredControlEnabled, requiredMessage);
}
}
public void setCategoryFieldVisible(boolean visible) {

View File

@ -5,51 +5,36 @@
package com.haulmont.cuba.gui.data;
import com.haulmont.chile.core.common.ValueListener;
import com.haulmont.chile.core.common.compatibility.InstancePropertyChangeListenerWrapper;
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.app.dynamicattributes.PropertyType;
import com.haulmont.cuba.core.entity.BaseEntity;
import com.haulmont.cuba.core.entity.CategoryAttribute;
import com.haulmont.cuba.core.entity.BaseGenericIdEntity;
import com.haulmont.cuba.core.entity.CategoryAttributeValue;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.global.UuidProvider;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
/**
* The entity, that contains a set of dynamic attributes.
* Specific entity, delegating all calls to internal BaseGenericIdEntity.
*
* Obsolete. Will be removed in future releases.
*
* @author devyatkin
* @version $Id$
*/
public class DynamicAttributesEntity implements BaseEntity {
private static final long serialVersionUID = -8091230910619941201L;
protected MetaClass metaClass;
protected BaseGenericIdEntity mainItem;
protected UUID id;
protected Map<String, Object> changed = new HashMap<>();
protected Collection<WeakReference<PropertyChangeListener>> __valueListeners;
protected Map<String, CategoryAttributeValue> categoryValues = new HashMap<>();
protected Map<String, Object> values = new HashMap<>();
public DynamicAttributesEntity(MetaClass metaClass) {
this.metaClass = metaClass;
public DynamicAttributesEntity(BaseGenericIdEntity mainItem) {
this.mainItem = mainItem;
this.id = UuidProvider.createUuid();
}
public void addAttributeValue(CategoryAttribute attribute, CategoryAttributeValue categoryAttributeValue, Object value) {
String attributeCode = DynamicAttributesUtils.encodeAttributeCode(attribute.getCode());
categoryValues.put(attributeCode, categoryAttributeValue);
values.put(attributeCode, value);
}
@Override
public UUID getId() {
return id;
@ -80,7 +65,7 @@ public class DynamicAttributesEntity implements BaseEntity {
@Override
public MetaClass getMetaClass() {
return metaClass;
return mainItem.getMetaClass();
}
@Override
@ -90,142 +75,54 @@ public class DynamicAttributesEntity implements BaseEntity {
@Override
public void addListener(com.haulmont.chile.core.common.ValueListener listener) {
addPropertyChangeListener(new InstancePropertyChangeListenerWrapper(listener));
mainItem.addListener(listener);
}
@Override
public void removeListener(ValueListener listener) {
removePropertyChangeListener(new InstancePropertyChangeListenerWrapper(listener));
mainItem.removeListener(listener);
}
@Override
public void addPropertyChangeListener(PropertyChangeListener listener) {
if (__valueListeners == null) {
__valueListeners = new ArrayList<>();
}
__valueListeners.add(new WeakReference<>(listener));
mainItem.addPropertyChangeListener(listener);
}
@Override
public void removePropertyChangeListener(PropertyChangeListener listener) {
if (__valueListeners != null) {
for (Iterator<WeakReference<PropertyChangeListener>> it = __valueListeners.iterator(); it.hasNext(); ) {
PropertyChangeListener iteratorListener = it.next().get();
if (iteratorListener == null || iteratorListener.equals(listener)) {
it.remove();
}
}
}
mainItem.removePropertyChangeListener(listener);
}
@Override
public void removeAllListeners() {
if (__valueListeners != null) {
__valueListeners.clear();
}
}
protected void propertyChanged(String s, Object prev, Object curr) {
if (__valueListeners != null) {
for (WeakReference<PropertyChangeListener> reference : new ArrayList<>(__valueListeners)) {
PropertyChangeListener listener = reference.get();
if (listener == null) {
__valueListeners.remove(reference);
} else {
listener.propertyChanged(new PropertyChangeEvent(this, s, prev, curr));
}
}
}
mainItem.removeAllListeners();
}
@Override
@SuppressWarnings("unchecked")
public <T> T getValue(String name) {
return (T) values.get(name);
return (T) mainItem.getValue(name);
}
@Override
public void setValue(String name, Object value) {
Object oldValue = values.get(name);
if (!ObjectUtils.equals(oldValue, value)) {
values.put(name, value);
changed.put(name, value);
CategoryAttributeValue categoryValue = categoryValues.get(name);
if (value != null) {
if (BaseEntity.class.isAssignableFrom(value.getClass())) {
categoryValue.setEntityValue(((Entity) value).getUuid());
} else {
setValue(categoryValue, value);
}
} else {
setValue(categoryValue, null);
}
propertyChanged(name, oldValue, value);
}
mainItem.setValue(name, value);
}
@Override
@SuppressWarnings("unchecked")
public <T> T getValueEx(String propertyPath) {
return (T) values.get(propertyPath);
return (T) mainItem.getValueEx(propertyPath);
}
@Override
public void setValueEx(String propertyPath, Object value) {
Object oldValue = values.get(propertyPath);
if (!ObjectUtils.equals(oldValue, value)) {
values.put(propertyPath, value);
changed.put(propertyPath, value);
CategoryAttributeValue attrValue = categoryValues.get(propertyPath);
if (value != null) {
if (Entity.class.isAssignableFrom(value.getClass())) {
attrValue.setEntityValue(((Entity) value).getUuid());
} else {
setValue(attrValue, value);
}
} else {
setValue(attrValue, null);
}
propertyChanged(propertyPath, oldValue, value);
}
mainItem.setValueEx(propertyPath, value);
}
@SuppressWarnings("unchecked")
public CategoryAttributeValue getCategoryValue(String name) {
return categoryValues.get(name);
}
private void setValue(CategoryAttributeValue attrValue, Object value) {
if (attrValue.getCategoryAttribute().getIsEntity()) {
attrValue.setEntityValue((UUID) value);
} else {
PropertyType propertyType = attrValue.getCategoryAttribute().getDataType();
switch (propertyType) {
case INTEGER:
attrValue.setIntValue((Integer) value);
break;
case DOUBLE:
attrValue.setDoubleValue((Double) value);
break;
case BOOLEAN:
attrValue.setBooleanValue((Boolean) value);
break;
case DATE:
attrValue.setDateValue((Date) value);
break;
case STRING:
case ENUMERATION:
attrValue.setStringValue(StringUtils.trimToNull((String) value));
break;
case ENTITY:
attrValue.setEntityValue((UUID) value);
break;
}
}
}
public void updateAttributeValue(CategoryAttributeValue attributeValue) {
CategoryAttribute attribute = attributeValue.getCategoryAttribute();
String attributeCode = DynamicAttributesUtils.encodeAttributeCode(attribute.getCode());
categoryValues.put(attributeCode, attributeValue);
Map<String, CategoryAttributeValue> dynamicAttributes = mainItem.getDynamicAttributes();
return dynamicAttributes != null ? dynamicAttributes.get(DynamicAttributesUtils.decodeAttributeCode(name)) : null;
}
}

View File

@ -7,6 +7,7 @@ package com.haulmont.cuba.gui.data;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.chile.core.model.MetaProperty;
import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesMetaProperty;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.global.View;
@ -20,9 +21,7 @@ public interface RuntimePropsDatasource<T extends Entity> extends Datasource<T>
Datasource getMainDs();
Collection<MetaProperty> getPropertiesFilteredByCategory();
View getAttributeValueView();
Collection<DynamicAttributesMetaProperty> getPropertiesFilteredByCategory();
MetaClass resolveCategorizedEntityClass();
}

View File

@ -288,10 +288,6 @@ public class DsContextImpl implements DsContextImplementation {
entities.add(entity);
views.put(entity, datasource.getView());
if (datasource instanceof RuntimePropsDatasource) {
views.put(entity, ((RuntimePropsDatasource) datasource).getAttributeValueView());
}
}
// Replace the reference to master entity with actual entity containing in the master datasource,

View File

@ -10,13 +10,15 @@ import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.chile.core.model.MetaProperty;
import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributes;
import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesMetaClass;
import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesMetaProperty;
import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesUtils;
import com.haulmont.cuba.core.app.dynamicattributes.PropertyType;
import com.haulmont.cuba.core.entity.*;
import com.haulmont.cuba.core.global.*;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.global.DevelopmentException;
import com.haulmont.cuba.core.global.PersistenceHelper;
import com.haulmont.cuba.core.global.View;
import com.haulmont.cuba.gui.data.*;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import com.haulmont.cuba.gui.dynamicattributes.DynamicAttributesGuiTools;
import javax.annotation.Nullable;
import java.util.*;
@ -34,6 +36,7 @@ public class RuntimePropsDatasourceImpl
protected DsContext dsContext;
protected DataSupplier dataSupplier;
protected DynamicAttributesGuiTools dynamicAttributesGuiTools;
protected DynamicAttributesMetaClass metaClass;
protected View view;
protected Datasource mainDs;
@ -47,39 +50,23 @@ public class RuntimePropsDatasourceImpl
protected Category category;
protected final Collection<CategoryAttribute> attributes;
protected final View attributeValueView;
public RuntimePropsDatasourceImpl(DsContext dsContext, DataSupplier dataSupplier, String id, String mainDsId, @Nullable MetaClass categorizedEntityClass) {
this.categorizedEntityClass = categorizedEntityClass;
this.id = id;
this.dsContext = dsContext;
this.dataSupplier = dataSupplier;
this.dynamicAttributesGuiTools = AppBeans.get(DynamicAttributesGuiTools.NAME);
this.metaClass = new DynamicAttributesMetaClass();
this.setMainDs(mainDsId);
this.setCommitMode(CommitMode.DATASTORE);
attributes = AppBeans.get(DynamicAttributes.class).getAttributesForMetaClass(resolveCategorizedEntityClass());
this.attributes = AppBeans.get(DynamicAttributes.NAME, DynamicAttributes.class).getAttributesForMetaClass(resolveCategorizedEntityClass());
for (CategoryAttribute attribute : attributes) {
MetaProperty metaProperty = DynamicAttributesUtils.getMetaPropertyPath(mainDs.getMetaClass(), attribute).getMetaProperty();
this.metaClass.addProperty(metaProperty, attribute);
}
//noinspection unchecked
mainDs.addItemPropertyChangeListener(e -> {
if (e.getProperty().equals("category")) {
categoryChanged = true;
initMetaClass();
}
});
mainDs.setLoadDynamicAttributes(true);
ViewRepository viewRepository = AppBeans.get(ViewRepository.NAME);
View baseAttributeValueView = viewRepository.getView(CategoryAttributeValue.class, View.LOCAL);
View baseAttributeView = viewRepository.getView(CategoryAttribute.class, View.LOCAL);
attributeValueView = new View(baseAttributeValueView, null, false)
.addProperty("categoryAttribute", new View(baseAttributeView, null, false).addProperty("category"));
}
@Override
@ -88,88 +75,6 @@ public class RuntimePropsDatasourceImpl
throw new UnsupportedOperationException();
}
protected void initMetaClass() {
Entity entity = mainDs.getItem();
if (!(entity instanceof BaseGenericIdEntity)) {
throw new IllegalStateException("This datasource can contain only entity with subclass of BaseGenericIdEntity");
}
BaseGenericIdEntity baseGenericIdEntity = (BaseGenericIdEntity) entity;
if (PersistenceHelper.isNew(baseGenericIdEntity)) {
baseGenericIdEntity.setDynamicAttributes(new HashMap<>());
}
@SuppressWarnings("unchecked")
Map<String, CategoryAttributeValue> dynamicAttributes = baseGenericIdEntity.getDynamicAttributes();
Preconditions.checkNotNullArgument(dynamicAttributes, "Dynamic attributes should be loaded explicitly");
if (entity instanceof Categorized) {
category = ((Categorized) entity).getCategory();
}
if (!initializedBefore && category == null) {
category = getDefaultCategory();
if (entity.getMetaClass().getProperty("category") != null) {
entity.setValue("category", category);
}
}
item = new DynamicAttributesEntity(metaClass);
Collection<CategoryAttributeValue> entityValues = dynamicAttributes.values();
TimeSource timeSource = AppBeans.get(TimeSource.NAME);
for (CategoryAttribute attribute : attributes) {
if (!attribute.getCategory().equals(category)) {
continue;
}
CategoryAttributeValue attributeValue = getValue(attribute, entityValues);
Object value;
if (attributeValue == null) {
attributeValue = new CategoryAttributeValue();
dynamicAttributes.put(attribute.getCode(), attributeValue);
attributeValue.setCode(DynamicAttributesUtils.decodeAttributeCode(attribute.getCode()));
attributeValue.setCategoryAttribute(attribute);
attributeValue.setEntityId(entity.getUuid());
if (PersistenceHelper.isNew(entity) || categoryChanged) {
attributeValue.setStringValue(StringUtils.trimToNull(attribute.getDefaultString()));
attributeValue.setIntValue(attribute.getDefaultInt());
attributeValue.setDoubleValue(attribute.getDefaultDouble());
attributeValue.setBooleanValue(attribute.getDefaultBoolean());
attributeValue.setDateValue(BooleanUtils.isTrue(attribute.getDefaultDateIsCurrent()) ?
timeSource.currentTimestamp() : attribute.getDefaultDate());
attributeValue.setEntityValue(attribute.getDefaultEntityId());
value = parseValue(attribute, attributeValue);
} else {
value = null;
}
} else {
value = parseValue(attribute, attributeValue);
}
item.addAttributeValue(attribute, attributeValue, value);
}
view = new View(DynamicAttributesEntity.class);
Collection<MetaProperty> properties = metaClass.getProperties();
for (MetaProperty property : properties) {
view.addProperty(property.getName());
}
item.addPropertyChangeListener(listener);
item.addPropertyChangeListener(e -> {
modified = true;
//noinspection unchecked
itemsToUpdate.add(item.getCategoryValue(e.getProperty()));
});
this.valid();
initializedBefore = true;
if (!itemsToDelete.isEmpty()) {
modified = true;
}
fireItemChanged(null);
}
@Override
public MetaClass resolveCategorizedEntityClass() {
if (categorizedEntityClass == null) {
return mainDs.getMetaClass();
@ -178,60 +83,6 @@ public class RuntimePropsDatasourceImpl
}
}
protected CategoryAttributeValue getValue(CategoryAttribute attribute, Collection<CategoryAttributeValue> entityValues) {
for (CategoryAttributeValue attrValue : entityValues) {
if (attrValue.getCategoryAttribute().equals(attribute))
return attrValue;
}
return null;
}
protected Object parseValue(CategoryAttribute attribute, CategoryAttributeValue attrValue) {
PropertyType dataType = attribute.getDataType();
if (BooleanUtils.isTrue(attribute.getIsEntity())) {
if (attrValue != null) {
UUID entityId = attrValue.getEntityValue();
return parseEntity(attribute.getEntityClass(), entityId);
} else {
UUID entityId = attribute.getDefaultEntityId();
return parseEntity(attribute.getEntityClass(), entityId);
}
} else {
switch (dataType) {
case STRING:
case ENUMERATION:
return attrValue != null ? attrValue.getStringValue() : attribute.getDefaultString();
case INTEGER:
return attrValue != null ? attrValue.getIntValue() : attribute.getDefaultInt();
case DOUBLE:
return attrValue != null ? attrValue.getDoubleValue() : attribute.getDefaultDouble();
case BOOLEAN:
return attrValue != null ? attrValue.getBooleanValue() : attribute.getDefaultBoolean();
case DATE:
return attrValue != null ? attrValue.getDateValue() : attribute.getDefaultDate();
}
}
return attrValue.getStringValue();
}
protected Entity parseEntity(String entityType, UUID uuid) {
try {
Class clazz = Class.forName(entityType);
String entityClassName = metadata.getSession().getClassNN(clazz).getName();
LoadContext entitiesContext = LoadContext.create(clazz)
.setQuery(LoadContext.createQuery("select a from " + entityClassName + " a where a.id =:e")
.setParameter("e", uuid))
.setView(View.LOCAL)
.setSoftDeletion(false);
Entity entity = dataSupplier.load(entitiesContext);
return entity;
} catch (ClassNotFoundException e) {
throw new RuntimeException("can't parse entity " + entityType + " " + uuid, e);
}
}
@Override
public DsContext getDsContext() {
return dsContext;
@ -244,24 +95,7 @@ public class RuntimePropsDatasourceImpl
@Override
public void commit() {
if (!allowCommit)
return;
if (Datasource.CommitMode.DATASTORE.equals(getCommitMode())) {
Set<Entity> commitInstances = new HashSet<>();
Set<Entity> deleteInstances = new HashSet<>();
commitInstances.addAll(itemsToCreate);
commitInstances.addAll(itemsToUpdate);
deleteInstances.addAll(itemsToDelete);
CommitContext cc = new CommitContext(commitInstances, deleteInstances);
Set<Entity> entities = getDataSupplier().commit(cc);
committed(entities);
} else {
throw new UnsupportedOperationException();
}
//just do nothing
}
@Override
@ -301,7 +135,7 @@ public class RuntimePropsDatasourceImpl
@Override
public void refresh() {
initMetaClass();
initMetaClass(mainDs.getItem());
}
@Override
@ -314,11 +148,6 @@ public class RuntimePropsDatasourceImpl
return null; // null is correct
}
@Override
public View getAttributeValueView() {
return attributeValueView;
}
@Override
public void initialized() {
final State prev = state;
@ -335,55 +164,29 @@ public class RuntimePropsDatasourceImpl
@Override
public void committed(Set<Entity> entities) {
if (state != State.VALID) {
if (!State.VALID.equals(state)) {
return;
}
for (Entity entity : entities) {
if (entity instanceof CategoryAttributeValue) {
CategoryAttributeValue attributeValue = (CategoryAttributeValue) entity;
item.updateAttributeValue(attributeValue);
Entity mainItem = mainDs.getItem();
if (mainItem instanceof BaseGenericIdEntity) {
BaseGenericIdEntity baseGenericIdEntity = (BaseGenericIdEntity) mainItem;
if (baseGenericIdEntity.getDynamicAttributes() == null) {
baseGenericIdEntity.setDynamicAttributes(new HashMap<>());
}
baseGenericIdEntity.getDynamicAttributes().put(attributeValue.getCode(), attributeValue);
}
if (entity.equals(mainDs.getItem())) {
initMetaClass(entity);
}
}
modified = false;
clearCommitLists();
}
protected void setMainDs(String name) {
mainDs = dsContext.get(name);
if (mainDs == null) {
throw new DevelopmentException("runtimePropsDatasource initialization error: mainDs '" + name + "' does not exists");
}
//noinspection unchecked
mainDs.addStateChangeListener(e -> {
if (e.getState() == State.VALID) {
if (e.getPrevState() != State.VALID) {
initMetaClass();
} else {
valid();
}
}
});
}
@Override
public Datasource getMainDs() {
return mainDs;
}
@Override
public Collection<MetaProperty> getPropertiesFilteredByCategory() {
return metaClass.getPropertiesFilteredByCategory(category);
@SuppressWarnings("unchecked")
public Collection<DynamicAttributesMetaProperty> getPropertiesFilteredByCategory() {
Collection propertiesFilteredByCategory = metaClass.getPropertiesFilteredByCategory(category);
return (Collection<DynamicAttributesMetaProperty>) propertiesFilteredByCategory;
}
@Nullable
@ -398,4 +201,80 @@ public class RuntimePropsDatasourceImpl
return null;
}
protected void setMainDs(String name) {
mainDs = dsContext.get(name);
if (mainDs == null) {
throw new DevelopmentException("runtimePropsDatasource initialization error: mainDs '" + name + "' does not exists");
}
mainDs.setLoadDynamicAttributes(true);
dynamicAttributesGuiTools.listenDynamicAttributesChanges(mainDs);
//noinspection unchecked
mainDs.addListener(
new DsListenerAdapter() {
@Override
public void stateChanged(Datasource ds, State prevState, State state) {
if (State.VALID.equals(state)) {
if (!State.VALID.equals(prevState))
initMetaClass(mainDs.getItem());
else
valid();
}
}
@Override
public void valueChanged(Entity source, String property, Object prevValue, Object value) {
if (property.equals("category")) {
categoryChanged = true;
initMetaClass(mainDs.getItem());
}
}
@Override
public void itemChanged(Datasource ds, @Nullable Entity prevItem, @Nullable Entity item) {
initMetaClass(item);
}
}
);
}
protected void initMetaClass(Entity entity) {
if (!(entity instanceof BaseGenericIdEntity)) {
throw new IllegalStateException("This datasource can contain only entity with subclass of BaseGenericIdEntity");
}
BaseGenericIdEntity baseGenericIdEntity = (BaseGenericIdEntity) entity;
if (PersistenceHelper.isNew(baseGenericIdEntity) && baseGenericIdEntity.getDynamicAttributes() == null) {
baseGenericIdEntity.setDynamicAttributes(new HashMap<>());
}
@SuppressWarnings("unchecked")
Map<String, CategoryAttributeValue> dynamicAttributes = baseGenericIdEntity.getDynamicAttributes();
Preconditions.checkNotNullArgument(dynamicAttributes, "Dynamic attributes should be loaded explicitly");
if (baseGenericIdEntity instanceof Categorized) {
category = ((Categorized) baseGenericIdEntity).getCategory();
}
if (!initializedBefore && category == null) {
category = getDefaultCategory();
if (baseGenericIdEntity.getMetaClass().getProperty("category") != null) {
baseGenericIdEntity.setValue("category", category);
}
}
item = new DynamicAttributesEntity(baseGenericIdEntity);
dynamicAttributesGuiTools.initDefaultAttributeValues(baseGenericIdEntity);
view = new View(DynamicAttributesEntity.class);
Collection<MetaProperty> properties = metaClass.getProperties();
for (MetaProperty property : properties) {
view.addProperty(property.getName());
}
valid();
initializedBefore = true;
fireItemChanged(null);
}
}