Skip to content

Commit

Permalink
Fix sync task naming
Browse files Browse the repository at this point in the history
The task names are now more understandable, without phrases like
"account/null". They are also localized now.

This resolves MID-8484.
  • Loading branch information
mederly committed Mar 21, 2023
1 parent cf3bb71 commit 0a1ed20
Show file tree
Hide file tree
Showing 3 changed files with 246 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.evolveum.midpoint.schema.RelationRegistry;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition;
import com.evolveum.midpoint.schema.processor.ResourceSchemaUtil;
import com.evolveum.midpoint.schema.util.FocusIdentityTypeUtil;
import com.evolveum.midpoint.schema.util.FocusTypeUtil;
import com.evolveum.midpoint.schema.util.WorkItemId;
Expand Down Expand Up @@ -1472,7 +1473,38 @@ interface TriggerCustomizer {
void customize(TriggerType trigger) throws SchemaException;
}

String describeResourceObjectSet(ResourceObjectSetType set) throws SchemaException, ExpressionEvaluationException, CommunicationException, SecurityViolationException, ConfigurationException, ObjectNotFoundException;
/**
* Returns longer version of human-readable description of the resource object set:
*
* . resource name
* . object type display name (if known)
* . object type ID (kind, intent)
* . flag whether we are using default type definition
* . object class
*
* Currently, object types are resolved and named using the
* {@link ResourceSchemaUtil#findDefinitionForBulkOperation(ResourceType, ShadowKindType, String, QName)} method
* that is used for import and reconciliation activities. Hence, the name should be quite precise in the context
* of these activities.
*/
String describeResourceObjectSetLong(ResourceObjectSetType set) throws SchemaException, ExpressionEvaluationException,
CommunicationException, SecurityViolationException, ConfigurationException, ObjectNotFoundException;

/**
* Short version of {@link #describeResourceObjectSetLong(ResourceObjectSetType)}:
*
* . only one of object type display name and type ID is shown;
* . object class is omitted when type is present
*/
String describeResourceObjectSetShort(ResourceObjectSetType set) throws SchemaException, ExpressionEvaluationException,
CommunicationException, SecurityViolationException, ConfigurationException, ObjectNotFoundException;

/** Synonym for {@link #describeResourceObjectSetShort(ResourceObjectSetType)}, mainly for compatibility reasons. */
default String describeResourceObjectSet(ResourceObjectSetType set) throws SchemaException, ExpressionEvaluationException,
CommunicationException, SecurityViolationException, ConfigurationException, ObjectNotFoundException {
return describeResourceObjectSetShort(set);
}


/**
* Selects specified values from all relevant identity data.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

import com.evolveum.midpoint.schema.processor.*;
import com.evolveum.midpoint.util.logging.LoggingUtils;

import com.google.common.base.Preconditions;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -86,10 +89,6 @@
import com.evolveum.midpoint.schema.constants.MidPointConstants;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.messaging.MessageWrapper;
import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition;
import com.evolveum.midpoint.schema.processor.ResourceObjectDefinition;
import com.evolveum.midpoint.schema.processor.ResourceSchema;
import com.evolveum.midpoint.schema.processor.ResourceSchemaFactory;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.result.OperationResultStatus;
import com.evolveum.midpoint.schema.util.*;
Expand Down Expand Up @@ -234,6 +233,7 @@ public String getPlaintextAccountPasswordFromDelta(ObjectDelta<? extends ShadowT
}
}

@SuppressWarnings("rawtypes")
private void takePasswordsFromItemDelta(List<ProtectedStringType> passwords, ItemDelta itemDelta) {
if (itemDelta.isDelete()) {
return;
Expand Down Expand Up @@ -1311,8 +1311,7 @@ public ObjectDeltaType getResourceDelta(ModelContext<?> context, String resource
List<ObjectDelta<ShadowType>> deltas = new ArrayList<>();
for (Object modelProjectionContextObject : context.getProjectionContexts()) {
LensProjectionContext lensProjectionContext = (LensProjectionContext) modelProjectionContextObject;
if (lensProjectionContext.getKey() != null &&
resourceOid.equals(lensProjectionContext.getKey().getResourceOid())) {
if (resourceOid.equals(lensProjectionContext.getKey().getResourceOid())) {
deltas.add(lensProjectionContext.getSummaryDelta()); // union of primary and secondary deltas
}
}
Expand Down Expand Up @@ -2315,8 +2314,22 @@ public <T> T getExtensionOptionRealValue(String localName, Class<T> type) {
}

@Override
public String describeResourceObjectSet(ResourceObjectSetType set)
throws SchemaException, ExpressionEvaluationException, CommunicationException, SecurityViolationException, ConfigurationException, ObjectNotFoundException {
public String describeResourceObjectSetLong(ResourceObjectSetType set)
throws SchemaException, ExpressionEvaluationException, CommunicationException, SecurityViolationException,
ConfigurationException, ObjectNotFoundException {
return describeResourceObjectSet(set, true);
}

@Override
public String describeResourceObjectSetShort(ResourceObjectSetType set)
throws SchemaException, ExpressionEvaluationException, CommunicationException, SecurityViolationException,
ConfigurationException, ObjectNotFoundException {
return describeResourceObjectSet(set, false);
}

private String describeResourceObjectSet(ResourceObjectSetType set, boolean longVersion)
throws SchemaException, ExpressionEvaluationException, CommunicationException, SecurityViolationException,
ConfigurationException, ObjectNotFoundException {

if (set == null) {
return null;
Expand All @@ -2327,31 +2340,101 @@ public String describeResourceObjectSet(ResourceObjectSetType set)
return null;
}

ObjectType resource = resolveReferenceInternal(ref, true);
if (resource == null) {
ObjectType object = resolveReferenceInternal(ref, true);
if (!(object instanceof ResourceType)) {
return null;
}

ResourceType resource = (ResourceType) object;

StringBuilder sb = new StringBuilder();
sb.append(resource.getName().getOrig());

if (set.getObjectclass() != null) {
sb.append(" for ");
sb.append(set.getObjectclass().getLocalPart());
ShadowKindType kind = set.getKind();
String intent = set.getIntent();
QName objectclass = set.getObjectclass();

if (kind != null) {

sb.append(": ");

var definition = getResourceObjectDefinition(resource, kind, intent, objectclass);
ResourceObjectTypeIdentification typeIdentification = definition != null ? definition.getTypeIdentification() : null;

String typeDisplayName = definition != null ? definition.getDisplayName() : null;
if (typeDisplayName != null) {
sb.append(typeDisplayName);
if (longVersion) {
sb.append(" (");
sb.append(getTypeIdDescription(kind, intent, typeIdentification, true));
sb.append(")");
}
} else {
sb.append(getTypeIdDescription(kind, intent, typeIdentification, longVersion));
}
}

ShadowKindType kind = set.getKind();
if (kind != null || set.getIntent() != null) {
sb.append(" (");
sb.append(kind != null ? kind.value() : "");
sb.append("/");
sb.append(set.getIntent());
sb.append(")");
// Actually, kind/intent + object class should not be used both
if (objectclass != null && (longVersion || kind == null)) {
sb.append(" [").append(objectclass.getLocalPart()).append("]");
}

return sb.toString();
}

private @NotNull String getTypeIdDescription(
ShadowKindType origKind, String origIntent, ResourceObjectTypeIdentification resolvedTypeId, boolean longVersion) {
if (origIntent != null) {
return localizedTypeId(origKind, origIntent);
} else {
if (resolvedTypeId != null) {
if (longVersion) {
return localizationService.translate(
"TypeIdDescription.asTheDefaultIntent",
new Object[] { localizedTypeId(resolvedTypeId.getKind(), resolvedTypeId.getIntent()) },
localizationService.getDefaultLocale());
} else {
return localizedTypeId(resolvedTypeId.getKind(), resolvedTypeId.getIntent());
}
} else {
return localizationService.translate(
"TypeIdDescription.defaultIntentFor",
new Object[] { SingleLocalizableMessage.forEnum(origKind) },
localizationService.getDefaultLocale());
}
}
}

private String localizedTypeId(@NotNull ShadowKindType kind, @NotNull String intent) {
return localizationService.translate(
"TypeIdDescription.typeId",
new Object[] { SingleLocalizableMessage.forEnum(kind), intent },
localizationService.getDefaultLocale());
}

private ResourceObjectDefinition getResourceObjectDefinition(
ResourceType resource, ShadowKindType kind, String intent, QName objectclass) {
ResourceSchema completeSchema;
try {
completeSchema = Resource.of(resource).getCompleteSchema();
} catch (Exception e) {
LoggingUtils.logException(LOGGER, "Couldn't get schema for {}", e, resource);
return null;
}
if (completeSchema == null) {
return null;
}

try {
// This is the same method that is currently used when doing the processing in import/recon tasks.
return ResourceSchemaUtil.findDefinitionForBulkOperation(resource, kind, intent, objectclass);
} catch (Exception e) {
LoggingUtils.logException(LOGGER, "Couldn't get definition for {}/{}/{} in {}",
e, kind, intent, objectclass, resource);
return null;
}
}

@Override
public Collection<PrismValue> selectIdentityItemValues(
@Nullable Collection<FocusIdentityType> identities,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
*/
package com.evolveum.midpoint.model.intest;

import static com.evolveum.midpoint.schema.constants.MidPointConstants.NS_RI;
import static com.evolveum.midpoint.schema.constants.SchemaConstants.RI_ACCOUNT_OBJECT_CLASS;

import static com.evolveum.midpoint.schema.constants.SchemaConstants.RI_GROUP_OBJECT_CLASS;

import static org.assertj.core.api.Assertions.assertThat;

import static com.evolveum.midpoint.schema.util.MiscSchemaUtil.getExpressionProfile;
Expand All @@ -20,8 +25,9 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import com.evolveum.midpoint.model.api.expr.MidpointFunctions;
import com.evolveum.midpoint.repo.api.CacheDispatcher;
import com.evolveum.midpoint.util.Holder;
import com.evolveum.midpoint.util.*;
import com.evolveum.midpoint.util.exception.SystemException;

import com.evolveum.midpoint.util.logging.Trace;
Expand All @@ -47,13 +53,12 @@
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.test.TestResource;
import com.evolveum.midpoint.test.util.TestUtil;
import com.evolveum.midpoint.util.CheckedRunnable;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.exception.CommonException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;

import javax.xml.namespace.QName;

/**
* Tests selected methods in MidpointFunctions + parts of "function libraries" feature.
*/
Expand Down Expand Up @@ -106,6 +111,16 @@ private void execute(Task task, OperationResult result, CheckedRunnable runnable
}
}

private <T> T execute(Task task, OperationResult result, CheckedProducer<T> producer) throws Exception {
ExpressionEnvironmentThreadLocalHolder.pushExpressionEnvironment(
new ExpressionEnvironment(task, result));
try {
return producer.get();
} finally {
ExpressionEnvironmentThreadLocalHolder.popExpressionEnvironment();
}
}

/**
* MID-6133
*/
Expand Down Expand Up @@ -141,8 +156,9 @@ public void test120AddRecomputeTrigger() throws Exception {
PrismObject<UserType> administrator = getUser(USER_ADMINISTRATOR_OID);

when();
execute(task, result, () -> libraryMidpointFunctions.addRecomputeTrigger(administrator, null,
trigger -> trigger.setOriginDescription("test120")));
execute(task, result, () ->
libraryMidpointFunctions.addRecomputeTrigger(
administrator, null, trigger -> trigger.setOriginDescription("test120")));

then();
assertSuccess(result);
Expand Down Expand Up @@ -336,4 +352,92 @@ private void executeWithInvalidationInBetween(
() -> cacheDispatcher.dispatchInvalidation(FunctionLibraryType.class, null, false, null);
executeWithActionInBetween(duration, invalidationInterval, minInvalidationCount, action, task, result);
}

/** Checks {@link MidpointFunctions#describeResourceObjectSetShort(ResourceObjectSetType)} and siblings. MID-8484. */
@Test
public void test300DescribeResourceObjectSet() throws Exception {

when("kind is present");
ResourceObjectSetType set1 = new ResourceObjectSetType()
.resourceRef(RESOURCE_DUMMY_OID, ResourceType.COMPLEX_TYPE)
.kind(ShadowKindType.ACCOUNT);
var short1 = describeShort(set1);
var long1 = describeLong(set1);

then("descriptions are OK");
displayValue("short", short1);
assertThat(short1).isEqualTo("Dummy Resource: Default Account");
displayValue("long", long1);
assertThat(long1).isEqualTo("Dummy Resource: Default Account (Account/default as the default intent)");

when("kind+intent are present");
ResourceObjectSetType set2 = new ResourceObjectSetType()
.resourceRef(RESOURCE_DUMMY_OID, ResourceType.COMPLEX_TYPE)
.kind(ShadowKindType.ACCOUNT)
.intent("default");
var short2 = describeShort(set2);
var long2 = describeLong(set2);

then("descriptions are OK");
displayValue("short", short2);
assertThat(short2).isEqualTo("Dummy Resource: Default Account");
displayValue("long", long2);
assertThat(long2).isEqualTo("Dummy Resource: Default Account (Account/default)");

when("kind+intent+OC are present");
ResourceObjectSetType set3 = new ResourceObjectSetType()
.resourceRef(RESOURCE_DUMMY_OID, ResourceType.COMPLEX_TYPE)
.kind(ShadowKindType.ACCOUNT)
.intent("default")
.objectclass(RI_ACCOUNT_OBJECT_CLASS);
var short3 = describeShort(set3);
var long3 = describeLong(set3);

then("descriptions are OK");
displayValue("short", short3);
assertThat(short3).isEqualTo("Dummy Resource: Default Account");
displayValue("long", long3);
assertThat(long3).isEqualTo("Dummy Resource: Default Account (Account/default) [AccountObjectClass]");

when("kind+OC are present (no display name)");
ResourceObjectSetType set4 = new ResourceObjectSetType()
.resourceRef(RESOURCE_DUMMY_OID, ResourceType.COMPLEX_TYPE)
.kind(ShadowKindType.ENTITLEMENT)
.objectclass(RI_GROUP_OBJECT_CLASS);
var short4 = describeShort(set4);
var long4 = describeLong(set4);

then("descriptions are OK");
displayValue("short", short4);
assertThat(short4).isEqualTo("Dummy Resource: Entitlement/group");
displayValue("long", long4);
assertThat(long4).isEqualTo("Dummy Resource: Entitlement/group as the default intent [GroupObjectClass]");

when("OC is present only");
ResourceObjectSetType set5 = new ResourceObjectSetType()
.resourceRef(RESOURCE_DUMMY_OID, ResourceType.COMPLEX_TYPE)
.objectclass(new QName(NS_RI, "CustomprivilegeObjectClass"));
var short5 = describeShort(set5);
var long5 = describeLong(set5);

then("descriptions are OK");
displayValue("short", short5);
assertThat(short5).isEqualTo("Dummy Resource [CustomprivilegeObjectClass]");
displayValue("long", long5);
assertThat(long5).isEqualTo("Dummy Resource [CustomprivilegeObjectClass]");
}

private String describeShort(ResourceObjectSetType set) throws Exception {
return execute(
getTestTask(),
getTestOperationResult(),
() -> libraryMidpointFunctions.describeResourceObjectSetShort(set));
}

private String describeLong(ResourceObjectSetType set) throws Exception {
return execute(
getTestTask(),
getTestOperationResult(),
() -> libraryMidpointFunctions.describeResourceObjectSetLong(set));
}
}

0 comments on commit 0a1ed20

Please sign in to comment.