private <T extends ShadowType> PrismObject<T> wrapInShadow(
     Class<T> type, ResourceAttributeContainer resourceObject) throws SchemaException {
   PrismObjectDefinition<T> shadowDefinition = getShadowDefinition(type);
   PrismObject<T> shadow = shadowDefinition.instantiate();
   resourceObject.setElementName(ShadowType.F_ATTRIBUTES);
   shadow.getValue().add(resourceObject);
   return shadow;
 }
 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;
 }
  /**
   * 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;
  }