1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1999-2016. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20%% 21 22-module(ic_enum_java). 23 24-include("icforms.hrl"). 25-include("ic.hrl"). 26-include("ic_debug.hrl"). 27%%----------------------------------------------------------------- 28%% External exports 29%%----------------------------------------------------------------- 30-export([gen/3]). 31 32%%----------------------------------------------------------------- 33%% Internal exports 34%%----------------------------------------------------------------- 35-export([]). 36 37%%----------------------------------------------------------------- 38%% External functions 39%%----------------------------------------------------------------- 40 41%%----------------------------------------------------------------- 42%% Func: gen/3 43%%----------------------------------------------------------------- 44gen(G, N, X) when is_record(X, enum) -> 45 %%?PRINTDEBUG2("enum: ~p", [X]), 46 EnumName = ic_forms:get_java_id(X), 47 N2 = ["_" ++ EnumName |N], 48 ic_jbe:gen(G, N2, ic_forms:get_body(X)), 49 50 emit_enum_class(G, N, X, EnumName), 51 emit_holder_class(G, N, X, EnumName), 52 emit_helper_class(G, N, X, EnumName); 53gen(_G, _N, _X) -> 54 ok. 55 56 57%%----------------------------------------------------------------- 58%% Internal functions 59%%----------------------------------------------------------------- 60 61%%----------------------------------------------------------------- 62%% Func: emit_enum_class/4 63%%----------------------------------------------------------------- 64emit_enum_class(G, N, X, EnumName) -> 65 {Fd, _} = ic_file:open_java_file(G, N, EnumName), 66 67 EList = enum_member_name_list(G, N, X), 68 %%?PRINTDEBUG2("EList: ~p", [EList]), 69 ic_codegen:emit(Fd, ["final public class ",EnumName," {\n\n" 70 71 " // instance variables\n"]), 72 73 emit_enum_member_int_values_initialization(G, N, X, Fd, EList), 74 emit_enum_public_instance_variables(G, N, X, Fd, EnumName, EList), 75 76 ic_codegen:emit(Fd, [" private int _value;\n\n" 77 78 " // constructors\n" 79 " private ",EnumName,"(int __value) {\n" 80 " _value = __value;\n" 81 " }\n\n" 82 83 " // methods\n" 84 " public int value() {\n" 85 " return _value;\n" 86 " }\n"]), 87 88 emit_enum_from_int_function(G, N, X, Fd, EnumName, EList), 89 90 ic_codegen:emit(Fd, "\n}\n"), 91 file:close(Fd). 92 93%%----------------------------------------------------------------- 94%% Func: emit_holder_class/4 95%%----------------------------------------------------------------- 96emit_holder_class(G, N, _X, EnumName) -> 97 EName = string:concat(EnumName, "Holder"), 98 {Fd, _} = ic_file:open_java_file(G, N, EName), 99 100 ic_codegen:emit(Fd, ["final public class ",EnumName,"Holder {\n\n" 101 102 " // instance variables\n" 103 " public ",EnumName," value;\n\n" 104 105 " // constructors\n" 106 " public ",EnumName,"Holder() {}\n\n" 107 108 " public ",EnumName,"Holder(",EnumName," initial) {\n" 109 " value = initial;\n" 110 " }\n\n" 111 112 " // methods\n" 113 " public void _marshal(",?ERLANGPACKAGE,"OtpOutputStream out) throws java.lang.Exception {\n" 114 " ",EnumName,"Helper.marshal(out, value);\n" 115 " }\n\n" 116 117 " public void _unmarshal(",?ERLANGPACKAGE,"OtpInputStream in) throws java.lang.Exception {\n" 118 " value = ",EnumName,"Helper.unmarshal(in);\n" 119 " }\n\n" 120 "}\n"]), 121 file:close(Fd). 122 123 124%%----------------------------------------------------------------- 125%% Func: emit_helper_class/4 126%%----------------------------------------------------------------- 127emit_helper_class(G, N, X, EnumName) -> 128 EName = string:concat(EnumName, "Helper"), 129 WEList = enum_member_atom_list(G, N, X), 130 {Fd, _} = ic_file:open_java_file(G, N, EName), 131 132 ic_codegen:emit(Fd, ["public class ",EnumName,"Helper {\n\n" 133 134 " // constructors\n" 135 " private ",EnumName,"Helper() {}\n\n" 136 137 " // methods\n" 138 139 " public static void marshal(",?ERLANGPACKAGE,"OtpOutputStream _out, ",EnumName," _value)\n" 140 " throws java.lang.Exception {\n\n"]), 141 142 emit_enum_write_function(G, N, X, Fd, EnumName), 143 144 ic_codegen:emit(Fd, [" }\n\n" 145 146 " public static ",EnumName," unmarshal(",?ERLANGPACKAGE,"OtpInputStream _in)\n" 147 " throws java.lang.Exception {\n\n"]), 148 149 emit_enum_read_function(G, N, X, Fd, EnumName), 150 151 ic_codegen:emit(Fd, "\n }\n\n"), 152 153 emit_enum_private_member_variables(Fd, WEList), 154 155 ic_codegen:emit(Fd, ["\n // Get integer value of enum from string\n" 156 " private static int _getIntFromName(String name) throws java.lang.Exception {\n" 157 " for(int i = 0; i < _memberCount; i++) {\n" 158 " if (name.equals(_members[i]))\n" 159 " return i;\n" 160 " }\n" 161 " throw new java.lang.Exception(\"\");\n" 162 " }\n\n" 163 164 " public static String id() {\n" 165 " return \"",ictk:get_IR_ID(G, N, X),"\";\n" 166 " }\n\n" 167 168 " public static String name() {\n" 169 " return \"",EnumName,"\";\n" 170 " }\n\n"]), 171 172 ic_jbe:emit_type_function(G, N, X, Fd), 173 174 ic_codegen:emit(Fd, [" public static void insert(",?ICPACKAGE,"Any _any, ",EnumName," _this)\n" 175 " throws java.lang.Exception {\n\n" 176 177 " ",?ERLANGPACKAGE,"OtpOutputStream _os = \n" 178 " new ",?ERLANGPACKAGE,"OtpOutputStream();\n\n" 179 180 " _any.type(type());\n" 181 " marshal(_os, _this);\n" 182 " _any.insert_Streamable(_os);\n" 183 " }\n\n" 184 185 " public static ",EnumName," extract(",?ICPACKAGE,"Any _any)\n" 186 " throws java.lang.Exception {\n\n" 187 188 " return unmarshal(_any.extract_Streamable());\n" 189 " }\n\n" 190 191 "}\n"]), 192 file:close(Fd). 193 194%%----------------------------------------------------------------- 195%% Func: emit_enum_public_instance_variables/6 196%%----------------------------------------------------------------- 197emit_enum_public_instance_variables(_G, _N, _X, _Fd, _EnumName, []) -> 198 ok; 199emit_enum_public_instance_variables(G, N, X, Fd, EnumName, [Enumerator |EList]) -> 200 ic_codegen:emit(Fd, [" public static final ",EnumName," ",Enumerator," = new ",EnumName,"(_",Enumerator,");\n"]), 201 emit_enum_public_instance_variables(G, N, X, Fd, EnumName, EList). 202 203%%----------------------------------------------------------------- 204%% Func: emit_enum_member_int_values_initialization/5 205%%----------------------------------------------------------------- 206emit_enum_member_int_values_initialization(G, N, X, Fd, EList) -> 207 InitString = emit_enum_member_int_values_initialization_1(G, N, X, Fd, EList, 0), 208 ic_codegen:emit(Fd, [" public static final int ",InitString,";\n"]). 209 210 211%%----------------------------------------------------------------- 212%% Func: emit_enum_member_int_values_initialization_1/6 213%%----------------------------------------------------------------- 214emit_enum_member_int_values_initialization_1(_G, _N, _X, _Fd, [Enumerator], Num) -> 215 " _" ++ Enumerator ++ " = " ++ ic_util:to_list(Num); 216emit_enum_member_int_values_initialization_1(G, N, X, Fd, [Enumerator |EList], Num) -> 217 Spaces = if 218 Num == 0 -> 219 ""; 220 true -> 221 " " 222 end, 223 Spaces ++ "_" ++ Enumerator ++ " = " ++ ic_util:to_list(Num) ++ ",\n" ++ 224 emit_enum_member_int_values_initialization_1(G, N, X, Fd, EList, Num + 1). 225 226%%----------------------------------------------------------------- 227%% Func: emit_enum_from_int_function/6 228%%----------------------------------------------------------------- 229emit_enum_from_int_function(_G, _N, _X, Fd, EnumName, EList) -> 230 ic_codegen:emit(Fd, 231 [" public static final ",EnumName," from_int(int __value) throws java.lang.Exception {\n" 232 " switch (__value) {\n"]), 233 emit_enum_from_int_function_switchbody(Fd, EList), 234 ic_codegen:emit(Fd, [" }\n" 235 " }\n"]). 236 237%%----------------------------------------------------------------- 238%% Func: emit_enum_from_int_function_switchbody/2 239%%----------------------------------------------------------------- 240emit_enum_from_int_function_switchbody(Fd, []) -> 241 ic_codegen:emit(Fd, [" default:\n" 242 " throw new java.lang.Exception(\"\");\n"]); 243emit_enum_from_int_function_switchbody(Fd, [Enumerator |EList]) -> 244 ic_codegen:emit(Fd, [" case _",Enumerator,":\n" 245 " return ",Enumerator,";\n"]), 246 emit_enum_from_int_function_switchbody(Fd, EList). 247 248%%----------------------------------------------------------------- 249%% Func: emit_enum_private_member_variables/2 250%%----------------------------------------------------------------- 251emit_enum_private_member_variables(Fd, EList) -> 252 ic_codegen:emit(Fd, [" private static final int _memberCount = ",integer_to_list(length(EList)),";\n" 253 " private static String[] _members = {\n"]), 254 emit_enum_private_member_variables_1(Fd, EList), 255 ic_codegen:emit(Fd, " };\n"). 256 257%%----------------------------------------------------------------- 258%% Func: emit_enum_private_member_variables_1/2 259%%----------------------------------------------------------------- 260emit_enum_private_member_variables_1(Fd, [Enumerator]) -> 261 ic_codegen:emit(Fd, [" \"",Enumerator,"\"\n"]); 262emit_enum_private_member_variables_1(Fd, [Enumerator |EList]) -> 263 ic_codegen:emit(Fd, [" \"",Enumerator,"\",\n"]), 264 emit_enum_private_member_variables_1(Fd, EList). 265 266%%----------------------------------------------------------------- 267%% Func: emit_enum_read_function/5 268%%----------------------------------------------------------------- 269emit_enum_read_function(_G, _N, _X, Fd, EnumName) -> 270 ic_codegen:emit(Fd, [" return ",EnumName,".from_int(_getIntFromName(_in.read_atom()));"]). 271 272%%----------------------------------------------------------------- 273%% Func: emit_enum_write_function/5 274%%----------------------------------------------------------------- 275emit_enum_write_function(_G, _N, _X, Fd, _EnumName) -> 276 ic_codegen:emit(Fd, " _out.write_atom(_members[_value.value()]);\n"). 277 278 279%%----------------------------------------------------------------- 280%% Func: enum_member_name_list/3 281%% 282%% Note: The names generated are checked for name coalition 283%% with java keywords. If so the name is always prefixed 284%% by "_" 285%%----------------------------------------------------------------- 286enum_member_name_list(_G, _N, X) -> 287 lists:map( 288 fun(Enumerator) -> 289 ic_forms:get_java_id(Enumerator) 290 end, 291 ic_forms:get_body(X)). 292 293%%----------------------------------------------------------------- 294%% Func: enum_member_atom_list/3 295%% 296%% Note : Similar to the emit_member_list/3 but does not 297%% solves name coalitions with java keywords. 298%% Used for wire encoding only 299%%----------------------------------------------------------------- 300enum_member_atom_list(_G, _N, X) -> 301 lists:map( 302 fun(Enumerator) -> 303 ic_forms:get_id2(Enumerator) 304 end, 305 ic_forms:get_body(X)). 306 307 308 309 310 311 312 313 314