Skip to content

Commit

Permalink
Display all correlation properties
Browse files Browse the repository at this point in the history
The correlation case panel used to show only those
correlation properties that were present in the pre-focus
object being correlated. This was confusing at times.

This commit derives the properties right from the definition
of the correlation, displaying all of them - even those not
present in pre-focus or candidates.

Resolves MID-9408.
  • Loading branch information
mederly committed Jan 15, 2024
1 parent 8c36a45 commit 61863e1
Show file tree
Hide file tree
Showing 22 changed files with 455 additions and 265 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.util.Map;
import java.util.stream.Collectors;

import com.evolveum.midpoint.model.api.correlation.CorrelationPropertyDefinition;
import com.evolveum.midpoint.model.api.correlation.CorrelationService;

import com.evolveum.midpoint.util.DebugUtil;
Expand Down Expand Up @@ -40,7 +41,7 @@ class CorrelationContextDto implements Serializable {
private static final Trace LOGGER = TraceManager.getTrace(CorrelationContextDto.class);

static final String F_CORRELATION_OPTIONS = "correlationOptions";
static final String F_CORRELATION_PROPERTIES = "correlationProperties";
static final String F_CORRELATION_PROPERTIES_DEFINITIONS = "correlationPropertiesDefinitions";

/**
* All correlation options. Correspond to columns in the correlation options table.
Expand All @@ -55,7 +56,7 @@ class CorrelationContextDto implements Serializable {
*
* Correspond to rows in the correlation options table.
*/
private final List<CorrelationCaseDescription.CorrelationProperty> correlationProperties = new ArrayList<>();
private final List<CorrelationPropertyDefinition> correlationPropertiesDefinitions = new ArrayList<>();

CorrelationContextDto(CaseType aCase, PageBase pageBase, Task task, OperationResult result) throws CommonException {
load(aCase, pageBase, task, result);
Expand Down Expand Up @@ -142,11 +143,11 @@ private void createCorrelationOptions(CaseType aCase, CorrelationCaseDescription

private void createCorrelationPropertiesDefinitions(CaseType aCase, PageBase pageBase, Task task, OperationResult result)
throws CommonException {
correlationProperties.clear();
correlationProperties.addAll(
correlationPropertiesDefinitions.clear();
correlationPropertiesDefinitions.addAll(
pageBase.getCorrelationService()
.describeCorrelationCase(aCase, null, task, result)
.getCorrelationPropertiesList());
.getCorrelationPropertiesDefinitionsList());
}

/** Accessed via {@link #F_CORRELATION_OPTIONS}. */
Expand All @@ -155,10 +156,10 @@ public List<CorrelationOptionDto> getCorrelationOptions() {
return correlationOptions;
}

/** Accessed via {@link #F_CORRELATION_PROPERTIES}. */
/** Accessed via {@link #F_CORRELATION_PROPERTIES_DEFINITIONS}. */
@SuppressWarnings("unused")
public List<CorrelationCaseDescription.CorrelationProperty> getCorrelationProperties() {
return correlationProperties;
public List<CorrelationPropertyDefinition> getCorrelationPropertiesDefinitions() {
return correlationPropertiesDefinitions;
}

boolean hasConfidences() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import com.evolveum.midpoint.gui.api.util.WebComponentUtil;
import com.evolveum.midpoint.gui.impl.page.admin.AbstractObjectMainPanel;
import com.evolveum.midpoint.gui.impl.page.admin.cases.CaseDetailsModels;
import com.evolveum.midpoint.model.api.correlation.CorrelationCaseDescription.CorrelationProperty;
import com.evolveum.midpoint.model.api.correlation.CorrelationPropertyDefinition;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;
import com.evolveum.midpoint.schema.util.WorkItemId;
Expand Down Expand Up @@ -218,11 +218,11 @@ protected void populateItem(ListItem<CorrelationOptionDto> item) {
add(matchConfidences);

// 5. A set of rows for individual correlation properties (given name, family name, and so on).
ListView<CorrelationProperty> rows = new ListView<>(ID_ROWS,
new PropertyModel<>(correlationCtxModel, CorrelationContextDto.F_CORRELATION_PROPERTIES)) {
ListView<CorrelationPropertyDefinition> rows = new ListView<>(ID_ROWS,
new PropertyModel<>(correlationCtxModel, CorrelationContextDto.F_CORRELATION_PROPERTIES_DEFINITIONS)) {

@Override
protected void populateItem(ListItem<CorrelationProperty> item) {
protected void populateItem(ListItem<CorrelationPropertyDefinition> item) {
// First column contains the property name
item.add(
new Label(ID_ATTR_NAME,
Expand Down Expand Up @@ -267,7 +267,7 @@ protected CorrelationContextDto load() {
}

private ListView<CorrelationOptionDto> createColumnsForCorrelationPropertyRow(
IModel<CorrelationContextDto> contextModel, ListItem<CorrelationProperty> rowItem) {
IModel<CorrelationContextDto> contextModel, ListItem<CorrelationPropertyDefinition> rowItem) {

return new ListView<>(ID_COLUMNS, new PropertyModel<>(contextModel, CorrelationContextDto.F_CORRELATION_OPTIONS)) {
@Override
Expand All @@ -277,16 +277,16 @@ protected void populateItem(ListItem<CorrelationOptionDto> columnItem) {
CorrelationOptionDto optionDto = columnItem.getModelObject();

// This is the row = the correlation property in question (given name, family name, and so on).
CorrelationProperty correlationProperty = rowItem.getModelObject();
CorrelationPropertyDefinition correlationPropertyDef = rowItem.getModelObject();

// Provide the values: either for a candidate or for the reference (object being matched).
CorrelationPropertyValues values = optionDto.getPropertyValues(correlationProperty);
CorrelationPropertyValues values = optionDto.getPropertyValues(correlationPropertyDef);
Label valuesLabel = new Label(ID_COLUMN, values.format());

// Colorize the field
if (optionDto instanceof CorrelationOptionDto.Candidate candidate) {
MatchVisualizationStyle matchVisualizationStyle;
var propertyValuesDescription = candidate.getPropertyValuesDescription(correlationProperty);
var propertyValuesDescription = candidate.getPropertyValuesDescription(correlationPropertyDef);
if (propertyValuesDescription != null) {
matchVisualizationStyle = MatchVisualizationStyle.forMatch(propertyValuesDescription.getMatch());
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import com.evolveum.midpoint.gui.api.util.LocalizationUtil;
import com.evolveum.midpoint.model.api.correlation.CorrelationCaseDescription;
import com.evolveum.midpoint.model.api.correlation.CorrelationCaseDescription.CorrelationProperty;
import com.evolveum.midpoint.model.api.correlation.CorrelationPropertyDefinition;
import com.evolveum.midpoint.model.api.correlation.CorrelationCaseDescription.CorrelationPropertyValuesDescription;
import com.evolveum.midpoint.model.api.correlator.CorrelationExplanation;
import com.evolveum.midpoint.prism.PrismObject;
Expand Down Expand Up @@ -51,7 +51,7 @@ public abstract class CorrelationOptionDto implements Serializable {
/**
* Returns all real values matching given item path. The path should not contain container IDs.
*/
abstract CorrelationPropertyValues getPropertyValues(CorrelationProperty correlationProperty);
abstract CorrelationPropertyValues getPropertyValues(CorrelationPropertyDefinition correlationPropertyDef);

public @NotNull PrismObject<?> getObject() {
return object;
Expand Down Expand Up @@ -103,13 +103,14 @@ public String getCandidateExplanation() {
}

@Override
CorrelationPropertyValues getPropertyValues(CorrelationProperty correlationProperty) {
CorrelationPropertyValues getPropertyValues(@NotNull CorrelationPropertyDefinition correlationPropertyDef) {
return CorrelationPropertyValues.fromDescription(
getPropertyValuesDescription(correlationProperty));
getPropertyValuesDescription(correlationPropertyDef));
}

CorrelationPropertyValuesDescription getPropertyValuesDescription(@NotNull CorrelationProperty correlationProperty) {
return candidateDescription.getPropertyValuesDescription(correlationProperty);
CorrelationPropertyValuesDescription getPropertyValuesDescription(
@NotNull CorrelationPropertyDefinition correlationPropertyDef) {
return candidateDescription.getPropertyValuesDescription(correlationPropertyDef);
}
}

Expand All @@ -136,8 +137,8 @@ public String getCandidateExplanation() {
}

@Override
CorrelationPropertyValues getPropertyValues(CorrelationProperty correlationProperty) {
return CorrelationPropertyValues.fromObject(object, correlationProperty.getItemPath());
CorrelationPropertyValues getPropertyValues(CorrelationPropertyDefinition correlationPropertyDef) {
return CorrelationPropertyValues.fromObject(object, correlationPropertyDef.getItemPath());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ public static List<PrismProperty<?>> getSingleValuedProperties(@NotNull ObjectTy
List<PrismProperty<?>> properties = new ArrayList<>();
//noinspection unchecked
object.asPrismObject().accept(visitable -> {
if (visitable instanceof PrismProperty<?>) {
PrismProperty<?> property = (PrismProperty<?>) visitable;
if (visitable instanceof PrismProperty<?> property) {
if (property.size() > 1) {
LOGGER.trace("getSingleValuedProperties: Ignoring property because of multiple values: {}", property);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,13 @@
import org.jetbrains.annotations.Nullable;

import com.evolveum.midpoint.model.api.correlator.CorrelationExplanation;
import com.evolveum.midpoint.prism.ItemDefinition;
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.path.ItemName;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.path.PathKeyedMap;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.util.DebugDumpable;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CaseType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusIdentityType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType;

/**
Expand All @@ -37,9 +32,9 @@
*
* Contains the object being correlated (currently called {@link #preFocus}) and the correlation candidates ({@link #candidates}).
*
* The correlation data are represented as a set of {@link #correlationProperties}, whose values on the source are to be fetched
* directly from {@link #preFocus}, but the valued for candidates are processed into the form of
* {@link CorrelationPropertyValuesDescription}:
* The correlation data are represented as a set of {@link #correlationPropertiesDefinitions},
* whose values on the source are to be fetched directly from {@link #preFocus}, but the valued for
* candidates are processed into the form of {@link CorrelationPropertyValuesDescription}:
*
* - sorted out into "primary" and "secondary" values (corresponding to the main identity and alternative ones),
* - and providing a {@link Match} value that shows the degree of match between the particular candidate and the pre-focus
Expand All @@ -52,7 +47,7 @@ public class CorrelationCaseDescription<F extends FocusType> implements DebugDum
/** Object being correlated, a.k.a. the source object. TODO find better name for this field */
@NotNull private final F preFocus;

@NotNull private final PathKeyedMap<CorrelationProperty> correlationProperties = new PathKeyedMap<>();
@NotNull private final PathKeyedMap<CorrelationPropertyDefinition> correlationPropertiesDefinitions = new PathKeyedMap<>();

@NotNull private final List<CandidateDescription<F>> candidates = new ArrayList<>();

Expand All @@ -64,31 +59,35 @@ public CorrelationCaseDescription(@NotNull F preFocus) {
return preFocus;
}

public @NotNull PathKeyedMap<CorrelationProperty> getCorrelationProperties() {
return correlationProperties;
public @NotNull PathKeyedMap<CorrelationPropertyDefinition> getCorrelationPropertiesDefinitions() {
return correlationPropertiesDefinitions;
}

/** The list is sorted according to display order (and display name, in case of ambiguity). */
public @NotNull List<CorrelationProperty> getCorrelationPropertiesList() {
var list = new ArrayList<>(correlationProperties.values());
public @NotNull List<CorrelationPropertyDefinition> getCorrelationPropertiesDefinitionsList() {
var list = new ArrayList<>(correlationPropertiesDefinitions.values());
list.sort(
Comparator.comparing(CorrelationProperty::getDisplayOrder, Comparator.nullsLast(Comparator.naturalOrder()))
.thenComparing(CorrelationProperty::getDisplayName));
Comparator.comparing(CorrelationPropertyDefinition::getDisplayOrder, Comparator.nullsLast(Comparator.naturalOrder()))
.thenComparing(CorrelationPropertyDefinition::getDisplayName));
return list;
}

public @NotNull List<CandidateDescription<F>> getCandidates() {
return candidates;
}

public void addCorrelationProperty(CorrelationProperty property) {
correlationProperties.put(property.getItemPath(), property);
public boolean hasCorrelationProperty(@NotNull ItemPath path) {
return correlationPropertiesDefinitions.containsKey(path);
}

public void addCorrelationPropertyDefinition(CorrelationPropertyDefinition property) {
correlationPropertiesDefinitions.put(property.getItemPath(), property);
}

@Override
public String toString() {
return getClass().getSimpleName() + "{" +
"correlationProperties: " + correlationProperties.size() +
"correlationProperties: " + correlationPropertiesDefinitions.size() +
"candidates: " + candidates.size() +
'}';
}
Expand All @@ -97,7 +96,7 @@ public String toString() {
public String debugDump(int indent) {
StringBuilder sb = DebugUtil.createTitleStringBuilderLn(getClass(), indent);
DebugUtil.debugDumpWithLabelLn(sb, "preFocus", preFocus, indent + 1);
DebugUtil.debugDumpWithLabelLn(sb, "correlationProperties", correlationProperties, indent + 1);
DebugUtil.debugDumpWithLabelLn(sb, "correlationPropertiesDefinitions", correlationPropertiesDefinitions, indent + 1);
DebugUtil.debugDumpWithLabel(sb, "candidates", candidates, indent + 1);
return sb.toString();
}
Expand Down Expand Up @@ -145,8 +144,9 @@ public double getConfidence() {
return confidence;
}

public @Nullable CorrelationPropertyValuesDescription getPropertyValuesDescription(@NotNull CorrelationProperty property) {
return getPropertyValuesDescription(property.getItemPath());
public @Nullable CorrelationPropertyValuesDescription getPropertyValuesDescription(
@NotNull CorrelationPropertyDefinition propertyDef) {
return getPropertyValuesDescription(propertyDef.getItemPath());
}

public @Nullable CorrelationPropertyValuesDescription getPropertyValuesDescription(@NotNull ItemPath propertyPath) {
Expand Down Expand Up @@ -178,93 +178,9 @@ public String debugDump(int indent) {
}
}

/**
* Contains information about a correlation property that is to be (e.g.) displayed in the correlation case view.
*
* TEMPORARY
*/
public static class CorrelationProperty implements Serializable, DebugDumpable {

public static final String F_DISPLAY_NAME = "displayName";

/** The "technical" name. */
@NotNull private final String name;

/** Path within the focus object. */
@NotNull private final ItemPath itemPath;

/** Definition in the focus object. */
@Nullable private final ItemDefinition<?> definition;

private CorrelationProperty(
@NotNull String name,
@NotNull ItemPath itemPath,
@Nullable ItemDefinition<?> definition) {
this.name = name;
this.itemPath = itemPath;
this.definition = definition;
}

public static CorrelationProperty createSimple(
@NotNull ItemPath path,
@Nullable PrismPropertyDefinition<?> definition) {
ItemName lastName =
MiscUtil.requireNonNull(path.lastName(), () -> new IllegalArgumentException("Path has no last name: " + path));
return new CorrelationProperty(lastName.getLocalPart(), path, definition);
}

public @NotNull ItemPath getItemPath() {
return itemPath;
}

public @NotNull ItemPath getSecondaryPath() {
return SchemaConstants.PATH_FOCUS_IDENTITY.append(FocusIdentityType.F_DATA, itemPath);
}

public @Nullable ItemDefinition<?> getDefinition() {
return definition;
}

public @NotNull String getDisplayName() {
if (definition != null) {
if (definition.getDisplayName() != null) {
return definition.getDisplayName();
} else {
return definition.getItemName().getLocalPart();
}
} else {
return name;
}
}

public Integer getDisplayOrder() {
return definition != null ? definition.getDisplayOrder() : null;
}

public @NotNull String getName() {
return name;
}

@Override
public String toString() {
return getClass().getSimpleName() + "{" +
"itemPath=" + itemPath +
'}';
}

@Override
public String debugDump(int indent) {
StringBuilder sb = DebugUtil.createTitleStringBuilderLn(getClass(), indent);
DebugUtil.debugDumpWithLabelLn(sb, "name", name, indent + 1);
DebugUtil.debugDumpWithLabelLn(sb, "itemPath", String.valueOf(itemPath), indent + 1);
DebugUtil.debugDumpWithLabel(sb, "definition", String.valueOf(definition), indent + 1);
return sb.toString();
}
}

public static class CorrelationPropertyValuesDescription implements Serializable {

@NotNull private final CorrelationProperty correlationProperty;
@NotNull private final CorrelationPropertyDefinition propertyDefinition;

// TODO clarify
@NotNull private final Set<PrismValue> primaryValues;
Expand All @@ -275,20 +191,16 @@ public static class CorrelationPropertyValuesDescription implements Serializable
@NotNull private final Match match;

public CorrelationPropertyValuesDescription(
@NotNull CorrelationProperty correlationProperty,
@NotNull CorrelationPropertyDefinition propertyDefinition,
@NotNull Set<PrismValue> primaryValues,
@NotNull Set<PrismValue> secondaryValues,
@NotNull Match match) {
this.correlationProperty = correlationProperty;
this.propertyDefinition = propertyDefinition;
this.primaryValues = primaryValues;
this.secondaryValues = secondaryValues;
this.match = match;
}

public @NotNull CorrelationProperty getCorrelationProperty() {
return correlationProperty;
}

public @NotNull Set<PrismValue> getPrimaryValues() {
return primaryValues;
}
Expand All @@ -303,7 +215,7 @@ public CorrelationPropertyValuesDescription(

@Override
public String toString() {
return correlationProperty.getItemPath()
return propertyDefinition.getItemPath()
+ ": primary=" + dump(primaryValues)
+ ", secondary=" + dump(secondaryValues)
+ ", match=" + match;
Expand Down

0 comments on commit 61863e1

Please sign in to comment.