From 633e33b63f0042de22789f396bab9f4be0b833ff Mon Sep 17 00:00:00 2001 From: Katarina Valalikova Date: Thu, 12 Mar 2020 10:32:01 +0100 Subject: [PATCH 1/7] fixing icon columns for shadow list (resource details page), small cleanup.. later unify icon column methods.. (MID-5926) --- .../gui/api/util/WebComponentUtil.java | 208 ++- .../component/icon/LayeredIconCssStyle.java | 38 +- .../FocusProjectionsTabPanel.java | 1633 ++++++++--------- 3 files changed, 962 insertions(+), 917 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebComponentUtil.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebComponentUtil.java index fb1e3ca6d3c..cfea60a9cb9 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebComponentUtil.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebComponentUtil.java @@ -18,13 +18,16 @@ import com.evolveum.midpoint.gui.api.page.PageBase; import com.evolveum.midpoint.gui.api.prism.ItemWrapper; import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; import com.evolveum.midpoint.gui.impl.component.icon.CompositedIcon; import com.evolveum.midpoint.gui.impl.component.icon.CompositedIconBuilder; import com.evolveum.midpoint.gui.impl.component.icon.IconCssStyle; +import com.evolveum.midpoint.gui.impl.component.icon.LayeredIconCssStyle; import com.evolveum.midpoint.gui.impl.factory.WrapperContext; import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; import com.evolveum.midpoint.gui.impl.prism.PrismPropertyValueWrapper; import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; import com.evolveum.midpoint.model.api.*; import com.evolveum.midpoint.model.api.authentication.CompiledObjectCollectionView; import com.evolveum.midpoint.model.api.authentication.CompiledGuiProfile; @@ -84,6 +87,7 @@ import com.evolveum.midpoint.web.component.util.Selectable; import com.evolveum.midpoint.web.component.util.SelectableBeanImpl; import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; +import com.evolveum.midpoint.web.model.PrismPropertyWrapperModel; import com.evolveum.midpoint.web.page.PageDialog; import com.evolveum.midpoint.web.page.admin.archetype.PageArchetype; import com.evolveum.midpoint.web.page.admin.cases.PageCase; @@ -122,6 +126,7 @@ import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; import org.apache.commons.lang.math.NumberUtils; @@ -150,6 +155,7 @@ import org.apache.wicket.markup.repeater.data.IDataProvider; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; +import org.apache.wicket.model.PropertyModel; import org.apache.wicket.model.StringResourceModel; import org.apache.wicket.request.IRequestHandler; import org.apache.wicket.request.cycle.RequestCycle; @@ -1574,6 +1580,10 @@ public static String getOrigStringFromPoly(PolyStringType str) { return str != null ? str.getOrig() : null; } + public static String getOrigStringFromPolyOrEmpty(PolyStringType str) { + return str != null ? str.getOrig() : ""; + } + public static T getValue(PrismContainerValue object, QName propertyName, Class type) { if (object == null) { return null; @@ -1907,6 +1917,8 @@ public static String createDefaultIcon(PrismObject obj return createTaskIcon((PrismObject) object); } else if (type.equals(ResourceType.class)) { return createResourceIcon((PrismObject) object); + } else if (type == ShadowType.class) { + return createShadowIcon((PrismObject) object); } return ""; @@ -3496,17 +3508,7 @@ public static DisplayType getDisplayTypeForObject(O obj, return ((ArchetypeType)obj).getArchetypePolicy().getDisplay(); } DisplayType displayType = WebComponentUtil.getArchetypePolicyDisplayType(obj, pageBase); -// if (displayType != null){ -// String disabledStyle = ""; -// if (obj instanceof FocusType) { -// disabledStyle = WebComponentUtil.getIconEnabledDisabled(((FocusType)obj).asPrismObject()); -// if (displayType.getIcon() != null && StringUtils.isNotEmpty(displayType.getIcon().getCssClass()) && -// disabledStyle != null){ -// displayType.getIcon().setCssClass(displayType.getIcon().getCssClass() + " " + disabledStyle); -// displayType.getIcon().setColor(""); -// } -// } -// } else { + if (displayType == null){ displayType = WebComponentUtil.createDisplayType(createDefaultIcon(obj.asPrismObject()), "", ColumnUtils.getIconColumnTitle(obj, result)); @@ -3514,37 +3516,22 @@ public static DisplayType getDisplayTypeForObject(O obj, return displayType; } + //TODO unify createAccountIcon with createCompositeIconForObject public static CompositedIcon createCompositeIconForObject(O obj, OperationResult result, PageBase pageBase){ + if (obj instanceof ShadowType) { + return createAccountIcon((ShadowType) obj, pageBase); + } + DisplayType basicIconDisplayType = getDisplayTypeForObject(obj, result, pageBase); CompositedIconBuilder iconBuilder = new CompositedIconBuilder(); if (basicIconDisplayType == null){ return new CompositedIconBuilder().build(); } + //TODO trigger + IconType lifecycleStateIcon = getIconForLifecycleState(obj); IconType activationStatusIcon = getIconForActivationStatus(obj); - StringBuilder title = new StringBuilder(basicIconDisplayType.getTooltip() != null ? basicIconDisplayType.getTooltip().getOrig() : ""); - if (StringUtils.isNotEmpty(lifecycleStateIcon.getCssClass())){ - if (title.length() > 0){ - title.append("\n"); - } - title.append(pageBase.createStringResource("ObjectType.lifecycleState").getString()) - .append(": ") - .append(obj.getLifecycleState()); - } - if (StringUtils.isNotEmpty(activationStatusIcon.getCssClass()) && obj instanceof FocusType - && ((FocusType)obj).getActivation() != null){ - if (title.length() > 0){ - title.append("\n"); - } - String lockedStatus = LockoutStatusType.LOCKED.equals(((FocusType)obj).getActivation().getLockoutStatus()) ? - ((FocusType)obj).getActivation().getLockoutStatus().value() : ""; - String effectiveStatus = ((FocusType)obj).getActivation().getEffectiveStatus() != null ? - ((FocusType)obj).getActivation().getEffectiveStatus().value() : ""; - title.append(pageBase.createStringResource("CapabilitiesType.activationStatus").getString()) - .append(": ") - .append(StringUtils.isNotEmpty(lockedStatus) ? lockedStatus : effectiveStatus); - } String iconColor = getIconColor(basicIconDisplayType); CompositedIconBuilder builder = iconBuilder.setBasicIcon( @@ -3553,25 +3540,168 @@ public static CompositedIcon createCompositeIconForObject .appendLayerIcon(lifecycleStateIcon, IconCssStyle.BOTTOM_LEFT_FOR_COLUMN_STYLE) .appendLayerIcon(activationStatusIcon, IconCssStyle.BOTTOM_RIGHT_FOR_COLUMN_STYLE); + StringBuilder title = new StringBuilder(getOrigStringFromPolyOrEmpty(basicIconDisplayType.getTooltip())); + appendLifecycleState(title, lifecycleStateIcon, obj, pageBase); + appendActivationStatus(title, activationStatusIcon, obj, pageBase); if (StringUtils.isNotEmpty(title.toString())){ builder.setTitle(title.toString()); } return builder.build(); } + public static CompositedIcon createAccountIcon(ShadowType shadow, PageBase pageBase) { + List triggerType = shadow.getTrigger(); + String iconCssClass = WebComponentUtil.createShadowIcon(shadow.asPrismObject()); + CompositedIconBuilder builder = new CompositedIconBuilder(); + String title = createTriggerTooltip(triggerType, pageBase); + if(StringUtils.isNotBlank(title)) { + IconType icon = new IconType(); + icon.setCssClass("fa fa-clock-o " + GuiStyleConstants.BLUE_COLOR); + builder.appendLayerIcon(icon, IconCssStyle.TOP_RIGHT_FOR_COLUMN_STYLE); + } + builder.setBasicIcon(iconCssClass, IconCssStyle.BOTTOM_RIGHT_FOR_COLUMN_STYLE); + + if (BooleanUtils.isTrue(shadow.isDead())) { + IconType icon = new IconType(); + icon.setCssClass("fa fa-times-circle " + GuiStyleConstants.RED_COLOR); + builder.appendLayerIcon(icon, IconCssStyle.BOTTOM_RIGHT_FOR_COLUMN_STYLE); + builder.setTitle(pageBase.createStringResource("FocusProjectionsTabPanel.deadShadow").getString() + + (StringUtils.isNotBlank(title) ? ("\n" + title) : "")); + return builder.build(); + } + + ActivationType activation = shadow.getActivation(); + if (activation == null) { + builder.setTitle(pageBase.createStringResource("ActivationStatusType.null").getString() + + (StringUtils.isNotBlank(title) ? ("\n" + title) : "")); + appendUndefinedIcon(builder); + return builder.build(); + } + LockoutStatusType lockoutStatus = activation.getLockoutStatus(); + XMLGregorianCalendar lockoutExpirationTimestamp = activation.getLockoutExpirationTimestamp(); + if((lockoutStatus != null && LockoutStatusType.LOCKED == lockoutStatus) + || (lockoutExpirationTimestamp != null && pageBase.getClock().isPast((lockoutExpirationTimestamp)))) { + IconType icon = new IconType(); + icon.setCssClass("fa fa-lock " + GuiStyleConstants.RED_COLOR); + builder.appendLayerIcon(icon, IconCssStyle.BOTTOM_RIGHT_FOR_COLUMN_STYLE); + builder.setTitle(pageBase.createStringResource("LockoutStatusType.LOCKED").getString() + + (StringUtils.isNotBlank(title) ? ("\n" + title) : "")); + return builder.build(); + } + + + ActivationStatusType value = activation.getAdministrativeStatus(); + builder.setTitle(pageBase.createStringResource("ActivationStatusType." +value).getString() + + (StringUtils.isNotBlank(title) ? ("\n" + title) : "")); + if(value == null) { + appendUndefinedIcon(builder); + return builder.build(); + } + + switch (value) { + case DISABLED: + appendIcon(builder, "fe fe-slash " + GuiStyleConstants.RED_COLOR, IconCssStyle.CENTER_FOR_COLUMN_STYLE); + return builder.build(); + case ARCHIVED: + appendIcon(builder, "fa fa-archive " + GuiStyleConstants.RED_COLOR, IconCssStyle.BOTTOM_RIGHT_FOR_COLUMN_STYLE); + return builder.build(); + } + + return builder.build(); + } + + private static void appendUndefinedIcon(CompositedIconBuilder builder) { + appendIcon(builder,"fa fa-question " + GuiStyleConstants.RED_COLOR, IconCssStyle.BOTTOM_RIGHT_FOR_COLUMN_STYLE); + + } + + private static void appendIcon(CompositedIconBuilder builder, String cssClass, LayeredIconCssStyle iconCssStyle) { + IconType icon = new IconType(); + icon.setCssClass(cssClass); + builder.appendLayerIcon(icon, iconCssStyle); + } + + private static String createTriggerTooltip(List triggers, PageBase pageBase) { + if (CollectionUtils.isEmpty(triggers)) { + return null; + } + + List triggerTooltips = new ArrayList<>(); + for (TriggerType trigger : triggers) { + XMLGregorianCalendar time = trigger.getTimestamp(); + + if (time == null) { + triggerTooltips.add(pageBase.getString("CheckTableHeader.triggerUnknownTime")); + } else { + triggerTooltips.add(pageBase.getString("CheckTableHeader.triggerPlanned", WebComponentUtil.formatDate(time))); + } + } + + return StringUtils.join(triggers, '\n'); + } + + private static void appendLifecycleState(StringBuilder title, IconType lifecycleStateIcon, O obj, PageBase pageBase) { + if (StringUtils.isEmpty(lifecycleStateIcon.getCssClass())) { + return; + } + + if (title.length() > 0){ + title.append("\n"); + } + title.append(pageBase.createStringResource("ObjectType.lifecycleState.title", obj.getLifecycleState()).getString()); + } + + private static void appendActivationStatus(StringBuilder title, IconType activationStatusIcon, O obj, PageBase pageBase) { + ActivationType activation = getActivation(obj); + if (StringUtils.isEmpty(activationStatusIcon.getCssClass()) || activation == null) { + return; + } + + if (title.length() > 0){ + title.append("\n"); + } + String lockedStatus = LockoutStatusType.LOCKED == activation.getLockoutStatus() ? activation.getLockoutStatus().value() : ""; + String effectiveStatus = activation.getEffectiveStatus() != null ? activation.getEffectiveStatus().value() : ""; + title.append(pageBase.createStringResource("CapabilitiesType.activationStatus").getString()) + .append(": ") + .append(StringUtils.isNotEmpty(lockedStatus) ? lockedStatus : effectiveStatus); + + } + + private static ActivationType getActivation(O obj) { + if (obj instanceof FocusType) { + return ((FocusType) obj).getActivation(); + } + + if (obj instanceof ShadowType) { + return ((ShadowType) obj).getActivation(); + } + + return null; + + } + public static IconType getIconForLifecycleState(O obj){ IconType icon = new IconType(); if (obj == null){ icon.setCssClass(""); return icon; } - if (SchemaConstants.LIFECYCLE_ARCHIVED.equals(obj.getLifecycleState())){ - icon.setCssClass(GuiStyleConstants.CLASS_FILE_EXCEL); - } else if (SchemaConstants.LIFECYCLE_DRAFT.equals(obj.getLifecycleState())){ - icon.setCssClass(GuiStyleConstants.CLASS_FILE_BLACK_FILLED); - } else if (SchemaConstants.LIFECYCLE_PROPOSED.equals(obj.getLifecycleState())){ - icon.setCssClass(GuiStyleConstants.CLASS_FILE_WHITE_FILLED); + String lifecycle = obj.getLifecycleState(); + if (lifecycle != null) { + switch (lifecycle) { + case SchemaConstants.LIFECYCLE_ARCHIVED: + icon.setCssClass(GuiStyleConstants.CLASS_FILE_EXCEL); + break; + case SchemaConstants.LIFECYCLE_DRAFT: + icon.setCssClass(GuiStyleConstants.CLASS_FILE_BLACK_FILLED); + break; + case SchemaConstants.LIFECYCLE_PROPOSED: + icon.setCssClass(GuiStyleConstants.CLASS_FILE_WHITE_FILLED); + break; + } } + if (icon.getCssClass() == null){ icon.setCssClass(""); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/icon/LayeredIconCssStyle.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/icon/LayeredIconCssStyle.java index 9e56ba14250..d6d03abe67a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/icon/LayeredIconCssStyle.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/icon/LayeredIconCssStyle.java @@ -1,19 +1,19 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.gui.impl.component.icon; - -/** - * @author skublik - */ -public interface LayeredIconCssStyle extends IconCssStyle { - - public String getBasicLayerCssClass(); - - public String getStrokeLayerCssClass(); - -} +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.gui.impl.component.icon; + +/** + * @author skublik + */ +public interface LayeredIconCssStyle extends IconCssStyle { + + String getBasicLayerCssClass(); + + String getStrokeLayerCssClass(); + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusProjectionsTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusProjectionsTabPanel.java index 6ef4de2659b..b33e77beffd 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusProjectionsTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusProjectionsTabPanel.java @@ -1,859 +1,774 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.component.objectdetails; - -import java.util.ArrayList; -import java.util.List; - -import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.model.api.AssignmentObjectRelation; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.Validate; -import org.apache.wicket.Component; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.markup.html.list.ListItem; -import org.apache.wicket.markup.html.panel.Fragment; -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.Model; -import org.apache.wicket.model.PropertyModel; - -import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; -import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; -import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl; -import com.evolveum.midpoint.gui.api.GuiStyleConstants; -import com.evolveum.midpoint.gui.api.component.DisplayNamePanel; -import com.evolveum.midpoint.gui.api.component.ObjectBrowserPanel; -import com.evolveum.midpoint.gui.api.component.PendingOperationPanel; -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.prism.ShadowWrapper; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.component.MultivalueContainerDetailsPanel; -import com.evolveum.midpoint.gui.impl.component.MultivalueContainerListPanelWithDetailsPanel; -import com.evolveum.midpoint.gui.impl.component.ProjectionDisplayNamePanel; -import com.evolveum.midpoint.gui.impl.component.data.column.PrismPropertyWrapperColumn; -import com.evolveum.midpoint.gui.impl.component.data.column.PrismReferenceWrapperColumn; -import com.evolveum.midpoint.gui.impl.component.data.column.AbstractItemWrapperColumn.ColumnType; -import com.evolveum.midpoint.gui.impl.component.icon.CompositedIcon; -import com.evolveum.midpoint.gui.impl.component.icon.CompositedIconBuilder; -import com.evolveum.midpoint.gui.impl.component.icon.IconCssStyle; -import com.evolveum.midpoint.gui.impl.component.data.column.CompositedIconColumn; -import com.evolveum.midpoint.gui.impl.component.data.column.PrismContainerWrapperColumn; -import com.evolveum.midpoint.gui.impl.factory.ItemRealValueModel; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismObjectValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.ShadowPanel; -import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContainerDefinition; -import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectDefinition; -import com.evolveum.midpoint.prism.PrismPropertyDefinition; -import com.evolveum.midpoint.prism.PrismPropertyValue; -import com.evolveum.midpoint.prism.PrismReferenceDefinition; -import com.evolveum.midpoint.prism.PrismValue; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.LoggingUtils; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.data.column.CheckBoxHeaderColumn; -import com.evolveum.midpoint.web.component.data.column.ColumnMenuAction; -import com.evolveum.midpoint.web.component.data.column.InlineMenuButtonColumn; -import com.evolveum.midpoint.web.component.dialog.ConfirmationPanel; -import com.evolveum.midpoint.web.component.dialog.Popupable; -import com.evolveum.midpoint.web.component.form.Form; -import com.evolveum.midpoint.web.component.menu.cog.ButtonInlineMenuItem; -import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItem; -import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItemAction; -import com.evolveum.midpoint.web.component.search.SearchItemDefinition; -import com.evolveum.midpoint.web.model.PrismPropertyWrapperModel; -import com.evolveum.midpoint.web.page.admin.PageAdminFocus; -import com.evolveum.midpoint.web.page.admin.users.dto.UserDtoStatus; -import com.evolveum.midpoint.web.session.PageStorage; -import com.evolveum.midpoint.web.session.UserProfileStorage; -import com.evolveum.midpoint.web.session.UserProfileStorage.TableId; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.IconType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LayerType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LockoutStatusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.PendingOperationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TriggerType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; - -/** - * @author semancik - * @author skublik - */ -public class FocusProjectionsTabPanel extends AbstractObjectTabPanel { - private static final long serialVersionUID = 1L; - - private static final String ID_SHADOW_TABLE = "shadowTable"; - private static final String ID_SHADOW_PANEL = "shadowPanel"; - protected static final String ID_SPECIFIC_CONTAINERS_FRAGMENT = "specificContainersFragment"; - - private static final String DOT_CLASS = FocusProjectionsTabPanel.class.getName() + "."; - private static final String OPERATION_ADD_ACCOUNT = DOT_CLASS + "addShadow"; - - private static final Trace LOGGER = TraceManager.getTrace(FocusProjectionsTabPanel.class); - - private LoadableModel> projectionModel; - - public FocusProjectionsTabPanel(String id, Form mainForm, LoadableModel> focusModel, - LoadableModel> projectionModel) { - super(id, mainForm, focusModel); - Validate.notNull(projectionModel, "Null projection model"); - this.projectionModel = projectionModel; - } - - @Override - protected void onInitialize() { - super.onInitialize(); - initLayout(); - } - - private PrismObjectDefinition getShadowDefinition() { - return getPrismContext().getSchemaRegistry().findObjectDefinitionByCompileTimeClass(ShadowType.class); - } - - private void initLayout() { - - TableId tableId = UserProfileStorage.TableId.FOCUS_PROJECTION_TABLE; - PageStorage pageStorage = getPageBase().getSessionStorage().getFocusProjectionTableStorage(); - - - MultivalueContainerListPanelWithDetailsPanel multivalueContainerListPanel = - new MultivalueContainerListPanelWithDetailsPanel(ID_SHADOW_TABLE, getShadowDefinition(), - tableId, pageStorage) { - - private static final long serialVersionUID = 1L; - - @Override - protected IModel>> loadValuesModel() { - return new IModel>>() { - - private static final long serialVersionUID = 1L; - - @Override - public List> getObject() { - List> items = new ArrayList>(); - for (ShadowWrapper projection : projectionModel.getObject()) { - items.add(projection.getValue()); - } - return items; - } - }; - - } - - @Override - protected List> postSearch( - List> items) { - - return items; - } - - @Override - protected void newItemPerformed(AjaxRequestTarget target, AssignmentObjectRelation relation) { - List supportedTypes = new ArrayList<>(1); - supportedTypes.add(ResourceType.COMPLEX_TYPE); - PageBase pageBase = FocusProjectionsTabPanel.this.getPageBase(); - ObjectBrowserPanel resourceSelectionPanel = new ObjectBrowserPanel( - pageBase.getMainPopupBodyId(), ResourceType.class, supportedTypes, true, - pageBase) { - - private static final long serialVersionUID = 1L; - - @Override - protected void addPerformed(AjaxRequestTarget target, QName type, - List selected) { - FocusProjectionsTabPanel.this.addSelectedAccountPerformed(target, - selected); - } - }; - resourceSelectionPanel.setOutputMarkupId(true); - pageBase.showMainPopup(resourceSelectionPanel, - target); - } - - @Override - protected void initPaging() { - FocusProjectionsTabPanel.this.initPaging(); - } - - @Override - protected boolean enableActionNewObject() { - PrismObjectDefinition def = getObjectWrapper().getObject().getDefinition(); - PrismReferenceDefinition ref = def.findReferenceDefinition(UserType.F_LINK_REF); - return (ref.canRead() && ref.canAdd()); - } - - @Override - protected ObjectQuery createQuery() { - return null; - } - - @Override - protected List, String>> createColumns() { - return initBasicColumns(); - } - - @Override - public void itemPerformedForDefaultAction(AjaxRequestTarget target, - IModel> rowModel, - List> listItems) { - - if(rowModel != null && rowModel.getObject() != null - && ((ShadowWrapper)rowModel.getObject().getParent()).isLoadWithNoFetch()) { - ((PageAdminFocus) getPage()).loadFullShadow((PrismObjectValueWrapper)rowModel.getObject(), target); - } - - if(listItems != null) { - listItems.forEach(value -> { - if(((ShadowWrapper)value.getParent()).isLoadWithNoFetch()) { - ((PageAdminFocus) getPage()).loadFullShadow((PrismObjectValueWrapper)value, target); - } - }); - } - super.itemPerformedForDefaultAction(target, rowModel, listItems); - } - - @Override - protected List initSearchableItems( - PrismContainerDefinition containerDef) { - List defs = new ArrayList<>(); - - return defs; - } - - @Override - protected MultivalueContainerDetailsPanel getMultivalueContainerDetailsPanel( - ListItem> item) { - return FocusProjectionsTabPanel.this.getMultivalueContainerDetailsPanel(item); - } - }; - add(multivalueContainerListPanel); - setOutputMarkupId(true); - } - - private void initPaging() { - getPageBase().getSessionStorage().getFocusProjectionTableStorage().setPaging( - getPrismContext().queryFactory().createPaging(0, (int) ((PageBase)getPage()).getItemsPerPage(UserProfileStorage.TableId.FOCUS_PROJECTION_TABLE))); - } - - private MultivalueContainerDetailsPanel getMultivalueContainerDetailsPanel( - ListItem> item) { - MultivalueContainerDetailsPanel detailsPanel = new MultivalueContainerDetailsPanel(MultivalueContainerListPanelWithDetailsPanel.ID_ITEM_DETAILS, item.getModel()) { - - private static final long serialVersionUID = 1L; - - @Override - protected DisplayNamePanel createDisplayNamePanel(String displayNamePanelId) { - ItemRealValueModel displayNameModel = - new ItemRealValueModel(item.getModel()); - return new ProjectionDisplayNamePanel(displayNamePanelId, displayNameModel); - } - - @Override - protected void addBasicContainerValuePanel(String idPanel) { - add(new WebMarkupContainer(idPanel)); - } - - @Override - protected WebMarkupContainer getSpecificContainers(String contentAreaId) { - Fragment specificContainers = new Fragment(contentAreaId, ID_SPECIFIC_CONTAINERS_FRAGMENT, FocusProjectionsTabPanel.this); - - ShadowPanel shadowPanel = new ShadowPanel(ID_SHADOW_PANEL, getParentModel(getModel())); - specificContainers.add(shadowPanel); - return specificContainers; - } - }; - return detailsPanel; - } - - private IModel getParentModel(IModel> model){ - return new PropertyModel(model, "parent"); - } - - private String createTriggerTooltip(PrismContainer container) { - if (container == null || container.isEmpty()) { - return null; - } - - List triggers = new ArrayList<>(); - for (PrismContainerValue val : container.getValues()) { - XMLGregorianCalendar time = val.getPropertyRealValue(TriggerType.F_TIMESTAMP, XMLGregorianCalendar.class); - - if (time == null) { - triggers.add(getString("CheckTableHeader.triggerUnknownTime")); - } else { - triggers.add(getString("CheckTableHeader.triggerPlanned", WebComponentUtil.formatDate(time))); - } - } - - return StringUtils.join(triggers, '\n'); - } - - private CompositedIcon createAccountIcon(IModel> prismContainerValue) { - PrismObject obj = ((PrismObjectWrapper)prismContainerValue.getObject().getParent()).getObject(); - PrismContainer container = obj.findContainer(ObjectType.F_TRIGGER); - String iconCssClass = WebComponentUtil.createShadowIcon(prismContainerValue.getObject().getNewValue()); - CompositedIconBuilder builder = new CompositedIconBuilder(); - String title = createTriggerTooltip(container); - if(StringUtils.isNotBlank(title)) { - IconType icon = new IconType(); - icon.setCssClass("fa fa-clock-o " + GuiStyleConstants.BLUE_COLOR); - builder.appendLayerIcon(icon, IconCssStyle.TOP_RIGHT_FOR_COLUMN_STYLE); - } - builder.setBasicIcon(iconCssClass, IconCssStyle.BOTTOM_RIGHT_FOR_COLUMN_STYLE); - - IModel deadStatus = new PropertyModel(PrismPropertyWrapperModel.fromContainerValueWrapper( - prismContainerValue, ItemPath.create(ShadowType.F_DEAD)), "value"); - if(deadStatus != null && Boolean.TRUE.equals(deadStatus.getObject().getRealValue())) { - IconType icon = new IconType(); - icon.setCssClass("fa fa-times-circle " + GuiStyleConstants.RED_COLOR); - builder.appendLayerIcon(icon, IconCssStyle.BOTTOM_RIGHT_FOR_COLUMN_STYLE); - builder.setTitle(getPageBase().createStringResource("FocusProjectionsTabPanel.deadShadow").getString() - + (StringUtils.isNotBlank(title) ? ("\n" + title) : "")); - return builder.build(); - } - - IModel lockoutStatus = new PropertyModel(PrismPropertyWrapperModel.fromContainerValueWrapper( - prismContainerValue, ItemPath.create(ShadowType.F_ACTIVATION, ActivationType.F_LOCKOUT_STATUS)), "value"); - IModel lockoutTimeStatus = new PropertyModel(PrismPropertyWrapperModel.fromContainerValueWrapper( - prismContainerValue, ItemPath.create(ShadowType.F_ACTIVATION, ActivationType.F_LOCKOUT_EXPIRATION_TIMESTAMP)), "value"); - if((lockoutStatus != null && LockoutStatusType.LOCKED.equals(lockoutStatus.getObject().getRealValue())) - || (lockoutTimeStatus.getObject() != null && lockoutTimeStatus.getObject().getRealValue() != null - && getPageBase().getClock().isPast(((XMLGregorianCalendar)lockoutTimeStatus.getObject().getRealValue())))) { - IconType icon = new IconType(); - icon.setCssClass("fa fa-lock " + GuiStyleConstants.RED_COLOR); - builder.appendLayerIcon(icon, IconCssStyle.BOTTOM_RIGHT_FOR_COLUMN_STYLE); - builder.setTitle(getPageBase().createStringResource("LockoutStatusType.LOCKED").getString() - + (StringUtils.isNotBlank(title) ? ("\n" + title) : "")); - return builder.build(); - } - - IModel status = new PropertyModel(PrismPropertyWrapperModel.fromContainerValueWrapper( - prismContainerValue, ItemPath.create(ShadowType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS)), "value"); - ActivationStatusType value = null; - if (status != null) { - value = (ActivationStatusType) status.getObject().getRealValue(); - } - builder.setTitle(getPageBase().createStringResource("ActivationStatusType." +value).getString() - + (StringUtils.isNotBlank(title) ? ("\n" + title) : "")); - if(value == null) { - IconType icon = new IconType(); - icon.setCssClass("fa fa-question " + GuiStyleConstants.RED_COLOR); - builder.appendLayerIcon(icon, IconCssStyle.BOTTOM_RIGHT_FOR_COLUMN_STYLE); - return builder.build(); - } - if (ActivationStatusType.DISABLED.equals(value)) { - IconType icon = new IconType(); - icon.setCssClass("fe fe-slash " + GuiStyleConstants.RED_COLOR); - builder.appendLayerIcon(icon, IconCssStyle.CENTER_FOR_COLUMN_STYLE); - return builder.build(); - } - - if (ActivationStatusType.ARCHIVED.equals(value)) { - IconType icon = new IconType(); - icon.setCssClass("fa fa-archive " + GuiStyleConstants.RED_COLOR); - builder.appendLayerIcon(icon, IconCssStyle.BOTTOM_RIGHT_FOR_COLUMN_STYLE); - return builder.build(); - } - return builder.build(); - } - - private List, String>> initBasicColumns() { - - IModel> shadowDef = Model.of(getShadowDefinition()); - - List, String>> columns = new ArrayList<>(); - columns.add(new CheckBoxHeaderColumn<>()); - columns.add(new CompositedIconColumn>(Model.of("")) { - - private static final long serialVersionUID = 1L; - - @Override - protected CompositedIcon getCompositedIcon(IModel> rowModel) { - return createAccountIcon(rowModel); - } - - }); - - columns.add(new PrismPropertyWrapperColumn(shadowDef, ShadowType.F_NAME, ColumnType.LINK, getPageBase()){ - private static final long serialVersionUID = 1L; - - @Override - protected void onClick(AjaxRequestTarget target, IModel> rowModel) { - getMultivalueContainerListPanel().itemDetailsPerformed(target, rowModel); - target.add(getFeedbackPanel()); - } - }); - columns.add(new PrismReferenceWrapperColumn(shadowDef, ShadowType.F_RESOURCE_REF, ColumnType.STRING, getPageBase())); - columns.add(new PrismPropertyWrapperColumn(shadowDef, ShadowType.F_OBJECT_CLASS, ColumnType.STRING, getPageBase())); - columns.add(new PrismPropertyWrapperColumn(shadowDef, ShadowType.F_KIND, ColumnType.STRING, getPageBase()){ - @Override - public String getCssClass() - { - return "col-xs-1"; - } - }); - columns.add(new PrismPropertyWrapperColumn(shadowDef, ShadowType.F_INTENT, ColumnType.STRING, getPageBase()){ - @Override - public String getCssClass() - { - return "col-xs-1"; - } - }); - columns.add(new PrismContainerWrapperColumn(shadowDef, ShadowType.F_PENDING_OPERATION, getPageBase()) { - @Override - public String getCssClass() - { - return "col-xs-2"; - } - - @Override - protected Component createColumnPanel(String componentId, IModel rowModel) { - IW object = rowModel.getObject(); - List> values = object.getValues(); - List pendingOperations = new ArrayList(); - values.forEach(value -> { - pendingOperations.add(value.getRealValue()); - }); - return new PendingOperationPanel(componentId, new IModel>() { - - @Override - public List getObject() { - return pendingOperations; - } - }); - } - }); - - columns.add(new InlineMenuButtonColumn(createShadowMenu(), getPageBase()) { - @Override - public String getCssClass() - { - return "col-xs-1"; - } - }); - - return columns; - } - - private MultivalueContainerListPanelWithDetailsPanel getMultivalueContainerListPanel(){ - return ((MultivalueContainerListPanelWithDetailsPanel)get(ID_SHADOW_TABLE)); - } - - - - private void addSelectedAccountPerformed(AjaxRequestTarget target, List newResources) { - getPageBase().hideMainPopup(target); - - if (newResources.isEmpty()) { - warn(getString("pageUser.message.noResourceSelected")); - return; - } - - for (ResourceType resource : newResources) { - try { - ShadowType shadow = new ShadowType(); - ObjectReferenceType resourceRef = new ObjectReferenceType(); - resourceRef.asReferenceValue().setObject(resource.asPrismObject()); - shadow.setResourceRef(resourceRef); - ResourceType usedResource = resource; - - RefinedResourceSchema refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema( - resource.asPrismObject(), LayerType.PRESENTATION, getPrismContext()); - if (refinedSchema == null) { - Task task = getPageBase().createSimpleTask(FocusPersonasTabPanel.class.getSimpleName() + ".loadResource"); - OperationResult result = task.getResult(); - PrismObject loadedResource = WebModelServiceUtils.loadObject(ResourceType.class, resource.getOid(), getPageBase(), task, result); - result.recomputeStatus(); - - refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema( - loadedResource, LayerType.PRESENTATION, getPrismContext()); - - if (refinedSchema == null) { - error(getString("pageAdminFocus.message.couldntCreateAccountNoSchema", - resource.getName())); - continue; - } - -// shadow.setResource(loadedResource.asObjectable()); - usedResource = loadedResource.asObjectable(); - } - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Refined schema for {}\n{}", resource, refinedSchema.debugDump()); - } - - RefinedObjectClassDefinition accountDefinition = refinedSchema - .getDefaultRefinedDefinition(ShadowKindType.ACCOUNT); - if (accountDefinition == null) { - error(getString("pageAdminFocus.message.couldntCreateAccountNoAccountSchema", - resource.getName())); - continue; - } -// shadow.asPrismContainer().findOrCreateContainer(ShadowType.F_ATTRIBUTES).applyDefinition(accountDefinition.toResourceAttributeContainerDefinition()); - QName objectClass = accountDefinition.getObjectClassDefinition().getTypeName(); - ObjectReferenceType usedResourceRef = new ObjectReferenceType(); - usedResourceRef.asReferenceValue().setObject(usedResource.asPrismObject()); - shadow.setResourceRef(usedResourceRef); - shadow.setObjectClass(objectClass); - shadow.setIntent(accountDefinition.getObjectClassDefinition().getIntent()); - shadow.setKind(accountDefinition.getObjectClassDefinition().getKind()); - getPrismContext().adopt(shadow); - - Task task = getPageBase().createSimpleTask(OPERATION_ADD_ACCOUNT); - PrismObjectWrapperFactory factory = getPageBase().getRegistry().getObjectWrapperFactory(shadow.asPrismContainer().getDefinition()); - WrapperContext context = new WrapperContext(task, task.getResult()); - ShadowWrapper wrappernew = (ShadowWrapper) factory.createObjectWrapper(shadow.asPrismContainer(), ItemStatus.ADDED, context); - if (task.getResult() != null - && !WebComponentUtil.isSuccessOrHandledError(task.getResult())) { - showResult(task.getResult(), false); - } - - wrappernew.setProjectionStatus(UserDtoStatus.ADD); - projectionModel.getObject().add(wrappernew); - } catch (Exception ex) { - error(getString("pageAdminFocus.message.couldntCreateAccount", resource.getName(), - ex.getMessage())); - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't create account", ex); - } - } - target.add(getMultivalueContainerListPanel()); - } - - private IModel> createEmptyShadowWrapperModel() { - ShadowType shadow = new ShadowType(); - ShadowWrapper wrapper = null; - Task task = getPageBase().createSimpleTask("create empty shadow wrapper"); - try { - getPageBase().getPrismContext().adopt(shadow); - wrapper = ((PageAdminFocus) getPage()).loadShadowWrapper(shadow.asPrismContainer(), task, task.getResult()); - } catch (SchemaException e) { - getPageBase().showResult(task.getResult(), "pageAdminFocus.message.couldntCreateShadowWrapper"); - LOGGER.error("Couldn't create shadow wrapper", e); - } - final ShadowWrapper ret = wrapper; - return new IModel>() { - - @Override - public PrismContainerWrapper getObject() { - return ret; - } - }; - } - - private List createShadowMenu() { - List items = new ArrayList<>(); - - PrismObjectDefinition def = getObjectWrapper().getObject().getDefinition(); - PrismReferenceDefinition ref = def.findReferenceDefinition(UserType.F_LINK_REF); - InlineMenuItem item; - PrismPropertyDefinition administrativeStatus = def - .findPropertyDefinition(SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS); - if (administrativeStatus.canRead() && administrativeStatus.canModify()) { - item = new ButtonInlineMenuItem(createStringResource("pageAdminFocus.button.enable")) { - private static final long serialVersionUID = 1L; - - @Override - public InlineMenuItemAction initAction() { - return new ColumnMenuAction() { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget target) { - updateShadowActivation(target, getMultivalueContainerListPanel() - .getPerformedSelectedItems(getRowModel()), true); - } - }; - } - - @Override - public String getButtonIconCssClass() { - return "fa fa-check"; - } - }; - items.add(item); - item = new InlineMenuItem(createStringResource("pageAdminFocus.button.disable")) { - private static final long serialVersionUID = 1L; - - @Override - public InlineMenuItemAction initAction() { - return new ColumnMenuAction() { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget target) { - updateShadowActivation(target, getMultivalueContainerListPanel() - .getPerformedSelectedItems(getRowModel()), false); - } - }; - } - }; - items.add(item); - } - if (ref.canRead() && ref.canAdd()) { - item = new InlineMenuItem(createStringResource("pageAdminFocus.button.unlink")) { - private static final long serialVersionUID = 1L; - - @Override - public InlineMenuItemAction initAction() { - return new ColumnMenuAction() { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget target) { - unlinkProjectionPerformed(target,getMultivalueContainerListPanel() - .getPerformedSelectedItems(getRowModel())); - } - }; - } - }; - items.add(item); - } - PrismPropertyDefinition locakoutStatus = def.findPropertyDefinition(SchemaConstants.PATH_ACTIVATION_LOCKOUT_STATUS); - if (locakoutStatus.canRead() && locakoutStatus.canModify()) { - item = new InlineMenuItem(createStringResource("pageAdminFocus.button.unlock")) { - private static final long serialVersionUID = 1L; - - @Override - public InlineMenuItemAction initAction() { - return new ColumnMenuAction() { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget target) { - unlockShadowPerformed(target,getMultivalueContainerListPanel() - .getPerformedSelectedItems(getRowModel())); - } - }; - } - }; - items.add(item); - } - if (administrativeStatus.canRead() && administrativeStatus.canModify()) { -// items.add(new InlineMenuItem()); - item = new InlineMenuItem(createStringResource("pageAdminFocus.button.delete")) { - private static final long serialVersionUID = 1L; - - @Override - public InlineMenuItemAction initAction() { - return new ColumnMenuAction() { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget target) { - deleteProjectionPerformed(target, getMultivalueContainerListPanel() - .getPerformedSelectedItems(getRowModel())); - } - }; - } - }; - items.add(item); - } - item = new ButtonInlineMenuItem(createStringResource("PageBase.button.edit")) { - private static final long serialVersionUID = 1L; - - @Override - public String getButtonIconCssClass() { - return GuiStyleConstants.CLASS_EDIT_MENU_ITEM; - } - - @Override - public InlineMenuItemAction initAction() { - return new ColumnMenuAction() { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget target) { - getMultivalueContainerListPanel().itemPerformedForDefaultAction(target, - getRowModel(), getMultivalueContainerListPanel().getSelectedItems()); - target.add(getFeedbackPanel()); - } - }; - } - }; - items.add(item); - return items; - } - - private void deleteProjectionPerformed(AjaxRequestTarget target, - List> selected) { - if (!isAnyProjectionSelected(target, selected)) { - return; - } - - showModalWindow(getDeleteProjectionPopupContent(selected), - target); - } - - private boolean isAnyProjectionSelected(AjaxRequestTarget target, - List> selected) { - if (selected.isEmpty()) { - warn(getString("pageAdminFocus.message.noAccountSelected")); - target.add(getFeedbackPanel()); - return false; - } - - return true; - } - - private void updateShadowActivation(AjaxRequestTarget target, - List> accounts, boolean enabled) { - - if (!isAnyProjectionSelected(target, accounts)) { - return; - } - - for (PrismContainerValueWrapper account : accounts) { -// if (!account.isLoadedOK()) { -// continue; -// } - try { -// ObjectWrapperOld wrapper = account.getObjectOld(); -// PrismObjectWrapper wrapper = account.getObject(); - PrismContainerWrapper activation = account - .findContainer(ShadowType.F_ACTIVATION); - if (activation == null) { - warn(getString("pageAdminFocus.message.noActivationFound")); - continue; - } - - PrismPropertyWrapper enabledProperty = (PrismPropertyWrapper) activation.getValues().iterator().next() - .findProperty(ActivationType.F_ADMINISTRATIVE_STATUS); - if (enabledProperty == null || enabledProperty.getValues().size() != 1) { - warn(getString("pageAdminFocus.message.noEnabledPropertyFound", account.getDisplayName())); - continue; - } - PrismValueWrapper value = (PrismValueWrapper) enabledProperty.getValues().get(0); - ActivationStatusType status = enabled ? ActivationStatusType.ENABLED - : ActivationStatusType.DISABLED; - ((PrismPropertyValue) value.getNewValue()).setValue(status); - - } catch (SchemaException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - -// wrapper.setSelected(false); - } - info(getString("pageAdminFocus.message.updated." + enabled)); - target.add(getFeedbackPanel(), getMultivalueContainerListPanel()); - } - - private void unlockShadowPerformed(AjaxRequestTarget target, - List> selected) { - if (!isAnyProjectionSelected(target, selected)) { - return; - } - - for (PrismContainerValueWrapper account : selected) { -// if (!account.isLoadedOK()) { -// continue; -// } - try { -// ObjectWrapperOld wrapper = account.getObjectOld(); -// PrismObjectWrapper wrapper = account.getObject(); -// wrapper.setSelected(false); - - PrismContainerWrapper activation = account.findContainer(ShadowType.F_ACTIVATION); - if (activation == null) { - warn(getString("pageAdminFocus.message.noActivationFound", account.getDisplayName())); - continue; - } - - PrismPropertyWrapper lockedProperty = (PrismPropertyWrapper) activation.getValues().iterator().next().findProperty(ActivationType.F_LOCKOUT_STATUS); - if (lockedProperty == null || lockedProperty.getValues().size() != 1) { - warn(getString("pageAdminFocus.message.noLockoutStatusPropertyFound")); - continue; - } - PrismValueWrapper value = (PrismValueWrapper) lockedProperty.getValues().get(0); - ((PrismPropertyValue) value.getNewValue()).setValue(LockoutStatusType.NORMAL); - } catch (SchemaException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - }// TODO only for really unlocked accounts - } - info(getString("pageAdminFocus.message.unlocked")); - target.add(getFeedbackPanel(), getMultivalueContainerListPanel()); - } - - private void unlinkProjectionPerformed(AjaxRequestTarget target, - List> selected) { - if (!isAnyProjectionSelected(target, selected)) { - return; - } - - for (PrismContainerValueWrapper projection : selected) { - if (UserDtoStatus.ADD.equals(((ShadowWrapper)projection.getParent()).getProjectionStatus())) { - continue; - } - ((ShadowWrapper)projection.getParent()).setProjectionStatus(UserDtoStatus.UNLINK); - } - target.add(getMultivalueContainerListPanel()); - } - - private Popupable getDeleteProjectionPopupContent(List> selected) { - ConfirmationPanel dialog = new ConfirmationPanel(getPageBase().getMainPopupBodyId(), - new IModel() { - private static final long serialVersionUID = 1L; - - @Override - public String getObject() { - return createStringResource("pageAdminFocus.message.deleteAccountConfirm", - selected.size()).getString(); - } - }) { - private static final long serialVersionUID = 1L; - - @Override - public void yesPerformed(AjaxRequestTarget target) { - deleteAccountConfirmedPerformed(target, selected); - } - }; - return dialog; - } - - private void deleteAccountConfirmedPerformed(AjaxRequestTarget target, - List> selected) { - List accounts = projectionModel.getObject(); - for (PrismContainerValueWrapper account : selected) { - if (UserDtoStatus.ADD.equals(((ShadowWrapper)account.getParent()).getProjectionStatus())) { - accounts.remove(account.getParent()); - } else { - ((ShadowWrapper)account.getParent()).setProjectionStatus(UserDtoStatus.DELETE); - } - } - target.add(getMultivalueContainerListPanel()); - } -} +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.component.objectdetails; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.model.api.AssignmentObjectRelation; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.Validate; +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.panel.Fragment; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.PropertyModel; + +import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; +import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; +import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl; +import com.evolveum.midpoint.gui.api.GuiStyleConstants; +import com.evolveum.midpoint.gui.api.component.DisplayNamePanel; +import com.evolveum.midpoint.gui.api.component.ObjectBrowserPanel; +import com.evolveum.midpoint.gui.api.component.PendingOperationPanel; +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.gui.api.page.PageBase; +import com.evolveum.midpoint.gui.api.prism.ItemStatus; +import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.ShadowWrapper; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; +import com.evolveum.midpoint.gui.impl.component.MultivalueContainerDetailsPanel; +import com.evolveum.midpoint.gui.impl.component.MultivalueContainerListPanelWithDetailsPanel; +import com.evolveum.midpoint.gui.impl.component.ProjectionDisplayNamePanel; +import com.evolveum.midpoint.gui.impl.component.data.column.PrismPropertyWrapperColumn; +import com.evolveum.midpoint.gui.impl.component.data.column.PrismReferenceWrapperColumn; +import com.evolveum.midpoint.gui.impl.component.data.column.AbstractItemWrapperColumn.ColumnType; +import com.evolveum.midpoint.gui.impl.component.icon.CompositedIcon; +import com.evolveum.midpoint.gui.impl.component.icon.CompositedIconBuilder; +import com.evolveum.midpoint.gui.impl.component.icon.IconCssStyle; +import com.evolveum.midpoint.gui.impl.component.data.column.CompositedIconColumn; +import com.evolveum.midpoint.gui.impl.component.data.column.PrismContainerWrapperColumn; +import com.evolveum.midpoint.gui.impl.factory.ItemRealValueModel; +import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.impl.factory.WrapperContext; +import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.impl.prism.PrismObjectValueWrapper; +import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; +import com.evolveum.midpoint.gui.impl.prism.ShadowPanel; +import com.evolveum.midpoint.prism.PrismContainer; +import com.evolveum.midpoint.prism.PrismContainerDefinition; +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismObjectDefinition; +import com.evolveum.midpoint.prism.PrismPropertyDefinition; +import com.evolveum.midpoint.prism.PrismPropertyValue; +import com.evolveum.midpoint.prism.PrismReferenceDefinition; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.component.data.column.CheckBoxHeaderColumn; +import com.evolveum.midpoint.web.component.data.column.ColumnMenuAction; +import com.evolveum.midpoint.web.component.data.column.InlineMenuButtonColumn; +import com.evolveum.midpoint.web.component.dialog.ConfirmationPanel; +import com.evolveum.midpoint.web.component.dialog.Popupable; +import com.evolveum.midpoint.web.component.form.Form; +import com.evolveum.midpoint.web.component.menu.cog.ButtonInlineMenuItem; +import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItem; +import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItemAction; +import com.evolveum.midpoint.web.component.search.SearchItemDefinition; +import com.evolveum.midpoint.web.model.PrismPropertyWrapperModel; +import com.evolveum.midpoint.web.page.admin.PageAdminFocus; +import com.evolveum.midpoint.web.page.admin.users.dto.UserDtoStatus; +import com.evolveum.midpoint.web.session.PageStorage; +import com.evolveum.midpoint.web.session.UserProfileStorage; +import com.evolveum.midpoint.web.session.UserProfileStorage.TableId; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.IconType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LayerType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LockoutStatusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PendingOperationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TriggerType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; + +/** + * @author semancik + * @author skublik + */ +public class FocusProjectionsTabPanel extends AbstractObjectTabPanel { + private static final long serialVersionUID = 1L; + + private static final String ID_SHADOW_TABLE = "shadowTable"; + private static final String ID_SHADOW_PANEL = "shadowPanel"; + protected static final String ID_SPECIFIC_CONTAINERS_FRAGMENT = "specificContainersFragment"; + + private static final String DOT_CLASS = FocusProjectionsTabPanel.class.getName() + "."; + private static final String OPERATION_ADD_ACCOUNT = DOT_CLASS + "addShadow"; + + private static final Trace LOGGER = TraceManager.getTrace(FocusProjectionsTabPanel.class); + + private LoadableModel> projectionModel; + + public FocusProjectionsTabPanel(String id, Form mainForm, LoadableModel> focusModel, + LoadableModel> projectionModel) { + super(id, mainForm, focusModel); + Validate.notNull(projectionModel, "Null projection model"); + this.projectionModel = projectionModel; + } + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(); + } + + private PrismObjectDefinition getShadowDefinition() { + return getPrismContext().getSchemaRegistry().findObjectDefinitionByCompileTimeClass(ShadowType.class); + } + + private void initLayout() { + + TableId tableId = UserProfileStorage.TableId.FOCUS_PROJECTION_TABLE; + PageStorage pageStorage = getPageBase().getSessionStorage().getFocusProjectionTableStorage(); + + + MultivalueContainerListPanelWithDetailsPanel multivalueContainerListPanel = + new MultivalueContainerListPanelWithDetailsPanel(ID_SHADOW_TABLE, getShadowDefinition(), + tableId, pageStorage) { + + private static final long serialVersionUID = 1L; + + @Override + protected IModel>> loadValuesModel() { + return new IModel>>() { + + private static final long serialVersionUID = 1L; + + @Override + public List> getObject() { + List> items = new ArrayList>(); + for (ShadowWrapper projection : projectionModel.getObject()) { + items.add(projection.getValue()); + } + return items; + } + }; + + } + + @Override + protected List> postSearch( + List> items) { + + return items; + } + + @Override + protected void newItemPerformed(AjaxRequestTarget target, AssignmentObjectRelation relation) { + List supportedTypes = new ArrayList<>(1); + supportedTypes.add(ResourceType.COMPLEX_TYPE); + PageBase pageBase = FocusProjectionsTabPanel.this.getPageBase(); + ObjectBrowserPanel resourceSelectionPanel = new ObjectBrowserPanel( + pageBase.getMainPopupBodyId(), ResourceType.class, supportedTypes, true, + pageBase) { + + private static final long serialVersionUID = 1L; + + @Override + protected void addPerformed(AjaxRequestTarget target, QName type, + List selected) { + FocusProjectionsTabPanel.this.addSelectedAccountPerformed(target, + selected); + } + }; + resourceSelectionPanel.setOutputMarkupId(true); + pageBase.showMainPopup(resourceSelectionPanel, + target); + } + + @Override + protected void initPaging() { + FocusProjectionsTabPanel.this.initPaging(); + } + + @Override + protected boolean enableActionNewObject() { + PrismObjectDefinition def = getObjectWrapper().getObject().getDefinition(); + PrismReferenceDefinition ref = def.findReferenceDefinition(UserType.F_LINK_REF); + return (ref.canRead() && ref.canAdd()); + } + + @Override + protected ObjectQuery createQuery() { + return null; + } + + @Override + protected List, String>> createColumns() { + return initBasicColumns(); + } + + @Override + public void itemPerformedForDefaultAction(AjaxRequestTarget target, + IModel> rowModel, + List> listItems) { + + if(rowModel != null && rowModel.getObject() != null + && ((ShadowWrapper)rowModel.getObject().getParent()).isLoadWithNoFetch()) { + ((PageAdminFocus) getPage()).loadFullShadow((PrismObjectValueWrapper)rowModel.getObject(), target); + } + + if(listItems != null) { + listItems.forEach(value -> { + if(((ShadowWrapper)value.getParent()).isLoadWithNoFetch()) { + ((PageAdminFocus) getPage()).loadFullShadow((PrismObjectValueWrapper)value, target); + } + }); + } + super.itemPerformedForDefaultAction(target, rowModel, listItems); + } + + @Override + protected List initSearchableItems( + PrismContainerDefinition containerDef) { + List defs = new ArrayList<>(); + + return defs; + } + + @Override + protected MultivalueContainerDetailsPanel getMultivalueContainerDetailsPanel( + ListItem> item) { + return FocusProjectionsTabPanel.this.getMultivalueContainerDetailsPanel(item); + } + }; + add(multivalueContainerListPanel); + setOutputMarkupId(true); + } + + private void initPaging() { + getPageBase().getSessionStorage().getFocusProjectionTableStorage().setPaging( + getPrismContext().queryFactory().createPaging(0, (int) ((PageBase)getPage()).getItemsPerPage(UserProfileStorage.TableId.FOCUS_PROJECTION_TABLE))); + } + + private MultivalueContainerDetailsPanel getMultivalueContainerDetailsPanel( + ListItem> item) { + MultivalueContainerDetailsPanel detailsPanel = new MultivalueContainerDetailsPanel(MultivalueContainerListPanelWithDetailsPanel.ID_ITEM_DETAILS, item.getModel()) { + + private static final long serialVersionUID = 1L; + + @Override + protected DisplayNamePanel createDisplayNamePanel(String displayNamePanelId) { + ItemRealValueModel displayNameModel = + new ItemRealValueModel(item.getModel()); + return new ProjectionDisplayNamePanel(displayNamePanelId, displayNameModel); + } + + @Override + protected void addBasicContainerValuePanel(String idPanel) { + add(new WebMarkupContainer(idPanel)); + } + + @Override + protected WebMarkupContainer getSpecificContainers(String contentAreaId) { + Fragment specificContainers = new Fragment(contentAreaId, ID_SPECIFIC_CONTAINERS_FRAGMENT, FocusProjectionsTabPanel.this); + + ShadowPanel shadowPanel = new ShadowPanel(ID_SHADOW_PANEL, getParentModel(getModel())); + specificContainers.add(shadowPanel); + return specificContainers; + } + }; + return detailsPanel; + } + + private IModel getParentModel(IModel> model){ + return new PropertyModel(model, "parent"); + } + + private List, String>> initBasicColumns() { + + IModel> shadowDef = Model.of(getShadowDefinition()); + + List, String>> columns = new ArrayList<>(); + columns.add(new CheckBoxHeaderColumn<>()); + columns.add(new CompositedIconColumn>(Model.of("")) { + + private static final long serialVersionUID = 1L; + + @Override + protected CompositedIcon getCompositedIcon(IModel> rowModel) { + if (rowModel == null || rowModel.getObject() == null || rowModel.getObject().getRealValue() == null) { + return new CompositedIconBuilder().build(); + } + return WebComponentUtil.createAccountIcon(rowModel.getObject().getRealValue(), getPageBase()); + } + + }); + + columns.add(new PrismPropertyWrapperColumn(shadowDef, ShadowType.F_NAME, ColumnType.LINK, getPageBase()){ + private static final long serialVersionUID = 1L; + + @Override + protected void onClick(AjaxRequestTarget target, IModel> rowModel) { + getMultivalueContainerListPanel().itemDetailsPerformed(target, rowModel); + target.add(getFeedbackPanel()); + } + }); + columns.add(new PrismReferenceWrapperColumn(shadowDef, ShadowType.F_RESOURCE_REF, ColumnType.STRING, getPageBase())); + columns.add(new PrismPropertyWrapperColumn(shadowDef, ShadowType.F_OBJECT_CLASS, ColumnType.STRING, getPageBase())); + columns.add(new PrismPropertyWrapperColumn(shadowDef, ShadowType.F_KIND, ColumnType.STRING, getPageBase()){ + @Override + public String getCssClass() + { + return "col-xs-1"; + } + }); + columns.add(new PrismPropertyWrapperColumn(shadowDef, ShadowType.F_INTENT, ColumnType.STRING, getPageBase()){ + @Override + public String getCssClass() + { + return "col-xs-1"; + } + }); + columns.add(new PrismContainerWrapperColumn(shadowDef, ShadowType.F_PENDING_OPERATION, getPageBase()) { + @Override + public String getCssClass() + { + return "col-xs-2"; + } + + @Override + protected Component createColumnPanel(String componentId, IModel rowModel) { + IW object = rowModel.getObject(); + List> values = object.getValues(); + List pendingOperations = new ArrayList(); + values.forEach(value -> { + pendingOperations.add(value.getRealValue()); + }); + return new PendingOperationPanel(componentId, new IModel>() { + + @Override + public List getObject() { + return pendingOperations; + } + }); + } + }); + + columns.add(new InlineMenuButtonColumn(createShadowMenu(), getPageBase()) { + @Override + public String getCssClass() + { + return "col-xs-1"; + } + }); + + return columns; + } + + private MultivalueContainerListPanelWithDetailsPanel getMultivalueContainerListPanel(){ + return ((MultivalueContainerListPanelWithDetailsPanel)get(ID_SHADOW_TABLE)); + } + + + + private void addSelectedAccountPerformed(AjaxRequestTarget target, List newResources) { + getPageBase().hideMainPopup(target); + + if (newResources.isEmpty()) { + warn(getString("pageUser.message.noResourceSelected")); + return; + } + + for (ResourceType resource : newResources) { + try { + ShadowType shadow = new ShadowType(); + ObjectReferenceType resourceRef = new ObjectReferenceType(); + resourceRef.asReferenceValue().setObject(resource.asPrismObject()); + shadow.setResourceRef(resourceRef); + ResourceType usedResource = resource; + + RefinedResourceSchema refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema( + resource.asPrismObject(), LayerType.PRESENTATION, getPrismContext()); + if (refinedSchema == null) { + Task task = getPageBase().createSimpleTask(FocusPersonasTabPanel.class.getSimpleName() + ".loadResource"); + OperationResult result = task.getResult(); + PrismObject loadedResource = WebModelServiceUtils.loadObject(ResourceType.class, resource.getOid(), getPageBase(), task, result); + result.recomputeStatus(); + + refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema( + loadedResource, LayerType.PRESENTATION, getPrismContext()); + + if (refinedSchema == null) { + error(getString("pageAdminFocus.message.couldntCreateAccountNoSchema", + resource.getName())); + continue; + } + +// shadow.setResource(loadedResource.asObjectable()); + usedResource = loadedResource.asObjectable(); + } + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Refined schema for {}\n{}", resource, refinedSchema.debugDump()); + } + + RefinedObjectClassDefinition accountDefinition = refinedSchema + .getDefaultRefinedDefinition(ShadowKindType.ACCOUNT); + if (accountDefinition == null) { + error(getString("pageAdminFocus.message.couldntCreateAccountNoAccountSchema", + resource.getName())); + continue; + } +// shadow.asPrismContainer().findOrCreateContainer(ShadowType.F_ATTRIBUTES).applyDefinition(accountDefinition.toResourceAttributeContainerDefinition()); + QName objectClass = accountDefinition.getObjectClassDefinition().getTypeName(); + ObjectReferenceType usedResourceRef = new ObjectReferenceType(); + usedResourceRef.asReferenceValue().setObject(usedResource.asPrismObject()); + shadow.setResourceRef(usedResourceRef); + shadow.setObjectClass(objectClass); + shadow.setIntent(accountDefinition.getObjectClassDefinition().getIntent()); + shadow.setKind(accountDefinition.getObjectClassDefinition().getKind()); + getPrismContext().adopt(shadow); + + Task task = getPageBase().createSimpleTask(OPERATION_ADD_ACCOUNT); + PrismObjectWrapperFactory factory = getPageBase().getRegistry().getObjectWrapperFactory(shadow.asPrismContainer().getDefinition()); + WrapperContext context = new WrapperContext(task, task.getResult()); + ShadowWrapper wrappernew = (ShadowWrapper) factory.createObjectWrapper(shadow.asPrismContainer(), ItemStatus.ADDED, context); + if (task.getResult() != null + && !WebComponentUtil.isSuccessOrHandledError(task.getResult())) { + showResult(task.getResult(), false); + } + + wrappernew.setProjectionStatus(UserDtoStatus.ADD); + projectionModel.getObject().add(wrappernew); + } catch (Exception ex) { + error(getString("pageAdminFocus.message.couldntCreateAccount", resource.getName(), + ex.getMessage())); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't create account", ex); + } + } + target.add(getMultivalueContainerListPanel()); + } + + private IModel> createEmptyShadowWrapperModel() { + ShadowType shadow = new ShadowType(); + ShadowWrapper wrapper = null; + Task task = getPageBase().createSimpleTask("create empty shadow wrapper"); + try { + getPageBase().getPrismContext().adopt(shadow); + wrapper = ((PageAdminFocus) getPage()).loadShadowWrapper(shadow.asPrismContainer(), task, task.getResult()); + } catch (SchemaException e) { + getPageBase().showResult(task.getResult(), "pageAdminFocus.message.couldntCreateShadowWrapper"); + LOGGER.error("Couldn't create shadow wrapper", e); + } + final ShadowWrapper ret = wrapper; + return new IModel>() { + + @Override + public PrismContainerWrapper getObject() { + return ret; + } + }; + } + + private List createShadowMenu() { + List items = new ArrayList<>(); + + PrismObjectDefinition def = getObjectWrapper().getObject().getDefinition(); + PrismReferenceDefinition ref = def.findReferenceDefinition(UserType.F_LINK_REF); + InlineMenuItem item; + PrismPropertyDefinition administrativeStatus = def + .findPropertyDefinition(SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS); + if (administrativeStatus.canRead() && administrativeStatus.canModify()) { + item = new ButtonInlineMenuItem(createStringResource("pageAdminFocus.button.enable")) { + private static final long serialVersionUID = 1L; + + @Override + public InlineMenuItemAction initAction() { + return new ColumnMenuAction() { + private static final long serialVersionUID = 1L; + + @Override + public void onClick(AjaxRequestTarget target) { + updateShadowActivation(target, getMultivalueContainerListPanel() + .getPerformedSelectedItems(getRowModel()), true); + } + }; + } + + @Override + public String getButtonIconCssClass() { + return "fa fa-check"; + } + }; + items.add(item); + item = new InlineMenuItem(createStringResource("pageAdminFocus.button.disable")) { + private static final long serialVersionUID = 1L; + + @Override + public InlineMenuItemAction initAction() { + return new ColumnMenuAction() { + private static final long serialVersionUID = 1L; + + @Override + public void onClick(AjaxRequestTarget target) { + updateShadowActivation(target, getMultivalueContainerListPanel() + .getPerformedSelectedItems(getRowModel()), false); + } + }; + } + }; + items.add(item); + } + if (ref.canRead() && ref.canAdd()) { + item = new InlineMenuItem(createStringResource("pageAdminFocus.button.unlink")) { + private static final long serialVersionUID = 1L; + + @Override + public InlineMenuItemAction initAction() { + return new ColumnMenuAction() { + private static final long serialVersionUID = 1L; + + @Override + public void onClick(AjaxRequestTarget target) { + unlinkProjectionPerformed(target,getMultivalueContainerListPanel() + .getPerformedSelectedItems(getRowModel())); + } + }; + } + }; + items.add(item); + } + PrismPropertyDefinition locakoutStatus = def.findPropertyDefinition(SchemaConstants.PATH_ACTIVATION_LOCKOUT_STATUS); + if (locakoutStatus.canRead() && locakoutStatus.canModify()) { + item = new InlineMenuItem(createStringResource("pageAdminFocus.button.unlock")) { + private static final long serialVersionUID = 1L; + + @Override + public InlineMenuItemAction initAction() { + return new ColumnMenuAction() { + private static final long serialVersionUID = 1L; + + @Override + public void onClick(AjaxRequestTarget target) { + unlockShadowPerformed(target,getMultivalueContainerListPanel() + .getPerformedSelectedItems(getRowModel())); + } + }; + } + }; + items.add(item); + } + if (administrativeStatus.canRead() && administrativeStatus.canModify()) { +// items.add(new InlineMenuItem()); + item = new InlineMenuItem(createStringResource("pageAdminFocus.button.delete")) { + private static final long serialVersionUID = 1L; + + @Override + public InlineMenuItemAction initAction() { + return new ColumnMenuAction() { + private static final long serialVersionUID = 1L; + + @Override + public void onClick(AjaxRequestTarget target) { + deleteProjectionPerformed(target, getMultivalueContainerListPanel() + .getPerformedSelectedItems(getRowModel())); + } + }; + } + }; + items.add(item); + } + item = new ButtonInlineMenuItem(createStringResource("PageBase.button.edit")) { + private static final long serialVersionUID = 1L; + + @Override + public String getButtonIconCssClass() { + return GuiStyleConstants.CLASS_EDIT_MENU_ITEM; + } + + @Override + public InlineMenuItemAction initAction() { + return new ColumnMenuAction() { + private static final long serialVersionUID = 1L; + + @Override + public void onClick(AjaxRequestTarget target) { + getMultivalueContainerListPanel().itemPerformedForDefaultAction(target, + getRowModel(), getMultivalueContainerListPanel().getSelectedItems()); + target.add(getFeedbackPanel()); + } + }; + } + }; + items.add(item); + return items; + } + + private void deleteProjectionPerformed(AjaxRequestTarget target, + List> selected) { + if (!isAnyProjectionSelected(target, selected)) { + return; + } + + showModalWindow(getDeleteProjectionPopupContent(selected), + target); + } + + private boolean isAnyProjectionSelected(AjaxRequestTarget target, + List> selected) { + if (selected.isEmpty()) { + warn(getString("pageAdminFocus.message.noAccountSelected")); + target.add(getFeedbackPanel()); + return false; + } + + return true; + } + + private void updateShadowActivation(AjaxRequestTarget target, + List> accounts, boolean enabled) { + + if (!isAnyProjectionSelected(target, accounts)) { + return; + } + + for (PrismContainerValueWrapper account : accounts) { +// if (!account.isLoadedOK()) { +// continue; +// } + try { +// ObjectWrapperOld wrapper = account.getObjectOld(); +// PrismObjectWrapper wrapper = account.getObject(); + PrismContainerWrapper activation = account + .findContainer(ShadowType.F_ACTIVATION); + if (activation == null) { + warn(getString("pageAdminFocus.message.noActivationFound")); + continue; + } + + PrismPropertyWrapper enabledProperty = (PrismPropertyWrapper) activation.getValues().iterator().next() + .findProperty(ActivationType.F_ADMINISTRATIVE_STATUS); + if (enabledProperty == null || enabledProperty.getValues().size() != 1) { + warn(getString("pageAdminFocus.message.noEnabledPropertyFound", account.getDisplayName())); + continue; + } + PrismValueWrapper value = (PrismValueWrapper) enabledProperty.getValues().get(0); + ActivationStatusType status = enabled ? ActivationStatusType.ENABLED + : ActivationStatusType.DISABLED; + ((PrismPropertyValue) value.getNewValue()).setValue(status); + + } catch (SchemaException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + +// wrapper.setSelected(false); + } + info(getString("pageAdminFocus.message.updated." + enabled)); + target.add(getFeedbackPanel(), getMultivalueContainerListPanel()); + } + + private void unlockShadowPerformed(AjaxRequestTarget target, + List> selected) { + if (!isAnyProjectionSelected(target, selected)) { + return; + } + + for (PrismContainerValueWrapper account : selected) { +// if (!account.isLoadedOK()) { +// continue; +// } + try { +// ObjectWrapperOld wrapper = account.getObjectOld(); +// PrismObjectWrapper wrapper = account.getObject(); +// wrapper.setSelected(false); + + PrismContainerWrapper activation = account.findContainer(ShadowType.F_ACTIVATION); + if (activation == null) { + warn(getString("pageAdminFocus.message.noActivationFound", account.getDisplayName())); + continue; + } + + PrismPropertyWrapper lockedProperty = (PrismPropertyWrapper) activation.getValues().iterator().next().findProperty(ActivationType.F_LOCKOUT_STATUS); + if (lockedProperty == null || lockedProperty.getValues().size() != 1) { + warn(getString("pageAdminFocus.message.noLockoutStatusPropertyFound")); + continue; + } + PrismValueWrapper value = (PrismValueWrapper) lockedProperty.getValues().get(0); + ((PrismPropertyValue) value.getNewValue()).setValue(LockoutStatusType.NORMAL); + } catch (SchemaException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + }// TODO only for really unlocked accounts + } + info(getString("pageAdminFocus.message.unlocked")); + target.add(getFeedbackPanel(), getMultivalueContainerListPanel()); + } + + private void unlinkProjectionPerformed(AjaxRequestTarget target, + List> selected) { + if (!isAnyProjectionSelected(target, selected)) { + return; + } + + for (PrismContainerValueWrapper projection : selected) { + if (UserDtoStatus.ADD.equals(((ShadowWrapper)projection.getParent()).getProjectionStatus())) { + continue; + } + ((ShadowWrapper)projection.getParent()).setProjectionStatus(UserDtoStatus.UNLINK); + } + target.add(getMultivalueContainerListPanel()); + } + + private Popupable getDeleteProjectionPopupContent(List> selected) { + ConfirmationPanel dialog = new ConfirmationPanel(getPageBase().getMainPopupBodyId(), + new IModel() { + private static final long serialVersionUID = 1L; + + @Override + public String getObject() { + return createStringResource("pageAdminFocus.message.deleteAccountConfirm", + selected.size()).getString(); + } + }) { + private static final long serialVersionUID = 1L; + + @Override + public void yesPerformed(AjaxRequestTarget target) { + deleteAccountConfirmedPerformed(target, selected); + } + }; + return dialog; + } + + private void deleteAccountConfirmedPerformed(AjaxRequestTarget target, + List> selected) { + List accounts = projectionModel.getObject(); + for (PrismContainerValueWrapper account : selected) { + if (UserDtoStatus.ADD.equals(((ShadowWrapper)account.getParent()).getProjectionStatus())) { + accounts.remove(account.getParent()); + } else { + ((ShadowWrapper)account.getParent()).setProjectionStatus(UserDtoStatus.DELETE); + } + } + target.add(getMultivalueContainerListPanel()); + } +} From 9345f95fd87d21dda734d99c1119b7493a7694e8 Mon Sep 17 00:00:00 2001 From: lskublik Date: Thu, 12 Mar 2020 10:34:22 +0100 Subject: [PATCH 2/7] fixes for schrodinger tests --- .../testing/schrodinger/UsersTest.java | 19 ++++++++++--------- .../schrodinger/page/AboutPageTest.java | 3 +++ .../page/InternalsConfigurationPageTest.java | 15 ++++++--------- ...LoginPageWithAuthenticationConfigTest.java | 11 +++++++---- .../scenarios/ObjectListArchetypeTests.java | 2 +- .../AssignmentHolderObjectListTable.java | 2 +- .../schrodinger/component/common/Paging.java | 11 ++++++++++- .../EditResourceConfigurationPage.java | 2 +- .../schrodinger/page/user/UserPage.java | 3 ++- 9 files changed, 41 insertions(+), 27 deletions(-) diff --git a/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/UsersTest.java b/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/UsersTest.java index 556844fe4dc..be97aa19a03 100644 --- a/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/UsersTest.java +++ b/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/UsersTest.java @@ -30,7 +30,7 @@ public void testUserTablePaging() { for (int i = 0; i < 21; i++) { addUser("john" + i); - Selenide.sleep(3000); + Selenide.sleep(5000); } Paging paging = users @@ -38,17 +38,18 @@ public void testUserTablePaging() { .paging(); paging.pageSize(5); + Selenide.sleep(3000); screenshot("paging"); - paging.next() - .last() - .previous() - .first() - .actualPagePlusOne() - .actualPagePlusTwo() - .actualPageMinusTwo() - .actualPageMinusOne(); + paging.next(); + paging.last(); + paging.previous(); + paging.first(); + paging.actualPagePlusOne(); + paging.actualPagePlusTwo(); + paging.actualPageMinusTwo(); + paging.actualPageMinusOne(); } private void addUser(String name) { diff --git a/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/AboutPageTest.java b/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/AboutPageTest.java index 04cbe99c495..32a4fa59e1c 100644 --- a/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/AboutPageTest.java +++ b/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/AboutPageTest.java @@ -6,6 +6,8 @@ */ package com.evolveum.midpoint.testing.schrodinger.page; +import com.codeborne.selenide.Selenide; + import com.evolveum.midpoint.schrodinger.page.configuration.AboutPage; import com.evolveum.midpoint.testing.schrodinger.AbstractSchrodingerTest; import org.testng.Assert; @@ -106,6 +108,7 @@ public void checkReindexRepositoryObjectsDisplayName() { @Test public void checkJVMPropertiesMidpointHome(){ + Selenide.sleep(2000); Assert.assertFalse( aboutPage.getJVMproperty(AbstractSchrodingerTest.PROPERTY_NAME_MIDPOINT_HOME).isEmpty()); } diff --git a/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/InternalsConfigurationPageTest.java b/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/InternalsConfigurationPageTest.java index 6ee77d28847..0df18bb694a 100644 --- a/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/InternalsConfigurationPageTest.java +++ b/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/InternalsConfigurationPageTest.java @@ -19,22 +19,18 @@ */ public class InternalsConfigurationPageTest extends AbstractSchrodingerTest { - private InternalsConfigurationPage configPage; - - @BeforeMethod - private void openPage() { - configPage = basicPage.internalsConfiguration(); - } - @AfterClass - private void cleanup() { - // Reset time because TestBase#afterClass() doesn't reset the clock. + @Override + public void afterClass() { + InternalsConfigurationPage configPage = basicPage.internalsConfiguration(); configPage = basicPage.internalsConfiguration(); configPage.clockTab().resetTime(); + super.afterClass(); } @Test public void test001changeTime() { + InternalsConfigurationPage configPage = basicPage.internalsConfiguration(); ClockTab clockTab = configPage.clockTab(); clockTab.changeTime("5/15/2099", "10", "30", ClockTab.AmOrPmChoice.PM); @@ -52,6 +48,7 @@ public void test001changeTime() { @Test public void test010resetTime() { + InternalsConfigurationPage configPage = basicPage.internalsConfiguration(); ClockTab clockTab = configPage.clockTab(); clockTab.resetTime(); diff --git a/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/LoginPageWithAuthenticationConfigTest.java b/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/LoginPageWithAuthenticationConfigTest.java index 6b568a3fcdb..bab73ea2d95 100644 --- a/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/LoginPageWithAuthenticationConfigTest.java +++ b/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/LoginPageWithAuthenticationConfigTest.java @@ -8,6 +8,8 @@ package com.evolveum.midpoint.testing.schrodinger.page; import com.codeborne.selenide.Condition; + +import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration; import com.evolveum.midpoint.schrodinger.MidPoint; import com.evolveum.midpoint.schrodinger.component.common.FeedbackBox; import com.evolveum.midpoint.schrodinger.component.common.PrismForm; @@ -114,7 +116,7 @@ public void test030changePassowordMailNonce() throws IOException, InterruptedExc FormLoginPage login = midPoint.formLogin(); MailNoncePage mailNonce = (MailNoncePage) login.forgotPassword(); mailNonce.setMail(MAIL_OF_ENABLED_USER); - TimeUnit.SECONDS.sleep(2); + TimeUnit.SECONDS.sleep(6); String notification = readLastNotification(); String bodyTag = "body='"; String link = notification.substring(notification.indexOf(bodyTag) + bodyTag.length(), notification.lastIndexOf("'")); @@ -142,6 +144,7 @@ public void test031changePassowordSecurityQuestion() { @Test public void test040selfRegistration() throws IOException, InterruptedException { + System.setProperty("midpoint.schrodinger","true"); basicPage.loggedUser().logoutIfUserIsLogin(); FormLoginPage login = midPoint.formLogin(); open("/login"); @@ -149,11 +152,11 @@ public void test040selfRegistration() throws IOException, InterruptedException { TimeUnit.SECONDS.sleep(2); SelfRegistrationPage registrationPage = login.register(); registrationPage.setGivenName("Test").setFamilyName("User").setEmail("test.user@evolveum.com").setPassword("5ecr3t").submit(); - TimeUnit.SECONDS.sleep(4); + TimeUnit.SECONDS.sleep(6); String notification = readLastNotification(); - String usernameTag = "username='"; +// String usernameTag = "username='"; String linkTag = "link='"; - String username = notification.substring(notification.indexOf(usernameTag) + usernameTag.length(), notification.lastIndexOf("', " + linkTag)); +// String username = notification.substring(notification.indexOf(usernameTag) + usernameTag.length(), notification.lastIndexOf("', " + linkTag)); String link = notification.substring(notification.indexOf(linkTag) + linkTag.length(), notification.lastIndexOf("''")); open(link); $(Schrodinger.byDataId("successPanel")).waitUntil(Condition.visible, MidPoint.TIMEOUT_DEFAULT_2_S); diff --git a/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/scenarios/ObjectListArchetypeTests.java b/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/scenarios/ObjectListArchetypeTests.java index 07fb16cf172..d0f59b35d05 100644 --- a/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/scenarios/ObjectListArchetypeTests.java +++ b/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/scenarios/ObjectListArchetypeTests.java @@ -159,8 +159,8 @@ public void createNewEmployeeUser(){ @Test(priority = 4, dependsOnMethods ={"actualizeArchetypeConfiguration"}) public void checkNewObjectButtonWithDropdown(){ + Selenide.sleep(5000); ListUsersPage userListPage = basicPage.listUsers(); - Selenide.sleep(2000); Assert.assertTrue(userListPage .table() .getToolbarButton("fa fa-plus") diff --git a/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/component/assignmentholder/AssignmentHolderObjectListTable.java b/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/component/assignmentholder/AssignmentHolderObjectListTable.java index eb9df71d397..3f8e9e50b79 100644 --- a/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/component/assignmentholder/AssignmentHolderObjectListTable.java +++ b/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/component/assignmentholder/AssignmentHolderObjectListTable.java @@ -88,7 +88,7 @@ public PD newObjectButtonClickPerformed(String iconCssClass){ getToolbarButton(iconCssClass) .waitUntil(Condition.appears, MidPoint.TIMEOUT_DEFAULT_2_S) .click(); - + Selenide.sleep(2000); return getObjectDetailsPage(); } diff --git a/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/component/common/Paging.java b/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/component/common/Paging.java index 546587f265a..d635c87e172 100644 --- a/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/component/common/Paging.java +++ b/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/component/common/Paging.java @@ -9,6 +9,7 @@ import com.codeborne.selenide.Condition; import com.codeborne.selenide.ElementsCollection; +import com.codeborne.selenide.Selenide; import com.codeborne.selenide.SelenideElement; import com.evolveum.midpoint.schrodinger.SchrodingerException; import com.evolveum.midpoint.schrodinger.component.Component; @@ -27,21 +28,25 @@ public Paging(T parent, SelenideElement parentElement) { public Paging first() { getParentElement().$(Schrodinger.byElementValue("a", "<<")).click(); + Selenide.sleep(1000); return this; } public Paging previous() { getParentElement().$(Schrodinger.byElementValue("a", "<")).click(); + Selenide.sleep(1000); return this; } public Paging next() { getParentElement().$(Schrodinger.byElementValue("a", ">")).click(); + Selenide.sleep(1000); return this; } public Paging last() { getParentElement().$(Schrodinger.byElementValue("a", ">>")).click(); + Selenide.sleep(1000); return this; } @@ -63,21 +68,25 @@ private void moveThroughPages(int offsetFromActual) { public Paging actualPageMinusOne() { moveThroughPages(-1); + Selenide.sleep(1000); return this; } public Paging actualPageMinusTwo() { moveThroughPages(-2); + Selenide.sleep(1000); return this; } public Paging actualPagePlusOne() { moveThroughPages(1); + Selenide.sleep(1000); return this; } public Paging actualPagePlusTwo() { moveThroughPages(2); + Selenide.sleep(1000); return this; } @@ -96,7 +105,7 @@ public Paging pageSize(int size) { popover.$(By.tagName("input")).setValue(Integer.toString(size)); popover.$(By.tagName("button")).click(); - + Selenide.sleep(2000); return this; } diff --git a/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/page/resource/EditResourceConfigurationPage.java b/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/page/resource/EditResourceConfigurationPage.java index d37b524e92c..dfdac82f635 100644 --- a/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/page/resource/EditResourceConfigurationPage.java +++ b/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/page/resource/EditResourceConfigurationPage.java @@ -63,7 +63,7 @@ public TestConnectionModal clickSaveAndTestConnec Selenide.sleep(MidPoint.TIMEOUT_LONG_1_M); SelenideElement testModalBox = $(Schrodinger .byElementAttributeValue("div", "aria-labelledby", "Test connection result(s)")) - .waitUntil(Condition.visible, MidPoint.TIMEOUT_LONG_1_M); + .waitUntil(Condition.visible, MidPoint.TIMEOUT_EXTRA_LONG_1_M); return new TestConnectionModal<>(this, testModalBox); } diff --git a/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/page/user/UserPage.java b/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/page/user/UserPage.java index 60d4c65343c..38d05db3697 100644 --- a/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/page/user/UserPage.java +++ b/tools/schrodinger/src/main/java/com/evolveum/midpoint/schrodinger/page/user/UserPage.java @@ -7,6 +7,7 @@ package com.evolveum.midpoint.schrodinger.page.user; import com.codeborne.selenide.Condition; +import com.codeborne.selenide.Selenide; import com.codeborne.selenide.SelenideElement; import com.evolveum.midpoint.schrodinger.MidPoint; import com.evolveum.midpoint.schrodinger.component.AssignmentHolderBasicTab; @@ -75,7 +76,7 @@ public PreviewPage clickPreviewChanges() { public ProjectionsTab selectTabProjections() { SelenideElement element = findTabPanel().clickTab("pageAdminFocus.projections"); - + Selenide.sleep(2000); return new ProjectionsTab(this, element); } From 762b5fdd48d6b35e07cefede06dfcba89f48e064 Mon Sep 17 00:00:00 2001 From: lskublik Date: Thu, 12 Mar 2020 10:47:38 +0100 Subject: [PATCH 3/7] change of schrodinger testng xml file because of email notification on jenkins build --- .../schrodingertest/testng-integration.xml | 72 +------------------ 1 file changed, 2 insertions(+), 70 deletions(-) diff --git a/testing/schrodingertest/testng-integration.xml b/testing/schrodingertest/testng-integration.xml index b7e6583a4c8..93d05f982c4 100644 --- a/testing/schrodingertest/testng-integration.xml +++ b/testing/schrodingertest/testng-integration.xml @@ -7,94 +7,26 @@ --> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - From ec990b5ded30ce1b0d82781701bcd2bd3a9518df Mon Sep 17 00:00:00 2001 From: lskublik Date: Thu, 12 Mar 2020 12:43:52 +0100 Subject: [PATCH 4/7] turning off validation of unchanged value for lookup table (MID-6024) --- .../api/component/autocomplete/AutoCompleteTextPanel.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/autocomplete/AutoCompleteTextPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/autocomplete/AutoCompleteTextPanel.java index 8146364ca02..33131f145c7 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/autocomplete/AutoCompleteTextPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/autocomplete/AutoCompleteTextPanel.java @@ -173,8 +173,13 @@ public C convertToObject(String value, Locale locale) throws ConversionException return originConverter.convertToObject(row.getKey(), locale); } } + boolean differentValue = true; + if (getBaseFormComponent() != null && getBaseFormComponent().getModelObject() != null + && getBaseFormComponent().getModelObject().equals(value)) { + differentValue = false; + } - if (strict) { + if (differentValue && strict) { throw new ConversionException("Cannot convert " + value); } From ab4df210bd91f50d1b99424562f2afbc603c2314 Mon Sep 17 00:00:00 2001 From: lskublik Date: Thu, 12 Mar 2020 12:55:22 +0100 Subject: [PATCH 5/7] undoing changes in testng-integration.xml --- .../schrodingertest/testng-integration.xml | 74 ++++++++++++++++++- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/testing/schrodingertest/testng-integration.xml b/testing/schrodingertest/testng-integration.xml index 93d05f982c4..8783635402e 100644 --- a/testing/schrodingertest/testng-integration.xml +++ b/testing/schrodingertest/testng-integration.xml @@ -7,26 +7,94 @@ --> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + \ No newline at end of file From c87213f61d4016c804f5f092872fc2c6ee4efcc0 Mon Sep 17 00:00:00 2001 From: Katarina Valalikova Date: Thu, 12 Mar 2020 14:03:09 +0100 Subject: [PATCH 6/7] small fix for operation statistics panel (task page MID-5926), clenaup --- .../data/BaseSortableDataProvider.java | 794 +++++++++--------- .../server/TaskOperationStatisticsPanel.html | 67 +- .../server/TaskOperationStatisticsPanel.java | 87 +- 3 files changed, 469 insertions(+), 479 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/BaseSortableDataProvider.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/BaseSortableDataProvider.java index d396cbf7307..04b397508bc 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/BaseSortableDataProvider.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/BaseSortableDataProvider.java @@ -1,395 +1,399 @@ -/* - * Copyright (c) 2010-2017 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.web.component.data; - -import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.model.api.*; -import com.evolveum.midpoint.model.api.authentication.CompiledObjectCollectionView; -import com.evolveum.midpoint.model.api.authentication.CompiledGuiProfile; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.ObjectOrdering; -import com.evolveum.midpoint.prism.query.ObjectPaging; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.query.OrderDirection; -import com.evolveum.midpoint.repo.api.RepositoryService; -import com.evolveum.midpoint.schema.*; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.TaskManager; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.page.PageDialog; -import com.evolveum.midpoint.web.security.MidPointApplication; -import com.evolveum.midpoint.wf.api.WorkflowManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.DistinctSearchOptionType; - -import org.apache.commons.lang.Validate; -import org.apache.wicket.Component; -import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder; -import org.apache.wicket.extensions.markup.html.repeater.util.SortParam; -import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider; -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.Model; -import org.jetbrains.annotations.NotNull; - -import javax.xml.namespace.QName; -import java.io.Serializable; -import java.util.*; - -import static com.evolveum.midpoint.gui.api.util.WebComponentUtil.safeLongToInteger; - -/** - * @author lazyman - */ -public abstract class BaseSortableDataProvider extends SortableDataProvider { - - private static final Trace LOGGER = TraceManager.getTrace(BaseSortableDataProvider.class); - private static final String DOT_CLASS = BaseSortableDataProvider.class.getName() + "."; - private static final String OPERATION_GET_EXPORT_SIZE_LIMIT = DOT_CLASS + "getDefaultExportSizeLimit"; - - private Component component; - private List availableData; - private ObjectQuery query; - - // after this amount of time cached size will be removed - // from cache and replaced by new value, time in seconds - private Map cache = new HashMap<>(); - private int cacheCleanupThreshold = 60; - private boolean useCache; - private boolean exportSize = false; - private long exportLimit = -1; - - public BaseSortableDataProvider(Component component) { - this(component, false, true); - } - - public BaseSortableDataProvider(Component component, boolean useCache) { - this(component, useCache, true); - } - - public BaseSortableDataProvider(Component component, boolean useCache, boolean useDefaultSortingField) { - Validate.notNull(component, "Component must not be null."); - this.component = component; - this.useCache = useCache; - - if (useDefaultSortingField) { - setSort("name", SortOrder.ASCENDING); - } - setExportLimitValue(); - } - - protected ModelService getModel() { - MidPointApplication application = MidPointApplication.get(); - return application.getModel(); - } - - protected RepositoryService getRepositoryService() { - MidPointApplication application = MidPointApplication.get(); - return application.getRepositoryService(); - } - - protected TaskManager getTaskManager() { - MidPointApplication application = MidPointApplication.get(); - return application.getTaskManager(); - } - - protected PrismContext getPrismContext() { - MidPointApplication application = MidPointApplication.get(); - return application.getPrismContext(); - } - - protected SchemaHelper getSchemaHelper() { - MidPointApplication application = MidPointApplication.get(); - return application.getSchemaHelper(); - } - - protected GetOperationOptionsBuilder getOperationOptionsBuilder() { - return getSchemaHelper().getOperationOptionsBuilder(); - } - - protected GetOperationOptionsBuilder getOperationOptionsBuilder(Collection> createFrom) { - return getSchemaHelper().getOperationOptionsBuilder().setFrom(createFrom); - } - - protected RelationRegistry getRelationRegistry() { - MidPointApplication application = MidPointApplication.get(); - return application.getRelationRegistry(); - } - - protected TaskService getTaskService() { - MidPointApplication application = MidPointApplication.get(); - return application.getTaskService(); - } - - protected ModelInteractionService getModelInteractionService() { - MidPointApplication application = MidPointApplication.get(); - return application.getModelInteractionService(); - } - - protected WorkflowService getWorkflowService() { - MidPointApplication application = MidPointApplication.get(); - return application.getWorkflowService(); - } - - protected ModelAuditService getAuditService() { - MidPointApplication application = MidPointApplication.get(); - return application.getAuditService(); - } - - protected WorkflowManager getWorkflowManager() { - MidPointApplication application = MidPointApplication.get(); - return application.getWorkflowManager(); - } - - public List getAvailableData() { - if (availableData == null) { - availableData = new ArrayList<>(); - } - return availableData; - } - - @Override - public IModel model(T object) { - return new Model<>(object); - } - - protected PageBase getPage() { - if (component instanceof PageBase) { - return (PageBase) component; - } - - if (component.getPage() instanceof PageBase) { - return (PageBase) component.getPage(); - } - - if (component.getPage() instanceof PageDialog) { - return ((PageDialog) component.getPage()).getPageBase(); - } - - throw new IllegalStateException("Component is not instance of '" + PageBase.class.getName() - + "' or is not placed on page of that instance."); - } - - public ObjectQuery getQuery() { - return query; - } - - public void setQuery(ObjectQuery query) { - this.query = query; - } - - /** - * Flag method for {@link TablePanel}. If true navigation panel with paging "X to Y from Z results is shown", - * otherwise only "previous and next" simple paging is used. - * - * @return By defaults it returns true. - */ - public IModel isSizeAvailableModel() { - return new IModel() { - @Override - public Boolean getObject() { - return true; - } - }; - } - - protected boolean checkOrderingSettings() { - return false; - } - - public boolean isDistinct() { - // TODO: Default list view setting should never be needed. Always check setting for specific object type (and archetype). - CompiledObjectCollectionView def = WebComponentUtil.getDefaultGuiObjectListType((PageBase) component.getPage()); - return def == null || def.getDistinct() != DistinctSearchOptionType.NEVER; // change after other options are added - } - - protected GetOperationOptionsBuilder getDefaultOptionsBuilder() { - return getDistinctRelatedOptionsBuilder(); // probably others in the future - } - - @NotNull - protected Collection> getDistinctRelatedOptions() { - return getDistinctRelatedOptionsBuilder().build(); - } - - @NotNull - protected GetOperationOptionsBuilder getDistinctRelatedOptionsBuilder() { - GetOperationOptionsBuilder builder = getOperationOptionsBuilder(); - if (isDistinct()) { - return builder.distinct(); - } else { - return builder; - } - } - - public boolean isOrderingDisabled() { - if (!checkOrderingSettings()) { - return false; - } - // TODO: Default list view setting should never be needed. Always check setting for specific object type (and archetype). - CompiledObjectCollectionView def = WebComponentUtil.getDefaultGuiObjectListType((PageBase) component.getPage()); - return def != null && def.isDisableSorting() != null && def.isDisableSorting(); - } - - protected ObjectPaging createPaging(long offset, long pageSize) { - Integer o = safeLongToInteger(offset); - Integer size = safeLongToInteger(pageSize); - List orderings = null; - if (!isOrderingDisabled()) { - orderings = createObjectOrderings(getSort()); - } - return getPrismContext().queryFactory().createPaging(o, size, orderings); - } - - /** - * Could be overridden in subclasses. - */ - @NotNull - protected List createObjectOrderings(SortParam sortParam) { - if (sortParam != null && sortParam.getProperty() != null) { - OrderDirection order = sortParam.isAscending() ? OrderDirection.ASCENDING : OrderDirection.DESCENDING; - return Collections.singletonList( - getPrismContext().queryFactory().createOrdering( - ItemPath.create(new QName(SchemaConstantsGenerated.NS_COMMON, sortParam.getProperty())), order)); - } else { - return Collections.emptyList(); - } - } - - public void clearCache() { - cache.clear(); - getAvailableData().clear(); - } - - public int getCacheCleanupThreshold() { - return cacheCleanupThreshold; - } - - public void setCacheCleanupThreshold(int cacheCleanupThreshold) { - Validate.isTrue(cacheCleanupThreshold > 0, "Cache cleanup threshold must be bigger than zero."); - this.cacheCleanupThreshold = cacheCleanupThreshold; - } - - @Override - public Iterator iterator(long first, long count) { - Iterator iterator = internalIterator(first, count); - saveProviderPaging(getQuery(), createPaging(first, count)); - - return iterator; - } - - protected void saveProviderPaging(ObjectQuery query, ObjectPaging paging) { - } - - public abstract Iterator internalIterator(long first, long count); - - @Override - public long size() { - LOGGER.trace("begin::size()"); - if (!useCache) { - int internalSize = internalSize(); - return exportSize && exportLimit >= 0 && exportLimit < internalSize ? exportLimit : internalSize; - } - - long size; - CachedSize cachedSize = getCachedSize(cache); - if (cachedSize != null) { - long timestamp = cachedSize.getTimestamp(); - if (System.currentTimeMillis() - timestamp > cacheCleanupThreshold * 1000) { - //recreate - size = internalSize(); - addCachedSize(cache, new CachedSize(size, System.currentTimeMillis())); - } else { - LOGGER.trace("Size returning from cache."); - size = cachedSize.getSize(); - } - } else { - //recreate - size = internalSize(); - addCachedSize(cache, new CachedSize(size, System.currentTimeMillis())); - } - - LOGGER.trace("end::size(): {}", size); - return exportSize && exportLimit >= 0 && exportLimit < size ? exportLimit : size; - } - - protected abstract int internalSize(); - - protected CachedSize getCachedSize(Map cache) { - return cache.get(query); - } - - protected void addCachedSize(Map cache, CachedSize newSize) { - cache.put(query, newSize); - } - - public static class CachedSize implements Serializable { - - private long timestamp; - private long size; - - private CachedSize(long size, long timestamp) { - this.size = size; - this.timestamp = timestamp; - } - - public long getSize() { - return size; - } - - public long getTimestamp() { - return timestamp; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - CachedSize that = (CachedSize) o; - - if (size != that.size) return false; - if (timestamp != that.timestamp) return false; - - return true; - } - - @Override - public int hashCode() { - int result = (int) (timestamp ^ (timestamp >>> 32)); - result = 31 * result + (int) (size ^ (size >>> 32)); - return result; - } - - @Override - public String toString() { - return "CachedSize(size=" + size + ", timestamp=" + timestamp + ")"; - } - } - - private void setExportLimitValue() { - OperationResult result = new OperationResult(OPERATION_GET_EXPORT_SIZE_LIMIT); - try { - CompiledGuiProfile adminGui = getModelInteractionService().getCompiledGuiProfile(null, result); - if (adminGui.getDefaultExportSettings() != null && adminGui.getDefaultExportSettings().getSizeLimit() != null) { - exportLimit = adminGui.getDefaultExportSettings().getSizeLimit(); - } - } catch (Exception ex) { - LOGGER.error("Unable to get default export size limit, ", ex); - } - } - - public boolean isExportSize() { - return exportSize; - } - - public void setExportSize(boolean exportSize) { - this.exportSize = exportSize; - } -} +/* + * Copyright (c) 2010-2017 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.web.component.data; + +import com.evolveum.midpoint.gui.api.page.PageBase; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.model.api.*; +import com.evolveum.midpoint.model.api.authentication.CompiledObjectCollectionView; +import com.evolveum.midpoint.model.api.authentication.CompiledGuiProfile; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.ObjectOrdering; +import com.evolveum.midpoint.prism.query.ObjectPaging; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.OrderDirection; +import com.evolveum.midpoint.repo.api.RepositoryService; +import com.evolveum.midpoint.schema.*; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.TaskManager; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.page.PageDialog; +import com.evolveum.midpoint.web.security.MidPointApplication; +import com.evolveum.midpoint.wf.api.WorkflowManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.DistinctSearchOptionType; + +import org.apache.commons.lang.Validate; +import org.apache.wicket.Component; +import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder; +import org.apache.wicket.extensions.markup.html.repeater.util.SortParam; +import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.jetbrains.annotations.NotNull; + +import javax.xml.namespace.QName; +import java.io.Serializable; +import java.util.*; + +import static com.evolveum.midpoint.gui.api.util.WebComponentUtil.safeLongToInteger; + +/** + * @author lazyman + */ +public abstract class BaseSortableDataProvider extends SortableDataProvider { + + private static final Trace LOGGER = TraceManager.getTrace(BaseSortableDataProvider.class); + private static final String DOT_CLASS = BaseSortableDataProvider.class.getName() + "."; + private static final String OPERATION_GET_EXPORT_SIZE_LIMIT = DOT_CLASS + "getDefaultExportSizeLimit"; + + private Component component; + private List availableData; + private ObjectQuery query; + + // after this amount of time cached size will be removed + // from cache and replaced by new value, time in seconds + private Map cache = new HashMap<>(); + private int cacheCleanupThreshold = 60; + private boolean useCache; + private boolean exportSize = false; + private long exportLimit = -1; + + public BaseSortableDataProvider(Component component) { + this(component, false, true); + } + + public BaseSortableDataProvider(Component component, boolean useCache) { + this(component, useCache, true); + } + + public BaseSortableDataProvider(Component component, boolean useCache, boolean useDefaultSortingField) { + Validate.notNull(component, "Component must not be null."); + this.component = component; + this.useCache = useCache; + + if (useDefaultSortingField) { + setSort("name", SortOrder.ASCENDING); + } + setExportLimitValue(); + } + + protected ModelService getModel() { + MidPointApplication application = MidPointApplication.get(); + return application.getModel(); + } + + protected RepositoryService getRepositoryService() { + MidPointApplication application = MidPointApplication.get(); + return application.getRepositoryService(); + } + + protected TaskManager getTaskManager() { + MidPointApplication application = MidPointApplication.get(); + return application.getTaskManager(); + } + + protected PrismContext getPrismContext() { + MidPointApplication application = MidPointApplication.get(); + return application.getPrismContext(); + } + + protected SchemaHelper getSchemaHelper() { + MidPointApplication application = MidPointApplication.get(); + return application.getSchemaHelper(); + } + + protected GetOperationOptionsBuilder getOperationOptionsBuilder() { + return getSchemaHelper().getOperationOptionsBuilder(); + } + + protected GetOperationOptionsBuilder getOperationOptionsBuilder(Collection> createFrom) { + return getSchemaHelper().getOperationOptionsBuilder().setFrom(createFrom); + } + + protected RelationRegistry getRelationRegistry() { + MidPointApplication application = MidPointApplication.get(); + return application.getRelationRegistry(); + } + + protected TaskService getTaskService() { + MidPointApplication application = MidPointApplication.get(); + return application.getTaskService(); + } + + protected ModelInteractionService getModelInteractionService() { + MidPointApplication application = MidPointApplication.get(); + return application.getModelInteractionService(); + } + + protected WorkflowService getWorkflowService() { + MidPointApplication application = MidPointApplication.get(); + return application.getWorkflowService(); + } + + protected ModelAuditService getAuditService() { + MidPointApplication application = MidPointApplication.get(); + return application.getAuditService(); + } + + protected WorkflowManager getWorkflowManager() { + MidPointApplication application = MidPointApplication.get(); + return application.getWorkflowManager(); + } + + public List getAvailableData() { + if (availableData == null) { + availableData = new ArrayList<>(); + } + return availableData; + } + + @Override + public IModel model(T object) { + return new Model<>(object); + } + + protected PageBase getPage() { + if (component instanceof PageBase) { + return (PageBase) component; + } + + if (component.getPage() instanceof PageBase) { + return (PageBase) component.getPage(); + } + + if (component.getPage() instanceof PageDialog) { + return ((PageDialog) component.getPage()).getPageBase(); + } + + throw new IllegalStateException("Component is not instance of '" + PageBase.class.getName() + + "' or is not placed on page of that instance."); + } + + public ObjectQuery getQuery() { + return query; + } + + public void setQuery(ObjectQuery query) { + this.query = query; + } + + /** + * Flag method for {@link TablePanel}. If true navigation panel with paging "X to Y from Z results is shown", + * otherwise only "previous and next" simple paging is used. + * + * @return By defaults it returns true. + */ + public IModel isSizeAvailableModel() { + return new IModel() { + @Override + public Boolean getObject() { + return true; + } + }; + } + + protected boolean checkOrderingSettings() { + return false; + } + + public boolean isDistinct() { + // TODO: Default list view setting should never be needed. Always check setting for specific object type (and archetype). + CompiledObjectCollectionView def = WebComponentUtil.getDefaultGuiObjectListType((PageBase) component.getPage()); + return def == null || def.getDistinct() != DistinctSearchOptionType.NEVER; // change after other options are added + } + + protected GetOperationOptionsBuilder getDefaultOptionsBuilder() { + return getDistinctRelatedOptionsBuilder(); // probably others in the future + } + + @NotNull + protected Collection> getDistinctRelatedOptions() { + return getDistinctRelatedOptionsBuilder().build(); + } + + @NotNull + protected GetOperationOptionsBuilder getDistinctRelatedOptionsBuilder() { + GetOperationOptionsBuilder builder = getOperationOptionsBuilder(); + if (isDistinct()) { + return builder.distinct(); + } else { + return builder; + } + } + + public boolean isOrderingDisabled() { + if (!checkOrderingSettings()) { + return false; + } + // TODO: Default list view setting should never be needed. Always check setting for specific object type (and archetype). + CompiledObjectCollectionView def = WebComponentUtil.getDefaultGuiObjectListType((PageBase) component.getPage()); + return def != null && def.isDisableSorting() != null && def.isDisableSorting(); + } + + protected ObjectPaging createPaging(long offset, long pageSize) { + Integer o = safeLongToInteger(offset); + Integer size = safeLongToInteger(pageSize); + List orderings = null; + if (!isOrderingDisabled()) { + orderings = createObjectOrderings(getSort()); + } + return getPrismContext().queryFactory().createPaging(o, size, orderings); + } + + /** + * Could be overridden in subclasses. + */ + @NotNull + protected List createObjectOrderings(SortParam sortParam) { + if (sortParam != null && sortParam.getProperty() != null) { + OrderDirection order = sortParam.isAscending() ? OrderDirection.ASCENDING : OrderDirection.DESCENDING; + return Collections.singletonList( + getPrismContext().queryFactory().createOrdering( + ItemPath.create(new QName(SchemaConstantsGenerated.NS_COMMON, sortParam.getProperty())), order)); + } else { + return Collections.emptyList(); + } + } + + public void clearCache() { + cache.clear(); + getAvailableData().clear(); + } + + public int getCacheCleanupThreshold() { + return cacheCleanupThreshold; + } + + public void setCacheCleanupThreshold(int cacheCleanupThreshold) { + Validate.isTrue(cacheCleanupThreshold > 0, "Cache cleanup threshold must be bigger than zero."); + this.cacheCleanupThreshold = cacheCleanupThreshold; + } + + @Override + public Iterator iterator(long first, long count) { + Iterator iterator = internalIterator(first, count); + saveProviderPaging(getQuery(), createPaging(first, count)); + + return iterator; + } + + protected void saveProviderPaging(ObjectQuery query, ObjectPaging paging) { + } + + public abstract Iterator internalIterator(long first, long count); + + @Override + public long size() { + LOGGER.trace("begin::size()"); + if (!useCache) { + int internalSize = internalSize(); + return exportSize && exportLimit >= 0 && exportLimit < internalSize ? exportLimit : internalSize; + } + + long size; + CachedSize cachedSize = getCachedSize(cache); + if (cachedSize != null) { + long timestamp = cachedSize.getTimestamp(); + if (System.currentTimeMillis() - timestamp > cacheCleanupThreshold * 1000) { + //recreate + size = internalSize(); + addCachedSize(cache, new CachedSize(size, System.currentTimeMillis())); + } else { + LOGGER.trace("Size returning from cache."); + size = cachedSize.getSize(); + } + } else { + //recreate + size = internalSize(); + addCachedSize(cache, new CachedSize(size, System.currentTimeMillis())); + } + + LOGGER.trace("end::size(): {}", size); + return exportSize && exportLimit >= 0 && exportLimit < size ? exportLimit : size; + } + + protected abstract int internalSize(); + + protected CachedSize getCachedSize(Map cache) { + return cache.get(query); + } + + protected void addCachedSize(Map cache, CachedSize newSize) { + cache.put(query, newSize); + } + + public static class CachedSize implements Serializable { + + private long timestamp; + private long size; + + private CachedSize(long size, long timestamp) { + this.size = size; + this.timestamp = timestamp; + } + + public long getSize() { + return size; + } + + public long getTimestamp() { + return timestamp; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + CachedSize that = (CachedSize) o; + + if (size != that.size) return false; + if (timestamp != that.timestamp) return false; + + return true; + } + + @Override + public int hashCode() { + int result = (int) (timestamp ^ (timestamp >>> 32)); + result = 31 * result + (int) (size ^ (size >>> 32)); + return result; + } + + @Override + public String toString() { + return "CachedSize(size=" + size + ", timestamp=" + timestamp + ")"; + } + } + + private void setExportLimitValue() { + OperationResult result = new OperationResult(OPERATION_GET_EXPORT_SIZE_LIMIT); + try { + CompiledGuiProfile adminGui = getModelInteractionService().getCompiledGuiProfile(null, result); + if (adminGui.getDefaultExportSettings() != null && adminGui.getDefaultExportSettings().getSizeLimit() != null) { + exportLimit = adminGui.getDefaultExportSettings().getSizeLimit(); + } + } catch (Exception ex) { + LOGGER.error("Unable to get default export size limit, ", ex); + } + } + + public boolean isExportSize() { + return exportSize; + } + + public void setExportSize(boolean exportSize) { + this.exportSize = exportSize; + } + + public boolean isUseCache() { + return useCache; + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationStatisticsPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationStatisticsPanel.html index 3d0f97ead21..6ed0b9c230e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationStatisticsPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationStatisticsPanel.html @@ -1,26 +1,41 @@ - - - - - -
-
-
-
-
- - + + + + + +

+ +

+
+

+ +

+
+

+ +

+ +
+

+ +

+ +
+ +
+ + diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationStatisticsPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationStatisticsPanel.java index bf91ec4a328..32f849570f0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationStatisticsPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationStatisticsPanel.java @@ -6,7 +6,6 @@ import java.util.Collection; import java.util.List; import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.namespace.QName; import org.apache.wicket.Component; import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator; @@ -103,9 +102,10 @@ protected Long getWallClockAverage(int objectsTotal) { add(infoPanel); - LoadableModel> syncInfoModel = new LoadableModel>(true) { + PropertyModel> syncInfoModel = new PropertyModel>(statisticsModel, "") { + @Override - protected List load() { + public List getObject() { OperationStatsType statsType = statisticsModel.getObject(); if (statsType == null) { return null; @@ -131,7 +131,12 @@ protected List load() { } }; - ListDataProvider syncDataProvider = new ListDataProvider<>(this, syncInfoModel); + ListDataProvider syncDataProvider = new ListDataProvider(this, syncInfoModel) { + @Override + public boolean isUseCache() { + return false; + } + }; List> syncColumns = new ArrayList<>(); syncColumns.add(new PropertyColumn<>(createStringResource("TaskOperationStatisticsPanel.situation"), SynchronizationInformationDto.F_ACTION_NAME)); @@ -148,60 +153,36 @@ protected boolean hideFooterIfSinglePage() { table.setOutputMarkupId(true); add(table); - - - ListDataProvider objectActionsEntry = new ListDataProvider<>(this, - new PropertyModel<>(statisticsModel, OperationStatsType.F_ACTIONS_EXECUTED_INFORMATION.getLocalPart() + "." + ActionsExecutedInformationType.F_RESULTING_OBJECT_ACTIONS_ENTRY)); - - List> actionEntryColumns = new ArrayList<>(); - actionEntryColumns.add(new AbstractColumn(createStringResource("ObjectActionsExecutedEntryType.objectType")) { - @Override - public void populateItem(Item> item, String id, IModel iModel) { - QName entry = iModel.getObject().getObjectType(); - ObjectTypes objectType = null; - if (entry != null) { - objectType = ObjectTypes.getObjectTypeFromTypeQName(entry); - } - item.add(new Label(id, createStringResource(objectType))); - } - }); - actionEntryColumns.add(new EnumPropertyColumn<>(createStringResource("ObjectActionsExecutedEntryType.operation"), ObjectActionsExecutedEntryType.F_OPERATION.getLocalPart())); - actionEntryColumns.add(new AbstractColumn(createStringResource("ObjectActionsExecutedEntryType.chanel")) { + ListDataProvider objectActionsEntry = createActionsEntryProvider(OperationStatsType.F_ACTIONS_EXECUTED_INFORMATION.getLocalPart() + "." + ActionsExecutedInformationType.F_RESULTING_OBJECT_ACTIONS_ENTRY); + BoxedTablePanel actionTable = new BoxedTablePanel(ID_ACTION_ENTRY, objectActionsEntry, createActionEntryColumns()) { @Override - public void populateItem(Item> item, String id, IModel iModel) { - String channel = iModel.getObject().getChannel(); - String key = ""; - if (channel != null && !channel.isEmpty()) { - key = "Channel." + WebComponentUtil.getSimpleChannel(channel); - } - item.add(new Label(id, createStringResource(key))); + protected boolean hideFooterIfSinglePage() { + return true; } - }); - actionEntryColumns.add(new PropertyColumn<>(createStringResource("ObjectActionsExecutedEntryType.totalSuccessCount"), ObjectActionsExecutedEntryType.F_TOTAL_SUCCESS_COUNT.getLocalPart())); - actionEntryColumns.add(new PropertyColumn<>(createStringResource("ObjectActionsExecutedEntryType.lastSuccessDisplayName"), ObjectActionsExecutedEntryType.F_LAST_SUCCESS_OBJECT_DISPLAY_NAME.getLocalPart())); - actionEntryColumns.add(new AbstractColumn(createStringResource("ObjectActionsExecutedEntryType.lastSuccessTimestamp")) { + }; + + actionTable.setOutputMarkupId(true); + add(actionTable); - @Override - public void populateItem(Item> item, String id, IModel iModel) { - XMLGregorianCalendar timestamp = iModel.getObject().getLastSuccessTimestamp(); - item.add(new Label(id, WebComponentUtil.formatDate(timestamp))); - } - }); - actionEntryColumns.add(new PropertyColumn<>(createStringResource("ObjectActionsExecutedEntryType.totalFailureCount"), ObjectActionsExecutedEntryType.F_TOTAL_FAILURE_COUNT.getLocalPart())); - BoxedTablePanel actionTable = new BoxedTablePanel(ID_ACTION_ENTRY, objectActionsEntry, actionEntryColumns) { + BoxedTablePanel resultingEntry = new BoxedTablePanel(ID_RESULTING_ENTRY, createActionsEntryProvider(OperationStatsType.F_ACTIONS_EXECUTED_INFORMATION.getLocalPart() + "." + ActionsExecutedInformationType.F_OBJECT_ACTIONS_ENTRY), createActionEntryColumns()) { @Override protected boolean hideFooterIfSinglePage() { return true; } }; - actionTable.setOutputMarkupId(true); - add(actionTable); + resultingEntry.setOutputMarkupId(true); + add(resultingEntry); - ListDataProvider resultingObjectActionsEntry = new ListDataProvider<>(this, - new PropertyModel<>(statisticsModel, OperationStatsType.F_ACTIONS_EXECUTED_INFORMATION.getLocalPart() + "." + ActionsExecutedInformationType.F_OBJECT_ACTIONS_ENTRY)); + } + + private ListDataProvider createActionsEntryProvider(String expression) { + return new ListDataProvider<>(this, + new PropertyModel<>(statisticsModel, expression)); + } + private List> createActionEntryColumns() { List> resultingEntryColumns = new ArrayList<>(); resultingEntryColumns.add(new AbstractColumn(createStringResource("ObjectActionsExecutedEntryType.objectType")) { @Override @@ -217,7 +198,7 @@ public void populateItem(Item> it } }); resultingEntryColumns.add(new EnumPropertyColumn<>(createStringResource("ObjectActionsExecutedEntryType.operation"), ObjectActionsExecutedEntryType.F_OPERATION.getLocalPart())); - resultingEntryColumns.add(new AbstractColumn(createStringResource("ObjectActionsExecutedEntryType.channel")) { + resultingEntryColumns.add(new AbstractColumn(createStringResource("ObjectActionsExecutedEntryType.chanel")) { @Override public void populateItem(Item> item, String id, IModel iModel) { String channel = iModel.getObject().getChannel(); @@ -238,17 +219,7 @@ public void populateItem(Item> it } }); resultingEntryColumns.add(new PropertyColumn<>(createStringResource("ObjectActionsExecutedEntryType.totalFailureCount"), ObjectActionsExecutedEntryType.F_TOTAL_FAILURE_COUNT.getLocalPart())); - - BoxedTablePanel resultingEntry = new BoxedTablePanel(ID_RESULTING_ENTRY, resultingObjectActionsEntry, resultingEntryColumns) { - @Override - protected boolean hideFooterIfSinglePage() { - return true; - } - }; - - resultingEntry.setOutputMarkupId(true); - add(resultingEntry); - + return resultingEntryColumns; } @Override From 55aeaa495a93fd953679a098718890fceda362ca Mon Sep 17 00:00:00 2001 From: Katarina Valalikova Date: Thu, 12 Mar 2020 14:11:09 +0100 Subject: [PATCH 7/7] bringing back comment :) --- .../java/com/evolveum/midpoint/gui/impl/prism/ItemPanel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemPanel.java index 423561f6e92..545e8fd9ed5 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemPanel.java @@ -74,6 +74,7 @@ protected void onInitialize() { private void initLayout() { + //ugly hack TODO FIME - prism context is lost during srialization/deserialization.. find better way how to do it. if (getModelObject() != null) { getModelObject().revive(getPrismContext()); }