mardi 23 avril 2019

Reflection Utility to Match Only Existing Fields

In my current project, I'm setting up a utility to compare fields generated by any number of application versions to the latest application results. For example, if I send in a document containing "This is a test of the emergency broadcast system," the production version of the application might return something like:

Sample A:

`{
text: "This is a test of the emergency broadcast system",
numWords: 9
}`

The latest stable development version might spit out:

Sample B:

`{
text: "This is a test of the emergency broadcast system",
numWords: 9,
notes: [ "Emergency", "Urgent"],
}`

And the latest build might give something like:

Sample C:

`{
text: "This is a test of the emergency broadcast system",
numWords: 9,
notes: [ "Emergency", "Urgent"],
subSentences: [
               sentence1: { text: "This is a test.",
                            numWords: 4 }
              ]
}`

The utility stores what it expects the application to return and a struct that contains A) the field it is attempting to compare and B) a list of these structs containing any sub fields. For example, I might want to make sure that the text of every subSentence matches. I can do this if I know the name of each field but...

The problem is that, in order to support extensibility, the software uses protobuf, and I must use reflection. I can make no assumption as to the contents of any object an application will return. The only information I have is that list of field names. If I'd like to make sure that the latest build gets the numWords for the entire sentence correct, for example, I'd pass the utility the object provided by the application, and a list of strings containing the entry numWords.

This poses two problems:

  1. The EqualsBuilder provided by the Apache commons (version 3.9 as of writing this) checks every field as default. This isn't useful in my case because if I'm expecting Sample A and only checking numWords and text, the utility should pass it. But EqualsBuilder.reflectEquals(Sample A, Sample B) will not return true, since Sample B has an entirely new field.

  2. EqualsBuilder provides .append() methods to compare only specified fields, which sounds more along what I need... except for nested data objects. The API only supports appending common types, so I can easily only check numWords by doing EqualsBuilder.append(9).isEqual(Sample A), but there's no way to do something like EqualsBuilder.append(subSentence) and use that as a comparison.

So, I think my question boils down to: Is there any way to compare fields based off field names instead of field values? And if not, is there any way to pull out internal structures without knowing anything about them (except that they exist)?





Aucun commentaire:

Enregistrer un commentaire