I have two TreeMaps that I want to compare. I currently have it written down like below but I feel like this could be written more efficiently. I tried looking in to comparators, but I don’t think that’s something I can use for my use-case.
The maps are Treemaps because the key must be case-insensitive.
public void theseRulesAreTheSame() { List<String> failures = new ArrayList<>(); TreeMap<String, NSG> configNsgs = platformConfiguration.getAzure().nsgs(); configNsgs.forEach((name, nsg) -> { assertThat(azureAdapter.doesNsgExistInAzure(name)) .as("Unable to find network security group " + name + " in Azure.").isTrue(); List<SecurityRulesItem> configSecurityRules = nsg.getSecurityRules(); TreeMap<String, Object> azureSecurityRules = azureAdapter .getSecurityRulesForNsg(name); assertThat(configSecurityRules.size()) .as("The nymber of security rules in Azure does not correspond to the number of security rules in the configuration!") .isEqualTo(azureSecurityRules.size()); configSecurityRules.forEach(configSecurityRule -> { SecurityRuleInner azureSecurityRule = (SecurityRuleInner) azureSecurityRules .get(configSecurityRule.getRuleName()); logger.info( "Checking security rule " + configSecurityRule.getRuleName() + " in network security group " + nsg.getName()); if (null == azureSecurityRule) { logFailure(failures, null, configSecurityRule.getRuleName()); } else { if (!azureSecurityRule.access().toString().equalsIgnoreCase(configSecurityRule.getAccess())) { logFailure(failures, configSecurityRule.getAccess(), azureSecurityRule.access()); } if (!azureSecurityRule.destinationAddressPrefix().equalsIgnoreCase(configSecurityRule.getDestinationAddressPrefix())) { logFailure(failures, configSecurityRule.getDestinationAddressPrefix(), azureSecurityRule.destinationAddressPrefix()); } if (!azureSecurityRule.destinationPortRange().equalsIgnoreCase(configSecurityRule.getDestinationPortRange())) { logFailure(failures, configSecurityRule.getDestinationPortRange(), azureSecurityRule.destinationPortRange()); } if (!azureSecurityRule.sourceAddressPrefix().equalsIgnoreCase(configSecurityRule.getSourceAddressPrefix())) { logFailure(failures, configSecurityRule.getSourceAddressPrefix(), azureSecurityRule.sourceAddressPrefix()); } if (!azureSecurityRule.sourcePortRange().equalsIgnoreCase(configSecurityRule.getSourcePortRange())) { logFailure(failures, configSecurityRule.getSourcePortRange(), azureSecurityRule.sourcePortRange()); } if (!azureSecurityRule.protocol().toString().equalsIgnoreCase(configSecurityRule.getProtocol())) { logFailure(failures, configSecurityRule.getProtocol(), azureSecurityRule.protocol()); } if (!azureSecurityRule.direction().toString().equalsIgnoreCase(configSecurityRule.getDirection())) { logFailure(failures, configSecurityRule.getDirection(), azureSecurityRule.direction()); } } }); }); if (!failures.isEmpty()) { Assertions.fail( "Error(s) detected while comparing the network security groups between Azure and the config. Failures: " + failures); } }
Thanks in advance
Advertisement
Answer
If we have the two types AzureSecurityRule
and ConfigSecurityRule
we could make the comparison less verbose like this:
BiConsumer<AzureSecurityRule, ConfigSecurityRule> compareField(Function<AzureSecurityRule,String> f1, Function<ConfigSecurityRule> f2) { return (az, cf) -> { if !f1.apply(az).equalsIgnoreCase(f2.apply(cf)) { logFailure(failure, f2.apply(cf), f1.apply(az)); } } } ... List.of( compareField(az -> az.access().toString(), cf -> cf.getAccess()), compareField(az -> az.destinationAddressPrefix(), cf -> cf.getDestinationAddressPrefix()), ... ).forEach(cf -> cf.accept(azureSecurityRule, configSecurityRule));