Skip to content

Commit 300e084

Browse files
Merge pull request #592 from BimsaraBodaragama/feature/user-sharing-v2-basis-4
Harden enum parsing with null-safe, case-insensitive resolution and consistent validation
2 parents ec345d9 + 894282c commit 300e084

File tree

8 files changed

+245
-48
lines changed

8 files changed

+245
-48
lines changed

components/org.wso2.carbon.identity.organization.management.organization.user.sharing/src/main/java/org/wso2/carbon/identity/organization/management/organization/user/sharing/constant/EditOperation.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,40 @@
1717

1818
package org.wso2.carbon.identity.organization.management.organization.user.sharing.constant;
1919

20+
import java.util.Arrays;
21+
import java.util.stream.Collectors;
22+
2023
/**
2124
* Enum representing the types of edit operations.
2225
*/
2326
public enum EditOperation {
2427
UPDATE,
25-
DELETE
28+
DELETE;
29+
30+
private static final String VALID_OPERATIONS =
31+
Arrays.stream(values()).map(Enum::name).collect(Collectors.joining(", "));
32+
33+
/**
34+
* Resolve {@link EditOperation} from a string value.
35+
*
36+
* @param value Edit operation value
37+
* @return Matching {@link EditOperation}
38+
* @throws IllegalArgumentException if the value is null, blank, or invalid
39+
*/
40+
public static EditOperation fromString(String value) {
41+
42+
if (value == null || value.trim().isEmpty()) {
43+
throw new IllegalArgumentException(
44+
"EditOperation value cannot be null or empty. Valid operations are: " + VALID_OPERATIONS);
45+
}
46+
47+
for (EditOperation operation : values()) {
48+
if (operation.name().equalsIgnoreCase(value.trim())) {
49+
return operation;
50+
}
51+
}
52+
53+
throw new IllegalArgumentException(
54+
"Invalid EditOperation value: " + value.trim() + ". Valid operations are: " + VALID_OPERATIONS);
55+
}
2656
}

components/org.wso2.carbon.identity.organization.management.organization.user.sharing/src/main/java/org/wso2/carbon/identity/organization/management/organization/user/sharing/constant/RoleAssignmentMode.java

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,19 @@
1717

1818
package org.wso2.carbon.identity.organization.management.organization.user.sharing.constant;
1919

20+
import java.util.Arrays;
21+
import java.util.stream.Collectors;
22+
2023
/**
2124
* Enum representing the modes of role assignments.
2225
*/
2326
public enum RoleAssignmentMode {
2427
SELECTED("SELECTED"),
2528
NONE("NONE");
2629

30+
private static final String VALID_MODES =
31+
Arrays.stream(values()).map(RoleAssignmentMode::toString).collect(Collectors.joining(", "));
32+
2733
private final String value;
2834

2935
RoleAssignmentMode(String value) {
@@ -47,25 +53,23 @@ public String toString() {
4753
*
4854
* @param stringValueOfRoleAssignmentMode The string value of RoleAssignmentMode.
4955
* @return The corresponding RoleAssignmentMode enum.
50-
* @throws IllegalArgumentException if the value does not match any enum.
56+
* @throws IllegalArgumentException if the value is null/blank or does not match any enum.
5157
*/
5258
public static RoleAssignmentMode fromString(String stringValueOfRoleAssignmentMode) {
5359

54-
for (RoleAssignmentMode mode : RoleAssignmentMode.values()) {
55-
if (mode.value.equalsIgnoreCase(stringValueOfRoleAssignmentMode)) {
56-
return mode;
57-
}
60+
if (stringValueOfRoleAssignmentMode == null || stringValueOfRoleAssignmentMode.trim().isEmpty()) {
61+
throw new IllegalArgumentException("RoleAssignmentMode value cannot be null or empty. Valid modes are: "
62+
+ VALID_MODES);
5863
}
59-
// Build a comma-separated list of valid RoleAssignmentMode values.
60-
StringBuilder validModes = new StringBuilder();
61-
for (RoleAssignmentMode mode : RoleAssignmentMode.values()) {
62-
if (validModes.length() > 0) {
63-
validModes.append(", ");
64+
65+
for (RoleAssignmentMode mode : values()) {
66+
if (mode.value.equalsIgnoreCase(stringValueOfRoleAssignmentMode.trim())) {
67+
return mode;
6468
}
65-
validModes.append(mode.toString());
6669
}
70+
6771
throw new IllegalArgumentException(
68-
"Invalid RoleAssignmentMode value: " + stringValueOfRoleAssignmentMode + ". Valid modes are: " +
69-
validModes);
72+
"Invalid RoleAssignmentMode value: " + stringValueOfRoleAssignmentMode.trim() + ". Valid modes are: " +
73+
VALID_MODES);
7074
}
7175
}

components/org.wso2.carbon.identity.organization.management.organization.user.sharing/src/main/java/org/wso2/carbon/identity/organization/management/organization/user/sharing/constant/SharedType.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717

1818
package org.wso2.carbon.identity.organization.management.organization.user.sharing.constant;
1919

20+
import java.util.Arrays;
21+
import java.util.stream.Collectors;
22+
2023
/**
2124
* Enum representing the types of user associations.
2225
*/
@@ -26,6 +29,9 @@ public enum SharedType {
2629
OWNER("OWNER"),
2730
NOT_SPECIFIED("NOT SPECIFIED");
2831

32+
private static final String VALID_TYPES =
33+
Arrays.stream(values()).map(SharedType::toString).collect(Collectors.joining(", "));
34+
2935
private final String value;
3036

3137
SharedType(String value) {
@@ -49,15 +55,22 @@ public String toString() {
4955
*
5056
* @param stringValueOfSharedType The string value of SharedType.
5157
* @return The corresponding SharedType enum.
52-
* @throws IllegalArgumentException if the value does not match any enum.
58+
* @throws IllegalArgumentException if the value is null, blank, or invalid.
5359
*/
5460
public static SharedType fromString(String stringValueOfSharedType) {
5561

56-
for (SharedType type : SharedType.values()) {
57-
if (type.value.equalsIgnoreCase(stringValueOfSharedType)) {
62+
if (stringValueOfSharedType == null || stringValueOfSharedType.trim().isEmpty()) {
63+
throw new IllegalArgumentException(
64+
"SharedType value cannot be null or empty. Valid types are: " + VALID_TYPES);
65+
}
66+
67+
for (SharedType type : values()) {
68+
if (type.value.equalsIgnoreCase(stringValueOfSharedType.trim())) {
5869
return type;
5970
}
6071
}
61-
throw new IllegalArgumentException("Invalid SharedType value: " + stringValueOfSharedType);
72+
73+
throw new IllegalArgumentException(
74+
"Invalid SharedType value: " + stringValueOfSharedType.trim() + ". Valid types are: " + VALID_TYPES);
6275
}
6376
}

components/org.wso2.carbon.identity.organization.management.organization.user.sharing/src/main/java/org/wso2/carbon/identity/organization/management/organization/user/sharing/constant/UserSharePatchOperation.java

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717

1818
package org.wso2.carbon.identity.organization.management.organization.user.sharing.constant;
1919

20+
import java.util.Arrays;
21+
import java.util.stream.Collectors;
22+
2023
/**
2124
* Enum representing the types of user share role assignment operations. Applicable to role assignment updates.
2225
*/
@@ -25,6 +28,9 @@ public enum UserSharePatchOperation {
2528
ADD("add"),
2629
REMOVE("remove");
2730

31+
private static final String VALID_OPERATIONS =
32+
Arrays.stream(values()).map(UserSharePatchOperation::getValue).collect(Collectors.joining(", "));
33+
2834
private final String value;
2935

3036
UserSharePatchOperation(String value) {
@@ -37,19 +43,27 @@ public String getValue() {
3743
return value;
3844
}
3945

46+
/**
47+
* Resolve {@link UserSharePatchOperation} from a string value.
48+
*
49+
* @param value Operation value (e.g. {@code add}, {@code remove})
50+
* @return Matching {@link UserSharePatchOperation}
51+
* @throws IllegalArgumentException if the value is null, blank, or invalid
52+
*/
4053
public static UserSharePatchOperation fromValue(String value) {
4154

42-
for (UserSharePatchOperation operation : UserSharePatchOperation.values()) {
43-
if (operation.getValue().equals(value)) {
55+
if (value == null || value.trim().isEmpty()) {
56+
throw new IllegalArgumentException(
57+
"Operation value cannot be null or empty. Valid operations are: " + VALID_OPERATIONS);
58+
}
59+
60+
for (UserSharePatchOperation operation : values()) {
61+
if (operation.value.equalsIgnoreCase(value.trim())) {
4462
return operation;
4563
}
4664
}
47-
// Throw an exception with a helpful message listing valid operations.
48-
String validOperations = String.join(", ",
49-
java.util.Arrays.stream(UserSharePatchOperation.values())
50-
.map(Enum::name)
51-
.toArray(String[]::new));
65+
5266
throw new IllegalArgumentException(
53-
"Invalid operation: " + value + ". Valid operations are: " + validOperations);
67+
"Invalid operation: " + value.trim() + ". Valid operations are: " + VALID_OPERATIONS);
5468
}
5569
}

components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/OrganizationScope.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,42 @@
1717

1818
package org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant;
1919

20+
import java.util.Arrays;
21+
import java.util.stream.Collectors;
22+
2023
/**
2124
* Enum representing the organization scope for which a given policy is shared with.
2225
*/
2326
public enum OrganizationScope {
2427
EXISTING_ORGS_ONLY,
2528
EXISTING_ORGS_AND_FUTURE_ORGS_ONLY,
2629
FUTURE_ORGS_ONLY,
27-
NO_ORG,
30+
NO_ORG;
31+
32+
private static final String VALID_SCOPES =
33+
Arrays.stream(values()).map(Enum::name).collect(Collectors.joining(", "));
34+
35+
/**
36+
* Resolve {@link OrganizationScope} from a string value.
37+
*
38+
* @param value Scope value
39+
* @return Matching {@link OrganizationScope}
40+
* @throws IllegalArgumentException if the value is null, blank, or invalid
41+
*/
42+
public static OrganizationScope fromString(String value) {
43+
44+
if (value == null || value.trim().isEmpty()) {
45+
throw new IllegalArgumentException(
46+
"OrganizationScope value cannot be null or empty. Valid values are: " + VALID_SCOPES);
47+
}
48+
49+
for (OrganizationScope scope : values()) {
50+
if (scope.name().equalsIgnoreCase(value.trim())) {
51+
return scope;
52+
}
53+
}
54+
55+
throw new IllegalArgumentException(
56+
"Invalid OrganizationScope value: " + value.trim() + ". Valid values are: " + VALID_SCOPES);
57+
}
2858
}

components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/PolicyEnum.java

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.Collections;
2222
import java.util.List;
2323
import java.util.Optional;
24+
import java.util.stream.Collectors;
2425

2526
/**
2627
* Enum representing user sharing policies with additional fields for code, name, value, organization scope, applicable
@@ -115,6 +116,16 @@ public enum PolicyEnum {
115116
"current context and is not shared with any organization."
116117
);
117118

119+
private static final String VALID_POLICY_CODES =
120+
Arrays.stream(values()).map(PolicyEnum::getPolicyCode).collect(Collectors.joining(", "));
121+
private static final String VALID_POLICY_NAMES =
122+
Arrays.stream(values()).map(PolicyEnum::getPolicyName).collect(Collectors.joining(", "));
123+
private static final String VALID_POLICY_VALUES =
124+
Arrays.stream(values()).map(PolicyEnum::getValue).collect(Collectors.joining(", "));
125+
private static final String VALID_POLICIES =
126+
"codes: [" + VALID_POLICY_CODES + "], names: [" + VALID_POLICY_NAMES + "], values: [" +
127+
VALID_POLICY_VALUES + "]";
128+
118129
private final String policyCode;
119130
private final String policyName;
120131
private final String value;
@@ -210,8 +221,13 @@ public String getDescription() {
210221
*/
211222
public static Optional<PolicyEnum> getByPolicyCode(String policyCode) {
212223

213-
for (PolicyEnum policy : PolicyEnum.values()) {
214-
if (policy.policyCode.equals(policyCode)) {
224+
if (policyCode == null || policyCode.trim().isEmpty()) {
225+
return Optional.empty();
226+
}
227+
String normalized = policyCode.trim();
228+
229+
for (PolicyEnum policy : values()) {
230+
if (policy.policyCode.equalsIgnoreCase(normalized)) {
215231
return Optional.of(policy);
216232
}
217233
}
@@ -226,8 +242,13 @@ public static Optional<PolicyEnum> getByPolicyCode(String policyCode) {
226242
*/
227243
public static Optional<PolicyEnum> getByValue(String value) {
228244

229-
for (PolicyEnum policy : PolicyEnum.values()) {
230-
if (policy.value.equals(value)) {
245+
if (value == null || value.trim().isEmpty()) {
246+
return Optional.empty();
247+
}
248+
String normalized = value.trim();
249+
250+
for (PolicyEnum policy : values()) {
251+
if (policy.value.equalsIgnoreCase(normalized)) {
231252
return Optional.of(policy);
232253
}
233254
}
@@ -243,15 +264,20 @@ public static Optional<PolicyEnum> getByValue(String value) {
243264
*/
244265
public static PolicyEnum validateAndGetPolicyEnum(String requestedPolicy) {
245266

246-
for (PolicyEnum policy : PolicyEnum.values()) {
247-
if (policy.value.equalsIgnoreCase(requestedPolicy) ||
248-
policy.policyCode.equalsIgnoreCase(requestedPolicy) ||
249-
policy.policyName.equalsIgnoreCase(requestedPolicy)) {
267+
if (requestedPolicy == null || requestedPolicy.trim().isEmpty()) {
268+
throw new IllegalArgumentException("Policy cannot be null or empty. Valid policies are: " + VALID_POLICIES);
269+
}
270+
String normalized = requestedPolicy.trim();
271+
272+
for (PolicyEnum policy : values()) {
273+
if (policy.value.equalsIgnoreCase(normalized) ||
274+
policy.policyCode.equalsIgnoreCase(normalized) ||
275+
policy.policyName.equalsIgnoreCase(normalized)) {
250276
return policy;
251277
}
252278
}
253-
// Handle the case where no matching policy is found
254-
throw new IllegalArgumentException("Invalid policy: " + requestedPolicy);
279+
throw new IllegalArgumentException(
280+
"Invalid policy: " + requestedPolicy.trim() + ". Valid policies are: " + VALID_POLICIES);
255281
}
256282

257283
/**
@@ -263,12 +289,19 @@ public static PolicyEnum validateAndGetPolicyEnum(String requestedPolicy) {
263289
*/
264290
public static PolicyEnum getPolicyByValue(String value) {
265291

266-
for (PolicyEnum policy : PolicyEnum.values()) {
267-
if (policy.value.equalsIgnoreCase(value)) {
292+
if (value == null || value.trim().isEmpty()) {
293+
throw new IllegalArgumentException(
294+
"Policy value cannot be null or empty. Valid values are: " + VALID_POLICY_VALUES);
295+
}
296+
String normalized = value.trim();
297+
298+
for (PolicyEnum policy : values()) {
299+
if (policy.value.equalsIgnoreCase(normalized)) {
268300
return policy;
269301
}
270302
}
271-
throw new IllegalArgumentException("Invalid policy value: " + value);
303+
throw new IllegalArgumentException(
304+
"Invalid policy value: " + value.trim() + ". Valid values are: " + VALID_POLICY_VALUES);
272305
}
273306

274307
/**
@@ -280,12 +313,19 @@ public static PolicyEnum getPolicyByValue(String value) {
280313
*/
281314
public static PolicyEnum getPolicyByPolicyCode(String policyCode) {
282315

283-
for (PolicyEnum policy : PolicyEnum.values()) {
284-
if (policy.policyCode.equalsIgnoreCase(policyCode)) {
316+
if (policyCode == null || policyCode.trim().isEmpty()) {
317+
throw new IllegalArgumentException(
318+
"Policy code cannot be null or empty. Valid codes are: " + VALID_POLICY_CODES);
319+
}
320+
String normalized = policyCode.trim();
321+
322+
for (PolicyEnum policy : values()) {
323+
if (policy.policyCode.equalsIgnoreCase(normalized)) {
285324
return policy;
286325
}
287326
}
288-
throw new IllegalArgumentException("Invalid policy code: " + policyCode);
327+
throw new IllegalArgumentException(
328+
"Invalid policy code: " + policyCode.trim() + ". Valid codes are: " + VALID_POLICY_CODES);
289329
}
290330

291331
/**
@@ -297,11 +337,18 @@ public static PolicyEnum getPolicyByPolicyCode(String policyCode) {
297337
*/
298338
public static PolicyEnum getPolicyByPolicyName(String policyName) {
299339

300-
for (PolicyEnum policy : PolicyEnum.values()) {
301-
if (policy.policyName.equalsIgnoreCase(policyName)) {
340+
if (policyName == null || policyName.trim().isEmpty()) {
341+
throw new IllegalArgumentException(
342+
"Policy name cannot be null or empty. Valid names are: " + VALID_POLICY_NAMES);
343+
}
344+
String normalized = policyName.trim();
345+
346+
for (PolicyEnum policy : values()) {
347+
if (policy.policyName.equalsIgnoreCase(normalized)) {
302348
return policy;
303349
}
304350
}
305-
throw new IllegalArgumentException("Invalid policy name: " + policyName);
351+
throw new IllegalArgumentException(
352+
"Invalid policy name: " + policyName.trim() + ". Valid names are: " + VALID_POLICY_NAMES);
306353
}
307354
}

0 commit comments

Comments
 (0)