use of com.haulmont.chile.core.model.MetaProperty in project cuba by cuba-platform.
the class DesktopAbstractTable method setDatasource.
@Override
public void setDatasource(final CollectionDatasource datasource) {
Preconditions.checkNotNullArgument(datasource, "datasource is null");
final Collection<Object> properties;
if (this.columns.isEmpty()) {
MetadataTools metadataTools = AppBeans.get(MetadataTools.NAME);
MessageTools messageTools = AppBeans.get(MessageTools.NAME);
Collection<MetaPropertyPath> paths = datasource.getView() != null ? // if a view is specified - use view properties
metadataTools.getViewPropertyPaths(datasource.getView(), datasource.getMetaClass()) : // otherwise use only string properties from meta-class - the temporary solution for KeyValue datasources
metadataTools.getPropertyPaths(datasource.getMetaClass()).stream().filter(mpp -> mpp.getRangeJavaClass().equals(String.class)).collect(Collectors.toList());
for (MetaPropertyPath metaPropertyPath : paths) {
MetaProperty property = metaPropertyPath.getMetaProperty();
if (!property.getRange().getCardinality().isMany() && !metadataTools.isSystem(property)) {
Table.Column column = new Table.Column(metaPropertyPath);
String propertyName = property.getName();
MetaClass propertyMetaClass = metadataTools.getPropertyEnclosingMetaClass(metaPropertyPath);
column.setCaption(messageTools.getPropertyCaption(propertyMetaClass, propertyName));
column.setType(metaPropertyPath.getRangeJavaClass());
Element element = DocumentHelper.createElement("column");
column.setXmlDescriptor(element);
addColumn(column);
}
}
}
properties = this.columns.keySet();
this.datasource = datasource;
collectionChangeListener = e -> {
switch(e.getOperation()) {
case CLEAR:
case REFRESH:
fieldDatasources.clear();
break;
case UPDATE:
case REMOVE:
for (Object entity : e.getItems()) {
fieldDatasources.remove(entity);
}
break;
}
};
// noinspection unchecked
datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, collectionChangeListener));
initTableModel(datasource);
initChangeListener();
setColumnIdentifiers();
if (isSortable()) {
impl.setRowSorter(new RowSorterImpl(tableModel));
}
initSelectionListener(datasource);
List<MetaPropertyPath> editableColumns = null;
if (isEditable()) {
editableColumns = new LinkedList<>();
}
MetaClass metaClass = datasource.getMetaClass();
for (final Object property : properties) {
final Table.Column column = this.columns.get(property);
if (column != null) {
if (column.isCollapsed() && getColumnControlVisible()) {
TableColumn tableColumn = getColumn(column);
if (tableColumn instanceof TableColumnExt) {
((TableColumnExt) tableColumn).setVisible(false);
}
}
if (editableColumns != null && column.isEditable() && (property instanceof MetaPropertyPath)) {
MetaPropertyPath propertyPath = (MetaPropertyPath) property;
if (security.isEntityAttrUpdatePermitted(metaClass, property.toString())) {
editableColumns.add(propertyPath);
}
}
}
}
if (editableColumns != null && !editableColumns.isEmpty()) {
setEditableColumns(editableColumns);
}
List<Object> columnsOrder = new ArrayList<>();
for (Table.Column column : this.columnsOrder) {
if (column.getId() instanceof MetaPropertyPath) {
MetaPropertyPath metaPropertyPath = (MetaPropertyPath) column.getId();
if (security.isEntityAttrReadPermitted(metaClass, metaPropertyPath.toString())) {
columnsOrder.add(column.getId());
}
} else {
columnsOrder.add(column.getId());
}
}
setVisibleColumns(columnsOrder);
if (security.isSpecificPermitted(ShowInfoAction.ACTION_PERMISSION)) {
ShowInfoAction action = (ShowInfoAction) getAction(ShowInfoAction.ACTION_ID);
if (action == null) {
action = new ShowInfoAction();
addAction(action);
}
action.setDatasource(datasource);
}
securityCollectionChangeListener = e -> {
onDataChange();
packRows();
// #PL-2035, reload selection from ds
Set<E> selectedItems1 = getSelected();
if (selectedItems1 == null) {
selectedItems1 = Collections.emptySet();
}
Set<E> newSelection = new HashSet<>();
for (E entity : selectedItems1) {
if (e.getDs().containsItem(entity.getId())) {
newSelection.add(entity);
}
}
if (e.getDs().getState() == Datasource.State.VALID && e.getDs().getItem() != null) {
if (e.getDs().containsItem(e.getDs().getItem().getId())) {
newSelection.add((E) e.getDs().getItem());
}
}
if (newSelection.isEmpty()) {
setSelected((E) null);
} else {
setSelected(newSelection);
}
};
// noinspection unchecked
datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, securityCollectionChangeListener));
itemPropertyChangeListener = e -> {
List<Column> columns1 = getColumns();
boolean find = false;
int i = 0;
while ((i < columns1.size()) & !find) {
Object columnId = columns1.get(i).getId();
if (columnId instanceof MetaPropertyPath) {
String propertyName = ((MetaPropertyPath) columnId).getMetaProperty().getName();
if (propertyName.equals(e.getProperty())) {
find = true;
}
}
i++;
}
if (find) {
onDataChange();
}
packRows();
};
// noinspection unchecked
datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener));
if (rowsCount != null) {
rowsCount.setDatasource(datasource);
}
collectionDsActionsNotifier = new CollectionDsActionsNotifier(this);
collectionDsActionsNotifier.bind(datasource);
for (Action action : getActions()) {
action.refreshState();
}
if (!canBeSorted(datasource))
setSortable(false);
}
use of com.haulmont.chile.core.model.MetaProperty in project cuba by cuba-platform.
the class FetchGroupManager method processView.
private void processView(View view, FetchGroupField parentField, Set<FetchGroupField> fetchGroupFields, boolean useFetchGroup) {
Class<? extends Entity> entityClass = view.getEntityClass();
if (useFetchGroup) {
// Always add SoftDelete properties to support EntityManager contract
if (SoftDelete.class.isAssignableFrom(entityClass)) {
for (String property : getInterfaceProperties(SoftDelete.class)) {
fetchGroupFields.add(createFetchGroupField(entityClass, parentField, property));
}
}
// Always add uuid property if the entity has primary key not of type UUID
if (!BaseUuidEntity.class.isAssignableFrom(entityClass) && !EmbeddableEntity.class.isAssignableFrom(entityClass)) {
MetaProperty uuidProp = metadata.getClassNN(entityClass).getProperty("uuid");
if (uuidProp != null && metadataTools.isPersistent(uuidProp)) {
fetchGroupFields.add(createFetchGroupField(entityClass, parentField, "uuid"));
}
}
}
for (ViewProperty property : view.getProperties()) {
String propertyName = property.getName();
MetaClass metaClass = metadata.getClassNN(entityClass);
MetaProperty metaProperty = metaClass.getPropertyNN(propertyName);
if (metadataTools.isPersistent(metaProperty) && (metaProperty.getRange().isClass() || useFetchGroup)) {
FetchGroupField field = createFetchGroupField(entityClass, parentField, propertyName, property.getFetchMode());
fetchGroupFields.add(field);
if (property.getView() != null) {
if (ClassUtils.isPrimitiveOrWrapper(metaProperty.getJavaType()) || String.class.isAssignableFrom(metaProperty.getJavaType())) {
String message = "Wrong Views mechanism usage found. View%s is set for property \"%s\" of " + "class \"%s\", but this property does not point to an Entity";
String propertyViewName = property.getView().getName();
propertyViewName = propertyViewName != null && !propertyViewName.isEmpty() ? " \"" + propertyViewName + "\"" : "";
message = String.format(message, propertyViewName, property.getName(), metaClass.getName());
throw new DevelopmentException(message);
}
processView(property.getView(), field, fetchGroupFields, useFetchGroup);
}
}
List<String> relatedProperties = metadataTools.getRelatedProperties(entityClass, propertyName);
for (String relatedProperty : relatedProperties) {
MetaProperty relatedMetaProp = metaClass.getPropertyNN(relatedProperty);
if (!view.containsProperty(relatedProperty) && (relatedMetaProp.getRange().isClass() || useFetchGroup)) {
FetchGroupField field = createFetchGroupField(entityClass, parentField, relatedProperty);
fetchGroupFields.add(field);
if (relatedMetaProp.getRange().isClass()) {
View relatedView = viewRepository.getView(relatedMetaProp.getRange().asClass(), View.MINIMAL);
processView(relatedView, field, fetchGroupFields, useFetchGroup);
}
}
}
}
}
use of com.haulmont.chile.core.model.MetaProperty in project cuba by cuba-platform.
the class FetchGroupManager method applyView.
private void applyView(JpaQuery query, String queryString, AttributeGroup attrGroup, View view, boolean singleResultExpected) {
boolean useFetchGroup = attrGroup instanceof FetchGroup;
Set<FetchGroupField> fetchGroupFields = new LinkedHashSet<>();
processView(view, null, fetchGroupFields, useFetchGroup);
Set<String> fetchGroupAttributes = new TreeSet<>();
// sort hints by attribute path
Map<String, String> fetchHints = new TreeMap<>();
for (FetchGroupField field : fetchGroupFields) {
fetchGroupAttributes.add(field.path());
}
if (attrGroup instanceof FetchGroup)
((FetchGroup) attrGroup).setShouldLoadAll(true);
List<FetchGroupField> refFields = new ArrayList<>();
for (FetchGroupField field : fetchGroupFields) {
if (field.metaProperty.getRange().isClass() && !metadataTools.isEmbedded(field.metaProperty))
refFields.add(field);
}
boolean hasBatches = false;
MetaClass metaClass = metadata.getClassNN(view.getEntityClass());
if (!refFields.isEmpty()) {
String alias = QueryTransformerFactory.createParser(queryString).getEntityAlias();
List<FetchGroupField> batchFields = new ArrayList<>();
List<FetchGroupField> joinFields = new ArrayList<>();
for (FetchGroupField refField : refFields) {
if (refField.fetchMode == FetchMode.UNDEFINED) {
if (refField.metaProperty.getRange().getCardinality().isMany()) {
List<String> masterAttributes = getMasterEntityAttributes(fetchGroupFields, refField, useFetchGroup);
fetchGroupAttributes.addAll(masterAttributes);
}
continue;
}
boolean selfRef = false;
for (MetaProperty mp : refField.metaPropertyPath.getMetaProperties()) {
if (!mp.getRange().getCardinality().isMany()) {
MetaClass mpClass = mp.getRange().asClass();
if (metadataTools.isAssignableFrom(mpClass, metaClass) || metadataTools.isAssignableFrom(metaClass, mpClass)) {
batchFields.add(refField);
selfRef = true;
break;
}
}
}
if (!selfRef) {
if (refField.metaProperty.getRange().getCardinality().isMany()) {
List<String> masterAttributes = getMasterEntityAttributes(fetchGroupFields, refField, useFetchGroup);
fetchGroupAttributes.addAll(masterAttributes);
if (refField.fetchMode == FetchMode.JOIN) {
joinFields.add(refField);
} else {
batchFields.add(refField);
}
} else {
if (refField.fetchMode == FetchMode.BATCH) {
batchFields.add(refField);
} else {
joinFields.add(refField);
}
}
}
}
for (FetchGroupField joinField : new ArrayList<>(joinFields)) {
// adjust fetch mode according to parent attributes
if (joinField.fetchMode == FetchMode.AUTO) {
Optional<FetchMode> parentMode = refFields.stream().filter(f -> joinField.metaPropertyPath.startsWith(f.metaPropertyPath) && joinField.fetchMode != FetchMode.JOIN).sorted((f1, f2) -> f1.metaPropertyPath.getPath().length - f2.metaPropertyPath.getPath().length).findFirst().map(f -> f.fetchMode);
if (parentMode.isPresent() && parentMode.get() == FetchMode.UNDEFINED) {
joinFields.remove(joinField);
} else {
for (FetchGroupField batchField : new ArrayList<>(batchFields)) {
if (joinField.metaPropertyPath.startsWith(batchField.metaPropertyPath)) {
joinFields.remove(joinField);
batchFields.add(joinField);
}
}
}
}
}
QueryParser parser = QueryTransformerFactory.createParser(queryString);
List<FetchGroupField> isNullFields = joinFields.stream().filter(f -> f.fetchMode == FetchMode.AUTO && parser.hasIsNullCondition(f.path())).collect(Collectors.toList());
if (!isNullFields.isEmpty()) {
for (Iterator<FetchGroupField> fieldIt = joinFields.iterator(); fieldIt.hasNext(); ) {
FetchGroupField joinField = fieldIt.next();
boolean isNullField = isNullFields.stream().anyMatch(f -> joinField == f || f.fetchMode == FetchMode.AUTO && joinField.metaPropertyPath.startsWith(f.metaPropertyPath));
if (isNullField) {
fieldIt.remove();
fetchGroupAttributes.removeIf(attr -> attr.startsWith(joinField.path() + "."));
}
}
}
long toManyCount = refFields.stream().filter(f -> f.metaProperty.getRange().getCardinality().isMany()).count();
// For query by ID, remove BATCH mode for to-many attributes that have no nested attributes
if (singleResultExpected && toManyCount <= 1) {
for (FetchGroupField batchField : new ArrayList<>(batchFields)) {
if (batchField.metaProperty.getRange().getCardinality().isMany()) {
boolean hasNested = refFields.stream().anyMatch(f -> f != batchField && f.metaPropertyPath.startsWith(batchField.metaPropertyPath));
if (!hasNested && batchField.fetchMode != FetchMode.BATCH) {
batchFields.remove(batchField);
}
}
}
}
// Remove this fields from BATCH processing
for (FetchGroupField refField : refFields) {
if (refField.fetchMode == FetchMode.AUTO && refField.metaProperty.getRange().getCardinality() == Range.Cardinality.MANY_TO_MANY) {
// find property {E}.a.b for {E}.a where b of type {E}
List<FetchGroupField> selfRefs = refFields.stream().filter(f -> isTransitiveSelfReference(refField, f)).collect(Collectors.toList());
for (FetchGroupField selfRef : selfRefs) {
List<FetchGroupField> secondLevelSelfRefs = refFields.stream().filter(f -> isTransitiveSelfReference(selfRef, f)).collect(Collectors.toList());
for (FetchGroupField f : secondLevelSelfRefs) {
batchFields.remove(f);
batchFields.remove(selfRef);
batchFields.remove(refField);
}
}
}
}
for (FetchGroupField joinField : joinFields) {
String attr = alias + "." + joinField.path();
fetchHints.put(attr, QueryHints.LEFT_FETCH);
}
for (FetchGroupField batchField : batchFields) {
if (batchField.fetchMode == FetchMode.BATCH || !singleResultExpected || batchFields.size() > 1) {
String attr = alias + "." + batchField.path();
fetchHints.put(attr, QueryHints.BATCH);
hasBatches = true;
}
}
}
if (log.isTraceEnabled())
log.trace((useFetchGroup ? "Fetch" : "Load") + " group for " + view + ":\n" + fetchGroupAttributes.stream().collect(Collectors.joining("\n")));
for (String attribute : fetchGroupAttributes) {
attrGroup.addAttribute(attribute);
}
if (!metadataTools.isCacheable(metaClass)) {
query.setHint(useFetchGroup ? QueryHints.FETCH_GROUP : QueryHints.LOAD_GROUP, attrGroup);
}
if (log.isDebugEnabled()) {
String fetchModes = fetchHints.entrySet().stream().map(e -> e.getKey() + "=" + (e.getValue().equals(QueryHints.LEFT_FETCH) ? "JOIN" : "BATCH")).collect(Collectors.joining(", "));
log.debug("Fetch modes for " + view + ": " + (fetchModes.equals("") ? "<none>" : fetchModes));
}
for (Map.Entry<String, String> entry : fetchHints.entrySet()) {
query.setHint(entry.getValue(), entry.getKey());
}
if (hasBatches) {
query.setHint(QueryHints.BATCH_TYPE, "IN");
}
}
use of com.haulmont.chile.core.model.MetaProperty in project cuba by cuba-platform.
the class PersistenceSecurityImpl method calculateFilteredData.
@SuppressWarnings("unchecked")
protected boolean calculateFilteredData(Entity entity, Set<EntityId> handled, boolean checkPermitted) {
MetaClass metaClass = entity.getMetaClass();
if (!isPermittedInMemory(entity) && checkPermitted) {
return true;
}
EntityId entityId = new EntityId(referenceToEntitySupport.getReferenceId(entity), metaClass.getName());
if (handled.contains(entityId)) {
return false;
}
handled.add(entityId);
if (entity instanceof BaseGenericIdEntity) {
BaseGenericIdEntity baseGenericIdEntity = (BaseGenericIdEntity) entity;
for (MetaProperty property : metaClass.getProperties()) {
if (metadataTools.isPersistent(property) && PersistenceHelper.isLoaded(entity, property.getName())) {
Object value = entity.getValue(property.getName());
if (value instanceof Collection) {
Set filtered = new LinkedHashSet();
for (Entity item : (Collection<Entity>) value) {
if (calculateFilteredData(item, handled, true)) {
filtered.add(referenceToEntitySupport.getReferenceId(item));
}
}
if (!filtered.isEmpty()) {
securityTokenManager.addFiltered(baseGenericIdEntity, property.getName(), filtered);
}
} else if (value instanceof Entity) {
Entity valueEntity = (Entity) value;
if (calculateFilteredData(valueEntity, handled, true)) {
securityTokenManager.addFiltered(baseGenericIdEntity, property.getName(), referenceToEntitySupport.getReferenceId(valueEntity));
}
}
}
}
securityTokenManager.writeSecurityToken(baseGenericIdEntity);
}
return false;
}
use of com.haulmont.chile.core.model.MetaProperty in project cuba by cuba-platform.
the class PersistenceSecurityImpl method restoreFilteredData.
@Override
@SuppressWarnings("unchecked")
public void restoreFilteredData(Entity entity) {
MetaClass metaClass = metadata.getClassNN(entity.getClass());
String storeName = metadataTools.getStoreName(metaClass);
EntityManager entityManager = persistence.getEntityManager(storeName);
Multimap<String, Object> filtered = BaseEntityInternalAccess.getFilteredData(entity);
if (filtered == null) {
return;
}
for (Map.Entry<String, Collection<Object>> entry : filtered.asMap().entrySet()) {
MetaProperty property = metaClass.getPropertyNN(entry.getKey());
Collection filteredIds = entry.getValue();
if (property.getRange().isClass() && CollectionUtils.isNotEmpty(filteredIds)) {
Class entityClass = property.getRange().asClass().getJavaClass();
Class propertyClass = property.getJavaType();
if (Collection.class.isAssignableFrom(propertyClass)) {
Collection currentCollection = entity.getValue(property.getName());
if (currentCollection == null) {
throw new RowLevelSecurityException(format("Could not restore an object to currentValue because it is null [%s]. Entity [%s].", property.getName(), metaClass.getName()), metaClass.getName());
}
for (Object entityId : filteredIds) {
Entity reference = entityManager.getReference((Class<Entity>) entityClass, entityId);
// we ignore situations when the currentValue is immutable
currentCollection.add(reference);
}
} else if (Entity.class.isAssignableFrom(propertyClass)) {
Object entityId = filteredIds.iterator().next();
Entity reference = entityManager.getReference((Class<Entity>) entityClass, entityId);
// we ignore the situation when the field is read-only
entity.setValue(property.getName(), reference);
}
}
}
}
Aggregations