node-opcua-schemas
Advanced tools
Comparing version 2.1.0 to 2.1.1
import { StructuredTypeSchema } from "node-opcua-factory"; | ||
import { ExpandedNodeId } from "node-opcua-nodeid"; | ||
import { TypeDictionary } from "./parse_binary_xsd"; | ||
export declare function getOrCreateConstructor(fieldType: string, typeDictionary: TypeDictionary, encodingDefaultBinary?: ExpandedNodeId, encodingDefaultXml?: ExpandedNodeId): AnyConstructable; | ||
export declare function getOrCreateConstructor(fieldType: string, typeDictionary: TypeDictionary, encodingDefaultBinary?: ExpandedNodeId, encodingDefaultXml?: ExpandedNodeId): AnyConstructorFunc; | ||
interface AnyConstructable { | ||
new (options?: any): any; | ||
schema: StructuredTypeSchema; | ||
possibleFields: string[]; | ||
new (options?: any, schema?: StructuredTypeSchema, typeDictionary?: TypeDictionary): any; | ||
} | ||
export declare type AnyConstructorFunc = AnyConstructable; | ||
export declare function createDynamicObject(schema: StructuredTypeSchema, typeDictionary: TypeDictionary): AnyConstructorFunc; | ||
export declare function createDynamicObjectConstructor(schema: StructuredTypeSchema, typeDictionary: TypeDictionary): AnyConstructorFunc; | ||
export {}; |
@@ -20,5 +20,5 @@ "use strict"; | ||
if (!schema) { | ||
throw new Error("Unknown type in dictionary" + fieldType); | ||
throw new Error("Unknown type in dictionary " + fieldType); | ||
} | ||
const constructor = createDynamicObject(schema, typeDictionary); | ||
const constructor = createDynamicObjectConstructor(schema, typeDictionary); | ||
if (encodingDefaultBinary && encodingDefaultBinary.value !== 0) { | ||
@@ -36,2 +36,6 @@ schema.encodingDefaultBinary = encodingDefaultBinary; | ||
else { | ||
// istanbul ignore next | ||
if (doDebug) { | ||
debugLog("registering factory , ", fieldType); | ||
} | ||
node_opcua_factory_1.registerFactory(fieldType, constructor); | ||
@@ -107,2 +111,119 @@ } | ||
} | ||
/** | ||
* @private | ||
* @param thisAny | ||
* @param options | ||
* @param schema | ||
* @param typeDictionary | ||
*/ | ||
function initializeFields(thisAny, options, schema, typeDictionary) { | ||
// initialize base class first | ||
if (schema._baseSchema && schema._baseSchema.fields.length) { | ||
initializeFields(thisAny, options, schema._baseSchema, typeDictionary); | ||
} | ||
// finding fields that are in options but not in schema! | ||
for (const field of schema.fields) { | ||
const name = field.name; | ||
// dealing with optional fields | ||
if (field.switchBit !== undefined && options[field.name] === undefined) { | ||
(thisAny)[name] = undefined; | ||
continue; | ||
} | ||
switch (field.category) { | ||
case node_opcua_factory_1.FieldCategory.complex: { | ||
const constuctor = getOrCreateConstructor(field.fieldType, typeDictionary) || node_opcua_factory_1.BaseUAObject; | ||
if (field.isArray) { | ||
(thisAny)[name] = (options[name] || []).map((x) => constuctor ? new constuctor(x) : null); | ||
} | ||
else { | ||
(thisAny)[name] = constuctor ? new constuctor(options[name]) : null; | ||
} | ||
// xx processStructuredType(fieldSchema); | ||
break; | ||
} | ||
case node_opcua_factory_1.FieldCategory.enumeration: | ||
case node_opcua_factory_1.FieldCategory.basic: | ||
if (field.isArray) { | ||
(thisAny)[name] = node_opcua_factory_1.initialize_field_array(field, options[name]); | ||
} | ||
else { | ||
(thisAny)[name] = node_opcua_factory_1.initialize_field(field, options[name]); | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
function encodeFields(thisAny, schema, stream) { | ||
// encodeFields base class first | ||
if (schema._baseSchema && schema._baseSchema.fields.length) { | ||
encodeFields(thisAny, schema._baseSchema, stream); | ||
} | ||
// ============ Deal with switchBits | ||
if (schema.bitFields && schema.bitFields.length) { | ||
let bitField = 0; | ||
for (const field of schema.fields) { | ||
if (field.switchBit === undefined) { | ||
continue; | ||
} | ||
if ((thisAny)[field.name] === undefined) { | ||
continue; | ||
} | ||
// tslint:disable-next-line:no-bitwise | ||
bitField |= (1 << field.switchBit); | ||
} | ||
// write | ||
stream.writeUInt32(bitField); | ||
} | ||
for (const field of schema.fields) { | ||
// ignore | ||
if (field.switchBit !== undefined && (thisAny)[field.name] === undefined) { | ||
continue; | ||
} | ||
switch (field.category) { | ||
case node_opcua_factory_1.FieldCategory.complex: | ||
encodeArrayOrElement(field, thisAny, stream); | ||
break; | ||
case node_opcua_factory_1.FieldCategory.enumeration: | ||
case node_opcua_factory_1.FieldCategory.basic: | ||
encodeArrayOrElement(field, thisAny, stream, field.schema.encode); | ||
break; | ||
default: | ||
/* istanbul ignore next*/ | ||
throw new Error("Invalid category " + field.category + " " + node_opcua_factory_1.FieldCategory[field.category]); | ||
} | ||
} | ||
} | ||
function decodeFields(thisAny, schema, stream) { | ||
// encodeFields base class first | ||
if (schema._baseSchema && schema._baseSchema.fields.length) { | ||
decodeFields(thisAny, schema._baseSchema, stream); | ||
} | ||
// ============ Deal with switchBits | ||
let bitField = 0; | ||
if (schema.bitFields && schema.bitFields.length) { | ||
bitField = stream.readUInt32(); | ||
} | ||
for (const field of schema.fields) { | ||
// ignore fields that have a switch bit when bit is not set | ||
if (field.switchBit !== undefined) { | ||
// tslint:disable-next-line:no-bitwise | ||
if ((bitField & (1 << field.switchBit)) === 0) { | ||
(thisAny)[field.name] = undefined; | ||
continue; | ||
} | ||
} | ||
switch (field.category) { | ||
case node_opcua_factory_1.FieldCategory.complex: | ||
decodeArrayOrElement(field, thisAny, stream); | ||
break; | ||
case node_opcua_factory_1.FieldCategory.enumeration: | ||
case node_opcua_factory_1.FieldCategory.basic: | ||
decodeArrayOrElement(field, thisAny, stream, field.schema.decode); | ||
break; | ||
default: | ||
/* istanbul ignore next*/ | ||
throw new Error("Invalid category " + field.category + " " + node_opcua_factory_1.FieldCategory[field.category]); | ||
} | ||
} | ||
} | ||
class DynamicExtensionObject extends node_opcua_extension_object_1.ExtensionObject { | ||
@@ -116,10 +237,54 @@ constructor(options, schema, typeDictionary) { | ||
node_opcua_factory_1.check_options_correctness_against_schema(this, this.schema, options); | ||
initializeFields(this, options, this.schema, typeDictionary); | ||
} | ||
encode(stream) { | ||
super.encode(stream); | ||
encodeFields(this, this.schema, stream); | ||
} | ||
decode(stream) { | ||
super.decode(stream); | ||
decodeFields(this, this.schema, stream); | ||
} | ||
get schema() { | ||
return this.__schema; | ||
} | ||
} | ||
DynamicExtensionObject.schema = node_opcua_extension_object_1.ExtensionObject.schema; | ||
DynamicExtensionObject.possibleFields = []; | ||
// tslint:disable-next-line:max-classes-per-file | ||
class UnionBaseClass extends node_opcua_factory_1.BaseUAObject { | ||
constructor(options, schema, typeDictionary) { | ||
super(); | ||
node_opcua_assert_1.assert(schema, "expecting a schema here "); | ||
node_opcua_assert_1.assert(typeDictionary, "expecting a typeDic"); | ||
options = options || {}; | ||
this.__schema = schema; | ||
node_opcua_factory_1.check_options_correctness_against_schema(this, this.schema, options); | ||
let uniqueFieldHasBeenFound = false; | ||
let switchFieldName = ""; | ||
// finding fields that are in options but not in schema! | ||
for (const field of this.schema.fields) { | ||
const name = field.name; | ||
if (field.switchValue === undefined) { | ||
switchFieldName = field.name; | ||
// this is the switch value field | ||
continue; | ||
} | ||
node_opcua_assert_1.assert(switchFieldName.length > 0); | ||
node_opcua_assert_1.assert(field.switchValue !== undefined, "union must only have field with switchedValue"); | ||
// dealing with optional fields | ||
if (field.switchBit !== undefined && options[field.name] === undefined) { | ||
this[name] = undefined; | ||
if (uniqueFieldHasBeenFound && options[field.name] !== undefined) { | ||
throw new Error("union must have only one choice"); | ||
} | ||
if (options[field.name] === undefined) { | ||
continue; | ||
} | ||
uniqueFieldHasBeenFound = true; | ||
if (options[switchFieldName] !== undefined) { | ||
// then options[switchFieldName] must equql | ||
if (options[switchFieldName] !== field.switchValue) { | ||
throw new Error("Invalid " + switchFieldName + " value : expecting " + field.switchValue); | ||
} | ||
} | ||
this[switchFieldName] = field.switchValue; | ||
switch (field.category) { | ||
@@ -148,24 +313,20 @@ case node_opcua_factory_1.FieldCategory.complex: { | ||
} | ||
if (!uniqueFieldHasBeenFound) { | ||
if (Object.keys(options).length === 0) { | ||
this[switchFieldName] = 0xFFFFFFFF; | ||
return; | ||
} | ||
const r = schema.fields.filter((f) => f.switchValue !== undefined).map((f) => f.name).join(" , "); | ||
throw new Error(" At least one of " + r + " must be specified"); | ||
} | ||
} | ||
encode(stream) { | ||
super.encode(stream); | ||
// ============ Deal with switchBits | ||
if (this.schema.bitFields && this.schema.bitFields.length) { | ||
let bitField = 0; | ||
for (const field of this.schema.fields) { | ||
if (field.switchBit === undefined) { | ||
continue; | ||
} | ||
if (this[field.name] === undefined) { | ||
continue; | ||
} | ||
// tslint:disable-next-line:no-bitwise | ||
bitField |= (1 << field.switchBit); | ||
} | ||
// write | ||
stream.writeUInt32(bitField); | ||
const switchFieldName = this.schema.fields[0].name; | ||
const switchValue = this[switchFieldName]; | ||
if (typeof switchValue !== "number") { | ||
throw new Error("Invalid switchValue " + switchValue); | ||
} | ||
stream.writeUInt32(switchValue); | ||
for (const field of this.schema.fields) { | ||
// ignore | ||
if (field.switchBit !== undefined && this[field.name] === undefined) { | ||
if (field.switchValue === undefined || field.switchValue !== switchValue) { | ||
continue; | ||
@@ -185,19 +346,12 @@ } | ||
} | ||
break; | ||
} | ||
} | ||
decode(stream) { | ||
super.decode(stream); | ||
// ============ Deal with switchBits | ||
let bitField = 0; | ||
if (this.schema.bitFields && this.schema.bitFields.length) { | ||
bitField = stream.readUInt32(); | ||
} | ||
const switchValue = stream.readUInt32(); | ||
const switchFieldName = this.schema.fields[0].name; | ||
this[switchFieldName] = switchValue; | ||
for (const field of this.schema.fields) { | ||
// ignore fields that have a switch bit when bit is not set | ||
if (field.switchBit !== undefined) { | ||
// tslint:disable-next-line:no-bitwise | ||
if ((bitField & (1 << field.switchBit)) === 0) { | ||
this[field.name] = undefined; | ||
continue; | ||
} | ||
if (field.switchValue === undefined || field.switchValue !== switchValue) { | ||
continue; | ||
} | ||
@@ -216,2 +370,3 @@ switch (field.category) { | ||
} | ||
break; | ||
} | ||
@@ -222,6 +377,41 @@ } | ||
} | ||
toString() { | ||
return super.toString(); | ||
} | ||
toJSON() { | ||
const pojo = {}; | ||
const switchFieldName = this.schema.fields[0].name; | ||
const switchValue = this[switchFieldName]; | ||
if (typeof switchValue !== "number") { | ||
throw new Error("Invalid switchValue " + switchValue); | ||
} | ||
pojo[switchFieldName] = switchValue; | ||
for (const field of this.schema.fields) { | ||
if (field.switchValue === undefined || field.switchValue !== switchValue) { | ||
continue; | ||
} | ||
if (this[field.name] === undefined) { | ||
continue; | ||
} | ||
switch (field.category) { | ||
case node_opcua_factory_1.FieldCategory.complex: | ||
pojo[field.name] = this[field.name].toJSON(); | ||
break; | ||
case node_opcua_factory_1.FieldCategory.enumeration: | ||
case node_opcua_factory_1.FieldCategory.basic: | ||
pojo[field.name] = this[field.name].toJSON ? this[field.name].toJSON() : this[field.name]; | ||
break; | ||
default: | ||
/* istanbul ignore next*/ | ||
throw new Error("Invalid category " + field.category + " " + node_opcua_factory_1.FieldCategory[field.category]); | ||
} | ||
break; | ||
} | ||
return pojo; | ||
} | ||
} | ||
function createDynamicObject(schema, typeDictionary) { | ||
function _createDynamicUnionConstructor(schema, typeDictionary) { | ||
const possibleFields = schema.fields.map((x) => x.name); | ||
// tslint:disable-next-line:max-classes-per-file | ||
class EXTENSION extends DynamicExtensionObject { | ||
class UNION extends UnionBaseClass { | ||
constructor(options) { | ||
@@ -231,2 +421,36 @@ super(options, schema, typeDictionary); | ||
} | ||
} | ||
UNION.possibleFields = possibleFields; | ||
UNION.schema = schema; | ||
// to do : may be remove DataType suffix here ? | ||
Object.defineProperty(UNION, "name", { value: schema.name }); | ||
return UNION; | ||
} | ||
function createDynamicObjectConstructor(schema, typeDictionary) { | ||
const schemaPriv = schema; | ||
if (schemaPriv.$Constructor) { | ||
return schemaPriv.$Constructor; | ||
} | ||
if (schema.baseType === "Union") { | ||
const UNIONConstructor = _createDynamicUnionConstructor(schema, typeDictionary); | ||
schemaPriv.$Constructor = UNIONConstructor; | ||
return UNIONConstructor; | ||
} | ||
let possibleFields = schema.fields.map((x) => x.name); | ||
let BaseClass = DynamicExtensionObject; | ||
if (schema.baseType !== "ExtensionObject") { | ||
BaseClass = getOrCreateConstructor(schema.baseType, typeDictionary); | ||
if (!BaseClass) { | ||
throw new Error("Cannot find base class : " + schema.baseType); | ||
} | ||
if (BaseClass.possibleFields) { | ||
possibleFields = BaseClass.possibleFields.concat(possibleFields); | ||
} | ||
schema._baseSchema = BaseClass.schema; | ||
} | ||
// tslint:disable-next-line:max-classes-per-file | ||
class EXTENSION extends BaseClass { | ||
constructor(options, schema2, typeDictionary2) { | ||
super(options, schema2 ? schema2 : schema, typeDictionary2 ? typeDictionary2 : typeDictionary); | ||
} | ||
toString() { | ||
@@ -238,9 +462,10 @@ return super.toString(); | ||
EXTENSION.encodingDefaultBinary = new node_opcua_nodeid_1.ExpandedNodeId(node_opcua_nodeid_1.NodeIdType.NUMERIC, 0, 0); | ||
EXTENSION.possibleFields = schema.fields.map((x) => x.name); | ||
EXTENSION.possibleFields = possibleFields; | ||
EXTENSION.schema = schema; | ||
// to do : may be remove DataType suffix here ? | ||
Object.defineProperty(EXTENSION, "name", { value: schema.name }); | ||
schemaPriv.$Constructor = EXTENSION; | ||
return EXTENSION; | ||
} | ||
exports.createDynamicObject = createDynamicObject; | ||
exports.createDynamicObjectConstructor = createDynamicObjectConstructor; | ||
//# sourceMappingURL=dynamic_extension_object.js.map |
@@ -182,3 +182,7 @@ "use strict"; | ||
if (this.attrs.SwitchValue) { | ||
// we are in a union | ||
field.switchValue = parseInt(this.attrs.SwitchValue, 10); | ||
if (doDebug) { | ||
console.log("field", field.name, " is part of a union => ", switchField, " value #", field.switchValue); | ||
} | ||
} | ||
@@ -185,0 +189,0 @@ else { |
import { StructuredTypeSchema } from "node-opcua-factory"; | ||
import { EnumeratedType, StructureTypeRaw, TypeDictionary } from "./parse_binary_xsd"; | ||
export declare function getOrCreateStructuredTypeSchema(name: string, typeDictionary: TypeDictionary): StructuredTypeSchema; | ||
export declare function prepareStructureType(structuredType: StructureTypeRaw, typeDictionary: TypeDictionary): void; | ||
export declare function prepareStructureType(structuredType: StructureTypeRaw, typeDictionary: TypeDictionary): StructuredTypeSchema; | ||
export declare function prepareEnumeratedType(enumeratedType: EnumeratedType, typeDictionary: TypeDictionary): void; |
@@ -8,3 +8,4 @@ "use strict"; | ||
} | ||
return str.split(":")[1]; | ||
const data = str.split(":"); | ||
return data.length > 1 ? data[1] : str; | ||
} | ||
@@ -111,5 +112,6 @@ function getNamespacePart(str) { | ||
if (typeDictionary.structuredTypes[key]) { | ||
return; // already done | ||
return typeDictionary.structuredTypes[key]; // already done | ||
} | ||
typeDictionary.structuredTypes[key] = getOrCreateStructuredTypeSchema(key, typeDictionary); | ||
return typeDictionary.structuredTypes[key]; | ||
} | ||
@@ -116,0 +118,0 @@ exports.prepareStructureType = prepareStructureType; |
{ | ||
"name": "node-opcua-schemas", | ||
"version": "2.1.0", | ||
"version": "2.1.1", | ||
"description": "pure nodejs OPCUA SDK - module -schemas", | ||
@@ -14,13 +14,13 @@ "main": "dist/source/index.js", | ||
"node-opcua-binary-stream": "^2.1.0", | ||
"node-opcua-data-model": "^2.1.0", | ||
"node-opcua-data-model": "^2.1.1", | ||
"node-opcua-debug": "^2.1.0", | ||
"node-opcua-enum": "^2.1.0", | ||
"node-opcua-extension-object": "^2.1.0", | ||
"node-opcua-factory": "^2.1.0", | ||
"node-opcua-extension-object": "^2.1.1", | ||
"node-opcua-factory": "^2.1.1", | ||
"node-opcua-nodeid": "^2.1.0", | ||
"node-opcua-variant": "^2.1.0", | ||
"node-opcua-xml2json": "^2.1.0" | ||
"node-opcua-variant": "^2.1.1", | ||
"node-opcua-xml2json": "^2.1.1" | ||
}, | ||
"devDependencies": { | ||
"node-opcua-packet-analyzer": "^2.1.0" | ||
"node-opcua-packet-analyzer": "^2.1.1" | ||
}, | ||
@@ -42,3 +42,3 @@ "author": "Etienne Rossignon", | ||
"homepage": "http://node-opcua.github.io/", | ||
"gitHead": "ddce2b6e3e13371510e63d839c1a4c4ff0be2c15" | ||
"gitHead": "672816a1babe8c9347f85e47cf4e947f4749507e" | ||
} |
@@ -30,3 +30,3 @@ /** | ||
encodingDefaultXml?: ExpandedNodeId | ||
) { | ||
): AnyConstructorFunc { | ||
@@ -40,6 +40,6 @@ if (hasStructuredType(fieldType)) { | ||
if (!schema) { | ||
throw new Error("Unknown type in dictionary" + fieldType); | ||
throw new Error("Unknown type in dictionary " + fieldType); | ||
} | ||
const constructor = createDynamicObject(schema, typeDictionary); | ||
const constructor = createDynamicObjectConstructor(schema, typeDictionary); | ||
@@ -59,2 +59,6 @@ if (encodingDefaultBinary && encodingDefaultBinary.value !== 0) { | ||
} else { | ||
// istanbul ignore next | ||
if (doDebug) { | ||
debugLog("registering factory , ", fieldType); | ||
} | ||
registerFactory(fieldType, constructor as ConstructorFuncWithSchema); | ||
@@ -134,4 +138,144 @@ } | ||
/** | ||
* @private | ||
* @param thisAny | ||
* @param options | ||
* @param schema | ||
* @param typeDictionary | ||
*/ | ||
function initializeFields(thisAny: any, options: any, schema: StructuredTypeSchema, typeDictionary: TypeDictionary) { | ||
// initialize base class first | ||
if (schema._baseSchema && schema._baseSchema.fields.length) { | ||
initializeFields(thisAny, options, schema._baseSchema!, typeDictionary); | ||
} | ||
// finding fields that are in options but not in schema! | ||
for (const field of schema.fields) { | ||
const name = field.name; | ||
// dealing with optional fields | ||
if (field.switchBit !== undefined && options[field.name] === undefined) { | ||
(thisAny)[name] = undefined; | ||
continue; | ||
} | ||
switch (field.category) { | ||
case FieldCategory.complex: { | ||
const constuctor = getOrCreateConstructor(field.fieldType, typeDictionary) || BaseUAObject; | ||
if (field.isArray) { | ||
(thisAny)[name] = (options[name] || []).map((x: any) => | ||
constuctor ? new constuctor(x) : null | ||
); | ||
} else { | ||
(thisAny)[name] = constuctor ? new constuctor(options[name]) : null; | ||
} | ||
// xx processStructuredType(fieldSchema); | ||
break; | ||
} | ||
case FieldCategory.enumeration: | ||
case FieldCategory.basic: | ||
if (field.isArray) { | ||
(thisAny)[name] = initialize_field_array(field, options[name]); | ||
} else { | ||
(thisAny)[name] = initialize_field(field, options[name]); | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
function encodeFields(thisAny: any, schema: StructuredTypeSchema, stream: OutputBinaryStream) { | ||
// encodeFields base class first | ||
if (schema._baseSchema && schema._baseSchema.fields.length) { | ||
encodeFields(thisAny, schema._baseSchema!, stream); | ||
} | ||
// ============ Deal with switchBits | ||
if (schema.bitFields && schema.bitFields.length) { | ||
let bitField = 0; | ||
for (const field of schema.fields) { | ||
if (field.switchBit === undefined) { | ||
continue; | ||
} | ||
if ((thisAny)[field.name] === undefined) { | ||
continue; | ||
} | ||
// tslint:disable-next-line:no-bitwise | ||
bitField |= (1 << field.switchBit); | ||
} | ||
// write | ||
stream.writeUInt32(bitField); | ||
} | ||
for (const field of schema.fields) { | ||
// ignore | ||
if (field.switchBit !== undefined && (thisAny)[field.name] === undefined) { | ||
continue; | ||
} | ||
switch (field.category) { | ||
case FieldCategory.complex: | ||
encodeArrayOrElement(field, thisAny, stream); | ||
break; | ||
case FieldCategory.enumeration: | ||
case FieldCategory.basic: | ||
encodeArrayOrElement(field, thisAny, stream, field.schema.encode); | ||
break; | ||
default: | ||
/* istanbul ignore next*/ | ||
throw new Error("Invalid category " + field.category + " " + FieldCategory[field.category]); | ||
} | ||
} | ||
} | ||
function decodeFields(thisAny: any, schema: StructuredTypeSchema, stream: BinaryStream) { | ||
// encodeFields base class first | ||
if (schema._baseSchema && schema._baseSchema.fields.length) { | ||
decodeFields(thisAny, schema._baseSchema!, stream); | ||
} | ||
// ============ Deal with switchBits | ||
let bitField = 0; | ||
if (schema.bitFields && schema.bitFields.length) { | ||
bitField = stream.readUInt32(); | ||
} | ||
for (const field of schema.fields) { | ||
// ignore fields that have a switch bit when bit is not set | ||
if (field.switchBit !== undefined) { | ||
// tslint:disable-next-line:no-bitwise | ||
if ((bitField & (1 << field.switchBit)) === 0) { | ||
(thisAny)[field.name] = undefined; | ||
continue; | ||
} | ||
} | ||
switch (field.category) { | ||
case FieldCategory.complex: | ||
decodeArrayOrElement(field, thisAny, stream); | ||
break; | ||
case FieldCategory.enumeration: | ||
case FieldCategory.basic: | ||
decodeArrayOrElement(field, thisAny, stream, field.schema.decode); | ||
break; | ||
default: | ||
/* istanbul ignore next*/ | ||
throw new Error("Invalid category " + field.category + " " + FieldCategory[field.category]); | ||
} | ||
} | ||
} | ||
class DynamicExtensionObject extends ExtensionObject { | ||
public static schema: StructuredTypeSchema = ExtensionObject.schema; | ||
public static possibleFields: string[] = []; | ||
private __schema?: StructuredTypeSchema; | ||
@@ -149,2 +293,48 @@ | ||
initializeFields(this as any, options, this.schema, typeDictionary); | ||
} | ||
public encode(stream: OutputBinaryStream): void { | ||
super.encode(stream); | ||
encodeFields(this as any, this.schema, stream); | ||
} | ||
public decode(stream: BinaryStream): void { | ||
super.decode(stream); | ||
decodeFields(this as any, this.schema, stream); | ||
} | ||
public get schema(): StructuredTypeSchema { | ||
return this.__schema!; | ||
} | ||
} | ||
// tslint:disable:callable-types | ||
interface AnyConstructable { | ||
schema: StructuredTypeSchema; | ||
possibleFields: string[]; | ||
new(options?: any, schema?: StructuredTypeSchema, typeDictionary?: TypeDictionary): any; | ||
} | ||
export type AnyConstructorFunc = AnyConstructable; | ||
// tslint:disable-next-line:max-classes-per-file | ||
class UnionBaseClass extends BaseUAObject { | ||
private __schema?: StructuredTypeSchema; | ||
constructor(options: any, schema: StructuredTypeSchema, typeDictionary: TypeDictionary) { | ||
super(); | ||
assert(schema, "expecting a schema here "); | ||
assert(typeDictionary, "expecting a typeDic"); | ||
options = options || {}; | ||
this.__schema = schema; | ||
check_options_correctness_against_schema(this, this.schema, options); | ||
let uniqueFieldHasBeenFound = false; | ||
let switchFieldName = ""; | ||
// finding fields that are in options but not in schema! | ||
@@ -155,8 +345,29 @@ for (const field of this.schema.fields) { | ||
if (field.switchValue === undefined) { | ||
switchFieldName = field.name; | ||
// this is the switch value field | ||
continue; | ||
} | ||
assert(switchFieldName.length > 0); | ||
assert(field.switchValue !== undefined, "union must only have field with switchedValue"); | ||
// dealing with optional fields | ||
if (field.switchBit !== undefined && options[field.name] === undefined) { | ||
(this as any)[name] = undefined; | ||
if (uniqueFieldHasBeenFound && options[field.name] !== undefined) { | ||
throw new Error("union must have only one choice"); | ||
} | ||
if (options[field.name] === undefined) { | ||
continue; | ||
} | ||
uniqueFieldHasBeenFound = true; | ||
if (options[switchFieldName] !== undefined) { | ||
// then options[switchFieldName] must equql | ||
if (options[switchFieldName] !== field.switchValue) { | ||
throw new Error("Invalid " + switchFieldName + " value : expecting " + field.switchValue); | ||
} | ||
} | ||
(this as any)[switchFieldName] = field.switchValue; | ||
switch (field.category) { | ||
@@ -186,34 +397,25 @@ case FieldCategory.complex: { | ||
} | ||
if (!uniqueFieldHasBeenFound) { | ||
if (Object.keys(options).length === 0) { | ||
(this as any)[switchFieldName] = 0xFFFFFFFF; | ||
return; | ||
} | ||
const r = schema.fields.filter((f) => f.switchValue !== undefined).map((f) => f.name).join(" , "); | ||
throw new Error(" At least one of " + r + " must be specified"); | ||
} | ||
} | ||
public encode(stream: OutputBinaryStream): void { | ||
super.encode(stream); | ||
// ============ Deal with switchBits | ||
if (this.schema.bitFields && this.schema.bitFields.length) { | ||
let bitField = 0; | ||
for (const field of this.schema.fields) { | ||
if (field.switchBit === undefined) { | ||
continue; | ||
} | ||
if ((this as any)[field.name] === undefined) { | ||
continue; | ||
} | ||
// tslint:disable-next-line:no-bitwise | ||
bitField |= (1 << field.switchBit); | ||
} | ||
// write | ||
stream.writeUInt32(bitField); | ||
const switchFieldName = this.schema.fields[0].name; | ||
const switchValue = (this as any)[switchFieldName]; | ||
if (typeof switchValue !== "number") { | ||
throw new Error("Invalid switchValue " + switchValue); | ||
} | ||
stream.writeUInt32(switchValue); | ||
for (const field of this.schema.fields) { | ||
// ignore | ||
if (field.switchBit !== undefined && (this as any)[field.name] === undefined) { | ||
if (field.switchValue === undefined || field.switchValue !== switchValue) { | ||
continue; | ||
} | ||
switch (field.category) { | ||
@@ -231,2 +433,3 @@ case FieldCategory.complex: | ||
} | ||
break; | ||
} | ||
@@ -236,20 +439,12 @@ } | ||
public decode(stream: BinaryStream): void { | ||
super.decode(stream); | ||
// ============ Deal with switchBits | ||
let bitField = 0; | ||
if (this.schema.bitFields && this.schema.bitFields.length) { | ||
bitField = stream.readUInt32(); | ||
} | ||
const switchValue = stream.readUInt32(); | ||
const switchFieldName = this.schema.fields[0].name; | ||
(this as any)[switchFieldName] = switchValue; | ||
for (const field of this.schema.fields) { | ||
// ignore fields that have a switch bit when bit is not set | ||
if (field.switchBit !== undefined) { | ||
// tslint:disable-next-line:no-bitwise | ||
if ((bitField & (1 << field.switchBit)) === 0) { | ||
(this as any)[field.name] = undefined; | ||
continue; | ||
} | ||
if (field.switchValue === undefined || field.switchValue !== switchValue) { | ||
continue; | ||
} | ||
@@ -269,2 +464,3 @@ | ||
} | ||
break; | ||
} | ||
@@ -277,12 +473,45 @@ } | ||
} | ||
public toString(): string { | ||
return super.toString(); | ||
} | ||
// tslint:disable:callable-types | ||
interface AnyConstructable { | ||
new(options?: any): any; | ||
public toJSON(): string { | ||
const pojo: any = {}; | ||
const switchFieldName = this.schema.fields[0].name; | ||
const switchValue = (this as any)[switchFieldName]; | ||
if (typeof switchValue !== "number") { | ||
throw new Error("Invalid switchValue " + switchValue); | ||
} | ||
pojo[switchFieldName] = switchValue; | ||
for (const field of this.schema.fields) { | ||
if (field.switchValue === undefined || field.switchValue !== switchValue) { | ||
continue; | ||
} | ||
if ((this as any)[field.name] === undefined) { | ||
continue; | ||
} | ||
switch (field.category) { | ||
case FieldCategory.complex: | ||
pojo[field.name] = (this as any)[field.name].toJSON(); | ||
break; | ||
case FieldCategory.enumeration: | ||
case FieldCategory.basic: | ||
pojo[field.name] = (this as any)[field.name].toJSON ? (this as any)[field.name].toJSON() : (this as any)[field.name]; | ||
break; | ||
default: | ||
/* istanbul ignore next*/ | ||
throw new Error("Invalid category " + field.category + " " + FieldCategory[field.category]); | ||
} | ||
break; | ||
} | ||
return pojo; | ||
} | ||
} | ||
export type AnyConstructorFunc = AnyConstructable; | ||
export function createDynamicObject( | ||
function _createDynamicUnionConstructor( | ||
schema: StructuredTypeSchema, | ||
@@ -292,7 +521,7 @@ typeDictionary: TypeDictionary | ||
const possibleFields = schema.fields.map((x: FieldType) => x.name); | ||
// tslint:disable-next-line:max-classes-per-file | ||
class EXTENSION extends DynamicExtensionObject { | ||
public static encodingDefaultXml = new ExpandedNodeId(NodeIdType.NUMERIC, 0, 0); | ||
public static encodingDefaultBinary = new ExpandedNodeId(NodeIdType.NUMERIC, 0, 0); | ||
public static possibleFields = schema.fields.map((x: FieldType) => x.name); | ||
class UNION extends UnionBaseClass { | ||
public static possibleFields = possibleFields; | ||
public static schema = schema; | ||
@@ -304,6 +533,57 @@ | ||
} | ||
} | ||
// to do : may be remove DataType suffix here ? | ||
Object.defineProperty(UNION, "name", { value: schema.name }); | ||
return UNION; | ||
} | ||
export function createDynamicObjectConstructor( | ||
schema: StructuredTypeSchema, | ||
typeDictionary: TypeDictionary | ||
): AnyConstructorFunc { | ||
const schemaPriv = schema as any; | ||
if (schemaPriv.$Constructor) { | ||
return schemaPriv.$Constructor; | ||
} | ||
if (schema.baseType === "Union") { | ||
const UNIONConstructor = _createDynamicUnionConstructor(schema, typeDictionary); | ||
schemaPriv.$Constructor = UNIONConstructor; | ||
return UNIONConstructor; | ||
} | ||
let possibleFields = schema.fields.map((x: FieldType) => x.name); | ||
let BaseClass: AnyConstructorFunc = DynamicExtensionObject as AnyConstructorFunc; | ||
if (schema.baseType !== "ExtensionObject") { | ||
BaseClass = getOrCreateConstructor(schema.baseType, typeDictionary); | ||
if (!BaseClass) { | ||
throw new Error("Cannot find base class : " + schema.baseType); | ||
} | ||
if ((BaseClass as any).possibleFields) { | ||
possibleFields = (BaseClass as any).possibleFields.concat(possibleFields); | ||
} | ||
schema._baseSchema = BaseClass.schema; | ||
} | ||
// tslint:disable-next-line:max-classes-per-file | ||
class EXTENSION extends BaseClass { | ||
public static encodingDefaultXml = new ExpandedNodeId(NodeIdType.NUMERIC, 0, 0); | ||
public static encodingDefaultBinary = new ExpandedNodeId(NodeIdType.NUMERIC, 0, 0); | ||
public static possibleFields = possibleFields; | ||
public static schema = schema; | ||
constructor(options?: any, schema2?: StructuredTypeSchema, typeDictionary2?: TypeDictionary) { | ||
super(options, schema2 ? schema2 : schema, typeDictionary2 ? typeDictionary2 : typeDictionary); | ||
} | ||
public toString(): string { | ||
return super.toString(); | ||
} | ||
} | ||
@@ -314,3 +594,5 @@ | ||
schemaPriv.$Constructor = EXTENSION; | ||
return EXTENSION; | ||
} |
@@ -243,3 +243,7 @@ /** | ||
if (this.attrs.SwitchValue) { | ||
// we are in a union | ||
field.switchValue = parseInt(this.attrs.SwitchValue, 10); | ||
if (doDebug) { | ||
console.log("field", field.name, " is part of a union => ", switchField, " value #", field.switchValue); | ||
} | ||
} else { | ||
@@ -246,0 +250,0 @@ field.switchBit = structuredType.bitFields ? |
@@ -18,3 +18,4 @@ import { | ||
} | ||
return str.split(":")[1]; | ||
const data = str.split(":"); | ||
return data.length > 1 ? data[1] : str; | ||
} | ||
@@ -88,3 +89,2 @@ | ||
} else { | ||
@@ -131,9 +131,10 @@ field.category = FieldCategory.basic; | ||
typeDictionary: TypeDictionary | ||
): void { | ||
): StructuredTypeSchema { | ||
const key = structuredType.name; | ||
if (typeDictionary.structuredTypes[key]) { | ||
return; // already done | ||
return typeDictionary.structuredTypes[key]; // already done | ||
} | ||
typeDictionary.structuredTypes[key] = getOrCreateStructuredTypeSchema(key, typeDictionary); | ||
return typeDictionary.structuredTypes[key]; | ||
} | ||
@@ -140,0 +141,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
106182
1791
Updatednode-opcua-data-model@^2.1.1
Updatednode-opcua-factory@^2.1.1
Updatednode-opcua-variant@^2.1.1
Updatednode-opcua-xml2json@^2.1.1