Skip to content

Commit

Permalink
Allow to pass options to erlsom (fix issue #65)
Browse files Browse the repository at this point in the history
  • Loading branch information
willemdj committed Oct 29, 2011
1 parent 942e307 commit ec553ff
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 40 deletions.
71 changes: 46 additions & 25 deletions src/yaws_soap_lib.erl
Expand Up @@ -55,8 +55,9 @@ write_hrl(WsdlURL, Output) when is_list(WsdlURL) ->
write_hrl(#wsdl{model = Model}, Output) when is_list(Output) ->
erlsom:write_hrl(Model, Output).

write_hrl(WsdlURL, Output, Prefix) when is_list(WsdlURL),is_list(Prefix) ->
write_hrl(initModel(WsdlURL, Prefix), Output).
write_hrl(WsdlURL, Output, PrefixOrOptions)
when is_list(WsdlURL),is_list(PrefixOrOptions) ->
write_hrl(initModel(WsdlURL, PrefixOrOptions), Output).



Expand Down Expand Up @@ -278,9 +279,22 @@ mk_envelope(Messages, Headers) when is_list(Messages),is_list(Headers) ->
initModel(WsdlFile) ->
initModel(WsdlFile, ?DefaultPrefix).

initModel(WsdlFile, Prefix) ->
%% PrefixOrOptions can be a property list that contains the options
%% for Erlsom, or a String. If it is a string, this is used as the
%% Erlsom 'prefix' option (and the other options are left unspecified).
initModel(WsdlFile, PrefixOrOptions) ->
Options = case is_string(PrefixOrOptions) of
no ->
%% It is an option list
%% Add the default prefix at the end - it will only be used
%% if no other prefix is specified
PrefixOrOptions ++ [{prefix, ?DefaultPrefix}];
_ ->
%% just the prefix
[{prefix, PrefixOrOptions}]
end,
PrivDir = priv_dir(),
initModel2(WsdlFile, Prefix, PrivDir, undefined, undefined).
initModel2(WsdlFile, Options, PrivDir, undefined, undefined).

initModelFile(ConfigFile) ->
{ok, ConfigSchema} = erlsom:compile_xsd(config_file_xsd()),
Expand All @@ -290,7 +304,7 @@ initModelFile(ConfigFile) ->
wsdl_file = Wsdl,
add_files = AddFiles} = Config,
#xsd_file{name = WsdlFile, prefix = Prefix, import_specs = Import} = Wsdl,
initModel2(WsdlFile, Prefix, XsdPath, Import, AddFiles).
initModel2(WsdlFile, [{prefix, Prefix}], XsdPath, Import, AddFiles).

priv_dir() ->
case code:priv_dir(yaws) of
Expand All @@ -300,7 +314,7 @@ priv_dir() ->
A
end.

initModel2(WsdlFile, Prefix, Path, Import, AddFiles) ->
initModel2(WsdlFile, ErlsomOptions, Path, Import, AddFiles) ->
WsdlName = filename:join([Path, "wsdl.xsd"]),
IncludeWsdl = {"http://schemas.xmlsoap.org/wsdl/", "wsdl", WsdlName},
{ok, WsdlModel} = erlsom:compile_xsd_file(
Expand All @@ -309,9 +323,9 @@ initModel2(WsdlFile, Prefix, Path, Import, AddFiles) ->
{include_files, [IncludeWsdl]}]),
%% add the xsd model (since xsd is also used in the wsdl)
WsdlModel2 = erlsom:add_xsd_model(WsdlModel),
Options = makeOptions(Import),
Options = ErlsomOptions ++ makeOptions(Import),
%% parse Wsdl
{Model, Operations} = parseWsdls([WsdlFile], Prefix, WsdlModel2,
{Model, Operations} = parseWsdls([WsdlFile], WsdlModel2,
Options, {undefined, []}),
%% TODO: add files as required
%% now compile envelope.xsd, and add Model
Expand All @@ -327,21 +341,19 @@ initModel2(WsdlFile, Prefix, Path, Import, AddFiles) ->
%%% Parse a list of WSDLs and import (recursively)
%%% Returns {Model, Operations}
%%% --------------------------------------------------------------------
parseWsdls([], _Prefix, _WsdlModel, _Options, Acc) ->
parseWsdls([], _WsdlModel, _Options, Acc) ->
Acc;
parseWsdls([WsdlFile | Tail], Prefix, WsdlModel, Options, {AccModel, AccOperations}) ->
parseWsdls([WsdlFile | Tail], WsdlModel, Options, {AccModel, AccOperations}) ->
{ok, WsdlFileContent} = get_url_file(rmsp(WsdlFile)),
{ok, ParsedWsdl, _} = erlsom:scan(WsdlFileContent, WsdlModel),
%% get the xsd elements from this model, and hand it over to erlsom_compile.
Xsds = getXsdsFromWsdl(ParsedWsdl),
%% Now we need to build a list: [{Namespace, Xsd, Prefix}, ...] for
%% all the Xsds in the WSDL.
%% This list is used when a schema inlcudes one of the other schemas.
%% The AXIS java2wsdl
%% generates wsdls that depend on this feature.
%% This list is used when a schema includes one of the other schemas.
%% The AXIS java2wsdl tool generates wsdls that depend on this feature.
ImportList = makeImportList(Xsds, []),
%% TODO: pass the right options here
Model2 = addSchemas(Xsds, AccModel, Prefix, Options, ImportList),
Model2 = addSchemas(Xsds, AccModel, Options, ImportList),
Ports = getPorts(ParsedWsdl),
Operations = getOperations(ParsedWsdl, Ports),
Imports = getImports(ParsedWsdl),
Expand All @@ -350,14 +362,13 @@ parseWsdls([WsdlFile | Tail], Prefix, WsdlModel, Options, {AccModel, AccOperatio
%% processed as well).
%% For the moment, the namespace is ignored on operations etc.
%% this makes it a bit easier to deal with imported wsdl's.
Acc3 = parseWsdls(Imports, Prefix, WsdlModel, Options, Acc2),
parseWsdls(Tail, Prefix, WsdlModel, Options, Acc3).
Acc3 = parseWsdls(Imports, WsdlModel, Options, Acc2),
parseWsdls(Tail, WsdlModel, Options, Acc3).

%%% --------------------------------------------------------------------
%%% build a list: [{Namespace, Xsd}, ...] for all the Xsds in the WSDL.
%%% This list is used when a schema inlcudes one of the other schemas.
%%% The AXIS java2wsdl
%%% generates wsdls that depend on this feature.
%%% The AXIS java2wsdl tool generates wsdls that depend on this feature.
makeImportList([], Acc) ->
Acc;
makeImportList([ Xsd | Tail], Acc) ->
Expand All @@ -370,24 +381,23 @@ makeImportList([ Xsd | Tail], Acc) ->
%%% Returns Model
%%% (TODO: using the same prefix for all XSDS makes no sense)
%%% --------------------------------------------------------------------
addSchemas([], AccModel, _Prefix, _Options, _ImportList) ->
addSchemas([], AccModel, _Options, _ImportList) ->
AccModel;
addSchemas([Xsd| Tail], AccModel, Prefix, Options, ImportList) ->
addSchemas([Xsd| Tail], AccModel, Options, ImportList) ->
Model2 = case Xsd of
undefined ->
AccModel;
_ ->
{ok, Model} =
erlsom_compile:compile_parsed_xsd(
Xsd,
[{prefix, Prefix},
{include_files, ImportList} |Options]),
[{include_files, ImportList} |Options]),
case AccModel of
undefined -> Model;
_ -> erlsom:add_model(AccModel, Model)
end
end,
addSchemas(Tail, Model2, Prefix, Options, ImportList).
addSchemas(Tail, Model2, Options, ImportList).

%%% --------------------------------------------------------------------
%%% Get a file from an URL spec.
Expand Down Expand Up @@ -669,11 +679,20 @@ searchPorts(BindingName, [Port | Tail], Acc) ->
searchPorts(BindingName, Tail, Acc)
end.

%% copied from yaws/json.erl
is_string([]) -> yes;
is_string(List) -> is_string(List, non_unicode).

is_string([C|Rest], non_unicode) when C >= 0, C =< 255 -> is_string(Rest, non_unicode);
is_string([C|Rest], _) when C =< 65000 -> is_string(Rest, unicode);
is_string([], non_unicode) -> yes;
is_string([], unicode) -> unicode;
is_string(_, _) -> no.

getXsdsFromWsdl(Definitions) ->
case getTopLevelElements(Definitions, 'wsdl:tTypes') of
[#'wsdl:tTypes'{choice = Xsds}] -> Xsds;
[] -> undefined
[] -> []
end.

config_file_xsd() ->
Expand Down Expand Up @@ -701,3 +720,5 @@ config_file_xsd() ->
" <xs:attribute name=\"location\" type=\"string\"/>"
" </xs:complexType>"
"</xs:schema>".


15 changes: 8 additions & 7 deletions src/yaws_soap_srv.erl
Expand Up @@ -79,9 +79,14 @@ setup(Id, WsdlFile) when is_tuple(Id),size(Id)==2 ->
Wsdl = yaws_soap_lib:initModel(WsdlFile),
gen_server:call(?SERVER, {add_wsdl, Id, Wsdl}, infinity).


setup(Id, WsdlFile, Prefix) when is_tuple(Id),size(Id)==2 ->
Wsdl = yaws_soap_lib:initModel(WsdlFile, Prefix),
%% PrefixOrOptions can be either a prefix (a String) or a property
%% list. It is used to construct the options that are passed to Erlsom
%% to compile the WSDL file. Passing a string ("Prefix") is equivalent
%% to [{prefix, "Prefix"}].
%% If a list of erlsom options is passed, and this does not contain
%% the {prefix, ...} option, the yaws_soap default ("p") will be used.
setup(Id, WsdlFile, PrefixOrOptions) when is_tuple(Id),size(Id)==2 ->
Wsdl = yaws_soap_lib:initModel(WsdlFile, PrefixOrOptions),
gen_server:call(?SERVER, {add_wsdl, Id, Wsdl}, infinity).


Expand Down Expand Up @@ -266,7 +271,3 @@ get_model(State, Id) ->
uinsert({K,_} = E, [{K,_}|T]) -> [E|T];
uinsert(E, [H|T]) -> [H|uinsert(E,T)];
uinsert(E, []) -> [E].




21 changes: 13 additions & 8 deletions www/soap_intro.yaws
Expand Up @@ -224,7 +224,15 @@ out(A) ->
"functions above may as well be a local file, and thus written as \"file://....\". "},
{li, [],
"When we retrieve a HTTP located file, we will use 'ibrowse' if it exist "
"in the code path. Otherwise we will use the OTP 'http' client."}
"in the code path. Otherwise we will use the OTP 'http' client."},
{li, [],
"The prefix ('foo' in the example above) is passed to erlsom - it is one of erlsom's "
"options. If you want to specify other options, you can also pass the regular erlsom "
"options to yaws_soap_lib:initModel/2 and yaws_soap_lib:write_hrl/3. For example, to "
"specify how files that the XSD inside the WSDL refers to via 'include' statements "
"can be retrieved, you can pass it a function GetIncludes/4 by specifying "
"[{include_fun, GetIncludes}]. See the erlsom documentation for other options that you "
"could specify."}
]}]},

{h2, [], "The SOAP server side"},
Expand Down Expand Up @@ -346,7 +354,10 @@ out(A) ->
),

{p,[],
"Now, in your Yaws shell, setup the Soap server as shown below:"
"Now, in your Yaws shell, setup the Soap server as shown below. (If required, for "
"example to specify a prefix or a function to retrieve included files, you can specify "
"options similar to what we saw above for yaws_soap_lib:initModel/2 and "
"yaws_soap_lib:write_hrl/3 , using yaws_soap_srv:setup/3.)"
},

box("6> yaws:start_embedded(Docroot,SL,GL).\n"
Expand Down Expand Up @@ -396,9 +407,3 @@ out(A) ->

</erl>







0 comments on commit ec553ff

Please sign in to comment.