Как преобразовать кортежи DAML, полученные через API DA Ledger, в пары Java?

Я написал модель DAML, которая генерирует список кортежей, например [(Int, Text)], Я получаю эти данные через API DA Ledger - как мне преобразовать их в List<Pair<Long, String>> в Java?

2 ответа

Решение

Java зависит от того, работаете ли вы с необработанными скомпилированными типами Protobuf или с обернутыми типами, предоставляемыми привязками языка Java.

Объекты, возвращаемые API, представлены тремя основными типами:

  • Record
  • RecordField
  • Value,

Упрощая несколько,Record это список RecordField, RecordField это ярлык и Value и Value может быть одной из многих вещей, в том числе Int64, String, Recordили List, Кортежи как (Int, Text) имеют специальные обозначения в DAML, но представлены как нормальные Record объекты в API.

Предполагая, что вы используете типы, скомпилированные из определений protobuf, и получили в свои руки com.digitalasset.ledger.api.v1.ValueOuterClass.Value представляя [(Int, Text)]Вам необходимо сделать следующее:

  1. использование Value::getList а также ValueOuterClass.List::getElementsList развернуть Value в List<Value>,
  2. Развернуть каждый Value в списке через Value::getRecord чтобы получить List<Record>
  3. Извлеките два поля каждой записи, используя Record::getFields получить List<Pair<RecordField, RecordField>>
  4. Извлечь значения из RecordFields с RecordFields::getValue, давая List<Pair<Value, Value>>
  5. Извлечь Int64, который является псевдонимом для long, а также String от Value объекты, чтобы получить финал List<Pair<Long, String>>

Шаги 2. - 4. могут быть выполнены аккуратно, используя потоковый интерфейс Java. Показанный код предназначен для необработанных типов gRPC, начиная с com.digitalasset.ledger.api.v1.ValueOuterClass.Value:

import com.digitalasset.ledger.api.v1.ValueOuterClass;
import static java.util.AbstractMap.SimpleImmutableEntry;

import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Demo {
    static SimpleImmutableEntry<ValueOuterClass.RecordField, ValueOuterClass.RecordField> EntryFromTuple(ValueOuterClass.Record tupleRecord) {
        return new SimpleImmutableEntry<>(tupleRecord.getFields(0), tupleRecord.getFields(1));
    }

    static class SimpleImmutableEntryMap<S, T, U, V> implements Function<SimpleImmutableEntry<S, T>, SimpleImmutableEntry<U, V>> {
        Function<S, U> mapFst;
        Function<T, V> mapSnd;

        public SimpleImmutableEntryMap(Function<S, U> mapFst, Function<T, V> mapSnd) {
            this.mapFst = mapFst;
            this.mapSnd = mapSnd;
        }

        @Override
        public SimpleImmutableEntry<U, V> apply(SimpleImmutableEntry<S, T> stEntry) {
            return new SimpleImmutableEntry<> (mapFst.apply(stEntry.getKey()), mapSnd.apply(stEntry.getValue()));
        }
    }

    static List<SimpleImmutableEntry<Long, String>> mapTuple(ValueOuterClass.Value v) {
        return v.getList().getElementsList().stream()
                .map(ValueOuterClass.Value::getRecord)
                .map(Demo::EntryFromTuple)
                .map(new SimpleImmutableEntryMap<>(ValueOuterClass.RecordField::getValue, ValueOuterClass.RecordField::getValue))
                .map(new SimpleImmutableEntryMap<>(ValueOuterClass.Value::getInt64, ValueOuterClass.Value::getText))
                .collect(Collectors.toList());
    }
}

Предполагая, что у вас есть следующий шаблон daml:

template ListOfTuples
  with
    party : Party
    listOfTuples : [(Int, Text)]
  where
    signatory party

который был преобразован в com.daml.ledger.javaapi.data.Record с Java API, вы можете преобразовать его в List<Pair<Long, String>> рассматривая кортежи в списке также как Records:

import java.util.List;
import javafx.util.Pair;
import java.util.stream.Collectors;
import com.daml.ledger.javaapi.data.Record;

public void parseListOfTuples(Record record) {

  List<Pair<Long, String>> listOfTuples =
     record.getFields().get(1).getValue().asList().get().getValues().stream()
             .map(t -> {
                 List<Record.Field> tuple = t.asRecord().get().getFields();
                 return new Pair<>(
                         tuple.get(0).getValue().asInt64().get().getValue(),
                         tuple.get(1).getValue().asText().get().getValue());
             })
             .collect(Collectors.toList());
}
Другие вопросы по тегам