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_struct_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%%-----------------------------------------------------------------
40gen(G, N, X) when is_record(X, struct) ->
41    StructName = ic_forms:get_java_id(X),
42    WireStructName = ic_forms:get_id2(X),
43    emit_struct_class(G, N, X, StructName),
44    emit_holder_class(G, N, X, StructName),
45    emit_helper_class(G, N, X, StructName, WireStructName),
46    N2 = [StructName ++ "Package" |N],
47    ic_jbe:gen(G, N2, ic_forms:get_body(X));
48gen(_G, _N, _X) ->
49    ok.
50
51%%-----------------------------------------------------------------
52%% Internal functions
53%%-----------------------------------------------------------------
54
55%%-----------------------------------------------------------------
56%% Func:  emit_struct_class/4
57%%-----------------------------------------------------------------
58emit_struct_class(G, N, X, StructName) ->
59    {Fd, _}= ic_file:open_java_file(G, N, StructName),
60
61    MList = struct_member_list(G, N, X),
62    ArgList = gen_parameter_list(G, [ StructName ++ "Package" |N], X, MList),
63
64    ic_codegen:emit(Fd, ["final public class ",StructName," {\n"
65			 "   // instance variables\n"]),
66
67    emit_struct_members_declarations(G, [StructName ++ "Package" |N],
68				     X, Fd, MList),
69
70    ic_codegen:emit(Fd, ["\n   // constructors\n"
71			 "   public ",StructName,"() {}\n\n"
72
73			 "   public ",StructName,"(",ArgList,") {\n"]),
74
75    emit_struct_members_initialisation(G, N, X, Fd, MList),
76
77    ic_codegen:emit(Fd, ["   }\n\n"
78
79			 "}\n\n"]),
80    file:close(Fd).
81
82
83%%-----------------------------------------------------------------
84%% Func:  emit_holder_class/4
85%%-----------------------------------------------------------------
86emit_holder_class(G, N, _X, StructName) ->
87    SName = string:concat(StructName, "Holder"),
88    {Fd, _}= ic_file:open_java_file(G, N, SName),
89
90    ic_codegen:emit(Fd, ["final public class ",StructName,"Holder {\n"
91
92			 "   // instance variables\n"
93			 "   public ",StructName," value;\n\n"
94
95			 "   // constructors\n"
96			 "   public ",StructName,"Holder() {}\n\n"
97
98			 "   public ",StructName,"Holder(",StructName," initial) {\n"
99			 "      value = initial;\n"
100			 "   }\n\n"
101
102			 "   // methods\n"]),
103
104    ic_codegen:emit(Fd, ["   public void _marshal(",?ERLANGPACKAGE,"OtpOutputStream out) throws java.lang.Exception {\n"
105			 "      ",StructName,"Helper.marshal(out, value);\n"
106			 "   }\n\n"
107
108			 "   public void _unmarshal(",?ERLANGPACKAGE,"OtpInputStream in) throws java.lang.Exception {\n"
109			 "      value = ",StructName,"Helper.unmarshal(in);\n"
110			 "   }\n"
111
112			 "}\n\n"]),
113    file:close(Fd).
114
115%%-----------------------------------------------------------------
116%% Func:  emit_helper_class/5
117%%-----------------------------------------------------------------
118emit_helper_class(G, N, X, StructName, WireStructName) ->
119    SName = string:concat(StructName, "Helper"),
120    {Fd, _}= ic_file:open_java_file(G, N, SName),
121
122    ic_codegen:emit(Fd, ["public class ",StructName,"Helper {\n"
123
124			 "   // constructors\n"
125			 "   private ",StructName,"Helper() {}\n\n"
126
127			 "   // methods\n"]),
128
129    MList = struct_member_list(G, N, X),
130
131    ic_codegen:emit(Fd, ["   public static void marshal(",?ERLANGPACKAGE,"OtpOutputStream _out, ",StructName," _value)\n"
132			 "     throws java.lang.Exception {\n\n"]),
133
134    emit_struct_marshal_function(G, N, X, Fd, StructName, WireStructName, MList),
135
136    ic_codegen:emit(Fd, ["   }\n\n"
137
138			 "   public static ",StructName," unmarshal(",?ERLANGPACKAGE,"OtpInputStream _in)\n"
139			 "     throws java.lang.Exception {\n\n"]),
140
141    emit_struct_unmarshal_function(G, N, X, Fd, StructName, WireStructName, MList),
142
143    ic_codegen:emit(Fd, ["   }\n\n"
144
145			 "   public static String id() {\n"
146			 "      return \"",ictk:get_IR_ID(G, N, X),"\";\n"
147			 "   }\n\n"
148
149			 "   public static String name() {\n"
150			 "      return \"",StructName,"\";\n"
151			 "   }\n\n"]),
152
153    ic_jbe:emit_type_function(G, N, X, Fd),
154
155    ic_codegen:emit(Fd, ["   public static void insert(",?ICPACKAGE,"Any _any, ",StructName," _this)\n"
156			 "     throws java.lang.Exception {\n\n"
157
158			 "     ",?ERLANGPACKAGE,"OtpOutputStream _os = \n"
159			 "       new ",?ERLANGPACKAGE,"OtpOutputStream();\n\n"
160
161			 "     _any.type(type());\n"
162			 "     marshal(_os, _this);\n"
163			 "     _any.insert_Streamable(_os);\n"
164			 "   }\n\n"
165
166			 "   public static ",StructName," extract(",?ICPACKAGE,"Any _any)\n"
167			 "     throws java.lang.Exception {\n\n"
168
169			 "     return unmarshal(_any.extract_Streamable());\n"
170			 "   }\n\n"
171
172
173			 %% In corba mapping there is also a _type function here.
174			 "}\n"]),
175    file:close(Fd).
176
177
178%%-----------------------------------------------------------------
179%% Func: emit_struct_members_declarations/
180%%-----------------------------------------------------------------
181emit_struct_members_declarations(_, _, _, _, []) ->
182    ok;
183emit_struct_members_declarations(G, N, X, Fd, [{Member, _Type, Id} | MList]) ->
184    ic_codegen:emit(Fd, ["   public ",ic_java_type:getType(G, N, Member)," ",Id,";\n"]),
185    emit_struct_members_declarations(G, N, X, Fd, MList).
186
187
188
189%%-----------------------------------------------------------------
190%% Func: emit_struct_members_initialisation/5
191%%-----------------------------------------------------------------
192emit_struct_members_initialisation(_, _, _, _, []) ->
193    ok;
194emit_struct_members_initialisation(G, N, X, Fd, [{_Member, _Type, Id} | MList]) ->
195    ic_codegen:emit(Fd, ["     ",Id," = _",Id,";\n"]),
196    emit_struct_members_initialisation(G, N, X, Fd, MList).
197
198
199
200
201%%-----------------------------------------------------------------
202%% Func: emit_struct_marshal_function/7
203%%-----------------------------------------------------------------
204emit_struct_marshal_function(G, N, X, Fd, StructName, WireStructName, MList) ->
205
206    ic_codegen:emit(Fd, ["     _out.write_tuple_head(",integer_to_list(length(MList) + 1),");\n"
207			 "     _out.write_atom(\"",ic_util:to_undersc([WireStructName|N]),"\");\n\n"]),
208
209    emit_struct_marshal_function_loop(G, [StructName ++ "Package" |N],
210				      X, Fd, MList, 1).
211
212%%-----------------------------------------------------------------
213%% Func: emit_struct_marshal_function_loop/6
214%%-----------------------------------------------------------------
215emit_struct_marshal_function_loop(_, _, _, Fd, [], _) ->
216    ic_codegen:nl(Fd);
217emit_struct_marshal_function_loop(G, N, X, Fd, [{Member, Type, Id} |MList], Num) ->
218
219    case ic_java_type:isBasicType(G, N, Member) of
220	true ->
221	    ic_codegen:emit(Fd, ["     _out",ic_java_type:marshalFun(G, N, Member, Type),"(_value.",Id,");\n"]);
222	_ ->
223	    if (element(1,hd(element(3,Member))) == array) ->
224		    ic_codegen:emit(Fd,
225				    ["     ",
226				     ic_util:to_dot(G,[ic_forms:get_id2(Member)|N]),
227				     "Helper.marshal(_out, _value.",Id,");\n"]);
228	       true ->
229		    ic_codegen:emit(Fd, ["     ",
230					 ic_java_type:marshalFun(G, N, Member, Type),
231					 "(_out, _value.",Id,");\n"])
232	    end
233    end,
234
235    emit_struct_marshal_function_loop(G, N, X, Fd, MList, Num+1).
236
237
238
239
240%%-----------------------------------------------------------------
241%% Func: emit_struct_unmarshal_function/7
242%%-----------------------------------------------------------------
243emit_struct_unmarshal_function(G, N, X, Fd, StructName, WireStructName, MList) ->
244
245    ic_codegen:emit(Fd, ["     _in.read_tuple_head();\n\n"
246
247			 "     if ((_in.read_atom()).compareTo(\"",
248			 ic_util:to_undersc([WireStructName|N]),
249			 "\") != 0)\n"
250			 "       throw new java.lang.Exception(\"\");\n\n"
251
252			 "     ",StructName," _value = new ",StructName,"();\n"]),
253
254    emit_struct_unmarshal_function_loop(G, [StructName ++ "Package"|N],
255					X, Fd, MList, 1),
256
257    ic_codegen:emit(Fd, "     return _value;\n").
258
259%%-----------------------------------------------------------------
260%% Func:  emit_union_unmarshal_function_loop/6
261%%-----------------------------------------------------------------
262emit_struct_unmarshal_function_loop(_, _, _, Fd, [], _) ->
263    ic_codegen:nl(Fd);
264emit_struct_unmarshal_function_loop(G, N, X, Fd, [{Member, Type, Id} |MList], Num) ->
265
266    case ic_java_type:isBasicType(G, N, Member) of
267	true ->
268	    ic_codegen:emit(Fd, ["     _value.",Id," = _in",ic_java_type:unMarshalFun(G, N, Member, Type),";\n"]);
269	_ ->
270	    if (element(1,hd(element(3,Member))) == array) ->
271		    ic_codegen:emit(Fd,
272				    ["     _value.",Id," = ",ic_util:to_dot(G,[ic_forms:get_id2(Member)|N]),"Helper.unmarshal(_in);\n"]);
273	       true ->
274		    ic_codegen:emit(Fd,
275				    ["     _value.",Id," = ",ic_java_type:getUnmarshalType(G, N, Member, Type),".unmarshal(_in);\n"])
276	    end
277    end,
278
279    emit_struct_unmarshal_function_loop(G, N, X, Fd, MList, Num +1).
280
281
282
283%%-----------------------------------------------------------------
284%% Func: gen_parameter_list/4
285%%-----------------------------------------------------------------
286gen_parameter_list(G, N, _X, [{Member, _Type, Id}]) ->
287    ic_java_type:getType(G,N,Member) ++
288	" _" ++
289	ic_util:to_list(Id);
290gen_parameter_list(G, N, X, [{Member, _Type, Id} | MList]) ->
291    ic_java_type:getType(G,N,Member) ++
292	" _" ++
293	ic_util:to_list(Id) ++
294	", " ++
295	gen_parameter_list(G, N, X, MList).
296
297
298%%-----------------------------------------------------------------
299%% Func: struct_member_list/3
300%%-----------------------------------------------------------------
301struct_member_list(_G, _N, X) ->
302    M = lists:map(
303	  fun(Member) ->
304		  lists:map(
305		    fun(Id) ->
306			    Type = ic_forms:get_type(Member),
307			    { Member, Type, ic_forms:get_java_id(Id)}
308		    end,
309		    ic_forms:get_idlist(Member))
310	  end,
311	  ic_forms:get_body(X)),
312    lists:flatten(M).
313
314
315
316