docs: private PatchingResult applyPatch(final String patchId, final Patch patch, final IdentityPatchContext context) throws PatchingException, IOException, XMLStreamException {
  
          final Identity identity = patch.getIdentity();
          final Patch.PatchType patchType = identity.getPatchType();
          final InstallationManager.InstallationModification modification = context.getModification();
          if (patchType == Patch.PatchType.CUMULATIVE) {
              // Invalidate all installed patches (one-off, cumulative) - we never need to invalidate the release base
              final List<String> invalidation = new ArrayList<String>(modification.getPatchIDs());
              if (!invalidation.isEmpty()) {
                  try {
                      // Before rolling back the one-off patches, validate that the state until that point is consistent
                      validateRollbackState(invalidation.get(invalidation.size() - 1),
                              modification.getUnmodifiedInstallationState());
                  } catch (PatchingException e) {
                      throw e;
                  } catch (Exception e) {
                      throw new PatchingException(e);
                  }
                  // Invalidate the installed patches first
                  for (final String rollback : invalidation) {
                      rollback(rollback, context);
                  }
              }
          }
  
          // Add to installed patches list
          modification.addInstalledPatch(patchId);
  
          // Then apply the current patch
          for (final PatchElement element : patch.getElements()) {
              // Apply the content modifications
              final IdentityPatchContext.PatchEntry target = context.resolveForElement(element);
              final PatchElementProvider provider = element.getProvider();
              final Patch.PatchType elementPatchType = provider.getPatchType();
              final String elementPatchId = element.getId();
              // See if we can skip this element
              if (target.isApplied(elementPatchId)) {
                  // TODO if it is already applied, we can just skip the entry (maybe based ont the type of the patch)
                  // This needs some further testing, maybe we need to compare our history with the patch if they are consistent
                  throw PatchLogger.ROOT_LOGGER.alreadyApplied(elementPatchId);
              }
              // Check upgrade conditions
              checkUpgradeConditions(provider, target);
              apply(elementPatchId, element.getModifications(), target);
              target.apply(elementPatchId, elementPatchType);
          }
          // Apply the patch to the identity
          final IdentityPatchContext.PatchEntry identityEntry = context.getIdentityEntry();
          apply(patchId, patch.getModifications(), identityEntry);
          identityEntry.apply(patchId, patchType);
  
          // Port forward missing module changes
          if (patchType == Patch.PatchType.CUMULATIVE) {
              portForward(patch, context);
          }
  
          // We need the resulting version for rollback
          if (patchType == Patch.PatchType.CUMULATIVE) {
              final Identity.IdentityUpgrade upgrade = identity.forType(Patch.PatchType.CUMULATIVE, Identity.IdentityUpgrade.class);
              identityEntry.setResultingVersion(upgrade.getResultingVersion());
          }
  
          // Execute the tasks
          final IdentityApplyCallback callback = new IdentityApplyCallback(patch, identityEntry.getDirectoryStructure());
          try {
              return executeTasks(context, callback);
          } catch (Exception e) {
              context.cancel(callback);
              throw rethrowException(e);
          }
      }