Skip to content

Commit be3e78f

Browse files
committed
Generalized validation issue filtering
1 parent 8724e84 commit be3e78f

File tree

4 files changed

+412
-141
lines changed

4 files changed

+412
-141
lines changed

src/issues/ValidationIssues.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,19 @@ export class ValidationIssues {
2121
const issue = new ValidationIssue(type, path, message, severity);
2222
return issue;
2323
}
24+
25+
/**
26+
* An issue that just summarizes information about the validation
27+
* process or result.
28+
*
29+
* @param path - The path for the `ValidationIssue`
30+
* @param message - The message for the `ValidationIssue`
31+
* @returns The `ValidationIssue`
32+
*/
33+
static VALIDATION_INFO(path: string, message: string) {
34+
const type = "VALIDATION_INFO";
35+
const severity = ValidationIssueSeverity.INFO;
36+
const issue = new ValidationIssue(type, path, message, severity);
37+
return issue;
38+
}
2439
}

src/tileFormats/GltfValidator.ts

Lines changed: 56 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { ValidationIssue } from "../validation/ValidationIssue";
66

77
import { ContentValidationIssues } from "../issues/ContentValidationIssues";
88
import { GltfExtensionValidators } from "../validation/gltf/GltfExtensionValidators";
9+
import { ValidationIssueSeverity } from "../validation/ValidationIssueSeverity";
10+
import { GltfDataReader } from "../validation/gltf/GltfDataReader";
911

1012
// eslint-disable-next-line @typescript-eslint/no-var-requires
1113
const validator = require("gltf-validator");
@@ -138,16 +140,40 @@ export class GltfValidator implements Validator<Buffer> {
138140
allCauses.push(cause);
139141
}
140142

141-
// XXX Draft for filtering.
142-
// TODO When the filtering removes the only WARNING, then
143-
// the "gltfResult.issues.numWarnings > 0" does no longer
144-
// make sense. The number of errors/warnings/infos have to
145-
// be determined based on the filtered result!
146-
const causes = GltfValidator.filterCauses(allCauses);
143+
// Read the glTF data
144+
const gltfData = await GltfDataReader.readGltfData(uri, input, context);
145+
if (!gltfData) {
146+
// Issue was already added to context
147+
return false;
148+
}
149+
150+
// Process the list of causes, possibly filtering out the ones that
151+
// are known to be obsolete due to the validation that is performed
152+
// by validators that are part of the 3D Tiles Validator
153+
const causes = await GltfExtensionValidators.processCauses(
154+
uri,
155+
gltfData,
156+
allCauses
157+
);
158+
159+
// The number of errors/warnings/infos is determined based on
160+
// the filtered issues.
161+
const numErrors = GltfValidator.countIssueSeverities(
162+
causes,
163+
ValidationIssueSeverity.ERROR
164+
);
165+
const numWarnings = GltfValidator.countIssueSeverities(
166+
causes,
167+
ValidationIssueSeverity.WARNING
168+
);
169+
const numInfos = GltfValidator.countIssueSeverities(
170+
causes,
171+
ValidationIssueSeverity.INFO
172+
);
147173

148174
// If there are any errors, then summarize ALL issues from the glTF
149175
// validation as 'internal issues' in a CONTENT_VALIDATION_ERROR
150-
if (gltfResult.issues.numErrors > 0) {
176+
if (numErrors > 0) {
151177
const path = uri;
152178
const message = `Content ${uri} caused validation errors`;
153179
const issue = ContentValidationIssues.CONTENT_VALIDATION_ERROR(
@@ -166,7 +192,7 @@ export class GltfValidator implements Validator<Buffer> {
166192
// If there are any warnings, then summarize them in a
167193
// CONTENT_VALIDATION_WARNING, but still consider the
168194
// object to be valid.
169-
if (gltfResult.issues.numWarnings > 0) {
195+
if (numWarnings > 0) {
170196
const path = uri;
171197
const message = `Content ${uri} caused validation warnings`;
172198
const issue = ContentValidationIssues.CONTENT_VALIDATION_WARNING(
@@ -178,7 +204,7 @@ export class GltfValidator implements Validator<Buffer> {
178204
issue.addCause(cause);
179205
}
180206
context.addIssue(issue);
181-
} else if (gltfResult.issues.numInfos > 0) {
207+
} else if (numInfos > 0) {
182208
// If there are no warnings, but infos, then summarize them in a
183209
// CONTENT_VALIDATION_INFO, but still consider the
184210
// object to be valid.
@@ -197,9 +223,14 @@ export class GltfValidator implements Validator<Buffer> {
197223
}
198224

199225
// When the glTF itself is considered to be valid, then perform
200-
// the validation of the Cesium glTF metadata extensions
226+
// the validation of the glTF extensions that are implemented
227+
// as part of the 3D Tiles Validator
201228
const extensionsValid =
202-
await GltfExtensionValidators.validateGltfExtensions(uri, input, context);
229+
await GltfExtensionValidators.validateGltfExtensions(
230+
uri,
231+
gltfData,
232+
context
233+
);
203234
if (!extensionsValid) {
204235
return false;
205236
}
@@ -208,92 +239,23 @@ export class GltfValidator implements Validator<Buffer> {
208239
}
209240

210241
/**
211-
* Tries to extract an extension name from the message that is generated by
212-
* the glTF Validator when it encounters an extension that is not supported.
213-
*
214-
* This makes assumptions about the structure of the message, and that it
215-
* is (verbatim) the message as it is generated by the glTF validator.
216-
*
217-
* @param message - The validation message
218-
* @returns The unsupported extension name, or `undefined` if the message
219-
* does not indicate an unsupported extension
220-
*/
221-
private static extractUnsupportedExtensionName(
222-
message: string
223-
): string | undefined {
224-
// Example:
225-
// "Cannot validate an extension as it is not supported by the validator: 'EXT_mesh_features'.",
226-
const prefix =
227-
"Cannot validate an extension as it is not supported by the validator: '";
228-
if (message.startsWith(prefix)) {
229-
const extensionName = message.substring(
230-
prefix.length,
231-
message.length - 2
232-
);
233-
return extensionName;
234-
}
235-
return undefined;
236-
}
237-
238-
/**
239-
* Filter the given list of validation issues based on the knowledge about
240-
* the the glTF extension validations that are implemented as part of the
241-
* 3D Tiles validator.
242-
*
243-
* The given list are the `ValidationIssue` objects that have been created
244-
* from the messages of the full glTF Validator output, using
245-
* `createValidationIssueFromGltfMessage`.
242+
* Counts and returns the number of issues in the given array that have
243+
* the given severity.
246244
*
247-
* @param causes - The causes
248-
* @returns The filtered causes
245+
* @param issues - The issues
246+
* @param severity - The severity
247+
* @returns The number of issues with the given severity
249248
*/
250-
private static filterCauses(causes: ValidationIssue[]): ValidationIssue[] {
251-
console.log("Filtering causes");
252-
const filteredCauses: ValidationIssue[] = causes.filter(
253-
(issue) => !GltfValidator.shouldRemove(issue)
254-
);
255-
return filteredCauses;
256-
}
257-
258-
// TODO DRAFT
259-
private static shouldRemove(issue: ValidationIssue): boolean {
260-
const message = issue.message;
261-
262-
// Messages about unsupported extensions should be removed
263-
// if and only if they are about an extension that was
264-
// registered in the GltfExtensionValidators
265-
const unsupportedExtensionName =
266-
GltfValidator.extractUnsupportedExtensionName(message);
267-
if (unsupportedExtensionName) {
268-
const isRegistered = GltfExtensionValidators.isRegistered(
269-
unsupportedExtensionName
270-
);
271-
if (isRegistered) {
272-
console.log(
273-
"Filtering out message about " +
274-
unsupportedExtensionName +
275-
" not being supported in glTF Validator"
276-
);
277-
return true;
249+
private static countIssueSeverities(
250+
issues: ValidationIssue[],
251+
severity: ValidationIssueSeverity
252+
): number {
253+
let count = 0;
254+
for (const issue of issues) {
255+
if (issue.severity === severity) {
256+
count++;
278257
}
279258
}
280-
281-
// TODO XXX DUMMY IMPLEMENTATION
282-
if (unsupportedExtensionName === "KHR_texture_basisu") {
283-
console.warn(
284-
"Filtering out message about KHR_texture_basisu not being supported!"
285-
);
286-
return true;
287-
}
288-
if (message.startsWith("Invalid value 'image/ktx2'.")) {
289-
console.warn("Filtering out message invalid image media type!");
290-
return true;
291-
}
292-
if (message === "Image format not recognized.") {
293-
console.warn("Filtering out unrecognized image format!");
294-
return true;
295-
}
296-
297-
return false;
259+
return count;
298260
}
299261
}

0 commit comments

Comments
 (0)