Skip to content

Commit c461ac4

Browse files
committed
Squashed commit of the following:
commit 17a2ab1 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 16:30:45 2020 -0800 Fixed indentation commit 9094055 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 16:03:51 2020 -0800 revising from feedback commit d350821 Merge: 9054c23 3acb7e7 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 15:56:55 2020 -0800 Merge branch 'master' of github.com:PolymerLabs/arcs into s2k-schemas commit 3acb7e7 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 15:56:42 2020 -0800 XXS CL to add a hash field to the Schema proto (PolymerLabs#4752) commit 9054c23 Merge: d15008e 337b7b2 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 15:55:27 2020 -0800 Merge branch 'master' of github.com:PolymerLabs/arcs into s2k-schemas commit 337b7b2 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 15:55:06 2020 -0800 recipe2plan 2/n: Validate Handles, Tests (PolymerLabs#4834) * creating structure of ts r2p script * Created fast CLI rapper for r2p script * WIP figuring out ways to resolve a recipe * fix sp * Passing lint, still WIP * Build macros for recipe2plan work * Lightweight iteration on recipe2plan, stubbed out tests * Revised method to find corresponding create handles * Added type info * Added method to get all handles to manifest + get all handles by Id * fix: no flatMap * - currently, fails since it cannot find associated stores for handles. * uncleaned, but working recipe resolution * Cleaned up for r2p, pt 1 * stubbed out second test (short, short) * Squashed commit of the following: commit 62dcc57 Author: Alex Rosengarten <[email protected]> Date: Mon Mar 2 14:38:14 2020 -0800 Fixed test, added TODO * updates to test, can't get two to fail * Squashed commit of the following: commit bede8d9 Author: Alex Rosengarten <[email protected]> Date: Mon Mar 2 14:52:02 2020 -0800 Fixed build rule, simplified runtime commit 62dcc57 Author: Alex Rosengarten <[email protected]> Date: Mon Mar 2 14:38:14 2020 -0800 Fixed test, added TODO * can't get test to fail... hmm... * Squashed commit of the following: commit f6df54a Author: Alex Rosengarten <[email protected]> Date: Mon Mar 2 15:44:32 2020 -0800 tools/sigh lint commit bede8d9 Author: Alex Rosengarten <[email protected]> Date: Mon Mar 2 14:52:02 2020 -0800 Fixed build rule, simplified runtime commit 62dcc57 Author: Alex Rosengarten <[email protected]> Date: Mon Mar 2 14:38:14 2020 -0800 Fixed test, added TODO * adjusting recipe copying to include triggers * Revert "adjusting recipe copying to include triggers" This reverts commit 9bc3734 * four tests complete * Added test, fixed minor async issue * Squashed commit of the following: commit 4b05a28 Merge: f4c1d26 99000c2 Author: Alex Rosengarten <[email protected]> Date: Tue Mar 3 11:18:14 2020 -0800 Merge branch 'r2p' of github.com:alxrsngrtn/arcs into r2p commit f4c1d26 Merge: 140111f 5c6310d Author: Alex Rosengarten <[email protected]> Date: Tue Mar 3 11:14:35 2020 -0800 Merge branch 'master' of github.com:PolymerLabs/arcs into r2p Fixed lint errors commit 99000c2 Merge: 140111f 5c6310d Author: Alex Rosengarten <[email protected]> Date: Tue Mar 3 11:14:35 2020 -0800 Merge branch 'master' of github.com:PolymerLabs/arcs into r2p Fixed lint errors commit 140111f Author: Alex Rosengarten <[email protected]> Date: Tue Mar 3 11:08:12 2020 -0800 Removed flatMap, added TODOs and link to GH issue commit 5c6310d Author: jblebrun <[email protected]> Date: Tue Mar 3 11:02:34 2020 -0800 Simplify service test pattern (PolymerLabs#4817) * Make a simple test lifecycle registry, instead of creating empty testactivity * Remove use of `runBlockingTest`: according to Kotlin/kotlinx.coroutines#1222, if the test results in coroutines being finished on other threads, it's possible to receive "This job has not yet completed" exceptions, even though the jobs were properly terminated. Since we don't need the delay-skipping properties of `runBlockingTest`, I think it's OK to use `runBlocking`. commit 472bc84 Author: Alex Rosengarten <[email protected]> Date: Tue Mar 3 10:27:56 2020 -0800 Improved build rules commit ca1ebf8 Author: Alex Rosengarten <[email protected]> Date: Tue Mar 3 10:17:13 2020 -0800 Impl suggestsions for r2p commit b5578ea Author: Jason Feinstein <[email protected]> Date: Tue Mar 3 09:54:17 2020 -0800 Add tests for dereferencing references to the HandleManagerTest(s) (PolymerLabs#4816) * Add dereferencing tests to the android handle manager test. * Add dereferencing tests to core HandleManager. commit a695797 Author: Jason Feinstein <[email protected]> Date: Mon Mar 2 18:14:07 2020 -0800 Create RawEntityDereferencerTest, storage Reference-> CrdtEntity.Reference (PolymerLabs#4812) * Create RawEntityDereferencerTest, make storage Reference implement CrdtEntity.Reference. Also: Create ParcelableReference. * Add dep. Also, apparently read/writeBoolean is Q-only. * Just write null if there is no version map. * Just write null if there is no version map. commit ba7a107 Author: Gogul Balakrishnan <[email protected]> Date: Mon Mar 2 17:51:35 2020 -0800 Add a decoder for PrimitiveTypeProto and an option to disable android constraints in BUILD. (PolymerLabs#4793) commit f6df54a Author: Alex Rosengarten <[email protected]> Date: Mon Mar 2 15:44:32 2020 -0800 tools/sigh lint commit bede8d9 Author: Alex Rosengarten <[email protected]> Date: Mon Mar 2 14:52:02 2020 -0800 Fixed build rule, simplified runtime commit 62dcc57 Author: Alex Rosengarten <[email protected]> Date: Mon Mar 2 14:38:14 2020 -0800 Fixed test, added TODO * fix ineq * existing tests passing * Updating invalid type test * Squashed commit of the following: commit b3d92d0 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 12:17:17 2020 -0800 updated test name commit ba7884b Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 12:16:09 2020 -0800 nested unit tests commit ef36fdf Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 12:15:00 2020 -0800 renamed to tryResolve commit 5703f02 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 12:07:18 2020 -0800 rm generator commit 658cb1a Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 12:01:54 2020 -0800 implemented more review suggestions commit 0056ee3 Merge: cae89c3 0f0f82a Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 11:54:23 2020 -0800 Merge branch 'master' of github.com:PolymerLabs/arcs into r2p commit 0f0f82a Author: Maria Mandlis <[email protected]> Date: Wed Mar 4 09:33:29 2020 -0800 add queryable capability (PolymerLabs#4794) commit d032c75 Author: Maria Mandlis <[email protected]> Date: Wed Mar 4 09:23:07 2020 -0800 add creatimeTimestamp to entities (kt) (PolymerLabs#4823) commit 30267fc Author: jblebrun <[email protected]> Date: Wed Mar 4 09:09:39 2020 -0800 Remove some unused deps (PolymerLabs#4831) commit c519181 Author: Cameron Silvestrini <[email protected]> Date: Wed Mar 4 17:14:07 2020 +1100 Increase size of DatabaseImplTest to medium (PolymerLabs#4827) * Increase size of DatabaseImplTest to medium Was a bit flaky. * Check flakiness * Revert presubmit tweak commit fa621c6 Author: jblebrun <[email protected]> Date: Tue Mar 3 22:05:07 2020 -0800 Fix a race condition when setting up `ServiceStore` message channel (PolymerLabs#4826) This seems to be the cause of the flakiness in `AndroidAllocatorTest` and `AndroidHandleManagerTest` (PolymerLabs#4781) commit 78bf4f0 Author: Gogul Balakrishnan <[email protected]> Date: Tue Mar 3 18:00:49 2020 -0800 Utility to convert type proto to field type (if possible). (PolymerLabs#4814) commit cae89c3 Merge: 0360752 e587539 Author: Alex Rosengarten <[email protected]> Date: Tue Mar 3 15:50:34 2020 -0800 Merge branch 'master' of github.com:PolymerLabs/arcs into r2p commit e587539 Author: jblebrun <[email protected]> Date: Tue Mar 3 15:07:16 2020 -0800 Apply simplified test pattern tests in `arcs.android.host` (PolymerLabs#4821) As in 5c6310d commit 1af1aac Author: Joshua Pratt <[email protected]> Date: Wed Mar 4 09:48:15 2020 +1100 Multinomials (PolymerLabs#4804) * multinomial * added tests * making constant readable again * reindent * added multivariate rearrangement tests * updated comment * pr comments: Co-authored-by: Ragav Sachdeva <[email protected]> commit 0360752 Author: Alex Rosengarten <[email protected]> Date: Tue Mar 3 11:42:31 2020 -0800 fix, bad comparison op commit 4b05a28 Merge: f4c1d26 99000c2 Author: Alex Rosengarten <[email protected]> Date: Tue Mar 3 11:18:14 2020 -0800 Merge branch 'r2p' of github.com:alxrsngrtn/arcs into r2p commit f4c1d26 Merge: 140111f 5c6310d Author: Alex Rosengarten <[email protected]> Date: Tue Mar 3 11:14:35 2020 -0800 Merge branch 'master' of github.com:PolymerLabs/arcs into r2p Fixed lint errors commit 99000c2 Merge: 140111f 5c6310d Author: Alex Rosengarten <[email protected]> Date: Tue Mar 3 11:14:35 2020 -0800 Merge branch 'master' of github.com:PolymerLabs/arcs into r2p Fixed lint errors commit 140111f Author: Alex Rosengarten <[email protected]> Date: Tue Mar 3 11:08:12 2020 -0800 Removed flatMap, added TODOs and link to GH issue commit 5c6310d Author: jblebrun <[email protected]> Date: Tue Mar 3 11:02:34 2020 -0800 Simplify service test pattern (PolymerLabs#4817) * Make a simple test lifecycle registry, instead of creating empty testactivity * Remove use of `runBlockingTest`: according to Kotlin/kotlinx.coroutines#1222, if the test results in coroutines being finished on other threads, it's possible to receive "This job has not yet completed" exceptions, even though the jobs were properly terminated. Since we don't need the delay-skipping properties of `runBlockingTest`, I think it's OK to use `runBlocking`. commit 472bc84 Author: Alex Rosengarten <[email protected]> Date: Tue Mar 3 10:27:56 2020 -0800 Improved build rules commit ca1ebf8 Author: Alex Rosengarten <[email protected]> Date: Tue Mar 3 10:17:13 2020 -0800 Impl suggestsions for r2p commit b5578ea Author: Jason Feinstein <[email protected]> Date: Tue Mar 3 09:54:17 2020 -0800 Add tests for dereferencing references to the HandleManagerTest(s) (PolymerLabs#4816) * Add dereferencing tests to the android handle manager test. * Add dereferencing tests to core HandleManager. commit a695797 Author: Jason Feinstein <[email protected]> Date: Mon Mar 2 18:14:07 2020 -0800 Create RawEntityDereferencerTest, storage Reference-> CrdtEntity.Reference (PolymerLabs#4812) * Create RawEntityDereferencerTest, make storage Reference implement CrdtEntity.Reference. Also: Create ParcelableReference. * Add dep. Also, apparently read/writeBoolean is Q-only. * Just write null if there is no version map. * Just write null if there is no version map. commit ba7a107 Author: Gogul Balakrishnan <[email protected]> Date: Mon Mar 2 17:51:35 2020 -0800 Add a decoder for PrimitiveTypeProto and an option to disable android constraints in BUILD. (PolymerLabs#4793) commit f6df54a Author: Alex Rosengarten <[email protected]> Date: Mon Mar 2 15:44:32 2020 -0800 tools/sigh lint commit bede8d9 Author: Alex Rosengarten <[email protected]> Date: Mon Mar 2 14:52:02 2020 -0800 Fixed build rule, simplified runtime commit 62dcc57 Author: Alex Rosengarten <[email protected]> Date: Mon Mar 2 14:38:14 2020 -0800 Fixed test, added TODO * fixed nested tests * rewording, reorganizing * assert more ergonomic commit 298fdcc Author: Maria Mandlis <[email protected]> Date: Wed Mar 4 15:29:37 2020 -0800 update wasm readme (PolymerLabs#4832) commit d15008e Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 15:11:14 2020 -0800 fixed build commit bbfc3d2 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 15:04:11 2020 -0800 EntitySpec Interface can return a schema commit 3b75c34 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 14:09:36 2020 -0800 ktlint fix commit 506457e Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 13:59:46 2020 -0800 addField arguments are more ergonomic commit 579b2e6 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 13:45:28 2020 -0800 grooming schema registry commit 3cb8023 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 11:39:30 2020 -0800 rm unused field commit 1cff99f Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 11:38:32 2020 -0800 rm import commit 855401c Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 11:31:14 2020 -0800 no difference w/ wasm golden commit 552e9ad Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 11:26:43 2020 -0800 Added test for mapOf commit 1430907 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 11:07:15 2020 -0800 sigh lint commit 9c22195 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 11:06:50 2020 -0800 minor adjustments commit 74ae770 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 10:58:20 2020 -0800 Improved shape of registry commit f69f99b Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 10:32:31 2020 -0800 excluding wasm from generation commit dcefb16 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 10:13:46 2020 -0800 Generation adds to schema registry commit f3b9ae5 Author: Alex Rosengarten <[email protected]> Date: Wed Mar 4 07:57:15 2020 -0800 packaging in a schema registry commit 2ce6da2 Author: Alex Rosengarten <[email protected]> Date: Tue Mar 3 22:30:39 2020 -0800 First iteration of schema gen on entities
1 parent aff420c commit c461ac4

13 files changed

+330
-41
lines changed

java/arcs/core/data/SchemaRegistry.kt

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2020 Google LLC.
3+
*
4+
* This code may only be used under the BSD style license found at
5+
* http://polymer.github.io/LICENSE.txt
6+
*
7+
* Code distributed by Google as part of this project is also subject to an additional IP rights
8+
* grant found at
9+
* http://polymer.github.io/PATENTS.txt
10+
*/
11+
package arcs.core.data
12+
13+
typealias SchemaHash = String
14+
15+
/**
16+
* A registry for generated [Schema]s.
17+
*/
18+
object SchemaRegistry {
19+
private val schemas = mutableMapOf<SchemaHash, Schema>()
20+
21+
/** Store a [Schema] in the registry. */
22+
fun register(schema: Schema) {
23+
schemas[schema.hash] = schema
24+
}
25+
26+
/** Given a [SchemaHash], return the [Schema] for that hash, if it exists. */
27+
operator fun get(hash: SchemaHash) = schemas[hash]
28+
}

java/arcs/core/data/proto/recipe.proto

+1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ message TypeVariableProto {
121121
message SchemaProto {
122122
repeated string names = 1;
123123
map<string, TypeProto> fields = 2;
124+
string hash = 3;
124125
}
125126

126127
enum OPERATOR {

java/arcs/core/storage/api/BUILD

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ arcs_kt_library(
1212
srcs = glob(["*.kt"]),
1313
deps = [
1414
"//java/arcs/core/common",
15-
"//java/arcs/core/data:rawentity",
15+
"//java/arcs/core/data",
1616
"//java/arcs/core/data/util:data-util",
1717
"//third_party/kotlin/kotlinx_coroutines",
1818
],

java/arcs/core/storage/api/Entity.kt

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ package arcs.core.storage.api
1313

1414
import arcs.core.common.Referencable
1515
import arcs.core.data.RawEntity
16+
import arcs.core.data.Schema
1617
import arcs.core.data.util.ReferencablePrimitive
1718
import kotlin.IllegalArgumentException
1819
import kotlin.reflect.KClass
@@ -38,6 +39,9 @@ interface EntitySpec<T : Entity> {
3839
* TODO: replace this with kotlinx.serialization
3940
*/
4041
fun deserialize(data: RawEntity): T
42+
43+
/** Returns the corresponding [Schema] for the specified [Entity]. */
44+
fun schema(): Schema
4145
}
4246

4347
/**

src/tools/schema2base.ts

+17-3
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,16 @@ import {Runtime} from '../runtime/runtime.js';
1515
import {SchemaGraph, SchemaNode} from './schema2graph.js';
1616
import {ParticleSpec} from '../runtime/particle-spec.js';
1717

18+
export type AddFieldOptions = Readonly<{
19+
field: string;
20+
typeChar: string;
21+
isOptional?: boolean;
22+
refClassName?: string;
23+
isCollection?: boolean;
24+
}>;
25+
1826
export interface ClassGenerator {
19-
addField(field: string, typeChar: string, isOptional: boolean, refClassName: string|null): void;
27+
addField(opts: AddFieldOptions): void;
2028
generate(schemaHash: string, fieldCount: number): string;
2129
}
2230

@@ -78,14 +86,20 @@ export abstract class Schema2Base {
7886
for (const [field, descriptor] of fields) {
7987
if (descriptor.kind === 'schema-primitive') {
8088
if (['Text', 'URL', 'Number', 'Boolean'].includes(descriptor.type)) {
81-
generator.addField(field, descriptor.type[0], false, null);
89+
generator.addField({field, typeChar: descriptor.type[0]});
8290
} else {
8391
throw new Error(`Schema type '${descriptor.type}' for field '${field}' is not supported`);
8492
}
8593
} else if (descriptor.kind === 'schema-reference') {
86-
generator.addField(field, 'R', false, node.refs.get(field).name);
94+
generator.addField({field, typeChar: 'R', refClassName: node.refs.get(field).name});
8795
} else if (descriptor.kind === 'schema-collection' && descriptor.schema.kind === 'schema-reference') {
8896
// TODO: support collections of references
97+
} else if (descriptor.kind === 'schema-collection') {
98+
const schema = descriptor.schema;
99+
if (!['Text', 'URL', 'Number', 'Boolean'].includes(schema.type)) {
100+
throw new Error(`Schema type '${schema.type}' for field '${field}' is not supported`);
101+
}
102+
generator.addField({field, typeChar: schema.type[0], isCollection: true});
89103
} else {
90104
throw new Error(`Schema kind '${descriptor.kind}' for field '${field}' is not supported`);
91105
}

src/tools/schema2cpp.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* subject to an additional IP rights grant found at
88
* http://polymer.github.io/PATENTS.txt
99
*/
10-
import {Schema2Base, ClassGenerator} from './schema2base.js';
10+
import {Schema2Base, ClassGenerator, AddFieldOptions} from './schema2base.js';
1111
import {SchemaNode} from './schema2graph.js';
1212
import {ParticleSpec} from '../runtime/particle-spec.js';
1313
import {Type} from '../runtime/type.js';
@@ -113,7 +113,7 @@ class CppGenerator implements ClassGenerator {
113113

114114
constructor(readonly node: SchemaNode, readonly namespace: string) {}
115115

116-
addField(field: string, typeChar: string, isOptional: boolean, refClassName: string|null) {
116+
addField({field, typeChar, refClassName, isOptional = false, isCollection = false}: AddFieldOptions) {
117117
const fixed = fixName(field);
118118
const valid = `${field}_valid_`;
119119
let {type, defaultVal, isString} = typeMap[typeChar];

src/tools/schema2kotlin.ts

+68-8
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* subject to an additional IP rights grant found at
88
* http://polymer.github.io/PATENTS.txt
99
*/
10-
import {Schema2Base, ClassGenerator} from './schema2base.js';
10+
import {Schema2Base, ClassGenerator, AddFieldOptions} from './schema2base.js';
1111
import {SchemaNode} from './schema2graph.js';
1212
import {ParticleSpec} from '../runtime/particle-spec.js';
1313
import minimist from 'minimist';
@@ -28,10 +28,10 @@ const keywords = [
2828
];
2929

3030
const typeMap = {
31-
'T': {type: 'String', decodeFn: 'decodeText()', defaultVal: `""`},
32-
'U': {type: 'String', decodeFn: 'decodeText()', defaultVal: `""`},
33-
'N': {type: 'Double', decodeFn: 'decodeNum()', defaultVal: '0.0'},
34-
'B': {type: 'Boolean', decodeFn: 'decodeBool()', defaultVal: 'false'},
31+
'T': {type: 'String', decodeFn: 'decodeText()', defaultVal: `""`, schemaType: 'FieldType.Text'},
32+
'U': {type: 'String', decodeFn: 'decodeText()', defaultVal: `""`, schemaType: 'FieldType.Text'},
33+
'N': {type: 'Double', decodeFn: 'decodeNum()', defaultVal: '0.0', schemaType: 'FieldType.Number'},
34+
'B': {type: 'Boolean', decodeFn: 'decodeBool()', defaultVal: 'false', schemaType: 'FieldType.Boolean'},
3535
};
3636

3737
export class Schema2Kotlin extends Schema2Base {
@@ -54,7 +54,14 @@ package ${this.scope}
5454
// Current implementation doesn't support references or optional field detection
5555
5656
import arcs.sdk.*
57-
${this.opts.wasm ? 'import arcs.sdk.wasm.*' : 'import arcs.core.storage.api.toPrimitiveValue\nimport arcs.core.data.RawEntity\nimport arcs.core.data.util.toReferencable\nimport arcs.core.data.util.ReferencablePrimitive'}
57+
${this.opts.wasm ?
58+
`import arcs.sdk.wasm.*` :
59+
`\
60+
import arcs.sdk.Entity
61+
import arcs.core.data.*
62+
import arcs.core.data.util.toReferencable
63+
import arcs.core.data.util.ReferencablePrimitive
64+
import arcs.core.storage.api.toPrimitiveValue`}
5865
`;
5966
}
6067

@@ -130,7 +137,7 @@ abstract class Abstract${particleName} : ${this.opts.wasm ? 'WasmParticleImpl' :
130137
}
131138
}
132139

133-
class KotlinGenerator implements ClassGenerator {
140+
export class KotlinGenerator implements ClassGenerator {
134141
fields: string[] = [];
135142
fieldVals: string[] = [];
136143
setFields: string[] = [];
@@ -144,11 +151,13 @@ class KotlinGenerator implements ClassGenerator {
144151
fieldSerializes: string[] = [];
145152
fieldDeserializes: string[] = [];
146153
fieldsForToString: string[] = [];
154+
singletonSchemaFields: string[] = [];
155+
collectionSchemaFields: string[] = [];
147156

148157
constructor(readonly node: SchemaNode, private readonly opts: minimist.ParsedArgs) {}
149158

150159
// TODO: allow optional fields in kotlin
151-
addField(field: string, typeChar: string, isOptional: boolean, refClassName: string|null) {
160+
addField({field, typeChar, refClassName, isOptional = false, isCollection = false}: AddFieldOptions) {
152161
// TODO: support reference types in kotlin
153162
if (typeChar === 'R') return;
154163

@@ -181,6 +190,46 @@ class KotlinGenerator implements ClassGenerator {
181190
this.fieldSerializes.push(`"${field}" to ${fixed}.toReferencable()`);
182191
this.fieldDeserializes.push(`${fixed} = data.singletons["${fixed}"].toPrimitiveValue(${type}::class, ${defaultVal})`);
183192
this.fieldsForToString.push(`${fixed} = $${fixed}`);
193+
if (isCollection) {
194+
this.collectionSchemaFields.push(`"${field}" to ${typeMap[typeChar].schemaType}`);
195+
} else {
196+
this.singletonSchemaFields.push(`"${field}" to ${typeMap[typeChar].schemaType}`);
197+
}
198+
}
199+
200+
mapOf(items: string[]): string {
201+
switch (items.length) {
202+
case 0:
203+
return `emptyMap()`;
204+
case 1:
205+
return `mapOf(${items[0]})`;
206+
default:
207+
return `\
208+
mapOf(
209+
${this.leftPad(items.join(',\n'), 4)}
210+
)`;
211+
}
212+
213+
}
214+
215+
createSchema(schemaHash: string): string {
216+
const schemaNames = this.node.schema.names.map(n => `SchemaName("${n}")`);
217+
return `\
218+
Schema(
219+
listOf(${schemaNames.join(',\n' + ' '.repeat(8))}),
220+
SchemaFields(
221+
singletons = ${this.leftPad(this.mapOf(this.singletonSchemaFields), 8, true)},
222+
collections = ${this.leftPad(this.mapOf(this.collectionSchemaFields), 8, true)}
223+
),
224+
"${schemaHash}"
225+
)`;
226+
}
227+
228+
leftPad(input: string, indent: number, skipFirst: boolean = false) {
229+
return input
230+
.split('\n')
231+
.map((line: string, idx: number) => (idx === 0 && skipFirst) ? line : ' '.repeat(indent) + line)
232+
.join('\n');
184233
}
185234

186235
generate(schemaHash: string, fieldCount: number): string {
@@ -256,7 +305,18 @@ ${this.opts.wasm ? `
256305
}
257306
258307
class ${name}_Spec() : ${this.getType('EntitySpec')}<${name}> {
308+
${this.opts.wasm ? '' : `\
259309
310+
companion object {
311+
val schema = ${this.leftPad(this.createSchema(schemaHash), 8, true)}
312+
313+
init {
314+
SchemaRegistry.register(schema)
315+
}
316+
}
317+
318+
override fun schema() = schema
319+
`}
260320
override fun create() = ${name}()
261321
${!this.opts.wasm ? `
262322
override fun deserialize(data: RawEntity): ${name} {

src/tools/storage-key-recipe-resolver.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,14 @@ export class StorageKeyRecipeResolver {
3232
/**
3333
* Produces resolved recipes with storage keys.
3434
*
35-
* TODO(alxr): Apply to long-running recipes appropriately.
35+
* TODO(#4818) Add passes to assign storage keys.
3636
* @throws Error if recipe fails to resolve on first or second pass.
3737
* @yields Resolved recipes with storage keys
3838
*/
3939
async resolve(): Promise<Recipe[]> {
4040
const recipes = [];
4141
for (const recipe of this.runtime.context.allRecipes) {
42+
this.validateHandles(recipe);
4243
const arc = this.runtime.newArc(this.getArcId(recipe), ramDiskStorageKeyPrefixForTest());
4344
const opts = {errors: new Map<Recipe | RecipeComponent, string>()};
4445
const resolved = await this.tryResolve(recipe, arc, opts);
@@ -63,7 +64,8 @@ export class StorageKeyRecipeResolver {
6364
*/
6465
async tryResolve(recipe: Recipe, arc: Arc, opts?: IsValidOptions): Promise<Recipe | null> {
6566
const normalized = recipe.clone();
66-
normalized.normalize();
67+
const successful = normalized.normalize(opts);
68+
if (!successful) return null;
6769
if (normalized.isResolved()) return normalized;
6870

6971
return await (new RecipeResolver(arc).resolve(recipe, opts));
@@ -97,14 +99,14 @@ export class StorageKeyRecipeResolver {
9799
}
98100

99101
/**
100-
* TODO(#4818) method to match `map` and `copy` fated handles with storage keys from `create` handles.
102+
* Checks that handles are existent, disambiguous, and initiated by a long-running arc.
101103
*
102-
* @throws when a mapped handle is associated with too many stores (ambiguous mapping).
103-
* @throws when a mapped handle isn't associated with any store (no matches found).
104-
* @throws when handle is mapped to a handle from an ephemeral recipe.
104+
* @throws when a map or copy handle is associated with too many stores (ambiguous mapping).
105+
* @throws when a map or copy handle isn't associated with any store (no matches found).
106+
* @throws when a map or copy handle is associated with a handle from an ephemeral recipe.
105107
* @param recipe long-running or ephemeral recipe
106108
*/
107-
matchKeysToHandles(recipe: Recipe) {
109+
validateHandles(recipe: Recipe) {
108110
recipe.handles
109111
.filter(h => h.fate === 'map' || h.fate === 'copy')
110112
.forEach(handle => {
@@ -121,8 +123,6 @@ export class StorageKeyRecipeResolver {
121123
if (!match.recipe.isLongRunning) {
122124
throw Error(`Handle ${handle.localName} mapped to ephemeral handle ${match.localName}.`);
123125
}
124-
125-
handle.storageKey = match.storageKey;
126126
});
127127
}
128128
}

src/tools/tests/goldens/generated-schemas.jvm.kt

+42-2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ package arcs.sdk
99
// Current implementation doesn't support references or optional field detection
1010

1111
import arcs.sdk.*
12-
import arcs.core.storage.api.toPrimitiveValue
13-
import arcs.core.data.RawEntity
12+
import arcs.sdk.Entity
13+
import arcs.core.data.*
1414
import arcs.core.data.util.toReferencable
1515
import arcs.core.data.util.ReferencablePrimitive
16+
import arcs.core.storage.api.toPrimitiveValue
1617

1718
class GoldInternal1() : Entity {
1819

@@ -71,6 +72,23 @@ class GoldInternal1() : Entity {
7172

7273
class GoldInternal1_Spec() : EntitySpec<GoldInternal1> {
7374

75+
companion object {
76+
val schema = Schema(
77+
listOf(),
78+
SchemaFields(
79+
singletons = mapOf("val" to FieldType.Text),
80+
collections = emptyMap()
81+
),
82+
"485712110d89359a3e539dac987329cd2649d889"
83+
)
84+
85+
init {
86+
SchemaRegistry.register(schema)
87+
}
88+
}
89+
90+
override fun schema() = schema
91+
7492
override fun create() = GoldInternal1()
7593

7694
override fun deserialize(data: RawEntity): GoldInternal1 {
@@ -179,6 +197,28 @@ class Gold_Data() : Entity {
179197

180198
class Gold_Data_Spec() : EntitySpec<Gold_Data> {
181199

200+
companion object {
201+
val schema = Schema(
202+
listOf(),
203+
SchemaFields(
204+
singletons = mapOf(
205+
"num" to FieldType.Number,
206+
"txt" to FieldType.Text,
207+
"lnk" to FieldType.Text,
208+
"flg" to FieldType.Boolean
209+
),
210+
collections = emptyMap()
211+
),
212+
"d8058d336e472da47b289eafb39733f77eadb111"
213+
)
214+
215+
init {
216+
SchemaRegistry.register(schema)
217+
}
218+
}
219+
220+
override fun schema() = schema
221+
182222
override fun create() = Gold_Data()
183223

184224
override fun deserialize(data: RawEntity): Gold_Data {

0 commit comments

Comments
 (0)