Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typed ACS and transaction streams for Java codegen #15159

Merged
merged 27 commits into from
Oct 12, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
43c9f36
added transactionFilter
chunlokling-da Oct 4, 2022
08d0254
move transactionFilter to `TransactionFilter`
chunlokling-da Oct 4, 2022
7178636
fromCreatedEvent
chunlokling-da Oct 5, 2022
ca68c0c
format
chunlokling-da Oct 5, 2022
b76ff64
added getTransaction with contract type companion
chunlokling-da Oct 6, 2022
7269048
ACS using contract type companion
chunlokling-da Oct 6, 2022
ff2cde0
Merge remote-tracking branch 'origin/main' into 14969-typed-acs-and-t…
chunlokling-da Oct 6, 2022
14af3cc
position
chunlokling-da Oct 6, 2022
1057819
add change log
chunlokling-da Oct 6, 2022
ac6fca6
Ct
chunlokling-da Oct 6, 2022
783383c
Ct
chunlokling-da Oct 6, 2022
6532d5d
format
chunlokling-da Oct 6, 2022
85d8973
better exception
chunlokling-da Oct 6, 2022
99868fb
fixed test cases
chunlokling-da Oct 6, 2022
bc65de3
added java doc and rename method to GetContracts
chunlokling-da Oct 10, 2022
ecb1ea8
address Stephen's comments
chunlokling-da Oct 11, 2022
ec9fc8f
address Stephen's comments
chunlokling-da Oct 11, 2022
f9c0fa4
address Stephen's comments
chunlokling-da Oct 11, 2022
5526e2f
Merge remote-tracking branch 'origin/main' into 14969-typed-acs-and-t…
chunlokling-da Oct 11, 2022
7b45bd3
remove unused import
chunlokling-da Oct 11, 2022
f8f58ba
format
chunlokling-da Oct 11, 2022
2e00060
address Stephen's comments
chunlokling-da Oct 11, 2022
73ee886
address Stephen's comments
chunlokling-da Oct 11, 2022
5e70489
Make some codegen code to be java 8 compatible; Modify IouMain to use…
chunlokling-da Oct 12, 2022
c8b2200
use 1.11, no need to be java 8 compatible
chunlokling-da Oct 12, 2022
922d1fd
revert
chunlokling-da Oct 12, 2022
24bbec2
11 not 1.11
chunlokling-da Oct 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@
package com.daml.ledger.javaapi.data;

import com.daml.ledger.api.v1.TransactionFilterOuterClass;
import com.daml.ledger.javaapi.data.codegen.ContractCompanion;
import com.daml.ledger.javaapi.data.codegen.ContractTypeCompanion;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

public abstract class TransactionFilter {

Expand All @@ -17,4 +23,17 @@ public static TransactionFilter fromProto(
abstract TransactionFilterOuterClass.TransactionFilter toProto();

public abstract Set<String> getParties();

public static TransactionFilter transactionFilter(
ContractTypeCompanion<?, ?> contractCompanion, Set<String> parties) {
Filter filter =
(contractCompanion instanceof ContractCompanion)
? new InclusiveFilter(Set.of(contractCompanion.TEMPLATE_ID), Collections.emptyMap())
: new InclusiveFilter(
Collections.emptySet(),
Map.of(contractCompanion.TEMPLATE_ID, Filter.Interface.INCLUDE_VIEW));
Map<String, Filter> partyToFilters =
parties.stream().collect(Collectors.toMap(Function.identity(), x -> filter));
return new FiltersByParty(partyToFilters);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ protected Contract(
this.observers = observers;
}

// concrete 1st type param would need a self-reference type param in Contract
protected abstract ContractCompanion<? extends Contract<Id, Data>, Id, Data> getCompanion();
chunlokling-da marked this conversation as resolved.
Show resolved Hide resolved

@Override
public boolean equals(Object object) {
if (this == object) {
Expand Down Expand Up @@ -74,12 +71,7 @@ public int hashCode() {
@Override
public String toString() {
return String.format(
"%s.Contract(%s, %s, %s, %s, %s)",
getCompanion().templateClassName,
this.id,
this.data,
this.agreementText,
this.signatories,
this.observers);
"Contract(%s, %s, %s, %s, %s)",
this.id, this.data, this.agreementText, this.signatories, this.observers);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@

package com.daml.ledger.javaapi.data.codegen;

import com.daml.ledger.javaapi.data.CreatedEvent;
import com.daml.ledger.javaapi.data.*;
import com.daml.ledger.javaapi.data.DamlRecord;
import com.daml.ledger.javaapi.data.Identifier;
import com.daml.ledger.javaapi.data.Value;
chunlokling-da marked this conversation as resolved.
Show resolved Hide resolved
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import com.daml.ledger.javaapi.data.Identifier;

/** The commonality between {@link ContractCompanion} and {@link InterfaceCompanion}. */
public abstract class ContractTypeCompanion<Maker, Data> {
public abstract class ContractTypeCompanion<Marker, Data> {
/** The full template ID of the template or interface that defined this companion. */
public final Identifier TEMPLATE_ID;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package com.daml.ledger.javaapi.data.codegen;

import java.util.Optional;
import java.util.Set;

public final class ContractWithInterfaceView<Id, View> extends Contract<Id, View> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An example of why I am reluctant to add extends clauses to class or interface type parameters that aren't strictly necessary.

Sure, when defining Contract, we could have made its second type parameter extends Template. That would have compiled at the time. However, it has no functional benefits for the API, and then you would be stuck here.

While adding constraints to class tparams can be useful, it is more often no better than DatatypeContexts aka "stupid theta" in Haskell, and just as worth avoiding.

chunlokling-da marked this conversation as resolved.
Show resolved Hide resolved

ContractWithInterfaceView(
Id id,
View interfaceView,
Optional<String> agreementText,
Set<String> signatories,
Set<String> observers) {
super(id, interfaceView, agreementText, signatories, observers);
}

@Override
public boolean equals(Object object) {
return object instanceof ContractWithInterfaceView && super.equals(object);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,7 @@ public final int hashCode() {
@Override
public final String toString() {
return String.format(
"%s.Contract(%s, %s, %s, %s, %s, %s)",
getCompanion().templateClassName,
this.id,
this.data,
this.agreementText,
this.key,
this.signatories,
this.observers);
"Contract(%s, %s, %s, %s, %s, %s)",
this.id, this.data, this.agreementText, this.key, this.signatories, this.observers);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,57 @@

package com.daml.ledger.javaapi.data.codegen;

import com.daml.ledger.javaapi.data.Identifier;
import com.daml.ledger.javaapi.data.*;
import com.daml.ledger.javaapi.data.DamlRecord;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;

/**
* Metadata and utilities associated with an interface as a whole. Its subclasses serve to
* disambiguate various generated {@code toInterface} overloads.
*
* @param <I> The generated interface marker class.
*/
public abstract class InterfaceCompanion<I, View> extends ContractTypeCompanion<I, View> {
public abstract class InterfaceCompanion<I, Id, View> extends ContractTypeCompanion<I, View> {

protected final Function<String, Id> newContractId;
chunlokling-da marked this conversation as resolved.
Show resolved Hide resolved

public final ValueDecoder<View> valueDecoder;

protected InterfaceCompanion(Identifier templateId, ValueDecoder<View> valueDecoder) {
private Contract<Id, View> fromIdAndRecord(
String contractId,
Map<Identifier, DamlRecord> interfaceViews,
Optional<String> agreementText,
Set<String> signatories,
Set<String> observers)
throws IllegalAccessException {
Optional<DamlRecord> maybeRecord = Optional.ofNullable(interfaceViews.get(TEMPLATE_ID));
Id id = newContractId.apply(contractId);
if (maybeRecord.isPresent()) {
View view = valueDecoder.decode(maybeRecord.get());
return new ContractWithInterfaceView<>(id, view, agreementText, signatories, observers);
} else {
// TODO: CL handle all exceptional cases
throw new IllegalAccessException("interface view not found. It could be failed");
}
}

public final Contract<Id, View> fromCreatedEvent(CreatedEvent event)
throws IllegalAccessException {
return fromIdAndRecord(
event.getContractId(),
event.getInterfaceViews(),
event.getAgreementText(),
event.getSignatories(),
event.getObservers());
}

protected InterfaceCompanion(
Identifier templateId, Function<String, Id> newContractId, ValueDecoder<View> valueDecoder) {
super(templateId);
this.newContractId = newContractId;
this.valueDecoder = valueDecoder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,19 +107,6 @@ object ContractClass {

private[this] val contractIdClassName = ClassName bestGuess "ContractId"

private[this] def generateGetCompanion(templateClassName: ClassName): MethodSpec = {
val contractClassName = ClassName bestGuess "Contract"
ClassGenUtils.generateGetCompanion(
ParameterizedTypeName.get(
ClassName get classOf[javaapi.data.codegen.ContractCompanion[_, _, _]],
contractClassName,
contractIdClassName,
templateClassName,
),
companionFieldName,
)
}

def create(
templateClassName: ClassName,
key: Option[Type],
Expand Down Expand Up @@ -172,8 +159,6 @@ object ContractClass {
classBuilder.addMethod(constructor)

val contractClassName = ClassName.bestGuess("Contract")
classBuilder
.addMethod(generateGetCompanion(templateClassName))
new Builder(
classBuilder,
contractClassName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,27 +84,36 @@ object InterfaceClass extends StrictLogging {
private def generateInterfaceCompanionClass(
interfaceName: ClassName,
interfaceViewTypeName: ClassName,
): TypeSpec = TypeSpec
.classBuilder(companionName)
.superclass(
ParameterizedTypeName
.get(ClassName get classOf[InterfaceCompanion[_, _]], interfaceName, interfaceViewTypeName)
)
.addModifiers(Modifier.FINAL, Modifier.PUBLIC, Modifier.STATIC)
.addMethod {
MethodSpec
.constructorBuilder()
// intentionally package-private
.addStatement(
"super($T.$N, $T.$L())",
interfaceName,
ClassGenUtils.templateIdFieldName,
interfaceViewTypeName,
"valueDecoder",
)
.build()
}
.build()
): TypeSpec = {
val contractIdClassName = ClassName bestGuess "ContractId"
TypeSpec
.classBuilder(companionName)
.superclass(
ParameterizedTypeName
.get(
ClassName get classOf[InterfaceCompanion[_, _, _]],
interfaceName,
contractIdClassName,
interfaceViewTypeName,
)
)
.addModifiers(Modifier.FINAL, Modifier.PUBLIC, Modifier.STATIC)
.addMethod {
MethodSpec
.constructorBuilder()
// intentionally package-private
.addStatement(
"super($T.$N, $T::new, $T.$L())",
interfaceName,
ClassGenUtils.templateIdFieldName,
contractIdClassName,
interfaceViewTypeName,
"valueDecoder",
)
.build()
}
.build()
}

private def generateTemplateIdField(packageId: PackageId, name: QualifiedName): FieldSpec =
ClassGenUtils.generateTemplateIdField(
Expand Down