Skip to content

Commit

Permalink
Extended conntests and some provisioning fixes (secondary identifiers…
Browse files Browse the repository at this point in the history
… and rename, MID-2926)
  • Loading branch information
semancik committed Oct 6, 2016
1 parent 86ba69e commit 2efd55e
Show file tree
Hide file tree
Showing 18 changed files with 2,643 additions and 114 deletions.
Expand Up @@ -77,6 +77,9 @@ public ObjectClassComplexTypeDefinition getObjectClassDefinition() {

public static ResourceObjectIdentification create(ObjectClassComplexTypeDefinition objectClassDefinition,
Collection<? extends ResourceAttribute<?>> allIdentifiers) throws SchemaException {
if (allIdentifiers == null) {
throw new IllegalArgumentException("Cannot create ResourceObjectIdentification with null identifiers");
}
Collection<? extends ResourceAttribute<?>> primaryIdentifiers = null;
Collection<? extends ResourceAttribute<?>> secondaryIdentifiers = null;
for (ResourceAttribute<?> identifier: allIdentifiers) {
Expand Down Expand Up @@ -118,11 +121,15 @@ public static ResourceObjectIdentification createFromAttributes(ObjectClassCompl
}

public void validatePrimaryIdenfiers() {
if (primaryIdentifiers == null || primaryIdentifiers.isEmpty()) {
if (!hasPrimaryIdentifiers()) {
throw new IllegalStateException("No primary identifiers in " + this);
}
}

public boolean hasPrimaryIdentifiers() {
return primaryIdentifiers != null && !primaryIdentifiers.isEmpty();
}

@Override
public int hashCode() {
final int prime = 31;
Expand Down
Expand Up @@ -199,8 +199,8 @@ private <S extends ShadowType,T> void postProcessEntitlementSubjectToEntitlement
ResourceAttributeContainer identifiersContainer = new ResourceAttributeContainer(
ShadowAssociationType.F_IDENTIFIERS, entitlementDef.toResourceAttributeContainerDefinition(), prismContext);
associationCVal.add(identifiersContainer);
LOGGER.trace("Assocciation attribute value resolved to valueAtrribute {} and identifiers container {}", valueAttribute, identifiersContainer);
identifiersContainer.add(valueAttribute);
LOGGER.trace("Assocciation attribute value resolved to valueAtrribute {} and identifiers container {}", valueAttribute, identifiersContainer);
}
}

Expand Down Expand Up @@ -660,9 +660,9 @@ private <TV,TA> PrismObject<ShadowType> collectEntitlementAsObjectOperation(Prov

ResourceAttributeContainer identifiersContainer =
ShadowUtil.getAttributesContainer(associationCVal, ShadowAssociationType.F_IDENTIFIERS);
Collection<ResourceAttribute<?>> entitlementIdentifiers = identifiersContainer.getAttributes();
Collection<ResourceAttribute<?>> entitlementIdentifiersFromAssociation = identifiersContainer.getAttributes();

ResourceObjectDiscriminator disc = new ResourceObjectDiscriminator(entitlementOcDef.getTypeName(), entitlementIdentifiers);
ResourceObjectDiscriminator disc = new ResourceObjectDiscriminator(entitlementOcDef.getTypeName(), entitlementIdentifiersFromAssociation);
ResourceObjectOperations operations = roMap.get(disc);
if (operations == null) {
operations = new ResourceObjectOperations();
Expand Down Expand Up @@ -741,8 +741,8 @@ private <TV,TA> PrismObject<ShadowType> collectEntitlementAsObjectOperation(Prov
if (ResourceTypeUtil.isAvoidDuplicateValues(resource)) {
PrismObject<ShadowType> currentObjectShadow = operations.getCurrentShadow();
if (currentObjectShadow == null) {
LOGGER.trace("Fetching entitlement shadow {} to avoid value duplication (intent={})", entitlementIdentifiers, entitlementIntent);
currentObjectShadow = resourceObjectReferenceResolver.fetchResourceObject(entitlementCtx, entitlementIdentifiers, null, result);
LOGGER.trace("Fetching entitlement shadow {} to avoid value duplication (intent={})", entitlementIdentifiersFromAssociation, entitlementIntent);
currentObjectShadow = resourceObjectReferenceResolver.fetchResourceObject(entitlementCtx, entitlementIdentifiersFromAssociation, null, result);
operations.setCurrentShadow(currentObjectShadow);
}
// TODO it seems that duplicate values are checked twice: once here and the second time in ResourceObjectConverter.executeModify
Expand Down
Expand Up @@ -922,9 +922,14 @@ private PrismObject<ShadowType> executeEntitlementChangesModify(ProvisioningCont

Map<ResourceObjectDiscriminator, ResourceObjectOperations> roMap = new HashMap<>();

if (LOGGER.isTraceEnabled()) {
LOGGER.trace("executeEntitlementChangesModify, old shadow:\n{}", subjectShadowBefore.debugDump(1));
}

for (ItemDelta subjectDelta : subjectDeltas) {
ItemPath subjectItemPath = subjectDelta.getPath();

if (new ItemPath(ShadowType.F_ASSOCIATION).equivalent(subjectDelta.getPath())) {
if (new ItemPath(ShadowType.F_ASSOCIATION).equivalent(subjectItemPath)) {
ContainerDelta<ShadowAssociationType> containerDelta = (ContainerDelta<ShadowAssociationType>)subjectDelta;
subjectShadowAfter = entitlementConverter.collectEntitlementsAsObjectOperation(ctx, roMap, containerDelta,
subjectShadowBefore, subjectShadowAfter, parentResult);
Expand All @@ -934,9 +939,12 @@ private PrismObject<ShadowType> executeEntitlementChangesModify(ProvisioningCont
ContainerDelta<ShadowAssociationType> associationDelta = ContainerDelta.createDelta(ShadowType.F_ASSOCIATION, subjectShadowBefore.getDefinition());
PrismContainer<ShadowAssociationType> associationContainer = subjectShadowBefore.findContainer(ShadowType.F_ASSOCIATION);
if (associationContainer == null || associationContainer.isEmpty()){
LOGGER.trace("No shadow association container in old shadow. Skipping processing entitlements change.");
LOGGER.trace("No shadow association container in old shadow. Skipping processing entitlements change for {}.", subjectItemPath);
continue;
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Processing association container in old shadow for {}:\n{}", subjectItemPath, associationContainer.debugDump(1));
}

// Delete + re-add association values that should ensure correct functioning in case of rename
// This has to be done only for associations that require explicit referential integrity.
Expand All @@ -954,13 +962,16 @@ private PrismObject<ShadowType> executeEntitlementChangesModify(ProvisioningCont
continue;
}
QName valueAttributeName = associationDefinition.getResourceObjectAssociationType().getValueAttribute();
if (!ShadowUtil.matchesAttribute(subjectDelta.getPath(), valueAttributeName)) {
if (!ShadowUtil.matchesAttribute(subjectItemPath, valueAttributeName)) {
continue;
}
LOGGER.trace("Processing association {} on rename", associationName);
associationDelta.addValuesToDelete(associationValue.clone());
associationDelta.addValuesToAdd(associationValue.clone());
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Resulting association delta for {}:\n{}", subjectItemPath, associationDelta.debugDump(1));
}
if (!associationDelta.isEmpty()) {
entitlementConverter.collectEntitlementsAsObjectOperation(ctx, roMap, associationDelta, subjectShadowBefore, subjectShadowAfter, parentResult);
}
Expand Down
Expand Up @@ -179,6 +179,45 @@ Collection<? extends ResourceAttribute<?>> resolvePrimaryIdentifier(Provisioning
return primaryIdentifiers;
}

/**
* Resolve primary identifier from a collection of identifiers that may contain only secondary identifiers.
*/
private ResourceObjectIdentification resolvePrimaryIdentifiers(ProvisioningContext ctx,
ResourceObjectIdentification identification, OperationResult result)
throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException,
SecurityViolationException {
if (identification == null) {
return identification;
}
if (identification.hasPrimaryIdentifiers()) {
return identification;
}
Collection<ResourceAttribute<?>> secondaryIdentifiers = (Collection<ResourceAttribute<?>>) identification.getSecondaryIdentifiers();
PrismObject<ShadowType> repoShadow = shadowManager.lookupShadowBySecondaryIdentifiers(ctx, secondaryIdentifiers, result);
if (repoShadow == null) {
// TODO: we should attempt resource search here
throw new ObjectNotFoundException("No repository shadow for "+secondaryIdentifiers+", cannot resolve identifiers");
}
PrismContainer<Containerable> attributesContainer = repoShadow.findContainer(ShadowType.F_ATTRIBUTES);
if (attributesContainer == null) {
throw new SchemaException("No attributes in "+repoShadow+", cannot resolve identifiers "+secondaryIdentifiers);
}
RefinedObjectClassDefinition ocDef = ctx.getObjectClassDefinition();
Collection primaryIdentifiers = new ArrayList<>();
for (PrismProperty<?> property: attributesContainer.getValue().getProperties()) {
if (ocDef.isPrimaryIdentifier(property.getElementName())) {
RefinedAttributeDefinition<?> attrDef = ocDef.findAttributeDefinition(property.getElementName());
ResourceAttribute<?> primaryIdentifier = new ResourceAttribute<>(property.getElementName(),
attrDef, prismContext);
primaryIdentifier.setRealValue(property.getRealValue());
primaryIdentifiers.add(primaryIdentifier);
}
}
LOGGER.trace("Resolved {} to primary identifiers {} (object class {})", identification, primaryIdentifiers, ocDef);
return new ResourceObjectIdentification(identification.getObjectClassDefinition(), primaryIdentifiers,
identification.getSecondaryIdentifiers());
}


public PrismObject<ShadowType> fetchResourceObject(ProvisioningContext ctx,
Collection<? extends ResourceAttribute<?>> identifiers,
Expand All @@ -196,6 +235,7 @@ public PrismObject<ShadowType> fetchResourceObject(ProvisioningContext ctx,
}

ResourceObjectIdentification identification = ResourceObjectIdentification.create(objectClassDefinition, identifiers);
identification = resolvePrimaryIdentifiers(ctx, identification, parentResult);
identification.validatePrimaryIdenfiers();
return connector.fetchObject(ShadowType.class, identification, attributesToReturn, ctx,
parentResult);
Expand Down

0 comments on commit 2efd55e

Please sign in to comment.