Skip to content

Commit 803915a

Browse files
authored
fix: parsing unhandled exceptions
2 parents 9756c93 + de68791 commit 803915a

6 files changed

Lines changed: 74 additions & 16 deletions

File tree

src/main/java/io/github/isagroup/services/parsing/AddOnParser.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,13 @@ private static void setAddOnFeatures(String addOnName, Map<String, Object> addOn
179179

180180
for (String addOnFeatureName : addOnFeaturesMap.keySet()) {
181181

182-
Map<String, Object> addOnFeatureMap = (Map<String, Object>) addOnFeaturesMap.get(addOnFeatureName);
182+
Object featureObj = addOnFeaturesMap.get(addOnFeatureName);
183+
if (!(featureObj instanceof Map)) {
184+
throw new PricingParsingException("The feature " + addOnFeatureName
185+
+ " of the add-on " + addOnName + " is not a valid map. Maybe 'value' attribute is missing to set the value of the feature");
186+
}
187+
@SuppressWarnings("unchecked")
188+
Map<String, Object> addOnFeatureMap = (Map<String, Object>) featureObj;
183189

184190
if (!globalFeaturesMap.containsKey(addOnFeatureName)) {
185191
throw new FeatureNotFoundException(
@@ -233,9 +239,23 @@ private static void setAddOnUsageLimits(String addOnName, Map<String, Object> ad
233239
Map<String, Object> addOnUsageLimitsMap = null;
234240

235241
if (areExtensions) {
236-
addOnUsageLimitsMap = (Map<String, Object>) addOnMap.get("usageLimitsExtensions");
242+
Object usageLimitsExtensionsObj = addOnMap.get("usageLimitsExtensions");
243+
if (usageLimitsExtensionsObj instanceof Map<?, ?>) {
244+
addOnUsageLimitsMap = (Map<String, Object>) usageLimitsExtensionsObj;
245+
} else if (usageLimitsExtensionsObj != null) {
246+
throw new PricingParsingException("The field \"usageLimitsExtensions\" should be a map. It is currently: "
247+
+ usageLimitsExtensionsObj.getClass().getSimpleName() + ". "
248+
+ "Maybe you forgot to add the 'value' attribute to the usage limit in the add-on definition.");
249+
}
237250
} else {
238-
addOnUsageLimitsMap = (Map<String, Object>) addOnMap.get("usageLimits");
251+
Object usageLimitsObj = addOnMap.get("usageLimits");
252+
if (usageLimitsObj instanceof Map<?, ?>) {
253+
addOnUsageLimitsMap = (Map<String, Object>) usageLimitsObj;
254+
} else if (usageLimitsObj != null) {
255+
throw new PricingParsingException("The field \"usageLimits\" should be a map. It is currently: "
256+
+ usageLimitsObj.getClass().getSimpleName() + ". "
257+
+ "Maybe you forgot to add the 'value' attribute to the usage limit in the add-on definition.");
258+
}
239259
}
240260
Map<String, UsageLimit> globalUsageLimitsMap = pricingManager.getUsageLimits();
241261
Map<String, UsageLimit> addOnUsageLimits = new LinkedHashMap<>();

src/main/java/io/github/isagroup/services/parsing/FeatureParser.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,17 @@ private static Integration parseMapToIntegration(String featureName, Map<String,
105105
}
106106

107107
if (integration.getIntegrationType().equals(IntegrationType.WEB_SAAS)) {
108-
integration.setPricingUrls((List<String>) map.get("pricingUrls"));
108+
if (map.get("pricingUrls") != null) {
109+
if (!(map.get("pricingUrls") instanceof List) || ((List<String>) map.get("pricingUrls")).isEmpty()
110+
|| ((List<String>) map.get("pricingUrls")).stream().anyMatch(url -> !url.matches("^(http|https)://.*"))) {
111+
throw new PricingParsingException("The feature " + featureName
112+
+ " is from type INTEGRATION with integrationType WEB_SAAS but does not have a valid pricingUrls list (each item must be a valid URL with the http or https protocol). Current value: " + map.get("pricingUrls")
113+
+ ". To specify a list you must use dash (-) before each item. Remember, it is an optional field so you can remove it from the input.");
114+
}
115+
integration.setPricingUrls((List<String>) map.get("pricingUrls"));
116+
} else {
117+
integration.setPricingUrls(List.of());
118+
}
109119
}
110120

111121
return integration;
@@ -134,7 +144,7 @@ private static Automation parseMapToAutomation(String featureName, Map<String, O
134144

135145
try {
136146
automation.setAutomationType(AutomationType.valueOf(automationType));
137-
} catch (IllegalArgumentException e) {
147+
} catch (NullPointerException | IllegalArgumentException e) {
138148
throw new InvalidAutomationTypeException(
139149
"The feature " + featureName + " does not have a supported automationType (" + Arrays.toString(AutomationType.values()) + "). Current value: "
140150
+ automationType);
@@ -160,7 +170,11 @@ private static Guarantee parseMapToGuarantee(String featureName, Map<String, Obj
160170

161171
if (map.get("docUrl") != null && !(map.get("docUrl") instanceof String)) {
162172
throw new PricingParsingException("\'docUrl\' must be a String but found a "
163-
+ map.get("docUrl").getClass().getSimpleName() + " instead");
173+
+ map.get("docUrl").getClass().getSimpleName() + " instead (feature affected: '" + featureName + "'). Remember, it is an optional field so you can remove it from the input.");
174+
}
175+
176+
if (map.get("docUrl") != null && !((String) map.get("docUrl")).matches("^(http|https)://.*")) {
177+
throw new PricingParsingException("The docUrl field (from feature '" + featureName + "') must be a valid URL with the http or https protocol. Received: " + map.get("docUrl") + ". Remember, it is an optional field so you can remove it from the input.");
164178
}
165179

166180
guarantee.setDocURL((String) map.get("docUrl"));
@@ -279,7 +293,7 @@ private static void parsePaymentValue(Feature feature, String featureName, Map<S
279293
for (String paymentType : allowedPaymentTypes) {
280294
try {
281295
PaymentType.valueOf(paymentType);
282-
} catch (IllegalArgumentException e) {
296+
} catch (NullPointerException | IllegalArgumentException e) {
283297
throw new InvalidDefaultValueException("The feature " + featureName
284298
+ " does not have a valid defaultValue consisting on a list of supported paymentType ("+Arrays.toString(PaymentType.values())+"). PaymentType that generates the issue: " + paymentType);
285299
}

src/main/java/io/github/isagroup/services/parsing/PlanParser.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,13 @@ private static void setFeaturesToPlan(String planName, Map<String, Object> map,
103103

104104
for (String planFeatureName : planFeaturesMap.keySet()) {
105105

106-
Map<String, Object> planFeatureMap = (Map<String, Object>) planFeaturesMap.get(planFeatureName);
106+
Object planFeatureObj = planFeaturesMap.get(planFeatureName);
107+
if (!(planFeatureObj instanceof Map)) {
108+
throw new PricingParsingException("The feature " + planFeatureName
109+
+ " of the plan " + planName + " is not a valid map. Maybe 'value' attribute is missing to set the value of the feature");
110+
}
111+
@SuppressWarnings("unchecked")
112+
Map<String, Object> planFeatureMap = (Map<String, Object>) planFeatureObj;
107113

108114
if (!plan.getFeatures().containsKey(planFeatureName)) {
109115
throw new FeatureNotFoundException(
@@ -188,15 +194,30 @@ private static void setUsageLimitsToPlan(String planName, Map<String, Object> ma
188194

189195
for (String planUsageLimitName : planUsageLimitsMap.keySet()) {
190196

191-
Map<String, Object> planUsageLimitMap = (Map<String, Object>) planUsageLimitsMap.get(planUsageLimitName);
197+
Object planUsageLimitObj = planUsageLimitsMap.get(planUsageLimitName);
198+
if (!(planUsageLimitObj instanceof Map)) {
199+
throw new PricingParsingException("The usageLimit " + planUsageLimitName
200+
+ " of the plan " + planName + " is not a valid map. Maybe 'value' attribute is missing to set the value of the usageLimit");
201+
}
202+
@SuppressWarnings("unchecked")
203+
Map<String, Object> planUsageLimitMap = (Map<String, Object>) planUsageLimitObj;
192204

193205
if (!plan.getUsageLimits().containsKey(planUsageLimitName)) {
194206
throw new FeatureNotFoundException(
195207
"The usageLimit " + planUsageLimitName + " is not defined in the global usageLimits");
196208
} else {
197209
UsageLimit usageLimit = plan.getUsageLimits().get(planUsageLimitName);
198210

199-
Object value = planUsageLimitMap.get("value");
211+
Object value = null;
212+
try{
213+
value = planUsageLimitMap.get("value");
214+
}
215+
catch (NullPointerException e){
216+
throw new InvalidDefaultValueException("The usageLimit " + planUsageLimitName
217+
+ " does not have a valid value. Current valueType: "
218+
+ usageLimit.getValueType().toString() + "; Current value in plan " + plan.getName() + " is null");
219+
}
220+
200221
boolean isValueNull = (value == null);
201222

202223
if (isValueNull){
@@ -251,7 +272,7 @@ public static void parsePaymentValue(Feature feature, String featureName, Map<St
251272
for (String type : allowedPaymentTypes) {
252273
try {
253274
PaymentType.valueOf(type);
254-
} catch (IllegalArgumentException e) {
275+
} catch (NullPointerException | IllegalArgumentException e) {
255276
throw new InvalidDefaultValueException(
256277
"Invalid payment type for feature \"" + featureName + "\": \"" + type + "\" is not a supported payment type. "
257278
+ "Supported types are: " + Arrays.toString(PaymentType.values()) + ". "

src/main/java/io/github/isagroup/services/parsing/PricingManagerParser.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,10 @@ private static void setPlans(Map<String, Object> map, PricingManager pricingMana
342342
}
343343

344344
private static void setAddOns(Map<String, Object> map, PricingManager pricingManager) {
345-
Map<String, Object> addOnsMap = (Map<String, Object>) map.get("addOns");
345+
Map<String, Object> addOnsMap = null;
346+
if (map.get("addOns") instanceof Map) {
347+
addOnsMap = (Map<String, Object>) map.get("addOns");
348+
}
346349

347350
if (addOnsMap == null) {
348351
return;
@@ -356,7 +359,7 @@ private static void setAddOns(Map<String, Object> map, PricingManager pricingMan
356359
AddOn addOn = AddOnParser.parseMapToAddOn(addOnName, addOnMap, pricingManager);
357360

358361
pricingManager.getAddOns().put(addOnName, addOn);
359-
} catch (ClassCastException e) {
362+
} catch (ClassCastException | NullPointerException | IllegalArgumentException e) {
360363
throw new PricingParsingException(
361364
"An error has occurred while parsing the add-on " + addOnName + ". Error: " + e.getMessage());
362365
}

src/main/java/io/github/isagroup/services/parsing/UsageLimitParser.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public static UsageLimit parseMapToUsageLimit(String limitName, Map<String, Obje
4747
default:
4848
return null;
4949
}
50-
} catch (IllegalArgumentException e) {
50+
} catch (NullPointerException | IllegalArgumentException e) {
5151
throw new IllegalArgumentException("The usage limit " + limitName
5252
+ " does not have a supported type (" + Arrays.toString(UsageLimitType.values()) + "). Current type value: " + (String) limitMap.get("type"));
5353
}
@@ -96,7 +96,7 @@ private static void loadBasicAttributes(UsageLimit limit, String limitName, Map<
9696
limit.setDescription((String) map.get("description"));
9797
try {
9898
limit.setValueType(ValueType.valueOf((String) map.get("valueType")));
99-
} catch (IllegalArgumentException e) {
99+
} catch (NullPointerException | IllegalArgumentException e) {
100100
throw new InvalidValueTypeException("The feature " + limitName
101101
+ " does not have a supported valueType (" + Arrays.toString(ValueType.values()) + "). Current valueType: " + (String) map.get("valueType"));
102102
}

src/test/resources/negative-parsing-tests.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Throw an error if 'currency' is missing;parsing/negative/currency/currency-is-nu
3131
Throw an error if a feature is not a map of attributes;parsing/negative/feature/feature-is-key-value.yml;Feature 'foo' must be a Map but found String instead
3232
Throw an error if a feature is named 'null';parsing/negative/feature/feature-null-as-key.yml;A feature cannot have the name null
3333
# feature.docUrl
34-
Throw an error if feature 'docUrl' is not a string;parsing/negative/feature/docUrl/is-bool.yml;'docUrl' must be a String but found a Boolean instead
34+
Throw an error if feature 'docUrl' is not a string;parsing/negative/feature/docUrl/is-bool.yml;'docUrl' must be a String but found a Boolean instead (feature affected: 'guarantee'). Remember, it is an optional field so you can remove it from the input.
3535
# feature.type
3636
Throw an error if feature 'type' is missing or null;parsing/negative/feature/type/null-type.yml;feature 'type' is mandatory
3737
# feature.valueType

0 commit comments

Comments
 (0)