Skip to content

Commit

Permalink
Add explicit list of ID Match correlation items
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Aug 16, 2022
1 parent 3e0af32 commit d607462
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@
</xsd:appinfo>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="path" type="t:ItemPathType" minOccurs="0">
<xsd:element name="path" type="t:ItemPathType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
Path of the property. It may start with $shadow (or $projection) - then it denotes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,23 @@

import static java.util.Objects.requireNonNullElse;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
import javax.xml.namespace.QName;

import com.evolveum.midpoint.model.impl.ModelBeans;
import com.evolveum.midpoint.model.impl.correlator.items.CorrelationItem;
import com.evolveum.midpoint.prism.Itemable;
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.schema.processor.ResourceAttribute;
import com.evolveum.midpoint.schema.util.ShadowUtil;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;

import com.evolveum.prism.xml.ns._public.types_3.ItemPathType;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

Expand Down Expand Up @@ -94,24 +97,70 @@ public IdMatchObject create() throws SchemaException, ConfigurationException {
return IdMatchObject.create(getSorIdentifierValue(), attributes);
}

/** May return "live" properties. They will be cloned. */
private @NotNull List<PrismProperty<?>> getCorrelationProperties() throws SchemaException, ConfigurationException {
List<CorrelationItem> correlationItems = getExplicitCorrelationItems();
if (!correlationItems.isEmpty()) {
List<PrismProperty<?>> properties = new ArrayList<>();
for (CorrelationItem correlationItem : correlationItems) {
PrismProperty<?> sourceProperty = correlationItem.getRenamedSourceProperty();
if (sourceProperty != null) {
properties.add(sourceProperty);
}
}
return properties;
/** May return "live" properties. They must be cloned by the caller. */
private @NotNull List<PrismProperty<?>> getCorrelationProperties() throws ConfigurationException {
IdMatchCorrelationPropertiesType propertiesDef = correlatorContext.getConfigurationBean().getCorrelationProperties();
List<ItemPathType> pathBeanList = propertiesDef != null ? propertiesDef.getPath() : List.of();
if (!pathBeanList.isEmpty()) {
return getConfiguredProperties(pathBeanList);
} else {
// Fallback: take all single-valued properties from the focus
return MatchingUtil.getSingleValuedProperties(preFocus);
}
}

private List<PrismProperty<?>> getConfiguredProperties(List<ItemPathType> pathBeanList) throws ConfigurationException {
List<PrismProperty<?>> properties = new ArrayList<>();
for (ItemPathType pathBean : pathBeanList) {
ItemPath propertyPath = pathBean.getItemPath();
ObjectType source = getSourceObject(propertyPath);
ItemPath purePath = propertyPath.stripVariableSegment();
Set<PrismValue> allValues = new HashSet<>(source.asPrismContainerValue().getAllValues(purePath));
LOGGER.trace("Configured correlation property '{}' yielding values: {}", propertyPath, allValues);
if (allValues.isEmpty()) {
// Let us check if the path is correct, to allow fast fail on problems.
PrismPropertyDefinition<Object> def = source.asPrismObject().getDefinition().findPropertyDefinition(purePath);
if (def == null) {
throw new ConfigurationException(
String.format("No definition of '%s' in %s. Is the path correct?", purePath, source));
} else {
continue;
}
} else if (allValues.size() > 1) {
throw new UnsupportedOperationException(
String.format("Correlation based on multi-valued properties is not supported. "
+ "Item '%s' has multiple values in %s: %s", purePath, source, allValues));
}
PrismValue value = allValues.iterator().next();
Itemable parent = value.getParent();
if (!(parent instanceof PrismProperty<?>)) {
throw new IllegalStateException("Parent of " + value + " is not a PrismProperty; it is " + parent);
}
properties.add(((PrismProperty<?>) parent));
}
return properties;
}

private @NotNull ObjectType getSourceObject(ItemPath propertyPath) throws ConfigurationException {
QName variableName = propertyPath.firstToVariableNameOrNull();
String variableLocalName = variableName != null ? variableName.getLocalPart() : null;
if (variableLocalName != null) {
if (ExpressionConstants.VAR_FOCUS.equals(variableLocalName)
|| ExpressionConstants.VAR_USER.equals(variableLocalName)) {
return preFocus;
} else if (ExpressionConstants.VAR_PROJECTION.equals(variableLocalName)
|| ExpressionConstants.VAR_SHADOW.equals(variableLocalName)
|| ExpressionConstants.VAR_ACCOUNT.equals(variableLocalName)) {
return shadow;
} else {
throw new ConfigurationException(
"Unsupported variable name in correlation property path '" + propertyPath + "'");
}
} else {
return preFocus;
}
}

private String getSorIdentifierValue() throws SchemaException {
PrismProperty<?> identifier = resolveProperty(sorIdPropertyPath);
if (identifier == null || identifier.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,27 +202,6 @@ private PrismValue getSinglePrismValue() {
() -> new UnsupportedOperationException("Multiple values of " + itemPath + " are not supported: " + prismValues));
}

public @Nullable PrismProperty<?> getProperty() throws SchemaException {
PrismValue single = getSinglePrismValue();
if (single == null) {
return null;
}
Itemable parent = single.getParent();
if (parent == null) {
throw new IllegalStateException("Parent-less source value: " + single + " in " + this);
} else if (parent instanceof PrismProperty) {
return (PrismProperty<?>) parent;
} else {
throw new UnsupportedOperationException("Non-property sources are not supported: " + single + " in " + this);
}
}

public @Nullable ItemDefinition<?> getDefinition() throws SchemaException {
// Very temporary implementation
PrismProperty<?> property = getProperty();
return property != null ? property.getDefinition() : null;
}

public S_FilterExit addClauseToQueryBuilder(
S_FilterEntry builder, Task task, OperationResult result)
throws SchemaException, ExpressionEvaluationException, CommunicationException, SecurityViolationException,
Expand Down Expand Up @@ -322,24 +301,6 @@ public boolean isApplicable() throws SchemaException {
return getRealValue() != null;
}

/**
* Returns the source value wrapped in a property.
* The property will be named after correlation item, not after the source property.
*
* It may be empty. But must not be multi-valued.
*
* TODO
*/
public @Nullable PrismProperty<?> getRenamedSourceProperty() throws SchemaException {
var property = getProperty();
if (property == null || name.equals(property.getElementName().getLocalPart())) {
return property;
}
PrismProperty<?> clone = property.clone();
clone.setElementName(new QName(name));
return clone;
}

public @NotNull String getName() {
return name;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@
<idMatchCorrelator
xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3">
<name>id-match</name>
<description>
Correlates using dummy ID Match service plus a filter that uses returned referenceId.
This is the expected style of use.
</description>
<!-- No url nor credentials. A dummy service is used instead. -->
<referenceIdProperty>employeeNumber</referenceIdProperty>
<correlationProperties>
<path>$focus/givenName</path>
<path>$shadow/attributes/familyName</path> <!-- just check the use of $shadow -->
<path>$focus/extension/dateOfBirth</path>
<path>$focus/extension/nationalId</path>
<path>$shadow/attributes/employeeNumber</path> <!-- Intentionally null-valued attribute -->
</correlationProperties>
<candidateConfidenceLimit>0.4</candidateConfidenceLimit>
</idMatchCorrelator>

0 comments on commit d607462

Please sign in to comment.