docs: public List<CaseStageInstance> internalGetCaseStages(CaseDefinition caseDef, String caseId, boolean activeOnly, QueryContext queryContext) {
          
          CorrelationKey correlationKey = correlationKeyFactory.newCorrelationKey(caseId);
          Collection<org.jbpm.services.api.model.NodeInstanceDesc> nodes = runtimeDataService.getNodeInstancesByCorrelationKeyNodeType(correlationKey, 
                                                                                              Arrays.asList(ProcessInstance.STATE_ACTIVE), 
                                                                                              Arrays.asList("DynamicNode"), 
                                                                                              queryContext);
          Collection<Long> completedNodes = nodes.stream().filter(n -> ((NodeInstanceDesc)n).getType() == 1).map(n -> n.getId()).collect(toList());
          
          Map<String, CaseStage> stagesByName = caseDef.getCaseStages().stream()
          .collect(toMap(CaseStage::getId, c -> c)); 
          Predicate<org.jbpm.services.api.model.NodeInstanceDesc> filterNodes = null;
          if (activeOnly) {
              
              filterNodes = n -> ((NodeInstanceDesc)n).getType() == 0 && !completedNodes.contains(((NodeInstanceDesc)n).getId());             
          } else {
              filterNodes = n -> ((NodeInstanceDesc)n).getType() == 0;
          }
          
          List<String> triggeredStages = new ArrayList<>();
          List<CaseStageInstance> stages = new ArrayList<>();
          nodes.stream()
          .filter(filterNodes)
          .map(n -> {
              StageStatus status = StageStatus.Active;
              if (completedNodes.contains(((NodeInstanceDesc)n).getId())) {
                  status = StageStatus.Completed;
              }
              Collection<org.jbpm.services.api.model.NodeInstanceDesc> activeNodes = getActiveNodesForCaseAndStage(caseId, n.getNodeId(), new QueryContext(0, 100));
              return new CaseStageInstanceImpl(n.getNodeId(), n.getName(), stagesByName.get(n.getNodeId()).getAdHocFragments(), activeNodes, status);
              })
          .forEach(csi -> {
              stages.add(csi);
              triggeredStages.add(csi.getName());                        
          });
          
          
          if (!activeOnly) {
              // add other stages that are present in the definition            
              caseDef.getCaseStages().stream()
              .filter(cs -> !triggeredStages.contains(cs.getName()))
              .map(cs -> new CaseStageInstanceImpl(cs.getId(), cs.getName(), cs.getAdHocFragments(), Collections.emptyList(), StageStatus.Available))
              .forEach(csi -> stages.add(csi));
          }
          
          return stages;
      }