From 4390d5112eec0299dbbd391701536d7b54685a12 Mon Sep 17 00:00:00 2001 From: Dushyant Bhalgami Date: Tue, 15 Oct 2019 12:31:39 +0530 Subject: [PATCH] changes to integrate v5-groups-api in direct --- .../management/project/ProjectGroup.java | 31 +++++ conf/web/WEB-INF/applicationContext.xml | 1 + .../action/contest/launch/CommonAction.java | 11 +- .../contest/launch/GetContestAction.java | 49 +++++-- .../contest/launch/GetGroupMemberAction.java | 129 ++++++++++++------ .../SoftwareCompetitionBeanProcessor.java | 17 ++- .../view/dto/contest/GroupMember.java | 15 +- .../services/view/util/DirectUtils.java | 70 ++++++++-- .../view/util/SortedCacheAddress.java | 20 ++- src/web/scripts/launch/main.js | 2 +- 10 files changed, 258 insertions(+), 87 deletions(-) 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 * *
+ * Changes related to v5-groups-api + *
+ * Version 1.11 (Topcoder - Integrate Direct with Groups V5) + *
@@ -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 + *
* 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 extends Map> membersGroup = getData(); + List extends Map> 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 extends Map> getData() throws Exception { + private List extends Map> getData(List groupIds) throws Exception { CacheClient cc = null; List extends Map> data = null; SortedCacheAddress cacheAddress = new SortedCacheAddress("group_member", MaxAge.HOUR); @@ -117,7 +146,7 @@ private List extends Map> 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 extends Map> 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 @@ *
GetContestAction