Skip to content

Commit

Permalink
improve code in factory, fix variant with complex type
Browse files Browse the repository at this point in the history
  • Loading branch information
erossignon committed Feb 12, 2014
1 parent c5af739 commit c070503
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 55 deletions.
75 changes: 32 additions & 43 deletions lib/factories.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,8 @@ var constructorMap = {};


exports.findSimpleType = function findSimpleType(name) {
if (name in _defaultTypeMap) {
return _defaultTypeMap[name];
}
throw "cannot find " + name + " in " + util.inspect(_defaultTypeMap);
assert (name in _defaultTypeMap);
return _defaultTypeMap[name];
};


Expand All @@ -139,6 +137,7 @@ function _decode_by_type(obj, fieldType, stream) {
}

function _encode_member_(member, fieldType, stream) {

if (_defaultTypeMap[fieldType]) {

_encode_by_type(member, fieldType, stream);
Expand Down Expand Up @@ -522,24 +521,24 @@ var objectVisitor = function (self, description, data, callback) {


/**
* base constructor for all OPC-UA Object
*
* OPC-UA Object are created against a schema and provide binary encode/decode facilities.
*
* @constructor
*/
function BaseObject(schema,options) {

assert(this != undefined, " keyword 'new' is required for constructor call");
this._schema = schema;
var self = this;

assert(this != undefined, " keyword 'new' is required for constructor call");
assert(schema.name, " expecting schema to have a name");
assert(schema.fields, " expecting schema to provide a set of fields " + schema.name);

var self = this;
this._schema = schema;

options = options || {};

if (!schema.fields) {
throw new Error("fields missing in description " + schema)
}

if (schema.construct_hook) {
schema.construct_hook.call(this);
}
Expand Down Expand Up @@ -604,6 +603,11 @@ BaseObject.prototype.decode = function (stream, options) {
_decode_(this, this._schema, stream, options);
}
};

/**
*
*
*/
BaseObject.prototype.explore = function () {

var self = this;
Expand All @@ -615,7 +619,12 @@ BaseObject.prototype.explore = function () {
};



/**
* register a new type of object in the factory
*
* @param schema
* @returns {*}
*/
function registerObject(schema) {

var name = schema.name;
Expand All @@ -632,74 +641,54 @@ function registerObject(schema) {
if (schema.hasOwnProperty("subtype")) {

var t = _defaultTypeMap[schema.subtype];
if (t === undefined) {
throw " " + util.inspect(schema, {color: true}) + " cannot find subtype " + schema.subtype;
}
//xx console.log(util.inspect(description));
assert (t !== undefined," " + util.inspect(schema, {color: true}) + " cannot find subtype " + schema.subtype);
assert(_.isFunction(t.encode));
assert(_.isFunction(t.decode));
registerType(name, t.encode, t.decode, t.defaultValue);
return;
}

assert( !(name in factories), " Class " + name + " already in factories");

// check the unique id of the object
var id = schema.id;
if (!id) {
var encode_name = name + "_Encoding_DefaultBinary";
id = objectNodeIds[encode_name];
if (!id) {
throw new Error(" " + name + " has no _Encoding_DefaultBinary id \n"
+" please add a Id field in the structure definition" );
}
}
var expandedNodeId = ec.makeExpandedNodeId(id);
assert(id, "" + name + " has no _Encoding_DefaultBinary id\nplease add a Id field in the structure definition");

var expandedNodeId = ec.makeExpandedNodeId(id);

var ClassConstructor = function (options) {

BaseObject.call(this,schema,options);


};
util.inherits(ClassConstructor,BaseObject);




ClassConstructor.prototype.encodingDefaultBinary = expandedNodeId;
ClassConstructor.prototype.constructor.name = name;
ClassConstructor.prototype._schema = schema;

if (name in factories) {
throw new Error(" Class " + name + " already in factories");
}
factories[name] = ClassConstructor;

if (expandedNodeId.value != 0) {
if (expandedNodeId.value in constructorMap) {
throw new Error(" Class " + name + " with ID " + expandedNodeId.value + " already in constructorMap");
}
}
assert(!(expandedNodeId.value in constructorMap)," Class " + name + " with ID " + expandedNodeId.value + " already in constructorMap");
constructorMap[expandedNodeId.value] = ClassConstructor;
return ClassConstructor;
}
exports.registerObject = registerObject;

var getConstructor = function (expandedId) {
if (!expandedId || !(expandedId.value in constructorMap)) {
return null;
}
assert (expandedId && (expandedId.value in constructorMap));
return constructorMap[expandedId.value];
};

exports.getConstructor = getConstructor;

exports.constructObject = function (expandedId) {
if (!expandedId || !(expandedId.value in constructorMap)) {
throw new Error("constructObject: cannot find constructor for " + expandedId);
}
return new constructorMap[expandedId.value]();
var constructor = getConstructor(expandedId);
return new constructor();
};

exports.registerObject = registerObject;

var _next_available_id = 0xFFFE0000;
exports.next_available_id = function(){
Expand Down
28 changes: 16 additions & 12 deletions lib/variant.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,24 @@ var ExtensionObject = s.ExtensionObject;
var DiagnosticInfo = s.DiagnosticInfo;


function _self_encode(value,stream) {
return value.encode(stream);
function _self_encode(Type) {
return function(value,stream) {
if (!value.encode) {
value = new Type(value);
}
value.encode(stream);
}
}
function _self_decode(Type) {

return function(stream) {
var value = new Type();
return value.decode(stream);
value.decode(stream);
return value;
}
}




factories.registerObject({name:"DateTime" ,subtype:"UtcTime"});

var _encoder_map = {
Expand All @@ -90,15 +94,15 @@ var _encoder_map = {
Guid: { encoder : ec.encodeGUID, decoder: ec.decodeGUID },
ByteString: { encoder : ec.encodeByteString,decoder: ec.decodeByteString},
XmlElement: { encoder : ec.encodeXmlElement,decoder: ec.decodeXmlElement},
NodeId: { encoder : ec.encodeNodeId, decoder: ec.decodeNodeId },
NodeId: { encoder : ec.encodeNodeId, decoder: ec.decodeNodeId },
ExpandedNodeId: { encoder : ec.encodeExpandedNodeId, decoder: ec.encodeExpandedNodeId },
StatusCode: { encoder : ec.encodeUInt32, decoder: ec.decodeUInt32 },
QualifiedName: { encoder : _self_encode, decoder: _self_decode(QualifiedName) },
LocalizedText: { encoder : _self_encode, decoder: _self_decode(LocalizedText) },
ExtensionObject: { encoder : _self_encode, decoder: _self_decode(ExtensionObject) },
DataValue: { encoder : _self_encode, decoder: _self_decode(DataValue) },
Variant: { encoder : _self_encode, decoder: _self_decode(Variant) },
DiagnosticInfo: { encoder : _self_encode, decoder: _self_decode(DiagnosticInfo) }
QualifiedName: { encoder : _self_encode(QualifiedName), decoder: _self_decode(QualifiedName) },
LocalizedText: { encoder : _self_encode(LocalizedText), decoder: _self_decode(LocalizedText) },
ExtensionObject: { encoder : _self_encode(ExtensionObject), decoder: _self_decode(ExtensionObject) },
DataValue: { encoder : _self_encode(DataValue), decoder: _self_decode(DataValue) },
Variant: { encoder : _self_encode(Variant) , decoder: _self_decode(Variant) },
DiagnosticInfo: { encoder : _self_encode(DiagnosticInfo), decoder: _self_decode(DiagnosticInfo) }
};


Expand Down
1 change: 1 addition & 0 deletions test/test_factories.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ describe("Factories: testing encodingDefaultBinary and constructObject",function


var MetaShape_Description = {
name: "metashape",
id: factories.next_available_id(),
fields: [
{ name: "name", fieldType: "String" },
Expand Down
15 changes: 15 additions & 0 deletions test/test_variant.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var VariantArrayType = require("../lib/variant").VariantArrayType;

var should = require("should");
var encode_decode_round_trip_test = require("./utils/encode_decode_round_trip_test").encode_decode_round_trip_test;
var s = require("./../lib/structures");


describe("Variant",function(){
Expand Down Expand Up @@ -32,6 +33,20 @@ describe("Variant",function(){
});
});

it("should create a Scalar LocalizedText Variant",function(){
var var1 = new Variant({
dataType: DataType.LocalizedText,
value: new s.LocalizedText({ text: "Hello" , locale: "en" })
});

var1.dataType.should.eql(DataType.LocalizedText);
var1.arrayType.should.eql(VariantArrayType.Scalar);

encode_decode_round_trip_test(var1,function(stream){
stream.length.should.equal(17);
});
});

it("should create a Scalar String Variant",function(){
var var1 = new Variant({dataType: DataType.String, value: "Hello" });

Expand Down

0 comments on commit c070503

Please sign in to comment.