%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 1999-2009. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. %% %% %CopyrightEnd% %% %% -module(ic_enum_java). -include("icforms.hrl"). -include("ic.hrl"). -include("ic_debug.hrl"). %%----------------------------------------------------------------- %% External exports %%----------------------------------------------------------------- -export([gen/3]). %%----------------------------------------------------------------- %% Internal exports %%----------------------------------------------------------------- -export([]). %%----------------------------------------------------------------- %% External functions %%----------------------------------------------------------------- %%----------------------------------------------------------------- %% Func: gen/3 %%----------------------------------------------------------------- gen(G, N, X) when is_record(X, enum) -> %%?PRINTDEBUG2("enum: ~p", [X]), EnumName = ic_forms:get_java_id(X), N2 = ["_" ++ EnumName |N], ic_jbe:gen(G, N2, ic_forms:get_body(X)), emit_enum_class(G, N, X, EnumName), emit_holder_class(G, N, X, EnumName), emit_helper_class(G, N, X, EnumName); gen(_G, _N, _X) -> ok. %%----------------------------------------------------------------- %% Internal functions %%----------------------------------------------------------------- %%----------------------------------------------------------------- %% Func: emit_enum_class/4 %%----------------------------------------------------------------- emit_enum_class(G, N, X, EnumName) -> {Fd, _} = ic_file:open_java_file(G, N, EnumName), EList = enum_member_name_list(G, N, X), %%?PRINTDEBUG2("EList: ~p", [EList]), ic_codegen:emit(Fd, ["final public class ",EnumName," {\n\n" " // instance variables\n"]), emit_enum_member_int_values_initialization(G, N, X, Fd, EList), emit_enum_public_instance_variables(G, N, X, Fd, EnumName, EList), ic_codegen:emit(Fd, [" private int _value;\n\n" " // constructors\n" " private ",EnumName,"(int __value) {\n" " _value = __value;\n" " }\n\n" " // methods\n" " public int value() {\n" " return _value;\n" " }\n"]), emit_enum_from_int_function(G, N, X, Fd, EnumName, EList), ic_codegen:emit(Fd, "\n}\n"), file:close(Fd). %%----------------------------------------------------------------- %% Func: emit_holder_class/4 %%----------------------------------------------------------------- emit_holder_class(G, N, _X, EnumName) -> EName = string:concat(EnumName, "Holder"), {Fd, _} = ic_file:open_java_file(G, N, EName), ic_codegen:emit(Fd, ["final public class ",EnumName,"Holder {\n\n" " // instance variables\n" " public ",EnumName," value;\n\n" " // constructors\n" " public ",EnumName,"Holder() {}\n\n" " public ",EnumName,"Holder(",EnumName," initial) {\n" " value = initial;\n" " }\n\n" " // methods\n" " public void _marshal(",?ERLANGPACKAGE,"OtpOutputStream out) throws java.lang.Exception {\n" " ",EnumName,"Helper.marshal(out, value);\n" " }\n\n" " public void _unmarshal(",?ERLANGPACKAGE,"OtpInputStream in) throws java.lang.Exception {\n" " value = ",EnumName,"Helper.unmarshal(in);\n" " }\n\n" "}\n"]), file:close(Fd). %%----------------------------------------------------------------- %% Func: emit_helper_class/4 %%----------------------------------------------------------------- emit_helper_class(G, N, X, EnumName) -> EName = string:concat(EnumName, "Helper"), WEList = enum_member_atom_list(G, N, X), {Fd, _} = ic_file:open_java_file(G, N, EName), ic_codegen:emit(Fd, ["public class ",EnumName,"Helper {\n\n" " // constructors\n" " private ",EnumName,"Helper() {}\n\n" " // methods\n" " public static void marshal(",?ERLANGPACKAGE,"OtpOutputStream _out, ",EnumName," _value)\n" " throws java.lang.Exception {\n\n"]), emit_enum_write_function(G, N, X, Fd, EnumName), ic_codegen:emit(Fd, [" }\n\n" " public static ",EnumName," unmarshal(",?ERLANGPACKAGE,"OtpInputStream _in)\n" " throws java.lang.Exception {\n\n"]), emit_enum_read_function(G, N, X, Fd, EnumName), ic_codegen:emit(Fd, "\n }\n\n"), emit_enum_private_member_variables(Fd, WEList), ic_codegen:emit(Fd, ["\n // Get integer value of enum from string\n" " private static int _getIntFromName(String name) throws java.lang.Exception {\n" " for(int i = 0; i < _memberCount; i++) {\n" " if (name.equals(_members[i]))\n" " return i;\n" " }\n" " throw new java.lang.Exception(\"\");\n" " }\n\n" " public static String id() {\n" " return \"",ictk:get_IR_ID(G, N, X),"\";\n" " }\n\n" " public static String name() {\n" " return \"",EnumName,"\";\n" " }\n\n"]), ic_jbe:emit_type_function(G, N, X, Fd), ic_codegen:emit(Fd, [" public static void insert(",?ICPACKAGE,"Any _any, ",EnumName," _this)\n" " throws java.lang.Exception {\n\n" " ",?ERLANGPACKAGE,"OtpOutputStream _os = \n" " new ",?ERLANGPACKAGE,"OtpOutputStream();\n\n" " _any.type(type());\n" " marshal(_os, _this);\n" " _any.insert_Streamable(_os);\n" " }\n\n" " public static ",EnumName," extract(",?ICPACKAGE,"Any _any)\n" " throws java.lang.Exception {\n\n" " return unmarshal(_any.extract_Streamable());\n" " }\n\n" "}\n"]), file:close(Fd). %%----------------------------------------------------------------- %% Func: emit_enum_public_instance_variables/6 %%----------------------------------------------------------------- emit_enum_public_instance_variables(_G, _N, _X, _Fd, _EnumName, []) -> ok; emit_enum_public_instance_variables(G, N, X, Fd, EnumName, [Enumerator |EList]) -> ic_codegen:emit(Fd, [" public static final ",EnumName," ",Enumerator," = new ",EnumName,"(_",Enumerator,");\n"]), emit_enum_public_instance_variables(G, N, X, Fd, EnumName, EList). %%----------------------------------------------------------------- %% Func: emit_enum_member_int_values_initialization/5 %%----------------------------------------------------------------- emit_enum_member_int_values_initialization(G, N, X, Fd, EList) -> InitString = emit_enum_member_int_values_initialization_1(G, N, X, Fd, EList, 0), ic_codegen:emit(Fd, [" public static final int ",InitString,";\n"]). %%----------------------------------------------------------------- %% Func: emit_enum_member_int_values_initialization_1/6 %%----------------------------------------------------------------- emit_enum_member_int_values_initialization_1(_G, _N, _X, _Fd, [Enumerator], Num) -> " _" ++ Enumerator ++ " = " ++ ic_util:to_list(Num); emit_enum_member_int_values_initialization_1(G, N, X, Fd, [Enumerator |EList], Num) -> Spaces = if Num == 0 -> ""; true -> " " end, Spaces ++ "_" ++ Enumerator ++ " = " ++ ic_util:to_list(Num) ++ ",\n" ++ emit_enum_member_int_values_initialization_1(G, N, X, Fd, EList, Num + 1). %%----------------------------------------------------------------- %% Func: emit_enum_from_int_function/6 %%----------------------------------------------------------------- emit_enum_from_int_function(_G, _N, _X, Fd, EnumName, EList) -> ic_codegen:emit(Fd, [" public static final ",EnumName," from_int(int __value) throws java.lang.Exception {\n" " switch (__value) {\n"]), emit_enum_from_int_function_switchbody(Fd, EList), ic_codegen:emit(Fd, [" }\n" " }\n"]). %%----------------------------------------------------------------- %% Func: emit_enum_from_int_function_switchbody/2 %%----------------------------------------------------------------- emit_enum_from_int_function_switchbody(Fd, []) -> ic_codegen:emit(Fd, [" default:\n" " throw new java.lang.Exception(\"\");\n"]); emit_enum_from_int_function_switchbody(Fd, [Enumerator |EList]) -> ic_codegen:emit(Fd, [" case _",Enumerator,":\n" " return ",Enumerator,";\n"]), emit_enum_from_int_function_switchbody(Fd, EList). %%----------------------------------------------------------------- %% Func: emit_enum_private_member_variables/2 %%----------------------------------------------------------------- emit_enum_private_member_variables(Fd, EList) -> ic_codegen:emit(Fd, [" private static final int _memberCount = ",integer_to_list(length(EList)),";\n" " private static String[] _members = {\n"]), emit_enum_private_member_variables_1(Fd, EList), ic_codegen:emit(Fd, " };\n"). %%----------------------------------------------------------------- %% Func: emit_enum_private_member_variables_1/2 %%----------------------------------------------------------------- emit_enum_private_member_variables_1(Fd, [Enumerator]) -> ic_codegen:emit(Fd, [" \"",Enumerator,"\"\n"]); emit_enum_private_member_variables_1(Fd, [Enumerator |EList]) -> ic_codegen:emit(Fd, [" \"",Enumerator,"\",\n"]), emit_enum_private_member_variables_1(Fd, EList). %%----------------------------------------------------------------- %% Func: emit_enum_read_function/5 %%----------------------------------------------------------------- emit_enum_read_function(_G, _N, _X, Fd, EnumName) -> ic_codegen:emit(Fd, [" return ",EnumName,".from_int(_getIntFromName(_in.read_atom()));"]). %%----------------------------------------------------------------- %% Func: emit_enum_write_function/5 %%----------------------------------------------------------------- emit_enum_write_function(_G, _N, _X, Fd, _EnumName) -> ic_codegen:emit(Fd, " _out.write_atom(_members[_value.value()]);\n"). %%----------------------------------------------------------------- %% Func: enum_member_name_list/3 %% %% Note: The names generated are checked for name coalition %% with java keywords. If so the name is always prefixed %% by "_" %%----------------------------------------------------------------- enum_member_name_list(_G, _N, X) -> lists:map( fun(Enumerator) -> ic_forms:get_java_id(Enumerator) end, ic_forms:get_body(X)). %%----------------------------------------------------------------- %% Func: enum_member_atom_list/3 %% %% Note : Similar to the emit_member_list/3 but does not %% solves name coalitions with java keywords. %% Used for wire encoding only %%----------------------------------------------------------------- enum_member_atom_list(_G, _N, X) -> lists:map( fun(Enumerator) -> ic_forms:get_id2(Enumerator) end, ic_forms:get_body(X)).