Drop MemberInfo and use AccountInfo instead

Both entities represent accounts and have similar fields. MemberInfo has
more fields but they aren't used so we can just drop them.

Move AccountInfo (on client and server side) from the 'change' package
into the 'account' package since it is now also used outside of the
'/changes/' scope.

Change-Id: I8e8732981ed09851ea0db848ad63a45b983954fe
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
This commit is contained in:
Edwin Kempin
2013-02-27 12:39:32 +01:00
parent b5b5c79b43
commit 963dfd07d0
25 changed files with 151 additions and 239 deletions

View File

@@ -247,6 +247,22 @@ the link:#capability-info[CapabilityInfo] entity.
JSON Entities JSON Entities
------------- -------------
[[account-info]]
AccountInfo
~~~~~~~~~~~
The `AccountInfo` entity contains information about an account.
[options="header",width="50%",cols="1,^1,5"]
|===========================
|Field Name ||Description
|`_account_id` ||The numeric ID of the account.
|`name` |optional|The full name of the user. +
Only set if detailed account information is requested.
|`email` |optional|
The email address the user prefers to be contacted through. +
Only set if detailed account information is requested.
|===========================
[[capability-info]] [[capability-info]]
CapabilityInfo CapabilityInfo
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~

View File

@@ -1540,24 +1540,6 @@ Message to be added as review comment to the change when abandoning the
change. change.
|=========================== |===========================
[[account-info]]
AccountInfo
~~~~~~~~~~~
The `AccountInfo` entity contains information about an account.
[options="header",width="50%",cols="1,^1,5"]
|===========================
|Field Name ||Description
|`_account_id` ||The numeric ID of the account.
|`name` |optional|The full name of the user. +
Only set if link:#detailed-accounts[detailed account information] is
requested.
|`email` |optional|
The email address the user prefers to be contacted through. +
Only set if link:#detailed-accounts[detailed account information] is
requested.
|===========================
[[add-reviewer-result]] [[add-reviewer-result]]
AddReviewerResult AddReviewerResult
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
@@ -1584,7 +1566,8 @@ ApprovalInfo
The `ApprovalInfo` entity contains information about an approval from a The `ApprovalInfo` entity contains information about an approval from a
user for a label on a change. user for a label on a change.
`ApprovalInfo` has the same fields as link:#account-info[AccountInfo]. `ApprovalInfo` has the same fields as
link:rest-api-accounts.html#account-info[AccountInfo].
In addition `ApprovalInfo` has the following fields: In addition `ApprovalInfo` has the following fields:
[options="header",width="50%",cols="1,^1,5"] [options="header",width="50%",cols="1,^1,5"]
@@ -1633,7 +1616,8 @@ Not set for merged changed.
|`_sortkey` ||The sortkey of the change. |`_sortkey` ||The sortkey of the change.
|`_number` ||The legacy numeric ID of the change. |`_number` ||The legacy numeric ID of the change.
|`owner` || |`owner` ||
The owner of the change as an link:#account-info[AccountInfo] entity. The owner of the change as an link:rest-api-accounts.html#account-info[
AccountInfo] entity.
|`labels` |optional| |`labels` |optional|
The labels of the change as a map that maps the label names to The labels of the change as a map that maps the label names to
link:#label-info[LabelInfo] entries. + link:#label-info[LabelInfo] entries. +
@@ -1645,7 +1629,7 @@ values that are allowed for that label. +
Only set if link:#detailed-labels[detailed labels] are requested. Only set if link:#detailed-labels[detailed labels] are requested.
|`removable_reviewers`|optional| |`removable_reviewers`|optional|
The reviewers that can be removed by the calling user as a list of The reviewers that can be removed by the calling user as a list of
link:#account-info[AccountInfo] entities. + link:rest-api-accounts.html#account-info[AccountInfo] entities. +
Only set if link:#detailed-labels[detailed labels] are requested. Only set if link:#detailed-labels[detailed labels] are requested.
|`current_revision` |optional| |`current_revision` |optional|
The commit ID of the current patch set of this change. + The commit ID of the current patch set of this change. +
@@ -1809,16 +1793,16 @@ The `LabelInfo` entity contains information about a label on a change.
|=========================== |===========================
|Field Name ||Description |Field Name ||Description
|`approved` |optional|The user who approved this label on the change |`approved` |optional|The user who approved this label on the change
as a link:#account-info[AccountInfo] entity. + as a link:rest-api-accounts.html#account-info[AccountInfo] entity. +
Only set if link:#labels[labels] are requested. Only set if link:#labels[labels] are requested.
|`rejected` |optional|The user who rejected this label on the change |`rejected` |optional|The user who rejected this label on the change
as a link:#account-info[AccountInfo] entity. + as a link:rest-api-accounts.html#account-info[AccountInfo] entity. +
Only set if link:#labels[labels] are requested. Only set if link:#labels[labels] are requested.
|`recommended` |optional|The user who recommended this label on the |`recommended` |optional|The user who recommended this label on the
change as a link:#account-info[AccountInfo] entity. + change as a link:rest-api-accounts.html#account-info[AccountInfo] entity. +
Only set if link:#labels[labels] are requested. Only set if link:#labels[labels] are requested.
|`disliked` |optional|The user who disliked this label on the change |`disliked` |optional|The user who disliked this label on the change
as a link:#account-info[AccountInfo] entity. + as a link:rest-api-accounts.html#account-info[AccountInfo] entity. +
Only set if link:#labels[labels] are requested. Only set if link:#labels[labels] are requested.
|`value` |optional|The voting value of the user who |`value` |optional|The voting value of the user who
recommended/disliked this label on the change if it is not recommended/disliked this label on the change if it is not
@@ -1919,8 +1903,9 @@ ReviewerInfo
The `ReviewerInfo` entity contains information about a reviewer and its The `ReviewerInfo` entity contains information about a reviewer and its
votes on a change. votes on a change.
`ReviewerInfo` has the same fields as link:#account-info[AccountInfo] `ReviewerInfo` has the same fields as
and includes link:#detailed-accounts[detailed account information]. link:rest-api-accounts.html#account-info[AccountInfo] and includes
link:#detailed-accounts[detailed account information].
In addition `ReviewerInfo` has the following fields: In addition `ReviewerInfo` has the following fields:
[options="header",width="50%",cols="1,6"] [options="header",width="50%",cols="1,6"]

View File

@@ -494,9 +494,9 @@ GET /groups/\{group-id\}/members/ (List Group Members)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Lists the direct members of a Gerrit internal group. Lists the direct members of a Gerrit internal group.
As result a list of link:#member-info[MemberInfo] entries is returned. As result a list of detailed link:rest-api-accounts.html#account-info[
The entries in the list are sorted by full name, preferred email and AccountInfo] entries is returned. The entries in the list are sorted by
id. full name, preferred email and id.
.Request .Request
---- ----
@@ -512,20 +512,14 @@ id.
)]}' )]}'
[ [
{ {
"kind": "gerritcodereview#member", "_account_id": 1000097,
"full_name": "Jane Roe", "name": "Jane Roe",
"id": "1000097", "email": "jane.roe@example.com"
"account_id": 1000097,
"preferred_email": "jane.roe@example.com",
"user_name": "jane"
}, },
{ {
"kind": "gerritcodereview#member", "_account_id": 1000096,
"full_name": "John Doe", "name": "John Doe",
"id": "1000096", "email": "john.doe@example.com"
"account_id": 1000096,
"preferred_email": "john.doe@example.com",
"user_name": "doe"
} }
] ]
---- ----
@@ -588,8 +582,8 @@ Retrieves a group member.
GET /groups/834ec36dd5e0ed21a2ff5d7e2255da082d63bbd7/members/1000096 HTTP/1.0 GET /groups/834ec36dd5e0ed21a2ff5d7e2255da082d63bbd7/members/1000096 HTTP/1.0
---- ----
As response a link:#member-info[MemberInfo] entity is returned that As response a detailed link:rest-api-accounts.html#account-info[
describes the group member. AccountInfo] entity is returned that describes the group member.
.Response .Response
---- ----
@@ -599,12 +593,9 @@ describes the group member.
)]}' )]}'
{ {
"kind": "gerritcodereview#member", "_account_id": 1000096,
"full_name": "John Doe", "name": "John Doe",
"id": "1000096", "email": "john.doe@example.com"
"account_id": 1000096,
"preferred_email": "john.doe@example.com",
"user_name": "doe"
} }
---- ----
@@ -618,8 +609,8 @@ Adds a user as member to a Gerrit internal group.
PUT /groups/MyProject-Committers/members/John%20Doe HTTP/1.0 PUT /groups/MyProject-Committers/members/John%20Doe HTTP/1.0
---- ----
As response a link:#member-info[MemberInfo] entity is returned that As response a detailed link:rest-api-accounts.html#account-info[
describes the group member. AccountInfo] entity is returned that describes the group member.
.Response .Response
---- ----
@@ -629,12 +620,9 @@ describes the group member.
)]}' )]}'
{ {
"kind": "gerritcodereview#member", "_account_id": 1000037,
"full_name": "John Doe", "name": "John Doe",
"id": "1000037", "email": "john.doe@example.com"
"account_id": 1000037,
"preferred_email": "john.doe@example.com",
"user_name": "jdoe"
} }
---- ----
@@ -666,9 +654,10 @@ as a link:#member-input[MemberInput] entity.
} }
---- ----
As response a list of link:#member-info[MemberInfo] entities is As response a list of detailed link:rest-api-accounts.html#account-info[
returned that describes the group members that were specified in the AccountInfo] entities is returned that describes the group members that
link:#member-input[MemberInput]. A link:#member-info[MemberInfo] entity were specified in the link:#member-input[MemberInput]. An
link:rest-api-accounts.html#account-info[AccountInfo] entity
is returned for each user specified in the input, independently of is returned for each user specified in the input, independently of
whether the user was newly added to the group or whether the user was whether the user was newly added to the group or whether the user was
already a member of the group. already a member of the group.
@@ -682,20 +671,14 @@ already a member of the group.
)]}' )]}'
[ [
{ {
"kind": "gerritcodereview#member", "_account_id": 1000057,
"full_name": "Jane Roe", "name": "Jane Roe",
"id": "1000057", "email": "jane.roe@example.com"
"account_id": 1000057,
"preferred_email": "jane.roe@example.com",
"user_name": "jroe"
}, },
{ {
"kind": "gerritcodereview#member", "_account_id": 1000037,
"full_name": "John Doe", "name": "John Doe",
"id": "1000037", "email": "john.doe@example.com"
"account_id": 1000037,
"preferred_email": "john.doe@example.com",
"user_name": "jdoe"
} }
] ]
---- ----
@@ -1078,25 +1061,6 @@ New options for a group.
Whether the group is visible to all registered users. Whether the group is visible to all registered users.
|============================= |=============================
[[member-info]]
MemberInfo
~~~~~~~~~~
The `MemberInfo` entity contains information about an account that is
member of a group.
[options="header",width="50%",cols="1,^1,5"]
|===============================
|Field Name ||Description
|`kind` ||`gerritcodereview#member`
|`id` ||The URL encoded ID of the account.
|`account_id` ||The numeric ID of the account.
|`full_name` |optional|
The full name of the user ("Given-name Surname" style).
|`preferred_email` |optional|
The email address the user prefers to be contacted through.
|`user_name` ||The user name.
|===============================
[[member-input]] [[member-input]]
MemberInput MemberInput
~~~~~~~~~~~ ~~~~~~~~~~~

View File

@@ -14,7 +14,7 @@
package com.google.gerrit.client; package com.google.gerrit.client;
import com.google.gerrit.client.changes.AccountInfo; import com.google.gerrit.client.account.AccountInfo;
import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences; import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.i18n.client.DateTimeFormat;

View File

@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package com.google.gerrit.client.changes; package com.google.gerrit.client.account;
import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JavaScriptObject;

View File

@@ -17,10 +17,10 @@ package com.google.gerrit.client.admin;
import com.google.gerrit.client.Dispatcher; import com.google.gerrit.client.Dispatcher;
import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.VoidResult; import com.google.gerrit.client.VoidResult;
import com.google.gerrit.client.account.AccountInfo;
import com.google.gerrit.client.groups.GroupApi; import com.google.gerrit.client.groups.GroupApi;
import com.google.gerrit.client.groups.GroupInfo; import com.google.gerrit.client.groups.GroupInfo;
import com.google.gerrit.client.groups.GroupList; import com.google.gerrit.client.groups.GroupList;
import com.google.gerrit.client.groups.MemberInfo;
import com.google.gerrit.client.groups.MemberList; import com.google.gerrit.client.groups.MemberList;
import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.Natives; import com.google.gerrit.client.rpc.Natives;
@@ -30,7 +30,6 @@ import com.google.gerrit.client.ui.AddMemberBox;
import com.google.gerrit.client.ui.FancyFlexTable; import com.google.gerrit.client.ui.FancyFlexTable;
import com.google.gerrit.client.ui.Hyperlink; import com.google.gerrit.client.ui.Hyperlink;
import com.google.gerrit.client.ui.SmallHeading; import com.google.gerrit.client.ui.SmallHeading;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup; import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.ClickHandler;
@@ -184,8 +183,8 @@ public class AccountGroupMembersScreen extends AccountGroupScreen {
addMemberBox.setEnabled(false); addMemberBox.setEnabled(false);
GroupApi.addMember(getGroupUUID(), nameEmail, GroupApi.addMember(getGroupUUID(), nameEmail,
new GerritCallback<MemberInfo>() { new GerritCallback<AccountInfo>() {
public void onSuccess(final MemberInfo memberInfo) { public void onSuccess(final AccountInfo memberInfo) {
addMemberBox.setEnabled(true); addMemberBox.setEnabled(true);
addMemberBox.setText(""); addMemberBox.setText("");
members.insert(memberInfo); members.insert(memberInfo);
@@ -222,7 +221,7 @@ public class AccountGroupMembersScreen extends AccountGroupScreen {
}); });
} }
private class MemberTable extends FancyFlexTable<MemberInfo> { private class MemberTable extends FancyFlexTable<AccountInfo> {
private boolean enabled = true; private boolean enabled = true;
MemberTable() { MemberTable() {
@@ -238,7 +237,7 @@ public class AccountGroupMembersScreen extends AccountGroupScreen {
void setEnabled(final boolean enabled) { void setEnabled(final boolean enabled) {
this.enabled = enabled; this.enabled = enabled;
for (int row = 1; row < table.getRowCount(); row++) { for (int row = 1; row < table.getRowCount(); row++) {
final MemberInfo i = getRowItem(row); final AccountInfo i = getRowItem(row);
if (i != null) { if (i != null) {
((CheckBox) table.getWidget(row, 1)).setEnabled(enabled); ((CheckBox) table.getWidget(row, 1)).setEnabled(enabled);
} }
@@ -246,11 +245,11 @@ public class AccountGroupMembersScreen extends AccountGroupScreen {
} }
void deleteChecked() { void deleteChecked() {
final HashSet<Account.Id> ids = new HashSet<Account.Id>(); final HashSet<Integer> ids = new HashSet<Integer>();
for (int row = 1; row < table.getRowCount(); row++) { for (int row = 1; row < table.getRowCount(); row++) {
final MemberInfo i = getRowItem(row); final AccountInfo i = getRowItem(row);
if (i != null && ((CheckBox) table.getWidget(row, 1)).getValue()) { if (i != null && ((CheckBox) table.getWidget(row, 1)).getValue()) {
ids.add(i.getAccountId()); ids.add(i._account_id());
} }
} }
if (!ids.isEmpty()) { if (!ids.isEmpty()) {
@@ -258,8 +257,8 @@ public class AccountGroupMembersScreen extends AccountGroupScreen {
new GerritCallback<VoidResult>() { new GerritCallback<VoidResult>() {
public void onSuccess(final VoidResult result) { public void onSuccess(final VoidResult result) {
for (int row = 1; row < table.getRowCount();) { for (int row = 1; row < table.getRowCount();) {
final MemberInfo i = getRowItem(row); final AccountInfo i = getRowItem(row);
if (i != null && ids.contains(i.getAccountId())) { if (i != null && ids.contains(i._account_id())) {
table.removeRow(row); table.removeRow(row);
} else { } else {
row++; row++;
@@ -270,11 +269,11 @@ public class AccountGroupMembersScreen extends AccountGroupScreen {
} }
} }
void display(final List<MemberInfo> result) { void display(final List<AccountInfo> result) {
while (1 < table.getRowCount()) while (1 < table.getRowCount())
table.removeRow(table.getRowCount() - 1); table.removeRow(table.getRowCount() - 1);
for (final MemberInfo i : result) { for (final AccountInfo i : result) {
final int row = table.getRowCount(); final int row = table.getRowCount();
table.insertRow(row); table.insertRow(row);
applyDataRowStyle(row); applyDataRowStyle(row);
@@ -282,22 +281,21 @@ public class AccountGroupMembersScreen extends AccountGroupScreen {
} }
} }
void insert(MemberInfo info) { void insert(AccountInfo info) {
Comparator<MemberInfo> c = new Comparator<MemberInfo>() { Comparator<AccountInfo> c = new Comparator<AccountInfo>() {
@Override @Override
public int compare(MemberInfo a, MemberInfo b) { public int compare(AccountInfo a, AccountInfo b) {
int cmp = nullToEmpty(a.fullName()).compareTo(nullToEmpty(b.fullName())); int cmp = nullToEmpty(a.name()).compareTo(nullToEmpty(b.name()));
if (cmp != 0) { if (cmp != 0) {
return cmp; return cmp;
} }
cmp = nullToEmpty(a.preferredEmail()).compareTo( cmp = nullToEmpty(a.email()).compareTo(nullToEmpty(b.email()));
nullToEmpty(b.preferredEmail()));
if (cmp != 0) { if (cmp != 0) {
return cmp; return cmp;
} }
return a.getAccountId().get() - b.getAccountId().get(); return a._account_id() - b._account_id();
} }
public String nullToEmpty(String str) { public String nullToEmpty(String str) {
@@ -309,7 +307,7 @@ public class AccountGroupMembersScreen extends AccountGroupScreen {
int right = table.getRowCount() - 1; int right = table.getRowCount() - 1;
while (left <= right) { while (left <= right) {
int middle = (left + right) >>> 1; // (left+right)/2 int middle = (left + right) >>> 1; // (left+right)/2
MemberInfo i = getRowItem(middle); AccountInfo i = getRowItem(middle);
int cmp = c.compare(i, info); int cmp = c.compare(i, info);
if (cmp < 0) { if (cmp < 0) {
@@ -328,12 +326,12 @@ public class AccountGroupMembersScreen extends AccountGroupScreen {
populate(insertPosition, info); populate(insertPosition, info);
} }
void populate(final int row, final MemberInfo i) { void populate(final int row, final AccountInfo i) {
CheckBox checkBox = new CheckBox(); CheckBox checkBox = new CheckBox();
table.setWidget(row, 1, checkBox); table.setWidget(row, 1, checkBox);
checkBox.setEnabled(enabled); checkBox.setEnabled(enabled);
table.setWidget(row, 2, new AccountLink(i.asAccountInfo())); table.setWidget(row, 2, new AccountLink(i));
table.setText(row, 3, i.preferredEmail()); table.setText(row, 3, i.email());
final FlexCellFormatter fmt = table.getFlexCellFormatter(); final FlexCellFormatter fmt = table.getFlexCellFormatter();
fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().iconCell()); fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().iconCell());

View File

@@ -20,6 +20,7 @@ import com.google.gerrit.client.ConfirmationCallback;
import com.google.gerrit.client.ConfirmationDialog; import com.google.gerrit.client.ConfirmationDialog;
import com.google.gerrit.client.ErrorDialog; import com.google.gerrit.client.ErrorDialog;
import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.account.AccountInfo;
import com.google.gerrit.client.changes.ChangeInfo.ApprovalInfo; import com.google.gerrit.client.changes.ChangeInfo.ApprovalInfo;
import com.google.gerrit.client.changes.ChangeInfo.LabelInfo; import com.google.gerrit.client.changes.ChangeInfo.LabelInfo;
import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.GerritCallback;

View File

@@ -14,6 +14,7 @@
package com.google.gerrit.client.changes; package com.google.gerrit.client.changes;
import com.google.gerrit.client.account.AccountInfo;
import com.google.gerrit.client.rpc.NativeMap; import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.NativeString; import com.google.gerrit.client.rpc.NativeString;
import com.google.gerrit.client.rpc.Natives; import com.google.gerrit.client.rpc.Natives;

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.client.changes;
import com.google.gerrit.client.Dispatcher; import com.google.gerrit.client.Dispatcher;
import com.google.gerrit.client.FormatUtil; import com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.account.AccountInfo;
import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.CommentPanel; import com.google.gerrit.client.ui.CommentPanel;
import com.google.gerrit.client.ui.ComplexDisclosurePanel; import com.google.gerrit.client.ui.ComplexDisclosurePanel;

View File

@@ -15,10 +15,10 @@
package com.google.gerrit.client.groups; package com.google.gerrit.client.groups;
import com.google.gerrit.client.VoidResult; import com.google.gerrit.client.VoidResult;
import com.google.gerrit.client.rpc.Natives; import com.google.gerrit.client.account.AccountInfo;
import com.google.gerrit.client.rpc.NativeString; import com.google.gerrit.client.rpc.NativeString;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.rpc.RestApi; import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup; import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray; import com.google.gwt.core.client.JsArray;
@@ -100,20 +100,20 @@ public class GroupApi {
/** Add member to a group. */ /** Add member to a group. */
public static void addMember(AccountGroup.UUID group, String member, public static void addMember(AccountGroup.UUID group, String member,
AsyncCallback<MemberInfo> cb) { AsyncCallback<AccountInfo> cb) {
members(group).id(member).put(cb); members(group).id(member).put(cb);
} }
/** Add members to a group. */ /** Add members to a group. */
public static void addMembers(AccountGroup.UUID group, public static void addMembers(AccountGroup.UUID group,
Set<String> members, Set<String> members,
final AsyncCallback<JsArray<MemberInfo>> cb) { final AsyncCallback<JsArray<AccountInfo>> cb) {
if (members.size() == 1) { if (members.size() == 1) {
addMember(group, addMember(group,
members.iterator().next(), members.iterator().next(),
new AsyncCallback<MemberInfo>() { new AsyncCallback<AccountInfo>() {
@Override @Override
public void onSuccess(MemberInfo result) { public void onSuccess(AccountInfo result) {
cb.onSuccess(Natives.arrayOf(result)); cb.onSuccess(Natives.arrayOf(result));
} }
@@ -133,14 +133,13 @@ public class GroupApi {
/** Remove members from a group. */ /** Remove members from a group. */
public static void removeMembers(AccountGroup.UUID group, public static void removeMembers(AccountGroup.UUID group,
Set<Account.Id> ids, final AsyncCallback<VoidResult> cb) { Set<Integer> ids, final AsyncCallback<VoidResult> cb) {
if (ids.size() == 1) { if (ids.size() == 1) {
Account.Id u = ids.iterator().next(); members(group).id(ids.iterator().next().toString()).delete(cb);
members(group).id(u.toString()).delete(cb);
} else { } else {
MemberInput in = MemberInput.create(); MemberInput in = MemberInput.create();
for (Account.Id u : ids) { for (Integer id : ids) {
in.add_member(u.toString()); in.add_member(id.toString());
} }
group(group).view("members.delete").post(in, cb); group(group).view("members.delete").post(in, cb);
} }

View File

@@ -1,36 +0,0 @@
// Copyright (C) 2013 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.client.groups;
import com.google.gerrit.client.changes.AccountInfo;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gwt.core.client.JavaScriptObject;
public class MemberInfo extends JavaScriptObject {
public final Account.Id getAccountId() {
return new Account.Id(account_id());
}
public final AccountInfo asAccountInfo() {
return AccountInfo.create(account_id(), fullName(), preferredEmail());
}
private final native int account_id() /*-{ return this.account_id || 0; }-*/;
public final native String fullName() /*-{ return this.full_name; }-*/;
public final native String preferredEmail() /*-{ return this.preferred_email; }-*/;
protected MemberInfo() {
}
}

View File

@@ -14,12 +14,13 @@
package com.google.gerrit.client.groups; package com.google.gerrit.client.groups;
import com.google.gerrit.client.account.AccountInfo;
import com.google.gerrit.client.rpc.RestApi; import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.reviewdb.client.AccountGroup; import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gwt.core.client.JsArray; import com.google.gwt.core.client.JsArray;
import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.AsyncCallback;
public class MemberList extends JsArray<MemberInfo> { public class MemberList extends JsArray<AccountInfo> {
public static void all(AccountGroup.UUID group, public static void all(AccountGroup.UUID group,
AsyncCallback<MemberList> callback) { AsyncCallback<MemberList> callback) {
new RestApi("/groups/").id(group.get()).view("members").get(callback); new RestApi("/groups/").id(group.get()).view("members").get(callback);

View File

@@ -17,7 +17,7 @@ package com.google.gerrit.client.patches;
import com.google.gerrit.client.Dispatcher; import com.google.gerrit.client.Dispatcher;
import com.google.gerrit.client.FormatUtil; import com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.changes.AccountInfo; import com.google.gerrit.client.account.AccountInfo;
import com.google.gerrit.client.changes.PatchTable; import com.google.gerrit.client.changes.PatchTable;
import com.google.gerrit.client.changes.Util; import com.google.gerrit.client.changes.Util;
import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.GerritCallback;

View File

@@ -16,7 +16,7 @@ package com.google.gerrit.client.ui;
import com.google.gerrit.client.FormatUtil; import com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.changes.AccountInfo; import com.google.gerrit.client.account.AccountInfo;
import com.google.gerrit.common.PageLinks; import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.data.AccountInfoCache; import com.google.gerrit.common.data.AccountInfoCache;
import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Account;

View File

@@ -16,7 +16,7 @@ package com.google.gerrit.client.ui;
import com.google.gerrit.client.FormatUtil; import com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.changes.AccountInfo; import com.google.gerrit.client.account.AccountInfo;
import com.google.gwt.event.dom.client.BlurEvent; import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler; import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickEvent;

View File

@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package com.google.gerrit.server.change; package com.google.gerrit.server.account;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@@ -21,8 +21,6 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountState;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Provider; import com.google.inject.Provider;
@@ -33,8 +31,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
public class AccountInfo { public class AccountInfo {
static class Loader { public static class Loader {
interface Factory { public interface Factory {
Loader create(boolean detailed); Loader create(boolean detailed);
} }
@@ -76,7 +74,7 @@ public class AccountInfo {
for (AccountInfo info : Iterables.concat(created.values(), provided)) { for (AccountInfo info : Iterables.concat(created.values(), provided)) {
AccountState state = accountCache.getIfPresent(info._id); AccountState state = accountCache.getIfPresent(info._id);
if (state != null) { if (state != null) {
fill(info, state.getAccount()); info.fill(state.getAccount(), detailed);
} else { } else {
missing.put(info._id, info); missing.put(info._id, info);
} }
@@ -84,7 +82,7 @@ public class AccountInfo {
if (!missing.isEmpty()) { if (!missing.isEmpty()) {
for (Account account : db.get().accounts().get(missing.keySet())) { for (Account account : db.get().accounts().get(missing.keySet())) {
for (AccountInfo info : missing.get(account.getId())) { for (AccountInfo info : missing.get(account.getId())) {
fill(info, account); info.fill(account, detailed);
} }
} }
} }
@@ -97,23 +95,29 @@ public class AccountInfo {
} }
fill(); fill();
} }
private void fill(AccountInfo info, Account account) {
info.name = account.getFullName();
if (detailed) {
info._account_id = account.getId().get();
info.email = account.getPreferredEmail();
}
}
} }
transient Account.Id _id; public static AccountInfo parse(Account a, boolean detailed) {
AccountInfo ai = new AccountInfo(a.getId());
ai.fill(a, detailed);
return ai;
}
protected AccountInfo(Account.Id id) { public transient Account.Id _id;
public AccountInfo(Account.Id id) {
_id = id; _id = id;
} }
public Integer _account_id; public Integer _account_id;
public String name; public String name;
public String email; public String email;
private void fill(Account account, boolean detailed) {
name = account.getFullName();
if (detailed) {
_account_id = account.getId().get();
email = account.getPreferredEmail();
}
}
} }

View File

@@ -56,6 +56,7 @@ import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.AnonymousUser; import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountInfo;
import com.google.gerrit.server.config.CanonicalWebUrl; import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.patch.PatchList; import com.google.gerrit.server.patch.PatchList;

View File

@@ -22,6 +22,7 @@ import static com.google.gerrit.server.change.RevisionResource.REVISION_KIND;
import com.google.gerrit.extensions.registration.DynamicMap; import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.RestApiModule; import com.google.gerrit.extensions.restapi.RestApiModule;
import com.google.gerrit.server.account.AccountInfo;
import com.google.gerrit.server.change.Reviewed.DeleteReviewed; import com.google.gerrit.server.change.Reviewed.DeleteReviewed;
import com.google.gerrit.server.change.Reviewed.PutReviewed; import com.google.gerrit.server.change.Reviewed.PutReviewed;
import com.google.gerrit.server.config.FactoryModule; import com.google.gerrit.server.config.FactoryModule;

View File

@@ -39,6 +39,7 @@ import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache; import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountInfo;
import com.google.gerrit.server.account.GroupMembers; import com.google.gerrit.server.account.GroupMembers;
import com.google.gerrit.server.change.PostReviewers.Input; import com.google.gerrit.server.change.PostReviewers.Input;
import com.google.gerrit.server.change.ReviewerJson.PostResult; import com.google.gerrit.server.change.ReviewerJson.PostResult;

View File

@@ -27,6 +27,7 @@ import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval; import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.account.AccountInfo;
import com.google.gerrit.server.project.ChangeControl; import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.query.change.ChangeData; import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.workflow.CategoryFunction; import com.google.gerrit.server.workflow.CategoryFunction;

View File

@@ -29,6 +29,7 @@ import com.google.gerrit.extensions.restapi.DefaultInput;
import com.google.gerrit.extensions.restapi.RestModifyView; import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.rules.RulesCache; import com.google.gerrit.rules.RulesCache;
import com.google.gerrit.server.account.AccountInfo;
import com.google.gerrit.server.change.TestSubmitRule.Input; import com.google.gerrit.server.change.TestSubmitRule.Input;
import com.google.gerrit.server.project.RuleEvalException; import com.google.gerrit.server.project.RuleEvalException;
import com.google.gerrit.server.project.SubmitRuleEvaluator; import com.google.gerrit.server.project.SubmitRuleEvaluator;

View File

@@ -35,6 +35,7 @@ import com.google.gerrit.server.BadRequestHandler;
import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache; import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountException; import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountInfo;
import com.google.gerrit.server.account.AccountManager; import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AccountResolver; import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.account.AccountsCollection; import com.google.gerrit.server.account.AccountsCollection;
@@ -42,7 +43,6 @@ import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.GroupControl; import com.google.gerrit.server.account.GroupControl;
import com.google.gerrit.server.config.AuthConfig; import com.google.gerrit.server.config.AuthConfig;
import com.google.gerrit.server.group.AddMembers.Input; import com.google.gerrit.server.group.AddMembers.Input;
import com.google.gerrit.server.group.MembersCollection.MemberInfo;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Provider; import com.google.inject.Provider;
@@ -94,7 +94,7 @@ class AddMembers implements RestModifyView<GroupResource, Input> {
} }
@Override @Override
public List<MemberInfo> apply(GroupResource resource, Input input) public List<AccountInfo> apply(GroupResource resource, Input input)
throws AuthException, MethodNotAllowedException, BadRequestException, throws AuthException, MethodNotAllowedException, BadRequestException,
OrmException { OrmException {
AccountGroup internalGroup = resource.toAccountGroup(); AccountGroup internalGroup = resource.toAccountGroup();
@@ -107,7 +107,7 @@ class AddMembers implements RestModifyView<GroupResource, Input> {
Map<Account.Id, AccountGroupMember> newAccountGroupMembers = Maps.newHashMap(); Map<Account.Id, AccountGroupMember> newAccountGroupMembers = Maps.newHashMap();
List<AccountGroupMemberAudit> newAccountGroupMemberAudits = Lists.newLinkedList(); List<AccountGroupMemberAudit> newAccountGroupMemberAudits = Lists.newLinkedList();
BadRequestHandler badRequest = new BadRequestHandler("adding new group members"); BadRequestHandler badRequest = new BadRequestHandler("adding new group members");
List<MemberInfo> result = Lists.newLinkedList(); List<AccountInfo> result = Lists.newLinkedList();
Account.Id me = ((IdentifiedUser) control.getCurrentUser()).getAccountId(); Account.Id me = ((IdentifiedUser) control.getCurrentUser()).getAccountId();
for (String nameOrEmail : input.members) { for (String nameOrEmail : input.members) {
@@ -136,7 +136,7 @@ class AddMembers implements RestModifyView<GroupResource, Input> {
newAccountGroupMemberAudits.add(new AccountGroupMemberAudit(m, me)); newAccountGroupMemberAudits.add(new AccountGroupMemberAudit(m, me));
} }
} }
result.add(MembersCollection.parse(a)); result.add(AccountInfo.parse(a, true));
} }
badRequest.failOnError(); badRequest.failOnError();
@@ -205,7 +205,7 @@ class AddMembers implements RestModifyView<GroupResource, Input> {
OrmException { OrmException {
AddMembers.Input in = new AddMembers.Input(); AddMembers.Input in = new AddMembers.Input();
in._oneMember = id; in._oneMember = id;
List<MemberInfo> list = put.get().apply(resource, in); List<AccountInfo> list = put.get().apply(resource, in);
if (list.size() == 1) { if (list.size() == 1) {
return list.get(0); return list.get(0);
} }

View File

@@ -15,11 +15,11 @@
package com.google.gerrit.server.group; package com.google.gerrit.server.group;
import com.google.gerrit.extensions.restapi.RestReadView; import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.group.MembersCollection.MemberInfo; import com.google.gerrit.server.account.AccountInfo;
public class GetMember implements RestReadView<MemberResource> { public class GetMember implements RestReadView<MemberResource> {
@Override @Override
public MemberInfo apply(MemberResource resource) { public AccountInfo apply(MemberResource resource) {
return MembersCollection.parse(resource.getMember().getAccount()); return AccountInfo.parse(resource.getMember().getAccount(), true);
} }
} }

View File

@@ -29,10 +29,9 @@ import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup; import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroupIncludeByUuid; import com.google.gerrit.reviewdb.client.AccountGroupIncludeByUuid;
import com.google.gerrit.reviewdb.client.AccountGroupMember; import com.google.gerrit.reviewdb.client.AccountGroupMember;
import com.google.gerrit.server.account.AccountCache; import com.google.gerrit.server.account.AccountInfo;
import com.google.gerrit.server.account.GroupCache; import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.GroupDetailFactory; import com.google.gerrit.server.account.GroupDetailFactory;
import com.google.gerrit.server.group.MembersCollection.MemberInfo;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
@@ -47,49 +46,49 @@ import java.util.Map;
public class ListMembers implements RestReadView<GroupResource> { public class ListMembers implements RestReadView<GroupResource> {
private final GroupCache groupCache; private final GroupCache groupCache;
private final GroupDetailFactory.Factory groupDetailFactory; private final GroupDetailFactory.Factory groupDetailFactory;
private final AccountCache accountCache; private final AccountInfo.Loader accountLoader;
@Option(name = "--recursive", usage = "to resolve included groups recursively") @Option(name = "--recursive", usage = "to resolve included groups recursively")
private boolean recursive; private boolean recursive;
@Inject @Inject
ListMembers(final GroupCache groupCache, ListMembers(GroupCache groupCache,
final GroupDetailFactory.Factory groupDetailFactory, GroupDetailFactory.Factory groupDetailFactory,
final AccountCache accountCache) { AccountInfo.Loader.Factory accountLoaderFactory) {
this.groupCache = groupCache; this.groupCache = groupCache;
this.groupDetailFactory = groupDetailFactory; this.groupDetailFactory = groupDetailFactory;
this.accountCache = accountCache; this.accountLoader = accountLoaderFactory.create(true);
} }
@Override @Override
public List<MemberInfo> apply(final GroupResource resource) public List<AccountInfo> apply(final GroupResource resource)
throws AuthException, BadRequestException, ResourceConflictException, throws AuthException, BadRequestException, ResourceConflictException,
ResourceNotFoundException, Exception { ResourceNotFoundException, Exception {
if (resource.toAccountGroup() == null) { if (resource.toAccountGroup() == null) {
throw new ResourceNotFoundException(resource.getGroupUUID().get()); throw new ResourceNotFoundException(resource.getGroupUUID().get());
} }
final Map<Account.Id, MemberInfo> members = final Map<Account.Id, AccountInfo> members =
getMembers(resource.getGroupUUID(), new HashSet<AccountGroup.UUID>()); getMembers(resource.getGroupUUID(), new HashSet<AccountGroup.UUID>());
final List<MemberInfo> memberInfos = Lists.newArrayList(members.values()); final List<AccountInfo> memberInfos = Lists.newArrayList(members.values());
Collections.sort(memberInfos, new Comparator<MemberInfo>() { Collections.sort(memberInfos, new Comparator<AccountInfo>() {
@Override @Override
public int compare(MemberInfo a, MemberInfo b) { public int compare(AccountInfo a, AccountInfo b) {
return ComparisonChain.start() return ComparisonChain.start()
.compare(a.fullName, b.fullName, Ordering.natural().nullsFirst()) .compare(a.name, b.name, Ordering.natural().nullsFirst())
.compare(a.preferredEmail, b.preferredEmail, Ordering.natural().nullsFirst()) .compare(a.email, b.email, Ordering.natural().nullsFirst())
.compare(a.id, b.id, Ordering.natural().nullsFirst()).result(); .compare(a._account_id, b._account_id, Ordering.natural().nullsFirst()).result();
} }
}); });
return memberInfos; return memberInfos;
} }
private Map<Account.Id, MemberInfo> getMembers( private Map<Account.Id, AccountInfo> getMembers(
final AccountGroup.UUID groupUUID, final AccountGroup.UUID groupUUID,
final HashSet<AccountGroup.UUID> seenGroups) throws OrmException, final HashSet<AccountGroup.UUID> seenGroups) throws OrmException,
NoSuchGroupException { NoSuchGroupException {
seenGroups.add(groupUUID); seenGroups.add(groupUUID);
final Map<Account.Id, MemberInfo> members = Maps.newHashMap(); final Map<Account.Id, AccountInfo> members = Maps.newHashMap();
final AccountGroup group = groupCache.get(groupUUID); final AccountGroup group = groupCache.get(groupUUID);
if (group == null) { if (group == null) {
// the included group is an external group and can't be resolved // the included group is an external group and can't be resolved
@@ -102,9 +101,7 @@ public class ListMembers implements RestReadView<GroupResource> {
if (groupDetail.members != null) { if (groupDetail.members != null) {
for (final AccountGroupMember m : groupDetail.members) { for (final AccountGroupMember m : groupDetail.members) {
if (!members.containsKey(m.getAccountId())) { if (!members.containsKey(m.getAccountId())) {
final Account account = members.put(m.getAccountId(), accountLoader.get(m.getAccountId()));
accountCache.get(m.getAccountId()).getAccount();
members.put(account.getId(), MembersCollection.parse(account));
} }
} }
} }
@@ -118,6 +115,7 @@ public class ListMembers implements RestReadView<GroupResource> {
} }
} }
} }
accountLoader.fill();
return members; return members;
} }
} }

View File

@@ -21,7 +21,6 @@ import com.google.gerrit.extensions.restapi.ChildCollection;
import com.google.gerrit.extensions.restapi.IdString; import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestView; import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroupMember; import com.google.gerrit.reviewdb.client.AccountGroupMember;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -86,28 +85,4 @@ public class MembersCollection implements
public DynamicMap<RestView<MemberResource>> views() { public DynamicMap<RestView<MemberResource>> views() {
return views; return views;
} }
public static MemberInfo parse(Account account) {
MemberInfo accountInfo = new MemberInfo();
accountInfo.setId(account.getId());
accountInfo.fullName = account.getFullName();
accountInfo.preferredEmail = account.getPreferredEmail();
accountInfo.userName = account.getUserName();
return accountInfo;
}
static class MemberInfo {
final String kind = "gerritcodereview#member";
String fullName;
String id;
int accountId;
String preferredEmail;
String userName;
void setId(Account.Id i) {
accountId = i.get();
id = Url.encode(Integer.toString(accountId));
}
}
} }