Baku - Derived SG suffixes
Adding derived syncgroup suffixes - syncgroup names must be unique even
if obtained from different app/db names, so it makes sense to in some
cases derive syncgroup names from app/db names to uniquely identify
syncgroups.
Change-Id: I1bb2ff4f0c9ea1171f281df167df033178c76ef2
diff --git a/baku-toolkit/lib/src/main/java/io/v/rx/syncbase/SgSuffixFormat.java b/baku-toolkit/lib/src/main/java/io/v/rx/syncbase/SgSuffixFormat.java
new file mode 100644
index 0000000..970d315
--- /dev/null
+++ b/baku-toolkit/lib/src/main/java/io/v/rx/syncbase/SgSuffixFormat.java
@@ -0,0 +1,12 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package io.v.rx.syncbase;
+
+import java8.lang.FunctionalInterface;
+
+@FunctionalInterface
+public interface SgSuffixFormat<T> {
+ String get(final T parameters);
+}
diff --git a/baku-toolkit/lib/src/main/java/io/v/rx/syncbase/SgSuffixFormats.java b/baku-toolkit/lib/src/main/java/io/v/rx/syncbase/SgSuffixFormats.java
new file mode 100644
index 0000000..38eac86
--- /dev/null
+++ b/baku-toolkit/lib/src/main/java/io/v/rx/syncbase/SgSuffixFormats.java
@@ -0,0 +1,32 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package io.v.rx.syncbase;
+
+import com.google.common.escape.CharEscaperBuilder;
+import com.google.common.escape.Escaper;
+
+import lombok.experimental.UtilityClass;
+
+@UtilityClass
+public class SgSuffixFormats {
+ public static final String SG_SUFFIX_DELIMITER = "/";
+ public static final Escaper SG_SUFFIX_COMPONENT_ESCAPER = new CharEscaperBuilder()
+ .addEscape('/', "\\/")
+ .addEscape('\\', "\\\\")
+ .toEscaper();
+
+ public static SgSuffixFormat<Object> simple(final String sgSuffix) {
+ return x -> sgSuffix;
+ }
+
+ public static SgSuffixFormat<UserSyncgroup.Parameters> discriminated(
+ final String customSuffix) {
+ return p -> SG_SUFFIX_COMPONENT_ESCAPER.escape(p.getDb().getRxApp().getName()) +
+ SG_SUFFIX_DELIMITER +
+ SG_SUFFIX_COMPONENT_ESCAPER.escape(p.getDb().getName()) +
+ SG_SUFFIX_DELIMITER +
+ customSuffix;
+ }
+}
diff --git a/baku-toolkit/lib/src/main/java/io/v/rx/syncbase/UserSyncgroup.java b/baku-toolkit/lib/src/main/java/io/v/rx/syncbase/UserSyncgroup.java
index f68e230..f942a40 100644
--- a/baku-toolkit/lib/src/main/java/io/v/rx/syncbase/UserSyncgroup.java
+++ b/baku-toolkit/lib/src/main/java/io/v/rx/syncbase/UserSyncgroup.java
@@ -35,13 +35,15 @@
// TODO(rosswang): Generalize this to other possible syncgroup strategies.
@Accessors(prefix = "m")
public abstract class UserSyncgroup extends RxSyncgroup {
- public static final String DEFAULT_SYNCGROUP_SUFFIX = "user";
+ public static final SgSuffixFormat<Parameters> DEFAULT_SYNCGROUP_SUFFIX =
+ SgSuffixFormats.discriminated("user");
public static class Builder {
protected VContext mVContext;
protected Observable<Blessings> mRxBlessings;
protected SyncHostLevel mSyncHostLevel;
- protected String mSgSuffix = DEFAULT_SYNCGROUP_SUFFIX;
+ protected SgSuffixFormat<? super Parameters> mSgSuffixFormat =
+ DEFAULT_SYNCGROUP_SUFFIX;
protected RxDb mDb;
protected Function<String, String> mDescriptionForUsername = u -> "User syncgroup for " + u;
protected Function<AccessList, Permissions> mPermissionsForAcl;
@@ -68,22 +70,32 @@
return this;
}
- public Builder sgSuffix(final String sgSuffix) {
- mSgSuffix = sgSuffix;
+ public Builder sgSuffixFormat(final SgSuffixFormat sgSuffixFormat) {
+ mSgSuffixFormat = sgSuffixFormat;
return this;
}
+ public Builder sgSuffix(final String sgSuffix) {
+ return sgSuffixFormat(SgSuffixFormats.simple(sgSuffix));
+ }
+
+ public Builder discriminatedSgSuffix(final String customSuffix) {
+ return sgSuffixFormat(SgSuffixFormats.discriminated(customSuffix));
+ }
+
public Builder db(final RxDb db) {
mDb = db;
return this;
}
- public Builder descriptionForUsername(final Function<String, String> descriptionForUsername) {
+ public Builder descriptionForUsername(
+ final Function<String, String> descriptionForUsername) {
mDescriptionForUsername = descriptionForUsername;
return this;
}
- public Builder permissionsForAcl(final Function<AccessList, Permissions> permissionsForAcl) {
+ public Builder permissionsForAcl(
+ final Function<AccessList, Permissions> permissionsForAcl) {
mPermissionsForAcl = permissionsForAcl;
return this;
}
@@ -173,7 +185,7 @@
final Function<AccessList, Permissions> defaultPermissionsForAcl) {
return new Parameters(mVContext, mRxBlessings,
mSyncHostLevel == null ? defaultSyncHost.get() : mSyncHostLevel,
- mSgSuffix, mDb, mDescriptionForUsername,
+ mSgSuffixFormat, mDb, mDescriptionForUsername,
mPermissionsForAcl == null? defaultPermissionsForAcl : mPermissionsForAcl,
ImmutableList.copyOf(mPrefixes), mMemberInfo, mOnError);
}
@@ -201,7 +213,7 @@
VContext mVContext;
Observable<Blessings> mRxBlessings;
SyncHostLevel mSyncHostLevel;
- String mSgSuffix;
+ SgSuffixFormat<? super Parameters> mSgSuffixFormat;
RxDb mDb;
Function<String, String> mDescriptionForUsername;
Function<AccessList, Permissions> mPermissionsForAcl;
@@ -229,7 +241,8 @@
private Observable<?> rxJoin(final ClientUser clientUser, final AccessList acl) {
final String sgHost = mParams.getSyncHostLevel().getSyncgroupHostName(clientUser);
- final String sgName = RxSyncbase.syncgroupName(sgHost, mParams.getSgSuffix());
+ final String sgName = RxSyncbase.syncgroupName(sgHost,
+ mParams.getSgSuffixFormat().get(mParams));
final SyncgroupSpec spec = createSpec(clientUser, acl);
return rxJoin(sgHost, sgName, spec);