Skip to content

Commit

Permalink
chore(*): remove Ergo References from Concerto (#610) (#637)
Browse files Browse the repository at this point in the history
Signed-off-by: Jamie Shorten <[email protected]>
  • Loading branch information
jamieshorten authored Apr 24, 2023
1 parent c8f7ae6 commit 892a423
Show file tree
Hide file tree
Showing 10 changed files with 19 additions and 489 deletions.
8 changes: 1 addition & 7 deletions packages/concerto-cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,6 @@ require('yargs')
type: 'boolean',
default: false
});
yargs.option('ergo', {
describe: 'validation and emit for Ergo',
type: 'boolean',
default: false
});
}, (argv) => {
if (argv.verbose) {
Logger.info(`validate ${argv.input} against the models ${argv.model}`);
Expand All @@ -67,8 +62,7 @@ require('yargs')
if (argv.utcOffset !== undefined) {
options.utcOffset = argv.utcOffset;
}
options.functional = !argv.ergo && argv.functional; // XXX Ergo option takes priority
options.ergo = argv.ergo;
options.functional = argv.functional;
return Commands.validate(argv.input, argv.model, options)
.then((result) => {
Logger.info('Input is valid');
Expand Down
10 changes: 2 additions & 8 deletions packages/concerto-core/lib/serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ const ResourceValidator = require('./serializer/resourcevalidator');
const { utcOffset: defaultUtcOffset } = DateTimeUtil.setCurrentTime();
const baseDefaultOptions = {
validate: true,
ergo: false,
utcOffset: defaultUtcOffset,
};

Expand Down Expand Up @@ -122,7 +121,7 @@ class Serializer {
options.permitResourcesForRelationships === true,
options.deduplicateResources === true,
options.convertResourcesToId === true,
options.ergo === true,
false,
options.utcOffset,
);

Expand Down Expand Up @@ -154,11 +153,6 @@ class Serializer {
// set default options
options = options ? Object.assign({}, this.defaultOptions, options) : this.defaultOptions;

if (options && options.ergo === true) {
const theClass = jsonObject.$class.$coll[0];
jsonObject = jsonObject.$data;
jsonObject.$class = theClass;
}
if(!jsonObject.$class) {
throw new Error('Invalid JSON data. Does not contain a $class type identifier.');
}
Expand Down Expand Up @@ -194,7 +188,7 @@ class Serializer {
parameters.resourceStack = new TypedStack(resource);
parameters.modelManager = this.modelManager;
parameters.factory = this.factory;
const populator = new JSONPopulator(options.acceptResourcesForRelationships === true, options.ergo === true, options.utcOffset, options.strictQualifiedDateTimes === true);
const populator = new JSONPopulator(options.acceptResourcesForRelationships === true, false, options.utcOffset, options.strictQualifiedDateTimes === true);
classDeclaration.accept(populator, parameters);

// validate the resource against the model
Expand Down
77 changes: 8 additions & 69 deletions packages/concerto-core/lib/serializer/jsongenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,15 @@ class JSONGenerator {
* in the object graph only the first instance is serialized, with only the $id
* written for subsequent instances, false by default.
* @param {boolean} [convertResourcesToId] Convert resources that
* @param {boolean} [ergo] - Deprecated - This is a dummy parameter to avoid breaking any consumers. It will be removed in a future release.
* are specified for relationship fields into their id, false by default.
* @param {boolean} [ergo] target ergo.
* @param {number} [utcOffset] UTC Offset for DateTime values.
*/
constructor(convertResourcesToRelationships, permitResourcesForRelationships, deduplicateResources, convertResourcesToId, ergo, utcOffset) {
this.convertResourcesToRelationships = convertResourcesToRelationships;
this.permitResourcesForRelationships = permitResourcesForRelationships;
this.deduplicateResources = deduplicateResources;
this.convertResourcesToId = convertResourcesToId;
this.ergo = ergo;
this.utcOffset = utcOffset || 0;
}

Expand Down Expand Up @@ -115,22 +114,9 @@ class JSONGenerator {
if (!Util.isNull(value)) {
parameters.stack.push(value);
result[property.getName()] = property.accept(this, parameters);
} else if (this.ergo) {
result[property.getName()] = { '$right' : null };
}
}

if (this.ergo) {
const theClass = result.$class;
delete result.$class;
result = {
$class: {
$coll: [theClass],
$length: 1
},
$data: result,
};
}
return result;
}

Expand All @@ -157,49 +143,17 @@ class JSONGenerator {
array.push(this.convertToJSON(field, item));
}
}
if (this.ergo) {
result = {
$coll: array,
$length: array.length
};
} else {
result = array;
}
result = array;
} else if (field.isPrimitive()) {
result = this.convertToJSON(field, obj);
} else if (ModelUtil.isEnum(field)) {
if (this.ergo) {
// Boxes an enum value to the expected combination of sum types
const enumDeclaration = field.getParent().getModelFile().getType(field.getType());
const enumName = enumDeclaration.getFullyQualifiedName();
const properties = enumDeclaration.getProperties();
let either = { '$left' : obj };
for(let n=0; n < properties.length; n++) {
const property = properties[n];
if(property.getName() === obj) {
break;
} else {
either = { '$right' : either };
}
}
result = { '$class' : [enumName], '$data': either };
} else {
result = this.convertToJSON(field, obj);
}
result = this.convertToJSON(field, obj);
} else {
parameters.stack.push(obj);
const classDeclaration = parameters.modelManager.getType(obj.getFullyQualifiedType());
result = classDeclaration.accept(this, parameters);
}
if (field.isOptional()) {
if (this.ergo) {
if (result) {
result = { '$left' : result };
} else {
result = { '$right' : result };
}
}
}

return result;
}

Expand All @@ -215,20 +169,12 @@ class JSONGenerator {
case 'DateTime':
{
const objWithOffset = obj.utc().utcOffset(this.utcOffset);
if (this.ergo) {
return objWithOffset;
} else {
const inZ = objWithOffset.utcOffset() === 0;
return objWithOffset.format(`YYYY-MM-DDTHH:mm:ss.SSS${inZ ? '[Z]': 'Z'}`);
}
const inZ = objWithOffset.utcOffset() === 0;
return objWithOffset.format(`YYYY-MM-DDTHH:mm:ss.SSS${inZ ? '[Z]': 'Z'}`);
}
case 'Integer':
case 'Long': {
if (this.ergo) {
return { $nat: obj };
} else {
return obj;
}
return obj;
}
case 'Double':
case 'Boolean':
Expand Down Expand Up @@ -272,14 +218,7 @@ class JSONGenerator {
array.push(relationshipText);
}
}
if (this.ergo) {
result = {
$coll: array,
$length: array.length
};
} else {
result = array;
}
result = array;
} else if (this.permitResourcesForRelationships && obj instanceof Resource) {
let fqi = obj.getFullyQualifiedIdentifier();
if (parameters.seenResources.has(fqi)) {
Expand Down
44 changes: 4 additions & 40 deletions packages/concerto-core/lib/serializer/jsonpopulator.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,13 @@ class JSONPopulator {
* Constructor.
* @param {boolean} [acceptResourcesForRelationships] Permit resources in the
* place of relationships, false by default.
* @param {boolean} [ergo] target ergo.
* @param {boolean} [ergo] - Deprecated - This is a dummy parameter to avoid breaking any consumers. It will be removed in a future release.
* @param {number} [utcOffset] - UTC Offset for DateTime values.
* @param {number} [strictQualifiedDateTimes] - Only allow fully-qualified date-times with offsets.
*/
constructor(acceptResourcesForRelationships, ergo, utcOffset, strictQualifiedDateTimes) {
this.acceptResourcesForRelationships = acceptResourcesForRelationships;
this.ergo = ergo;
this.utcOffset = utcOffset || 0; // Defaults to UTC
this.strictQualifiedDateTimes = strictQualifiedDateTimes;

Expand Down Expand Up @@ -149,13 +149,6 @@ class JSONPopulator {

properties.forEach((property) => {
let value = jsonObj[property];
if (this.ergo) { // XXX Unpack optionals
if (Object.prototype.hasOwnProperty.call(value,'$left')) {
value = value.$left;
} else if (Object.prototype.hasOwnProperty.call(value,'$right')) {
value = value.$right;
}
}
if (value !== null) {
parameters.path.push(`.${property}`);
parameters.jsonStack.push(value);
Expand All @@ -180,11 +173,6 @@ class JSONPopulator {
let result = null;

if(field.isArray()) {
if (this.ergo) {
if (Object.prototype.hasOwnProperty.call(jsonObj,'$coll')) {
jsonObj = jsonObj.$coll.slice(0,jsonObj.$length);
}
}
result = [];
for(let n=0; n < jsonObj.length; n++) {
parameters.path.push(`[${n}]`);
Expand All @@ -210,11 +198,6 @@ class JSONPopulator {
let result = null;

if(!field.isPrimitive() && !field.isTypeEnum()) {
if (this.ergo) {
const theClass = jsonItem.$class.$coll[0];
jsonItem = jsonItem.$data;
jsonItem.$class = theClass ;
}
let typeName = jsonItem.$class;
if(!typeName) {
// If the type name is not specified in the data, then use the
Expand Down Expand Up @@ -287,7 +270,7 @@ class JSONPopulator {
break;
case 'Integer':
case 'Long': {
const num = this.ergo ? json.$nat : json;
const num = json;
if (typeof num === 'number') {
if (Math.trunc(num) !== num) {
throw new ValidationException(`Expected value at path \`${path}\` to be of type \`${field.getType()}\``);
Expand Down Expand Up @@ -324,16 +307,7 @@ class JSONPopulator {
break;
default: {
// everything else should be an enumerated value...
if (this.ergo) {
// unpack the enum
let current = json.$data;
while (!current.$left) {
current = current.$right;
}
result = current.$left;
} else {
result = json;
}
result = json;
}
}
return result;
Expand Down Expand Up @@ -374,11 +348,6 @@ class JSONPopulator {
throw new Error('Invalid JSON data. Does not contain a $class type identifier: ' + jsonItem + ' for relationship ' + relationshipDeclaration );
}

if (this.ergo) {
const theClass = jsonItem.$class.$coll[0];
jsonItem = jsonItem.$data;
jsonItem.$class = theClass;
}
const classDeclaration = parameters.modelManager.getType(jsonItem.$class);

// create a new instance, using the identifier field name as the ID.
Expand All @@ -403,11 +372,6 @@ class JSONPopulator {
if(!jsonObj.$class) {
throw new Error('Invalid JSON data. Does not contain a $class type identifier: ' + jsonObj + ' for relationship ' + relationshipDeclaration );
}
if (this.ergo) {
const theClass = jsonObj.$class.$coll[0];
jsonObj = jsonObj.$data;
jsonObj.$class = theClass;
}
const classDeclaration = parameters.modelManager.getType(jsonObj.$class);

// create a new instance, using the identifier field name as the ID.
Expand Down
48 changes: 1 addition & 47 deletions packages/concerto-core/test/1.0.0/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,26 +54,6 @@ const validateFunctional = async (sample, ctoFiles, options) => {

return concerto.validate(json);
};
const validateToErgo = async (sample, ctoFiles, options) => {
const json = loadJson(sample);

const modelManager = await ModelLoader.loadModelManager(ctoFiles.map((file) => path.join(__dirname,file)), options);
const factory = new Factory(modelManager);
const serializer = new Serializer(factory, modelManager);

const object = serializer.fromJSON(json);
return serializer.toJSON(object, { ergo: true, utcOffset: 0 });
};
const validateFromErgo = async (sample, ctoFiles, options) => {
const json = loadJson(sample);

const modelManager = await ModelLoader.loadModelManager(ctoFiles.map((file) => path.join(__dirname,file)), options);
const factory = new Factory(modelManager);
const serializer = new Serializer(factory, modelManager);

const object = serializer.fromJSON(json, { ergo: true, utcOffset: 0 });
return serializer.toJSON(object);
};

const positive = [{
name: 'date',
Expand Down Expand Up @@ -110,18 +90,6 @@ const positive = [{
sample: './data/timestamp1.json',
ctoFiles: ['./models/timestamp1.cto'],
expected: './data/timestamp1.expect'
}, {
name: 'test1a',
sample: './data/test1a.json',
ctoFiles: ['./models/test1.cto'],
expected: './data/test1a.expect',
ergo: './data/test1a.ergo'
}, {
name: 'test1b',
sample: './data/test1b.json',
ctoFiles: ['./models/test1.cto'],
expected: './data/test1b.expect',
ergo: './data/test1b.ergo'
}];

const negative = [{
Expand Down Expand Up @@ -153,7 +121,7 @@ describe('Validation (1.0.0)', () => {

describe('#positive', () => {
positive
.forEach(({ name, sample, ctoFiles, expected, ergo }) => {
.forEach(({ name, sample, ctoFiles, expected }) => {
it(`should validate - classic (${name})`, async function() {
const resultActual = await validateClassic(sample, ctoFiles);
const resultExpected = loadJson(expected);
Expand All @@ -164,20 +132,6 @@ describe('Validation (1.0.0)', () => {
const resultActual = await validateFunctional(sample, ctoFiles);
(typeof resultActual === 'undefined').should.equal(true);
});

if (ergo) {
it(`should validate - to ergo (${name})`, async function() {
const resultActual = await validateToErgo(sample, ctoFiles);
const resultExpected = loadJson(ergo);
resultActual.should.deep.equal(resultExpected);
});

it(`should validate - from ergo (${name})`, async function() {
const resultActual = await validateFromErgo(ergo, ctoFiles);
const resultExpected = loadJson(expected);
resultActual.should.deep.equal(resultExpected);
});
}
});
});

Expand Down
Loading

0 comments on commit 892a423

Please sign in to comment.