I tried to implement bubble sort in BICMD by phoenetic string comparison turned out not to be supported
But for my use case a method to group a 2D array of string by first key would do fine
/* ----------------------------------------------------------------
Peter Lykkegaard, 25 Oct 2025
-----------------------------
Name: groupByArray
Description
This code processes a 2D array "pvData$[][]" by grouping rows based on the value in the first column.
It avoids reprocessing rows by marking them as "found" in "lvProcessedRows$[]".
The grouped rows are stored in "lvGroupedData$[][]", preserving all column data.
The algorithm uses nested loops to compare and group rows with matching keys.
Parameters
pvData$[][] - 2D array which should be grouped
Output
$[][] - 2D array grouped by keyword
-------------------------------------------------------------- */
local
lvTotalRows%, // Total number of rows in pvData$
lvColumnIndex%, // Index for iterating through columns
lvNewRowIndex%, // Index for inserting into lvGroupedData$
lvKeyIndex%, // Index for keyword for grouping
lvTotalColumns%, // Total number of columns in pvData$
lvCurrentRow%, // Current row being processed
lvCurrentKey$, // Key value from the first column of the current row
lvCheckRow%, // Row index used to check for matching keys
lvProcessedRows$[], // Array to track which rows have been processed
lvGroupedData$[][], // Output array to store grouped rows
lvFound$; // Marker string to indicate a row has been processed
copy 0 to lvKeyIndex%;
copy 0 to lvCurrentRow%;
copy 0 to lvNewRowIndex%;
copy "found" to lvFound$;
// Number of rows
copy getSize(pvData$) to lvTotalRows%;
// Depth / number of columns
copy getSize(pvData$[1]) to lvTotalColumns%;
// Outer loop: iterate through the array
for lvCurrentRow% = 0 to lvTotalRows% - 1
if (lvProcessedRows$[lvCurrentRow%] &!= lvFound$)
copy pvData$[lvCurrentRow%][lvKeyIndex%] to lvCurrentKey$;
// Inner loop: check all rows from current to end for matching keys
for lvCheckRow% = lvCurrentRow% to lvTotalRows% - 1
if (pvData$[lvCheckRow%][lvKeyIndex%] &= lvCurrentKey$)
traceln("lvCurrentKey: " & lvCurrentKey$);
for lvColumnIndex% = 0 TO lvTotalColumns% - 1
copy pvData$[lvCheckRow%][lvColumnIndex%] to lvGroupedData$[lvNewRowIndex%][lvColumnIndex%];
next
// Mark the row as processed and increment the index
// to examine the next row for grouping
copy lvFound$ to lvProcessedRows$[lvCheckRow%];
copy lvNewRowIndex% + 1 to lvNewRowIndex%;
endif
next
endif
next
// return array grouped by first given key
exitProc(lvGroupedData$);
Easily converted to NET 9 C# 12 using CoPilot / ChatGPT5, use what data content you'd prefer and run some iterations in a Console App to check program flow
For mappings created in the Business Integration Converter (BIC) at times you need local or global procedures following the DRY principles in coding (Don't repeat yourself)
Maybe you need to enhance the BIC script by adding some inline Java code like shown in eg the unescapeHTML procedure found on these pages
It can be parameters in procedure signature or local variables, in the unescapeHTML procedure we can find this code
// Procedure parameter used in java code
String source = _StrVar_PSOURCE.getString();
You can find a lot of examples of this style of Java code in your build folders, in <source>\<project>\build\test\com\seeburger\jucon\mapping you can examine the Java files from your recent build
An example
// Java code example assigning an IDOC numer to a numeric variable
_NumVar_IDOC_NUMBER.setNum(stdin.getField("THIS:DOCNUM"));
Another small example which uses Java variables described is the getUUID method
You can find some examples on this site: Methods using inline Java
An utility to add leading zeros up to given length to a numeric string
Please note Alphanumeric string will be left untouched
A procedure to use in Seeburger BIC Mapping Designer
It will extend your library for string handling
/* -----------------------------
Peter Lykkegaard, 22 mar 2019
-----------------------------
Method
zeroFill
Parameters
value$: String to prefix with zeros
Num%: Number of characters, length of string after prefixzing
Returns
$
Description
If the parameter value is a numeric value and
the length of the string does not exceed length of the value
*/
if (isNumeric(value$) && len(value$) < num%)
copy lfill(value$, "0", num%) to value$;
endif
exitProc(value$);
Split text on right most space before limit is reached
Use to split text on several lines in receiving document, eg edifact LIN-IMD-C273 has several 7008 text element
// -----------------------------
// Peter Lykkegaard, 22 mar 2019
// -----------------------------
// Split long note on right most space before limit is reached
// TODO! Check parameters if they are of valid type/content
//
// Name: splitNoteBySpace
// Description: Method to split a given string by latest space before length limit
// Parameters
// input$, alphanumerical / String which needs to be split
// max$, alphanumerical / Max characters on each line
// Output, alphanumeric / array / Array of strings to return
local lvOutput$[];
#importJavaStart
import java.util.regex.Matcher;
import java.util.regex.Pattern;
#importJavaEnd
#javastart
String input = _StrVar_PINPUT.getString();
int max = (int)_NumVar_PMAX.getNum();
int len = input.length();
String regex = "(.{1," + max + "})(?:\\s|$)";
Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
Matcher matcher = pattern.matcher(input);
_StrVar_LVOUTPUT.getJuVar(0, 2).setString(input);
if (len > max)
{
int idx = 0; // Entries in output
while (matcher.find()) {
for (int i = 1; i <= matcher.groupCount(); i++) {
_StrVar_LVOUTPUT.getJuVar(idx, 2).setString(matcher.group(i).toString());
}
idx++;
}
}
#javaEnd
exitProc(lvOutput$);
An utility to decode or unescape HTML characters in XML (EDI) documents
This is a procedure to use in Seeburger BIC Mapping Designer
It will extend your library for string handling
/* -----------------------------
Peter Lykkegaard, 25 apr 2023
-----------------------------
procedure unescapeHTML
Parameters:
Source / String, alphanumeric
Output
String, alphanumericString
Adapted from How to Unescape HTML in Java using Plain Java
https://howtodoinjava.com/java/string/unescape-html-to-string/
----------------------------- */
local lvOutput$;
#importJavaStart
import java.util.HashMap;
#importJavaEnd
// Save source in case changes are not needed
copy pSource$ to lvOutput$;
// Check for any ampersand / & character
if (containsSubstring(pSource$, "&") != 0)
if (containsSubstring(pSource$, "&") != 0)
// HTML decode ampersand / &
copy replaceAll(pSource$, "&", "&") to pSource$;
endif
#javastart
int i, j;
boolean continueLoop;
int skip = 0;
HashMap<String, String> htmlEntities = new HashMap<String, String>();
htmlEntities.put("<", "<");
htmlEntities.put(">", ">");
htmlEntities.put("&", "&");
htmlEntities.put(""", "\"");
htmlEntities.put(" ", " ");
htmlEntities.put("©", "\u00a9");
htmlEntities.put("®", "\u00ae");
htmlEntities.put("€", "\u20a0");
htmlEntities.put("Å", "Å");
htmlEntities.put("Æ", "Æ");
htmlEntities.put("Ø", "Ø");
htmlEntities.put("å", "å");
htmlEntities.put("æ", "æ");
htmlEntities.put("ø", "ø");
String source = _StrVar_PSOURCE.getString();
do {
continueLoop = false;
i = source.indexOf("&", skip);
if (i > -1) {
j = source.indexOf(";", i);
if (j > i) {
String entityToLookFor = source.substring(i, j + 1);
String value = (String) htmlEntities.get(entityToLookFor);
if (value != null) {
source = source.substring(0, i) + value + source.substring(j + 1);
continueLoop = true;
} else if (value == null) {
skip = i + 1;
continueLoop = true;
}
}
}
} while (continueLoop);
_StrVar_LVOUTPUT.setString(source);
#javaend
endif
exitProc(lvOutput$);