Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a "plugin" concept for validating extensions #227

Open
javagl opened this issue Oct 4, 2022 · 1 comment
Open

Implement a "plugin" concept for validating extensions #227

javagl opened this issue Oct 4, 2022 · 1 comment

Comments

@javagl
Copy link
Contributor

javagl commented Oct 4, 2022

The validator currently does not support validation of extensions. There are many technical caveats for that in the detail. But it might be possible to set up a basic "plugin" infrastructure for the validation of extensions, that could already have a great effort-to-benefit ratio.

One basic idea was to offer a point where it is possible to plug in implementations of the Validator interface. In pseudocode, this could be

class S2ExtensionValidator implements Validator<any> {
  validateObject(input: any, context: ValidationContext): boolean {
    // TODO Validate the input
    return true;
  }
}
TilesetValidator.registerExtensionValidator(
    "3DTILES_bounding_volume_S2", new S2ExtensionValidator());

Whenever the validation encounters a 3DTILES_bounding_volume_S2 extension object, the given validator will be consulted for that validation.

A neat side effect of this is that it would be possible to perform the purely JSON-schema based validation generically So creating a validator for a new extension, purely based on the schema, could be as easy as

const example= Magic.create("/example.schema.json");
TilesetValidator.registerExtensionValidator("EXAMPLE_extension", example);

But there are some details to sort out, and these are not entirely trivial. Extensions can sometimes not be validated "isolatedly". Some extensions affect the validity of the surrounding objects. One example is, exactly, the 3DTILES_bounding_volume_S2 extension: For a bounding volume like this

{
    box: undefined,
    region: undefined,
    sphere: undefined,
    extensions: {
    3DTILES_bounding_volume_S2: {  ... }
   }
}

one could validate the extension, but the bounding volume itself would still be considered to be invalid, because according to the specification, one of box, region and sphere must be defined.

A similar (but more generic) instance of this is when an extension extends the set of possible values for enums. For example, there might be an extension that defines a new refine value, and in addition to ADD and REPLACE, there is now a value like MERGE that is considered to be valid.

Ideally, the "core" validator should not be aware of the specific behavior of extensions. But in doubt, it may be necessary to adjust the validator for specific extensions, even though the bulk of the specific validation work can be moved into such a "plugin" class.

@javagl
Copy link
Contributor Author

javagl commented Oct 14, 2022

The basic infrastructure for validation extension has been added in #230 :

  • It is possible to register a validator for a certain extension. When the extension is found, then the registered validator will be applied to the extended object.
  • It is possible to register validator for a certain content type. When that content type is encountered, the registered validator will be applied to that.

There are some limitations to that approach (largely summarized in this comment), but the infrastructure should already be capable of supporting the most important types of extensions that we are aware of.


An open question is still how the actual "plugin" functionality is supposed to be implemented. Right now, an "extension validator" or "content type validator" can be added, as an implementation of the Validator interface.

These validators are supposed to be located in this repository, and they are registered internally, at compile-time.

If there should be the possibility to "plug in" any sort of external validator implementation, then there has to be a runtime mechanism for that.

A quick websearch suggests that there is not really a "silver bullet" solution for such plugins. They all raise questions about compilation+bundling+deployment, and therefore, the solution might depend on the build system and module manager.


Even if the plugin can only be added at compile time, with the validator itself being used as a library, there is the question about how such a plugin can be registered.

Registering a "standalone" validator for an extension that may just extend a certain object could be simple:

      const s2Validator = new BoundingVolumeS2Validator();
      const override = true;
      ExtendedObjectsValidators.register(
        "3DTILES_bounding_volume_S2",
        s2Validator,
        override
      );

This already exists as of the linked PR, and might only have to be reviewed if it was supposed to be made "public".

Registering a validator for an extension that allows new content types is more tricky. It raises the question of how the content type can be detected. There must must be 'something' that sufficiently describes the condition that is used for deciding whether content data has a certain type. Internally, some structures for that are already in place. The content type can be determined...

  • via the file extension
  • via the "magic header" (i.e. a string of the first 4 bytes of the file)
  • an arbitrary predicate on the content data (and the first two options are already built on top of that)

Some pseudocode (!) for what such a registation might look like,

const extensionName = "EXAMPLE_content_XYZ";
const contentValidator = new ContentValidatorXYZ();
const contentTypeDescription = {
    // Alternatively, one of these:
    fileExtension: ".xyz",
    magic: "XYZ!",
    predicate: (contentType) => defined(contentType.parsedObject.xyzVersion), 
};
register(extensionName, contentTypeDescription, contentValidator);

However, when this is supposed to be exposed and used by clients, care has to be taken to provide that functionality in a sustainable form, and whether all use-cases are covered. This refers, for example, to the difference of whether the validator is used as a library (where a 'predicate' can easily be passed to the library), or as a command-line tool (where only the 'fileExtension' and 'magic' conditions could be used).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant