Skip to content

Commit

Permalink
Fix bugs found parsing all of Redfish in one shot
Browse files Browse the repository at this point in the history
  • Loading branch information
pboyd04 committed Nov 17, 2016
1 parent eaaa9a3 commit 28c158d
Show file tree
Hide file tree
Showing 19 changed files with 322 additions and 172 deletions.
11 changes: 9 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var Metadata = process.env.CSDL_COV ? require('./lib-cov/Metadata') : require('./lib/Metadata');
var Reference = process.env.CSDL_COV ? require('./lib-cov/Reference') : require('./lib/Reference');
var CSDLCache = process.env.CSDL_COV ? require('./lib-cov/cache/csdlCache') : require('./lib/cache/csdlCache');
var CSDLSearch = process.env.CSDL_COV ? require('./lib-cov/CSDLSearch') : require('./lib/CSDLSearch');

//constants
module.exports.version = require('./package.json').version;
Expand All @@ -14,4 +15,10 @@ module.exports.parseMetadataFile = Metadata.parseMetadataFile;
module.exports.parseMetadataUri = Metadata.parseMetadataUri;

/// Allow the caller access to the cache
module.exports.cache = Reference.cache;
module.exports.cache = CSDLCache;

/// Search a metadata for entity type and names
module.exports.search = CSDLSearch.search;

/// Search a metadata for entity type and names
module.exports.findByType = CSDLSearch.findByType;
6 changes: 6 additions & 0 deletions lib/Action.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const ReturnType = require('./ReturnType');

function Action(xml) {
this.Name = xml.attr('Name').value();
this.Annotations = {};
this.Parameters = {};
this.ReturnType = null;

Expand All @@ -19,6 +20,11 @@ function Action(xml) {
Action.prototype.parseElement = function(element) {
var elemName = element.name();
switch(elemName) {
case 'Annotation':
var name = element.attr('Term').value();
var Annotation = require('./Annotation');
this.Annotations[name] = new Annotation(element);
break;
case 'Parameter':
var name = element.attr('Name').value();
this.Parameters[name] = new Parameter(element);
Expand Down
7 changes: 7 additions & 0 deletions lib/Annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ Annotation.prototype.parseElement = function(element) {
case 'String':
this.String = element.text();
break;
case 'Record':
var Record = require('./Record');
this.Record = new Record(element);
break;
default:
throw new Error('Unknown element name '+elemName);
break;
Expand All @@ -34,6 +38,9 @@ Annotation.prototype.parseAttribute = function(attribute) {
case 'Term':
//Already used... drop on floor
break;
case 'Int':
this[attrName] = attribute.value()*1;
break;
case 'Bool':
ParserCommon.parseBooleanAttribute(this, attribute, attrName);
break;
Expand Down
110 changes: 110 additions & 0 deletions lib/CSDLSearch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@

function searchAnnotation(collection, elementName) {
var ret = [];
if(elementName === undefined) {
for(var name in collection) {
ret.push(collection[name]);
}
}
else {
if(collection[elementName] !== undefined) {
ret.push(collection[elementName]);
}
}
return ret;
}

function getElementIfNameEqual(element, elementName) {
if(elementName === undefined) {
return element;
}
if(elementName === element.Name) {
return element;
}
return undefined;
}

function searchCSDL(root, elementType, elementName, includeReferences) {
var ret = [];
for(var key in root) {
if(key[0] === '_') {
continue;
}
else if(key === 'Annotations') {
if(elementType === 'Annotation') {
ret = ret.concat(searchAnnotation(root.Annotations, elementName));
}
continue;
}
else if(key === 'References' && includeReferences !== true) {
continue;
}
var element = root[key];
if(element === undefined || element === null) {
continue;
}
if(typeof element !== 'object') {
continue;
}
if(elementType !== undefined) {
if(elementType === element.constructor.name) {
var tmp = getElementIfNameEqual(element, elementName);
if(tmp !== undefined) {
ret.push(tmp);
}
}
else {
var tmp = searchCSDL(element, elementType, elementName);
if(tmp.length > 0) {
ret = ret.concat(tmp);
}
}
}
else {
var tmp = getElementIfNameEqual(element, elementName);
if(tmp !== undefined) {
ret.push(tmp);
}
}
}
return ret;
}

function remapNamespace(references, namespace) {
for(var i = 0; i < references.length; i++) {
if(references[i].Includes[namespace] !== undefined) {
return references[i].Includes[namespace];
}
}
return undefined;
}

function findByType(metadata, typeName) {
if(typeName.startsWith('Edm')) {
return typeName;
}
var index = typeName.lastIndexOf('.');
if(index === -1) {
return null;
}
var namespace = typeName.substring(0, index);
var justType = typeName.substring(index+1);
var schema = metadata[namespace];
if(schema === undefined) {
schema = metadata._options.cache.getSchema(namespace);
if(schema === undefined) {
namespace = remapNamespace(metadata.References, namespace);
if(namespace !== undefined) {
schema = metadata._options.cache.getSchema(namespace);
}
else {
return null;
}
}
}
return schema[justType];
}

module.exports.search = searchCSDL;
module.exports.findByType = findByType;
/* vim: set tabstop=2 shiftwidth=2 expandtab: */
1 change: 1 addition & 0 deletions lib/ComplexType.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ ComplexType.prototype.parseAttribute = function(attribute) {
this.BaseType = attribute.value();
break;
case 'Abstract':
case 'OpenType':
ParserCommon.parseBooleanAttribute(this, attribute, attrName);
break;
default:
Expand Down
3 changes: 3 additions & 0 deletions lib/EntityContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ EntityContainer.prototype.parseAttribute = function(attribute) {
case 'Name':
//Already used... drop on floor
break;
case 'Extends':
this[attrName] = attribute.value();
break;
default:
throw new Error('Unknown attribute name '+attrName+' in EntityContainer '+this.Name);
break;
Expand Down
34 changes: 11 additions & 23 deletions lib/EnumType.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,24 @@ const ParserCommon = require('./ParserCommon');
function EnumType(xml) {
this._index = 0;
this.Members = {};
var name = xml.attr('Name').value();
var children = xml.childNodes();
for(var i = 0; i < children.length; i++)
{
var elemType = children[i].type();
if(elemType === 'element') {
this.parseElement(children[i], name);
}
else if(elemType === 'text') {
var text = children[i].toString().trim();
if(text.length !== 0) {
throw new Error('Unknown text element in EnumType! Text = "'+text+'"');
}
}
else {
throw new Error('Unknown element type '+elemType+' in EnumType '+name+'!');
}
}
var attributes = xml.attrs();
for(var i = 0; i < attributes.length; i++)
{
this.parseAttribute(attributes[i], name);
}
this.Annotations = {};
this.Name = xml.attr('Name').value();

var parseElement = this.parseElement.bind(this);
var parseAttribute = this.parseAttribute.bind(this);
ParserCommon.parseEntity(xml, 'EnumType', parseElement, parseAttribute);
delete this._index;
return this;
}

EnumType.prototype.parseElement = function(element, entityName) {
var elemName = element.name();
switch(elemName) {
case 'Annotation':
var name = element.attr('Term').value();
var Annotation = require('./Annotation');
this.Annotations[name] = new Annotation(element);
break;
case 'Member':
var name = element.attr('Name').value();
var value = element.attr('Value');
Expand Down
45 changes: 9 additions & 36 deletions lib/Metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,51 +66,21 @@ Metadata.prototype.resolve = function(callback) {
Metadata.prototype.resolvePromise = function() {
var self = this;
if(this.References === undefined || this.References.length === 0) {
delete this.References;
delete this.context;
delete this._options;
return new Promise(function(resolve, reject) {
resolve(self);
});
}
else {
var refs = [];
for(var i = 0; i < this.References.length; i++) {
refs.push(this.References[i].MetaPromise);
}
else {
return new Promise(function(resolve, reject) {
Promise.all(refs).then(function(values) {
var childPromises = [];
for(var i = 0; i < values.length; i++) {
if(values[i] === undefined) {
continue;
}
//console.log(values);
childPromises.push(values[i].resolvePromise());
}
if(childPromises.length === 0) {
resolve(self);
self._options.cache.waitForCoherent(function(error) {
if(error) {
reject(error);
}
else {
Promise.all(childPromises).then(function(childValues) {
for(var i = 0; i < childValues.length; i++) {
var value = childValues[i];
if(value === undefined) {
continue;
}
delete value.References;
delete value.context;
delete value._options;
self = Object.assign(value, self);
delete self.References;
delete self.context;
delete self._options;
resolve(self);
}
});
resolve(self);
}
});

});
}
}
Expand All @@ -120,7 +90,8 @@ Metadata.prototype.parseElement = function(element) {
switch(elemName) {
case 'Reference':
var Reference = require('./Reference');
this.References.push(new Reference(element, this._options.cache));
var errorCallback = this.done.bind(this);
this.References.push(new Reference(element, this._options.cache, errorCallback));
break;
case 'DataServices':
this.parseDataServices(element);
Expand Down Expand Up @@ -155,6 +126,8 @@ Metadata.prototype.parseDataServiceElement = function(element) {
}
}

module.exports.construct = Metadata;

module.exports.parseMetadata = function(string, options, callback) {
try {
var meta = new Metadata(options);
Expand Down
1 change: 1 addition & 0 deletions lib/NavigationProperty.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ NavigationProperty.prototype.parseAttribute = function(attribute, entityName) {
this.Type = attribute.value();
break;
case 'Nullable':
case 'ContainsTarget':
ParserCommon.parseBooleanAttribute(this, attribute, attrName);
break;
default:
Expand Down
38 changes: 15 additions & 23 deletions lib/Parameter.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,30 @@
const ParserCommon = require('./ParserCommon');

function Parameter(xml) {
var name = xml.attr('Name').value();
var children = xml.childNodes();
for(var i = 0; i < children.length; i++)
{
var elemType = children[i].type();
if(elemType === 'element')
{
this.parseElement(children[i], name);
}
else
{
throw new Error('Unknown element type in Parameter '+name+'!');
}
}
var attributes = xml.attrs();
for(var i = 0; i < attributes.length; i++)
{
this.parseAttribute(attributes[i], name);
}
this.Name = xml.attr('Name').value();
this.Annotations = {};

var parseElement = this.parseElement.bind(this);
var parseAttribute = this.parseAttribute.bind(this);
ParserCommon.parseEntity(xml, 'Action', parseElement, parseAttribute);
return this;
}

Parameter.prototype.parseElement = function(element, actionName) {
Parameter.prototype.parseElement = function(element) {
var elemName = element.name();
switch(elemName) {
case 'Annotation':
var name = element.attr('Term').value();
var Annotation = require('./Annotation');
this.Annotations[name] = new Annotation(element);
break;
default:
throw new Error('Unknown element name '+elemName);
throw new Error('Unknown element name '+elemName+' in Parameter '+this.Name);
break;
}
}

Parameter.prototype.parseAttribute = function(attribute, actionName) {
Parameter.prototype.parseAttribute = function(attribute) {
var attrName = attribute.name();
switch(attrName) {
case 'Name':
Expand All @@ -46,7 +38,7 @@ Parameter.prototype.parseAttribute = function(attribute, actionName) {
ParserCommon.parseBooleanAttribute(this, attribute, attrName);
break;
default:
throw new Error('Unknown attribute name '+attrName+' in Parameter '+actionName);
throw new Error('Unknown attribute name '+attrName+' in Parameter '+this.Name);
break;
}
}
Expand Down
Loading

0 comments on commit 28c158d

Please sign in to comment.