1
1
/*
2
- * Copyright 2017-2024 ObjectBox Ltd. All rights reserved.
2
+ * Copyright 2017-2025 ObjectBox Ltd. All rights reserved.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
34
34
import io .objectbox .model .ModelProperty ;
35
35
import io .objectbox .model .ModelRelation ;
36
36
37
- // Remember: IdUid is a struct, not a table, and thus must be inlined
38
- @ SuppressWarnings ("WeakerAccess,UnusedReturnValue, unused" )
37
+ // To learn how to use the FlatBuffers API see https://flatbuffers.dev/tutorial/
38
+ // Note: IdUid is a struct, not a table, and thus must be inlined
39
+
40
+ /**
41
+ * Builds a flatbuffer representation of the database model to be passed when opening a store.
42
+ * <p>
43
+ * This is an internal API that should only be called by the generated MyObjectBox code.
44
+ */
39
45
@ Internal
40
46
public class ModelBuilder {
41
47
private static final int MODEL_VERSION = 2 ;
42
48
43
- final FlatBufferBuilder fbb = new FlatBufferBuilder ();
44
- final List <Integer > entityOffsets = new ArrayList <>();
49
+ private final FlatBufferBuilder fbb = new FlatBufferBuilder ();
50
+ private final List <Integer > entityOffsets = new ArrayList <>();
51
+
52
+ private long version = 1 ;
53
+
54
+ private Integer lastEntityId ;
55
+ private Long lastEntityUid ;
56
+
57
+ private Integer lastIndexId ;
58
+ private Long lastIndexUid ;
59
+
60
+ private Integer lastRelationId ;
61
+ private Long lastRelationUid ;
62
+
63
+ /**
64
+ * Base class for builders.
65
+ * <p>
66
+ * Methods adding properties to be used by {@link #createFlatBufferTable(FlatBufferBuilder)} should call
67
+ * {@link #checkNotFinished()}.
68
+ * <p>
69
+ * The last call should be {@link #finish()}.
70
+ */
71
+ abstract static class PartBuilder {
72
+
73
+ private final FlatBufferBuilder fbb ;
74
+ private boolean finished ;
75
+
76
+ PartBuilder (FlatBufferBuilder fbb ) {
77
+ this .fbb = fbb ;
78
+ }
45
79
46
- long version = 1 ;
80
+ FlatBufferBuilder getFbb () {
81
+ return fbb ;
82
+ }
47
83
48
- Integer lastEntityId ;
49
- Long lastEntityUid ;
84
+ void checkNotFinished () {
85
+ if (finished ) {
86
+ throw new IllegalStateException ("Already finished" );
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Marks this as finished and returns {@link #createFlatBufferTable(FlatBufferBuilder)}.
92
+ */
93
+ public final int finish () {
94
+ checkNotFinished ();
95
+ finished = true ;
96
+ return createFlatBufferTable (getFbb ());
97
+ }
50
98
51
- Integer lastIndexId ;
52
- Long lastIndexUid ;
99
+ /**
100
+ * Creates a flatbuffer table using the given builder and returns its offset.
101
+ */
102
+ public abstract int createFlatBufferTable (FlatBufferBuilder fbb );
103
+ }
53
104
54
- Integer lastRelationId ;
55
- Long lastRelationUid ;
105
+ public static class PropertyBuilder extends PartBuilder {
56
106
57
- public class PropertyBuilder {
58
107
private final int type ;
59
108
private final int virtualTargetOffset ;
60
109
private final int propertyNameOffset ;
61
110
private final int targetEntityOffset ;
62
111
63
112
private int secondaryNameOffset ;
64
- boolean finished ;
65
113
private int flags ;
66
114
private int id ;
67
115
private long uid ;
@@ -71,7 +119,9 @@ public class PropertyBuilder {
71
119
private int externalPropertyType ;
72
120
private int hnswParamsOffset ;
73
121
74
- PropertyBuilder (String name , @ Nullable String targetEntityName , @ Nullable String virtualTarget , int type ) {
122
+ private PropertyBuilder (FlatBufferBuilder fbb , String name , @ Nullable String targetEntityName ,
123
+ @ Nullable String virtualTarget , int type ) {
124
+ super (fbb );
75
125
this .type = type ;
76
126
propertyNameOffset = fbb .createString (name );
77
127
targetEntityOffset = targetEntityName != null ? fbb .createString (targetEntityName ) : 0 ;
@@ -129,6 +179,7 @@ public PropertyBuilder hnswParams(long dimensions,
129
179
@ Nullable Float reparationBacklinkProbability ,
130
180
@ Nullable Long vectorCacheHintSizeKb ) {
131
181
checkNotFinished ();
182
+ FlatBufferBuilder fbb = getFbb ();
132
183
HnswParams .startHnswParams (fbb );
133
184
HnswParams .addDimensions (fbb , dimensions );
134
185
if (neighborsPerNode != null ) {
@@ -161,19 +212,12 @@ public PropertyBuilder flags(int flags) {
161
212
162
213
public PropertyBuilder secondaryName (String secondaryName ) {
163
214
checkNotFinished ();
164
- secondaryNameOffset = fbb .createString (secondaryName );
215
+ secondaryNameOffset = getFbb () .createString (secondaryName );
165
216
return this ;
166
217
}
167
218
168
- private void checkNotFinished () {
169
- if (finished ) {
170
- throw new IllegalStateException ("Already finished" );
171
- }
172
- }
173
-
174
- public int finish () {
175
- checkNotFinished ();
176
- finished = true ;
219
+ @ Override
220
+ public int createFlatBufferTable (FlatBufferBuilder fbb ) {
177
221
ModelProperty .startModelProperty (fbb );
178
222
ModelProperty .addName (fbb , propertyNameOffset );
179
223
if (targetEntityOffset != 0 ) {
@@ -210,7 +254,41 @@ public int finish() {
210
254
}
211
255
}
212
256
213
- public class EntityBuilder {
257
+ public static class RelationBuilder extends PartBuilder {
258
+
259
+ private final String name ;
260
+ private final int relationId ;
261
+ private final long relationUid ;
262
+ private final int targetEntityId ;
263
+ private final long targetEntityUid ;
264
+
265
+ private RelationBuilder (FlatBufferBuilder fbb , String name , int relationId , long relationUid ,
266
+ int targetEntityId , long targetEntityUid ) {
267
+ super (fbb );
268
+ this .name = name ;
269
+ this .relationId = relationId ;
270
+ this .relationUid = relationUid ;
271
+ this .targetEntityId = targetEntityId ;
272
+ this .targetEntityUid = targetEntityUid ;
273
+ }
274
+
275
+ @ Override
276
+ public int createFlatBufferTable (FlatBufferBuilder fbb ) {
277
+ int nameOffset = fbb .createString (name );
278
+
279
+ ModelRelation .startModelRelation (fbb );
280
+ ModelRelation .addName (fbb , nameOffset );
281
+ int relationIdOffset = IdUid .createIdUid (fbb , relationId , relationUid );
282
+ ModelRelation .addId (fbb , relationIdOffset );
283
+ int targetEntityIdOffset = IdUid .createIdUid (fbb , targetEntityId , targetEntityUid );
284
+ ModelRelation .addTargetEntityId (fbb , targetEntityIdOffset );
285
+ return ModelRelation .endModelRelation (fbb );
286
+ }
287
+ }
288
+
289
+ public static class EntityBuilder extends PartBuilder {
290
+
291
+ private final ModelBuilder model ;
214
292
final String name ;
215
293
final List <Integer > propertyOffsets = new ArrayList <>();
216
294
final List <Integer > relationOffsets = new ArrayList <>();
@@ -220,10 +298,13 @@ public class EntityBuilder {
220
298
Integer flags ;
221
299
Integer lastPropertyId ;
222
300
Long lastPropertyUid ;
223
- PropertyBuilder propertyBuilder ;
301
+ @ Nullable PropertyBuilder propertyBuilder ;
302
+ @ Nullable RelationBuilder relationBuilder ;
224
303
boolean finished ;
225
304
226
- EntityBuilder (String name ) {
305
+ EntityBuilder (ModelBuilder model , FlatBufferBuilder fbb , String name ) {
306
+ super (fbb );
307
+ this .model = model ;
227
308
this .name = name ;
228
309
}
229
310
@@ -246,12 +327,6 @@ public EntityBuilder flags(int flags) {
246
327
return this ;
247
328
}
248
329
249
- private void checkNotFinished () {
250
- if (finished ) {
251
- throw new IllegalStateException ("Already finished" );
252
- }
253
- }
254
-
255
330
public PropertyBuilder property (String name , int type ) {
256
331
return property (name , null , type );
257
332
}
@@ -263,43 +338,48 @@ public PropertyBuilder property(String name, @Nullable String targetEntityName,
263
338
public PropertyBuilder property (String name , @ Nullable String targetEntityName , @ Nullable String virtualTarget ,
264
339
int type ) {
265
340
checkNotFinished ();
266
- checkFinishProperty ();
267
- propertyBuilder = new PropertyBuilder (name , targetEntityName , virtualTarget , type );
341
+ finishPropertyOrRelation ();
342
+ propertyBuilder = new PropertyBuilder (getFbb (), name , targetEntityName , virtualTarget , type );
268
343
return propertyBuilder ;
269
344
}
270
345
271
- void checkFinishProperty () {
346
+ public RelationBuilder relation (String name , int relationId , long relationUid , int targetEntityId ,
347
+ long targetEntityUid ) {
348
+ checkNotFinished ();
349
+ finishPropertyOrRelation ();
350
+
351
+ RelationBuilder relationBuilder = new RelationBuilder (getFbb (), name , relationId , relationUid , targetEntityId , targetEntityUid );
352
+ this .relationBuilder = relationBuilder ;
353
+ return relationBuilder ;
354
+ }
355
+
356
+ private void finishPropertyOrRelation () {
357
+ if (propertyBuilder != null && relationBuilder != null ) {
358
+ throw new IllegalStateException ("Must not build property and relation at the same time." );
359
+ }
272
360
if (propertyBuilder != null ) {
273
361
propertyOffsets .add (propertyBuilder .finish ());
274
362
propertyBuilder = null ;
275
363
}
364
+ if (relationBuilder != null ) {
365
+ relationOffsets .add (relationBuilder .finish ());
366
+ relationBuilder = null ;
367
+ }
276
368
}
277
369
278
- public EntityBuilder relation ( String name , int relationId , long relationUid , int targetEntityId ,
279
- long targetEntityUid ) {
370
+ public ModelBuilder entityDone () {
371
+ // Make sure any pending property or relation is finished first
280
372
checkNotFinished ();
281
- checkFinishProperty ();
282
-
283
- int propertyNameOffset = fbb .createString (name );
284
-
285
- ModelRelation .startModelRelation (fbb );
286
- ModelRelation .addName (fbb , propertyNameOffset );
287
- int relationIdOffset = IdUid .createIdUid (fbb , relationId , relationUid );
288
- ModelRelation .addId (fbb , relationIdOffset );
289
- int targetEntityIdOffset = IdUid .createIdUid (fbb , targetEntityId , targetEntityUid );
290
- ModelRelation .addTargetEntityId (fbb , targetEntityIdOffset );
291
- relationOffsets .add (ModelRelation .endModelRelation (fbb ));
292
-
293
- return this ;
373
+ finishPropertyOrRelation ();
374
+ model .entityOffsets .add (finish ());
375
+ return model ;
294
376
}
295
377
296
- public ModelBuilder entityDone () {
297
- checkNotFinished ();
298
- checkFinishProperty ();
299
- finished = true ;
378
+ @ Override
379
+ public int createFlatBufferTable (FlatBufferBuilder fbb ) {
300
380
int testEntityNameOffset = fbb .createString (name );
301
- int propertiesOffset = createVector (propertyOffsets );
302
- int relationsOffset = relationOffsets .isEmpty () ? 0 : createVector (relationOffsets );
381
+ int propertiesOffset = model . createVector (propertyOffsets );
382
+ int relationsOffset = relationOffsets .isEmpty () ? 0 : model . createVector (relationOffsets );
303
383
304
384
ModelEntity .startModelEntity (fbb );
305
385
ModelEntity .addName (fbb , testEntityNameOffset );
@@ -316,12 +396,12 @@ public ModelBuilder entityDone() {
316
396
if (flags != null ) {
317
397
ModelEntity .addFlags (fbb , flags );
318
398
}
319
- entityOffsets .add (ModelEntity .endModelEntity (fbb ));
320
- return ModelBuilder .this ;
399
+ return ModelEntity .endModelEntity (fbb );
321
400
}
401
+
322
402
}
323
403
324
- int createVector (List <Integer > offsets ) {
404
+ private int createVector (List <Integer > offsets ) {
325
405
int [] offsetArray = new int [offsets .size ()];
326
406
for (int i = 0 ; i < offsets .size (); i ++) {
327
407
offsetArray [i ] = offsets .get (i );
@@ -335,7 +415,7 @@ public ModelBuilder version(long version) {
335
415
}
336
416
337
417
public EntityBuilder entity (String name ) {
338
- return new EntityBuilder (name );
418
+ return new EntityBuilder (this , fbb , name );
339
419
}
340
420
341
421
public ModelBuilder lastEntityId (int lastEntityId , long lastEntityUid ) {
0 commit comments