/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const Concept = require('./concept');
const TypedStack = require('../serializer/typedstack');
/**
* <p>
* Resource is an instance that has a type. The type of the resource
* specifies a set of properites (which themselves have types).
* </p>
* <p>
* Type information in Composer is used to validate the structure of
* Resource instances and for serialization.
* </p>
* <p>
* Resources are used in Composer to represent Assets, Participants, Transactions and
* other domain classes that can be serialized for long-term persistent storage.
* </p>
* @extends Identifiable
* @see See [Resource]{@link module:composer-common.Resource}
* @class
* @memberof module:composer-common
*/
class ValidatedConcept extends Concept {
/**
* This constructor should not be called directly.
* <p>
* <strong>Note: Only to be called by framework code. Applications should
* retrieve instances from {@link Factory}</strong>
* </p>
*
* @param {ModelManager} modelManager - The ModelManager for this instance
* @param {string} ns - The namespace this instance.
* @param {string} type - The type this instance.
* @param {ResourceValidator} resourceValidator - The validator to use for this instance
* @private
*/
constructor(modelManager, ns, type, resourceValidator) {
super(modelManager, ns, type);
this.$validator = resourceValidator;
}
/**
* Sets a property, validating that it does not violate the model
* @param {string} propName - the name of the field
* @param {string} value - the value of the property
* @throws {Error} if the value is not compatible with the model definition for the field
*/
setPropertyValue(propName, value) {
let classDeclaration = this.getClassDeclaration();
let field = classDeclaration.getProperty(propName);
if (!field) {
throw new Error('Trying to set field ' +
propName + ' which is not declared in the model.');
}
// else {
// this.log( 'Validating field ' + field + ' with data ' + value );
// }
const parameters = {};
parameters.stack = new TypedStack(value);
parameters.modelManager = this.getModelManager();
parameters.rootResourceIdentifier = 'undefined';
field.accept(this.$validator, parameters);
super.setPropertyValue(propName,value);
}
/**
* Adds an array property value, validating that it does not violate the model
* @param {string} propName - the name of the field
* @param {string} value - the value of the property
* @throws {Error} if the value is not compatible with the model definition for the field
*/
addArrayValue(propName, value) {
let classDeclaration = this.getClassDeclaration();
let field = classDeclaration.getProperty(propName);
if (!field) {
throw new Error('Trying to set field ' +
propName + ' which is not declared in the model.');
}
if (!field.isArray()) {
throw new Error('Trying to add array item ' +
propName + ' which is not declared as an array in the model.');
}
const parameters = {};
let newArray = [];
if(this[propName]) {
newArray = this[propName].slice(0);
}
newArray.push(value);
parameters.stack = new TypedStack(newArray);
parameters.modelManager = this.getModelManager();
parameters.rootResourceIdentifier = 'undefined';
field.accept(this.$validator, parameters);
super.addArrayValue(propName, value);
}
/**
* Validates the instance against its model.
*
* @throws {Error} - if the instance if invalid with respect to the model
*/
validate() {
const classDeclaration = this.getClassDeclaration();
const parameters = {};
parameters.stack = new TypedStack(this);
parameters.modelManager = this.getModelManager();
parameters.rootResourceIdentifier = 'undefined';
classDeclaration.accept(this.$validator, parameters);
}
}
module.exports = ValidatedConcept;