content: package com.ctrip.framework.apollo.portal.spi.ctrip;
  
  import com.google.common.collect.ImmutableMap;
  import com.google.common.collect.Lists;
  import com.google.common.collect.Maps;
  
  import com.ctrip.framework.apollo.portal.component.config.PortalConfig;
  import com.ctrip.framework.apollo.portal.entity.bo.UserInfo;
  import com.ctrip.framework.apollo.portal.spi.UserService;
  
  import org.springframework.core.ParameterizedTypeReference;
  import org.springframework.http.HttpEntity;
  import org.springframework.http.HttpMethod;
  import org.springframework.http.ResponseEntity;
  import org.springframework.http.client.ClientHttpRequestFactory;
  import org.springframework.http.client.SimpleClientHttpRequestFactory;
  import org.springframework.util.CollectionUtils;
  import org.springframework.web.client.RestTemplate;
  
  import java.util.Collections;
  import java.util.List;
  import java.util.Map;
  import java.util.stream.Collectors;
  
  /**
   * @author Jason Song(song_s@ctrip.com)
   */
  public class CtripUserService implements UserService {
    private RestTemplate restTemplate;
    private List<String> searchUserMatchFields;
    private ParameterizedTypeReference<Map<String, List<UserServiceResponse>>> responseType;
    private PortalConfig portalConfig;
  
    public CtripUserService(PortalConfig portalConfig) {
      this.portalConfig = portalConfig;
      this.restTemplate = new RestTemplate(clientHttpRequestFactory());
      this.searchUserMatchFields =
          Lists.newArrayList("empcode", "empaccount", "displayname", "c_name", "pinyin");
      this.responseType = new ParameterizedTypeReference<Map<String, List<UserServiceResponse>>>() {
      };
    }
  
    private ClientHttpRequestFactory clientHttpRequestFactory() {
      SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
      factory.setConnectTimeout(portalConfig.connectTimeout());
      factory.setReadTimeout(portalConfig.readTimeout());
  
      return factory;
    }
  
    @Override
    public List<UserInfo> searchUsers(String keyword, int offset, int limit) {
      UserServiceRequest request = assembleSearchUserRequest(keyword, offset, limit);
  
      HttpEntity<UserServiceRequest> entity = new HttpEntity<>(request);
      ResponseEntity<Map<String, List<UserServiceResponse>>> response =
          restTemplate.exchange(portalConfig.userServiceUrl(), HttpMethod.POST, entity, responseType);
  
      if (!response.getBody().containsKey("result")) {
        return Collections.emptyList();
      }
  
      List<UserInfo> result = Lists.newArrayList();
      result.addAll(
          response.getBody().get("result").stream().map(this::transformUserServiceResponseToUserInfo)
              .collect(Collectors.toList()));
  
      return result;
    }
  
    @Override
    public UserInfo findByUserId(String userId) {
      List<UserInfo> userInfoList = this.findByUserIds(Lists.newArrayList(userId));
      if (CollectionUtils.isEmpty(userInfoList)) {
        return null;
      }
      return userInfoList.get(0);
    }
  
    public List<UserInfo> findByUserIds(List<String> userIds) {
      UserServiceRequest request = assembleFindUserRequest(Lists.newArrayList(userIds));
  
      HttpEntity<UserServiceRequest> entity = new HttpEntity<>(request);
      ResponseEntity<Map<String, List<UserServiceResponse>>> response =
          restTemplate.exchange(portalConfig.userServiceUrl(), HttpMethod.POST, entity, responseType);
  
      if (!response.getBody().containsKey("result")) {
        return Collections.emptyList();
      }
  
      List<UserInfo> result = Lists.newArrayList();
      result.addAll(
          response.getBody().get("result").stream().map(this::transformUserServiceResponseToUserInfo)
              .collect(Collectors.toList()));
  
      return result;
    }
  
    private UserInfo transformUserServiceResponseToUserInfo(UserServiceResponse userServiceResponse) {
      UserInfo userInfo = new UserInfo();
      userInfo.setUserId(userServiceResponse.getEmpaccount());
      userInfo.setName(userServiceResponse.getDisplayname());
      userInfo.setEmail(userServiceResponse.getEmail());
      return userInfo;
    }
  
    UserServiceRequest assembleSearchUserRequest(String keyword, int offset, int limit) {
      Map<String, Object> query = Maps.newHashMap();
      Map<String, Object> multiMatchMap = Maps.newHashMap();
      multiMatchMap.put("fields", searchUserMatchFields);
      multiMatchMap.put("operator", "and");
      multiMatchMap.put("query", keyword);
      multiMatchMap.put("type", "best_fields");
      query.put("multi_match", multiMatchMap);
  
      return assembleUserServiceRequest(query, offset, limit);
    }
  
    UserServiceRequest assembleFindUserRequest(List<String> userIds) {
      Map<String, Object>
          query =
          ImmutableMap.of("filtered", ImmutableMap
              .of("filter", ImmutableMap.of("terms", ImmutableMap.of("empaccount", userIds))));
  
      return assembleUserServiceRequest(query, 0, userIds.size());
    }
  
    private UserServiceRequest assembleUserServiceRequest(Map<String, Object> query, int offset,
                                                          int limit) {
      UserServiceRequest request = new UserServiceRequest();
      request.setAccess_token(portalConfig.userServiceAccessToken());
  
      UserServiceRequestBody requestBody = new UserServiceRequestBody();
      requestBody.setIndexAlias("itdb_emloyee");
      requestBody.setType("emloyee");
      request.setRequest_body(requestBody);
  
      Map<String, Object> queryJson = Maps.newHashMap();
      requestBody.setQueryJson(queryJson);
  
      queryJson.put("query", query);
  
      queryJson.put("from", offset);
      queryJson.put("size", limit);
  
      return request;
    }
  
  
    static class UserServiceRequest {
      private String access_token;
      private UserServiceRequestBody request_body;
  
      public String getAccess_token() {
        return access_token;
      }
  
      public void setAccess_token(String access_token) {
        this.access_token = access_token;
      }
  
      public UserServiceRequestBody getRequest_body() {
        return request_body;
      }
  
      public void setRequest_body(
          UserServiceRequestBody request_body) {
        this.request_body = request_body;
      }
    }
  
    static class UserServiceRequestBody {
      private String indexAlias;
      private String type;
      private Map<String, Object> queryJson;
  
      public String getType() {
        return type;
      }
  
      public void setType(String type) {
        this.type = type;
      }
  
      public String getIndexAlias() {
        return indexAlias;
      }
  
      public void setIndexAlias(String indexAlias) {
        this.indexAlias = indexAlias;
      }
  
      public Map<String, Object> getQueryJson() {
        return queryJson;
      }
  
      public void setQueryJson(Map<String, Object> queryJson) {
        this.queryJson = queryJson;
      }
    }
  
    static class UserServiceResponse {
      private String empaccount;
      private String displayname;
      private String email;
  
      public String getEmpaccount() {
        return empaccount;
      }
  
      public void setEmpaccount(String empaccount) {
        this.empaccount = empaccount;
      }
  
      public String getDisplayname() {
        return displayname;
      }
  
      public void setDisplayname(String displayname) {
        this.displayname = displayname;
      }
  
      public String getEmail() {
        return email;
      }
  
      public void setEmail(String email) {
        this.email = email;
      }
    }
  
  }
  