use of com.evolveum.midpoint.xml.ns._public.common.common_3.PartialProcessingTypeType.SKIP in project midpoint by Evolveum.
the class AccountActivationNotifier method checkApplicability.
@Override
protected boolean checkApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) {
if (!event.isSuccess()) {
LOGGER.trace("Operation was not successful, exiting.");
return false;
}
ModelEvent modelEvent = (ModelEvent) event;
if (modelEvent.getFocusDeltas().isEmpty()) {
LOGGER.trace("No user deltas in event, exiting.");
return false;
}
List<ShadowType> shadows = getShadowsToActivate(modelEvent);
if (shadows.isEmpty()) {
LOGGER.trace("No shadows to activate found in model context. Skip sending notifications.");
return false;
}
LOGGER.trace("Found shadows to activate: {}. Skip sending notifications.", shadows);
return true;
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.PartialProcessingTypeType.SKIP in project midpoint by Evolveum.
the class WfHook method invoke.
@Override
public <O extends ObjectType> HookOperationMode invoke(@NotNull ModelContext<O> context, @NotNull Task task, @NotNull OperationResult parentResult) {
// Generally this cannot be minor as we need the "task switched to background" flag.
// But if the hook does nothing (returns FOREGROUND flag), we mark the result
// as minor afterwards.
OperationResult result = parentResult.createSubresult(OP_INVOKE);
result.addParam("task", task.toString());
result.addArbitraryObjectAsContext("model state", context.getState());
try {
WfConfigurationType wfConfigurationType = configurationHelper.getWorkflowConfiguration(context, result);
if (wfConfigurationType != null && Boolean.FALSE.equals(wfConfigurationType.isModelHookEnabled())) {
LOGGER.info("Workflow model hook is disabled. Proceeding with operation execution as if everything is approved.");
result.recordSuccess();
return HookOperationMode.FOREGROUND;
}
if (context.getPartialProcessingOptions().getApprovals() == PartialProcessingTypeType.SKIP) {
LOGGER.debug("Skipping workflow processing because of the partial processing option set to SKIP");
result.recordSuccess();
return HookOperationMode.FOREGROUND;
}
// e.g. for tests, initialization is scattered through many places, so that would be too much work.
if (SchemaConstants.CHANNEL_INIT_URI.equals(context.getChannel())) {
LOGGER.debug("Skipping workflow processing because the channel is '" + SchemaConstants.CHANNEL_INIT_URI + "'.");
result.recordSuccess();
return HookOperationMode.FOREGROUND;
}
logOperationInformation(context);
HookOperationMode retval = processModelInvocation(context, wfConfigurationType, task, result);
result.computeStatus();
if (retval == HookOperationMode.FOREGROUND) {
result.setMinor();
}
return retval;
} catch (RuntimeException e) {
result.recordFatalError("Couldn't process model invocation in workflow module: " + e.getMessage(), e);
throw e;
}
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.PartialProcessingTypeType.SKIP in project midpoint by Evolveum.
the class ReconciliationProcessor method reconcileProjectionAttribute.
private <T> void reconcileProjectionAttribute(QName attrName, LensProjectionContext projCtx, Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<?>, PrismPropertyDefinition<?>>>> squeezedAttributes, PrismContainer attributesContainer) throws SchemaException {
LOGGER.trace("Attribute reconciliation processing attribute {}", attrName);
// noinspection unchecked
ResourceAttributeDefinition<T> attributeDefinition = (ResourceAttributeDefinition<T>) projCtx.findAttributeDefinition(attrName);
if (attributeDefinition == null) {
throw new SchemaException("No definition for attribute " + attrName + " in " + projCtx.getResourceShadowDiscriminator());
}
DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<T>, PrismPropertyDefinition<T>>> pvwoTriple = squeezedAttributes != null ? (DeltaSetTriple) squeezedAttributes.get(attrName) : null;
if (attributeDefinition.isIgnored(LayerType.MODEL)) {
LOGGER.trace("Skipping reconciliation of attribute {} because it is ignored", attrName);
return;
}
PropertyLimitations limitations = attributeDefinition.getLimitations(LayerType.MODEL);
if (limitations != null) {
PropertyAccessType access = limitations.getAccess();
if (access != null) {
if (projCtx.isAdd() && (access.isAdd() == null || !access.isAdd())) {
LOGGER.trace("Skipping reconciliation of attribute {} because it is non-createable", attrName);
return;
}
if (projCtx.isModify() && (access.isModify() == null || !access.isModify())) {
LOGGER.trace("Skipping reconciliation of attribute {} because it is non-updateable", attrName);
return;
}
}
}
Collection<ItemValueWithOrigin<PrismPropertyValue<T>, PrismPropertyDefinition<T>>> shouldBePValues;
if (pvwoTriple == null) {
shouldBePValues = new HashSet<>();
} else {
shouldBePValues = new HashSet<>(selectValidValues(pvwoTriple.getNonNegativeValues()));
}
// We consider values explicitly requested by user to be among "should be values".
addPropValuesFromDelta(shouldBePValues, projCtx.getPrimaryDelta(), attrName);
// But we DO NOT take values from sync delta (because they just reflect what's on the resource),
// nor from secondary delta (because these got there from mappings).
boolean hasStrongShouldBePValue = false;
boolean hasOtherNonWeakValues = false;
for (ItemValueWithOrigin<? extends PrismPropertyValue<T>, PrismPropertyDefinition<T>> shouldBePValue : shouldBePValues) {
if (shouldBePValue.getMapping() != null) {
if (shouldBePValue.getMapping().getStrength() == MappingStrengthType.STRONG) {
hasStrongShouldBePValue = true;
hasOtherNonWeakValues = true;
break;
}
if (shouldBePValue.getMapping().getStrength() == null || shouldBePValue.getMapping().getStrength() == MappingStrengthType.NORMAL) {
hasOtherNonWeakValues = true;
}
}
}
// noinspection unchecked
PrismProperty<T> attribute = attributesContainer.findProperty(ItemName.fromQName(attrName));
Collection<PrismPropertyValue<T>> arePValues;
if (attribute != null) {
arePValues = attribute.getValues();
} else {
arePValues = new HashSet<>();
}
// Too loud :-)
// if (LOGGER.isTraceEnabled()) {
// StringBuilder sb = new StringBuilder();
// sb.append("Reconciliation\nATTR: ").append(PrettyPrinter.prettyPrint(attrName));
// sb.append("\n Should be:");
// for (ItemValueWithOrigin<?,?> shouldBePValue : shouldBePValues) {
// sb.append("\n ");
// sb.append(shouldBePValue.getItemValue());
// PrismValueDeltaSetTripleProducer<?, ?> shouldBeMapping = shouldBePValue.getMapping();
// if (shouldBeMapping.getStrength() == MappingStrengthType.STRONG) {
// sb.append(" STRONG");
// }
// if (shouldBeMapping.getStrength() == MappingStrengthType.WEAK) {
// sb.append(" WEAK");
// }
// if (!shouldBePValue.isValid()) {
// sb.append(" INVALID");
// }
// }
// sb.append("\n Is:");
// for (PrismPropertyValue<Object> isPVal : arePValues) {
// sb.append("\n ");
// sb.append(isPVal);
// }
// LOGGER.trace("{}", sb.toString());
// }
ValueMatcher<T> valueMatcher = ValueMatcher.createMatcher(attributeDefinition, matchingRuleRegistry);
T realValueToReplace = null;
boolean hasRealValueToReplace = false;
for (ItemValueWithOrigin<? extends PrismPropertyValue<T>, PrismPropertyDefinition<T>> shouldBePvwo : shouldBePValues) {
PrismPropertyValue<T> shouldBePrismValue = shouldBePvwo.getItemValue();
// probably too careful (the value should not be null, shouldn't it?)
T shouldBeRealValue = shouldBePrismValue != null ? shouldBePrismValue.getValue() : null;
PrismValueDeltaSetTripleProducer<?, ?> shouldBeMapping = shouldBePvwo.getMapping();
if (shouldBeMapping == null) {
LOGGER.trace("Skipping reconciliation of value {} of the attribute {}: no origin mapping", shouldBeRealValue, attributeDefinition.getItemName().getLocalPart());
continue;
}
if (shouldBeMapping.getStrength() != MappingStrengthType.STRONG && (!arePValues.isEmpty() || hasStrongShouldBePValue)) {
// Weak or normal value and the attribute already has a value. Skip it.
// We cannot override it as it might have been legally changed directly on the projection resource object
LOGGER.trace("Skipping reconciliation of value {} of the attribute {}: the mapping is not strong", shouldBeRealValue, attributeDefinition.getItemName().getLocalPart());
continue;
}
if (!isInValues(valueMatcher, shouldBeRealValue, arePValues)) {
if (attributeDefinition.isSingleValue()) {
// TODO generalize this a bit (e.g. also for multivalued items)
if (hasRealValueToReplace) {
if (matchValue(shouldBeRealValue, realValueToReplace, valueMatcher)) {
LOGGER.trace("Value to replace for {} is already set, skipping it: {}", attrName, realValueToReplace);
continue;
} else {
String message = "Attempt to set more than one value for single-valued attribute " + attrName + " in " + projCtx.getResourceShadowDiscriminator();
LOGGER.debug("{}: value to be added: {}, existing value to replace: {}", message, shouldBeMapping, realValueToReplace);
throw new SchemaException(message);
}
}
hasRealValueToReplace = true;
realValueToReplace = shouldBeRealValue;
recordDelta(valueMatcher, projCtx, SchemaConstants.PATH_ATTRIBUTES, attributeDefinition, ModificationType.REPLACE, shouldBeRealValue, shouldBePvwo.getSource(), "it is given by a mapping");
} else {
recordDelta(valueMatcher, projCtx, SchemaConstants.PATH_ATTRIBUTES, attributeDefinition, ModificationType.ADD, shouldBeRealValue, shouldBePvwo.getSource(), "it is given by a mapping");
}
} else {
LOGGER.trace("Value is already present in {}, skipping it: {}", attrName, shouldBeRealValue);
}
}
decideIfTolerate(projCtx, attributeDefinition, arePValues, shouldBePValues, valueMatcher, hasOtherNonWeakValues);
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.PartialProcessingTypeType.SKIP in project midpoint by Evolveum.
the class OrgStructFunctionsImpl method getParentOrgs.
@Override
public Collection<OrgType> getParentOrgs(ObjectType object, QName relation, @NotNull Predicate<OrgType> predicate, boolean preAuthorized) throws SchemaException, SecurityViolationException {
List<ObjectReferenceType> parentOrgRefs = object.getParentOrgRef();
List<OrgType> parentOrgs = new ArrayList<>(parentOrgRefs.size());
for (ObjectReferenceType parentOrgRef : parentOrgRefs) {
if (!prismContext.relationMatches(relation, parentOrgRef.getRelation())) {
continue;
}
OrgType parentOrg;
try {
parentOrg = getObject(OrgType.class, parentOrgRef.getOid(), preAuthorized);
} catch (ObjectNotFoundException e) {
LOGGER.warn("Org " + parentOrgRef.getOid() + " specified in parentOrgRef in " + object + " was not found: " + e.getMessage(), e);
// but do not rethrow, just skip this
continue;
} catch (CommunicationException | ConfigurationException | ExpressionEvaluationException e) {
// This should not happen.
throw new SystemException(e.getMessage(), e);
}
if (predicate.test(parentOrg)) {
parentOrgs.add(parentOrg);
}
}
return parentOrgs;
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.PartialProcessingTypeType.SKIP in project midpoint by Evolveum.
the class SqaleAuditService method iterativeSearchCondition.
/**
* Similar to {@link SqaleRepositoryService#lastOidCondition}.
*
* TODO, lots of possible improvements:
*
* * Just like in repo iterative search this is added to the original filter with `AND`.
* However, if `timestamp` is used in the original filter, it could be replaced by stricter
* `timestamp` condition based on the `lastProcessedObject` - this is not implemented yet.
* ** TODO: If provided, do we want to add another timestamp condition?
* Would it help with partitions?
* Probably, with ID condition + ordering, it's not a big deal to leave it out.
*
* * Support for multiple order specifications from the client is not supported.
* Perhaps some short-term stateful filter/order object would be better to construct this,
* especially if it could be used in both repo and audit (with strict order attribute
* provided in constructor for example).
*
* [NOTE]
* ====
* Both `timestamp` and `repoId` is used for iterative search condition, but *only `repoId`*
* is used for additional ordering to assure strict reliable ordering.
* This can be further complicated by the fact that both `repoId` and `timestamp`
* can be part of custom ordering from client (this is different from repository, where `oid`
* is not valid for filter and ordering on the model level, even when it's usable for repository).
* If used on the top-level `AND` group, they can be be replaced by next iteration condition,
* which is likely more selective.
*
* As for the ordering, if multiple ordering is used (*not supported yet*) if `repoId` is used,
* anything after it can be omitted as irrelevant.
* ====
*
* TODO: Currently, single path ordering is supported. Finish multi-path too.
* TODO: What about nullable columns?
*/
@Nullable
private ObjectFilter iterativeSearchCondition(@Nullable AuditEventRecordType lastProcessedObject, List<? extends ObjectOrdering> providedOrdering) {
if (lastProcessedObject == null) {
return null;
}
// TODO inspect originalFilter to detect timestamp/repoId conditions.
// Only top level AND filter should be checked, anything else is irrelevant
// for the decision whether to skip additional timestamp condition.
// BTW: We CANNOT skip repoId condition, that one is CRITICAL for proper iterating.
Long lastProcessedId = lastProcessedObject.getRepoId();
XMLGregorianCalendar lastProcessedTimestamp = lastProcessedObject.getTimestamp();
if (providedOrdering == null || providedOrdering.isEmpty()) {
return prismContext().queryFor(AuditEventRecordType.class).item(AuditEventRecordType.F_REPO_ID).gt(lastProcessedId).and().item(AuditEventRecordType.F_TIMESTAMP).ge(lastProcessedTimestamp).buildFilter();
}
if (providedOrdering.size() == 1) {
ObjectOrdering objectOrdering = providedOrdering.get(0);
ItemPath orderByPath = objectOrdering.getOrderBy();
boolean asc = objectOrdering.getDirection() == OrderDirection.ASCENDING;
S_ConditionEntry filter = prismContext().queryFor(AuditEventRecordType.class).item(orderByPath);
@SuppressWarnings("unchecked") Item<PrismValue, ItemDefinition<?>> item = lastProcessedObject.asPrismContainerValue().findItem(orderByPath);
if (item.size() > 1) {
throw new IllegalArgumentException("Multi-value property for ordering is forbidden - item: " + item);
} else if (item.isEmpty()) {
// TODO what if it's nullable? is it null-first or last?
// See: https://www.postgresql.org/docs/13/queries-order.html
// "By default, null values sort as if larger than any non-null value; that is,
// NULLS FIRST is the default for DESC order, and NULLS LAST otherwise."
} else {
S_MatchingRuleEntry matchingRuleEntry = asc ? filter.gt(item.getRealValue()) : filter.lt(item.getRealValue());
filter = matchingRuleEntry.or().block().item(orderByPath).eq(item.getRealValue()).and().item(AuditEventRecordType.F_REPO_ID);
return (asc ? filter.gt(lastProcessedId) : filter.lt(lastProcessedId)).endBlock().buildFilter();
}
}
throw new IllegalArgumentException("Shouldn't get here with check in executeSearchObjectsIterative()");
}
Aggregations