比较 QuickFIXJ 中的两个 FixMessage

发布于 2024-10-25 17:02:52 字数 608 浏览 7 评论 0原文

我需要在 QuickFIXJ 中比较两个修复消息(例如两个执行报告)。

我们将它们称为 er1er2

现在,我比较它们的意思是一堆字段必须相同。 例如我关心标签 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

}

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

I need to compare two fix messages (say two ExecutionReports) in QuickFIXJ.

Let's call them er1 and er2

Now, what I mean by comparing them is that a bunch of fields must be identical.
for instance I care that tag 55, tag 207, tag 1 are the same.
but not others.

It seems to me that the only way to do so is to write something as expensive (performance-wise) as this:

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

}

Am I missing something ?
can somebody suggest a better/faster approach ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ˇ宁静的妩媚 2024-11-01 17:02:52

API 中似乎没有比较两个修复消息的功能。但最好不要比较整个消息字段,而是仅比较那些必填字段。如果您完全确定这些字段会出现在 FIX 消息中,则可以进行扩展。

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

There is no function to compare two fix messages in the API, it seems. But instead of comparing the whole message fields, the best would be to compare only those fields which are mandatory. An extension would be if you are dead sure those fields would be present in the FIX message.

Another option would be to compare in a thread different than the one for the session where you are sending and receiving messages. It would be hard to decide if the messages need to be compared in the same thread, without knowing what happens downstream with the Execution reports or what are your actions if the Execution reports match.

三生池水覆流年 2024-11-01 17:02:52

基于 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();
        }
    }
}

Implementation based on quickfix.Message.toXML() iteration logic.
Result of the comparison is sorted map of composite key (if field is part of the group) and pair of 'before' and 'after' state.

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();
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文