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

댓글

이 블로그의 인기 게시물

food eff privacy

판다 스픽 , 개인정보 처리방침 , Panda Speak Privacy Term

판다 수학 개인정보 처리방침 , Privacy , Panda Math