diff --git a/components/project_management/src/java/main/com/topcoder/management/project/ProjectGroup.java b/components/project_management/src/java/main/com/topcoder/management/project/ProjectGroup.java index 57c84bb93..6f6566e7a 100644 --- a/components/project_management/src/java/main/com/topcoder/management/project/ProjectGroup.java +++ b/components/project_management/src/java/main/com/topcoder/management/project/ProjectGroup.java @@ -17,6 +17,16 @@ * @author TCSCODER * @version 1.0 */ + + /** + *

+ * Changes related to v5-groups-api + *

+ * + * @author dushyantb + * @version 1.1 + */ + public class ProjectGroup implements Serializable { /** * Represents group id @@ -27,6 +37,11 @@ public class ProjectGroup implements Serializable { * Represents group name */ private String name; + + /** + * Represent new Id format + */ + private String newId; /** * Constructor @@ -76,4 +91,20 @@ public String getName() { public void setName(String name) { this.name = name; } + + /** + * Getter for {@link #newId} + * @return + */ + public String getNewId() { + return newId; + } + + /** + * Setter for {@link #newId} + * @param newId + */ + public void setNewId(String newId) { + this.newId = newId; + } } diff --git a/conf/web/WEB-INF/applicationContext.xml b/conf/web/WEB-INF/applicationContext.xml index 26d5871b7..b99153ea1 100644 --- a/conf/web/WEB-INF/applicationContext.xml +++ b/conf/web/WEB-INF/applicationContext.xml @@ -467,6 +467,7 @@ parent="contestAction" scope="prototype"> + diff --git a/src/java/main/com/topcoder/direct/services/view/action/contest/launch/CommonAction.java b/src/java/main/com/topcoder/direct/services/view/action/contest/launch/CommonAction.java index 9681f6d5d..240f547b0 100644 --- a/src/java/main/com/topcoder/direct/services/view/action/contest/launch/CommonAction.java +++ b/src/java/main/com/topcoder/direct/services/view/action/contest/launch/CommonAction.java @@ -99,8 +99,15 @@ *
  • Add enable effort hours
  • * *

    + * + *

    + * Version 1.11 (Topcoder - Integrate Direct with Groups V5) + *

      + *
    • Refactor projectGroup to comply with v5
    • + *
    + *

    * - * @author BeBetter, pvmagacho, GreatKevin, bugbuka, GreatKevin + * @author BeBetter, pvmagacho, GreatKevin, bugbuka, GreatKevin, dushyantb * @version 1.10 */ public class CommonAction extends BaseContestFeeAction { @@ -575,7 +582,7 @@ public void setCategoryId(long categoryId) { public String getGroups() { try { TCSubject tcSubject = DirectUtils.getTCSubjectFromSession(); - Set projectGroups = DirectUtils.getGroups(tcSubject, userGroupsApiEndpoint); + Set> projectGroups = DirectUtils.getGroups(tcSubject, userGroupsApiEndpoint); setResult(projectGroups); } catch (Throwable e) { if (getModel() != null) { diff --git a/src/java/main/com/topcoder/direct/services/view/action/contest/launch/GetContestAction.java b/src/java/main/com/topcoder/direct/services/view/action/contest/launch/GetContestAction.java index 40b39123a..d1c95484a 100644 --- a/src/java/main/com/topcoder/direct/services/view/action/contest/launch/GetContestAction.java +++ b/src/java/main/com/topcoder/direct/services/view/action/contest/launch/GetContestAction.java @@ -21,6 +21,7 @@ import com.topcoder.direct.services.view.util.SessionData; import com.topcoder.management.deliverable.Submission; import com.topcoder.management.project.Prize; +import com.topcoder.management.project.ProjectGroup; import com.topcoder.management.resource.Resource; import com.topcoder.management.resource.ResourceRole; import com.topcoder.security.TCSubject; @@ -37,13 +38,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** *

    @@ -274,6 +269,14 @@ * * @author fabrizyo, FireIce, isv, morehappiness, GreatKevin, minhu, Veve, Ghost_141, GreatKevin, Veve, GreatKevin, TCSCODER * @version 3.5 + * + * *

    + * Version 3.6 - Topcoder - Integrate Direct with Groups V5 + * - Refactor projectGroup to comply with v5 + *

    + * + * @author fabrizyo, FireIce, isv, morehappiness, GreatKevin, minhu, Veve, Ghost_141, GreatKevin, Veve, GreatKevin, TCSCODER, dushyantb + * @version 3.6 */ public class GetContestAction extends ContestAction { /** @@ -401,6 +404,11 @@ public class GetContestAction extends ContestAction { */ private boolean showSaveChallengeConfirmation; + /** + * Endpoint to group of a user + */ + private String userGroupsApiEndpoint; + /** *

    * Creates a GetContestAction instance. @@ -463,8 +471,23 @@ protected void executeAction() throws Exception { if (DirectUtils.isStudio(softwareCompetition)) { softwareCompetition.setType(CompetionType.STUDIO); } - softwareCompetition.getProjectHeader().setGroups(DirectUtils.getGroupIdAndName( - softwareCompetition.getProjectHeader().getGroups())); + List projectGroups = DirectUtils.getGroupIdAndName( + softwareCompetition.getProjectHeader().getGroups()); + + if (this.type == TYPE.CONTEST_JSON) { + // get v5 id of groups + Set> projectGroupUser = DirectUtils.getGroups(DirectUtils.getTCSubjectFromSession(), + userGroupsApiEndpoint); + for (ProjectGroup pg : projectGroups) { + for (Map pgu : projectGroupUser) { + if (String.valueOf(pg.getId()).equals(pgu.get("oldId"))) { + pg.setNewId(pgu.get("id")); + break; + } + } + } + } + softwareCompetition.getProjectHeader().setGroups(projectGroups); setResult(softwareCompetition); regEndDate = DirectUtils.getDateString(DirectUtils.getRegistrationEndDate(softwareCompetition)); @@ -974,4 +997,12 @@ public boolean isShowSaveChallengeConfirmation() { return showSaveChallengeConfirmation; } + public String getUserGroupsApiEndpoint() { + return userGroupsApiEndpoint; + } + + public void setUserGroupsApiEndpoint(String userGroupsApiEndpoint) { + this.userGroupsApiEndpoint = userGroupsApiEndpoint; + } + } diff --git a/src/java/main/com/topcoder/direct/services/view/action/contest/launch/GetGroupMemberAction.java b/src/java/main/com/topcoder/direct/services/view/action/contest/launch/GetGroupMemberAction.java index 3da8a7413..dc31dc0bc 100644 --- a/src/java/main/com/topcoder/direct/services/view/action/contest/launch/GetGroupMemberAction.java +++ b/src/java/main/com/topcoder/direct/services/view/action/contest/launch/GetGroupMemberAction.java @@ -3,8 +3,8 @@ */ package com.topcoder.direct.services.view.action.contest.launch; +import com.topcoder.direct.services.exception.DirectException; import com.topcoder.direct.services.view.dto.contest.GroupMember; -import com.topcoder.direct.services.view.dto.my.RestResult; import com.topcoder.direct.services.view.util.DirectUtils; import com.topcoder.direct.services.view.util.SortedCacheAddress; import com.topcoder.web.common.cache.CacheClient; @@ -17,13 +17,15 @@ import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.utils.URIBuilder; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.log4j.Logger; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.map.DeserializationConfig; import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.TypeReference; -import java.net.URI; +import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -35,6 +37,13 @@ * This action handle group member search for given list of groups and substringof user's handle * * @version 1.0 + * + * Version 1.1 (Topcoder - Integrate Direct with Groups V5) + *

      + *
    • Refactor projectGroup to comply with v5
    • + *
    + * @author TCSCODER + * @version 1.1 */ class GetGroupMemberAction extends ContestAction { /** @@ -47,10 +56,30 @@ class GetGroupMemberAction extends ContestAction { */ private static final int DEFAULT_LIMIT = 20; + /** + * Url parameter for perPage + */ + private static final String PER_PAGE = "perPage"; + + /** + * Url parameter for page + */ + private static final String PAGE = "page"; + + /** + * Response header for X-Total-Pages + */ + private static final String X_TOTAL_PAGE = "X-Total-Pages"; + + /** + * Default value url parameter perPage + */ + private static final String PER_PAGE_VALUE = "1000"; + /** * List of source group id */ - private List groupIds; + private List groupIds; /** * Group api endpoint @@ -80,7 +109,7 @@ class GetGroupMemberAction extends ContestAction { @Override protected void executeAction() throws Exception { try { - List> membersGroup = getData(); + List> membersGroup = getData(groupIds); CollectionUtils.filter(membersGroup, new Predicate() { @Override public boolean evaluate(Object o) { @@ -97,12 +126,12 @@ public boolean evaluate(Object o) { /** * Get list of user id and handle. It will try to get from cache first. - * + * @param groupIds list of group ids * @return List of userHandlePair * @throws Exception if any exception occur */ @SuppressWarnings("unchecked") - private List> getData() throws Exception { + private List> getData(List groupIds) throws Exception { CacheClient cc = null; List> data = null; SortedCacheAddress cacheAddress = new SortedCacheAddress("group_member", MaxAge.HOUR); @@ -117,7 +146,7 @@ private List> getData() throws Exception { } if (data == null){ - Set groupMembers = getGroupMembers(); + Set groupMembers = getGroupMembers(groupIds); data = DirectUtils.getUsersFromId(groupMembers.toArray(new Long[groupMembers.size()])); try{ cc.set(cacheAddress, data, MaxAge.HOUR); @@ -131,35 +160,36 @@ private List> getData() throws Exception { /** * Get all group member user id from API - * + * @param groupIds list of group ids * @return set of userId * @throws Exception if any exception occur */ - private Set getGroupMembers() throws Exception{ + private Set getGroupMembers(List groupIds) throws Exception{ Set members = new HashSet(); // this will be increased, for inner groups - LinkedList gids = new LinkedList(groupIds); - Set gidProcessed = new HashSet(); + LinkedList gids = new LinkedList(groupIds); + Set gidProcessed = new HashSet(); + + CacheClient cc = null; boolean finished = false; while (!finished) { - ListIterator iter = gids.listIterator(); + ListIterator iter = gids.listIterator(); finished = true; while (iter.hasNext()) { - Long gid = iter.next(); + String gid = iter.next(); if (!gidProcessed.contains(gid)) { logger.info("processing gid: " + gid); - RestResult result = getGroupMemberByGid(gid); - if (result != null) { - for (GroupMember gm : result.getContent()) { - if (gm.isGroup()) { - if (!gids.contains(gm.getMemberId())) { - iter.add(gm.getMemberId()); - finished = false; - } - logger.info(" inner group: " + gm.getMemberId()); - } else { - members.add(gm.getMemberId()); + List result = getGroupMemberByGid(gid); + + for (GroupMember gm : result) { + if (gm.isGroup()) { + if (!gids.contains(gm.getMemberId())) { + iter.add(gm.getMemberId()); + finished = false; } + logger.info(" inner group: " + gm.getMemberId()); + } else { + members.add(Long.valueOf(gm.getMemberId())); } } gidProcessed.add(gid); @@ -177,39 +207,52 @@ private Set getGroupMembers() throws Exception{ * @return a RestResult of groupMember * @throws Exception if any exception occur */ - private RestResult getGroupMemberByGid(Long gid) throws Exception { + private List getGroupMemberByGid(String gid) throws Exception { DefaultHttpClient httpClient = new DefaultHttpClient(); + List result = new ArrayList(); + int page = 1; JsonNode jsonNode = null; try{ - URI groupApiEndpointUri = new URI(String.format(groupApiEndpoint, gid)); - HttpGet request = new HttpGet(groupApiEndpointUri); - String jwtToken = getSessionData().getToken(); - - request.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + jwtToken); - request.addHeader(HttpHeaders.ACCEPT, "application/json"); - HttpResponse response = httpClient.execute(request); - HttpEntity entity = response.getEntity(); - - if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { - logger.error("Failed to get Group Member for " + gid + " - " + response.getStatusLine().toString()); - return null; - } + boolean finished = false; + URIBuilder groupApiEndpointUri = new URIBuilder(String.format(groupApiEndpoint, gid)); + while (!finished) { + groupApiEndpointUri.setParameter(PER_PAGE, PER_PAGE_VALUE); + groupApiEndpointUri.setParameter(PAGE, String.valueOf(page)); + HttpGet request = new HttpGet(groupApiEndpointUri.build()); + String jwtToken = getSessionData().getToken(); + + request.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + jwtToken); + request.addHeader(HttpHeaders.ACCEPT, "application/json"); + HttpResponse response = httpClient.execute(request); + HttpEntity entity = response.getEntity(); - jsonNode = objectMapper.readTree(entity.getContent()); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + logger.error("Failed to get Group Member for " + gid + " - " + response.getStatusLine().toString()); + throw new DirectException("Fail to get group member from group api"); + } + jsonNode = objectMapper.readTree(entity.getContent()); + List groupMembers = objectMapper.readValue(jsonNode.path("result"), + new TypeReference>(){}); + for (GroupMember groupMember : groupMembers) { + result.add(groupMember); + } + String totalPage = DirectUtils.getHeader(response.getAllHeaders(), X_TOTAL_PAGE); + finished = (page == Integer.valueOf(totalPage)); + page++; + } } finally { httpClient.getConnectionManager().shutdown(); } - return objectMapper.readValue(jsonNode.get("result"), - objectMapper.getTypeFactory().constructParametricType(RestResult.class, GroupMember.class)); + return result; } - public List getGroupIds() { + public List getGroupIds() { return groupIds; } - public void setGroupIds(List groupIds) { + public void setGroupIds(List groupIds) { this.groupIds = groupIds; } diff --git a/src/java/main/com/topcoder/direct/services/view/ajax/SoftwareCompetitionBeanProcessor.java b/src/java/main/com/topcoder/direct/services/view/ajax/SoftwareCompetitionBeanProcessor.java index 5a543a28f..6f85d0cd9 100644 --- a/src/java/main/com/topcoder/direct/services/view/ajax/SoftwareCompetitionBeanProcessor.java +++ b/src/java/main/com/topcoder/direct/services/view/ajax/SoftwareCompetitionBeanProcessor.java @@ -1,12 +1,9 @@ /* - * Copyright (C) 2010 - 2017 TopCoder Inc., All Rights Reserved. + * Copyright (C) 2010 - 2019 TopCoder Inc., All Rights Reserved. */ package com.topcoder.direct.services.view.ajax; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.List; +import java.util.*; import com.topcoder.management.project.ProjectGroup; import com.topcoder.management.project.ProjectPlatform; @@ -136,6 +133,13 @@ * @author BeBetter, TCSDEVELOPER, morehappiness, bugbuka, GreatKevin, TCSCODER * @version 2.5 * @since Direct - View/Edit/Activate Software Contests Assembly + * + * Version 2.6 (Topcoder - Integrate Direct with Groups V5) + *
      + *
    • Refactor projectGroup to comply with v5
    • + *
    + * + * @version 2.6 */ public class SoftwareCompetitionBeanProcessor implements JsonBeanProcessor { /** @@ -313,9 +317,10 @@ public Object transform(Object object) { })); } + // group api v5 use ProjectGroup.newId as id result.put("groupIds", CollectionUtils.collect(bean.getProjectHeader().getGroups(), new Transformer() { public Object transform(Object object) { - return ((ProjectGroup) object).getId(); + return ((ProjectGroup) object).getNewId(); } })); diff --git a/src/java/main/com/topcoder/direct/services/view/dto/contest/GroupMember.java b/src/java/main/com/topcoder/direct/services/view/dto/contest/GroupMember.java index beba2a131..ec247cab6 100644 --- a/src/java/main/com/topcoder/direct/services/view/dto/contest/GroupMember.java +++ b/src/java/main/com/topcoder/direct/services/view/dto/contest/GroupMember.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 TopCoder Inc., All Rights Reserved. + * Copyright (C) 2017 - 2019 TopCoder Inc., All Rights Reserved. */ package com.topcoder.direct.services.view.dto.contest; @@ -7,6 +7,13 @@ * Group member dto * * @version 1.0 + * + * Version 1.1 (Topcoder - Integrate Direct with Groups V5) + *
      + *
    • Refactor projectGroup to comply with v5
    • + *
    + * @author TCSCODER + * @version 1.1 */ public class GroupMember { public static final String GROUP = "group"; @@ -14,7 +21,7 @@ public class GroupMember { /** * Member id */ - private Long memberId; + private String memberId; /** * Membership type: @@ -25,11 +32,11 @@ public class GroupMember { public GroupMember() { } - public Long getMemberId() { + public String getMemberId() { return memberId; } - public void setMemberId(Long memberId) { + public void setMemberId(String memberId) { this.memberId = memberId; } diff --git a/src/java/main/com/topcoder/direct/services/view/util/DirectUtils.java b/src/java/main/com/topcoder/direct/services/view/util/DirectUtils.java index c61ed3623..7d7a46ecb 100644 --- a/src/java/main/com/topcoder/direct/services/view/util/DirectUtils.java +++ b/src/java/main/com/topcoder/direct/services/view/util/DirectUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 - 2018 TopCoder Inc., All Rights Reserved. + * Copyright (C) 2010 - 2019 TopCoder Inc., All Rights Reserved. */ package com.topcoder.direct.services.view.util; @@ -86,10 +86,7 @@ import eu.medsea.mimeutil.MimeUtil; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; -import org.apache.http.HttpEntity; -import org.apache.http.HttpHeaders; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; +import org.apache.http.*; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.utils.URIBuilder; import org.apache.http.impl.client.DefaultHttpClient; @@ -764,6 +761,12 @@ *

    * @author BeBetter, isv, flexme, Blues, Veve, GreatKevin, minhu, FireIce, Ghost_141, jiajizhou86, TCSCODER * @version 2.5 + * + * Version 2.6 (Topcoder - Integrate Direct with Groups V5) + *
      + *
    • Refactor all projectGroup to use v5 of api
    • + *
    + * @version 2.6 */ public final class DirectUtils { @@ -1030,6 +1033,16 @@ public final class DirectUtils { */ private static final String AWS_CREDENTIALS_FILE = "AwsS3Credentials.properties"; + /** + * Url parameter for perPage + */ + private static final String PER_PAGE = "perPage"; + + /** + * Default value url parameter perPage + */ + private static final String PER_PAGE_VALUE = "1000"; + /** * The jackson object mapping which is used to deserialize json return from API to domain model. */ @@ -3858,19 +3871,21 @@ public static List getGroupIdAndName(List projectGro * @return set of group * @throws Exception */ - public static Set getGroupsFromApi(TCSubject tcSubject, String endpoint) throws Exception { + public static Set> getGroupsFromApi(TCSubject tcSubject, String endpoint) throws Exception { URIBuilder uri = new URIBuilder(endpoint); if (!DirectUtils.isCockpitAdmin(tcSubject) && !DirectUtils.isTcStaff(tcSubject)) { uri.setParameter("memberId", String.valueOf(tcSubject.getUserId())); } + uri.setParameter(PER_PAGE, PER_PAGE_VALUE); DefaultHttpClient httpClient = new DefaultHttpClient(); HttpGet getRequest = new HttpGet(uri.build()); logger.info("Getting Group with thi uri: " + uri.build().toString()); String jwtToken = new SessionData(ServletActionContext.getRequest().getSession()).getToken(); + getRequest.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + jwtToken); getRequest.addHeader(HttpHeaders.ACCEPT, "application/json"); @@ -3882,12 +3897,20 @@ public static Set getGroupsFromApi(TCSubject tcSubject, String end throw new Exception("Unable to get groups from the API:" + httpResponse.getStatusLine().getReasonPhrase()); } - JsonNode result = objectMapper.readTree(entity.getContent()); - JsonNode groups = result.path("result").path("content"); - Set groupResults = new HashSet(); + JsonNode groups = objectMapper.readTree(entity.getContent()); + + Set> groupResults = new HashSet>(); for (JsonNode group : groups) { - ProjectGroup pg = new ProjectGroup(group.get("id").asLong(), group.get("name").asText()); - groupResults.add(pg); + Map groupMap = new HashMap(); + groupMap.put("id", group.get("id").asText()); + groupMap.put("name", group.get("name").asText()); + if (group.get("oldId") == null) { + logger.error("OldId is required - skip this group: " + group.get("id").asText()); + continue; + } else { + groupMap.put("oldId", group.get("oldId").asText()); + } + groupResults.add(groupMap); } return groupResults; } @@ -3900,14 +3923,14 @@ public static Set getGroupsFromApi(TCSubject tcSubject, String end * @return set of groupfor user * @throws Exception */ - public static Set getGroups(TCSubject tcSubject, String endpoint) throws Exception { + public static Set> getGroups(TCSubject tcSubject, String endpoint) throws Exception { CacheClient cc = null; - Set projectGroups = null; + Set> projectGroups = null; SortedCacheAddress cacheAddress = new SortedCacheAddress("user_group", MaxAge.FIVE_MINUTES); - cacheAddress.add(tcSubject.getUserId()); + cacheAddress.add(String.valueOf(tcSubject.getUserId())); try { cc = CacheClientFactory.create(); - projectGroups = (Set) cc.get(cacheAddress); + projectGroups = (Set>) cc.get(cacheAddress); } catch (Exception e) { logger.info("Can't get group for user " + tcSubject.getUserId() + " from cache"); } @@ -4129,4 +4152,21 @@ public static String createStudioLocalFilePath(long projectId, long userId, Stri buf.append(parameter); return buf.toString(); } + + /** + * Get http header value from array of headers + * + * @param headers array of headers + * @param name http header name + * @return http header value + */ + public static String getHeader(Header[] headers, String name) { + if (name == null || headers == null) return null; + for (Header header : headers) { + if (name.equalsIgnoreCase(header.getName())) { + return header.getValue(); + } + } + return null; + } } diff --git a/src/java/main/com/topcoder/direct/services/view/util/SortedCacheAddress.java b/src/java/main/com/topcoder/direct/services/view/util/SortedCacheAddress.java index dc6e99605..542022600 100644 --- a/src/java/main/com/topcoder/direct/services/view/util/SortedCacheAddress.java +++ b/src/java/main/com/topcoder/direct/services/view/util/SortedCacheAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 TopCoder Inc., All Rights Reserved. + * Copyright (C) 2017 - 2019 TopCoder Inc., All Rights Reserved. */ package com.topcoder.direct.services.view.util; @@ -15,6 +15,12 @@ * return a sorted keys on {@link #getKey()} * * @version 1.0 + * + * Version 1.1 (Topcoder - Integrate Direct with Groups V5) + *
      + *
    • Change key use String
    • + *
    + * @version 1.1 */ public class SortedCacheAddress implements JbossCacheAddress { /** @@ -32,7 +38,7 @@ public class SortedCacheAddress implements JbossCacheAddress { /** * List of items for key */ - private List items = new ArrayList(); + private List items = new ArrayList(); public SortedCacheAddress() { this(DEFAULT_PREFIX); @@ -51,7 +57,7 @@ public SortedCacheAddress(String prefix, MaxAge maxAge) { * * @param item item to add */ - public void add(Long item) { + public void add(String item) { items.add(item); Collections.sort(items); } @@ -61,7 +67,7 @@ public void add(Long item) { * * @param added list of item yo add */ - public void addAll(List added) { + public void addAll(List added) { items.addAll(added); Collections.sort(items); } @@ -71,7 +77,7 @@ public void addAll(List added) { * * @param item item to be removed */ - public void remove (Long item) { + public void remove (String item) { items.remove(item); } @@ -84,9 +90,9 @@ public void remove (Long item) { public String getKey() { StringBuffer keyBuffer = new StringBuffer(prefix); - for (Long item : items) { + for (String item : items) { keyBuffer.append("-"); - keyBuffer.append(String.valueOf(item)); + keyBuffer.append(item); } return keyBuffer.toString(); } diff --git a/src/web/scripts/launch/main.js b/src/web/scripts/launch/main.js index 5a04f09ef..6503360f6 100644 --- a/src/web/scripts/launch/main.js +++ b/src/web/scripts/launch/main.js @@ -1359,7 +1359,7 @@ function saveAsDraftRequest() { .magicSuggest() .getSelection(); request['groups'] = $.map(selectedGroups, function(val, i) { - return val.id.toString(); + return val.oldId.toString(); }); var copilotCost = parseFloat(mainWidget.softwareCompetition.copilotCost);