Extract a ListOption class, deduplicating fromBits method
Remove the toBits method, which was unused in all cases. It was
primarily for the GWT UI code.
Change-Id: I755c4b4a752ba9fe2a6771f313c4a9361d4c071b
diff --git a/java/com/google/gerrit/extensions/client/ListAccountsOption.java b/java/com/google/gerrit/extensions/client/ListAccountsOption.java
index b5e9004..2274d5d 100644
--- a/java/com/google/gerrit/extensions/client/ListAccountsOption.java
+++ b/java/com/google/gerrit/extensions/client/ListAccountsOption.java
@@ -14,11 +14,8 @@
package com.google.gerrit.extensions.client;
-import java.util.EnumSet;
-import java.util.Set;
-
/** Output options available for retrieval of account details. */
-public enum ListAccountsOption {
+public enum ListAccountsOption implements ListOption {
/** Return detailed account properties. */
DETAILS(0),
@@ -31,32 +28,8 @@
this.value = v;
}
+ @Override
public int getValue() {
return value;
}
-
- public static EnumSet<ListAccountsOption> fromBits(int v) {
- EnumSet<ListAccountsOption> r = EnumSet.noneOf(ListAccountsOption.class);
- for (ListAccountsOption o : ListAccountsOption.values()) {
- if ((v & (1 << o.value)) != 0) {
- r.add(o);
- v &= ~(1 << o.value);
- }
- if (v == 0) {
- return r;
- }
- }
- if (v != 0) {
- throw new IllegalArgumentException("unknown " + Integer.toHexString(v));
- }
- return r;
- }
-
- public static int toBits(Set<ListAccountsOption> set) {
- int r = 0;
- for (ListAccountsOption o : set) {
- r |= 1 << o.value;
- }
- return r;
- }
}
diff --git a/java/com/google/gerrit/extensions/client/ListChangesOption.java b/java/com/google/gerrit/extensions/client/ListChangesOption.java
index 5e4a3a7..c842adc 100644
--- a/java/com/google/gerrit/extensions/client/ListChangesOption.java
+++ b/java/com/google/gerrit/extensions/client/ListChangesOption.java
@@ -14,11 +14,8 @@
package com.google.gerrit.extensions.client;
-import java.util.EnumSet;
-import java.util.Set;
-
/** Output options available for retrieval of change details. */
-public enum ListChangesOption {
+public enum ListChangesOption implements ListOption {
LABELS(0),
DETAILED_LABELS(8),
@@ -86,32 +83,8 @@
this.value = v;
}
+ @Override
public int getValue() {
return value;
}
-
- public static EnumSet<ListChangesOption> fromBits(int v) {
- EnumSet<ListChangesOption> r = EnumSet.noneOf(ListChangesOption.class);
- for (ListChangesOption o : ListChangesOption.values()) {
- if ((v & (1 << o.value)) != 0) {
- r.add(o);
- v &= ~(1 << o.value);
- }
- if (v == 0) {
- return r;
- }
- }
- if (v != 0) {
- throw new IllegalArgumentException("unknown " + Integer.toHexString(v));
- }
- return r;
- }
-
- public static int toBits(Set<ListChangesOption> set) {
- int r = 0;
- for (ListChangesOption o : set) {
- r |= 1 << o.value;
- }
- return r;
- }
}
diff --git a/java/com/google/gerrit/extensions/client/ListGroupsOption.java b/java/com/google/gerrit/extensions/client/ListGroupsOption.java
index e95570f..a971226 100644
--- a/java/com/google/gerrit/extensions/client/ListGroupsOption.java
+++ b/java/com/google/gerrit/extensions/client/ListGroupsOption.java
@@ -14,10 +14,8 @@
package com.google.gerrit.extensions.client;
-import java.util.EnumSet;
-
/** Output options available when using {@code /groups/} RPCs. */
-public enum ListGroupsOption {
+public enum ListGroupsOption implements ListOption {
/** Return information on the direct group members. */
MEMBERS(0),
@@ -30,32 +28,8 @@
this.value = v;
}
+ @Override
public int getValue() {
return value;
}
-
- public static EnumSet<ListGroupsOption> fromBits(int v) {
- EnumSet<ListGroupsOption> r = EnumSet.noneOf(ListGroupsOption.class);
- for (ListGroupsOption o : ListGroupsOption.values()) {
- if ((v & (1 << o.value)) != 0) {
- r.add(o);
- v &= ~(1 << o.value);
- }
- if (v == 0) {
- return r;
- }
- }
- if (v != 0) {
- throw new IllegalArgumentException("unknown " + Integer.toHexString(v));
- }
- return r;
- }
-
- public static int toBits(EnumSet<ListGroupsOption> set) {
- int r = 0;
- for (ListGroupsOption o : set) {
- r |= 1 << o.value;
- }
- return r;
- }
}
diff --git a/java/com/google/gerrit/extensions/client/ListOption.java b/java/com/google/gerrit/extensions/client/ListOption.java
new file mode 100644
index 0000000..e694c0e
--- /dev/null
+++ b/java/com/google/gerrit/extensions/client/ListOption.java
@@ -0,0 +1,49 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.extensions.client;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.EnumSet;
+
+/** Enum that can be expressed as a bitset in query parameters. */
+public interface ListOption {
+ int getValue();
+
+ static <T extends Enum<T> & ListOption> EnumSet<T> fromBits(Class<T> clazz, int v) {
+ EnumSet<T> r = EnumSet.noneOf(clazz);
+ T[] values;
+ try {
+ @SuppressWarnings("unchecked")
+ T[] tmp = (T[]) clazz.getMethod("values").invoke(null);
+ values = tmp;
+ } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
+ throw new IllegalStateException(e);
+ }
+ for (T o : values) {
+ if ((v & (1 << o.getValue())) != 0) {
+ r.add(o);
+ v &= ~(1 << o.getValue());
+ }
+ if (v == 0) {
+ return r;
+ }
+ }
+ if (v != 0) {
+ throw new IllegalArgumentException(
+ "unknown " + clazz.getName() + ": " + Integer.toHexString(v));
+ }
+ return r;
+ }
+}
diff --git a/java/com/google/gerrit/server/restapi/account/QueryAccounts.java b/java/com/google/gerrit/server/restapi/account/QueryAccounts.java
index 2c0512c..f527ba4 100644
--- a/java/com/google/gerrit/server/restapi/account/QueryAccounts.java
+++ b/java/com/google/gerrit/server/restapi/account/QueryAccounts.java
@@ -17,6 +17,7 @@
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.extensions.client.ListAccountsOption;
+import com.google.gerrit.extensions.client.ListOption;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.AccountVisibility;
import com.google.gerrit.extensions.restapi.AuthException;
@@ -97,7 +98,7 @@
@Option(name = "-O", usage = "Output option flags, in hex")
void setOptionFlagsHex(String hex) {
- options.addAll(ListAccountsOption.fromBits(Integer.parseInt(hex, 16)));
+ options.addAll(ListOption.fromBits(ListAccountsOption.class, Integer.parseInt(hex, 16)));
}
@Option(
diff --git a/java/com/google/gerrit/server/restapi/change/GetChange.java b/java/com/google/gerrit/server/restapi/change/GetChange.java
index a8f8bbb..2decb4e 100644
--- a/java/com/google/gerrit/server/restapi/change/GetChange.java
+++ b/java/com/google/gerrit/server/restapi/change/GetChange.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server.restapi.change;
import com.google.gerrit.extensions.client.ListChangesOption;
+import com.google.gerrit.extensions.client.ListOption;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestReadView;
@@ -37,7 +38,7 @@
@Option(name = "-O", usage = "Output option flags, in hex")
void setOptionFlagsHex(String hex) {
- options.addAll(ListChangesOption.fromBits(Integer.parseInt(hex, 16)));
+ options.addAll(ListOption.fromBits(ListChangesOption.class, Integer.parseInt(hex, 16)));
}
@Inject
diff --git a/java/com/google/gerrit/server/restapi/change/QueryChanges.java b/java/com/google/gerrit/server/restapi/change/QueryChanges.java
index 9fedfd6..23b3011 100644
--- a/java/com/google/gerrit/server/restapi/change/QueryChanges.java
+++ b/java/com/google/gerrit/server/restapi/change/QueryChanges.java
@@ -17,6 +17,7 @@
import com.google.common.collect.Iterables;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.client.ListChangesOption;
+import com.google.gerrit.extensions.client.ListOption;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
@@ -70,7 +71,7 @@
@Option(name = "-O", usage = "Output option flags, in hex")
void setOptionFlagsHex(String hex) {
- options.addAll(ListChangesOption.fromBits(Integer.parseInt(hex, 16)));
+ options.addAll(ListOption.fromBits(ListChangesOption.class, Integer.parseInt(hex, 16)));
}
@Option(
diff --git a/java/com/google/gerrit/server/restapi/group/ListGroups.java b/java/com/google/gerrit/server/restapi/group/ListGroups.java
index 8d8dc3d..600379c 100644
--- a/java/com/google/gerrit/server/restapi/group/ListGroups.java
+++ b/java/com/google/gerrit/server/restapi/group/ListGroups.java
@@ -25,6 +25,7 @@
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.client.ListGroupsOption;
+import com.google.gerrit.extensions.client.ListOption;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.RestApiException;
@@ -202,7 +203,7 @@
@Option(name = "-O", usage = "Output option flags, in hex")
void setOptionFlagsHex(String hex) {
- options.addAll(ListGroupsOption.fromBits(Integer.parseInt(hex, 16)));
+ options.addAll(ListOption.fromBits(ListGroupsOption.class, Integer.parseInt(hex, 16)));
}
@Option(name = "--owned-by", usage = "list groups owned by the given group uuid")
diff --git a/java/com/google/gerrit/server/restapi/group/QueryGroups.java b/java/com/google/gerrit/server/restapi/group/QueryGroups.java
index fa9285d..6a7262b 100644
--- a/java/com/google/gerrit/server/restapi/group/QueryGroups.java
+++ b/java/com/google/gerrit/server/restapi/group/QueryGroups.java
@@ -17,6 +17,7 @@
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.gerrit.extensions.client.ListGroupsOption;
+import com.google.gerrit.extensions.client.ListOption;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
@@ -82,7 +83,7 @@
@Option(name = "-O", usage = "Output option flags, in hex")
public void setOptionFlagsHex(String hex) {
- options.addAll(ListGroupsOption.fromBits(Integer.parseInt(hex, 16)));
+ options.addAll(ListOption.fromBits(ListGroupsOption.class, Integer.parseInt(hex, 16)));
}
@Inject
diff --git a/javatests/com/google/gerrit/extensions/BUILD b/javatests/com/google/gerrit/extensions/BUILD
index adf696d..94e433c 100644
--- a/javatests/com/google/gerrit/extensions/BUILD
+++ b/javatests/com/google/gerrit/extensions/BUILD
@@ -8,6 +8,7 @@
"//java/com/google/gerrit/extensions:api",
"//java/com/google/gerrit/extensions/common/testing:common-test-util",
"//java/com/google/gerrit/testing:gerrit-test-util",
+ "//lib:guava",
"//lib/guice",
"//lib/truth",
],
diff --git a/javatests/com/google/gerrit/extensions/client/ListOptionTest.java b/javatests/com/google/gerrit/extensions/client/ListOptionTest.java
new file mode 100644
index 0000000..4bb9107
--- /dev/null
+++ b/javatests/com/google/gerrit/extensions/client/ListOptionTest.java
@@ -0,0 +1,72 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.extensions.client;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+import static com.google.gerrit.extensions.client.ListOptionTest.MyOption.BAR;
+import static com.google.gerrit.extensions.client.ListOptionTest.MyOption.BAZ;
+import static com.google.gerrit.extensions.client.ListOptionTest.MyOption.FOO;
+
+import com.google.common.math.IntMath;
+import com.google.gerrit.testing.GerritBaseTests;
+import java.util.EnumSet;
+import org.junit.Test;
+
+public class ListOptionTest extends GerritBaseTests {
+ enum MyOption implements ListOption {
+ FOO(0),
+ BAR(1),
+ BAZ(17);
+
+ private final int value;
+
+ MyOption(int value) {
+ this.value = value;
+ }
+
+ @Override
+ public int getValue() {
+ return value;
+ }
+ }
+
+ @Test
+ public void fromBits() {
+ assertThat(IntMath.pow(2, BAZ.getValue())).isEqualTo(131072);
+ assertThat(ListOption.fromBits(MyOption.class, 0)).isEmpty();
+ assertThat(ListOption.fromBits(MyOption.class, 1)).containsExactly(FOO);
+ assertThat(ListOption.fromBits(MyOption.class, 2)).containsExactly(BAR);
+ assertThat(ListOption.fromBits(MyOption.class, 131072)).containsExactly(BAZ);
+ assertThat(ListOption.fromBits(MyOption.class, 3)).containsExactly(FOO, BAR);
+ assertThat(ListOption.fromBits(MyOption.class, 131073)).containsExactly(FOO, BAZ);
+ assertThat(ListOption.fromBits(MyOption.class, 131074)).containsExactly(BAR, BAZ);
+ assertThat(ListOption.fromBits(MyOption.class, 131075)).containsExactly(FOO, BAR, BAZ);
+
+ assertFromBitsFails(4);
+ assertFromBitsFails(8);
+ assertFromBitsFails(16);
+ assertFromBitsFails(250);
+ }
+
+ private void assertFromBitsFails(int v) {
+ try {
+ EnumSet<MyOption> opts = ListOption.fromBits(MyOption.class, v);
+ assertWithMessage("expected RuntimeException for fromBits(%s), got: %s", v, opts).fail();
+ } catch (RuntimeException e) {
+ // Expected.
+ }
+ }
+}