1616
1717package io .objectbox .sync ;
1818
19+ import java .util .ArrayList ;
1920import java .util .Arrays ;
20- import java .util .Collections ;
2121import java .util .List ;
2222import java .util .Map ;
2323import java .util .TreeMap ;
2424
2525import javax .annotation .Nullable ;
2626
2727import io .objectbox .BoxStore ;
28- import io .objectbox .annotation .apihint .Internal ;
2928import io .objectbox .exception .FeatureNotAvailableException ;
3029import io .objectbox .sync .internal .Platform ;
3130import io .objectbox .sync .listener .SyncChangeListener ;
3635import io .objectbox .sync .listener .SyncTimeListener ;
3736
3837/**
39- * A builder to create a {@link SyncClient}; the builder itself should be created via
40- * {@link Sync#client(BoxStore, String, SyncCredentials)}.
38+ * A builder to create a {@link SyncClient}; the builder itself should be created via {@link Sync#client(BoxStore)}.
4139 */
4240@ SuppressWarnings ({"unused" , "WeakerAccess" })
4341public final class SyncBuilder {
4442
4543 final Platform platform ;
4644 final BoxStore boxStore ;
47- @ Nullable private String url ;
48- final List <SyncCredentials > credentials ;
45+ final List < String > urls = new ArrayList <>() ;
46+ final List <SyncCredentials > credentials = new ArrayList <>() ;
4947
5048 @ Nullable SyncLoginListener loginListener ;
5149 @ Nullable SyncCompletedListener completedListener ;
@@ -56,6 +54,7 @@ public final class SyncBuilder {
5654
5755 @ Nullable
5856 String [] trustedCertPaths ;
57+ int flags ;
5958 boolean uncommittedAcks ;
6059
6160 RequestUpdatesMode requestUpdatesMode = RequestUpdatesMode .AUTO ;
@@ -98,47 +97,80 @@ private static void checkSyncFeatureAvailable() {
9897 }
9998 }
10099
101- private SyncBuilder (BoxStore boxStore , @ Nullable String url , @ Nullable List <SyncCredentials > credentials ) {
102- checkNotNull (boxStore , "BoxStore is required." );
103- checkNotNull (credentials , "Sync credentials are required." );
100+ /**
101+ * Creates a builder for a {@link SyncClient}.
102+ * <p>
103+ * Don't use this directly, use the {@link Sync#client} method instead.
104+ */
105+ SyncBuilder (BoxStore boxStore ) {
106+ checkNotNull (boxStore , "boxStore" );
104107 this .boxStore = boxStore ;
105- this .url = url ;
106- this .credentials = credentials ;
107108 checkSyncFeatureAvailable ();
108109 this .platform = Platform .findPlatform (); // Requires APIs only present in Android Sync library
109110 }
110111
111- @ Internal
112- public SyncBuilder (BoxStore boxStore , String url , @ Nullable SyncCredentials credentials ) {
113- this (boxStore , url , credentials == null ? null : Collections .singletonList (credentials ));
114- }
115-
116- @ Internal
117- public SyncBuilder (BoxStore boxStore , String url , @ Nullable SyncCredentials [] multipleCredentials ) {
118- this (boxStore , url , multipleCredentials == null ? null : Arrays .asList (multipleCredentials ));
112+ /**
113+ * Adds a Sync server URL the client should connect to.
114+ * <p>
115+ * This is typically a WebSockets URL starting with {@code ws://} or {@code wss://} (for encrypted connections), for
116+ * example if the server is running on localhost {@code ws://127.0.0.1:9999}.
117+ * <p>
118+ * Can be called multiple times to add multiple URLs for high availability and load balancing (like when using an
119+ * ObjectBox Sync Server Cluster). A random URL is selected for each connection attempt.
120+ *
121+ * @param url The URL of the Sync server on which the Sync protocol is exposed.
122+ * @return this builder for chaining
123+ * @see #urls(List)
124+ */
125+ public SyncBuilder url (String url ) {
126+ checkNotNull (url , "url" );
127+ this .urls .add (url );
128+ return this ;
119129 }
120130
121131 /**
122- * When using this constructor, make sure to set the server URL before starting.
132+ * Like {@link #url(String)}, but accepts a list of URLs.
133+ *
134+ * @param urls A list of URLs of Sync servers on which the Sync protocol is exposed.
135+ * @return this builder for chaining
136+ * @see #url(String)
123137 */
124- @ Internal
125- public SyncBuilder (BoxStore boxStore , @ Nullable SyncCredentials credentials ) {
126- this (boxStore , null , credentials == null ? null : Collections .singletonList (credentials ));
138+ public SyncBuilder urls (List <String > urls ) {
139+ checkNotNull (urls , "urls" );
140+ for (String url : urls ) {
141+ url (url );
142+ }
143+ return this ;
127144 }
128145
129146 /**
130- * Allows internal code to set the Sync server URL after creating this builder.
147+ * Adds {@link SyncCredentials} to authenticate the client with the server.
148+ * <p>
149+ * The accepted credentials types depend on your Sync server configuration.
150+ *
151+ * @param credentials credentials created using a {@link SyncCredentials} factory method, for example
152+ * {@code SyncCredentials.jwtIdToken(idToken)}.
153+ * @see #credentials(List)
131154 */
132- @ Internal
133- SyncBuilder serverUrl ( String url ) {
134- this .url = url ;
155+ public SyncBuilder credentials ( SyncCredentials credentials ) {
156+ checkNotNull ( credentials , "credentials" );
157+ this .credentials . add ( credentials ) ;
135158 return this ;
136159 }
137160
138- @ Internal
139- String serverUrl () {
140- checkNotNull (url , "Sync Server URL is null." );
141- return url ;
161+ /**
162+ * Like {@link #credentials(SyncCredentials)}, but accepts a list of credentials.
163+ *
164+ * @param credentials a list of credentials where each element is created using a {@link SyncCredentials} factory
165+ * method, for example {@code SyncCredentials.jwtIdToken(idToken)}.
166+ * @return this builder for chaining
167+ */
168+ public SyncBuilder credentials (List <SyncCredentials > credentials ) {
169+ checkNotNull (credentials , "credentials" );
170+ for (SyncCredentials credential : credentials ) {
171+ credentials (credential );
172+ }
173+ return this ;
142174 }
143175
144176 /**
@@ -151,8 +183,8 @@ String serverUrl() {
151183 * @see SyncClient#putFilterVariable
152184 */
153185 public SyncBuilder filterVariable (String name , String value ) {
154- checkNotNull (name , "Filter variable name is null. " );
155- checkNotNull (value , "Filter variable value is null. " );
186+ checkNotNull (name , "name" );
187+ checkNotNull (value , "value" );
156188 filterVariables .put (name , value );
157189 return this ;
158190 }
@@ -170,6 +202,16 @@ public SyncBuilder trustedCertificates(String[] paths) {
170202 return this ;
171203 }
172204
205+ /**
206+ * Sets bit flags to adjust Sync behavior, like additional logging.
207+ *
208+ * @param flags One or multiple {@link SyncFlags}, combined with bitwise or.
209+ */
210+ public SyncBuilder flags (int flags ) {
211+ this .flags = flags ;
212+ return this ;
213+ }
214+
173215 /**
174216 * Configure automatic sync updates from the server.
175217 * If automatic sync updates are turned off, they will need to be requested using the sync client.
@@ -265,23 +307,25 @@ public SyncClient build() {
265307 if (boxStore .getSyncClient () != null ) {
266308 throw new IllegalStateException ("The given store is already associated with a Sync client, close it first." );
267309 }
268- checkNotNull (url , "Sync Server URL is required." );
269310 return new SyncClientImpl (this );
270311 }
271312
272313 /**
273- * Builds, {@link SyncClient#start() starts} and returns a Sync client.
314+ * {@link #build() Builds} , {@link SyncClient#start() starts} and returns a Sync client.
274315 */
275316 public SyncClient buildAndStart () {
276317 SyncClient syncClient = build ();
277318 syncClient .start ();
278319 return syncClient ;
279320 }
280321
281- private void checkNotNull (@ Nullable Object object , String message ) {
282- //noinspection ConstantConditions Non-null annotation does not enforce, so check for null.
322+ /**
323+ * Nullness annotations are only a hint in Java, so explicitly check nonnull annotated parameters
324+ * (see package-info.java for package settings).
325+ */
326+ private void checkNotNull (@ Nullable Object object , String name ) {
283327 if (object == null ) {
284- throw new IllegalArgumentException (message );
328+ throw new IllegalArgumentException (name + " must not be null." );
285329 }
286330 }
287331
0 commit comments