use of com.evolveum.midpoint.prism.PrismReference in project midpoint by Evolveum.
the class ModelObjectResolver method searchOrgTreeWidthFirst.
public <R, O extends ObjectType> R searchOrgTreeWidthFirst(PrismObject<O> object, Function<PrismObject<OrgType>, R> function, Task task, OperationResult result) {
PrismReference orgRef = object.findReference(ObjectType.F_PARENT_ORG_REF);
if (orgRef == null) {
return null;
}
List<PrismReferenceValue> orgRefValues = orgRef.getValues();
List<PrismObject<OrgType>> orgs = new ArrayList<PrismObject<OrgType>>();
for (PrismReferenceValue orgRefValue : orgRefValues) {
if (orgRefValue != null) {
try {
PrismObject<OrgType> org = resolve(orgRefValue, "resolving parent org ref", null, null, result);
orgs.add(org);
R val = function.apply(org);
if (val != null) {
return val;
}
} catch (ObjectNotFoundException ex) {
// Just log the error, but do not fail on that. Failing would prohibit login
// and that may mean the misconfiguration could not be easily fixed.
LOGGER.warn("Cannot find organization {} referenced in {}", orgRefValue.getOid(), object);
}
}
}
// go deeper
for (PrismObject<OrgType> orgType : orgs) {
R val = searchOrgTreeWidthFirst((PrismObject<O>) orgType, function, task, result);
if (val != null) {
return val;
}
}
return null;
}
use of com.evolveum.midpoint.prism.PrismReference in project midpoint by Evolveum.
the class ModelObjectResolver method searchOrgTreeWidthFirstReference.
public <O extends ObjectType, R extends ObjectType> PrismObject<R> searchOrgTreeWidthFirstReference(PrismObject<O> object, Function<PrismObject<OrgType>, ObjectReferenceType> function, String shortDesc, Task task, OperationResult result) throws SchemaException {
if (object == null) {
LOGGER.trace("No object provided. Cannost find security policy specific for an object.");
return null;
}
PrismReference orgRef = object.findReference(ObjectType.F_PARENT_ORG_REF);
if (orgRef == null) {
return null;
}
List<PrismReferenceValue> orgRefValues = orgRef.getValues();
List<PrismObject<OrgType>> orgs = new ArrayList<PrismObject<OrgType>>();
PrismObject<R> resultObject = null;
for (PrismReferenceValue orgRefValue : orgRefValues) {
if (orgRefValue != null) {
try {
PrismObject<OrgType> org = resolve(orgRefValue, "resolving parent org ref", null, null, result);
orgs.add(org);
ObjectReferenceType ref = function.apply(org);
if (ref != null) {
PrismObject<R> resolvedObject;
try {
resolvedObject = resolve(ref.asReferenceValue(), shortDesc, task, result);
} catch (ObjectNotFoundException ex) {
// Just log the error, but do not fail on that. Failing would prohibit login
// and that may mean the misconfiguration could not be easily fixed.
LOGGER.warn("Cannot find object {} referenced in {} while resolving {}", orgRefValue.getOid(), object, shortDesc);
continue;
}
if (resolvedObject != null) {
if (resultObject == null) {
resultObject = resolvedObject;
} else if (!StringUtils.equals(resolvedObject.getOid(), resultObject.getOid())) {
throw new SchemaException("Found more than one object (" + resolvedObject + ", " + resultObject + ") while " + shortDesc);
}
}
}
} catch (ObjectNotFoundException ex) {
// Just log the error, but do not fail on that. Failing would prohibit login
// and that may mean the misconfiguration could not be easily fixed.
LOGGER.warn("Cannot find organization {} referenced in {}", orgRefValue.getOid(), object);
}
}
}
if (resultObject != null) {
return resultObject;
}
// go deeper
for (PrismObject<OrgType> org : orgs) {
PrismObject<R> val = searchOrgTreeWidthFirstReference((PrismObject<O>) org, function, shortDesc, task, result);
if (val != null) {
return val;
}
}
return null;
}
use of com.evolveum.midpoint.prism.PrismReference in project midpoint by Evolveum.
the class ConsolidationProcessor method consolidateAssociation.
private <V extends PrismValue> ContainerDelta<ShadowAssociationType> consolidateAssociation(RefinedObjectClassDefinition rOcDef, ResourceShadowDiscriminator discr, ObjectDelta<ShadowType> existingDelta, LensProjectionContext projCtx, boolean addUnchangedValues, boolean completeShadow, QName associationName, DeltaSetTriple<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>> triple) throws SchemaException, ExpressionEvaluationException, PolicyViolationException {
ItemPath itemPath = new ItemPath(ShadowType.F_ASSOCIATION);
PrismContainerDefinition<ShadowAssociationType> asspcContainerDef = getAssociationDefinition();
RefinedAssociationDefinition associationDef = rOcDef.findAssociationDefinition(associationName);
Comparator<PrismContainerValue<ShadowAssociationType>> comparator = new Comparator<PrismContainerValue<ShadowAssociationType>>() {
@Override
public int compare(PrismContainerValue<ShadowAssociationType> o1, PrismContainerValue<ShadowAssociationType> o2) {
if (o1 == null && o2 == null) {
LOGGER.trace("Comparing {} and {}: 0 (A)", o1, o2);
return 0;
}
if (o1 == null || o2 == null) {
LOGGER.trace("Comparing {} and {}: 2 (B)", o1, o2);
return 1;
}
PrismReference ref1 = o1.findReference(ShadowAssociationType.F_SHADOW_REF);
PrismReference ref2 = o2.findReference(ShadowAssociationType.F_SHADOW_REF);
// We do not want to compare references in details. Comparing OIDs suffices.
// Otherwise we get into problems, as one of the references might be e.g. without type,
// causing unpredictable behavior (MID-2368)
String oid1 = ref1 != null ? ref1.getOid() : null;
String oid2 = ref2 != null ? ref2.getOid() : null;
if (ObjectUtils.equals(oid1, oid2)) {
LOGGER.trace("Comparing {} and {}: 0 (C)", o1, o2);
return 0;
}
LOGGER.trace("Comparing {} and {}: 1 (D)", o1, o2);
return 1;
}
};
ContainerDelta<ShadowAssociationType> delta = (ContainerDelta<ShadowAssociationType>) consolidateItem(rOcDef, discr, existingDelta, projCtx, addUnchangedValues, completeShadow, associationDef.isExclusiveStrong(), itemPath, asspcContainerDef, triple, null, comparator, "association " + associationName);
if (delta != null) {
setAssociationName(delta.getValuesToAdd(), associationName);
setAssociationName(delta.getValuesToDelete(), associationName);
setAssociationName(delta.getValuesToReplace(), associationName);
}
return delta;
}
use of com.evolveum.midpoint.prism.PrismReference in project midpoint by Evolveum.
the class ContextLoader method loadLinkRefsFromFocus.
/**
* Does not overwrite existing account contexts, just adds new ones.
*/
private <F extends FocusType> void loadLinkRefsFromFocus(LensContext<F> context, PrismObject<F> focus, Task task, OperationResult result) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, PolicyViolationException, ExpressionEvaluationException {
PrismReference linkRef = focus.findReference(FocusType.F_LINK_REF);
if (linkRef == null) {
return;
}
for (PrismReferenceValue linkRefVal : linkRef.getValues()) {
String oid = linkRefVal.getOid();
if (StringUtils.isBlank(oid)) {
LOGGER.trace("Null or empty OID in link reference {} in:\n{}", linkRef, focus.debugDump(1));
throw new SchemaException("Null or empty OID in link reference in " + focus);
}
LensProjectionContext existingAccountContext = findAccountContext(oid, context);
if (!canBeLoaded(context, existingAccountContext)) {
continue;
}
if (existingAccountContext != null) {
// TODO: do we need to reload the account inside here? yes we need
existingAccountContext.setFresh(true);
continue;
}
PrismObject<ShadowType> shadow = linkRefVal.getObject();
if (shadow == null) {
// Using NO_FETCH so we avoid reading in a full account. This is more efficient as we don't need full account here.
// We need to fetch from provisioning and not repository so the correct definition will be set.
GetOperationOptions rootOpts = GetOperationOptions.createNoFetch();
rootOpts.setPointInTimeType(PointInTimeType.FUTURE);
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(rootOpts);
LOGGER.trace("Loading shadow {} from linkRef, options={}", oid, options);
try {
shadow = provisioningService.getObject(ShadowType.class, oid, options, task, result);
} catch (ObjectNotFoundException e) {
// Broken accountRef. We need to mark it for deletion
LensProjectionContext accountContext = getOrCreateEmptyThombstoneProjectionContext(context, oid);
accountContext.setFresh(true);
accountContext.setExists(false);
OperationResult getObjectSubresult = result.getLastSubresult();
getObjectSubresult.setErrorsHandled();
continue;
}
} else {
// Make sure it has a proper definition. This may come from outside of the model.
provisioningService.applyDefinition(shadow, task, result);
}
LensProjectionContext accountContext = getOrCreateAccountContext(context, shadow, task, result);
accountContext.setFresh(true);
accountContext.setExists(shadow != null);
if (context.isDoReconciliationForAllProjections()) {
accountContext.setDoReconciliation(true);
}
if (accountContext.isDoReconciliation()) {
// reconciliation step.
continue;
}
accountContext.setLoadedObject(shadow);
}
}
use of com.evolveum.midpoint.prism.PrismReference in project midpoint by Evolveum.
the class ContextLoader method loadLinkRefsFromDelta.
private <F extends FocusType> void loadLinkRefsFromDelta(LensContext<F> context, PrismObject<F> focus, ObjectDelta<F> focusPrimaryDelta, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, PolicyViolationException, ExpressionEvaluationException {
if (focusPrimaryDelta == null) {
return;
}
ReferenceDelta linkRefDelta;
if (focusPrimaryDelta.getChangeType() == ChangeType.ADD) {
PrismReference linkRef = focusPrimaryDelta.getObjectToAdd().findReference(FocusType.F_LINK_REF);
if (linkRef == null) {
// Adding new focus with no linkRef -> nothing to do
return;
}
linkRefDelta = linkRef.createDelta(new ItemPath(FocusType.F_LINK_REF));
linkRefDelta.addValuesToAdd(PrismValue.cloneValues(linkRef.getValues()));
} else if (focusPrimaryDelta.getChangeType() == ChangeType.MODIFY) {
linkRefDelta = focusPrimaryDelta.findReferenceModification(FocusType.F_LINK_REF);
if (linkRefDelta == null) {
return;
}
} else {
// delete, all existing account are already marked for delete
return;
}
if (linkRefDelta.isReplace()) {
// process "replace" by distributing values to delete and add
linkRefDelta = (ReferenceDelta) linkRefDelta.clone();
PrismReference linkRef = focus.findReference(FocusType.F_LINK_REF);
linkRefDelta.distributeReplace(linkRef == null ? null : linkRef.getValues());
}
if (linkRefDelta.getValuesToAdd() != null) {
for (PrismReferenceValue refVal : linkRefDelta.getValuesToAdd()) {
String oid = refVal.getOid();
LensProjectionContext accountContext = null;
PrismObject<ShadowType> shadow = null;
boolean isCombinedAdd = false;
if (oid == null) {
// Adding new account
shadow = refVal.getObject();
if (shadow == null) {
throw new SchemaException("Null or empty OID in account reference " + refVal + " in " + focus);
}
provisioningService.applyDefinition(shadow, task, result);
if (consistencyChecks)
ShadowUtil.checkConsistence(shadow, "account from " + linkRefDelta);
// Check for conflicting change
accountContext = LensUtil.getProjectionContext(context, shadow, provisioningService, prismContext, task, result);
if (accountContext != null) {
// There is already existing context for the same discriminator. Tolerate this only if
// the deltas match. It is an error otherwise.
ObjectDelta<ShadowType> primaryDelta = accountContext.getPrimaryDelta();
if (primaryDelta == null) {
throw new SchemaException("Attempt to add " + shadow + " to a user that already contains " + accountContext.getHumanReadableKind() + " of type '" + accountContext.getResourceShadowDiscriminator().getIntent() + "' on " + accountContext.getResource());
}
if (!primaryDelta.isAdd()) {
throw new SchemaException("Conflicting changes in the context. " + "Add of accountRef in the user delta with embedded object conflicts with explicit delta " + primaryDelta);
}
if (!shadow.equals(primaryDelta.getObjectToAdd())) {
throw new SchemaException("Conflicting changes in the context. " + "Add of accountRef in the user delta with embedded object is not adding the same object as explicit delta " + primaryDelta);
}
} else {
// Create account context from embedded object
accountContext = createProjectionContext(context, shadow, task, result);
}
// This is a new account that is to be added. So it should
// go to account primary delta
ObjectDelta<ShadowType> accountPrimaryDelta = shadow.createAddDelta();
accountContext.setPrimaryDelta(accountPrimaryDelta);
accountContext.setFullShadow(true);
accountContext.setExists(false);
isCombinedAdd = true;
} else {
// therefore check for account existence to decide
try {
// Using NO_FETCH so we avoid reading in a full account. This is more efficient as we don't need full account here.
// We need to fetch from provisioning and not repository so the correct definition will be set.
GetOperationOptions rootOpts = GetOperationOptions.createNoFetch();
rootOpts.setPointInTimeType(PointInTimeType.FUTURE);
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(rootOpts);
shadow = provisioningService.getObject(ShadowType.class, oid, options, task, result);
// Create account context from retrieved object
accountContext = getOrCreateAccountContext(context, shadow, task, result);
accountContext.setLoadedObject(shadow);
accountContext.setExists(true);
} catch (ObjectNotFoundException e) {
if (refVal.getObject() == null) {
// ref -> this is really an error
throw e;
} else {
// New account (with OID)
result.muteLastSubresultError();
shadow = refVal.getObject();
if (!shadow.hasCompleteDefinition()) {
provisioningService.applyDefinition(shadow, task, result);
}
// Create account context from embedded object
accountContext = createProjectionContext(context, shadow, task, result);
ObjectDelta<ShadowType> accountPrimaryDelta = shadow.createAddDelta();
accountContext.setPrimaryDelta(accountPrimaryDelta);
accountContext.setFullShadow(true);
accountContext.setExists(false);
isCombinedAdd = true;
}
}
}
if (context.isDoReconciliationForAllProjections() && !isCombinedAdd) {
accountContext.setDoReconciliation(true);
}
accountContext.setFresh(true);
}
}
if (linkRefDelta.getValuesToDelete() != null) {
for (PrismReferenceValue refVal : linkRefDelta.getValuesToDelete()) {
String oid = refVal.getOid();
LensProjectionContext accountContext = null;
PrismObject<ShadowType> account = null;
if (oid == null) {
throw new SchemaException("Cannot delete account ref without an oid in " + focus);
} else {
try {
// Using NO_FETCH so we avoid reading in a full account. This is more efficient as we don't need full account here.
// We need to fetch from provisioning and not repository so the correct definition will be set.
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(GetOperationOptions.createNoFetch());
account = provisioningService.getObject(ShadowType.class, oid, options, task, result);
// Create account context from retrieved object
accountContext = getOrCreateAccountContext(context, account, task, result);
accountContext.setLoadedObject(account);
accountContext.setExists(true);
} catch (ObjectNotFoundException e) {
try {
// Broken accountRef. We need to try again with raw options, because the error should be thrown because of non-existent resource
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(GetOperationOptions.createRaw());
account = provisioningService.getObject(ShadowType.class, oid, options, task, result);
accountContext = getOrCreateEmptyThombstoneProjectionContext(context, oid);
accountContext.setFresh(true);
accountContext.setExists(false);
OperationResult getObjectSubresult = result.getLastSubresult();
getObjectSubresult.setErrorsHandled();
} catch (ObjectNotFoundException ex) {
// This is still OK. It means deleting an accountRef
// that points to non-existing object
// just log a warning
LOGGER.warn("Deleting accountRef of " + focus + " that points to non-existing OID " + oid);
}
}
}
if (accountContext != null) {
if (refVal.getObject() == null) {
accountContext.setSynchronizationIntent(SynchronizationIntent.UNLINK);
} else {
accountContext.setSynchronizationIntent(SynchronizationIntent.DELETE);
ObjectDelta<ShadowType> accountPrimaryDelta = account.createDeleteDelta();
accountContext.setPrimaryDelta(accountPrimaryDelta);
}
accountContext.setFresh(true);
}
}
}
if (focusPrimaryDelta.getChangeType() == ChangeType.ADD) {
focusPrimaryDelta.getObjectToAdd().removeReference(FocusType.F_LINK_REF);
} else if (focusPrimaryDelta.getChangeType() == ChangeType.MODIFY) {
focusPrimaryDelta.removeReferenceModification(FocusType.F_LINK_REF);
}
}
Aggregations