Add code for data format webtool
[dcaegen2/platform/cli.git] / dcaedftool / src / app / validate-metaschema.service.ts
1 // org.onap.dcae\r
2 // ============LICENSE_START====================================================\r
3 // Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.\r
4 // =============================================================================\r
5 // Licensed under the Apache License, Version 2.0 (the "License");\r
6 // you may not use this file except in compliance with the License.\r
7 // You may obtain a copy of the License at\r
8 //\r
9 //     http://www.apache.org/licenses/LICENSE-2.0\r
10 //\r
11 // Unless required by applicable law or agreed to in writing, software\r
12 // distributed under the License is distributed on an "AS IS" BASIS,\r
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
14 // See the License for the specific language governing permissions and\r
15 // limitations under the License.\r
16 // ============LICENSE_END======================================================\r
17 //\r
18 // ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
19 import { Injectable } from '@angular/core';\r
20 import {MetaSchemaService} from './metaschema.service';\r
21 import {ValidateJSONService} from './validate-json.service';\r
22 import * as Ajv from 'ajv';\r
23 \r
24 @Injectable()\r
25 export class ValidateMetaSchemaService {\r
26 \r
27   private ajv: any;\r
28   private schemaValidate: any;\r
29   private metaSchema: MetaSchemaService;\r
30   private jsonValidate: ValidateJSONService;\r
31   private lastErrors:string[] = [];\r
32 \r
33   constructor(metaSchemaService: MetaSchemaService, jsonValidateService: ValidateJSONService) {\r
34     this.metaSchema = metaSchemaService;\r
35     this.jsonValidate = jsonValidateService;\r
36     }\r
37 \r
38   validate(schema: string): boolean {\r
39      // check JSON\r
40      if (this.jsonValidate.validate(schema) === false) {\r
41        // assumes simple message - TBD???\r
42        this.lastErrors[0] = this.jsonValidate.validateMsgs();\r
43        return false;\r
44      }\r
45     // Schema is assumed to be V4 for now (jsonschema does not support V6 yet so we must wait since this is used by the CLI)\r
46     try {\r
47        this.ajv = new Ajv({\r
48          meta: false, // optional, to prevent adding draft-06 meta-schema\r
49          extendRefs: true, // optional, current default is to 'fail', spec behaviour is to 'ignore'\r
50          allErrors:        true,\r
51          unknownFormats: 'ignore'  // optional, current default is true (fail)\r
52      });\r
53      // change this to http get at some point TBD\r
54      const schemav4: any = {    'id': 'http://json-schema.org/draft-04/schema#',    '$schema': 'http://json-schema.org/draft-04/schema#',    'description': 'Core schema meta-schema',    'definitions': {        'schemaArray': {            'type': 'array',            'minItems': 1,            'items': { '$ref': '#' }   },        'positiveInteger': {  'type': 'integer',            'minimum': 0        },        'positiveIntegerDefault0': {            'allOf': [ { '$ref': '#/definitions/positiveInteger' }, { 'default': 0 } ]        },        'simpleTypes': {            'enum': [ 'array', 'boolean', 'integer', 'null', 'number', 'object', 'string' ]        },        'stringArray': {            'type': 'array',            'items': { 'type': 'string' },            'minItems': 1,            'uniqueItems': true        }    },    'type': 'object',    'properties': {        'id': {            'type': 'string',            'format': 'uri'        },        '$schema': {            'type': 'string',            'format': 'uri'        },        'title': {            'type': 'string'        },        'description': {            'type': 'string'        },        'default': {},        'multipleOf': {            'type': 'number',            'minimum': 0,            'exclusiveMinimum': true        },        'maximum': {            'type': 'number'        },        'exclusiveMaximum': {            'type': 'boolean',            'default': false        },        'minimum': {            'type': 'number'        },        'exclusiveMinimum': {            'type': 'boolean',            'default': false        },        'maxLength': { '$ref': '#/definitions/positiveInteger' },        'minLength': { '$ref': '#/definitions/positiveIntegerDefault0' },        'pattern': {            'type': 'string',            'format': 'regex'        },        'additionalItems': {            'anyOf': [                { 'type': 'boolean' },                { '$ref': '#' }            ],            'default': {}        },        'items': {            'anyOf': [                { '$ref': '#' },                { '$ref': '#/definitions/schemaArray' }            ],            'default': {}        },        'maxItems': { '$ref': '#/definitions/positiveInteger' },        'minItems': { '$ref': '#/definitions/positiveIntegerDefault0' },        'uniqueItems': {            'type': 'boolean',            'default': false        },        'maxProperties': { '$ref': '#/definitions/positiveInteger' },        'minProperties': { '$ref': '#/definitions/positiveIntegerDefault0' },        'required': { '$ref': '#/definitions/stringArray' },        'additionalProperties': {            'anyOf': [                { 'type': 'boolean' },                { '$ref': '#' }            ],            'default': {}        },        'definitions': {            'type': 'object',            'additionalProperties': { '$ref': '#' },            'default': {}        },        'properties': {            'type': 'object',            'additionalProperties': { '$ref': '#' },            'default': {}        },        'patternProperties': {            'type': 'object',            'additionalProperties': { '$ref': '#' },            'default': {}        },        'dependencies': {            'type': 'object',            'additionalProperties': {                'anyOf': [                    { '$ref': '#' },                    { '$ref': '#/definitions/stringArray' }                ]            }        },        'enum': {            'type': 'array',            'minItems': 1,            'uniqueItems': true        },        'type': {            'anyOf': [                { '$ref': '#/definitions/simpleTypes' },                {                    'type': 'array',                    'items': { '$ref': '#/definitions/simpleTypes' },                    'minItems': 1,                    'uniqueItems': true                }            ]        },        'allOf': { '$ref': '#/definitions/schemaArray' },        'anyOf': { '$ref': '#/definitions/schemaArray' },        'oneOf': { '$ref': '#/definitions/schemaArray' },        'not': { '$ref': '#' }    },    'dependencies': {        'exclusiveMaximum': [ 'maximum' ],        'exclusiveMinimum': [ 'minimum' ]    },    'default': {}}\r
55 \r
56      const metaSchema = schemav4;\r
57 \r
58        this.ajv.addMetaSchema(metaSchema);\r
59        this.ajv._opts.defaultMeta = metaSchema.id;\r
60 \r
61        // Optionally you can also disable keywords defined in draft-06\r
62        this.ajv.removeKeyword('propertyNames');\r
63        this.ajv.removeKeyword('contains');\r
64        this.ajv.removeKeyword('const');\r
65 \r
66        const sValidate = this.ajv.compile(this.metaSchema.currentMetaSchema());\r
67        const result = sValidate(JSON.parse(schema));\r
68        let j = 0;\r
69        if (result === false) {\r
70          for ( const errMsg of Object.keys(sValidate.errors)) {\r
71             let msg = sValidate.errors[errMsg].message;\r
72             if (sValidate.errors[errMsg].hasOwnProperty('params')) {\r
73               if (sValidate.errors[errMsg].params.hasOwnProperty('additionalProperty')) {\r
74                 msg = msg + ' - ';\r
75                 msg = msg + sValidate.errors[errMsg].params.additionalProperty;\r
76               }\r
77             }\r
78             let dupMsg = false;\r
79             for (const k in this.lastErrors) {\r
80               if ( this.lastErrors[k] === msg) {\r
81                 dupMsg = true;\r
82               }\r
83             }\r
84             if (dupMsg ===  false) {\r
85              this.lastErrors[j] = msg;\r
86              j = j + 1;\r
87             }\r
88          }\r
89        }\r
90        return result;\r
91     } catch(ajvError){\r
92        this.lastErrors[0] =  ajvError;\r
93     }\r
94   }\r
95 \r
96   validateMsgs(): string[] {\r
97     return this.lastErrors;\r
98   }\r
99 }\r