vo 변환기 vo <=> crypto-targets.json
generator.js
--------------------------------
import fs from 'fs';
import path from 'path';
const DEFAULT_DEST_COLUMN_KEYS = [
'encColumn',
'encryptColumn',
'encryptedColumn',
'cryptoColumn',
'destColumn',
'hashColumn'
];
function readJson(filePath) {
const raw = fs.readFileSync(filePath, 'utf8').replace(/^\uFEFF/, '');
return JSON.parse(raw);
}
function requireString(target, key, index) {
const value = target[key];
if (typeof value !== 'string' || value.trim() === '') {
throw new Error(`Target #${index} is missing "${key}".`);
}
return value.trim();
}
export function getOptionalString(target, key) {
const value = target[key];
return typeof value === 'string' && value.trim() !== '' ? value.trim() : '';
}
function findDestColumn(target, index, destColumnKeys) {
for (const key of destColumnKeys) {
const value = getOptionalString(target, key);
if (value) {
return value;
}
}
throw new Error(
`Target #${index} is missing destination column. Expected one of: ${destColumnKeys.join(', ')}.`
);
}
function groupTargets(targets, options = {}) {
const destColumnKeys = options.destColumnKeys || DEFAULT_DEST_COLUMN_KEYS;
const groups = [];
const groupByTableName = new Map();
targets.forEach((target, offset) => {
const sourceNo = offset + 1;
if (options.filter && !options.filter(target, sourceNo)) {
return;
}
const tableName = requireString(target, 'tableName', sourceNo);
const plainColumn = requireString(target, 'plainColumn', sourceNo);
const cryptoType = requireString(target, 'cryptoType', sourceNo);
const destColumn = findDestColumn(target, sourceNo, destColumnKeys);
if (!groupByTableName.has(tableName)) {
const group = {
tableName,
sourceNos: [],
plainColumns: [],
destColumns: [],
cryptoTypes: []
};
groupByTableName.set(tableName, group);
groups.push(group);
}
const group = groupByTableName.get(tableName);
group.sourceNos.push(sourceNo);
group.plainColumns.push(plainColumn);
group.destColumns.push(destColumn);
group.cryptoTypes.push(cryptoType);
});
return groups;
}
function quoteJavaString(value) {
return `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
}
function formatArrayDeclaration(name, values, comments, options = {}) {
const lines = [];
if (options.annotation) {
lines.push(options.annotation);
}
lines.push(`private String[] ${name} = {`);
values.forEach((value, index) => {
const comma = index === values.length - 1 ? '' : ',';
lines.push(` ${quoteJavaString(value)}${comma}//${comments[index]}`);
});
lines.push('};');
return lines.join('\n');
}
function buildOutput(groups) {
const comments = groups.map((group) => group.sourceNos.join(','));
return [
formatArrayDeclaration('tableLists', groups.map((group) => group.tableName), comments),
'',
formatArrayDeclaration(
'srcColLists',
groups.map((group) => group.plainColumns.join(',')),
comments,
{ annotation: '@Override' }
),
'',
formatArrayDeclaration('destColLists', groups.map((group) => group.destColumns.join(',')), comments),
'',
formatArrayDeclaration('typeLists', groups.map((group) => group.cryptoTypes.join(',')), comments),
''
].join('\n');
}
export function generate(options) {
const inputPath = path.resolve(process.cwd(), options.inputPath);
const outputPath = path.resolve(process.cwd(), options.outputPath);
const targets = readJson(inputPath);
if (!Array.isArray(targets)) {
throw new Error(`Input JSON must be an array: ${inputPath}`);
}
const output = buildOutput(groupTargets(targets, options));
fs.writeFileSync(outputPath, output, 'utf8');
return outputPath;
}
------------------------------------
index.hash.js
------------------------------
#!/usr/bin/env node
import { fileURLToPath } from 'url';
import { generate, getOptionalString } from './generator.js';
const DEFAULT_SQL_QUERY_XML_PATH = fileURLToPath(new URL('./sqlquery.xml', import.meta.url));
function printUsage() {
console.log([
'Usage:',
' node vogen/index.hash.js [crypto-targets-json-path] [output-hash-txt-path] [sqlquery-xml-path]',
'',
'Defaults:',
' input : ./crypto-targets.json',
' output: ./output.hash.txt',
' sql : ./vogen/sqlquery.xml'
].join('\n'));
}
function main() {
const args = process.argv.slice(2);
if (args.includes('-h') || args.includes('--help')) {
printUsage();
return;
}
const result = generate({
inputPath: args[0] || 'crypto-targets.json',
outputPath: args[1] || 'output.hash.txt',
sqlQueryXmlPath: args[2] || DEFAULT_SQL_QUERY_XML_PATH,
destColumnKeys: ['hashColumn'],
renumberSourceNosByOutput: true,
filter: (target) => Boolean(getOptionalString(target, 'hashColumn'))
});
console.log(`Generated ${result.outputPath}`);
console.log(`SQL query XML: ${result.sqlQueryXmlPath}`);
console.log(`Table groups: ${result.groupCount}`);
}
try {
main();
} catch (error) {
console.error(error.message);
process.exit(1);
}
-------------------------------------------
index.js
#!/usr/bin/env node
import { generate } from './generator.js';
function printUsage() {
console.log([
'Usage:',
' node vogen/index.js [crypto-targets-json-path] [output-txt-path] [sqlquery-xml-path]',
'',
'Defaults:',
' input : ./crypto-targets.json',
' output: ./output.txt',
' sql : ./vogen/sqlquery.xml'
].join('\n'));
}
function main() {
const args = process.argv.slice(2);
if (args.includes('-h') || args.includes('--help')) {
printUsage();
return;
}
const outputPath = generate({
inputPath: args[0] || 'crypto-targets.json',
outputPath: args[1] || 'output.txt',
sqlQueryXmlPath: args[2] ||"sqlquery.xml"
});
console.log(`Generated ${outputPath}`);
}
try {
main();
} catch (error) {
console.error(error.message);
process.exit(1);
}
------------------------
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);
}
----------------------------------------------
package.json
{
"type": "module"
}
-----------------------------------------------
sqlquery.xml
댓글
댓글 쓰기