docs: public ActivityImpl parseCallActivity(Element callActivityElement, ScopeImpl scope, boolean isMultiInstance) {
      ActivityImpl activity = createActivityOnScope(callActivityElement, scope);
  
      // parse async
      parseAsynchronousContinuationForActivity(callActivityElement, activity);
  
      // parse definition key (and behavior)
      String calledElement = callActivityElement.attribute("calledElement");
      String caseRef = callActivityElement.attributeNS(CAMUNDA_BPMN_EXTENSIONS_NS, "caseRef");
      String className = callActivityElement.attributeNS(CAMUNDA_BPMN_EXTENSIONS_NS, PROPERTYNAME_VARIABLE_MAPPING_CLASS);
      String delegateExpression = callActivityElement.attributeNS(CAMUNDA_BPMN_EXTENSIONS_NS, PROPERTYNAME_VARIABLE_MAPPING_DELEGATE_EXPRESSION);
  
      if (calledElement == null && caseRef == null) {
        addError("Missing attribute 'calledElement' or 'caseRef'", callActivityElement);
      } else if (calledElement != null && caseRef != null) {
        addError("The attributes 'calledElement' or 'caseRef' cannot be used together: Use either 'calledElement' or 'caseRef'", callActivityElement);
      }
  
      String bindingAttributeName = "calledElementBinding";
      String versionAttributeName = "calledElementVersion";
      String versionTagAttributeName = "calledElementVersionTag";
      String tenantIdAttributeName = "calledElementTenantId";
  
      String deploymentId = deployment.getId();
  
      CallableElement callableElement = new CallableElement();
      callableElement.setDeploymentId(deploymentId);
  
      CallableElementActivityBehavior behavior = null;
  
      if (calledElement != null) {
        if (className != null) {
            behavior = new CallActivityBehavior(className);
        } else if (delegateExpression != null) {
           Expression exp = expressionManager.createExpression(delegateExpression);
           behavior = new CallActivityBehavior(exp);
        } else {
          behavior = new CallActivityBehavior();
        }
        ParameterValueProvider definitionKeyProvider = createParameterValueProvider(calledElement, expressionManager);
        callableElement.setDefinitionKeyValueProvider(definitionKeyProvider);
  
      } else {
        behavior = new CaseCallActivityBehavior();
        ParameterValueProvider definitionKeyProvider = createParameterValueProvider(caseRef, expressionManager);
        callableElement.setDefinitionKeyValueProvider(definitionKeyProvider);
        bindingAttributeName = "caseBinding";
        versionAttributeName = "caseVersion";
        tenantIdAttributeName = "caseTenantId";
      }
  
      behavior.setCallableElement(callableElement);
  
      // parse binding
      parseBinding(callActivityElement, activity, callableElement, bindingAttributeName);
  
      // parse version
      parseVersion(callActivityElement, activity, callableElement, bindingAttributeName, versionAttributeName);
  
      // parse versionTag
      parseVersionTag(callActivityElement, activity, callableElement, bindingAttributeName, versionTagAttributeName);
  
      // parse tenant id
      parseTenantId(callActivityElement, activity, callableElement, tenantIdAttributeName);
  
      // parse input parameter
      parseInputParameter(callActivityElement, callableElement);
  
      // parse output parameter
      parseOutputParameter(callActivityElement, activity, callableElement);
  
      if (!isMultiInstance) {
        // turn activity into a scope unless it is a multi instance activity, in
        // that case this
        // is not necessary because there is already the multi instance body scope
        // and concurrent
        // child executions are sufficient
        activity.setScope(true);
      }
      activity.setActivityBehavior(behavior);
  
      parseExecutionListenersOnScope(callActivityElement, activity);
  
      for (BpmnParseListener parseListener : parseListeners) {
        parseListener.parseCallActivity(callActivityElement, scope, activity);
      }
      return activity;
    }