use of io.jmix.core.metamodel.model.MetaProperty in project jmix by jmix-framework.
the class BulkEditorWindow method getManagedFields.
protected List<ManagedField> getManagedFields(MetaClass metaClass) {
List<ManagedField> managedFields = new ArrayList<>();
// sort Fields
for (MetaProperty metaProperty : metaClass.getProperties()) {
if (isManagedAttribute(metaClass, metaProperty)) {
String propertyCaption = messageTools.getPropertyCaption(metaClass, metaProperty.getName());
if (!metadataTools.isEmbedded(metaProperty)) {
managedFields.add(new ManagedField(metaProperty.getName(), metaProperty, propertyCaption, null));
} else {
List<ManagedField> nestedFields = getManagedFields(metaProperty, metaProperty.getName(), propertyCaption);
if (nestedFields.size() > 0) {
managedEmbeddedProperties.add(metaProperty.getName());
}
managedFields.addAll(nestedFields);
}
}
}
/*if (loadDynamicAttributes) {
List<CategoryAttribute> categoryAttributes = (List<CategoryAttribute>) dynamicAttributes.getAttributesForMetaClass(metaClass);
if (!categoryAttributes.isEmpty()) {
for (CategoryAttribute attribute : categoryAttributes) {
MetaPropertyPath metaPropertyPath = DynamicAttributesUtils.getMetaPropertyPath(metaClass, attribute);
String propertyCaption = attribute.getLocaleName();
if (isManagedDynamicAttribute(metaClass, metaPropertyPath.getMetaProperty())) {
managedFields.add(new ManagedField(metaPropertyPath.getMetaProperty().getName(), metaPropertyPath.getMetaProperty(),
propertyCaption, null));
}
}
}
}*/
return managedFields;
}
use of io.jmix.core.metamodel.model.MetaProperty in project jmix by jmix-framework.
the class BulkEditorWindow method createDataComponents.
@SuppressWarnings("unchecked")
protected void createDataComponents() {
if (managedFields.isEmpty()) {
infoLabel.setValue(messages.getMessage("io.jmix.ui.app.bulk/bulk.noEditableProperties"));
applyButton.setVisible(false);
return;
}
List<ManagedField> editFields = new ArrayList<>(managedFields.values());
// sort fields
Comparator comparator;
if (fieldSorter != null) {
Map<MetaProperty, Integer> sorted = fieldSorter.apply(editFields.stream().map(ManagedField::getMetaProperty).collect(Collectors.toList()));
comparator = Comparator.<ManagedField>comparingInt(item -> sorted.get(item.getMetaProperty()));
} else {
comparator = Comparator.comparing(ManagedField::getLocalizedName);
}
editFields.sort(comparator);
CssLayout fieldsLayout = uiComponents.create(CssLayout.NAME);
fieldsLayout.setStyleName("jmix-bulk-editor-fields-layout");
fieldsLayout.setWidthFull();
fieldsLayout.setHeightFull();
int fromField;
int toField = 0;
int addedColumns = 0;
for (int col = 0; col < columnsMode.getColumnsCount(); col++) {
fromField = toField;
toField += getFieldsCountForColumn(editFields.size() - toField, columnsMode.getColumnsCount() - col);
DeviceInfo deviceInfo = deviceInfoProvider.getDeviceInfo();
VBoxLayout column = uiComponents.create(VBoxLayout.NAME);
column.setStyleName("jmix-bulk-editor-column");
column.setWidth(Component.AUTO_SIZE);
for (int fieldIndex = fromField; fieldIndex < toField; fieldIndex++) {
ManagedField field = editFields.get(fieldIndex);
CssLayout row = uiComponents.create(CssLayout.NAME);
row.setStyleName("jmix-bulk-editor-row");
row.setWidth("100%");
Label<String> label = uiComponents.create(Label.NAME);
label.setValue(field.getLocalizedName());
label.setStyleName("jmix-bulk-editor-label");
row.add(label);
Datasource<Entity> fieldDs = datasource;
// so we can check field domain
if (metadataTools.isJpaEmbeddable(field.getMetaProperty().getDomain())) {
fieldDs = datasources.get(field.getParentFqn());
}
BulkEditorFieldFactory fieldFactory = getFieldFactory();
Field<?> editField = fieldFactory.createField(fieldDs, field.getMetaProperty());
if (editField != null) {
editField.setFrame(getFrame());
editField.setStyleName("jmix-bulk-editor-field");
if (isPickerFieldWrapperNeeded(editField, deviceInfo)) {
CssLayout wrapper = uiComponents.create(CssLayout.NAME);
wrapper.setStyleName("jmix-bulk-editor-picker-field-wrapper");
wrapper.add(editField);
row.add(wrapper);
} else {
row.add(editField);
}
boolean required = editField.isRequired();
if (!required) {
Button clearButton = uiComponents.create(Button.class);
clearButton.setIconFromSet(JmixIcon.TRASH);
clearButton.setCaption("");
clearButton.setDescription(messages.getMessage("io.jmix.ui.app.bulk/bulk.clearAttribute"));
clearButton.addClickListener(e -> {
editField.setEnabled(!editField.isEnabled());
if (!editField.isEnabled()) {
if (editField instanceof ListEditor) {
((Field) editField).setValue(Collections.EMPTY_LIST);
} else {
editField.setValue(null);
}
e.getSource().setIconFromSet(JmixIcon.EDIT);
e.getSource().setDescription(messages.getMessage("io.jmix.ui.app.bulk/bulk.editAttribute"));
} else {
e.getSource().setIconFromSet(JmixIcon.TRASH);
e.getSource().setDescription(messages.getMessage("io.jmix.ui.app.bulk/bulk.clearAttribute"));
}
});
row.add(clearButton);
} else {
// hidden component for correctly showing layout
Button spacerButton = uiComponents.create(Button.class);
spacerButton.setIconFromSet(JmixIcon.TRASH);
spacerButton.setStyleName("jmix-bulk-editor-spacer");
row.add(spacerButton);
}
// disable bean validator
// noinspection RedundantCast
editField.getValidators().stream().filter(v -> v instanceof AbstractBeanValidator).findFirst().ifPresent(((Field) editField)::removeValidator);
// disable required
editField.setRequired(false);
if (editField instanceof ListEditor) {
((Field) editField).setValue(Collections.EMPTY_LIST);
} else {
editField.setValue(null);
}
if (fieldValidators != null) {
Consumer validator = fieldValidators.get(field.getFqn());
if (validator != null) {
editField.addValidator(validator);
}
}
column.add(row);
dataFields.put(field.getFqn(), editField);
} else {
column.add(uiComponents.create(Label.class));
}
}
fieldsLayout.add(column);
// if there is no fields remain
if (editFields.size() - toField == 0) {
addedColumns = col + 1;
break;
}
}
fieldsLayout.addStyleName(COLUMN_COUNT_STYLENAME + addedColumns);
fieldsScrollBox.add(fieldsLayout);
dataFields.values().stream().filter(f -> f instanceof Focusable).findFirst().ifPresent(f -> ((Focusable) f).focus());
}
use of io.jmix.core.metamodel.model.MetaProperty in project jmix by jmix-framework.
the class EntityMutationDataFetcher method populateAndCheckComposition.
/**
* Walk through entity graph and check that all compositions have correct relations. If composition inverse value is
* null - update it to correct value. If composition inverse value doesn't match parent - throw exception.
*
* @param entity entity to be checked
* @param visited a set of entities that already be checked in graph
*/
protected void populateAndCheckComposition(Object entity, Set<Object> visited) {
if (visited.contains(entity)) {
return;
}
MetaClass metaClass = metadata.getClass(entity);
visited.add(entity);
metaClass.getProperties().stream().filter(metaProperty -> MetaProperty.Type.COMPOSITION.equals(metaProperty.getType())).filter(metaProperty -> !visited.contains(EntityValues.getValue(entity, metaProperty.getName()))).filter(metaProperty -> EntityValues.getValue(entity, metaProperty.getName()) != null).forEach(metaProperty -> {
// value from COMPOSITION metaProperty
Object childEntity = EntityValues.getValue(entity, metaProperty.getName());
Stream<?> childEntityStream = (childEntity instanceof Iterable<?>) ? StreamSupport.stream(((Iterable<?>) childEntity).spliterator(), false) : Stream.of(childEntity);
childEntityStream.forEach(childElement -> {
// have to check a linking for retrieved composition with a parent it can be different
assureCompositionInverseLink(entity, metaClass, metaProperty, childElement);
// digging deeper for child element to find any compositions inside
populateAndCheckComposition(childElement, visited);
});
});
}
use of io.jmix.core.metamodel.model.MetaProperty in project jmix by jmix-framework.
the class EntityMutationDataFetcher method assureCompositionInverseLink.
/**
* Check that inverse link is set correctly in composition relation. If link is null - fix it (assign to parent).
* If link point to different entity (not equals to parent) - throw exception.
*
* @param parent - parent entity
* @param parentMetaClass - meta class of parent entity
* @param metaProperty - metadata of property which points to child in parent entity
* @param child - child entity
*/
protected void assureCompositionInverseLink(Object parent, MetaClass parentMetaClass, MetaProperty metaProperty, Object child) {
MetaProperty inverseMetaProperty = metaProperty.getInverse();
if (inverseMetaProperty == null) {
return;
}
Object inverseValue = EntityValues.getValue(child, inverseMetaProperty.getName());
if (inverseValue == null) {
// inverse value is null - update it to correct value
EntityValues.setValue(child, inverseMetaProperty.getName(), parent);
} else {
if (!parent.equals(inverseValue)) {
// parent id doesn't match parent in graph - throw exception
String message = String.format("Composition attribute '%s' in class '%s' doesn't contain the correct link to parent entity. " + "Please set correct parent ID '%s' in composition relation.", metaProperty.getName(), parentMetaClass.getName(), EntityValues.getId(parent));
log.error(message);
throw new GqlEntityValidationException(message);
}
}
}
use of io.jmix.core.metamodel.model.MetaProperty in project jmix by jmix-framework.
the class MessagesDataFetcher method getEntityMessages.
protected List<MessageDetail> getEntityMessages(MetaClass metaClass, Locale locale) {
List<MessageDetail> messages = new ArrayList<>();
CrudEntityContext entityContext = new CrudEntityContext(metaClass);
accessManager.applyRegisteredConstraints(entityContext);
String metaClassName = metaClass.getName();
if (entityContext.isReadPermitted()) {
String entityCaption = messageTools.getEntityCaption(metaClass, locale);
messages.add(new MessageDetail(metaClassName, entityCaption));
}
for (MetaProperty metaProperty : metaClass.getProperties()) {
EntityAttributeContext attributeContext = new EntityAttributeContext(metaClass, metaProperty.getName());
accessManager.applyRegisteredConstraints(attributeContext);
if (attributeContext.canView()) {
String propertyCaption = messageTools.getPropertyCaption(metaProperty, locale);
messages.add(new MessageDetail(metaClassName + "." + metaProperty.getName(), propertyCaption));
}
}
return messages;
}
Aggregations