mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 09:17:43 +03:00
Java Codegen now supports parametrized ContractIds. (#2621)
Fixes #2258
This commit is contained in:
parent
16d88ebcc0
commit
32a61b275f
@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2019 The DAML Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.ledger.javaapi.data.codegen;
|
||||
|
||||
import com.daml.ledger.javaapi.data.Value;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This class is used as a super class for all concrete ContractIds generated
|
||||
* by the java codegen with the following properties:
|
||||
*
|
||||
*<pre>
|
||||
* Foo.ContractId fooCid = new Foo.ContractId("test");
|
||||
* Bar.ContractId barCid = new Bar.ContractId("test");
|
||||
* ContractId<Foo> genericFooCid = new ContractId<>("test");
|
||||
* ContractId<Foo> genericBarCid = new ContractId<>("test");
|
||||
*
|
||||
* fooCid.equals(genericFooCid) == true;
|
||||
* genericFooCid.equals(fooCid) == true;
|
||||
*
|
||||
* fooCid.equals(barCid) == false;
|
||||
* barCid.equals(fooCid) == false;
|
||||
*</pre>
|
||||
*
|
||||
* Due to erase, we cannot distinguish ContractId<Foo> from ContractId<Bar>, thus:
|
||||
*
|
||||
* <pre>
|
||||
* fooCid.equals(genericBarCid) == true
|
||||
* genericBarCid.equals(fooCid) == true
|
||||
*
|
||||
* genericFooCid.equals(genericBarCid) == true
|
||||
* genericBarCid.equals(genericFooCid) == true
|
||||
* </pre>
|
||||
*
|
||||
* @param <T> A template type
|
||||
*/
|
||||
public class ContractId<T> {
|
||||
public final String contractId;
|
||||
|
||||
public ContractId(String contractId) {
|
||||
this.contractId = contractId;
|
||||
}
|
||||
|
||||
public final Value toValue() {
|
||||
return new com.daml.ledger.javaapi.data.ContractId(contractId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || !(
|
||||
getClass().isAssignableFrom(o.getClass()) || o.getClass().isAssignableFrom(getClass()))
|
||||
)
|
||||
return false;
|
||||
ContractId<?> that = (ContractId<?>) o;
|
||||
return contractId.equals(that.contractId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(contractId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ContractId(" + contractId + ')';
|
||||
}
|
||||
}
|
@ -43,4 +43,12 @@ template Foo
|
||||
with
|
||||
owner : Party
|
||||
where
|
||||
signatory owner
|
||||
signatory owner
|
||||
|
||||
data ParametrizedContractId a = ParametricContractId
|
||||
with
|
||||
parametrizedContractId: ContractId a
|
||||
|
||||
data FixedContractId = FixedContractId
|
||||
with
|
||||
fixedContractId: ParametrizedContractId Foo
|
@ -14,6 +14,7 @@ import com.digitalasset.AllGenericTests;
|
||||
OptionalTest.class,
|
||||
MapTest.class,
|
||||
ContractKeysTest.class,
|
||||
ParametrizedContractIdTest.class,
|
||||
})
|
||||
public class AllTests {
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2019 The DAML Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.digitalasset.lf_latest;
|
||||
|
||||
import com.daml.ledger.javaapi.data.Record;
|
||||
import com.daml.ledger.javaapi.data.codegen.ContractId;
|
||||
import com.digitalasset.ledger.api.v1.ValueOuterClass;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.platform.runner.JUnitPlatform;
|
||||
import org.junit.runner.RunWith;
|
||||
import tests.recordtest.FixedContractId;
|
||||
import tests.recordtest.Foo;
|
||||
import tests.recordtest.ParametrizedContractId;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
|
||||
@RunWith(JUnitPlatform.class)
|
||||
public class ParametrizedContractIdTest {
|
||||
|
||||
@Test
|
||||
void contractIdsCanBeParameterized() {
|
||||
ValueOuterClass.Record protoRecord = ValueOuterClass.Record.newBuilder()
|
||||
.addFields(ValueOuterClass.RecordField.newBuilder()
|
||||
.setLabel("fixedContractId")
|
||||
.setValue(ValueOuterClass.Value.newBuilder().setRecord(ValueOuterClass.Record.newBuilder()
|
||||
.addFields(ValueOuterClass.RecordField.newBuilder()
|
||||
.setLabel("parametrizedContractId")
|
||||
.setValue(ValueOuterClass.Value.newBuilder().setContractId("SomeID"))
|
||||
)
|
||||
)
|
||||
)
|
||||
).build();
|
||||
Record dataRecord = Record.fromProto(protoRecord);
|
||||
FixedContractId fromValue = FixedContractId.fromValue(dataRecord);
|
||||
FixedContractId fromConstructor = new FixedContractId(new ParametrizedContractId<>(new Foo.ContractId("SomeID")));
|
||||
FixedContractId fromRoundTrip = FixedContractId.fromValue(fromConstructor.toValue());
|
||||
|
||||
assertEquals(fromValue, fromConstructor);
|
||||
assertEquals(fromConstructor.toValue(), dataRecord);
|
||||
assertEquals(fromConstructor.toValue().toProtoRecord(), protoRecord);
|
||||
assertEquals(fromRoundTrip, fromConstructor);
|
||||
}
|
||||
|
||||
@Test
|
||||
void fixedContractIdIsEqualToParametrizedContractId() {
|
||||
|
||||
Foo.ContractId fixed = new Foo.ContractId("test");
|
||||
ContractId<Foo> parametrized = new ContractId<>("test");
|
||||
|
||||
tests.template1.TestTemplate.ContractId test = new tests.template1.TestTemplate.ContractId("test");
|
||||
|
||||
assertEquals(parametrized, fixed);
|
||||
assertEquals(fixed, parametrized);
|
||||
assertNotEquals(test, fixed);
|
||||
assertNotEquals(fixed, test);
|
||||
}
|
||||
}
|
@ -6,7 +6,8 @@ package com.digitalasset.daml.lf.codegen.backend.java.inner
|
||||
import java.util.Optional
|
||||
|
||||
import com.daml.ledger.javaapi
|
||||
import com.daml.ledger.javaapi.data.{ContractId, CreatedEvent}
|
||||
import com.daml.ledger.javaapi.data.CreatedEvent
|
||||
import com.daml.ledger.javaapi.data.codegen.{ContractId => CodegenContractId}
|
||||
import com.digitalasset.daml.lf.codegen.TypeWithContext
|
||||
import com.digitalasset.daml.lf.codegen.backend.java.ObjectMethods
|
||||
import com.digitalasset.daml.lf.data.Ref.{ChoiceName, PackageId, QualifiedName}
|
||||
@ -301,14 +302,15 @@ private[inner] object TemplateClass extends StrictLogging {
|
||||
val idClassBuilder =
|
||||
TypeSpec
|
||||
.classBuilder("ContractId")
|
||||
.superclass(ParameterizedTypeName
|
||||
.get(ClassName.get(classOf[CodegenContractId[_]]), templateClassName))
|
||||
.addModifiers(Modifier.FINAL, Modifier.PUBLIC, Modifier.STATIC)
|
||||
.addField(ClassName.get(classOf[String]), "contractId", Modifier.PUBLIC, Modifier.FINAL)
|
||||
val constructor =
|
||||
MethodSpec
|
||||
.constructorBuilder()
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.addParameter(ClassName.get(classOf[String]), "contractId")
|
||||
.addStatement("this.contractId = contractId")
|
||||
.addStatement("super(contractId)")
|
||||
.build()
|
||||
idClassBuilder.addMethod(constructor)
|
||||
for ((choiceName, choice) <- choices) {
|
||||
@ -327,19 +329,6 @@ private[inner] object TemplateClass extends StrictLogging {
|
||||
idClassBuilder.addMethod(splatted)
|
||||
}
|
||||
}
|
||||
val toValue = MethodSpec
|
||||
.methodBuilder("toValue")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.returns(classOf[javaapi.data.Value])
|
||||
.addStatement(
|
||||
CodeBlock.of("return new $L(this.contractId)", ClassName.get(classOf[ContractId])))
|
||||
.build()
|
||||
idClassBuilder.addMethod(toValue)
|
||||
|
||||
idClassBuilder.addMethods(ObjectMethods(
|
||||
ClassName.bestGuess("ContractId"),
|
||||
IndexedSeq("contractId"),
|
||||
templateClassName).asJava)
|
||||
idClassBuilder.build()
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ package com.digitalasset.daml.lf.codegen.backend.java
|
||||
import java.util
|
||||
|
||||
import com.daml.ledger.javaapi
|
||||
import com.daml.ledger.javaapi.data.codegen.ContractId
|
||||
import com.daml.ledger.javaapi.data.{DamlList, DamlMap, DamlOptional}
|
||||
import com.digitalasset.daml.lf.data.ImmArray.ImmArraySeq
|
||||
import com.digitalasset.daml.lf.data.Ref.{Identifier, PackageId, QualifiedName}
|
||||
@ -59,7 +60,9 @@ package object inner {
|
||||
case TypePrim(PrimTypeContractId, ImmArraySeq(templateType)) =>
|
||||
toJavaTypeName(templateType, packagePrefixes) match {
|
||||
case templateClass: ClassName => templateClass.nestedClass("ContractId")
|
||||
case _ => sys.error("should not happen")
|
||||
case typeVariableName: TypeVariableName =>
|
||||
ParameterizedTypeName.get(ClassName.get(classOf[ContractId[_]]), typeVariableName)
|
||||
case unexpected => sys.error(s"Unexpected type [$unexpected] for DAML type [$damlType]")
|
||||
}
|
||||
case TypePrim(PrimTypeList, typeParameters) =>
|
||||
ParameterizedTypeName
|
||||
|
@ -26,3 +26,5 @@ HEAD — ongoing
|
||||
+ [DAML Studio] The VSCode extension now has a configuration field for
|
||||
passing extra arguments to ``damlc ide``.
|
||||
+ [Sandbox] Fixed a bug that caused the reset service to hang for 10 seconds. See issue `#2549 <https://github.com/digital-asset/daml/issues/2549>`__.
|
||||
+ [Java Bindings] The Java Codegen now supports parametrized ContractIds.
|
||||
See `#2258 <https://github.com/digital-asset/daml/issues/2258>`__.
|
||||
|
Loading…
Reference in New Issue
Block a user