Abhishek
Abhishek

Reputation: 698

Best way to validate keys in property file in java8

I have a property file which I need to validate against a set of keys and values. So that user can't provide any anonymous key or invalid value in properties file.

I have done it using reading the property file and creating a ENUM of all possible keys and with the help of streams I am validating each and every key from property file with that mentioned in Enum.

My Enum:

public enum VersionEnum {
A,
B,
C,
D

public static Stream<VersionEnum> stream() {
        return Arrays.stream(VersionEnum.values());
    }
}

ANd then running another loop to compare the value for each key.

I was wondering if there's any better way to accomplish this in java?

Any Help would be highly appreciated.

Upvotes: 1

Views: 853

Answers (1)

LppEdd
LppEdd

Reputation: 21124

Imho, the better approach (because a best one doesn't exist) is maintaining a default set of properties stored in another file. Having an hard-coded Enum sounds way too "strange" for this kind of task.

See example code, with comments (if you don't like reading, move down to the Stream solution).
For keys, we can use Properties#keySet()

// Load default/allowed properties from a resource file
final Properties allowed = new Properties();
properties.load(allowedInput);

// Load user-defined properties from a file
final Properties userDefined = new Properties();
properties.load(userDefinedInput);

// Remove all the keys from the user-defined Property
// that match with the allowed one. 
final Collection<Object> userDefinedCopy = new HashSet<>(userDefined.keySet());
userDefinedCopy.removeAll(allowed.keySet());

// If the key Set is not empty, it means the user added
// invalid or not allowed keys
if (!userDefined.isEmpty()) {
    // Error!
}

The same approach could be taken for values with Properties#values(), if the order or the association with the keys is not important.

final Collection<Object> allowedValues = allowed.values();
final Collection<Object> userDefinedValues = userDefined.values();
userDefinedValues.removeAll(allowedValues);

if (!userDefinedValues.isEmpty()) {
    // Error!
}

In this case we do not have to create an additional Collection<T>, as Properties is doing it for us

@Override
public Collection<Object> values() {
    return Collections.synchronizedCollection(map.values(), this);
}

Or even, a Stream solution, if the key-value association is important

final Properties allowed = new Properties();
// Load

final Properties userDefined = new Properties();
// Load

final long count =
    userDefined.entrySet()
               .stream()
               .filter(e -> {
                  final Object o = allowed.get(e.getKey());

                  // If 'o' is null, the user-defined property is out of bounds.
                  // If 'o' is present ('o' represents the valid value), but it doesn't
                  // match with the user-defined value, the property is wrong

                  return o == null || !Objects.equals(o, e.getValue());
               }).count();

if (count != 0) {
   // Error!
}

You can play with it on Ideone.com here.

Upvotes: 2

Related Questions