Example #1
0
 private <O extends Objectable> MapXNode serializeObjectContent(
     PrismObject<O> object, SerializationContext ctx) throws SchemaException {
   MapXNode xmap = new MapXNode();
   if (object.getOid() != null) {
     xmap.put(XNode.KEY_OID, createPrimitiveXNodeStringAttr(object.getOid()));
   }
   if (object.getVersion() != null) {
     xmap.put(XNode.KEY_VERSION, createPrimitiveXNodeStringAttr(object.getVersion()));
   }
   PrismObjectDefinition<O> objectDefinition = object.getDefinition();
   serializeContainerValue(xmap, object.getValue(), objectDefinition, ctx);
   return xmap;
 }
Example #2
0
 private ObjectQuery getAssociationsSearchQuery(
     PrismContext prismContext,
     PrismObject resource,
     QName objectClass,
     ShadowKindType kind,
     String intent) {
   try {
     ObjectFilter andFilter =
         AndFilter.createAnd(
             EqualFilter.createEqual(
                 ShadowType.F_OBJECT_CLASS, ShadowType.class, prismContext, objectClass),
             EqualFilter.createEqual(ShadowType.F_KIND, ShadowType.class, prismContext, kind),
             //                    EqualFilter.createEqual(ShadowType.F_INTENT, ShadowType.class,
             // prismContext, intent),
             RefFilter.createReferenceEqual(
                 new ItemPath(ShadowType.F_RESOURCE_REF),
                 ShadowType.class,
                 prismContext,
                 resource.getOid()));
     ObjectQuery query = ObjectQuery.createObjectQuery(andFilter);
     return query;
   } catch (SchemaException ex) {
     LoggingUtils.logUnexpectedException(LOGGER, "Unable to create associations search query", ex);
     return null;
   }
 }
  private List<ObjectReferenceType> createResourceList() {
    resourceMap.clear();
    OperationResult result = new OperationResult(OPERATION_LOAD_RESOURCES);
    Task task = getPageBase().createSimpleTask(OPERATION_LOAD_RESOURCES);
    List<PrismObject<ResourceType>> resources = null;
    List<ObjectReferenceType> references = new ArrayList<>();

    try {
      resources =
          getPageBase()
              .getModelService()
              .searchObjects(ResourceType.class, new ObjectQuery(), null, task, result);
      result.recomputeStatus();
    } catch (Exception e) {
      result.recordFatalError("Couldn't get resource list.", e);
      LoggingUtils.logException(LOGGER, "Couldn't get resource list.", e);
    }

    // TODO - show error somehow
    // if(!result.isSuccess()){
    //    getPageBase().showResult(result);
    // }

    if (resources != null) {
      ObjectReferenceType ref;
      for (PrismObject<ResourceType> r : resources) {
        resourceMap.put(r.getOid(), WebMiscUtil.getName(r));
        ref = new ObjectReferenceType();
        ref.setType(ResourceType.COMPLEX_TYPE);
        ref.setOid(r.getOid());
        references.add(ref);
      }
    }

    return references;
  }
  /**
   * Method inserts id for prism container values, which didn't have ids, also returns all container
   * values which has generated id
   *
   * @param object
   * @return
   */
  public IdGeneratorResult generate(PrismObject object, Operation operation) {
    IdGeneratorResult result = new IdGeneratorResult();
    boolean adding = Operation.ADD.equals(operation);
    result.setGeneratedOid(adding);

    if (StringUtils.isEmpty(object.getOid())) {
      String oid = UUID.randomUUID().toString();
      object.setOid(oid);

      result.setGeneratedOid(true);
    }

    generateIdForObject(object, result, operation);

    return result;
  }
  private ObjectViewDto loadResource() {
    if (!isEditing()) {
      return new ObjectViewDto();
    }

    ObjectViewDto dto;
    try {
      PrismObject<ResourceType> resource = loadResource(null);
      String xml = getPrismContext().serializeObjectToString(resource, PrismContext.LANG_XML);

      dto = new ObjectViewDto(resource.getOid(), WebMiscUtil.getName(resource), resource, xml);
    } catch (Exception ex) {
      LoggingUtils.logException(LOGGER, "Couldn't load resource", ex);
      throw new RestartResponseException(PageResources.class);
    }

    return dto;
  }
  /**
   * Method which attempts to resolve connector reference filter to actual connector (if necessary).
   *
   * @param resource {@link PrismObject} resource
   */
  private void updateConnectorRef(
      PrismObject<ResourceType> resource, Task task, OperationResult result)
      throws SchemaException, ObjectNotFoundException, SecurityViolationException,
          CommunicationException, ConfigurationException {
    if (resource == null) {
      return;
    }

    PrismReference resourceRef = resource.findReference(ResourceType.F_CONNECTOR_REF);
    if (resourceRef == null || resourceRef.getValue() == null) {
      return;
    }

    PrismReferenceValue refValue = resourceRef.getValue();
    if (StringUtils.isNotEmpty(refValue.getOid())) {
      return;
    }

    if (refValue.getFilter() == null) {
      return;
    }

    SchemaRegistry registry = getPrismContext().getSchemaRegistry();
    PrismObjectDefinition objDef =
        registry.findObjectDefinitionByCompileTimeClass(ConnectorType.class);
    ObjectFilter filter = QueryConvertor.parseFilter(refValue.getFilter(), objDef);

    List<PrismObject<ConnectorType>> connectors =
        getModelService()
            .searchObjects(
                ConnectorType.class, ObjectQuery.createObjectQuery(filter), null, task, result);
    if (connectors.size() != 1) {
      return;
    }

    PrismObject<ConnectorType> connector = connectors.get(0);
    refValue.setOid(connector.getOid());
    refValue.setTargetType(ConnectorType.COMPLEX_TYPE);

    refValue.setFilter(null);
  }
  @Test
  public void test500ScriptingUsers() throws Exception {
    final String TEST_NAME = "test500ScriptingUsers";
    TestUtil.displayTestTile(this, TEST_NAME);

    // GIVEN
    OperationResult result = new OperationResult(DOT_CLASS + TEST_NAME);
    PrismProperty<ScriptingExpressionType> expression = parseAnyData(SCRIPTING_USERS_FILE);

    // WHEN
    ExecutionContext output =
        scriptingExpressionEvaluator.evaluateExpression(
            expression.getAnyValue().getValue(), result);

    // THEN
    TestUtil.assertSuccess(result);
    Data data = output.getFinalOutput();
    assertEquals("Unexpected # of items in output", 5, data.getData().size());
    Set<String> realOids = new HashSet<>();
    for (PrismValue value : data.getData()) {
      PrismObject<UserType> user = ((PrismObjectValue<UserType>) value).asPrismObject();
      assertEquals("Description not set", "Test", user.asObjectable().getDescription());
      realOids.add(user.getOid());
    }
    assertEquals(
        "Unexpected OIDs in output",
        Sets.newHashSet(
            Arrays.asList(
                USER_ADMINISTRATOR_OID,
                USER_JACK_OID,
                USER_BARBOSSA_OID,
                USER_GUYBRUSH_OID,
                USER_ELAINE_OID)),
        realOids);
    IntegrationTestTools.display("stdout", output.getConsoleOutput());
    IntegrationTestTools.display(result);
    result.computeStatus();
  }
  public List<SecurityQuestionAnswerDTO> createUsersSecurityQuestionsList(
      PrismObject<UserType> user) {
    LOGGER.debug("Security Questions Loading for user: "******"User SecurityQuestion ANswer List is Not null");
        List<SecurityQuestionAnswerDTO> secQuestAnswListDTO =
            new ArrayList<SecurityQuestionAnswerDTO>();
        for (Iterator iterator = secQuestAnsList.iterator(); iterator.hasNext(); ) {
          SecurityQuestionAnswerType securityQuestionAnswerType =
              (SecurityQuestionAnswerType) iterator.next();

          Protector protector = getPrismContext().getDefaultProtector();
          String decoded = "";
          if (securityQuestionAnswerType.getQuestionAnswer().getEncryptedDataType() != null) {
            try {
              decoded = protector.decryptString(securityQuestionAnswerType.getQuestionAnswer());

            } catch (EncryptionException e) {
              LoggingUtils.logException(LOGGER, "Couldn't decrypt user answer", e);
            }
          }
          // LOGGER.debug("SecAnswerIdentifier:"+securityQuestionAnswerType.getQuestionIdentifier());
          secQuestAnswListDTO.add(
              new SecurityQuestionAnswerDTO(
                  securityQuestionAnswerType.getQuestionIdentifier(), decoded));
        }

        return secQuestAnswListDTO;
      }
    }
    return null;
  }
  private void assertTask(PrismObject<TaskType> task) {

    task.checkConsistence();

    assertEquals("Wrong oid", "44444444-4444-4444-4444-000000001111", task.getOid());
    PrismObjectDefinition<TaskType> usedDefinition = task.getDefinition();
    assertNotNull("No task definition", usedDefinition);
    PrismAsserts.assertObjectDefinition(
        usedDefinition,
        new QName(SchemaConstantsGenerated.NS_COMMON, "task"),
        TaskType.COMPLEX_TYPE,
        TaskType.class);
    assertEquals("Wrong class in task", TaskType.class, task.getCompileTimeClass());
    TaskType taskType = task.asObjectable();
    assertNotNull("asObjectable resulted in null", taskType);

    assertPropertyValue(task, "name", PrismTestUtil.createPolyString("Task2"));
    assertPropertyDefinition(task, "name", PolyStringType.COMPLEX_TYPE, 0, 1);

    assertPropertyValue(task, "taskIdentifier", "44444444-4444-4444-4444-000000001111");
    assertPropertyDefinition(task, "taskIdentifier", DOMUtil.XSD_STRING, 0, 1);

    assertPropertyDefinition(
        task, "executionStatus", JAXBUtil.getTypeQName(TaskExecutionStatusType.class), 1, 1);
    PrismProperty<TaskExecutionStatusType> executionStatusProperty =
        task.findProperty(TaskType.F_EXECUTION_STATUS);
    PrismPropertyValue<TaskExecutionStatusType> executionStatusValue =
        executionStatusProperty.getValue();
    TaskExecutionStatusType executionStatus = executionStatusValue.getValue();
    assertEquals("Wrong execution status", TaskExecutionStatusType.RUNNABLE, executionStatus);

    PrismContainer extension = task.getExtension();
    PrismContainerValue extensionValue = extension.getValue();
    assertTrue("Extension parent", extensionValue.getParent() == extension);
    assertNull("Extension ID", extensionValue.getId());
  }
Example #10
0
  /**
   * Retrieves all definitions. Augments them by count of campaigns (all + open ones).
   *
   * <p>TODO query parameters, customizable sorting definitions and campaigns counts are expected to
   * be low, so we can afford to go through all of them here
   */
  public Collection<PrismObject<AccessCertificationDefinitionForReportType>>
      searchCertificationDefinitions()
          throws ConfigurationException, SchemaException, ObjectNotFoundException,
              CommunicationException, SecurityViolationException {

    Task task = taskManager.createTaskInstance();
    OperationResult result = task.getResult();
    Collection<SelectorOptions<GetOperationOptions>> options =
        SelectorOptions.createCollection(GetOperationOptions.createResolveNames());
    List<PrismObject<AccessCertificationDefinitionType>> definitions =
        model.searchObjects(AccessCertificationDefinitionType.class, null, options, task, result);
    final Map<String, PrismObject<AccessCertificationDefinitionForReportType>>
        definitionsForReportMap = new HashMap<>();
    for (PrismObject<AccessCertificationDefinitionType> definition : definitions) {
      // create subclass with the values copied from the superclass
      PrismObject<AccessCertificationDefinitionForReportType> definitionForReport =
          prismContext
              .createObjectable(AccessCertificationDefinitionForReportType.class)
              .asPrismObject();
      for (Item<?, ?> item : definition.getValue().getItems()) {
        definitionForReport.getValue().add(item.clone());
      }
      definitionsForReportMap.put(definition.getOid(), definitionForReport);
    }

    ResultHandler<AccessCertificationCampaignType> handler =
        new ResultHandler<AccessCertificationCampaignType>() {
          @Override
          public boolean handle(
              PrismObject<AccessCertificationCampaignType> campaignObject,
              OperationResult parentResult) {
            AccessCertificationCampaignType campaign = campaignObject.asObjectable();
            if (campaign.getDefinitionRef() != null) {
              String definitionOid = campaign.getDefinitionRef().getOid();
              PrismObject<AccessCertificationDefinitionForReportType> definitionObject =
                  definitionsForReportMap.get(definitionOid);
              if (definitionObject != null) {
                AccessCertificationDefinitionForReportType definition =
                    definitionObject.asObjectable();
                int campaigns = definition.getCampaigns() != null ? definition.getCampaigns() : 0;
                definition.setCampaigns(campaigns + 1);
                AccessCertificationCampaignStateType state = campaign.getState();
                if (state != AccessCertificationCampaignStateType.CREATED && state != CLOSED) {
                  int openCampaigns =
                      definition.getOpenCampaigns() != null ? definition.getOpenCampaigns() : 0;
                  definition.setOpenCampaigns(openCampaigns + 1);
                }
              }
            }
            return true;
          }
        };
    model.searchObjectsIterative(
        AccessCertificationCampaignType.class, null, handler, null, task, result);

    List<PrismObject<AccessCertificationDefinitionForReportType>> rv =
        new ArrayList<>(definitionsForReportMap.values());
    Collections.sort(
        rv,
        new Comparator<PrismObject<AccessCertificationDefinitionForReportType>>() {
          @Override
          public int compare(
              PrismObject<AccessCertificationDefinitionForReportType> o1,
              PrismObject<AccessCertificationDefinitionForReportType> o2) {
            String n1 = o1.asObjectable().getName().getOrig();
            String n2 = o2.asObjectable().getName().getOrig();
            if (n1 == null) {
              n1 = "";
            }
            return n1.compareTo(n2);
          }
        });
    for (PrismObject<AccessCertificationDefinitionForReportType> defObject : rv) {
      AccessCertificationDefinitionForReportType def = defObject.asObjectable();
      if (def.getCampaigns() == null) {
        def.setCampaigns(0);
      }
      if (def.getOpenCampaigns() == null) {
        def.setOpenCampaigns(0);
      }
    }
    return rv;
  }
  private <F extends FocusType> void processFocusFocus(
      LensContext<F> context,
      String activityDescription,
      XMLGregorianCalendar now,
      Task task,
      OperationResult result)
      throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException,
          PolicyViolationException, ObjectAlreadyExistsException, CommunicationException,
          ConfigurationException, SecurityViolationException {

    LensFocusContext<F> focusContext = context.getFocusContext();
    ObjectTemplateType objectTemplate = context.getFocusTemplate();

    boolean resetOnRename = true; // This is fixed now. TODO: make it configurable
    int maxIterations = 0;
    IterationSpecificationType iterationSpecificationType = null;
    if (objectTemplate != null) {
      iterationSpecificationType = objectTemplate.getIteration();
      maxIterations = LensUtil.determineMaxIterations(iterationSpecificationType);
    }
    int iteration = focusContext.getIteration();
    String iterationToken = focusContext.getIterationToken();
    boolean wasResetIterationCounter = false;

    PrismObject<F> focusCurrent = focusContext.getObjectCurrent();
    if (focusCurrent != null && iterationToken == null) {
      Integer focusIteration = focusCurrent.asObjectable().getIteration();
      if (focusIteration != null) {
        iteration = focusIteration;
      }
      iterationToken = focusCurrent.asObjectable().getIterationToken();
    }

    while (true) {

      ObjectTypeTemplateType objectPolicyConfigurationType =
          focusContext.getObjectPolicyConfigurationType();
      if (objectPolicyConfigurationType != null
          && BooleanUtils.isTrue(objectPolicyConfigurationType.isOidNameBoundMode())) {
        // Generate the name now - unless it is already present
        PrismObject<F> focusNew = focusContext.getObjectNew();
        if (focusNew != null) {
          PolyStringType focusNewName = focusNew.asObjectable().getName();
          if (focusNewName == null) {
            String newName = focusNew.getOid();
            if (newName == null) {
              newName = OidUtil.generateOid();
            }
            LOGGER.trace("Generating new name (bound to OID): {}", newName);
            PrismObjectDefinition<F> focusDefinition = focusContext.getObjectDefinition();
            PrismPropertyDefinition<PolyString> focusNameDef =
                focusDefinition.findPropertyDefinition(FocusType.F_NAME);
            PropertyDelta<PolyString> nameDelta =
                focusNameDef.createEmptyDelta(new ItemPath(FocusType.F_NAME));
            nameDelta.setValueToReplace(
                new PrismPropertyValue<PolyString>(
                    new PolyString(newName), OriginType.USER_POLICY, null));
            focusContext.swallowToSecondaryDelta(nameDelta);
            focusContext.recompute();
          }
        }
      }

      ExpressionVariables variables =
          Utils.getDefaultExpressionVariables(
              focusContext.getObjectNew(), null, null, null, context.getSystemConfiguration());
      if (iterationToken == null) {
        iterationToken =
            LensUtil.formatIterationToken(
                context,
                focusContext,
                iterationSpecificationType,
                iteration,
                expressionFactory,
                variables,
                task,
                result);
      }

      // We have to remember the token and iteration in the context.
      // The context can be recomputed several times. But we always want
      // to use the same iterationToken if possible. If there is a random
      // part in the iterationToken expression that we need to avoid recomputing
      // the token otherwise the value can change all the time (even for the same inputs).
      // Storing the token in the secondary delta is not enough because secondary deltas can be
      // dropped
      // if the context is re-projected.
      focusContext.setIteration(iteration);
      focusContext.setIterationToken(iterationToken);
      LOGGER.trace(
          "Focus {} processing, iteration {}, token '{}'",
          new Object[] {focusContext.getHumanReadableName(), iteration, iterationToken});

      String conflictMessage;
      if (!LensUtil.evaluateIterationCondition(
          context,
          focusContext,
          iterationSpecificationType,
          iteration,
          iterationToken,
          true,
          expressionFactory,
          variables,
          task,
          result)) {

        conflictMessage = "pre-iteration condition was false";
        LOGGER.debug(
            "Skipping iteration {}, token '{}' for {} because the pre-iteration condition was false",
            new Object[] {iteration, iterationToken, focusContext.getHumanReadableName()});
      } else {

        // INBOUND

        if (consistencyChecks) context.checkConsistence();
        // Loop through the account changes, apply inbound expressions
        inboundProcessor.processInbound(context, now, task, result);
        if (consistencyChecks) context.checkConsistence();
        context.recomputeFocus();
        LensUtil.traceContext(LOGGER, activityDescription, "inbound", false, context, false);
        if (consistencyChecks) context.checkConsistence();

        // ACTIVATION

        processActivation(context, now, result);

        // OBJECT TEMPLATE (before assignments)

        objectTemplateProcessor.processTemplate(
            context,
            ObjectTemplateMappingEvaluationPhaseType.BEFORE_ASSIGNMENTS,
            now,
            task,
            result);

        // ASSIGNMENTS

        assignmentProcessor.processAssignmentsProjections(context, now, task, result);
        assignmentProcessor.processOrgAssignments(context, result);
        context.recompute();

        assignmentProcessor.checkForAssignmentConflicts(context, result);

        // OBJECT TEMPLATE (after assignments)

        objectTemplateProcessor.processTemplate(
            context, ObjectTemplateMappingEvaluationPhaseType.AFTER_ASSIGNMENTS, now, task, result);
        context.recompute();

        // PASSWORD POLICY

        passwordPolicyProcessor.processPasswordPolicy(focusContext, context, result);

        // Processing done, check for success

        if (resetOnRename && !wasResetIterationCounter && willResetIterationCounter(focusContext)) {
          // Make sure this happens only the very first time during the first recompute.
          // Otherwise it will always change the token (especially if the token expression has a
          // random part)
          // hence the focusContext.getIterationToken() == null
          wasResetIterationCounter = true;
          if (iteration != 0) {
            iteration = 0;
            iterationToken = null;
            LOGGER.trace("Resetting iteration counter and token because rename was detected");
            cleanupContext(focusContext);
            continue;
          }
        }

        PrismObject<F> previewObjectNew = focusContext.getObjectNew();
        if (previewObjectNew == null) {
          // this must be delete
        } else {
          // Explicitly check for name. The checker would check for this also. But checking it here
          // will produce better error message
          PolyStringType objectName = previewObjectNew.asObjectable().getName();
          if (objectName == null || objectName.getOrig().isEmpty()) {
            throw new SchemaException(
                "No name in new object "
                    + objectName
                    + " as produced by template "
                    + objectTemplate
                    + " in iteration "
                    + iteration
                    + ", we cannot process an object without a name");
          }
        }

        // Check if iteration constraints are OK
        FocusConstraintsChecker<F> checker = new FocusConstraintsChecker<>();
        checker.setPrismContext(prismContext);
        checker.setContext(context);
        checker.setRepositoryService(cacheRepositoryService);
        checker.check(previewObjectNew, result);
        if (checker.isSatisfiesConstraints()) {
          LOGGER.trace(
              "Current focus satisfies uniqueness constraints. Iteration {}, token '{}'",
              iteration,
              iterationToken);

          if (LensUtil.evaluateIterationCondition(
              context,
              focusContext,
              iterationSpecificationType,
              iteration,
              iterationToken,
              false,
              expressionFactory,
              variables,
              task,
              result)) {
            // stop the iterations
            break;
          } else {
            conflictMessage = "post-iteration condition was false";
            LOGGER.debug(
                "Skipping iteration {}, token '{}' for {} because the post-iteration condition was false",
                new Object[] {iteration, iterationToken, focusContext.getHumanReadableName()});
          }
        } else {
          LOGGER.trace(
              "Current focus does not satisfy constraints. Conflicting object: {}; iteration={}, maxIterations={}",
              new Object[] {checker.getConflictingObject(), iteration, maxIterations});
          conflictMessage = checker.getMessages();
        }

        if (!wasResetIterationCounter) {
          wasResetIterationCounter = true;
          if (iteration != 0) {
            iterationToken = null;
            iteration = 0;
            LOGGER.trace("Resetting iteration counter and token after conflict");
            cleanupContext(focusContext);
            continue;
          }
        }
      }

      // Next iteration
      iteration++;
      iterationToken = null;
      if (iteration > maxIterations) {
        StringBuilder sb = new StringBuilder();
        if (iteration == 1) {
          sb.append("Error processing ");
        } else {
          sb.append("Too many iterations (" + iteration + ") for ");
        }
        sb.append(focusContext.getHumanReadableName());
        if (iteration == 1) {
          sb.append(": constraint violation: ");
        } else {
          sb.append(": cannot determine values that satisfy constraints: ");
        }
        if (conflictMessage != null) {
          sb.append(conflictMessage);
        }
        throw new ObjectAlreadyExistsException(sb.toString());
      }
      cleanupContext(focusContext);
    }

    addIterationTokenDeltas(focusContext, iteration, iterationToken);
    if (consistencyChecks) context.checkConsistence();
  }
 private <T extends ObjectType> void cacheObject(Cache cache, PrismObject<T> object) {
   if (cache != null) {
     cache.putObject(object.getOid(), (PrismObject<ObjectType>) object.clone());
   }
 }
Example #13
0
  public ObjectDelta getObjectDelta() throws SchemaException {
    if (ContainerStatus.ADDING.equals(getStatus())) {
      return createAddingObjectDelta();
    }

    ObjectDelta delta =
        new ObjectDelta(object.getCompileTimeClass(), ChangeType.MODIFY, object.getPrismContext());
    delta.setOid(object.getOid());

    List<ContainerWrapper> containers = getContainers();
    // sort containers by path size
    Collections.sort(containers, new PathSizeComparator());

    for (ContainerWrapper containerWrapper : getContainers()) {
      // create ContainerDelta for association container
      // HACK HACK HACK create correct procession for association container data
      // according to its structure
      if (containerWrapper.getItemDefinition().getName().equals(ShadowType.F_ASSOCIATION)) {
        ContainerDelta<ShadowAssociationType> associationDelta =
            ContainerDelta.createDelta(
                ShadowType.F_ASSOCIATION, containerWrapper.getItemDefinition());
        List<AssociationWrapper> associationItemWrappers =
            (List<AssociationWrapper>) containerWrapper.getItems();
        for (AssociationWrapper associationItemWrapper : associationItemWrappers) {
          List<ValueWrapper> assocValueWrappers = associationItemWrapper.getValues();
          for (ValueWrapper assocValueWrapper : assocValueWrappers) {
            PrismContainerValue<ShadowAssociationType> assocValue =
                (PrismContainerValue<ShadowAssociationType>) assocValueWrapper.getValue();
            if (assocValueWrapper.getStatus() == ValueStatus.DELETED) {
              associationDelta.addValueToDelete(assocValue.clone());
            } else if (assocValueWrapper.getStatus().equals(ValueStatus.ADDED)) {
              associationDelta.addValueToAdd(assocValue.clone());
            }
          }
        }
        delta.addModification(associationDelta);
      } else {
        if (!containerWrapper.hasChanged()) {
          continue;
        }

        for (ItemWrapper itemWrapper : (List<ItemWrapper>) containerWrapper.getItems()) {
          if (!itemWrapper.hasChanged()) {
            continue;
          }
          ItemPath containerPath =
              containerWrapper.getPath() != null ? containerWrapper.getPath() : new ItemPath();
          if (itemWrapper instanceof PropertyWrapper) {
            ItemDelta pDelta = computePropertyDeltas((PropertyWrapper) itemWrapper, containerPath);
            if (!pDelta.isEmpty()) {
              delta.addModification(pDelta);
            }
          }

          if (itemWrapper instanceof ReferenceWrapper) {
            ReferenceDelta pDelta =
                computeReferenceDeltas((ReferenceWrapper) itemWrapper, containerPath);
            if (!pDelta.isEmpty()) {
              delta.addModification(pDelta);
            }
          }
        }
      }
    }
    // returning container to previous order
    Collections.sort(containers, new ItemWrapperComparator());

    // Make sure we have all the definitions
    if (object.getPrismContext() != null) {
      object.getPrismContext().adopt(delta);
    }
    return delta;
  }