rutile
Version:
Factory automation for Mobile Enterprise.
1,589 lines (1,355 loc) • 50.1 kB
JavaScript
console.log("start server generator");
var path = require('path');
var program_file = process.argv[1];
var LIB_PATH = path.resolve(program_file,"../../lib/node_modules/rutile/lib");
var WORKING_DIR = process.cwd();
console.log("program_file:"+program_file);
console.log("LIB_PATH:"+LIB_PATH);
var tools = require(path.resolve(LIB_PATH,'tools.js'));
var Generator = require(path.resolve(LIB_PATH,'Generator_server'));
// $ rutile generate server ./Config.js
var config_file = process.argv[4];
if( config_file.match(/^\./) ){
config_file = path.resolve(WORKING_DIR,config_file);
}else{
throw new Error("invalid config file: "+config_file);
}
var MyAppConfig = require(config_file);
var CONFIG_PATH = path.resolve(config_file,'..');
// * * * * * * * * * * * * * * * * * * * *
console.log("loading config...");
var APP_NAME = MyAppConfig.APP_NAME;
var SERVER_NAME = APP_NAME + "Server";
console.log("APP_NAME : "+APP_NAME);
console.log("SERVER_NAME : "+SERVER_NAME);
var Protocol = MyAppConfig.Protocol || 'websocket';
var AppHost = MyAppConfig.AppHost || '127.0.0.1';
var AppPort = MyAppConfig.AppPort || 3000;
var DBHost = MyAppConfig.DBHost || '127.0.0.1';
var DBPort = MyAppConfig.DBPort || 5432;
var DBUser = MyAppConfig.DBUser;
var DBPass = MyAppConfig.DBPass;
var CacheHost = MyAppConfig.CacheHost || '127.0.0.1';
var CachePort = MyAppConfig.CachePort || 6379;
var SelectAllLimit = MyAppConfig.SelectAllLimit || 1000; // default select all limit is 1000
console.log("Application select all limit:"+SelectAllLimit);
var MaxExpandLevel = MyAppConfig.MaxExpandLevel || 2; // default recursive expand() is set to 2
console.log("Application recursive expand limit:"+MaxExpandLevel);
var Segments = [];
var SegmentMap = {};
for( var i=0; i<MyAppConfig.segments.length; i++ ){
var SegmentDef = MyAppConfig.segments[i];
var SegmentModule = require(path.resolve(CONFIG_PATH,SegmentDef.file));
Segments.push({
name : SegmentModule.name,
segment : SegmentModule.name, // alias
module : SegmentModule.Entities,
});
SegmentMap[SegmentModule.name] = {
module : SegmentModule.Entities,
};
console.log("segment name :"+SegmentModule.name);
console.log("segment module:"+SegmentModule);
}
Segments[Segments.length-1].last = true;
var config = {
APP_NAME : APP_NAME,
SERVER_NAME : SERVER_NAME,
Protocol : Protocol,
template_dir : LIB_PATH,
output_dir : WORKING_DIR,
tools : tools,
};
console.log("start generating "+APP_NAME);
// ********** General **********
// MyApp.js
config.view = {
APP_NAME : APP_NAME
};
console.log("generating " + APP_NAME + ".js ...");
Generator.generate("MyApp",config);
// package.json
config.view = {
APP_NAME : APP_NAME
};
console.log("generating package.json");
Generator.generate("package",config);
// ********** Container **********
// Container/ContainerFactory
config.view = {
APP_NAME : APP_NAME
};
console.log("generating Container/ContainerFactory.js ...");
Generator.generate("Container/ContainerFactory",config);
// Container/ContainerManifest
config.view = {
APP_NAME : APP_NAME,
Segments : Segments,
};
console.log("generating Container/ContainerManifest.js ...");
Generator.generate("Container/ContainerManifest",config);
// Container/Container
config.view = {
APP_NAME : APP_NAME,
};
console.log("generating Container/Container.js ...");
Generator.generate("Container/Container",config);
// Container/Transaction
config.view = {
APP_NAME : APP_NAME
};
console.log("generating Container/Transaction.js ...");
Generator.generate("Container/Transaction",config);
// Container/ContainerFacade
config.view = {
APP_NAME : APP_NAME
};
console.log("generating Container/ContainerFacade.js ...");
Generator.generate("Container/ContainerFacade",config);
// Container/TransactionFacade
config.view = {
APP_NAME : APP_NAME
};
console.log("generating Container/TransactionFacade.js ...");
Generator.generate("Container/TransactionFacade",config);
// ********** Model **********
// make Entities
var Entities = [];
for( var i=0; i<Segments.length; i++ ){
var segmentName = Segments[i].segment;
var segmentDef = Segments[i].module;
var entityNames = Object.keys(segmentDef);
for( var j=0; j<entityNames.length; j++ ){
var entityName = entityNames[j];
Entities.push({
segment : segmentName,
entity : entityName,
});
}
}
Entities[Entities.length-1].last = true;
// Model/ModelFacade
config.view = {
APP_NAME : APP_NAME
};
console.log("generating Model/ModelFactory.js ...");
Generator.generate("Model/ModelFactory",config);
// Model/ModelManifest
config.view = {
APP_NAME : APP_NAME,
Entities : Entities, // [{ segment:, entity:, last:0|1 }],
};
console.log("generating Model/ModelManifest.js ...");
Generator.generate("Model/ModelManifest",config);
// Model/Segment
config.view = {
APP_NAME : APP_NAME,
Segments : Segments,
};
console.log("generating Model/Segment folders...");
Generator.generate("Model/Segment",config);
// Model/Segment/Entity,Collection
for( var i=0; i<Segments.length; i++ ){
var segmentName = Segments[i].segment;
var segmentDef = Segments[i].module;
var entityNames = Object.keys(segmentDef);
for( var j=0; j<entityNames.length; j++ ){
var entityName = entityNames[j];
var entityDef = segmentDef[entityName];
// Model/Segment/Entity
if( entityDef.type === 'Entity' ){
var fieldsDef = entityDef.fields;
var fieldNames = Object.keys(fieldsDef);
var Fields = []; // [{ field:, holder:$N, last:0|1 }],
var Holders = []; // holders for primary key and all fields [ '$1','$2',...'$field.length+1' ],
var Aggregation = []; // aggretation resolve external key and collection
for( var k=0; k<fieldNames.length; k++ ){
var fieldName = fieldNames[k];
var fieldDef = fieldsDef[fieldName];
var helper = fieldDef.helper;
var holder = '$'+(k+1);
Fields.push({
field : fieldName,
holder : holder,
helper : helper,
geography : fieldDef.type == "geography" ? true : false, // is this a geography field?
});
Holders.push({
holder : holder
});
if( helper ){
// helper should
var helper_segment_entity = helper.split('/');
var helper_segmentName = helper_segment_entity[0];
var helper_entityName = helper_segment_entity[1];
Aggregation.push({
aggregation_segmentName : '',
aggregation_entityName : '',
aggregated_segmentName : helper_segmentName,
aggregated_entityName : helper_entityName,
});
}
}
var primary_key_holder = '$' + (Fields.length+1);
Holders.push({
holder : primary_key_holder
});
Fields[Fields.length-1].last = true;
Holders[Holders.length-1].last = true;
var sequence = '';
if( entityDef.sequence ){ sequence = entityDef.sequence.name; }
// expand
var Collection = [];
if( entityDef.aggregate ){
var aggregate_segment_entities = entityDef.aggregate.split(',');
for( var k=0; k<aggregate_segment_entities.length; k++ ){
var aggregate_segment_entity = aggregate_segment_entities[k];
var array_aggregate_segment_entity = aggregate_segment_entity.split('/');
var aggregate_segmentName = array_aggregate_segment_entity[0];
var aggregate_entityName = array_aggregate_segment_entity[1];
var aggregate_segmentDef = SegmentMap[aggregate_segmentName].module;
var aggregate_entityDef = aggregate_segmentDef[aggregate_entityName];
if( aggregate_entityDef.type === 'Collection' ){
var collector_segment_entity = aggregate_entityDef.collector.entity.split('/');
var collector_segment = collector_segment_entity[0];
var collector_entity = collector_segment_entity[1];
var collected_segment_entity = aggregate_entityDef.collected.entity.split('/');
var collected_segment = collected_segment_entity[0];
var collected_entity = collected_segment_entity[1];
Collection.push({
collection_segment : aggregate_segmentName,
collection_entity : aggregate_entityName,
collectorSegment : collector_segment,
collectorEntity : collector_entity,
collectorID : aggregate_entityDef.collector.primary_key,
collectedSegment : collected_segment,
collectedEntity : collected_entity,
collectedID : aggregate_entityDef.collected.primary_key,
});
Aggregation.push({
aggregation_segmentName : aggregate_segmentName, // segment of junction table
aggregation_entityName : aggregate_entityName, // entity(collection) of junction table
aggregated_segmentName : collected_segment,
aggregated_entityName : collected_entity,
});
}
}
}
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
sequence : sequence,
primary_key : entityDef.primary_key.field,
primary_key_holder : primary_key_holder,
Fields : Fields,
Holders : Holders,
Aggregation : Aggregation,
Collection : Collection,
};
console.log("generating Model for " + entityName + " ...");
Generator.generate("Model/Segment/Entity",config);
}
// Model/Segment/Collection
else if( entityDef.type === 'Collection' ){
var fieldsDef = entityDef.fields;
var fieldNames = Object.keys(fieldsDef);
var Fields = [];
var Holders = [];
for( var k=0; k<fieldNames.length; k++ ){
var fieldName = fieldNames[k];
var holder = '$'+(k+1);
Fields.push({
field : fieldName,
holder : holder
});
Holders.push(holder);
}
Fields[Fields.length-1].last = true;
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
collectorEntity : entityDef.collector.entity,
collectorID : entityDef.collector.primary_key,
collectedEntity : entityDef.collected.entity,
collectedID : entityDef.collected.primary_key,
};
console.log("generating Model for " + entityName + " (collection) ...");
Generator.generate("Model/Segment/Collection",config);
}
}
}
// ********** ModelSanitizer **********
// make Entities
var Entities = [];
for( var i=0; i<Segments.length; i++ ){
var segmentName = Segments[i].segment;
var segmentDef = Segments[i].module;
var entityNames = Object.keys(segmentDef);
for( var j=0; j<entityNames.length; j++ ){
var entityName = entityNames[j];
Entities.push({
segment : segmentName,
entity : entityName
});
}
}
Entities[Entities.length-1].last = true;
// ModelSanitizer/ModelSanitizerFactory
config.view = {
APP_NAME : APP_NAME,
};
console.log("generating ModelSanitizer/ModelSanitizerFactory.js ...");
Generator.generate("ModelSanitizer/ModelSanitizerFactory",config);
// ModelSanitizer/ModelSanitizerManifest
config.view = {
APP_NAME : APP_NAME,
Entities : Entities,
};
console.log("generating ModelSanitizer/ModelSanitizerManifest.js ...");
Generator.generate("ModelSanitizer/ModelSanitizerManifest",config);
// ModelSanitizer/GenericSanitizer
config.view = {
APP_NAME : APP_NAME
};
console.log("generating ModelSanitizer/GenericSanitizer.js ...");
Generator.generate("ModelSanitizer/GenericSanitizer",config);
// ModelSanitizer/Segment
config.view = {
APP_NAME : APP_NAME,
Segments : Segments,
};
console.log("generating ModelSanitizer/Segment folders ...");
Generator.generate("ModelSanitizer/Segment",config);
// ModelSanitizer/Segment/Entity,Collection
var SanitizerMap = {
int : "simpleNumber",
int2 : "simpleNumber",
int4 : "simpleNumber",
text : "simpleText",
date : "simpleDate",
timestamp : "simpleTimestamp",
geography : "simpleText", // geography value should be a text representing postgis geography type by point : POINT(lon lat)
};
for( var i=0; i<Segments.length; i++ ){
var segmentName = Segments[i].segment;
var segmentDef = Segments[i].module;
var entityNames = Object.keys(segmentDef);
for( var j=0; j<entityNames.length; j++ ){
var entityName = entityNames[j];
var entityDef = segmentDef[entityName];
// ModelSanitizer/Segment/Entity
if( entityDef.type === 'Entity' ){
var fieldsDef = entityDef.fields;
var fieldNames = Object.keys(fieldsDef);
var Fields = []; // [ { field:, sanitizeMethod:auto generated by field type, last:0|1 }],
for( var k=0; k<fieldNames.length; k++ ){
var fieldName = fieldNames[k];
var fieldDef = fieldsDef[fieldName];
var fieldType = fieldDef.type;
// field based sanitization
var typedSanitizeMethod = SanitizerMap[fieldType] || SanitizerMap['text'];
// user defined sanitization
var field_sanitize_def = fieldDef.sanitize;
var sanitizeMethods = [];
if( field_sanitize_def ){
var field_sinitizes = field_sanitize_def.split(',');
for( var l=0; l<field_sinitizes.length; l++ ){
var field_sinitize = field_sinitizes[l];
var sanitizeMethod = SanitizerMap[field_sinitize];
if( sanitizeMethod ){
sanitizeMethods.push({ sanitize:sanitizeMethods });
}
}
}
// null checker, null means 0 in int field, and so on...
var notNull = false;
var field_validate_def = fieldDef.validate;
if( !field_validate_def ){
notNull = false; // allow null
}else{
var field_validates = field_validate_def.split(',');
for( var l=0; l<field_validates.length; l++ ){
var field_validate = field_validates[l];
if( field_validate == 'notNull' ){ notNull = true; } // dont allow null
}
}
Fields.push({
field : fieldName,
typedSanitizeMethod : typedSanitizeMethod,
sanitizes : sanitizeMethods,
notNull : notNull,
});
}
Fields[Fields.length-1].last = true;
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
primary_key : entityDef.primary_key.field, // primary key of this entity,
Fields : Fields,
};
console.log("generating Sanitizer for model:" + entityName + " ...");
Generator.generate("ModelSanitizer/Segment/Entity",config);
}
// ModelSanitizer/Segment/Collection (same as entity)
else if( entityDef.type === 'Collection' ){
var fieldsDef = entityDef.fields;
var fieldNames = Object.keys(fieldsDef);
var Fields = []; // [{ field:, sanitizeMethod:auto generated by field type, last:0|1 }],
for( var k=0; k<fieldNames.length; k++ ){
var fieldName = fieldNames[k];
var fieldDef = fieldsDef[fieldName];
var fieldType = fieldDef.type;
var sanitizeMethod = SanitizerMap[fieldType] || SanitizerMap['text'];
Fields.push({
field : fieldName,
sanitizeMethod : sanitizeMethod
});
}
Fields[Fields.length-1].last = true;
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
Fields : Fields,
};
console.log("generating Sanitizer for model:" + entityName + " (collection) ...");
Generator.generate("ModelSanitizer/Segment/Collection",config);
}
}
}
// ********** ModelValidator **********
// make Entities
var Entities = [];
for( var i=0; i<Segments.length; i++ ){
var segmentName = Segments[i].segment;
var segmentDef = Segments[i].module;
var entityNames = Object.keys(segmentDef);
for( var j=0; j<entityNames.length; j++ ){
var entityName = entityNames[j];
Entities.push({
segment : segmentName,
entity : entityName
});
}
}
Entities[Entities.length-1].last = true;
// ModelValidator/ModelValidatorFactory
config.view = {
APP_NAME : APP_NAME,
};
console.log("generating ModelValidator/ModelValidatorFactory.js ...");
Generator.generate("ModelValidator/ModelValidatorFactory",config);
// ModelValidator/ModelValidatorManifest
config.view = {
APP_NAME : APP_NAME,
Entities : Entities,
};
console.log("generating ModelValidator/ModelValidatorManifest.js ...");
Generator.generate("ModelValidator/ModelValidatorManifest",config);
// ModelValidator/GenericValidator
config.view = {
APP_NAME : APP_NAME,
};
console.log("generating ModelValidator/GenericValidator.js ...");
Generator.generate("ModelValidator/GenericValidator",config);
// ModelValidator/Segment
config.view = {
APP_NAME : APP_NAME,
Segments : Segments,
};
console.log("generating ModelValidator segment folders ...");
Generator.generate("ModelValidator/Segment",config);
// ModelValidator/Segment/Entity,Collection
var ValidatorMap = {
empty : "empty",
notNull : "notNull",
positiveValue : "positiveValue",
negativeValue : "negativeValue",
timestampString : "timestampString",
dateString : "dateString",
emailString : "emailString",
escapedHtmlTag : "escapedHtmlTag",
geographyPoint : "geographyPoint", // postgis geography type by point : POINT(lon lat)
};
for( var i=0; i<Segments.length; i++ ){
var segmentName = Segments[i].segment;
var segmentDef = Segments[i].module;
var entityNames = Object.keys(segmentDef);
for( var j=0; j<entityNames.length; j++ ){
var entityName = entityNames[j];
var entityDef = segmentDef[entityName];
// ModelValidator/Segment/Entity
if( entityDef.type === 'Entity' ){
var fieldsDef = entityDef.fields;
var fieldNames = Object.keys(fieldsDef);
// [{
// field : FIELD,
// valids : auto generated genric validator according to user definition,
// notNull : field nullability (special valid)
// helper : external entity (segment/entity),
// last : 0|1
// }],
var Fields = [];
for( var k=0; k<fieldNames.length; k++ ){
var fieldName = fieldNames[k];
var fieldDef = fieldsDef[fieldName];
var helper = fieldDef.helper;
var field_validate_def = fieldDef.validate;
var validateMethods = [];
var notNull = false;
if( !field_validate_def ){
validateMethods.push({ valid:ValidatorMap['empty'] });
}else{
var field_validates = field_validate_def.split(',');
for( var l=0; l<field_validates.length; l++ ){
var field_validate = field_validates[l];
var validateMethod = ValidatorMap[field_validate] || ValidatorMap['empty'];
validateMethods.push({ valid:validateMethod });
if( field_validate == 'notNull' ){ notNull = true; }
}
}
Fields.push({
field : fieldName,
valids : validateMethods,
notNull : notNull,
helper : helper,
});
}
Fields[Fields.length-1].last = true;
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
primary_key : entityDef.primary_key.field, // primary key of this entity,
primary_key_valid : entityDef.primary_key.validate, // validator of the primary key,
Fields : Fields,
};
console.log("generating Validator for model:" + entityName + " ...");
Generator.generate("ModelValidator/Segment/Entity",config);
}
// ModelValidator/Segment/Collection
else if( entityDef.type === 'Collection' ){
var collector_segment_entity = entityDef.collector.entity.split('/');
var collector_segment = collector_segment_entity[0];
var collector_entity = collector_segment_entity[1];
var collected_segment_entity = entityDef.collected.entity.split('/');
var collected_segment = collected_segment_entity[0];
var collected_entity = collected_segment_entity[1];
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
collectorSegment : collector_segment, // segment of collector (not needed)
collectorEntity : collector_entity, // collector entity (not needed)
collectorID : entityDef.collector.primary_key, // primary key of collector entity (not needed)
collectedSegment : collected_segment, // segment of collected item
collectedEntity : collected_entity, // collected entity
collectedID : entityDef.collected.primary_key, // primary key of collected entity
};
console.log("generating Validator for model:" + entityName + " (collection) ...");
Generator.generate("ModelValidator/Segment/Collection",config);
}
}
}
// ********** Constarint **********
// make Entities
var Entities = [];
for( var i=0; i<Segments.length; i++ ){
var segmentName = Segments[i].segment;
var segmentDef = Segments[i].module;
var entityNames = Object.keys(segmentDef);
for( var j=0; j<entityNames.length; j++ ){
var entityDef = segmentDef[entityNames[j]];
var entityName = entityNames[j];
// [{
// collection : type of this entity, skip collection, 0|1,
// segment : the segmet of this entity,
// entity : entity,
// last : 0|1
// }],
Entities.push({
collection : entityDef.type === 'Collection' ? true : false,
segment : segmentName,
entity : entityName,
});
}
}
Entities[Entities.length-1].last = true;
// Constraint/ConstraintFactory
config.view = {
APP_NAME : APP_NAME,
};
console.log("generating Constraint/ConstraintFactory.js ...");
Generator.generate("Constraint/ConstraintFactory",config);
// Constraint/ConstraintManifest
config.view = {
APP_NAME : APP_NAME,
Entities : Entities,
};
console.log("generating Constraint/ConstraintManifest.js ...");
Generator.generate("Constraint/ConstraintManifest",config);
// Constraint/Segment
config.view = {
APP_NAME : APP_NAME,
Segments : Segments,
};
console.log("generating Constraint/Segment folders ...");
Generator.generate("Constraint/Segment",config);
// Constraint/Entity
config.view = {
APP_NAME : APP_NAME,
Entities : Entities,
};
console.log("generating Constraint/Entity folders ...");
Generator.generate("Constraint/Entity",config);
// Constraint/EntityManifest
// Constraint/Segment/Entity/Slectby*,Orderby*
var ConstraintMap = {
key : "Constraint/Segment/Entity/SelectbyField_Key",
num : "Constraint/Segment/Entity/SelectbyField_Num",
like : "Constraint/Segment/Entity/SelectbyField_Like",
date : "Constraint/Segment/Entity/SelectbyField_Date",
timestamp : "Constraint/Segment/Entity/SelectbyField_Timestamp",
nearby : "Constraint/Segment/Entity/SelectbyField_Nearby",
area : "Constraint/Segment/Entity/SelectbyField_Area",
orderby : "Constraint/Segment/Entity/OrderbyField"
};
var ConstraintMapForJoin = {
key : "Constraint/Segment/Entity/SelectbyField_Key_join",
num : "Constraint/Segment/Entity/SelectbyField_Num_join",
like : "Constraint/Segment/Entity/SelectbyField_Like_join",
date : "Constraint/Segment/Entity/SelectbyField_Date_join",
timestamp : "Constraint/Segment/Entity/SelectbyField_Timestamp_join",
nearby : "Constraint/Segment/Entity/SelectbyField_Nearby_join",
area : "Constraint/Segment/Entity/SelectbyField_Area_join",
orderby : "Constraint/Segment/Entity/OrderbyField_join"
};
var ConstraintMapForJoinExt = { // join to a remote database entity
key : "Constraint/Segment/Entity/SelectbyField_Key_join_ext",
num : "Constraint/Segment/Entity/SelectbyField_Num_join_ext",
like : "Constraint/Segment/Entity/SelectbyField_Like_join_ext",
date : "Constraint/Segment/Entity/SelectbyField_Date_join_ext",
timestamp : "Constraint/Segment/Entity/SelectbyField_Timestamp_join_ext",
nearby : "Constraint/Segment/Entity/SelectbyField_Nearby_join_ext",
area : "Constraint/Segment/Entity/SelectbyField_Area_join_ext",
// orderby : "Constraint/Segment/Entity/OrderbyField_join_ext" // order by remote data field is not supported
};
var ConstraintMapForJnx = {
key : "Constraint/Segment/Entity/SelectbyField_Key_jnx",
num : "Constraint/Segment/Entity/SelectbyField_Num_jnx",
like : "Constraint/Segment/Entity/SelectbyField_Like_jnx",
date : "Constraint/Segment/Entity/SelectbyField_Date_jnx",
timestamp : "Constraint/Segment/Entity/SelectbyField_Timestamp_jnx",
nearby : "Constraint/Segment/Entity/SelectbyField_Nearby_jnx",
area : "Constraint/Segment/Entity/SelectbyField_Area_jnx",
orderby : "Constraint/Segment/Entity/OrderbyField_jnx"
};
var ConstraintMapForJnxExt = { // collecting remote database entity
key : "Constraint/Segment/Entity/SelectbyField_Key_jnx_ext",
num : "Constraint/Segment/Entity/SelectbyField_Num_jnx_ext",
like : "Constraint/Segment/Entity/SelectbyField_Like_jnx_ext",
date : "Constraint/Segment/Entity/SelectbyField_Date_jnx_ext",
timestamp : "Constraint/Segment/Entity/SelectbyField_Timestamp_jnx_ext",
nearby : "Constraint/Segment/Entity/SelectbyField_Nearby_jnx_ext",
area : "Constraint/Segment/Entity/SelectbyField_Area_jnx_ext",
// orderby : "Constraint/Segment/Entity/OrderbyField_jnx_ext" // order by remote data field is not supported
};
for( var i=0; i<Segments.length; i++ ){
var segmentName = Segments[i].segment;
var segmentDef = Segments[i].module;
var entityNames = Object.keys(segmentDef);
for( var j=0; j<entityNames.length; j++ ){
var entityName = entityNames[j];
var entityDef = segmentDef[entityName];
// no constraint for collection
if( entityDef.type === 'Collection' ){ continue; }
// Constraint/Segment/EntitySQLMaker
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
};
console.log("generating SQLMaker for model:" + entityName + " ...");
Generator.generate("Constraint/Segment/EntitySQLMaker",config);
// Constraint/Segment/Entity/SelectAll
// special constraint, selectAll
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
limit : SelectAllLimit,
primary_key : entityDef.primary_key.field,
};
console.log("generating select all module for the entity " + entityName);
Generator.generate("Constraint/Segment/Entity/SelectAll",config);
// Constraint/Segment/Entity/Limit
// special constraint, limiting final result
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
primary_key : entityDef.primary_key.field,
};
console.log("generating limiter module for the entity " + entityName);
Generator.generate("Constraint/Segment/Entity/Limit",config);
// prep manifest
var Selectbys = []; // [{ field:field name, search_type:search type, key,like,num,timestamp etc, last:0|1 }],
var Orderbys = []; // [{ field:field name, last:0|1, } ],
var primary_key_search_def = entityDef.primary_key.search;
if( primary_key_search_def ){
var primary_key_searches = primary_key_search_def.split(',');
for( var k=0; k<primary_key_searches.length; k++ ){
var search_type = primary_key_searches[k];
var target = ConstraintMap[search_type];
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
field : entityDef.primary_key.field,
search_type : search_type,
primary_key : entityDef.primary_key.field,
};
console.log("generating Constraint for " + entityName + "." + entityDef.primary_key.field + " (" + search_type + ") ...");
Generator.generate(target,config);
if( search_type === 'orderby' ){
Orderbys.push({
field : entityDef.primary_key.field,
});
}else{
Selectbys.push({
search_segment : segmentName,
search_entity : entityName,
search_field : entityDef.primary_key.field,
search_type : search_type,
});
}
}
}
var fieldsDef = entityDef.fields;
var fieldNames = Object.keys(fieldsDef);
for( var k=0; k<fieldNames.length; k++ ){
var fieldName = fieldNames[k];
var fieldDef = fieldsDef[fieldName];
var field_search_def = fieldDef.search;
if( !field_search_def ){ continue; }
var field_searches = field_search_def.split(',');
for( var l=0; l<field_searches.length; l++ ){
var search_type = field_searches[l];
if( search_type === 'join' ){
// get joined entity info and loop the field,
var joined_segment_entity = fieldDef.helper;
var array_segment_entity = joined_segment_entity.split('/');
var joined_segmentName = array_segment_entity[0];
var joined_entityName = array_segment_entity[1];
var joined_segmentDef = SegmentMap[joined_segmentName].module;
var joined_entityDef = joined_segmentDef[joined_entityName];
var joined_fieldsDef = joined_entityDef.fields;
var joined_fieldNames = Object.keys(joined_fieldsDef);
for( var m=0; m<joined_fieldNames.length; m++ ){
var joined_fieldName = joined_fieldNames[m];
var joined_fieldDef = joined_fieldsDef[joined_fieldName];
var joined_field_search_def = joined_fieldDef.search;
if( !joined_field_search_def ){ continue; }
var joined_field_searches = joined_field_search_def.split(',');
for( var n=0; n<joined_field_searches.length; n++ ){
var joined_search_type = joined_field_searches[n];
if( joined_search_type === 'join' ){ continue; } // recursive join not supported
var target;
if( segmentName == joined_segmentName ){
target = ConstraintMapForJoin[joined_search_type];
}else{
target = ConstraintMapForJoinExt[joined_search_type];
}
if( !target ){ continue; } // unsupported type, might be a orderby remote field
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
field : fieldName,
search_type : search_type, // might be 'join'
primary_key : entityDef.primary_key.field, // pk of the entity, the target field is belonging in,
segment_joined : joined_segmentName, // segment of the joined entity,
entity_joined : joined_entityName, // joined entity,
field_joined : joined_fieldName, // field of the joined entity,
primary_key_joined : joined_entityDef.primary_key.field, // primary key of joined entity
search_type_joined : joined_search_type, // search type of the joined field,
};
console.log("generating Constraint for " + entityName + "." + fieldName + " (join) ...");
Generator.generate(target,config);
if( joined_search_type === 'orderby' ){
Orderbys.push({
field : joined_fieldName,
});
}else{
Selectbys.push({
search_segment : joined_segmentName,
search_entity : joined_entityName,
search_field : joined_fieldName,
search_type : joined_search_type,
});
}
}
}
}
else{
var target = ConstraintMap[search_type];
config.view = {
APP_NAME : APP_NAME,
segment : segmentName, // segment of the entity,
entity : entityName, // entity of the field,
field : fieldName, // field,
search_type : search_type, // search type, key,like,num,timestamp etc,
primary_key : entityDef.primary_key.field, // pk of the entity, the target field is belonging in,
};
console.log("generating Constraint for " + entityName + "." + fieldName + " (" + search_type + ") ...");
Generator.generate(target,config);
if( search_type === 'orderby' ){
Orderbys.push({
field : fieldName,
});
}else{
Selectbys.push({
search_segment : segmentName,
search_entity : entityName,
search_field : fieldName,
search_type : search_type,
});
}
}
}
}
// junction table
if( entityDef.aggregate ){
var jnx_segment_entities = entityDef.aggregate.split(',');
for( var k=0; k<jnx_segment_entities.length; k++ ){
var jnx_segment_entity = jnx_segment_entities[k];
var array_segment_entity = jnx_segment_entity.split('/');
var jnx_segmentName = array_segment_entity[0];
var jnx_entityName = array_segment_entity[1];
var jnx_segmentDef = SegmentMap[jnx_segmentName].module;
var jnx_entityDef = jnx_segmentDef[jnx_entityName];
var col_segment_entity = jnx_entityDef.collected.entity;
var array_segment_entity = col_segment_entity.split('/');
var col_segmentName = array_segment_entity[0];
var col_entityName = array_segment_entity[1];
var col_segmentDef = SegmentMap[col_segmentName].module;
var col_entityDef = col_segmentDef[col_entityName];
var col_fieldsDef = col_entityDef.fields;
var col_fieldNames = Object.keys(col_fieldsDef);
var col_primary_key = col_entityDef.primary_key.field;
for( var l=0; l<col_fieldNames.length; l++ ){
var col_fieldName = col_fieldNames[l];
var col_fieldDef = col_fieldsDef[col_fieldName];
var col_field_search_def = col_fieldDef.search;
if( !col_field_search_def ){ continue; }
var col_field_searches = col_field_search_def.split(',');
for( var m=0; m<col_field_searches.length; m++ ){
var col_search_type = col_field_searches[m];
if( col_search_type === 'join' ){ continue; } // recursive join not supported
if( col_search_type === 'orderby' ){ continue; } // orderby via junction is not supported
var target;
if( segmentName == col_segmentName ){
target = ConstraintMapForJnx[col_search_type];
}else{
target = ConstraintMapForJnxExt[col_search_type];
}
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
primary_key : entityDef.primary_key.field,
junction : jnx_entityName,
segment_jnx : col_segmentName,
entity_jnx : col_entityName,
primary_key_jnx : col_entityDef.primary_key.field,
field_jnx : col_fieldName,
search_type_jnx : col_search_type,
};
console.log("generating Constraint for " + entityName + "." + col_fieldName + " (" + col_search_type + ") (junction) ...");
Generator.generate(target,config);
Selectbys.push({
search_segment : col_segmentName,
search_entity : col_entityName,
search_field : col_fieldName,
search_type : col_search_type,
});
}
}
}
}
if( Selectbys.length > 0 ){ Selectbys[Selectbys.length-1].last = true; }
if( Orderbys.length > 0 ){ Orderbys[Orderbys.length-1].last = true; }
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
primary_key : entityDef.primary_key.field, // pk of this entity,
Selectbys : Selectbys,
Orderbys : Orderbys,
};
console.log("generating Constraint manifest for " + entityName + " ...");
Generator.generate("Constraint/Segment/EntityManifest",config);
}
}
// ********** Logic **********
// make Entities
var Entities = [];
for( var i=0; i<Segments.length; i++ ){
var segmentName = Segments[i].segment;
var segmentDef = Segments[i].module;
var entityNames = Object.keys(segmentDef);
for( var j=0; j<entityNames.length; j++ ){
var entityName = entityNames[j];
Entities.push({
segment : segmentName,
entity : entityName,
});
}
}
Entities[Entities.length-1].last = true;
// Logic/LogicFactory
config.view = {
APP_NAME : APP_NAME,
};
console.log("generating Logic/LogicFactory.js ...");
Generator.generate("Logic/LogicFactory",config);
// Logic/LogicManifest
config.view = {
APP_NAME : APP_NAME,
Entities : Entities,
};
console.log("generating Logic/LogicManifest.js ...");
Generator.generate("Logic/LogicManifest",config);
// Logic/Segment
config.view = {
APP_NAME : APP_NAME,
Segments : Segments,
};
console.log("generating Logic/Segment folders ...");
Generator.generate("Logic/Segment",config);
// Logic/Segment/Entity,Collection
for( var i=0; i<Segments.length; i++ ){
var segmentName = Segments[i].segment;
var segmentDef = Segments[i].module;
var entityNames = Object.keys(segmentDef);
for( var j=0; j<entityNames.length; j++ ){
var entityDef = segmentDef[entityNames[j]];
var entityName = entityNames[j];
// Logic/Segment/Entity
if( entityDef.type === 'Entity' ){
var fieldsDef = entityDef.fields;
var fieldNames = Object.keys(fieldsDef);
var Fields = []; // [{ field:FIELD, last:0|1 }]
for( var k=0; k<fieldNames.length; k++ ){
var fieldName = fieldNames[k];
var fieldDef = fieldsDef[fieldName];
var notNull = false;
var field_validate_def = fieldDef.validate;
if( !field_validate_def ){
notNull = false; // allow null
}else{
var field_validates = field_validate_def.split(',');
for( var l=0; l<field_validates.length; l++ ){
var field_validate = field_validates[l];
if( field_validate == 'notNull' ){ notNull = true; } // dont allow null
}
}
Fields.push({
field : fieldName,
notNull : notNull,
});
}
Fields[Fields.length-1].last = true;
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
primary_key : entityDef.primary_key.field, // primary key of this entity,
Fields : Fields,
};
console.log("generating logic for model:" + entityName + " ...");
Generator.generate("Logic/Segment/Entity",config);
}
// Logic/Segment/Collection
else if( entityDef.type === 'Collection' ){
var fieldsDef = entityDef.fields;
var fieldNames = Object.keys(fieldsDef);
var Fields = [];
for( var k=0; k<fieldNames.length; k++ ){
var fieldName = fieldNames[k];
var fieldDef = fieldsDef[fieldName];
Fields.push({
field : fieldNames[k],
});
}
Fields[Fields.length-1].last = true;
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
collectorID : entityDef.collector.primary_key, // pk of collector entity
};
console.log("generating logic for model:" + entityName + " (collection) ...");
Generator.generate("Logic/Segment/Collection",config);
}
}
}
// ********** Utils **********
// Utils/Utils
config.view = {
APP_NAME : APP_NAME,
};
console.log("generating Utils/Utils.js ...");
Generator.generate("Utils/Utils",config);
// ********** Implementation **********
// MyAppImpl.js
config.view = {
APP_NAME : APP_NAME
};
console.log("generating " + APP_NAME + ".js ...");
Generator.generate("MyAppImpl",config);
// MyAppImpl/package.json
config.view = {
APP_NAME : APP_NAME
};
console.log("generating package.json");
Generator.generate("MyAppImpl/package",config);
// ***** Model implementation *****
var hasAutoModelImpl = false;
var ImplePermissionCheck = false;
if( MyAppConfig.Permission ){
hasAutoModelImpl = true;
ImplePermissionCheck = true;
}
// ModelImpl/ModelImplFactory
config.view = {
APP_NAME : APP_NAME
};
console.log("generating ModelImplFactory");
Generator.generate("ModelImpl/ModelImplFactory",config);
// ModelSanitizerImpl/ModelSanitizerImplFactory
config.view = {
APP_NAME : APP_NAME
};
console.log("generating ModelSanitizerImplFactory");
Generator.generate("ModelSanitizerImpl/ModelSanitizerImplFactory",config);
// ModelValidatorImpl/ModelValidatorImplFactory
config.view = {
APP_NAME : APP_NAME
};
console.log("generating ModelValidatorImplFactory");
Generator.generate("ModelValidatorImpl/ModelValidatorImplFactory",config);
// ConstraintImpl/ConstraintImplFactory
config.view = {
APP_NAME : APP_NAME
};
console.log("generating ConstraintImplFactory");
Generator.generate("ConstraintImpl/ConstraintImplFactory",config);
// ConstraintImpl/SelectbyImplFactory
config.view = {
APP_NAME : APP_NAME
};
console.log("generating SelectbyImplFactory");
Generator.generate("ConstraintImpl/SelectbyImplFactory",config);
// ConstraintImpl/OrderbyImplFactory
config.view = {
APP_NAME : APP_NAME
};
console.log("generating OrderbyImplFactory");
Generator.generate("ConstraintImpl/OrderbyImplFactory",config);
// ***** Logic implementation *****
//
// precheck
//
var hasAutoLogicImpl = false;
var ImplAuthLogic = false;
var AuthPassword = false;
if( MyAppConfig.AuthPassword ){
hasAutoLogicImpl = true;
ImplAuthLogic = true;
AuthPassword = true;
}
var TokenLifetime = eval(MyAppConfig.TokenLifetime) || 60*60*24*365; // default token lifetime is 1year
// LogicImpl/LogicImplFactory
config.view = {
APP_NAME : APP_NAME
};
console.log("generating LogicImplFactory");
Generator.generate("LogicImpl/LogicImplFactory",config);
// LogicImpl/LogicImplManifest
config.view = {
APP_NAME : APP_NAME,
Entities : Entities,
hasAutoLogicImpl : hasAutoLogicImpl,
ImplAuthLogic : ImplAuthLogic,
AuthPassword : AuthPassword,
};
console.log("generating Logic/LogicImplManifest.js ...");
Generator.generate("LogicImpl/LogicImplManifest",config);
// LogicImpl/Auth
if( MyAppConfig.AuthPassword ){
var auth_elements = MyAppConfig.AuthPassword.match(/(\w+)\/(\w+)\.(\w+),(\w+)/); // format: Segment/Entity.id_field,pass_field
if( !auth_elements ){
throw new Error("invalid AuthPassword definition");
}
var auth_segment = auth_elements[1];
var auth_entity = auth_elements[2];
var auth_id_field = auth_elements[3];
var auth_pass_field = auth_elements[4];
config.view = {
APP_NAME : APP_NAME,
Segments : Segments,
auth_segment : auth_segment,
auth_entity : auth_entity,
auth_id_field : auth_id_field,
auth_pass_field : auth_pass_field,
token_lifetime : TokenLifetime,
};
console.log("generating LogicImpl/AuthPassword ...");
Generator.generate("LogicImpl/AuthPassword",config);
}
// LogicImpl/Segment
config.view = {
APP_NAME : APP_NAME,
Segments : Segments,
};
console.log("generating Logic/Segment folders ..."); // unless no need to make folders
Generator.generate("LogicImpl/Segment",config);
// LogicImpl/Segment/Entity,Collection
for( var i=0; i<Segments.length; i++ ){
var segmentName = Segments[i].segment;
var segmentDef = Segments[i].module;
var entityNames = Object.keys(segmentDef);
for( var j=0; j<entityNames.length; j++ ){
var entityDef = segmentDef[entityNames[j]];
var entityName = entityNames[j];
// Logic/Segment/Entity
if( entityDef.type === 'Entity' ){
var fieldsDef = entityDef.fields;
var fieldNames = Object.keys(fieldsDef);
var Fields = []; // [{ field:FIELD, last:0|1 }]
for( var k=0; k<fieldNames.length; k++ ){
var fieldName = fieldNames[k];
var fieldDef = fieldsDef[fieldName];
var notNull = false;
var field_validate_def = fieldDef.validate;
if( !field_validate_def ){
notNull = false; // allow null
}else{
var field_validates = field_validate_def.split(',');
for( var l=0; l<field_validates.length; l++ ){
var field_validate = field_validates[l];
if( field_validate == 'notNull' ){ notNull = true; } // dont allow null
}
}
Fields.push({
field : fieldName,
notNull : notNull,
});
}
Fields[Fields.length-1].last = true;
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
primary_key : entityDef.primary_key.field, // primary key of this entity,
Fields : Fields,
ImplAuthLogic : ImplAuthLogic,
AuthPassword : AuthPassword,
};
console.log("generating logic for model:" + entityName + " ...");
Generator.generate("LogicImpl/Segment/Entity",config);
}
// Logic/Segment/Collection
else if( entityDef.type === 'Collection' ){
var fieldsDef = entityDef.fields;
var fieldNames = Object.keys(fieldsDef);
var Fields = [];
for( var k=0; k<fieldNames.length; k++ ){
var fieldName = fieldNames[k];
var fieldDef = fieldsDef[fieldName];
Fields.push({
field : fieldNames[k],
});
}
Fields[Fields.length-1].last = true;
config.view = {
APP_NAME : APP_NAME,
segment : segmentName,
entity : entityName,
collectorID : entityDef.collector.primary_key, // pk of collector entity
ImplAuthLogic : ImplAuthLogic,
AuthPassword : AuthPassword,
};
console.log("generating logic for model:" + entityName + " (collection) ...");
Generator.generate("LogicImpl/Segment/Collection",config);
}
}
}
// ********** schema **********
//
// current version supports postgresql/postgis
//
var FieldTypePgTypeMap = {
int : "int",
int2 : "int2",
int4 : "int4",
text : "text",
date : "date",
timestamp : "timestamp",
image : "text",
geography : "geography(point)",
};
for( var i=0; i<Segments.length; i++ ){
var segmentName = Segments[i].segment;
var segmentDef = Segments[i].module;
var entityNames = Object.keys(segmentDef);
var Entities = [];
for( var j=0; j<entityNames.length; j++ ){
var entityName = entityNames[j];
var entityDef = segmentDef[entityName];
if( entityDef.type === 'Entity' ){
var Fields = [];
var Data = [];
if( entityDef.data && entityDef.data.length > 0 ){ // check predefined initial data
var initial_data = entityDef.data;
for( var k=0; k<initial_data.length; k++ ){
var raw_values = initial_data[k].values;
var values = [];
for( var l=0; l<raw_values.length; l++ ){
values.push({
escvalue : raw_values[l].escvalue,
rawvalue : raw_values[l].rawvalue,
value : raw_values[l].value,
last : l==raw_values.length-1 ? true : false
});
}
Data.push({ values : values });
}
}
Fields.push({
fieldName : entityDef.primary_key.field,
type : FieldTypePgTypeMap[entityDef.primary_key.type],
});
var fieldsDef = entityDef.fields;
var fieldNames = Object.keys(fieldsDef);
for( var k=0; k<fieldNames.length; k++ ){
var fieldName = fieldNames[k];
var fieldDef = fieldsDef[fieldName];
Fields.push({
fieldName : fieldName,
type : FieldTypePgTypeMap[fieldDef.type],
});
}
Fields[Fields.length-1].last = true;
var sequenceName = '';
var start = '';
if( entityDef.sequence ){
sequenceName = entityDef.sequence.name;
start = entityDef.sequence.start;
}
Entities.push({
entityName : entityName,
primary_key : entityDef.primary_key.field,
Fields : Fields,
isEntity : true,
sequenceName : sequenceName,
start : start,
Data : Data,
});
}
else if( entityDef.type === 'Collection' ){
var Data = [];
if( entityDef.data && entityDef.data.length > 0 ){ // check predefined initial data
var initial_data = entityDef.data;
for( var k=0; k<initial_data.length; k++ ){
var raw_values = initial_data[k].values;
var values = [];
for( var l=0; l<raw_values.length; l++ ){
values.push({
escvalue : raw_values[l].escvalue,
rawvalue : raw_values[l].rawvalue,
value : raw_values[l].value,
last : l==raw_values.length-1 ? true : false
});
}
Data.push({ values : values });
}
}
Entities.push({
segmentName : segmentName,
entityName : entityName,
ui_entityName : entityDef.name,
collector_primary_key : entityDef.collector.primary_key,
collected_primary_key : entityDef.collected.primary_key,
isCollection : true,
Data : Data,
});
}
}
config.view = {
APP_NAME : APP_NAME,
SERVER_NAME : SERVER_NAME,
segmentName : segmentName,
Entities : Entities,
};
console.log("generating schema files for postgresql/postgis for segment:"+segmentName);
Generator.generate("schema/postgresql", config);
Generator.generate("schema/postgresql_data", config);
}
// * * * * * * * * * * * * * * * * * * * *
// MyAppConfig
config.view = {
APP_NAME : APP_NAME,
Segments : Segments,
SelectAllLimit : SelectAllLimit,
MaxExpandLevel : MaxExpandLevel,
ImplAuthLogic : ImplAuthLogic,
Protocol : Protocol,
AppHost : AppHost,
AppPort : AppPort,
DBHost : DBHost,
DBPort : DBPort,
DBUser : DBUser,
DBPass : DBPass,
CacheHost : CacheHost,
CachePort : CachePort,
};
console.log("generating MyAppConfig ...");
Generator.generate("MyAppConfig",config);
// MyAppConfig/package.json
config.view = {
APP_NAME : APP_NAME
};
console.log("generating package.json");
Generator.generate("MyAppConfig/package",config);
// MyAppConfig/README.md
config.view = {
APP_NAME : APP_NAME
};
console.log("generating README.md");
Generator.generate("MyAppConfig/README",config);
// MyAppConfig/SSLDefaultCert
config.view = {
APP_NAME : APP_NAME,
AppHost : AppHost,
};
console.log("generating default cert for ssl");
Generator.generate("MyAppConfig/SSLDefaultCert",config);
// MyAppConfig/JWSDefaultCert
config.view = {
APP_NAME : APP_NAME,
AppHost : AppHost,
};
console.log("generating default cert for jws");
Generator.generate("MyAppConfig/JWSDefaultCert",config);
// * * * * * * * * * * * * * * * * * * * *
// server.js
config.view = {
APP_NAME : APP_NAME,
Segments : Segments,
Protocol : Protocol,
AppHost