/**
   * Fetches a single change package fragment.
   *
   * @param sessionId the {@link SessionId} representing the requesting user
   * @param proxyId the ID that identifies the list of stored fragments
   * @param fragmentIndex allows to request different change package fragments
   * @return a {@link ChangePackageEnvelope} containing the change package fragment
   * @throws ESException in case the mandatory session adapter is missing
   */
  @ESMethod(MethodId.DOWNLOADCHANGEPACKAGEFRAGMENT)
  public ChangePackageEnvelope downloadChangePackageFragment(
      SessionId sessionId, String proxyId, int fragmentIndex) throws ESException {

    final ESSessionId resolvedSession =
        getAccessControl().getSessions().resolveSessionById(sessionId.getId());
    final SessionId session = APIUtil.toInternal(SessionId.class, resolvedSession);
    final Optional<ChangePackageFragmentProviderAdapter> maybeAdapter =
        ESCollections.find(session.eAdapters(), ChangePackageFragmentProviderAdapter.class);

    if (!maybeAdapter.isPresent()) {
      throw new ESException(
          Messages.VersionSubInterfaceImpl_ChangePackageFragmentProviderAdapterMissing + sessionId);
    }

    final ChangePackageFragmentProviderAdapter adapter = maybeAdapter.get();
    final ChangePackageEnvelope envelope =
        VersioningFactory.eINSTANCE.createChangePackageEnvelope();
    final List<String> fragment = adapter.getFragment(proxyId, fragmentIndex);

    envelope.getFragment().addAll(fragment);
    envelope.setFragmentCount(adapter.getFragmentSize(proxyId));
    envelope.setFragmentIndex(fragmentIndex);

    if (envelope.isLast()) {
      adapter.markAsConsumed(proxyId);
    }

    return envelope;
  }