2

我需要在 QuickFIXJ 中比较两个修复消息(比如两个 ExecutionReports)。

让我们打电话给er1他们er2

现在,我比较它们的意思是一堆字段必须相同。例如,我关心标签 55、标签 207、标签 1 是否相同。但不是其他人。

在我看来,这样做的唯一方法是编写像这样昂贵(性能方面)的东西:

public static boolean compare(ExecutionReport er1,ExecutionReport er2) 
{
   StringField sf1 = new StringField(55);
   StringField sf2 = new StringField(55);

   er.getField(sf1);
   er.getField(sf2);

   if (sf1.getValue().equals(sf2.getValue())==false) return false;

   ... // continue with all of the other fields
   ... // in the same way

}

我错过了什么吗?有人可以提出更好/更快的方法吗?

4

2 回答 2

2

似乎没有比较API中的两条修复消息的功能。但与其比较整个消息字段,不如只比较那些必填字段。如果您确定这些字段会出现在 FIX 消息中,则可以进行扩展。

另一种选择是在与您发送和接收消息的会话不同的线程中进行比较。如果不知道执行报告下游会发生什么,或者如果执行报告匹配,您将很难决定是否需要在同一个线程中比较消息。

于 2011-03-23T09:10:41.663 回答
0

基于quickfix.Message.toXML()迭代逻辑的实现。比较的结果是复合键(如果字段是组的一部分)和“之前”和“之后”状态对的排序映射。

import static java.lang.Math.min;
import static java.util.Collections.emptySet;
import static java.util.stream.Collectors.toList;
import static org.apache.commons.collections4.CollectionUtils.subtract;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;

import quickfix.Field;
import quickfix.FieldMap;
import quickfix.Group;
import quickfix.Message;

public class FixDiff {

    private static final CompositeKeyComparator COMPARATOR = new CompositeKeyComparator();

    private Set<Integer> ignored;

    public FixDiff() {
        this(emptySet());
    }

    public FixDiff(Set<Integer> ignored) {
        this.ignored = ignored;
    }

    public Map<List<Integer>, Pair<String, String>> compare(Message expected, Message actual) {
        Map<List<Integer>, String> expectedMap = toHierarchialMap(expected);
        Map<List<Integer>, String> actualMap = toHierarchialMap(actual);

        Collection<List<Integer>> missing = subtract(expectedMap.keySet(), actualMap.keySet());
        Collection<List<Integer>> extra = subtract(actualMap.keySet(), expectedMap.keySet());
        Collection<List<Integer>> diff = expectedMap.entrySet().stream()
                .filter(e -> !missing.contains(e.getKey()) && !extra.contains(e.getKey()))
                .filter(e -> !e.getValue().equals(actualMap.get(e.getKey())))
                .map(Entry::getKey)
                .collect(toList());

        TreeMap<List<Integer>, Pair<String, String>> discrepancies = new TreeMap<List<Integer>, Pair<String, String>>(COMPARATOR);
        missing.forEach(key -> discrepancies.put(key, new ImmutablePair<String, String>(expectedMap.get(key), null)));
        extra.forEach(key -> discrepancies.put(key, new ImmutablePair<String, String>(null, actualMap.get(key))));
        diff.forEach(key -> discrepancies.put(key, new ImmutablePair<String, String>(expectedMap.get(key), actualMap.get(key))));
        return discrepancies;
    }

    private Map<List<Integer>, String> toHierarchialMap(Message message) {
        Map<List<Integer>, String> result = new HashMap<List<Integer>, String>();
        toHierarchialMap(result, new ArrayList<Integer>(), message.getHeader());
        toHierarchialMap(result, new ArrayList<Integer>(), message);
        toHierarchialMap(result, new ArrayList<Integer>(), message.getTrailer());
        return result;
    }

    private void toHierarchialMap(Map<List<Integer>, String> map, ArrayList<Integer> segmentKey, FieldMap segment) {
        Iterator<Field<?>> iterator = segment.iterator();
        while (iterator.hasNext()) {
            Field<?> field = iterator.next();
            if (!ignored.contains(field.getTag()) && field.getObject() != null)
                map.put(compositeKey(segmentKey, field.getTag()), field.getObject().toString());
        }
        Iterator<Integer> groupKeyIterator = segment.groupKeyIterator();
        while (iterator.hasNext()) {
            Integer groupKey = groupKeyIterator.next();
            if (ignored.contains(groupKey))
                continue;
            for (Group group : segment.getGroups(groupKey))
                toHierarchialMap(map, compositeKey(segmentKey, groupKey), group);
        }
    }

    private ArrayList<Integer> compositeKey(ArrayList<Integer> parent, Integer tag) {
        ArrayList<Integer> copy = new ArrayList<>(parent);
        copy.add(tag);
        return copy;
    }

    private static class CompositeKeyComparator implements Comparator<List<Integer>> {
        @Override
        public int compare(List<Integer> o1, List<Integer> o2) {
            for (int i = 0; i < min(o1.size(), o2.size()); i++) {
                if (o1.get(i) != o2.get(i))
                    return o1.get(i) - o2.get(i);
            }
            return o1.size() - o2.size();
        }
    }
}
于 2021-03-25T14:58:50.003 回答