public MatchResult match(EvaluationCtx context) {
        // if we apply to anything, then we always match
        if (matchGroups.isEmpty())
            return new MatchResult(MatchResult.MATCH);

        // there are specific matching elements, so prepare to iterate
        // through the list
        Iterator it = matchGroups.iterator();
        Status firstIndeterminateStatus = null;

        // in order for this section to match, one of the groups must match 
        while (it.hasNext()) {
            // get the next group and try matching it
            TargetMatchGroup group = (TargetMatchGroup)(it.next());
            MatchResult result = group.match(context);

            // we only need one match, so if this matched, then we're done
            if (result.getResult() == MatchResult.MATCH)
                return result;

            // if we didn't match then it was either a NO_MATCH or
            // INDETERMINATE...in the second case, we need to remember
            // it happened, 'cause if we don't get a MATCH, then we'll
            // be returning INDETERMINATE
            if (result.getResult() == MatchResult.INDETERMINATE) {
                if (firstIndeterminateStatus == null)
                    firstIndeterminateStatus = result.getStatus();
            }
        }

        // if we got here, then none of the sub-matches passed, so
        // we have to see if we got any INDETERMINATE cases
        if (firstIndeterminateStatus == null)
            return new MatchResult(MatchResult.NO_MATCH);
        else
            return new MatchResult(MatchResult.INDETERMINATE,
                                   firstIndeterminateStatus);
    }