gen::add_generator "Java" gen_java::generate

namespace eval gen_java {

variable java_keywords {
abstract    continue  for           new            switch
    assert  default   goto     package        synchronized
    boolean     do        if            private        this
    break       double    implements    protected      throw
    byte        else      import        public         throws
    case        enum  instanceof    return         transient
    catch       extends   int           short          try
    char        final     interface     static         void
    class       finally   long          strictfp   volatile
    const   float     native        super          while
    true false null
}

# Autogenerated with DRAKON Editor 1.29

proc assign { variable value } {
    #item 572
    return "$variable = $value;"
}

proc bad_case { switch_var select_icon_number } {
    #item 1080
    if {[ string compare -nocase $switch_var "select" ] == 0} {
        #item 1085
        return "throw new IllegalStateException\(\"Condition was not detected.\"\);"
    } else {
        #item 1084
        return "throw new IllegalStateException\(\"Not expected:  \" + $switch_var\);"
    }
}

proc block_close { output depth } {
    #item 1060
    upvar 1 $output result
    set line [ gen::make_indent $depth ]
    append line "\}"
    lappend result $line
}

proc classify_keywords { keywords name } {
    #item 788
    set errors {}
    #item 742
    set access [ gen_cpp::find_keywords $keywords { private public protected } ]
    #item 7500000
    set _sw7500000_ [ llength $access ]
    #item 7500001
    if {($_sw7500000_ == 0) || ($_sw7500000_ == 1)} {
        
    } else {
        #item 744
        lappend errors "$name: inconsistent access: $access"
    }
    #item 746
    set dispatch [ gen_cpp::find_keywords $keywords { override abstract static } ]
    #item 7620000
    set _sw7620000_ [ llength $dispatch ]
    #item 7620001
    if {$_sw7620000_ == 0} {
        #item 761
        set dispatch "normal"
    } else {
        #item 7620002
        if {$_sw7620000_ == 1} {
            
        } else {
            #item 754
            lappend errors "$name: inconsistent dispatch: $dispatch"
        }
    }
    #item 772
    set subtype [ gen_cpp::find_keywords $keywords { method ctr } ]
    #item 7730000
    set _sw7730000_ [ llength $subtype ]
    #item 7730001
    if {$_sw7730000_ == 0} {
        #item 771
        set subtype "method"
    } else {
        #item 7730002
        if {$_sw7730000_ == 1} {
            
        } else {
            #item 764
            lappend errors "$name: inconsistent method type: $subtype"
        }
    }
    #item 7750001
    if {(($subtype == "method") || (!($subtype == "ctr"))) || ($dispatch == "normal")} {
        
    } else {
        #item 820
        lappend errors \
        "$name: constructor cannot be $dispatch"
    }
    #item 837
    if {$access == ""} {
        #item 838
        set access "none"
    } else {
        
    }
    #item 866
    array set props {}
    #item 867
    set props(access) $access
    set props(dispatch) $dispatch
    set props(type) $subtype
    #item 868
    set proplist [ array get props ]
    set error_message [ join $errors "\n" ]
    #item 869
    return [ list $error_message $proplist ]
}

proc commentator { line } {
    #item 45
    return "// $line"
}

proc compare { variable constant } {
    #item 581
    return "$variable == $constant"
}

proc else_start { } {
    #item 582
    return "\} else \{"
}

proc elseif_start { } {
    #item 583
    return "\} else if \("
}

proc extract_class_name { section } {
    #item 957
    set section [ string map { "\{" " " } $section ]
    #item 940
    set count [ llength $section ]
    #item 941
    if {$count < 2} {
        #item 955
        return ""
    } else {
        #item 944
        set found [ lsearch $section "class" ]
        #item 945
        if {$found == -1} {
            #item 949
            set found [ lsearch $section "enum" ]
            #item 950
            if {$found == -1} {
                #item 955
                return ""
            } else {
                #item 951
                set name_pos [ expr { $found + 1 } ]
                #item 954
                if {$name_pos < $count} {
                    #item 956
                    return [ lindex $section $name_pos ]
                } else {
                    #item 955
                    return ""
                }
            }
        } else {
            #item 951
            set name_pos [ expr { $found + 1 } ]
            #item 954
            if {$name_pos < $count} {
                #item 956
                return [ lindex $section $name_pos ]
            } else {
                #item 955
                return ""
            }
        }
    }
}

proc extract_signature { text name } {
    #item 710
    array set props { 
    	access none 
    	dispatch normal
    	type method
    }
    set error_message ""
    set parameters {}
    set returns ""
    set throws {}
    set type "method"
    #item 669
    set lines [ gen::separate_from_comments $text ]
    #item 671
    if {[ llength $lines ] == 0} {
        
    } else {
        #item 670
        set first_line [ lindex $lines 0 ]
        set first [ lindex $first_line 0 ]
        #item 693
        if {$first == "#comment"} {
            #item 683
            set type "comment"
        } else {
            #item 699
            set keywords { 
            	public private protected
            	override abstract static
            	method ctr
            }
            #item 700
            set found_keywords [ gen_cpp::find_keywords $first $keywords ]
            #item 698
            if {[ llength $found_keywords ] == 0} {
                #item 702
                set start_index 0
                #item 678
                set count [ llength $lines ]
                #item 6810001
                set i $start_index
                while { 1 } {
                    #item 6810002
                    if {$i < $count} {
                        
                    } else {
                        break
                    }
                    #item 680
                    set current [ lindex $lines $i ]
                    set stripped [ lindex $current 0 ]
                    #item 686
                    if {[ string match "returns *" $stripped ]} {
                        #item 888
                        set returns [ gen_cpp::extract_return_type $stripped ]
                    } else {
                        #item 887
                        if {[ string match "throws *" $stripped ]} {
                            #item 895
                            set throws [ extract_throws $stripped ]
                        } else {
                            #item 685
                            lappend parameters $current
                        }
                    }
                    #item 6810003
                    incr i
                }
            } else {
                #item 701
                set start_index 1
                #item 704
                set alien_keywords [ gen_cpp::find_not_belonging $first $keywords ]
                #item 705
                if {[ llength $alien_keywords ] == 0} {
                    #item 711
                    unpack [ classify_keywords $found_keywords $name ] \
                    	error_message prop_list
                    #item 712
                    if {$error_message == ""} {
                        #item 713
                        array unset props
                        array set props $prop_list
                        set type $props(type)
                        #item 678
                        set count [ llength $lines ]
                        #item 6810001
                        set i $start_index
                        while { 1 } {
                            #item 6810002
                            if {$i < $count} {
                                
                            } else {
                                break
                            }
                            #item 680
                            set current [ lindex $lines $i ]
                            set stripped [ lindex $current 0 ]
                            #item 686
                            if {[ string match "returns *" $stripped ]} {
                                #item 888
                                set returns [ gen_cpp::extract_return_type $stripped ]
                            } else {
                                #item 887
                                if {[ string match "throws *" $stripped ]} {
                                    #item 895
                                    set throws [ extract_throws $stripped ]
                                } else {
                                    #item 685
                                    lappend parameters $current
                                }
                            }
                            #item 6810003
                            incr i
                        }
                    } else {
                        
                    }
                } else {
                    #item 706
                    set error_message \
                        "$name: Unexpected keywords: $alien_keywords"
                }
            }
        }
    }
    #item 897
    if {$type == "ctr"} {
        #item 898
        if {$returns == ""} {
            
        } else {
            #item 899
            set error_message \
            "$name: constructors must not have return type"
        }
    } else {
        #item 902
        if {$returns == ""} {
            #item 905
            set returns "void"
        } else {
            
        }
    }
    #item 714
    set prop_list [ array get props ]
    #item 682
    set signature [ gen::create_signature $type $prop_list $parameters $returns ]
    lappend signature $throws
    set result [ list $error_message $signature ]
    #item 896
    return $result
}

proc extract_throws { text } {
    #item 894
    set skip [ string length "throws " ]
    set raw [ string range $text $skip end ]
    return [ string trim $raw ]
}

proc foreach_check { item_id first second } {
    #item 1057
    set iter_var "_it$item_id"
    #item 1055
    return "$iter_var.hasNext()"
}

proc foreach_current { item_id first second } {
    #item 1059
    unpack [ parse_foreach $item_id $first ] type var
    #item 1058
    set iter_var "_it$item_id"
    
    return "$var = $iter_var.next();"
}

proc foreach_declare { item_id first second } {
    #item 1067
    unpack [ parse_foreach $item_id $first ] type var
    #item 1066
    set iter_var "_it$item_id"
    set iter_type "Iterator<$type>"
    set col_type "Iterable<$type>"
    
    
    return "$iter_type $iter_var = null;\n$type $var = null;"
}

proc foreach_incr { item_id first second } {
    #item 32
    return ""
}

proc foreach_init { item_id first second } {
    #item 1054
    unpack [ parse_foreach $item_id $first ] type var
    #item 19
    set iter_var "_it$item_id"
    
    
    return "$iter_var = $second.iterator();"
}

proc generate { db gdb filename } {
    #item 337
    set callbacks [ make_callbacks ]
    #item 349
    gen::fix_graph $gdb $callbacks 1
    unpack [ gen::scan_file_description $db { header class } ] header class
    set goto 1
    set functions [ gen::generate_functions $db $gdb $callbacks $goto ]
    #item 734
    if {$class == ""} {
        #item 735
        error "Please add the ===class=== section to the file description."
    } else {
        #item 338
        if {[ graph::errors_occured ]} {
            
        } else {
            #item 927
            set class_name [ extract_class_name $class ]
            #item 928
            if {$class_name == ""} {
                #item 929
                error "Class or enum is missing in the ===class=== section."
            } else {
                #item 339
                set hfile [ replace_extension $filename "java" ]
                set fhandle [ open_output_file $hfile ]
                
                catch {
                	p.print_to_file $fhandle $functions \
                		$header $class $class_name
                } error_message
                
                catch { close $fhandle }
                #item 340
                if {$error_message == ""} {
                    
                } else {
                    #item 341
                    error $error_message
                }
            }
        }
    }
}

proc generate_body { gdb diagram_id start_item node_list items incoming } {
    #item 590
    set callbacks [ make_callbacks ]
    #item 591
    return [ cbody::generate_body $gdb $diagram_id $start_item $node_list \
    $items $incoming $callbacks ]
}

proc highlight { tokens } {
    #item 1091
    variable java_keywords
    #item 1092
    return [ gen_cs::highlight_generic $java_keywords $tokens ]
}

proc if_end { } {
    #item 584
    return "\) \{"
}

proc if_start { } {
    #item 585
    return "if \("
}

proc is_ctr { method } {
    #item 911
    set signature [ lindex $method 2 ]
    set type [ lindex $signature 0 ]
    return [ expr { $type == "ctr" } ]
}

proc make_callbacks { } {
    #item 641
    set callbacks {}
    
    gen::put_callback callbacks assign			gen_java::assign
    gen::put_callback callbacks compare			gen_java::compare
    gen::put_callback callbacks compare2		gen_java::compare
    gen::put_callback callbacks while_start 	gen_java::while_start
    gen::put_callback callbacks if_start		gen_java::if_start
    gen::put_callback callbacks elseif_start	gen_java::elseif_start
    gen::put_callback callbacks if_end			gen_java::if_end
    gen::put_callback callbacks else_start		gen_java::else_start
    gen::put_callback callbacks pass			gen_java::pass
    gen::put_callback callbacks continue		gen_java::p.continue
    gen::put_callback callbacks return_none		gen_java::return_none
    gen::put_callback callbacks block_close		gen_java::block_close
    gen::put_callback callbacks comment			gen_java::commentator
    gen::put_callback callbacks bad_case		gen_java::bad_case	
    gen::put_callback callbacks for_check		gen_java::foreach_check
    gen::put_callback callbacks for_current		gen_java::foreach_current	
    gen::put_callback callbacks body			gen_java::generate_body
    gen::put_callback callbacks signature		gen_java::extract_signature
    gen::put_callback callbacks and				gen_java::p.and
    gen::put_callback callbacks or				gen_java::p.or
    gen::put_callback callbacks not				gen_java::p.not
    gen::put_callback callbacks break			"break;"
    gen::put_callback callbacks declare		gen_java::p.declare
    gen::put_callback callbacks for_init		gen_java::foreach_init
    gen::put_callback callbacks for_incr		gen_java::foreach_incr
    gen::put_callback callbacks for_declare		gen_java::foreach_declare
    gen::put_callback callbacks shelf		gen_java::shelf
    gen::put_callback callbacks native_foreach gen_java::native_foreach
    #item 650
    return $callbacks
}

proc method_of_access { procedure access } {
    #item 1041
    set signature [ lindex $procedure 2 ]
    set type [ lindex $signature 0 ]
    #item 918
    if {$type == "method"} {
        #item 923
        set props_list [ lindex $signature 1 ]
        array set props $props_list
        #item 924
        if {$props(access) == $access} {
            #item 921
            return 1
        } else {
            #item 922
            return 0
        }
    } else {
        #item 922
        return 0
    }
}

proc native_foreach { for_it for_var } {
    #item 1098
    return "for ($for_it : $for_var) \{"
}

proc p.and { left right } {
    #item 621
    return "($left) && ($right)"
}

proc p.build_declaration { name signature } {
    #item 103
    unpack $signature type access parameters returns
    set param_names {}
    foreach parameter $parameters {
        #item 104
        set pname [ lindex $parameter 0 ]
        lappend param_names $pname
    }
    #item 107
    set param_string [ join $param_names ", " ]
    return "def $name\($param_string\):"
}

proc p.continue { } {
    #item 586
    return "continue;"
}

proc p.declare { type name value } {
    #item 1099
    if {$value == ""} {
        #item 1102
        return "$type $name;"
    } else {
        #item 656
        return "$type $name = $value;"
    }
}

proc p.not { operand } {
    #item 633
    return "!\($operand\)"
}

proc p.or { left right } {
    #item 652
    return "($left) || ($right)"
}

proc p.print_proc { fhandle procedure class_name } {
    #item 97
    unpack $procedure diagram_id name signature body
    #item 968
    if {$class_name == ""} {
        
    } else {
        #item 971
        set name $class_name
    }
    #item 972
    unpack $signature type prop_list parameters returns throws
    array set props $prop_list
    #item 1039
    set depth 1
    #item 66
    set indent [ gen::make_indent $depth ]
    #item 67
    set body_depth [ expr { $depth + 1 } ]
    set lines [ gen::indent $body $body_depth ]
    #item 985
    set header ""
    #item 9860000
    set _sw9860000_ $props(access)
    #item 9860001
    if {(($_sw9860000_ == "public") || ($_sw9860000_ == "protected")) || ($_sw9860000_ == "private")} {
        #item 995
        append header "$props(access) "
    } else {
        #item 9860004
        if {$_sw9860000_ == "none"} {
            
        } else {
            #item 9860005
            error "Unexpected switch value: $_sw9860000_"
        }
    }
    #item 10010000
    set _sw10010000_ $props(dispatch)
    #item 10010001
    if {($_sw10010000_ == "static") || ($_sw10010000_ == "abstract")} {
        #item 1007
        append header "$props(dispatch) "
    } else {
        
    }
    #item 1011
    if {$type == "ctr"} {
        
    } else {
        #item 1014
        append header "$returns "
    }
    #item 1015
    append header "$name\("
    #item 1021
    set i 0
    foreach parameter $parameters {
        #item 1024
        if {$i == 0} {
            
        } else {
            #item 1027
            append header ", "
        }
        #item 1023
        set arg [ lindex $parameter 0 ]
        append header $arg
        #item 1022
        incr i
    }
    #item 1031
    append header "\)"
    #item 1028
    if {$throws == ""} {
        
    } else {
        #item 1032
        set exceptions [ join $throws ", " ]
        append header " throws $exceptions"
    }
    #item 1036
    puts $fhandle ""
    #item 981
    if {$props(dispatch) == "override"} {
        #item 984
        puts $fhandle "${indent}@Override"
    } else {
        
    }
    #item 1033
    if {$props(dispatch) == "abstract"} {
        #item 1037
        puts $fhandle "$indent$header;"
    } else {
        #item 96
        puts $fhandle "$indent$header \{"
        puts $fhandle $lines
        puts $fhandle "$indent\}"
    }
}

proc p.print_to_file { fhandle functions header class class_name } {
    #item 400
    set version [ version_string ]
    puts $fhandle \
        "// Autogenerated with DRAKON Editor $version"
    #item 68
    puts $fhandle $header
    #item 925
    puts $fhandle $class
    #item 926
    set ctrs      [ lfilter $functions gen_java::is_ctr ]
    set public    [ lfilter_user $functions gen_java::method_of_access "public"    ]
    set none      [ lfilter_user $functions gen_java::method_of_access "none"      ]
    set protected [ lfilter_user $functions gen_java::method_of_access "protected" ]
    set private   [ lfilter_user $functions gen_java::method_of_access "private"   ]
    #item 966
    print_procs $fhandle $ctrs $class_name
    #item 967
    print_procs $fhandle $public ""
    print_procs $fhandle $none ""
    print_procs $fhandle $protected ""
    print_procs $fhandle $private ""
    #item 76
    puts $fhandle "\}"
}

proc parse_foreach { item_id init } {
    #item 1048
    set length [ llength $init ]
    #item 1050
    if {$length == 2} {
        
    } else {
        #item 1049
        set message "item id: $item_id, wrong syntax in foreach. Should be: Type variable; collection"
    }
    #item 1053
    return $init
}

proc pass { } {
    #item 587
    return ""
}

proc print_procs { fhandle procedures class_name } {
    foreach procedure $procedures {
        #item 965
        p.print_proc $fhandle $procedure $class_name
    }
}

proc return_none { } {
    #item 588
    return "return;"
}

proc shelf { primary secondary } {
    #item 1073
    return "$secondary = $primary;"
}

proc while_start { } {
    #item 589
    return "while (true) \{"
}

}
