java2js.js
#!/usr/bin/env node
import fs from 'fs';
import path from 'path';
const ARRAY_ALIASES = {
table: ['tableLists'],
src: ['srcColLists'],
dest: ['destColLists', 'destColList'],
type: ['typeLists'],
tableHash: ['tableLists_hash'],
srcHash: ['srcColLists_hash'],
destHash: ['destColLists_hash', 'destColList_hash'],
typeHash: ['typeLists_hash']
};
function printUsage() {
console.log([
'Usage:',
' node vogen/java2js.js [java-array-text-path] [crypto-targets-json-path]',
'',
'Defaults:',
' input : ./outall.txt',
' output: ./crypto-targets.json'
].join('\n'));
}
function readText(filePath) {
return fs.readFileSync(filePath, 'utf8').replace(/^\uFEFF/, '');
}
function parseJavaStringArrays(text) {
const arrays = new Map();
const pattern =
/(?:@\w+(?:\([^)]*\))?\s*)*(?:(?:private|protected|public)\s+)?String\s*\[\]\s+([A-Za-z_$][\w$]*)\s*=\s*\{([\s\S]*?)\}\s*;/g;
let match;
while ((match = pattern.exec(text)) !== null) {
const [, name, body] = match;
arrays.set(name, parseJavaStringValues(body));
}
return arrays;
}
function parseJavaStringValues(body) {
const values = [];
const pattern = /"((?:\\.|[^"\\])*)"/g;
let match;
while ((match = pattern.exec(body)) !== null) {
values.push(unescapeJavaString(match[1]));
}
return values;
}
function unescapeJavaString(value) {
return value
.replace(/\\n/g, '\n')
.replace(/\\r/g, '\r')
.replace(/\\t/g, '\t')
.replace(/\\"/g, '"')
.replace(/\\\\/g, '\\');
}
function getArray(arrays, aliases, required) {
for (const alias of aliases) {
if (arrays.has(alias)) {
return arrays.get(alias);
}
}
if (required) {
throw new Error(`Missing array variable. Expected one of: ${aliases.join(', ')}`);
}
return [];
}
function splitCsvValue(value) {
if (typeof value !== 'string' || value.trim() === '') {
return [];
}
return value.split(',').map((item) => item.trim());
}
function requireAlignedLength(tableName, label, expectedLength, values, rowNo) {
if (values.length !== expectedLength) {
throw new Error(
`${label} length mismatch at row #${rowNo} (${tableName}). Expected ${expectedLength}, got ${values.length}.`
);
}
}
function buildTargetsFromArrays(tables, srcRows, destRows, typeRows, options) {
const targets = [];
tables.forEach((tableName, index) => {
const rowNo = index + 1;
const srcColumns = splitCsvValue(srcRows[index] || '');
const destColumns = splitCsvValue(destRows[index] || '');
const cryptoTypes = splitCsvValue(typeRows[index] || '');
requireAlignedLength(tableName, `${options.destLabel} columns`, srcColumns.length, destColumns, rowNo);
requireAlignedLength(tableName, `${options.typeLabel} values`, srcColumns.length, cryptoTypes, rowNo);
srcColumns.forEach((plainColumn, columnIndex) => {
targets.push({
tableName,
plainColumn,
cryptoType: cryptoTypes[columnIndex],
[options.destKey]: destColumns[columnIndex]
});
});
});
return targets;
}
function mergeHashTargets(targets, hashTargets) {
const usedTargetIndexes = new Set();
for (const hashTarget of hashTargets) {
let targetIndex = -1;
for (let index = targets.length - 1; index >= 0; index -= 1) {
const target = targets[index];
if (
!usedTargetIndexes.has(index) &&
target.tableName === hashTarget.tableName &&
target.plainColumn === hashTarget.plainColumn &&
!target.hashColumn
) {
targetIndex = index;
break;
}
}
if (targetIndex >= 0) {
targets[targetIndex].hashColumn = hashTarget.hashColumn;
usedTargetIndexes.add(targetIndex);
continue;
}
targets.push({
tableName: hashTarget.tableName,
plainColumn: hashTarget.plainColumn,
cryptoType: hashTarget.cryptoType,
hashColumn: hashTarget.hashColumn
});
}
}
function normalizeTargets(targets) {
return targets.map((target) => ({
tableName: target.tableName,
plainColumn: target.plainColumn,
cryptoType: target.cryptoType,
encColumn: target.encColumn || '',
hashColumn: target.hashColumn || ''
}));
}
function convertJavaArraysToTargets(text) {
const arrays = parseJavaStringArrays(text);
const tables = getArray(arrays, ARRAY_ALIASES.table, true);
const srcRows = getArray(arrays, ARRAY_ALIASES.src, true);
const destRows = getArray(arrays, ARRAY_ALIASES.dest, true);
const typeRows = getArray(arrays, ARRAY_ALIASES.type, true);
const targets = buildTargetsFromArrays(tables, srcRows, destRows, typeRows, {
destKey: 'encColumn',
destLabel: 'destination',
typeLabel: 'cryptoType'
});
const hashTables = getArray(arrays, ARRAY_ALIASES.tableHash, false);
const hashSrcRows = getArray(arrays, ARRAY_ALIASES.srcHash, false);
const hashDestRows = getArray(arrays, ARRAY_ALIASES.destHash, false);
const hashTypeRows = getArray(arrays, ARRAY_ALIASES.typeHash, false);
if (hashTables.length > 0) {
const hashTargets = buildTargetsFromArrays(hashTables, hashSrcRows, hashDestRows, hashTypeRows, {
destKey: 'hashColumn',
destLabel: 'hash destination',
typeLabel: 'hash cryptoType'
});
mergeHashTargets(targets, hashTargets);
}
return normalizeTargets(targets);
}
function main() {
const args = process.argv.slice(2);
if (args.includes('-h') || args.includes('--help')) {
printUsage();
return;
}
const inputPath = path.resolve(process.cwd(), args[0] || 'outall.txt');
const outputPath = path.resolve(process.cwd(), args[1] || 'crypto-targets.json');
const targets = convertJavaArraysToTargets(readText(inputPath));
fs.writeFileSync(outputPath, `${JSON.stringify(targets, null, 2)}\n`, 'utf8');
console.log(`Generated ${outputPath}`);
console.log(`Target count: ${targets.length}`);
}
try {
main();
} catch (error) {
console.error(error.message);
process.exit(1);
}
댓글
댓글 쓰기