jhipster-rasha-core
Version:
JHipster's own domain language and core objects
241 lines (222 loc) • 8.07 kB
JavaScript
;
const _ = require('lodash'),
JDLObject = require('../core/jdl_object'),
JDLEnum = require('../core/jdl_enum'),
JDLField = require('../core/jdl_field'),
JDLRelationship = require('../core/jdl_relationship'),
JDLValidation = require('../core/jdl_validation'),
JDLUnaryOption = require('../core/jdl_unary_option'),
JDLBinaryOption = require('../core/jdl_binary_option'),
UnaryOptions = require('../core/jhipster/unary_options'),
BinaryOptions = require('../core/jhipster/binary_options'),
FieldTypes = require('../core/jhipster/field_types'),
formatComment = require('../utils/format_utils').formatComment,
isReservedClassName = require('../core/jhipster/reserved_keywords').isReservedClassName,
isReservedFieldName = require('../core/jhipster/reserved_keywords').isReservedFieldName,
buildException = require('../exceptions/exception_factory').buildException,
exceptions = require('../exceptions/exception_factory').exceptions;
module.exports = {
parse: parse
};
const USER = 'User';
let document;
let jdlObject;
let isType;
/**
* Convert the given intermediate object to JDLObject
*/
function parse(passedDocument, passedDatabaseType) {
if (!passedDocument || !passedDatabaseType) {
throw new buildException(exceptions.NullPointer, 'The parsed JDL content and the database type must be passed.');
}
init(passedDocument, passedDatabaseType);
fillEnums();
fillClassesAndFields(passedDatabaseType);
fillAssociations();
fillOptions();
return jdlObject;
}
function init(passedDocument, passedDatabaseType) {
document = passedDocument;
jdlObject = new JDLObject();
isType = FieldTypes.getIsType(passedDatabaseType, () => isType = null);
}
function fillEnums() {
for (let i = 0; i < document.enums.length; i++) {
let enumObj = document.enums[i];
if (isReservedClassName(enumObj.name)) {
throw new buildException(
exceptions.IllegalName,
`The name '${enumObj.name}' is reserved keyword and can not be used as enum class name.`);
}
jdlObject.addEnum(new JDLEnum({
name: enumObj.name,
values: enumObj.values,
comment: formatComment(enumObj.javadoc)
}));
}
}
function fillClassesAndFields(passedDatabaseType) {
for (let i = 0; i < document.entities.length; i++) {
let entity = document.entities[i];
if (isReservedClassName(entity.name)) {
throw new buildException(
exceptions.IllegalName,
`The name '${entity.name}' is reserved keyword and can not be used as entity class name.`);
}
let tableName = entity.tableName || entity.name;
jdlObject.addEntity({
name: entity.name,
tableName: tableName,
fields: getFields(entity, passedDatabaseType),
comment: formatComment(entity.javadoc)
});
}
let relationToUser = document.relationships.filter(function (val) {
return val.to.name.toLowerCase() === USER.toLowerCase();
});
if (relationToUser && relationToUser.length && !jdlObject.entities[USER]) {
jdlObject.addEntity({
name: USER,
tableName: 'jhi_user',
fields: {}
});
}
}
function getFields(entity, passedDatabaseType) {
const fields = {};
for (let i = 0; i < entity.body.length; i++) {
let field = entity.body[i];
let fieldName = _.lowerFirst(field.name);
if (fieldName.toLowerCase() === 'id') {
continue;
}
if (isReservedFieldName(fieldName)) {
throw new buildException(
exceptions.IllegalName,
`The name '${fieldName}' is a reserved keyword and can not be used as entity field name.`);
}
if (jdlObject.enums[field.type] || isType(field.type)) {
let fieldObject = new JDLField({
name: fieldName,
type: field.type,
validations: getValidations(field, jdlObject.enums[field.type])
});
if (field.javadoc) {
fieldObject.comment = formatComment(field.javadoc);
}
fields[fieldName] = fieldObject;
} else {
throw new buildException(exceptions.WrongType, `The type '${field.type}' doesn't exist.`);
}
}
return fields;
}
function getValidations(field, isAnEnum) {
const validations = {};
for (let i = 0; i < field.validations.length; i++) {
let validation = field.validations[i];
if (!FieldTypes.hasValidation(field.type, validation.key, isAnEnum)) {
throw new buildException(
exceptions.WrongValidation,
`The validation '${validation.key}' isn't supported for the type '${field.type}'.`);
}
if (validation.constant) {
validation.value = document.constants[validation.value];
}
validations[validation.key] = new JDLValidation({
name: validation.key,
value: validation.value
});
}
return validations;
}
function fillAssociations() {
for (let i = 0; i < document.relationships.length; i++) {
let relationship = document.relationships[i];
checkEntityDeclaration(relationship);
jdlObject.addRelationship(new JDLRelationship({
from: jdlObject.entities[relationship.from.name],
to: jdlObject.entities[relationship.to.name],
type: _.upperFirst(_.camelCase(relationship.cardinality)),
injectedFieldInFrom: relationship.from.injectedfield,
injectedFieldInTo: relationship.to.injectedfield,
isInjectedFieldInFromRequired: relationship.from.required,
isInjectedFieldInToRequired: relationship.to.required,
commentInFrom: formatComment(relationship.from.javadoc),
commentInTo: formatComment(relationship.to.javadoc)
}));
}
}
function checkEntityDeclaration(relationship) {
const absentEntities = [];
if (relationship.from.name.toLowerCase() === USER.toLowerCase()) {
throw new buildException(
exceptions.IllegalAssociation,
`Relationships from User entity is not supported in the declaration between ${relationship.from.name} and `
+ `${relationship.to.name}.`
);
}
if (!jdlObject.entities[relationship.from.name]) {
absentEntities.push(relationship.from.name);
}
if (relationship.to.name.toLowerCase() !== USER.toLowerCase() && !jdlObject.entities[relationship.to.name]) {
absentEntities.push(relationship.to.name);
}
if (absentEntities.length !== 0) {
throw new buildException(
exceptions.UndeclaredEntity,
`In the relationship between ${relationship.from.name} and `
+ `${relationship.to.name}, ${absentEntities.join(' and ')} `
+ `${(absentEntities.length === 1 ? 'is' : 'are')} not declared.`
);
}
}
function fillOptions() {
fillUnaryOptions();
fillBinaryOptions();
}
function fillUnaryOptions() {
if (document.noClient.list.length !== 0) {
jdlObject.addOption(new JDLUnaryOption({
name: UnaryOptions.UNARY_OPTIONS.SKIP_CLIENT,
entityNames: document.noClient.list,
excludedNames: document.noClient.excluded
}));
}
if (document.noServer.list.length !== 0) {
jdlObject.addOption(new JDLUnaryOption({
name: UnaryOptions.UNARY_OPTIONS.SKIP_SERVER,
entityNames: document.noServer.list,
excludedNames: document.noServer.excluded
}));
}
if (document.noFluentMethod.list.length !== 0) {
jdlObject.addOption(new JDLUnaryOption({
name: UnaryOptions.UNARY_OPTIONS.NO_FLUENT_METHOD,
entityNames: document.noFluentMethod.list,
excludedNames: document.noFluentMethod.excluded
}));
}
}
function addOption(key, value) {
let option = new JDLBinaryOption({
name: key,
value: value,
entityNames: document[key][value].list,
excludedNames: document[key][value].excluded
});
if (!document[key].hasOwnProperty(value) || !JDLBinaryOption.isValid(option)) {
throw new buildException(
exceptions.InvalidObject,
`The parsed ${key} option is not valid for value ${value}.`);
}
jdlObject.addOption(option);
}
function fillBinaryOptions() {
_.forEach(BinaryOptions.BINARY_OPTIONS, (optionValue) => {
_.forEach(document[optionValue], (documentOptionValue, documentOptionKey) => {
addOption(optionValue, documentOptionKey);
});
});
}