in src/processors/ReferenceProcessor.js [19:228]
process(specs, metadata) {
const APISpecs = specs.api_specs;
const enumMetadataMap = specs.enumMetadataMap;
// add enum reference info into class specs
for (const index in enumMetadataMap) {
const enumType = enumMetadataMap[index];
const nodeName = enumType.node;
if (nodeName && APISpecs[nodeName]) {
const clsSpec = APISpecs[nodeName];
if (!clsSpec.api_spec_based_enum_reference) {
clsSpec.api_spec_based_enum_reference = [];
clsSpec.api_spec_based_enum_list = {};
}
if (clsSpec.api_spec_based_enum_list[enumType.field_or_param]) {
// already exists. do nothing
} else {
clsSpec.api_spec_based_enum_reference.push(enumType);
clsSpec.api_spec_based_enum_list[enumType.field_or_param] = true;
}
}
}
for (const clsName in APISpecs) {
const APIClsSpec = APISpecs[clsName];
codeGenNameConventions.populateNameConventions(
APISpecs[clsName],
'names',
codeGenNameConventions.parsePascalName(clsName),
);
// Initialize references based on API return types
const references = {};
if (APIClsSpec.references) {
APIClsSpec.references.forEach((ref: string) => {
const ref_cls_name = ref;
references[ref_cls_name] = true;
});
}
// Initialize field references
const fieldReferences = {};
// Process API class
APIClsSpec.node = [];
APIClsSpec.edges = [];
for (const index in APIClsSpec.apis) {
const APISpec = APIClsSpec.apis[index];
const apiReferencedEnumTypes = {};
const apiClassReferences = {};
let hasParamFields = false;
const params = APISpec.params || [];
for (const index in params) {
const paramSpec = params[index];
if (paramSpec.name === 'fields') {
hasParamFields = true;
}
if (paramSpec.type) {
paramSpec['type:short'] = paramSpec.type;
const baseType = CodeGenUtil.getBaseType(paramSpec.type);
if (APISpecs[baseType]) {
APISpecs[baseType]['can_be_data_type'] = true;
}
if (enumMetadataMap[baseType]) {
const enumParamName = paramSpec.name + '_enum';
const metadata = enumMetadataMap[baseType];
const enumType = {
name: enumParamName,
metadata: metadata,
};
codeGenNameConventions.populateNameConventions(
enumType,
'name',
codeGenNameConventions.parseUnderscoreName(enumType.name),
);
paramSpec['type:short'] = paramSpec.type.replace(
baseType,
enumParamName,
);
apiReferencedEnumTypes[baseType] = enumType;
}
}
}
// Standardize endpoints starting with "/"
if (APISpec.endpoint.charAt(0) !== '/') {
APISpec.endpoint = '/' + APISpec.endpoint;
}
// Resolve return types
const returnClsSpec = APISpecs[APISpec.return];
if (returnClsSpec) {
// Add "fields" field
if (APISpec.method === 'GET' && !hasParamFields) {
APISpec.param_fields = returnClsSpec.fields.filter(
(field: {[x: string]: mixed}) => {
return !field.is_creation_field;
},
);
} else {
APISpec.param_fields = false;
}
} else {
delete APISpec.return;
}
if (APISpec.return) {
references[APISpec.return] = true;
apiClassReferences[APISpec.return] = true;
codeGenNameConventions.populateNameConventions(
APISpec,
'return',
codeGenNameConventions.parsePascalName(APISpec.return),
);
}
if (Object.keys(apiReferencedEnumTypes).length) {
const apiReferencedEnumList = [];
for (const key in apiReferencedEnumTypes) {
apiReferencedEnumList.push(apiReferencedEnumTypes[key]);
const cls = apiReferencedEnumTypes[key]['metadata']['node'];
if (cls) {
apiClassReferences[cls] = true;
}
}
APISpec.referred_enums = apiReferencedEnumList;
}
APISpec.referred_classes = [];
for (const refName in apiClassReferences) {
if (refName !== clsName) {
const refObj = {};
codeGenNameConventions.populateNameConventions(
refObj,
'name',
codeGenNameConventions.parsePascalName(refName),
'api-ref:',
);
APISpec.referred_classes.push(refObj);
}
}
if (APISpec.is_node_api === true) {
APIClsSpec.node.push(APISpec);
} else {
APIClsSpec.edges.push(APISpec);
}
}
// Process references
APIClsSpec.references = [];
for (const refName in references) {
// no self-reference
// no self-reference after overrides
if (refName !== clsName && refName !== APIClsSpec.name) {
const refObj = {};
codeGenNameConventions.populateNameConventions(
refObj,
'name',
codeGenNameConventions.parsePascalName(refName),
'ref:',
);
APIClsSpec.references.push(refObj);
}
}
// Pure data type or not
const isDataType = !APIClsSpec.apis || APIClsSpec.apis.length == 0;
APIClsSpec.data_type = isDataType;
// Process fields of current object
let hasIdField = false;
for (const index in APIClsSpec.fields) {
const fieldSpec = APIClsSpec.fields[index];
if (fieldSpec.name === 'id') {
hasIdField = true;
fieldSpec.is_id_field = true;
}
const referenceType = getReferenceType(fieldSpec.type, APISpecs);
if (referenceType !== null && referenceType !== undefined) {
fieldReferences[referenceType] = true;
}
}
// Process references
APIClsSpec.field_references = [];
for (const refName in fieldReferences) {
// no self-reference
// no self-reference after overrihs
if (refName !== clsName && refName !== APIClsSpec.name) {
const refObj = {};
codeGenNameConventions.populateNameConventions(
refObj,
'name',
codeGenNameConventions.parsePascalName(refName),
'ref:',
);
APIClsSpec.field_references.push(refObj);
}
}
if (!isDataType && !hasIdField) {
throw Error('Root nodes ' + clsName + ' must have the "id" field!');
}
}
return specs;
},