database-jones/Adapter/api/Projection.js (88 lines of code) (raw):
/*
Copyright (c) 2014, 2015, 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 unified_debug = require("unified_debug"),
udebug = unified_debug.getLogger("Projection.js"),
path = require("path"),
jones = require("database-jones"),
doc = require(path.join(jones.fs.api_doc_dir, "Projection"));
function Projection(domainObject) {
if (typeof domainObject === 'function' && domainObject.prototype.jones && domainObject.prototype.jones.mapping) {
this.domainObject = domainObject;
this.name = domainObject.name + 'Projection';
this.validated = false; // this projection has not been validated or has changed since validation
this.id = 0; // initial value for projection id; when validated it will be 1
this.fields = [];
this.relationships = {};
this.usedBy = [];
this.fetchSparseFields = false;
this.error = '';
} else {
// there is nothing that we can do with a Projection with an invalid domain object
throw new Error(
'The parameter of Projection constructor must be a mapped domain object (constructor function). ' +
'@See TableMapping.applyToClass');
}
}
/** Invalidate this projection and all projections used by this projection.
* The function recursively adds projections used by this projection
* and invalidates them one by one. The parameter is modified by this function.
* @param toBeInvalidated an array of projections to be invalidated.
*/
function invalidateAll(toBeInvalidated) {
if (toBeInvalidated.length === 0) {return;}
var projection = toBeInvalidated.shift();
if (projection.error != '') {return;}
projection.validated = false;
projection.usedBy.forEach(function(used) {
toBeInvalidated.push(used);
});
invalidateAll(toBeInvalidated);
}
Projection.prototype.addSparseFields = function() {
this.fetchSparseFields = true;
return this;
};
Projection.prototype.addFields = function() {
var projection = this;
// if this projection is in error just return
if (projection.error != '') {return;}
var toBeInvalidated = [this];
invalidateAll(toBeInvalidated);
var i, j;
var argument;
var field;
// iterate the arguments of the function
for (i = 0; i < arguments.length; ++i) {
argument = arguments[i];
if (typeof argument === 'string') {
projection.fields.push(argument);
} else if (Array.isArray(argument)) {
for (j = 0; j < argument.length; ++j) {
field = argument[j];
if (typeof field === 'string') {
projection.fields.push(field);
} else {
projection.error += '\nError in addFields for ' + projection.domainObject.prototype.constructor.name +
' Field names must be strings or arrays of strings ' + field;
}
}
} else {
projection.error += '\nError in addFields for ' + projection.domainObject.prototype.constructor.name +
' Field names must be strings or arrays of strings ' + argument;
}
}
return this;
};
/** addField is an alias for addFields for usability */
Projection.prototype.addField = Projection.prototype.addFields;
Projection.prototype.addRelationship = function(fieldName, relationshipProjection) {
var projection = this;
// if this projection is in error just return
if (projection.error != '') {return;}
var toBeInvalidated = [this];
invalidateAll(toBeInvalidated);
if (typeof fieldName !== 'string') {
projection.error += '\nError in addRelationship for ' + projection.domainObject.prototype.constructor.name +
'fieldName must be a string ' + fieldName;
}
if (typeof relationshipProjection !== 'object' ||
relationshipProjection.constructor.name !== 'Projection') {
projection.error += '\nError in addRelationship for ' + projection.domainObject.prototype.constructor.name +
' parameter relationshipProjection must be a projection for field ' + fieldName;
}
if (projection.error == '') {
projection.relationships[fieldName] = relationshipProjection;
// establish the used-by relationship
relationshipProjection.usedBy.push(this);
}
return this;
};
/* Public exports of this module: */
exports.Projection = Projection;