private int compareInstanceUsingKey(
     String key, ProcessInstanceDAO instanceDAO1, ProcessInstanceDAO instanceDAO2) {
   String s1 = null;
   String s2 = null;
   boolean ascending = true;
   String orderKey = key;
   if (key.startsWith("+") || key.startsWith("-")) {
     orderKey = key.substring(1, key.length());
     if (key.startsWith("-")) ascending = false;
   }
   ProcessDAO process1 = getProcess(instanceDAO1.getProcess().getProcessId());
   ProcessDAO process2 = getProcess(instanceDAO2.getProcess().getProcessId());
   if ("pid".equals(orderKey)) {
     s1 = process1.getProcessId().toString();
     s2 = process2.getProcessId().toString();
   } else if ("name".equals(orderKey)) {
     s1 = process1.getProcessId().getLocalPart();
     s2 = process2.getProcessId().getLocalPart();
   } else if ("namespace".equals(orderKey)) {
     s1 = process1.getProcessId().getNamespaceURI();
     s2 = process2.getProcessId().getNamespaceURI();
   } else if ("version".equals(orderKey)) {
     s1 = "" + process1.getVersion();
     s2 = "" + process2.getVersion();
   } else if ("status".equals(orderKey)) {
     s1 = "" + instanceDAO1.getState();
     s2 = "" + instanceDAO2.getState();
   } else if ("started".equals(orderKey)) {
     s1 = ISO8601DateParser.format(instanceDAO1.getCreateTime());
     s2 = ISO8601DateParser.format(instanceDAO2.getCreateTime());
   } else if ("last-active".equals(orderKey)) {
     s1 = ISO8601DateParser.format(instanceDAO1.getLastActiveTime());
     s2 = ISO8601DateParser.format(instanceDAO2.getLastActiveTime());
   }
   if (ascending) return s1.compareTo(s2);
   else return s2.compareTo(s1);
 }
  @SuppressWarnings("unchecked")
  public Collection<ProcessInstanceDAO> instanceQuery(InstanceFilter filter) {
    if (filter.getLimit() == 0) {
      return Collections.EMPTY_LIST;
    }
    List<ProcessInstanceDAO> matched = new ArrayList<ProcessInstanceDAO>();
    // Selecting
    selectionCompleted:
    for (ProcessDaoImpl proc : _store.values()) {
      boolean pmatch = true;
      if (filter.getNameFilter() != null
          && !equalsOrWildcardMatch(filter.getNameFilter(), proc.getProcessId().getLocalPart()))
        pmatch = false;
      if (filter.getNamespaceFilter() != null
          && !equalsOrWildcardMatch(
              filter.getNamespaceFilter(), proc.getProcessId().getNamespaceURI())) pmatch = false;

      if (pmatch) {
        for (ProcessInstanceDAO inst : proc._instances.values()) {
          boolean match = true;

          if (filter.getStatusFilter() != null) {
            boolean statusMatch = false;
            for (Short status : filter.convertFilterState()) {
              if (inst.getState() == status.byteValue()) statusMatch = true;
            }
            if (!statusMatch) match = false;
          }
          if (filter.getStartedDateFilter() != null
              && !dateMatch(filter.getStartedDateFilter(), inst.getCreateTime(), filter))
            match = false;
          if (filter.getLastActiveDateFilter() != null
              && !dateMatch(filter.getLastActiveDateFilter(), inst.getLastActiveTime(), filter))
            match = false;

          // if (filter.getPropertyValuesFilter() != null) {
          // for (Map.Entry propEntry :
          // filter.getPropertyValuesFilter().entrySet()) {
          // boolean entryMatched = false;
          // for (ProcessPropertyDAO prop : proc.getProperties()) {
          // if (prop.getName().equals(propEntry.getKey())
          // && (propEntry.getValue().equals(prop.getMixedContent())
          // || propEntry.getValue().equals(prop.getSimpleContent())))
          // {
          // entryMatched = true;
          // }
          // }
          // if (!entryMatched) {
          // match = false;
          // }
          // }
          // }

          if (match) {
            matched.add(inst);
            if (matched.size() == filter.getLimit()) {
              break selectionCompleted;
            }
          }
        }
      }
    }
    // And ordering
    if (filter.getOrders() != null) {
      final List<String> orders = filter.getOrders();

      Collections.sort(
          matched,
          new Comparator<ProcessInstanceDAO>() {
            public int compare(ProcessInstanceDAO o1, ProcessInstanceDAO o2) {
              for (String orderKey : orders) {
                int result = compareInstanceUsingKey(orderKey, o1, o2);
                if (result != 0) return result;
              }
              return 0;
            }
          });
    }

    return matched;
  }