<commit_before><!DOCTYPE>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Copybook to Java Class Converter</title>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/codemirror.css" />
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/theme/twilight.css" />

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/codemirror.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/mode/clike/clike.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/addon/edit/matchbrackets.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/addon/selection/active-line.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/mode/cobol/cobol.js"></script>
</head>
<body>

<div style="width: 100%">
    <div style="float: left;">
        <p>Copybook:</p>
        <textarea id="copybook" name="copybook" cols="80" rows="50">
                        * Comment stuff
            01 SUBFIELD.  * Lineending comment
                02 COUNT PIC 9(2).
            * Comment stuff ...
            01 RESULT. 
                                                        * Comment stuff
                02 FIELDS OCCURS 0 TO 10 TIMES PIC X(8) DEPENDING ON
                                                        COUNT
                                                        IN SUBFIELD. 
            * Comment stuff
            01 SUBFIELD2. 
                02 COUNT1 PIC 9(2).
                02 COUNT2 PIC 9(2).
            01 FIELD PIC X(10).
            01 STUFFS OCCURS 10 TIMES.
                02 STUFF PIC X(8).
        </textarea>
    </div>

    <div style="float: left;">
        <p>Java Class:</p>

        <div>
            <div>
                <span>Accessors</span>
                <select id="accessorpattern">
                    <option value="none">None</option>
                    <option value="getset">Getter/setter</option>
                    <option value="lombokdata">Lombok Data</option>
                </select>
                <span>Charset</span>
                <input id="charset" type="text" value="UTF-8">
            </div>
        </div>

        <textarea id="javaclass" name="javaclass"></textarea>
    </div>
    <br style="clear: left;"/>
</div>

<script type="application/javascript">

    function convertCopybook (str, accessor, charset) {
        var fields = [];

        (function parseCopybook(copybook) {
            var last = [{ level: 0, fields: fields }];
            copybook.replace(/\*[^\n]*/g, '').match(/[\s\S]+?\.[ \t]*\n/g).forEach(function(line, i) {
                // Remove comments, newlines, extra space and trim
                line = line.replace(/\s*\*[^\n]+\n/g, '').replace(/\n/g, ' ').replace(/\s{2,}/g, ' ').replace(/^\s+/, '').replace(/\s+$/, '');

                if(match = line.match(/^\s*(\d+)\s+([^\s]+)((?:\s+OCCURS\s+\d+(?:\s+TO\s+\d+)?\s+TIMES)|(?:\s+REDEFINES\s+[^\s]+))?(\s+PIC\s+[^\s]+)?(\s+DEPENDING\s+ON\s+[^\s]+(?:\s+IN\s+[^\s+]+)?)?\s*\.\s*$/)) {
                    var level = parseInt(match[1]);
                    var name = match[2];

                    var current = {
                        name: name,
                        level: level,
                        lines: [ line ],
                        fields: [],
                        type: ''
                    };

                    if (match[4] != undefined) {
                        if(pic_match = match[4].match(/^\s*PIC\s+(S)?(X+|9+)(?:\((\d+)\))?(?:V(9+)(?:\((\d+)\))?)?\s*$/)) {
                            var signed = pic_match[1] !== undefined ? true : false;
                            var main_type = pic_match[2];
                            var main_size = pic_match[3] !== undefined ? parseInt(pic_match[3]) : main_type.length;
                            var decimal_type = pic_match[4] !== undefined ?  match[4] : "";
                            var decimal_size = pic_match[5] != undefined ? parseInt(pic_match[5]) : decimal_type.length;

                            if (main_type.indexOf("X") === 0) {
                                current['type'] = "String";

                            } else if (main_type.indexOf("9") === 0 && decimal_type !== '') { // Signed or unsigned decimal type
                                current['type'] = "BigDecimal";

                            } else if (main_type.indexOf("9") === 0 && decimal_type === '') { // Signed or unsigned integer type
                                if(main_size < 10) {
                                    current['type'] = "int";

                                } else {
                                    current['type'] = "BigInteger";
                                }
                            }

                        }
                    }

                    if(match[3] != undefined) {
                        if (occurs_match = match[3].match(/^\s*OCCURS\s+(?:(\d+)\s+TO\s+)?(\d+)\s+TIMES\s*$/)) {
                            current['type'] += "[]";

                        } else if (redefines_match = match[3].match(/\s*REDEFINES\s+([^\s]+)\s*/)) {

                        }
                    }

                    if(match[5] != undefined) {
                        if(depending_match = match[5].match(/^\s*DEPENDING\s+ON\s+([^\s]+)(?:\s+IN\s+([^\s]+))?\s*$/)) {

                        }
                    }

                    while(last.length > 0) {
                        if(level > last[last.length - 1]['level']) {
                            last[last.length - 1]['fields'].push(current);
                            last.push(current);
                            break;

                        } else if (level === last[last.length - 1]['level']) {
                            last[last.length - 2]['fields'].push(current);
                            last[last.length - 1] = current;
                            break;

                        } else {
                            last.pop();
                        }
                    }
                }
            });
        }(str));

        // Simplify structure
        (function traverse(fields, parent) {
            var types = 0;
            fields.forEach(function(field, i){
                if(field["type"] && field["type"] !== '[]') {
                    types++;

                } else if (field["fields"].length > 0) {
                    types += traverse(field["fields"], field);
                }
            });

            if(types < 2) {
                fields.forEach(function(field, i) {
                    parent["name"] = parent["name"] + "." + field["name"];
                    parent["lines"] = parent["lines"].concat(field["lines"]);
                    parent["type"] = field["type"] ? field["type"] + (parent["type"] ? parent["type"] : '') : parent["type"];
                });
                parent["fields"] = [];
            }

            return types;
        })(fields, fields);

        // Generate java class
        var classes = [];
        (function traverse(classname, fields) {
            var current = "";
            current += "@CopyBook(charset = \""+ charset +"\")\n";
            current += (accessor === "lombokdata" ? "@Data " : "") + "class "+ classname + " {\n";

            fields.forEach(function(field, i){
                var java_name = toCamelCase(field["name"].replace(".", "_"));

                field["lines"].forEach(function(line, j) {
                    current += "    @CopyBookLine(\"" + line + "\")\n";
                });

                if (field["fields"].length > 0) {
                    current += "    private " + toCapitalCase(java_name) + " " + java_name + ";\n";
                    traverse(toCapitalCase(java_name), field["fields"]);

                } else {
                    current += "    private " + field["type"] + " " + java_name + ";\n";
                }

                if(fields.length -1 > i) { current += "\n"; }
            });

            if(accessor === "getset") {
                current += "\n";
                fields.forEach(function (field, i) {
                    var java_name = toCamelCase(field["name"].replace(".", "_"));
                    var java_type = field["fields"].length > 0 ? toCapitalCase(java_name) : field["type"];

                    current += "    public " + java_type + " get" + toCapitalCase(java_name) + "() {\n";
                    current += "        return this." + java_name + ";\n";
                    current += "    }\n";
                    current += "\n";
                    current += "    public void set" + toCapitalCase(java_name) + "(" + java_type + " " + java_name + ") {\n";
                    current += "        this." + java_name + " = " + java_name + ";\n";
                    current += "    }\n";

                    if(fields.length -1 > i) { current += "\n"; }
                });
            }

            current += "}\n";
            classes.push(current);
        })("RenameMeCopyBook", fields);

        return classes.join("\n");

    }

    function toCamelCase(str) {
        return str.toLocaleLowerCase().replace(/([\-_]\w)/g, function(m){ return m[1].toUpperCase(); });
    }

    function toCapitalCase(str) {
        return str.charAt(0).toUpperCase() + str.slice(1)
    }

    function updateEditor(srcEditor, dstEditor) {
        var accessorSelector = document.getElementById("accessorpattern");
        var accessor = accessorSelector.options[accessorSelector.selectedIndex].value;
        var charset = document.getElementById("charset").value;
        var src = srcEditor.getValue();
        var dst = convertCopybook(src, accessor, charset);
        dstEditor.setValue(dst);
        dstEditor.refresh();
    }

    $(function() {
        var javaEditor = CodeMirror.fromTextArea(document.getElementById("javaclass"), {
            lineNumbers: true,
            matchBrackets: true,
            mode: "text/x-java",
            viewportMargin: Infinity
        });
        javaEditor.setSize(null, 750);

        var cobolEditor = CodeMirror.fromTextArea(document.getElementById("copybook"), {
            lineNumbers: true,
            matchBrackets: true,
            mode: "text/x-cobol",
            viewportMargin: Infinity,
            styleActiveLine: true,
            theme : "twilight",
            showCursorWhenSelecting : true
        });

        cobolEditor.setSize(null, 750);
        cobolEditor.on("change", function (cm) {
            updateEditor(cm, javaEditor);
        });
<commit_msg>Fix regex so it also works in Nashorm and add package and import statements<commit_after><!DOCTYPE>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Copybook to Java Class Converter</title>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/codemirror.css" />
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/theme/twilight.css" />

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/codemirror.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/mode/clike/clike.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/addon/edit/matchbrackets.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/addon/selection/active-line.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.8.0/mode/cobol/cobol.js"></script>
</head>
<body>

<div style="width: 100%">
    <div style="float: left;">
        <p>Copybook:</p>
        <textarea id="copybook" name="copybook" cols="80" rows="50">
                        * Comment stuff
            01 SUBFIELD.  * Lineending comment
                02 COUNT PIC 9(2).
            * Comment stuff ...
            01 RESULT. 
                                                        * Comment stuff
                02 FIELDS OCCURS 0 TO 10 TIMES PIC X(8) DEPENDING ON
                                                        COUNT
                                                        IN SUBFIELD. 
            * Comment stuff
            01 SUBFIELD2. 
                02 COUNT1 PIC 9(2).
                02 COUNT2 PIC 9(2).
            01 FIELD PIC X(10).
            01 STUFFS OCCURS 10 TIMES.
                02 STUFF PIC X(8).
        </textarea>
    </div>

    <div style="float: left;">
        <p>Java Class:</p>

        <div>
            <div>
                <span>Accessors</span>
                <select id="accessorpattern">
                    <option value="none">None</option>
                    <option value="getset">Getter/setter</option>
                    <option value="lombokdata">Lombok Data</option>
                </select>
                <span>Charset</span>
                <input id="charset" type="text" value="UTF-8">
            </div>
        </div>

        <textarea id="javaclass" name="javaclass"></textarea>
    </div>
    <br style="clear: left;"/>
</div>

<script type="application/javascript">

    /*** convertCopybook start ***/
    function convertCopybook (packageName, rootClassName, str, accessor, charset) {
        var fields = [];

        (function parseCopybook(copybook) {
            var last = [{ level: 0, fields: fields }];
            copybook.replace(/\*[^\n]*/g, '').match(/[\s\S]+?\.[\s\t]*\n/g).forEach(function(line, i) {
                // Remove comments, newlines, extra space and trim
                line = line.replace(/\s*\*[^\n]+\n/g, '').replace(/\n/g, ' ').replace(/\s{2,}/g, ' ').replace(/^\s+/, '').replace(/\s+$/, '');

                if(match = line.match(/^\s*(\d+)\s+([^\s]+)((?:\s+OCCURS\s+\d+(?:\s+TO\s+\d+)?\s+TIMES)|(?:\s+REDEFINES\s+[^\s]+))?(\s+PIC\s+[^\s]+)?(\s+DEPENDING\s+ON\s+[^\s]+(?:\s+IN\s+[^\s+]+)?)?\s*\.\s*$/)) {
                    var level = parseInt(match[1]);
                    var name = match[2];

                    var current = {
                        name: name,
                        level: level,
                        lines: [ line ],
                        fields: [],
                        type: ''
                    };

                    if (match[4] != undefined) {
                        if(pic_match = match[4].match(/^\s*PIC\s+(S)?(X+|9+)(?:\((\d+)\))?(?:V(9+)(?:\((\d+)\))?)?\s*$/)) {
                            var signed = pic_match[1] !== undefined ? true : false;
                            var main_type = pic_match[2];
                            var main_size = pic_match[3] !== undefined ? parseInt(pic_match[3]) : main_type.length;
                            var decimal_type = pic_match[4] !== undefined ?  match[4] : "";
                            var decimal_size = pic_match[5] != undefined ? parseInt(pic_match[5]) : decimal_type.length;

                            if (main_type.indexOf("X") === 0) {
                                current['type'] = "String";

                            } else if (main_type.indexOf("9") === 0 && decimal_type !== '') { // Signed or unsigned decimal type
                                current['type'] = "BigDecimal";

                            } else if (main_type.indexOf("9") === 0 && decimal_type === '') { // Signed or unsigned integer type
                                if(main_size < 10) {
                                    current['type'] = "int";

                                } else {
                                    current['type'] = "BigInteger";
                                }
                            }

                        }
                    }

                    if(match[3] != undefined) {
                        if (occurs_match = match[3].match(/^\s*OCCURS\s+(?:(\d+)\s+TO\s+)?(\d+)\s+TIMES\s*$/)) {
                            current['type'] += "[]";

                        } else if (redefines_match = match[3].match(/\s*REDEFINES\s+([^\s]+)\s*/)) {

                        }
                    }

                    if(match[5] != undefined) {
                        if(depending_match = match[5].match(/^\s*DEPENDING\s+ON\s+([^\s]+)(?:\s+IN\s+([^\s]+))?\s*$/)) {

                        }
                    }

                    while(last.length > 0) {
                        if(level > last[last.length - 1]['level']) {
                            last[last.length - 1]['fields'].push(current);
                            last.push(current);
                            break;

                        } else if (level === last[last.length - 1]['level']) {
                            last[last.length - 2]['fields'].push(current);
                            last[last.length - 1] = current;
                            break;

                        } else {
                            last.pop();
                        }
                    }
                }
            });
        }(str));

        // Simplify structure
        (function traverse(fields, parent) {
            var types = 0;
            fields.forEach(function(field, i){
                if(field["type"] && field["type"] !== '[]') {
                    types++;

                } else if (field["fields"].length > 0) {
                    types += traverse(field["fields"], field);
                }
            });

            if(types < 2) {
                fields.forEach(function(field, i) {
                    parent["name"] = parent["name"] + "." + field["name"];
                    parent["lines"] = parent["lines"].concat(field["lines"]);
                    parent["type"] = field["type"] ? field["type"] + (parent["type"] ? parent["type"] : '') : parent["type"];
                });
                parent["fields"] = [];
            }

            return types;
        })(fields, fields);

        // Generate java class
        var classes = [];
        (function traverse(classname, fields) {
            var current = "";
            current += "@CopyBook(charset = \""+ charset +"\")\n";
            current += (accessor === "lombokdata" ? "@Data " : "") + "class "+ classname + " {\n";

            fields.forEach(function(field, i){
                var java_name = toCamelCase(field["name"].replace(".", "_"));

                field["lines"].forEach(function(line, j) {
                    current += "    @CopyBookLine(\"" + line + "\")\n";
                });

                if (field["fields"].length > 0) {
                    current += "    private " + toCapitalCase(java_name) + " " + java_name + ";\n";
                    traverse(toCapitalCase(java_name), field["fields"]);

                } else {
                    current += "    private " + field["type"] + " " + java_name + ";\n";
                }

                if(fields.length -1 > i) { current += "\n"; }
            });

            if(accessor === "getset") {
                current += "\n";
                fields.forEach(function (field, i) {
                    var java_name = toCamelCase(field["name"].replace(".", "_"));
                    var java_type = field["fields"].length > 0 ? toCapitalCase(java_name) : field["type"];

                    current += "    public " + java_type + " get" + toCapitalCase(java_name) + "() {\n";
                    current += "        return this." + java_name + ";\n";
                    current += "    }\n";
                    current += "\n";
                    current += "    public void set" + toCapitalCase(java_name) + "(" + java_type + " " + java_name + ") {\n";
                    current += "        this." + java_name + " = " + java_name + ";\n";
                    current += "    }\n";

                    if(fields.length -1 > i) { current += "\n"; }
                });
            }

            current += "}\n";
            classes.push(current);
        })(rootClassName, fields);

        var classHeader = [
            "package " + packageName + ";\n",
            "import dk.nversion.copybook.annotations.CopyBook;",
            "import dk.nversion.copybook.annotations.CopyBookLine;"
        ].join("\n")

        return classHeader + "\n\n" + classes.join("\n");
    }

    function toCamelCase(str) {
        return str.toLocaleLowerCase().replace(/([\-_]\w)/g, function(m){ return m[1].toUpperCase(); });
    }

    function toCapitalCase(str) {
        return str.charAt(0).toUpperCase() + str.slice(1)
    }
    /*** convertCopybook stop ***/

    function updateEditor(srcEditor, dstEditor) {
        var accessorSelector = document.getElementById("accessorpattern");
        var accessor = accessorSelector.options[accessorSelector.selectedIndex].value;
        var charset = document.getElementById("charset").value;
        var src = srcEditor.getValue();
        var dst = convertCopybook("renamemepackage", "RenameMeCopyBook", src, accessor, charset);
        dstEditor.setValue(dst);
        dstEditor.refresh();
    }

    $(function() {
        var javaEditor = CodeMirror.fromTextArea(document.getElementById("javaclass"), {
            lineNumbers: true,
            matchBrackets: true,
            mode: "text/x-java",
            viewportMargin: Infinity
        });
        javaEditor.setSize(null, 750);

        var cobolEditor = CodeMirror.fromTextArea(document.getElementById("copybook"), {
            lineNumbers: true,
            matchBrackets: true,
            mode: "text/x-cobol",
            viewportMargin: Infinity,
            styleActiveLine: true,
            theme : "twilight",
            showCursorWhenSelecting : true
        });

        cobolEditor.setSize(null, 750);
        cobolEditor.on("change", function (cm) {
            updateEditor(cm, javaEditor);
        });

{'fraction_non_alphanumeric': 0.16769933517253854, 'fraction_numerical': 0.010944778616977974, 'mean_word_length': 1.4008686210640608, 'pattern_counts': {'":': 0, '<': 117, '<?xml version=': 0, '>': 127, 'https://': 16, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1312812', 'n_tokens_mistral': 6620, 'n_tokens_neox': 6147, 'n_words': 1058}