mirror of
https://gitee.com/jmix/cuba.git
synced 2024-11-30 18:27:56 +08:00
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:
parent
53d24315dd
commit
d5bb032088
@ -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 + "]";
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user