private static List<IActivity> getEndActivities(IProcessDefinition process) {
   List<IActivity> activities = CollectionUtils.newList();
   for (IActivity activity : process.getActivities()) {
     if (activity.getOutTransitions().isEmpty()) {
       activities.add(activity);
     }
   }
   return activities;
 }
  /**
   * @param modelCache
   * @param ai
   * @return
   */
  private static Map<String, DescriptorDTO> getProcessDescriptors(
      ModelCache modelCache, ActivityInstance ai) {
    List<ProcessDescriptor> processDescriptorsList = CollectionUtils.newList();

    Model model = modelCache.getModel(ai.getModelOID());
    ProcessDefinition processDefinition =
        (model != null) ? model.getProcessDefinition(ai.getProcessDefinitionId()) : null;
    if (processDefinition != null) {
      ProcessInstanceDetails processInstanceDetails =
          (ProcessInstanceDetails) ai.getProcessInstance();
      Map<String, Object> descriptorValues = processInstanceDetails.getDescriptors();
      CommonDescriptorUtils.updateProcessDocumentDescriptors(
          descriptorValues, ai.getProcessInstance(), processDefinition);
      if (processInstanceDetails.isCaseProcessInstance()) {
        processDescriptorsList =
            CommonDescriptorUtils.createCaseDescriptors(
                processInstanceDetails.getDescriptorDefinitions(),
                descriptorValues,
                processDefinition,
                true);
      } else {
        processDescriptorsList =
            CommonDescriptorUtils.createProcessDescriptors(
                descriptorValues, processDefinition, true, true);
      }

      Map<String, DescriptorDTO> descriptors = new LinkedHashMap<String, DescriptorDTO>();
      for (Object descriptor : processDescriptorsList) {
        if (descriptor instanceof ProcessDocumentDescriptor) {
          ProcessDocumentDescriptor desc = (ProcessDocumentDescriptor) descriptor;

          List<DocumentDTO> documents = new ArrayList<DocumentDTO>();

          for (DocumentInfo documentInfo : desc.getDocuments()) {
            DocumentDTO documentDTO = new DocumentDTO();
            documentDTO.name = documentInfo.getName();
            documentDTO.uuid = documentInfo.getId();
            documentDTO.contentType =
                (MimeTypesHelper.detectMimeType(documentInfo.getName(), null).getType());
            documents.add(documentDTO);
          }

          DescriptorDTO descriptorDto =
              new DescriptorDTO(desc.getKey(), desc.getValue(), true, documents);
          descriptors.put(desc.getId(), descriptorDto);
        } else {
          ProcessDescriptor desc = (ProcessDescriptor) descriptor;
          DescriptorDTO descriptorDto =
              new DescriptorDTO(desc.getKey(), desc.getValue(), false, null);
          descriptors.put(desc.getId(), descriptorDto);
        }
      }
      return descriptors;
    }
    return null;
  }
 @Override
 public Collection<IDaemon> getDaemons() {
   List<IModel> models = ModelManagerFactory.getCurrent().findActiveModels();
   if (!models.isEmpty()) {
     Set<String> ids = CollectionUtils.newSet();
     List<IDaemon> daemons = CollectionUtils.newList();
     for (IModel model : models) {
       // Compute and store the model dependent daemons in model for faster lookup
       List<IDaemon> modelDependentDaemons;
       synchronized (model) {
         modelDependentDaemons =
             (List<IDaemon>) model.getRuntimeAttribute(CACHED_DAEMON_FACTORY);
         if (modelDependentDaemons == null) {
           modelDependentDaemons = CollectionUtils.newList();
           for (Iterator i = model.getAllTriggerTypes(); i.hasNext(); ) {
             ITriggerType type = (ITriggerType) i.next();
             if (type.isPullTrigger()) {
               modelDependentDaemons.add(new TriggerDaemon(type));
             }
           }
           model.setRuntimeAttribute(CACHED_DAEMON_FACTORY, modelDependentDaemons);
         }
       }
       // Compute union of all daemons
       // This always has to be computed as the daemons of a model might change
       // if new model version is deployed
       for (IDaemon daemon : modelDependentDaemons) {
         String type = daemon.getType();
         if (!ids.contains(type)) {
           daemons.add(daemon);
           ids.add(type);
         }
       }
     }
     return daemons;
   }
   return Collections.emptyList();
 }
  public static List<TransitionTarget> getRelocateTargets(
      long activityInstanceOid, TransitionOptions options, ScanDirection direction) {
    IActivityInstance ai = ActivityInstanceBean.findByOID(activityInstanceOid);
    IActivity activity = ai.getActivity();

    if (!activity.getBooleanAttribute(PredefinedConstants.ACTIVITY_IS_RELOCATE_SOURCE_ATT)) {
      // activity is not a relocation source
      return Collections.emptyList();
    }

    Stack<TransitionStep> steps = new Stack();
    List<TransitionTarget> targets = CollectionUtils.newList();
    Set<TransitionTarget> visited = CollectionUtils.newSet();
    switch (direction) {
      case FORWARD:
        addActivities(
            visited,
            targets,
            ai,
            options == null ? TransitionOptions.DEFAULT : options,
            true,
            steps);
        break;
      case BACKWARD:
        addActivities(
            visited,
            targets,
            ai,
            options == null ? TransitionOptions.DEFAULT : options,
            false,
            steps);
        break;
      default:
        addActivities(
            visited,
            targets,
            ai,
            options == null ? TransitionOptions.DEFAULT : options,
            true,
            steps);
        addActivities(
            visited,
            targets,
            ai,
            options == null ? TransitionOptions.DEFAULT : options,
            false,
            steps);
    }
    return targets;
  }
/**
 * @author rsauer
 * @version $Revision$
 */
public class AuditTrailActivator extends Plugin {
  private final List<IAuditTrailDbListener> dbListeners = CollectionUtils.newList();

  private static AuditTrailActivator instance = null;

  public static AuditTrailActivator instance() {
    return instance;
  }

  public AuditTrailActivator() {}

  public void start(BundleContext context) throws Exception {
    super.start(context);

    instance = this;
  }

  public void stop(BundleContext context) throws Exception {
    super.stop(context);

    instance = null;
  }

  public void addDbListener(IAuditTrailDbListener listener) {
    if (!dbListeners.contains(listener)) {
      dbListeners.add(listener);
    }
  }

  public void removeDbListener(IAuditTrailDbListener listener) {
    dbListeners.remove(listener);
  }

  protected void notifyDbListeners(IFolder dbFolder, int change) {
    if (!dbListeners.isEmpty()) {
      IAuditTrailDbListener[] listeners =
          (IAuditTrailDbListener[]) dbListeners.toArray(new IAuditTrailDbListener[0]);
      for (int i = 0; i < listeners.length; i++) {
        listeners[i].onAuditTrailDbChanged(dbFolder, change);
      }
    }
  }
}
  private static IActivity consume(
      IActivity startActivity,
      LinkedList<ITransition> unconsumed,
      HashSet<ITransition> visited,
      boolean forward,
      boolean supportsLoops) {
    int unchanged = 0;
    while (!unconsumed.isEmpty()) {
      ITransition transition = unconsumed.element();
      IActivity target = forward ? transition.getToActivity() : transition.getFromActivity();

      if (startActivity == target) {
        // unsupported loop
        break;
      }

      JoinSplitType inJsType = forward ? target.getJoinType() : target.getSplitType();
      if (JoinSplitType.And == inJsType) {
        List<ITransition> pending = CollectionUtils.newList();
        ModelElementList<ITransition> transitions =
            forward ? target.getInTransitions() : target.getOutTransitions();
        for (ITransition incoming : transitions) {
          if (unconsumed.remove(incoming)) {
            pending.add(incoming);
          }
        }
        if (pending.size() == transitions.size()) // all incoming transitions consumed
        {
          if (unconsumed.isEmpty()) {
            return target;
          }
        } else {
          if (!unconsumed
              .isEmpty()) // unable to consume all transitions, but there are more branches, put
          // them all back to the end
          {
            unconsumed.addAll(pending);
            unchanged++;
          }
          if (unchanged == unconsumed.size()) {
            return null;
          }
          continue;
        }
      } else {
        unconsumed.remove(transition);
      }
      unchanged = 0;

      ModelElementList<ITransition> transitions =
          forward ? target.getOutTransitions() : target.getInTransitions();
      if (transitions.isEmpty()) {
        return null;
      }

      JoinSplitType outJsType = forward ? target.getSplitType() : target.getJoinType();
      if (JoinSplitType.Xor == outJsType && transitions.size() > 1) {
        return consumeXor(startActivity, unconsumed, visited, forward, supportsLoops, transitions);
      } else {
        for (ITransition out : transitions) {
          if (visited.contains(out)) // loop
          {
            if (!supportsLoops) {
              return null;
            }
          } else {
            visited.add(out);
            unconsumed.add(out);
          }
        }
      }
    }
    return null;
  }
    public PerformanceStatistics(long userOid) {
      this.userOid = userOid;

      this.contributions = CollectionUtils.newList();
    }