381 lines
13 KiB
JavaScript

/*
Copyright (c) 2014, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
"use strict";
var udebug = unified_debug.getLogger("composition/lib.js");
var util = require("util");
function Customer(id, first, last) {
if (typeof id !== 'undefined') {
this.id = id;
this.firstName = first;
this.lastName = last;
}
}
function ShoppingCart(id, customerid) {
if (typeof id !== 'undefined') {
this.id = id;
this.customerid = customerid;
}
}
function LineItem(line, shoppingcartid, quantity, itemid) {
if (typeof line !== 'undefined') {
this.line = line;
this.shoppingcartid = shoppingcartid;
this.quantity = quantity;
this.itemid = itemid;
}
}
function Item(id, description) {
if (typeof id !== 'undefined') {
this.id = id;
this.description = description;
}
}
function Discount(id, description, percent) {
if (typeof id !== 'undefined') {
this.id = id;
this.description = description;
this.percent = percent;
}
}
function mapCustomer() {
// map customer
var customerMapping = new mynode.TableMapping('customer');
customerMapping.mapField('id');
customerMapping.mapField('firstName', 'firstname');
customerMapping.mapField('lastName', 'lastname');
customerMapping.mapOneToOne( {
fieldName: 'shoppingCart',
target: ShoppingCart,
targetField: 'customer'
} );
customerMapping.mapManyToMany( {
fieldName: 'discounts',
target: Discount,
targetField: 'customers'
} );
customerMapping.applyToClass(Customer);
}
function mapShoppingCart() {
// map shopping cart
var shoppingCartMapping = new mynode.TableMapping('shoppingcart');
shoppingCartMapping.mapField('id');
shoppingCartMapping.mapOneToOne( {
fieldName: 'customer',
foreignKey: 'fkcustomerid',
target: Customer
} );
shoppingCartMapping.mapOneToMany( {
fieldName: 'lineItems',
targetField: 'shoppingCart',
target: LineItem
} );
shoppingCartMapping.applyToClass(ShoppingCart);
}
function mapLineItem() {
// map line item
var lineItemMapping = new mynode.TableMapping('lineitem');
lineItemMapping.mapField('line');
lineItemMapping.mapField('quantity');
lineItemMapping.mapField('shoppingcartid');
lineItemMapping.mapField('itemid');
lineItemMapping.mapManyToOne( {
fieldName: 'shoppingCart',
foreignKey: 'fkshoppingcartid',
target: ShoppingCart
});
lineItemMapping.mapManyToOne( {
fieldName: 'item',
foreignKey: 'fkitemid',
target: Item
});
lineItemMapping.applyToClass(LineItem);
}
function mapItem() {
var itemMapping = new mynode.TableMapping('item');
itemMapping.mapField('id');
itemMapping.mapField('description');
itemMapping.mapOneToMany( {
fieldName: 'lineItems',
target: LineItem,
targetField: 'item'
} );
itemMapping.applyToClass(Item);
}
function mapDiscount() {
var discountMapping = new mynode.TableMapping('discount');
discountMapping.mapField('id');
discountMapping.mapField('description');
discountMapping.mapField('percent');
discountMapping.mapManyToMany( {
fieldName: 'customers',
target: Customer,
joinTable: 'customerdiscount',
} );
discountMapping.applyToClass(Discount);
}
function CustomerDiscount(customerid, discountid) {
if (typeof customerid !== 'undefined') {
this.customerid = customerid;
this.discountid = discountid;
}
}
function mapCustomerDiscount() {
var customerDiscountMapping = new mynode.TableMapping('customerdiscount');
customerDiscountMapping.mapField('customerid');
customerDiscountMapping.mapField('discountid');
customerDiscountMapping.applyToClass(CustomerDiscount);
}
function FkDifferentDb(id) {
if (typeof id !== 'undefined') {
this.id = id;
}
}
function mapFkDifferentDb() {
var fkDifferentDbMapping = new mynode.TableMapping('testfk.fkdifferentdb');
fkDifferentDbMapping.mapField('id');
fkDifferentDbMapping.applyToClass(FkDifferentDb);
}
function verifyFK(testCase, tableMetadata, fks) {
function verify(name, expected, actual) {
var expectedValue = expected[name];
var actualValue = actual[name];
if (typeof actualValue === 'undefined') {
testCase.appendErrorMessage('\nExpected ' + name + ' was undefined');
return;
}
switch(typeof expectedValue) {
case 'string':
if (expectedValue !== actualValue) {
testCase.appendErrorMessage('\nMismatch on ' + name + '; expected: ' + expectedValue + '; actual: ' + actualValue);
}
break;
case 'object':
if (!Array.isArray(actualValue)) {
testCase.appendErrorMessage('\nUnexpected not an array: ' + util.inspect(actualValue));
} else {
expectedValue.forEach(function(element) {
if (actualValue.indexOf(element) == -1) {
testCase.appendErrorMessage('\nExpected element missing from ' + name + ': ' + element + ' in ' + util.inspect(actualValue));
}
});
}
break;
}
}
if (!tableMetadata.foreignKeys) {
testCase.appendErrorMessage('\nMetadata for ' + tableMetadata.name + ' did not include foreignKeys.');
} else {
fks.forEach(function(fkexpected) {
var found = false;
tableMetadata.foreignKeys.forEach(function(fkactual) {
if (fkexpected.name === fkactual.name) {
found = true;
verify('targetTable', fkexpected, fkactual);
verify('targetDatabase', fkexpected, fkactual);
verify('columnNames', fkexpected, fkactual);
verify('targetColumnNames', fkexpected, fkactual);
}
});
if (!found) {
testCase.appendErrorMessage('\nNo foreign key ' + fkexpected.name + ' in table metadata for ' + tableMetadata.name);
}
});
}
}
function mapShop() {
mapCustomer();
mapShoppingCart();
mapLineItem();
mapItem();
mapDiscount();
mapCustomerDiscount();
}
var shopDomainObjects = [Customer, ShoppingCart, LineItem, Item, Discount, CustomerDiscount];
function createLineItem(line, quantity, itemid) {
var result = new LineItem();
result.line = line;
result.quantity = quantity;
result.itemid = itemid;
return result;
}
function sortFunction(a, b) {
// sort based on id if it exists, or on line if it exists or throw an exception
if (typeof(a.id) !== 'undefined' && typeof(b.id) !== 'undefined') {
return a.id - b.id;
}
if (typeof(a.line) !== 'undefined' && typeof(b.line) !== 'undefined') {
return a.line - b.line;
}
throw new Error('Error: can only sort objects containing properties id or line.');
}
function verifyProjection(tc, p, e, a) {
var testCase = tc;
var projectionVerifications;
var projectionVerification;
var i;
function verifyOneProjection() {
udebug.log_detail('verifyOneProjection with', projectionVerifications.length, 'waiting:\n', projectionVerifications[0]);
while (projectionVerifications.length > 0) {
projectionVerification = projectionVerifications.shift();
var projection = projectionVerification[0];
var expected = projectionVerification[1];
var actual = projectionVerification[2];
var domainObjectName = projection.domainObject.prototype.constructor.name;
var expectedField;
var actualField;
var expectedRelationship;
var actualRelationship;
// check that the actual object exists and is unexpected
if ((expected !== null && actual === null) ||
(typeof expected !== 'undefined' && typeof actual === 'undefined')) {
testCase.appendErrorMessage('\n' + testCase.name +
' VerifyProjection failure for ' + domainObjectName +
'\nexpected: ' + util.inspect(expected) + '\nactual: ' + actual);
continue;
}
// check for null and undefined
if ((typeof expected === 'undefined' && typeof actual === 'undefined') ||
(expected === null && actual === null)) {
continue;
}
// verify the fields first
projection.fields.forEach(function(fieldName) {
expectedField = expected[fieldName];
actualField = actual[fieldName];
if (expectedField != actualField) {
testCase.appendErrorMessage('\n' + testCase.name +
' VerifyProjection failure for ' + domainObjectName + ' field ' + fieldName +
'\nexpected: ' + expectedField + '\nactual: ' + actualField);
}
});
// now verify the relationships (iteratively)
if (projection.relationships) {
Object.keys(projection.relationships).forEach(function(relationshipName) {
expectedRelationship = expected[relationshipName];
actualRelationship = actual[relationshipName];
if (Array.isArray(expectedRelationship)) {
if (Array.isArray(actualRelationship)) {
// we need to sort the actual array
// TODO let the user provide a sort function
actualRelationship.sort(sortFunction);
if (expectedRelationship.length === actualRelationship.length) {
// check each value in turn
for (i = 0; i < expectedRelationship.length; ++i) {
projectionVerifications.push([projection.relationships[relationshipName],
expectedRelationship[i], actualRelationship[i]]);
}
} else {
testCase.appendErrorMessage('\n' + testCase.name +
' VerifyProjection failure for ' + domainObjectName +
' relationship ' + relationshipName +
' expected relationship length: ' + expectedRelationship.length +
' actual relationship length: ' + actualRelationship.length);
}
} else {
testCase.appendErrorMessage('\n' + testCase.name +
' VerifyProjection failure for ' + domainObjectName +
' relationship ' + relationshipName +
' actual relationship is not an array: ' + actualRelationship);
}
} else {
// expected value is an object
if ((typeof expectedRelationship === 'undefined' && typeof actualRelationship !== 'undefined') ||
(expectedRelationship === null && actualRelationship !== null) ||
(typeof expectedRelationship !== 'undefined' & typeof actualRelationship === 'undefined') ||
(expectedRelationship !== null && actualRelationship === null)) {
// error
testCase.appendErrorMessage('\n' + testCase.name +
' VerifyProjection failure for ' + domainObjectName +
' relationship ' + relationshipName +
'\nexpected relationship: ' + util.inspect(expectedRelationship) +
'\nactual relationship: ' + util.inspect(actualRelationship));
} else {
if (!((typeof expectedRelationship === 'undefined' && typeof actualRelationship === 'undefined') ||
(expectedRelationship === null && actualRelationship === null))) {
// we need to check the values
projectionVerifications.push([projection.relationships[relationshipName],
expectedRelationship, actualRelationship]);
}
}
}
});
}
verifyOneProjection();
}
}
// verifyProjection starts here
projectionVerifications = [[p, e, a]];
verifyOneProjection();
}
exports.Customer = Customer;
exports.mapCustomer = mapCustomer;
exports.ShoppingCart = ShoppingCart;
exports.mapShoppingCart = mapShoppingCart;
exports.LineItem = LineItem;
exports.mapLineItem = mapLineItem;
exports.Item = Item;
exports.mapItem = mapItem;
exports.Discount = Discount;
exports.mapDiscount = mapDiscount;
exports.CustomerDiscount = CustomerDiscount;
exports.mapCustomerDiscount = mapCustomerDiscount;
exports.FkDifferentDb = FkDifferentDb;
exports.mapFkDifferentDb = mapFkDifferentDb;
exports.mapShop = mapShop;
exports.verifyFK = verifyFK;
exports.verifyProjection = verifyProjection;
exports.shopDomainObjects = shopDomainObjects;
exports.createLineItem = createLineItem;