Skip to content

Commit

Permalink
optimize form load (especially for objects with many attributes) MID-…
Browse files Browse the repository at this point in the history
…6593
  • Loading branch information
katkav committed Dec 15, 2020
1 parent 29be424 commit 04d566b
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 102 deletions.
Expand Up @@ -8,10 +8,12 @@
package com.evolveum.midpoint.gui.api.component;

import com.evolveum.midpoint.gui.api.util.WebComponentUtil;
import com.evolveum.midpoint.web.component.util.VisibleBehaviour;
import com.evolveum.midpoint.web.util.InfoTooltipBehavior;
import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultStatusType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.PendingOperationExecutionStatusType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.PendingOperationType;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.html.WebMarkupContainer;
Expand Down Expand Up @@ -40,6 +42,7 @@ protected void onInitialize() {
super.onInitialize();

initLayout();
add(new VisibleBehaviour(() -> CollectionUtils.isNotEmpty(getModelObject())));
}

private void initLayout() {
Expand Down
Expand Up @@ -18,6 +18,7 @@
import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour;
import com.evolveum.midpoint.xml.ns._public.common.common_3.PendingOperationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;
import org.apache.wicket.model.PropertyModel;

/**
* @author skublik
Expand All @@ -43,27 +44,8 @@ protected void onInitialize(){

private void initLayout() {
WebMarkupContainer pendingOperationContainer = new WebMarkupContainer(ID_PENDING_OPERATION_CONTAINER);
List<PendingOperationType> pendingOperations = getModelObject().getPendingOperation();
if(pendingOperations != null
&& !pendingOperations.isEmpty()) {

pendingOperationContainer.add(new PendingOperationPanel(ID_PENDING_OPERATION, new IModel<List<PendingOperationType>>() {

@Override
public List<PendingOperationType> getObject() {
return pendingOperations;
}

}));
} else {
pendingOperationContainer.add(new WebMarkupContainer(ID_PENDING_OPERATION));
pendingOperationContainer.add(new VisibleEnableBehaviour() {
@Override
public boolean isVisible() {
return false;
}
});
}

pendingOperationContainer.add(new PendingOperationPanel(ID_PENDING_OPERATION, new PropertyModel<>(getModel(), ShadowType.F_PENDING_OPERATION.getLocalPart())));
add(pendingOperationContainer);
}

Expand Down
Expand Up @@ -88,6 +88,7 @@ public PrismContainerValueWrapper<C> createValueWrapper(PrismContainerWrapper<C>
containerValueWrapper.setVirtualContainerItems(context.getVirtualItemSpecification());
parent.setVirtual(context.getVirtualItemSpecification() != null);
containerValueWrapper.setExpanded(shouldBeExpanded(parent, value, context));

return containerValueWrapper;
}

Expand Down
Expand Up @@ -23,11 +23,6 @@

<span wicket:id="required" style="color: #f00; font-weight: bold;"
wicket:message="title:prismPropertyPanel.required">*</span>
<!-- <span wicket:id="hasOutbound" style="color: #8080ff; font-weight: bold;" -->
<!-- wicket:message="title:prismPropertyPanel.hasOutbound"><i class="fa fa-sign-out"></i></span> -->
<!-- <span wicket:id="hasPendingModification" style="color: #f0f; font-weight: bold;" -->
<!-- wicket:message="title:prismPropertyPanel.hasPendingModification">*</span> -->
<!-- <i class="helpTextIcon" wicket:id="help"/> -->
<i class="helpTextIcon" wicket:id="help"/>
<i class="helpTextIcon" wicket:id="deprecated"/>
<i class="helpTextIcon" wicket:id="experimental"/>
Expand Down
Expand Up @@ -41,7 +41,7 @@
</div>
<div class="prism-properties">
<div wicket:id="propertiesLabel">
<div wicket:id="properties">
<div class="property-stripe" wicket:id="properties">
<div class="row prism-property" wicket:id="property"/>
</div>
</div>
Expand Down
Expand Up @@ -213,34 +213,6 @@ public List<IW> getObject() {
private <IW extends ItemWrapper> List<IW> getNonContainerWrappers() {
CVW containerValueWrapper = getModelObject();
List<? extends ItemWrapper<?, ?, ?, ?>> nonContainers = containerValueWrapper.getNonContainers();

Locale locale = WebModelServiceUtils.getLocale();
if (locale == null) {
locale = Locale.getDefault();
}
Collator collator = Collator.getInstance(locale);
collator.setStrength(Collator.SECONDARY); // e.g. "a" should be different from "á"
collator.setDecomposition(Collator.FULL_DECOMPOSITION);
ItemWrapperComparator<?> comparator = new ItemWrapperComparator<>(collator, getModelObject().isSorted());
if (CollectionUtils.isNotEmpty(nonContainers)) {
nonContainers.sort((Comparator) comparator);

int visibleProperties = 0;

for (ItemWrapper<?,?,?,?> item : nonContainers) {
if (item.isVisible(containerValueWrapper, visibilityHandler)) {
visibleProperties++;
}

if (visibleProperties % 2 == 0) {
item.setStripe(false);
} else {
item.setStripe(true);
}

}
}

return (List<IW>) nonContainers;
}

Expand All @@ -256,7 +228,7 @@ private <IW extends ItemWrapper> void populateNonContainer(ListItem<IW> item) {
ItemPanelSettingsBuilder builder = new ItemPanelSettingsBuilder().visibilityHandler(visibilityHandler);
Panel panel = getPageBase().initItemPanel("property", typeName, item.getModel(), builder.build());
panel.setOutputMarkupId(true);
panel.add(new VisibleEnableBehaviour() {
item.add(new VisibleEnableBehaviour() {

private static final long serialVersionUID = 1L;

Expand Down Expand Up @@ -288,7 +260,7 @@ private void populateContainer(ListItem<PrismContainerWrapper> container) {
ItemPanelSettingsBuilder builder = new ItemPanelSettingsBuilder().visibilityHandler(visibilityHandler);
Panel panel = getPageBase().initItemPanel("container", itemWrapper.getTypeName(), container.getModel(), builder.build());
panel.setOutputMarkupId(true);
panel.add(new VisibleBehaviour(() -> {
container.add(new VisibleBehaviour(() -> {
CVW parent = PrismContainerValuePanel.this.getModelObject();
return container.getModelObject().isVisible(parent, visibilityHandler);
}));
Expand Down Expand Up @@ -463,7 +435,7 @@ private void prepareNewContainers(AjaxRequestTarget target, List<PrismContainerD
try {
ItemWrapper iw = getPageBase().createItemWrapper(container, getModelObject(), ctx);
if (iw != null) {
((List) getModelObject().getItems()).add(iw);
getModelObject().addItem(iw);
}
} catch (SchemaException e) {
OperationResult result = ctx.getResult();
Expand Down
Expand Up @@ -6,6 +6,7 @@
*/
package com.evolveum.midpoint.gui.impl.prism;

import java.util.Collection;
import java.util.List;

import com.evolveum.midpoint.gui.api.prism.ItemWrapper;
Expand Down Expand Up @@ -89,4 +90,8 @@ public interface PrismContainerValueWrapper<C extends Containerable> extends Pri
void setVirtualContainerItems(List<VirtualContainerItemSpecificationType> virtualItems);
boolean isVirtual();


void addItem(ItemWrapper<?, ?, ?, ?> iw);
void clearItems();
void addItems(Collection<ItemWrapper<?, ?, ?, ?>> items);
}
Expand Up @@ -10,6 +10,7 @@
import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper;
import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper;
import com.evolveum.midpoint.gui.api.util.WebComponentUtil;
import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils;
import com.evolveum.midpoint.gui.api.util.WebPrismUtil;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.delta.ItemDelta;
Expand All @@ -27,11 +28,11 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.VirtualContainerItemSpecificationType;
import com.evolveum.prism.xml.ns._public.types_3.ItemPathType;
import org.apache.commons.collections4.CollectionUtils;

import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.text.Collator;
import java.util.*;

/**
* @author katka
Expand All @@ -55,6 +56,8 @@ public class PrismContainerValueWrapperImpl<C extends Containerable> extends Pri
private List<VirtualContainerItemSpecificationType> virtualItems;
private List<ItemWrapper<?, ?, ?,?>> items = new ArrayList<>();

private List<ItemWrapper<?, ?, ?, ?>> nonContainers = new ArrayList<>();

public PrismContainerValueWrapperImpl(PrismContainerWrapper<C> parent, PrismContainerValue<C> pcv, ValueStatus status) {
super(parent, pcv, status);
}
Expand Down Expand Up @@ -236,7 +239,10 @@ public <T extends Containerable> List<PrismContainerWrapper<T>> getContainers()

@Override
public List<? extends ItemWrapper<?,?,?,?>> getNonContainers() {
List<? extends ItemWrapper<?,?,?,?>> nonContainers = new ArrayList<>();
// List<? extends ItemWrapper<?,?,?,?>> nonContainers = new ArrayList<>();
if (!nonContainers.isEmpty()) {
return nonContainers;
}
for (ItemWrapper<?,?,?,?> item : items) {

collectExtensionItems(item, false, nonContainers);
Expand All @@ -246,49 +252,68 @@ public List<? extends ItemWrapper<?,?,?,?>> getNonContainers() {
}
}

if (getVirtualItems() == null) {
return nonContainers;
}

if (getParent() == null) {
LOGGER.trace("Parent null, skipping virtual items");
return nonContainers;
}

PrismObjectWrapper objectWrapper = getParent().findObjectWrapper();
if (objectWrapper == null) {
LOGGER.trace("No object wrapper found. Skipping virtual items.");
return nonContainers;
}
PrismObjectWrapper<?> objectWrapper = getObjectWrapperForVirtualContainers();
if (objectWrapper != null) {

for (VirtualContainerItemSpecificationType virtualItem : getVirtualItems()) {
if (objectWrapper == null) {
//should not happen, if happens it means something veeery strange happened
continue;
}
try {
ItemPath virtualItemPath = getVirtualItemPath(virtualItem);
ItemWrapper itemWrapper = objectWrapper.findItem(virtualItemPath, ItemWrapper.class);
if (itemWrapper == null) {
LOGGER.warn("No wrapper found for {}", virtualItemPath);
for (VirtualContainerItemSpecificationType virtualItem : getVirtualItems()) {
if (objectWrapper == null) {
//should not happen, if happens it means something veeery strange happened
continue;
}
try {
ItemPath virtualItemPath = getVirtualItemPath(virtualItem);
ItemWrapper itemWrapper = objectWrapper.findItem(virtualItemPath, ItemWrapper.class);
if (itemWrapper == null) {
LOGGER.warn("No wrapper found for {}", virtualItemPath);
continue;
}

if (itemWrapper instanceof PrismContainerWrapper) {
continue;
if (itemWrapper instanceof PrismContainerWrapper) {
continue;
}

((List) nonContainers).add(itemWrapper);
} catch (SchemaException e) {
LOGGER.error("Cannot find wrapper with path {}, error occured {}", virtualItem, e.getMessage(), e);
}

((List)nonContainers).add(itemWrapper);
} catch (SchemaException e) {
LOGGER.error("Cannot find wrapper with path {}, error occured {}", virtualItem, e.getMessage(), e);
}
}


Locale locale = WebModelServiceUtils.getLocale();
if (locale == null) {
locale = Locale.getDefault();
}
Collator collator = Collator.getInstance(locale);
collator.setStrength(Collator.SECONDARY); // e.g. "a" should be different from "á"
collator.setDecomposition(Collator.FULL_DECOMPOSITION);
ItemWrapperComparator<?> comparator = new ItemWrapperComparator<>(collator, sorted);
if (CollectionUtils.isNotEmpty(nonContainers)) {
nonContainers.sort((Comparator) comparator);
}

return nonContainers;
}

private PrismObjectWrapper<?> getObjectWrapperForVirtualContainers() {
if (getVirtualItems() == null) {
LOGGER.trace("Skipping processing of virtual containers, no virtual container definition found");
return null;
}

if (getParent() == null) {
LOGGER.trace("Parent null, skipping virtual items");
return null;
}

PrismObjectWrapper objectWrapper = getParent().findObjectWrapper();
if (objectWrapper == null) {
LOGGER.trace("No object wrapper found. Skipping virtual items.");
return null;
}
return objectWrapper;
}

private ItemPath getVirtualItemPath(VirtualContainerItemSpecificationType virtualItem) throws SchemaException {
ItemPathType itemPathType = virtualItem.getPath();
if (itemPathType == null) {
Expand Down Expand Up @@ -474,4 +499,21 @@ public List<VirtualContainerItemSpecificationType> getVirtualItems() {
public boolean isVirtual() {
return virtualItems != null;
}

public void addItem(ItemWrapper<?, ?, ?, ?> iw) {
items.add(iw);
nonContainers.clear();
}

@Override
public void clearItems() {
items.clear();
nonContainers.clear();
}

@Override
public void addItems(Collection<ItemWrapper<?,?,?,?>> items) {
items.addAll(items);
nonContainers.clear();
}
}
Expand Up @@ -46,9 +46,17 @@ private IModel<ResourceAttributeWrapper<T>> getResourceAttributeDefinitionModel(
}

private boolean hasOutboundMapping() {
return getResourceAttributeDefinitionModel() != null &&
getResourceAttributeDefinitionModel().getObject() != null &&
getResourceAttributeDefinitionModel().getObject().hasOutboundMapping();
IModel<ResourceAttributeWrapper<T>> model = getResourceAttributeDefinitionModel();
if (model == null) {
return false;
}

ResourceAttributeWrapper<T> modelObject = model.getObject();
if (modelObject == null) {
return false;
}

return modelObject.hasOutboundMapping();
}

}
Expand Up @@ -230,11 +230,7 @@ public void itemPerformedForDefaultAction(AjaxRequestTarget target,
IModel<PrismContainerValueWrapper<ShadowType>> rowModel,
List<PrismContainerValueWrapper<ShadowType>> listItems) {

if(rowModel != null && rowModel.getObject() != null
&& ((ShadowWrapper)rowModel.getObject().getParent()).isLoadWithNoFetch()) {
((PageAdminFocus) getPage()).loadFullShadow((PrismObjectValueWrapper)rowModel.getObject(), target);
}

loadShadowIfNeeded(rowModel, target);
if(listItems != null) {
listItems.forEach(value -> {
if(((ShadowWrapper)value.getParent()).isLoadWithNoFetch()) {
Expand Down Expand Up @@ -263,6 +259,26 @@ protected MultivalueContainerDetailsPanel<ShadowType> getMultivalueContainerDeta
setOutputMarkupId(true);
}

private void loadShadowIfNeeded(IModel<PrismContainerValueWrapper<ShadowType>> rowModel, AjaxRequestTarget target) {
if (rowModel == null) {
return;
}

PrismContainerValueWrapper<ShadowType> shadow = rowModel.getObject();
if (shadow == null) {
return;
}

ShadowWrapper shadowWrapper = shadow.getParent();
if (shadowWrapper == null) {
return;
}

if (shadowWrapper.isLoadWithNoFetch()) {
((PageAdminFocus) getPage()).loadFullShadow((PrismObjectValueWrapper)rowModel.getObject(), target);
}
}

private void initPaging() {
getPageBase().getSessionStorage().getFocusProjectionTableStorage().setPaging(
getPrismContext().queryFactory().createPaging(0, (int) ((PageBase)getPage()).getItemsPerPage(UserProfileStorage.TableId.FOCUS_PROJECTION_TABLE)));
Expand Down

0 comments on commit 04d566b

Please sign in to comment.