Deep analysis of core data access, encryption, calibration processing, and session management
File: src/ddec-web/src/main/java/com/detroitdiesel/ddec/dao/DdecCoreDao.java
Primary DAO translating IMS DLI operations to SQL. All database access flows through this class.
| IMS Call | Method | SQL Equivalent | Lock Behavior |
|---|---|---|---|
| GU | doGu() |
SELECT TOP 1 ... WHERE key = ? |
None |
| GHU | doGu(lock=true) |
SELECT TOP 1 ... WITH(XLOCK, HOLDLOCK, ROWLOCK, NOWAIT) |
Row lock |
| GN | doGnp() |
SELECT TOP 1 ... WHERE key > ? ORDER BY key |
None |
| GNP | doGnp() |
SELECT TOP 1 ... WHERE parent_key = ? AND key > ? |
None |
| GHNP | doGnp(lock=true) |
Same + lock hints | Row lock |
| ISRT | doIsrt() |
INSERT INTO ... VALUES (?) |
Implicit |
| REPL | doRepl() |
UPDATE ... SET ... WHERE pk = ? |
Implicit |
| DLET | doDlet() |
DELETE FROM ... WHERE pk = ? |
Implicit |
Uses CaseUtils.toCamelCase(columnName, false, '_') from Apache Commons Text:
FIRST_NAME -> Java: firstNameUSER_ID_CODE -> Java: userIdCodeMaps via Java reflection at runtime (line 222-223).
| Segment | Routes To |
|---|---|
| R24yunit | BILLING_EXTRACT_DDEC3 |
| R24y5unt | BILLING_EXTRACT_DDEC5 |
| CUST01 | Special doGuForCust01() path |
| Logical DBs | doGuForLogicalDB() path |
Queries INFORMATION_SCHEMA.COLUMNS dynamically to discover:
ConcurrentHashMap| SQL Type | Java Type | Notes |
|---|---|---|
| VARCHAR, CHAR | String / LegacyData | |
| DECIMAL | BigDecimal / LegacyData | |
| VARBINARY | byte[] / LegacyData | ISO-8859-1 encoding |
File: src/ddec-web/src/main/java/com/detroitdiesel/ddec/engineering/util/EncodingUtil.java
Symmetric XOR-based encryption matching legacy C++ DRS Client.
Two-step process with fixed keyMask=63 (0x3F):
Encryption (arrangeByte first, then applyKey):
1. Nibble Swap: lower 4 bits << 4 | upper 4 bits >> 4
2. XOR with 0x3F
Decryption (applyKey first, then arrangeByte):
1. XOR with 0x3F
2. Nibble Swap: lower 4 bits << 4 | upper 4 bits >> 4
public static int ArrangeByte(int byteIn) {
int saveByte = (byteIn & 0x0F) << 4;
int tempByte = (byteIn >> 4);
return (tempByte | saveByte) & 0xFF;
}
public static int ApplyKey(int byteIn) {
byteIn ^= 63;
return byteIn & 0xFF;
}
public static int[] Decrypt(byte[] data) {
var result = new int[data.Length];
for (int i = 0; i < data.Length; i++) {
int b = data[i] & 0xFF;
b = ApplyKey(b);
b = ArrangeByte(b);
result[i] = b;
}
return result;
}
Migration complexity: LOW - direct bitwise operation translation.
File: src/ddec-web/src/main/java/com/detroitdiesel/ddec/engineering/V2DdecCalibrationSplitter.java
Splits download.dat files into individual calibration records.
| Code | Type | Format | Compression | Encryption |
|---|---|---|---|---|
| D01-D04 | DDEC II Master/Receiver | Header + Binary | None | None |
| D08 | DDEC III/IV Base Cal | Binary | PKWARE DCL Implode | XOR |
| D09 | Screen Message | ASCII | None | None |
| D11-D13 | DDEC III Prod Units | ASCII | None | None |
| D14-D16 | DDEC III Test Cals | Binary | PKWARE DCL Implode | XOR |
| D20 | Split Base Cal | Binary | None | XOR |
| D28 | Split Historical | Binary | None | XOR |
| D51 | DDEC V Prod Unit | ASCII | None | None |
| D54 | DDEC V Test Cal | Binary | PKWARE DCL Implode | XOR |
| D58 | DDEC V Base Cal | Binary | PKWARE DCL Implode | XOR |
| D88 | Historical Base Cal | Binary | PKWARE DCL Implode | XOR |
Cp037 (EBCDIC-US) for header reading and offset discoveryEncoding.GetEncoding("IBM037") (requires System.Text.Encoding.CodePages NuGet)Migration complexity: MEDIUM-HIGH - XCompress native library integration is the main challenge.
File: src/ddec-web/src/main/java/com/detroitdiesel/ddec/engineering/util/R24kd500shDownloadRequestBuilder.java
| Parameter | Function |
|---|---|
| 100 | Download Engine Serial Number |
| 200 | Download Calibration Without History |
| 600 | Download Calibration With History |
Process:
request0.file: {calName}{userId} 9999999999history.file: H99 {userId}9999999999{timestamp}{userId}500.sh bash scriptdownload.file responseSame architecture but accepts user-uploaded request0.file and runs r24kd505.sh batch job.
Migration complexity: MEDIUM - need SSH.NET for SFTP, bash template generation.
File: src/ddec-web/src/main/java/com/detroitdiesel/ddec/common/R35sspdb.java
Session-scoped temporary storage system with IMS semantics.
| Code | Function | Description |
|---|---|---|
| U | UPDATE | Insert or replace user data |
| R | RETRIEVE | Read user data |
| C | COPY | Read user data (same as R) |
| D | DELETE | Remove user data |
SDSPROOT (root): LTRMTRAN key, user ID, timestamps, up to 6000 bytes app data
SDSPCONT (continuation): Up to 8 children x 18000 bytes for large data
| Data Size | Segments Used |
|---|---|
| 0-6000 bytes | Root only |
| 6001-12000 | Root + 1 SDSPCONT |
| 12001-18000 | Root + 2 SDSPCONT |
| 18001-24000 | Root + 3 SDSPCONT |
| >24000 | Truncated (return code 16) |
| Code | Meaning |
|---|---|
| 0 | Success |
| 4 | Data timed out (>2 hours) |
| 8 | Data in use by another user |
| 12 | Data not found |
| 16 | Data > 24000 bytes (truncated) |
| 20 | Invalid function code |
| 24 | Invalid data length |
| 100-164 | Various IMS errors |
Migration complexity: HIGH - complex validation, date arithmetic, multi-user isolation.
File: src/ddec-web/src/main/java/com/detroitdiesel/ddec/utils/dao/R35dpspRepository.java
R35DPSP with LTRMTRAN (key), SDSPROOT (VARBINARY), SDSPCONT (VARBINARY)StringUtils.compress() before storageFile: src/ddec-web/src/main/java/com/detroitdiesel/ddec/support/ImsAccessModel.java
Generic interface defining data access patterns. Key methods:
| Method | Returns | Purpose |
|---|---|---|
getFormatType() |
Class | COBOL-generated Java class |
getTableName() |
String | SQL table name (from @Table) |
getKeyColumnNames() |
List | Primary key columns |
getColumnTypes() |
Map<String,Integer> | SQL type codes |
getColumnName2JavaField() |
Map<String,Field> | Column-to-field mapping |
columnName2JavaName() |
String | SNAKE_CASE to camelCase conversion |
Column naming: WordUtils.capitalize(col, '_').replace("_", "") then lowercase first char.
File: src/ddec-web/src/main/java/com/detroitdiesel/ddec/utils/DdecFunctions.java
| Method | Legacy COBOL | Purpose |
|---|---|---|
checkpoint() |
CHKPTID | Checkpoint generation |
forceFail() |
ABEND | Force program abend |
callSpadbsub() |
R35SSPDB/SPADBSUB | Scratch pad DB access |
handleError() |
DFS0AER | IMS error handling |
callWaasabnd() |
WAASABND | WAAS abend handler |
callWaasdate() |
WAASDATE | Date conversion YYMMDD->MMDDYYYY |
callWaasdatr() |
WAASDATR | Date/time retrieval |
callGredate() |
GREDATE | Gregorian date processing |
Migration complexity: LOW - thin wrappers that can be replaced with direct C# service calls.
| Component | Complexity | Key Challenge |
|---|---|---|
| DdecCoreDao | MEDIUM-HIGH | Dynamic metadata, lock hints, reflection |
| EncodingUtil | LOW | Direct bitwise translation |
| CalibrationSplitter | MEDIUM-HIGH | XCompress/PKWARE DCL, EBCDIC, streaming |
| Download/Release Builders | MEDIUM | SFTP, bash templates, polling |
| R35sspdb (SPDB) | HIGH | Validation logic, date math, isolation |
| R35dpspRepository | MEDIUM | Compression, VARBINARY, caching |
| ImsAccessModel | MEDIUM | Reflection, metadata caching |
| DdecFunctions | LOW | Thin wrappers |
DdecCoreDao
+-- ImsAccessModel (interface)
+-- TableDetails (metadata)
+-- Spring JdbcTemplate -> ADO.NET/Dapper
V2DdecCalibrationSplitter
+-- EncodingUtil (XOR crypto)
+-- JavaToC (XCompress wrapper)
+-- FileUtil
R24kd500sh / R24kd505sh
+-- SftpClient -> SSH.NET
+-- EngineeringBatchJobResponse
SpdbController -> R35dpspRepository -> JdbcTemplate
R35sspdb -> IMS DLI Module -> DdecCoreDao
DdecFunctions
+-- CheckpointGenerator
+-- R35sspdb
+-- WaasFunctions
+-- Gredate