/**
   * Returns an array of claims of the authorized user. This is for the OpenIDConnect user-end-point
   * implementation.
   *
   * <p>TODO : 1. Should return the userinfo response instead. TODO : 2. Should create another
   * service API for userinfo endpoint
   *
   * @param accessTokenIdentifier
   * @return
   * @throws IdentityException
   */
  public Claim[] getUserClaims(String accessTokenIdentifier) {

    OAuth2TokenValidationRequestDTO reqDTO = new OAuth2TokenValidationRequestDTO();
    OAuth2TokenValidationRequestDTO.OAuth2AccessToken accessToken = reqDTO.new OAuth2AccessToken();
    accessToken.setTokenType("bearer");
    accessToken.setIdentifier(accessTokenIdentifier);
    reqDTO.setAccessToken(accessToken);
    OAuth2TokenValidationResponseDTO respDTO = new OAuth2TokenValidationService().validate(reqDTO);

    String username = respDTO.getAuthorizedUser();
    if (username == null) { // invalid token
      log.debug(respDTO.getErrorMsg());
      return new Claim[0];
    }
    String[] scope = respDTO.getScope();
    boolean isOICScope = false;
    for (String curScope : scope) {
      if ("openid".equals(curScope)) {
        isOICScope = true;
      }
    }
    if (!isOICScope) {
      log.error("AccessToken does not have the openid scope");
      return new Claim[0];
    }

    // TODO : this code is ugly
    String profileName = "default"; // TODO : configurable
    String tenantDomain = MultitenantUtils.getTenantDomain(username);
    String tenatUser = MultitenantUtils.getTenantAwareUsername(username);

    List<Claim> claimsList = new ArrayList<Claim>();

    // MUST claim
    // http://openid.net/specs/openid-connect-basic-1_0-22.html#id_res
    Claim subClaim = new Claim();
    subClaim.setClaimUri("sub");
    subClaim.setValue(username);
    claimsList.add(subClaim);

    try {
      UserStoreManager userStore =
          IdentityTenantUtil.getRealm(tenantDomain, tenatUser).getUserStoreManager();
      // externel configured claims
      String[] claims = OAuthServerConfiguration.getInstance().getSupportedClaims();
      if (claims != null) {
        Map<String, String> extClaimsMap =
            userStore.getUserClaimValues(username, claims, profileName);
        for (Map.Entry<String, String> entry : extClaimsMap.entrySet()) {
          Claim curClaim = new Claim();
          curClaim.setClaimUri(entry.getKey());
          curClaim.setValue(entry.getValue());
          claimsList.add(curClaim);
        }
      }
      // default claims
      String[] defaultClaims = new String[3];
      defaultClaims[0] = "http://wso2.org/claims/emailaddress";
      defaultClaims[1] = "http://wso2.org/claims/givenname";
      defaultClaims[2] = "http://wso2.org/claims/lastname";
      String emailAddress = null;
      String firstName = null;
      String lastName = null;
      Map<String, String> defClaimsMap =
          userStore.getUserClaimValues(username, defaultClaims, profileName);
      if (defClaimsMap.get(defaultClaims[0]) != null) {
        emailAddress = defClaimsMap.get(defaultClaims[0]);
        Claim email = new Claim();
        email.setClaimUri("email");
        email.setValue(emailAddress);
        claimsList.add(email);
        Claim prefName = new Claim();
        prefName.setClaimUri("preferred_username");
        prefName.setValue(emailAddress.split("@")[0]);
        claimsList.add(prefName);
      }
      if (defClaimsMap.get(defaultClaims[1]) != null) {
        firstName = defClaimsMap.get(defaultClaims[1]);
        Claim givenName = new Claim();
        givenName.setClaimUri("given_name");
        givenName.setValue(firstName);
        claimsList.add(givenName);
      }
      if (defClaimsMap.get(defaultClaims[2]) != null) {
        lastName = defClaimsMap.get(defaultClaims[2]);
        Claim familyName = new Claim();
        familyName.setClaimUri("family_name");
        familyName.setValue(lastName);
        claimsList.add(familyName);
      }
      if (firstName != null && lastName != null) {
        Claim name = new Claim();
        name.setClaimUri("name");
        name.setValue(firstName + " " + lastName);
        claimsList.add(name);
      }

    } catch (Exception e) {
      log.error("Error while reading user claims ", e);
    }

    Claim[] allClaims = new Claim[claimsList.size()];
    for (int i = 0; i < claimsList.size(); i++) {
      allClaims[i] = claimsList.get(i);
    }
    return allClaims;
  }
  public void doClaimStuff() throws Exception {
    UserStoreManager usWriter = realm.getUserStoreManager();
    String[] allClaims = {
      ClaimTestUtil.CLAIM_URI1, ClaimTestUtil.CLAIM_URI2, ClaimTestUtil.CLAIM_URI3
    };

    // add DEFAULT
    usWriter.setUserClaimValue("dimuthu", ClaimTestUtil.CLAIM_URI1, "claim1default", null);
    try {
      usWriter.setUserClaimValue(null, ClaimTestUtil.CLAIM_URI1, "claim1default", null);
      fail("Exception at set claim values to null users");
    } catch (Exception e) {
      // expected exception
      if (log.isDebugEnabled()) {
        log.debug("Expected error, hence ignored", e);
      }
    }
    try {
      usWriter.setUserClaimValue("isuru", null, "claim1default", null);
      fail("Exception at set claim values to null claimURI");
    } catch (Exception e) {
      // expected exception
      if (log.isDebugEnabled()) {
        log.debug("Expected error, hence ignored", e);
      }
    }
    try {
      usWriter.setUserClaimValue("isuru", ClaimTestUtil.CLAIM_URI1, null, null);
      fail("Exception at set claim values to null claimValue");
    } catch (Exception e) {
      // expected exception
      if (log.isDebugEnabled()) {
        log.debug("Expected error, hence ignored", e);
      }
    }

    String value = usWriter.getUserClaimValue("dimuthu", ClaimTestUtil.CLAIM_URI1, null);
    assertEquals("claim1default", value);
    // Non existing user
    String value1 = usWriter.getUserClaimValue("isuru", ClaimTestUtil.CLAIM_URI1, null);
    assertEquals(null, value1);
    // update default
    usWriter.setUserClaimValue("dimuthu", ClaimTestUtil.CLAIM_URI1, "dimzi lee", null);
    value = usWriter.getUserClaimValue("dimuthu", ClaimTestUtil.CLAIM_URI1, null);
    assertEquals("dimzi lee", value);

    // multiple additions
    Map<String, String> map = new HashMap<String, String>();
    map.put(ClaimTestUtil.CLAIM_URI1, "lee");
    map.put(ClaimTestUtil.CLAIM_URI3, "muthu");

    usWriter.setUserClaimValue("dimuthu", ClaimTestUtil.CLAIM_URI2, "claim2default", null);
    assertEquals(
        "dimzi lee", usWriter.getUserClaimValue("dimuthu", ClaimTestUtil.CLAIM_URI1, null));
    assertEquals(
        "claim2default", usWriter.getUserClaimValue("dimuthu", ClaimTestUtil.CLAIM_URI2, null));
    assertNull(usWriter.getUserClaimValue("dimuthu", ClaimTestUtil.CLAIM_URI3, null));

    usWriter.setUserClaimValues("dimuthu", map, ClaimTestUtil.HOME_PROFILE_NAME);
    assertEquals(
        "lee",
        usWriter.getUserClaimValue(
            "dimuthu", ClaimTestUtil.CLAIM_URI1, ClaimTestUtil.HOME_PROFILE_NAME));
    assertNull(
        usWriter.getUserClaimValue(
            "dimuthu", ClaimTestUtil.CLAIM_URI2, ClaimTestUtil.HOME_PROFILE_NAME));
    assertEquals(
        "muthu",
        usWriter.getUserClaimValue(
            "dimuthu", ClaimTestUtil.CLAIM_URI3, ClaimTestUtil.HOME_PROFILE_NAME));

    usWriter.setUserClaimValue(
        "dimuthu",
        UserCoreConstants.PROFILE_CONFIGURATION,
        ClaimTestUtil.HOME_PROFILE_NAME,
        ClaimTestUtil.HOME_PROFILE_NAME);
    Map<String, String> obtained =
        usWriter.getUserClaimValues("dimuthu", allClaims, ClaimTestUtil.HOME_PROFILE_NAME);
    // assertNull(obtained.get(ClaimTestUtil.CLAIM_URI1)); // hidden
    // assertEquals("claim2default", obtained.get(ClaimTestUtil.CLAIM_URI2)); // overridden
    assertEquals("muthu", obtained.get(ClaimTestUtil.CLAIM_URI3)); // normal

    // UPDATE
    map.put(ClaimTestUtil.CLAIM_URI3, "muthulee");
    usWriter.setUserClaimValues("dimuthu", map, ClaimTestUtil.HOME_PROFILE_NAME);
    value =
        usWriter.getUserClaimValue(
            "dimuthu", ClaimTestUtil.CLAIM_URI3, ClaimTestUtil.HOME_PROFILE_NAME);
    assertEquals("muthulee", value);

    // DELETE
    usWriter.deleteUserClaimValue("dimuthu", ClaimTestUtil.CLAIM_URI1, null);
    value = usWriter.getUserClaimValue("dimuthu", ClaimTestUtil.CLAIM_URI1, null);
    assertNull(value);
    try {
      usWriter.deleteUserClaimValue("dimuthu", null, null);
      fail("Exception at null Claim URI");
    } catch (Exception e) {
      // expected exception
      if (log.isDebugEnabled()) {
        log.debug("Expected error, hence ignored", e);
      }
    }
    try {
      usWriter.deleteUserClaimValue(null, ClaimTestUtil.CLAIM_URI1, null);
      fail("Exception at giving null user name to delete user claim values");
    } catch (Exception e) {
      // expected exception
      if (log.isDebugEnabled()) {
        log.debug("Expected error, hence ignored", e);
      }
    }

    usWriter.deleteUserClaimValues("dimuthu", allClaims, ClaimTestUtil.HOME_PROFILE_NAME);
    obtained = usWriter.getUserClaimValues("dimuthu", allClaims, ClaimTestUtil.HOME_PROFILE_NAME);
    assertNull(obtained.get(ClaimTestUtil.CLAIM_URI2)); // overridden
    assertNull(obtained.get(ClaimTestUtil.CLAIM_URI3));

    // UserStoreManager admin = realm.getUserStoreManager();
    // admin.deleteUser("dimuthu");
  }