2020package org .spine3 .server ;
2121
2222import com .google .common .base .Optional ;
23+ import com .google .common .base .Supplier ;
24+ import com .google .common .base .Suppliers ;
2325import com .google .common .collect .Lists ;
2426import com .google .common .collect .Maps ;
2527import com .google .protobuf .Message ;
4951import org .spine3 .server .stand .StandStorage ;
5052import org .spine3 .server .stand .StandUpdateDelivery ;
5153import org .spine3 .server .storage .StorageFactory ;
54+ import org .spine3 .server .storage .StorageFactorySwitch ;
5255
5356import javax .annotation .CheckReturnValue ;
5457import javax .annotation .Nullable ;
@@ -81,7 +84,7 @@ public final class BoundedContext extends IntegrationEventSubscriberGrpc.Integra
8184
8285 /** If `true` the bounded context serves many organizations. */
8386 private final boolean multitenant ;
84- private final StorageFactory storageFactory ;
87+
8588 private final CommandBus commandBus ;
8689 private final EventBus eventBus ;
8790 private final Stand stand ;
@@ -96,11 +99,16 @@ public final class BoundedContext extends IntegrationEventSubscriberGrpc.Integra
9699 */
97100 private final Map <Class <? extends Message >, AggregateRepository <?, ?>> aggregateRepositories = Maps .newHashMap ();
98101
102+ /**
103+ * Memoized version of the {@code StorageFactory} supplier passed to the constructor.
104+ */
105+ private final Supplier <StorageFactory > storageFactory ;
106+
99107 private BoundedContext (Builder builder ) {
100108 super ();
101109 this .name = builder .name ;
102110 this .multitenant = builder .multitenant ;
103- this .storageFactory = builder .storageFactory ;
111+ this .storageFactory = Suppliers . memoize ( builder .storageFactorySupplier ) ;
104112 this .commandBus = builder .commandBus ;
105113 this .eventBus = builder .eventBus ;
106114 this .stand = builder .stand ;
@@ -139,7 +147,7 @@ public static Builder newBuilder() {
139147 */
140148 @ Override
141149 public void close () throws Exception {
142- storageFactory .close ();
150+ storageFactory .get (). close ();
143151 commandBus .close ();
144152 eventBus .close ();
145153 stand .close ();
@@ -209,7 +217,7 @@ public boolean isMultitenant() {
209217
210218 private void checkStorageAssigned (Repository repository ) {
211219 if (!repository .storageAssigned ()) {
212- repository .initStorage (this . storageFactory );
220+ repository .initStorage (storageFactory . get () );
213221 }
214222 }
215223
@@ -283,6 +291,7 @@ public Stand getStand() {
283291 final AggregateRepository <?, ?> result = aggregateRepositories .get (aggregateStateClass );
284292 return Optional .fromNullable (result );
285293 }
294+
286295 /**
287296 * A builder for producing {@code BoundedContext} instances.
288297 *
@@ -292,7 +301,7 @@ public Stand getStand() {
292301 public static class Builder {
293302
294303 private String name = DEFAULT_NAME ;
295- private StorageFactory storageFactory ;
304+ private Supplier < StorageFactory > storageFactorySupplier ;
296305 private CommandStore commandStore ;
297306 private CommandBus commandBus ;
298307 private EventBus eventBus ;
@@ -333,34 +342,38 @@ public boolean isMultitenant() {
333342 return this .multitenant ;
334343 }
335344
336- public Builder setStorageFactory (StorageFactory storageFactory ) {
337- this .storageFactory = checkNotNull (storageFactory );
345+ /**
346+ * Sets the supplier for {@code StorageFactory}.
347+ *
348+ * <p>If the supplier was not set or {@code null} was passed,
349+ * {@link StorageFactorySwitch} will be used during the construction of
350+ * a {@code BoundedContext} instance.
351+ */
352+ public Builder setStorageFactorySupplier (@ Nullable Supplier <StorageFactory > supplier ) {
353+ this .storageFactorySupplier = supplier ;
338354 return this ;
339355 }
340356
341- @ Nullable
342- public StorageFactory getStorageFactory () {
343- return storageFactory ;
357+ public Optional <Supplier <StorageFactory >> storageFactorySupplier () {
358+ return Optional .fromNullable (storageFactorySupplier );
344359 }
345360
346361 public Builder setCommandStore (CommandStore commandStore ) {
347362 this .commandStore = checkNotNull (commandStore );
348363 return this ;
349364 }
350365
351- @ Nullable
352- public CommandStore getCommandStore () {
353- return this .commandStore ;
366+ public Optional <CommandStore > commandStore () {
367+ return Optional .fromNullable (commandStore );
354368 }
355369
356370 public Builder setCommandBus (CommandBus commandBus ) {
357371 this .commandBus = checkNotNull (commandBus );
358372 return this ;
359373 }
360374
361- @ Nullable
362- public CommandBus getCommandBus () {
363- return commandBus ;
375+ public Optional <CommandBus > commandBus () {
376+ return Optional .fromNullable (commandBus );
364377 }
365378
366379
@@ -369,24 +382,21 @@ public Builder setEventBus(EventBus eventBus) {
369382 return this ;
370383 }
371384
372- @ Nullable
373- public EventBus getEventBus () {
374- return eventBus ;
385+ public Optional <EventBus > eventBus () {
386+ return Optional .fromNullable (eventBus );
375387 }
376388
377389 public Builder setStand (Stand stand ) {
378390 this .stand = checkNotNull (stand );
379391 return this ;
380392 }
381393
382- @ Nullable
383- public Stand getStand () {
384- return stand ;
394+ public Optional <Stand > stand () {
395+ return Optional .fromNullable (stand );
385396 }
386397
387- @ Nullable
388- public StandUpdateDelivery getStandUpdateDelivery () {
389- return standUpdateDelivery ;
398+ public Optional <StandUpdateDelivery > standUpdateDelivery () {
399+ return Optional .fromNullable (standUpdateDelivery );
390400 }
391401
392402 public Builder setStandUpdateDelivery (StandUpdateDelivery standUpdateDelivery ) {
@@ -395,17 +405,26 @@ public Builder setStandUpdateDelivery(StandUpdateDelivery standUpdateDelivery) {
395405 }
396406
397407 public BoundedContext build () {
398- checkNotNull (storageFactory , "storageFactory must be set" );
408+ if (storageFactorySupplier == null ) {
409+ storageFactorySupplier = StorageFactorySwitch .getInstance ();
410+ }
411+
412+ final StorageFactory storageFactory = storageFactorySupplier .get ();
413+
414+ if (storageFactory == null ) {
415+ throw new IllegalStateException ("Supplier of StorageFactory (" + storageFactorySupplier +
416+ ") returned null instance" );
417+ }
399418
400419 /* If some of the properties were not set, create them using set StorageFactory. */
401420 if (commandStore == null ) {
402- commandStore = createCommandStore ();
421+ commandStore = createCommandStore (storageFactory );
403422 }
404423 if (commandBus == null ) {
405- commandBus = createCommandBus ();
424+ commandBus = createCommandBus (storageFactory );
406425 }
407426 if (eventBus == null ) {
408- eventBus = createEventBus ();
427+ eventBus = createEventBus (storageFactory );
409428 }
410429
411430 if (stand == null ) {
@@ -423,36 +442,30 @@ public BoundedContext build() {
423442 }
424443
425444 private StandFunnel createStandFunnel (@ Nullable StandUpdateDelivery standUpdateDelivery ) {
426- StandFunnel standFunnel ;
427- if (standUpdateDelivery == null ) {
428- standFunnel = StandFunnel .newBuilder ()
429- .setStand (stand )
430- .build ();
431- } else {
432- standFunnel = StandFunnel .newBuilder ()
433- .setDelivery (standUpdateDelivery )
434- .setStand (stand )
435- .build ();
445+ final StandFunnel .Builder builder = StandFunnel .newBuilder ()
446+ .setStand (stand );
447+ if (standUpdateDelivery != null ) {
448+ builder .setDelivery (standUpdateDelivery );
436449 }
437- return standFunnel ;
450+ return builder . build () ;
438451 }
439452
440- private CommandStore createCommandStore () {
453+ private static CommandStore createCommandStore (StorageFactory storageFactory ) {
441454 final CommandStore result = new CommandStore (storageFactory .createCommandStorage ());
442455 return result ;
443456 }
444457
445- private CommandBus createCommandBus () {
458+ private CommandBus createCommandBus (StorageFactory storageFactory ) {
446459 if (commandStore == null ) {
447- this .commandStore = createCommandStore ();
460+ this .commandStore = createCommandStore (storageFactory );
448461 }
449462 final CommandBus commandBus = CommandBus .newBuilder ()
450463 .setCommandStore (commandStore )
451464 .build ();
452465 return commandBus ;
453466 }
454467
455- private EventBus createEventBus () {
468+ private static EventBus createEventBus (StorageFactory storageFactory ) {
456469 final EventBus result = EventBus .newBuilder ()
457470 .setStorageFactory (storageFactory )
458471 .build ();
0 commit comments