@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;
  }