-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpositionalFileHelper.js
More file actions
155 lines (125 loc) · 5.61 KB
/
positionalFileHelper.js
File metadata and controls
155 lines (125 loc) · 5.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
const os = require('os');
const moment = require('moment');
const { v4: uuidv4 } = require('uuid');
const { setNestedAttribute, pushNestedAttribute } = require("./nestedUtil");
function getObjectsFromFile(data, fileMapping) {
let dataObjectsArray = [];
let parentMap = new Map();
const lines = data.split(os.EOL);
checkFileIsValid(lines);
for(let lineNumber=0;lineNumber<lines.length;lineNumber++){
let line = lines[lineNumber];
if (!isLineHasData(line)) continue; //ignoring empty lines
let discriminator = getDiscriminator(line, fileMapping, lineNumber);
let lineMapping = fileMapping.lines.get(discriminator);
if (!isLineMappingValid(lineMapping, discriminator, lineNumber)) continue;
let object = getObjectFromLine(lineMapping, line, lineNumber, parentMap);
object.uuid = uuidv4();
parentMap.set(discriminator, object);
dataObjectsArray.push(object);
}
return dataObjectsArray;
}
function getObjectFromLine(lineMapping, line, lineNumber, parentMap) {
const dataObject = {};
for (i=0;i<lineMapping.length;i++){
const attribute = lineMapping[i];
checkMappingIsValid(attribute);
const value = line.substring(attribute.initialPosition, attribute.initialPosition + attribute.length);
let parentObject = {};
switch (attribute.type) {
case 'integer':
dataObject[attribute.name] = parseInteger(value, attribute, lineNumber);
break;
case 'date':
dataObject[attribute.name] = parseDate(value, attribute, lineNumber);
break;
case 'string':
dataObject[attribute.name] = parseString(value, attribute, lineNumber);
break;
case 'parent':
if (attribute.name == 'parent') throw "Attribute Parent, declared in lineMapping. Could not be named 'parent', due to, its reserved to de parent object";
parentObject = parentMap.get(attribute.parentDiscriminator);
dataObject[attribute.name] = parentObject[attribute.parentAttribute];
//adding children to parent
pushNestedAttribute(parentObject, attribute.childName, dataObject);
//adding parent attribute to the children.
dataObject['parent'] = parentObject;
break;
default:
throw `Attribute type "${attribute.type}", declared in lineMapping is not valid or not implemented. line number ${lineNumber}.`;
}
checkRequiredIsValid(attribute, dataObject[attribute.name], lineNumber);
}
return dataObject;
}
function parseDate(value, attribute, lineNumber) {
if (!attribute.dateFormat)
throw `The attribute ${attribute.name} has no dateFormat declared in lineMapping`;
if (attribute.nullIf && attribute.nullIf.includes(value))
return null;
const dateMoment = moment(value, attribute.dateFormat);
if (!dateMoment.isValid())
throw `Value "${value}", is not a valid Date for the attribute ${attribute.name} (${attribute.dateFormat}). line number ${lineNumber}.`;
return dateMoment.toDate();
}
function parseString(value, attribute, lineNumber) {
const convertedValue = value.trim();
if (convertedValue == '') return null;
return convertedValue;
}
function parseInteger(value, attribute, lineNumber) {
if (value && isNaN(value))
throw `Value "${value}", is not a valid Number for the attribute ${attribute.name}. line number ${lineNumber}.`;
const convertedValue = parseInt(value);
if (isNaN(convertedValue))
return null;
return convertedValue;
}
function isLineHasData(line) {
if (!line) return false;
return line.trim() != '';
}
function checkFileIsValid(lines) {
if (!lines || (lines.length === 1 && lines[0] === ''))
throw Error('file has no lines');
}
function isLineMappingValid(lineMapping, discriminator, lineNumber) {
if (!lineMapping || lineMapping.length == 0) {
console.log(`missing lineMapping for discriminator "${discriminator}". Line #${lineNumber} IGNORED`);
return false;
}
return true;
}
function getDiscriminator (line, fileMapping, lineNumber) {
const discriminator = line.substr(fileMapping.discriminatorInitialPosition, fileMapping.discriminatorInitialPosition + fileMapping.discriminatorLength)
if (!discriminator) { throw new Error(`could not get discriminator at position ${fileMapping.discriminatorInitialPosition}(${fileMapping.discriminatorLength}). line number ${lineNumber}.`) }
return discriminator;
}
function checkRequiredIsValid(attribute, value, lineNumber) {
if (attribute.required && (!value && value != 0) )
throw `${attribute.name} is required but has no value. line number ${lineNumber}.`;
}
function checkMappingIsValid(attribute) {
if (!attribute)
throw 'missing mapping attribute';
if (!attribute.name)
throw 'missing mapping attribute: name';
if (!attribute.initialPosition && attribute.initialPosition != 0 && attribute.type != 'parent') //ZERO is valid
throw 'missing mapping attribute: initialPosition';
if (!attribute.length && attribute.type != 'parent')
throw 'missing mapping attribute: length';
}
module.exports = {
checkFileIsValid,
getDiscriminator,
isLineMappingValid,
checkMappingIsValid,
checkRequiredIsValid,
getObjectFromLine,
getObjectsFromFile: getObjectsFromFile,
isLineHasData: isLineHasData,
parseString: parseString,
parseInteger: parseInteger,
parseDate: parseDate,
};