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_sequence_java).
23
24
25-include("icforms.hrl").
26-include("ic.hrl").
27-include("ic_debug.hrl").
28%%-----------------------------------------------------------------
29%% External exports
30%%-----------------------------------------------------------------
31-export([gen/4]).
32
33%%-----------------------------------------------------------------
34%% Internal exports
35%%-----------------------------------------------------------------
36-export([]).
37
38%%-----------------------------------------------------------------
39%% External functions
40%%-----------------------------------------------------------------
41
42%%-----------------------------------------------------------------
43%% Func: gen/4
44%%-----------------------------------------------------------------
45gen(G, N, X, SequenceName) when is_record(X, sequence) ->
46    emit_holder_class(G, N, X, SequenceName),
47    emit_helper_class(G, N, X, SequenceName);
48gen(_G, _N, _X, _SequenceName) ->
49    ok.
50
51
52%%-----------------------------------------------------------------
53%% Internal functions
54%%-----------------------------------------------------------------
55
56
57%%-----------------------------------------------------------------
58%% Func:  emit_holder_class/4
59%%-----------------------------------------------------------------
60emit_holder_class(G, N, X, SequenceName) ->
61    SName = string:concat(SequenceName, "Holder"),
62    {Fd, _}= ic_file:open_java_file(G, N, SName),
63
64    SequenceType = ic_java_type:getType(G, N, X),
65
66    ic_codegen:emit(Fd, ["final public class ",SequenceName,"Holder {\n"
67			 "   // instance variables\n"
68			 "   public ",SequenceType," value;\n\n"
69			 "   // constructors\n"
70			 "   public ",SequenceName,"Holder() {}\n"
71			 "   public ",SequenceName,"Holder(",SequenceType," initial) {\n"
72			 "      value = initial;\n"
73			 "   }\n\n"
74
75			 "   // methods\n"
76
77			 "   public void _marshal(",?ERLANGPACKAGE,"OtpOutputStream out) throws java.lang.Exception{\n"
78			 "      ",SequenceName,"Helper.marshal(out, value);\n"
79			 "   }\n\n"
80
81			 "   public void _unmarshal(",?ERLANGPACKAGE,"OtpInputStream in) throws java.lang.Exception {\n"
82			 "      value = ",SequenceName,"Helper.unmarshal(in);\n"
83			 "   }\n\n"
84			 "}\n"]),
85    file:close(Fd).
86
87
88
89emit_helper_class(G, N, X, SequenceName) ->
90    SName = string:concat(SequenceName, "Helper"),
91    {Fd, _}= ic_file:open_java_file(G, N, SName),
92
93    SequenceType = ic_java_type:getType(G, N, X),
94    ElementType = ic_forms:get_type(X),
95
96    ic_codegen:emit(Fd, ["public class ",SequenceName,"Helper {\n"
97
98			 "   // constructors\n"
99			 "   private ",SequenceName,"Helper() {}\n\n"
100
101			 "   // methods\n"
102			 "   public static void marshal(",?ERLANGPACKAGE,"OtpOutputStream _out, ",SequenceType," _value) \n"
103			 "     throws java.lang.Exception {\n\n"]),
104
105    emit_sequence_marshal_function(G, N, X, Fd, SequenceName, ElementType),
106
107    ic_codegen:emit(Fd, ["   }\n\n"
108
109			 "   public static ",SequenceType," unmarshal(",?ERLANGPACKAGE,"OtpInputStream _in) \n"
110			 "     throws java.lang.Exception {\n\n"]),
111
112    emit_sequence_unmarshal_function(G, N, X, Fd, SequenceName, ElementType),
113
114    ic_codegen:emit(Fd, ["   }\n\n"
115
116			 "   public static String id() {\n"
117			 "      return \"",ic_pragma:scope2id(G, [SequenceName | N]),"\";\n"
118			 "   }\n\n"
119
120			 "   public static String name() {\n"
121			 "      return \"",SequenceName,"\";\n"
122			 "   }\n\n"]),
123
124    ic_jbe:emit_type_function(G, N, X, Fd),
125
126    ic_codegen:emit(Fd, ["   public static void insert(",?ICPACKAGE,"Any _any, ",SequenceType," _this)\n"
127			 "     throws java.lang.Exception {\n\n"
128
129			 "     ",?ERLANGPACKAGE,"OtpOutputStream _os = \n"
130			 "       new ",?ERLANGPACKAGE,"OtpOutputStream();\n\n"
131
132			 "     _any.type(type());\n"
133			 "     marshal(_os, _this);\n"
134			 "     _any.insert_Streamable(_os);\n"
135			 "   }\n\n"
136
137			 "   public static ",SequenceType," extract(",?ICPACKAGE,"Any _any)\n"
138			 "     throws java.lang.Exception {\n\n"
139
140			 "     return unmarshal(_any.extract_Streamable());\n"
141			 "   }\n\n"
142
143
144    %% In corba mapping there is also a _type function here.
145			 "}\n\n"]),
146    file:close(Fd).
147
148
149%%-----------------------------------------------------------------
150%% Func: emit_sequence_marshal_function/6
151%%-----------------------------------------------------------------
152emit_sequence_marshal_function(G, N, X, Fd, _SequenceName, ElementType) ->
153    ic_codegen:emit(Fd, ["    int _length = _value.length;\n\n"
154
155			 "    _out.write_list_head(_length);\n\n"
156
157			 "    if (_length > 0) {\n"
158			 "      for(int _tmp = 0; _tmp < _length; _tmp++)\n"]),
159
160    case ic_java_type:isBasicType(G, N, ElementType) of
161	true ->
162	    ic_codegen:emit(Fd, ["        _out",ic_java_type:marshalFun(G, N, X, ElementType),"(_value[_tmp]);\n\n"]);
163	false ->
164	    ic_codegen:emit(Fd, ["        ",ic_java_type:marshalFun(G, N, X, ElementType),"(_out, _value[_tmp]);\n\n"])
165    end,
166
167    ic_codegen:emit(Fd, ["      _out.write_nil();\n"
168			 "    }\n\n"]).
169
170
171
172
173%%-----------------------------------------------------------------
174%% Func: emit_sequence_unmarshal_function/6
175%%-----------------------------------------------------------------
176emit_sequence_unmarshal_function(G, N, X, Fd, _SequenceName, ElementType) ->
177
178    SequenceElementType = ic_java_type:getType(G, N, ElementType),
179
180    ic_codegen:emit(Fd, ["    int _tag,_length;\n"
181			 "    ",SequenceElementType," _sequence[];\n"
182			 "    _tag = _in.peek();\n\n"]),
183
184    case ic_java_type:isIntegerType(G, N, ElementType) of
185	true ->
186	    ic_codegen:emit(Fd, ["    switch(_tag) {\n"
187				 "    case ",?ERLANGPACKAGE,"OtpExternal.stringTag:\n"
188				 "      byte _compressed[] = (_in.read_string()).getBytes();\n"
189				 "      _length = _compressed.length;\n"
190				 "      _sequence = new ",ic_java_type:getFullType(G,N,X),";\n\n"
191
192				 "      for(int _tmp = 0; _tmp < _length; _tmp++)\n"
193				 "        _sequence[_tmp] = (",ic_java_type:getType(G, N, ElementType),")(_compressed[_tmp] & 0xff);\n\n"
194
195				 "      break;\n"
196				 "    default:\n"
197				 "      _length = _in.read_list_head();\n"
198				 "      _sequence = new ",ic_java_type:getFullType(G,N,X),";\n\n"
199
200				 "      if(_length > 0) {\n"
201				 "        for(int _tmp = 0; _tmp < _length; _tmp++)\n"
202				 "          _sequence[_tmp] = _in",ic_java_type:unMarshalFun(G, N, X, ElementType),";\n\n"
203
204				 "        _in.read_nil();\n"
205				 "      }\n"
206				 "    }\n"]);
207	false ->
208	    ic_codegen:emit(Fd, ["    _length = _in.read_list_head();\n"
209				 "    _sequence = new ",ic_java_type:getFullType(G,N,X),";\n\n"
210
211				 "    if(_length > 0) {\n"
212				 "      for(int _tmp = 0; _tmp < _length; _tmp++)\n"]),
213	    case ic_java_type:isBasicType(G, N, ElementType) of
214		true ->
215		    ic_codegen:emit(Fd, ["        _sequence[_tmp] = _in",ic_java_type:unMarshalFun(G, N, X, ElementType),";\n\n"]);
216		_ ->
217		    ic_codegen:emit(Fd, ["        _sequence[_tmp] = ",ic_java_type:getUnmarshalType(G, N, X, ElementType),".unmarshal(_in);\n\n"])
218	    end,
219
220	    ic_codegen:emit(Fd, ["      _in.read_nil();\n"
221				 "    }\n\n"])
222    end,
223
224    ic_codegen:emit(Fd, "    return _sequence;\n").
225
226
227
228
229%%---------------------------------------------------
230%%  Utilities
231%%---------------------------------------------------
232
233
234
235
236
237
238
239
240
241