2 votes

Comparer deux FixMessages dans QuickFIXJ

Je dois comparer deux messages fixes (disons deux ExecutionReports) dans QuickFIXJ.

Appelons-les er1 y er2

Maintenant, ce que je veux dire en les comparant, c'est qu'un certain nombre de champs doivent être identiques. par exemple, je veux que le tag 55, le tag 207, le tag 1 soient identiques. mais pas les autres.

Il me semble que la seule façon de le faire est d'écrire quelque chose d'aussi coûteux (en termes de performances) que celui-ci :

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

}

Est-ce que quelque chose m'échappe ? Quelqu'un peut-il suggérer une approche meilleure/plus rapide ?

2voto

DumbCoder Points 4097

Il n'y a pas de fonction permettant de comparer deux messages fixes dans l'application API il semble. Mais au lieu de comparer l'ensemble des champs du message, le mieux serait de ne comparer que les champs qui sont obligatoires. Une extension serait si vous êtes absolument sûr que ces champs seront présents dans le message FIX.

Une autre option serait de comparer dans un fil différent de celui de la session où vous envoyez et recevez des messages. Il serait difficile de décider si les messages doivent être comparés dans le même thread, sans savoir ce qui se passe en aval avec les rapports d'exécution ou quelles sont vos actions si les rapports d'exécution correspondent.

0voto

Mykhaylo Adamovych Points 1907

Mise en œuvre basée sur quickfix.Message.toXML() logique d'itération. Le résultat de la comparaison est une carte triée de la clé composite (si le champ fait partie du groupe) et de la paire d'états "avant" et "après".

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X