Namdak Tonpa 5 years ago
parent
commit
ca0486f5e5
6 changed files with 98 additions and 30 deletions
  1. 5 5
      mix.exs
  2. 6 0
      src/hist.erl
  3. 58 23
      src/rest.erl
  4. 11 2
      src/rest_kvs.erl
  5. 9 0
      src/step.erl
  6. 9 0
      src/ts.erl

+ 5 - 5
mix.exs

@@ -3,7 +3,7 @@ defmodule REST.Mixfile do
 
 
   def project do
   def project do
     [app: :rest,
     [app: :rest,
-     version: "5.10.3",
+     version: "5.10.5",
      description: "REST erlang interface generator",
      description: "REST erlang interface generator",
      deps: deps(),
      deps: deps(),
      package: package()]
      package: package()]
@@ -12,15 +12,15 @@ defmodule REST.Mixfile do
   def application() do
   def application() do
     [
     [
       mod: {:rest, []},
       mod: {:rest, []},
-      applications: [:public_key,:asn1,:kernel,:stdlib,:ranch,:cowboy,:syntax_tools,:compiler,:rocksdb,:kvs,:n2o,:erp]
+      applications: [:public_key,:asn1,:kernel,:stdlib,:ranch,:cowboy,:syntax_tools,:compiler,:rocksdb,:kvs, :erp, :bpe]
     ]
     ]
   end
   end
 
 
   def deps, do: [ {:ex_doc, ">= 0.0.0", only: :dev},
   def deps, do: [ {:ex_doc, ">= 0.0.0", only: :dev},
                   {:rocksdb, "~> 1.3.2"},
                   {:rocksdb, "~> 1.3.2"},
-                  {:syn, "~> 1.6.3"},
-                  {:erp, "~> 0.10.2"},
-                  {:n2o, "~> 6.9.0"},
+                  {:kvs, "~> 6.9.2"},
+                  {:erp, "~> 0.10.3"},
+                  {:bpe, "~> 4.9.17"},
                   {:jsone, "~> 1.5.0"},
                   {:jsone, "~> 1.5.0"},
                   {:cowboy, "~> 2.5.0"} ]
                   {:cowboy, "~> 2.5.0"} ]
 
 

+ 6 - 0
src/hist.erl

@@ -0,0 +1,6 @@
+-module(hist).
+-include_lib("bpe/include/bpe.hrl").
+-compile({parse_transform, rest}).
+-compile(export_all).
+-rest_record(hist).
+new() -> #hist{}.

+ 58 - 23
src/rest.erl

@@ -3,8 +3,8 @@
 -behaviour(application).
 -behaviour(application).
 -behaviour(supervisor).
 -behaviour(supervisor).
 -export([init/1,start/2, stop/1]).
 -export([init/1,start/2, stop/1]).
--export([behaviour_info/1, parse_transform/2, generate_to_json/3,
-         generate_from_json/3, from_json/1, to_json/1, to_binary/1]).
+-export([behaviour_info/1, parse_transform/2, generate_to_json/3, binarize/1,
+         generate_from_json/3, from_json/2, to_json/1, to_binary/1, parse/1]).
 
 
 stop(_State) -> ok.
 stop(_State) -> ok.
 start(_StartType, _StartArgs) -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
 start(_StartType, _StartArgs) -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
@@ -26,24 +26,42 @@ behaviour_info(callbacks) -> [{exists, 1}, {get, 0}, {get, 1}, {post, 1}, {delet
 behaviour_info(_) -> undefined.
 behaviour_info(_) -> undefined.
 
 
 parse_transform(Forms, _Options) ->
 parse_transform(Forms, _Options) ->
-%    io:format("~p~n", [Forms]),
     RecordName = rest_record(Forms),
     RecordName = rest_record(Forms),
     RecordFields = record_fields(RecordName, Forms),
     RecordFields = record_fields(RecordName, Forms),
     Forms1 = generate({from_json, 2}, RecordName, RecordFields, Forms),
     Forms1 = generate({from_json, 2}, RecordName, RecordFields, Forms),
     Forms2 = generate({to_json, 1}, RecordName, RecordFields, Forms1),
     Forms2 = generate({to_json, 1}, RecordName, RecordFields, Forms1),
-%    io:format("~p~n", [Forms2]),
     Forms2.
     Forms2.
 
 
 rest_record([]) -> [];
 rest_record([]) -> [];
 rest_record([{attribute, _, rest_record, RecordName} | _Forms]) -> RecordName;
 rest_record([{attribute, _, rest_record, RecordName} | _Forms]) -> RecordName;
 rest_record([_ | Forms]) -> rest_record(Forms).
 rest_record([_ | Forms]) -> rest_record(Forms).
 
 
-record_field({record_field, _, {atom, _, Field}   }) -> Field;
-record_field({record_field, _, {atom, _, Field}, _}) -> Field;
-record_field({typed_record_field, {record_field,_,{atom, _, Field},_}, _}) -> Field.
+record_field({record_field, _, {atom, _, Field}   },_cordName) ->
+%  io:format("Case 1: ~p~n",[Field]),
+  Field;
+record_field({record_field, _, {atom, _, Field}, Type},_cordName) ->
+%  io:format("Case 2: ~p~n",[Field]),
+  Field;
+record_field({typed_record_field, {record_field,_,{atom, _, Field},_}, Type},RecordName) ->
+  Rec = allow(Type),
+  put({RecordName,Field},Rec),
+%  case Rec of
+%    undefined -> io:format("Case 3: ~p~n",[Field]);
+%            _ -> io:format("Case 3: ~p, Link: ~p~n",[Field,Rec]) end,
+  Field.
+
+allow({type,_,union,Components}) -> findType(Components);
+allow(Type) -> findType([Type]).
+
+findType([]) -> undefined;
+findType([{type,_,record,[{atom,_,X}]}|T]) -> X;
+findType([{remote_type,_,[{atom,_,_},{atom,_,X},_]}|T]) -> X;
+findType([H|T]) ->
+%  io:format("Unknown Type: ~p~n",[H]),
+  findType(T).
 
 
 record_fields(RecordName, [{attribute, _, record, {RecordName, Fields}} | _Forms]) ->
 record_fields(RecordName, [{attribute, _, record, {RecordName, Fields}} | _Forms]) ->
-    [record_field(Field) || Field <- Fields];
+    [record_field(Field,RecordName) || Field <- Fields];
 record_fields(RecordName, [_ | Forms]) -> record_fields(RecordName, Forms);
 record_fields(RecordName, [_ | Forms]) -> record_fields(RecordName, Forms);
 record_fields(__cordName, []) -> [].
 record_fields(__cordName, []) -> [].
 
 
@@ -76,7 +94,10 @@ from_json_coda(Line) ->
     {clause, Line,
     {clause, Line,
      [{cons, Line, {var, Line, '_'}, {var, Line, 'Json'}}, {var, Line, 'Acc'}],
      [{cons, Line, {var, Line, '_'}, {var, Line, 'Json'}}, {var, Line, 'Acc'}],
      [],
      [],
-     [{call, Line, {atom, Line, from_json}, [{var, Line, 'Json'}, {var, Line, 'Acc'}]}]}.
+     [{call, Line, {atom, Line, from_json}, [
+%     {var, Line, 'Json'} % here is fix for recursive binarized preprocessing to raw X:from_json
+     {call,Line,{remote,Line,{atom,Line,?MODULE},{atom,Line,binarize}},[{var, Line, 'Json'}]}
+     , {var, Line, 'Acc'}]}]}.
 
 
 from_json_clauses(_, _, []) -> [];
 from_json_clauses(_, _, []) -> [];
 from_json_clauses(Line, Record, [Field | Fields]) ->
 from_json_clauses(Line, Record, [Field | Fields]) ->
@@ -97,9 +118,11 @@ from_json_clauses(Line, Record, [Field | Fields]) ->
           Record,
           Record,
           [{record_field, Line,
           [{record_field, Line,
             {atom, Line, Field},
             {atom, Line, Field},
-            {call, Line,
-             {remote, Line, {atom, Line, ?MODULE}, {atom, Line, from_json}},
-             [{var, Line, field_var(Field)}]}}]}]}]}
+             {call, Line,
+             {remote, Line, {atom, Line, ?MODULE }, {atom, Line, from_json}},
+             [{var, Line, field_var(Field)},
+              {atom,Line, case get({Record,Field}) of undefined -> Record; FieldType -> FieldType end}]}
+            }]}]}]}
      | from_json_clauses(Line, Record, Fields)].
      | from_json_clauses(Line, Record, Fields)].
 
 
 generate_from_json({eof, Line}, Record, Fields) ->
 generate_from_json({eof, Line}, Record, Fields) ->
@@ -133,17 +156,24 @@ generate_to_json({eof, Line}, Record, Fields) ->
 
 
 generate_to_json(Form, _, _) -> Form.
 generate_to_json(Form, _, _) -> Form.
 
 
-from_json(<<Data/binary>>) -> binary_to_list(Data);
-from_json({struct, Props}) -> from_json(Props);
-from_json([{Key, _} | _] = Props) when Key =/= struct -> lists:foldr(fun props_skip/2, [], Props);
-from_json([_|_] = NonEmptyList) -> [from_json(X) || X <- NonEmptyList];
-from_json(Any) -> Any.
-
-props_skip({<<BinaryKey/binary>>, Value}, Acc) ->
-    try Key = list_to_existing_atom(binary_to_list(BinaryKey)),
-        props_skip({Key, Value}, Acc)
-    catch _:_ -> Acc end;
-props_skip({Key, Value}, Acc) -> [{Key, from_json(Value)} | Acc].
+from_json(<<Data/binary>>,_) ->
+  binary_to_list(Data);
+from_json({struct, Props},X) ->
+  from_json(Props,X);
+from_json([{Key,_}|_]=Props,X) when Key =/= struct ->
+  X:from_json(binarize(Props),X:new());
+from_json(Any,X) ->
+  Any.
+
+atomize([{Key,_}|_]=Props) when Key =/= struct ->
+  lists:map(fun ({K,V}) when is_atom(K) -> {K,V};
+                ({K,V}) when is_binary(K) -> {list_to_existing_atom(binary_to_list(K)),V} end, Props);
+atomize(X) -> X.
+
+binarize([{Key,_}|_]=Props) when Key =/= struct ->
+  lists:map(fun ({K,V}) when is_atom(K) -> {list_to_binary(atom_to_list(K)),V};
+                ({K,V}) when is_binary(K) -> {K,V} end, Props);
+binarize(X) -> X.
 
 
 to_json(X) when is_tuple(X) -> Module = hd(tuple_to_list(X)), Module:to_json(X);
 to_json(X) when is_tuple(X) -> Module = hd(tuple_to_list(X)), Module:to_json(X);
 to_json(Data) ->
 to_json(Data) ->
@@ -168,3 +198,8 @@ to_binary(I) when is_integer(I) -> to_binary(integer_to_list(I));
 to_binary(F) when is_float(F) -> float_to_binary(F,[{decimals,9},compact]);
 to_binary(F) when is_float(F) -> float_to_binary(F,[{decimals,9},compact]);
 to_binary(L) when is_list(L) ->  iolist_to_binary(L).
 to_binary(L) when is_list(L) ->  iolist_to_binary(L).
 
 
+parse(String) ->
+    {ok,Tokens,_EndLine} = erl_scan:string(String),
+    {ok,AbsForm} = erl_parse:parse_exprs(Tokens),
+    {value,Value,_Bs} = erl_eval:exprs(AbsForm, erl_eval:new_bindings()),
+    Value.

+ 11 - 2
src/rest_kvs.erl

@@ -9,6 +9,7 @@
 -define(REST_JSON, (application:get_env(rest,json,jsone))).
 -define(REST_JSON, (application:get_env(rest,json,jsone))).
 -endif.
 -endif.
 
 
+c(X) when is_tuple(X) -> Module = hd(tuple_to_list(X)), Module:uri(X);
 c(X) -> binary_to_list(X).
 c(X) -> binary_to_list(X).
 
 
 % kvs rest api
 % kvs rest api
@@ -30,7 +31,15 @@ update_req(Req) -> #{ bindings := Bindings, path_info := List } = Req,
 init(#{bindings := #{id := Id}} = Req, State) -> {cowboy_rest, update_req(Req), State};
 init(#{bindings := #{id := Id}} = Req, State) -> {cowboy_rest, update_req(Req), State};
 init(Req, State) -> {cowboy_rest, update_req(Req), State}.
 init(Req, State) -> {cowboy_rest, update_req(Req), State}.
 
 
-resource_exists(#{bindings := #{resource := Module, id := Id}} = Req, State) -> {rest_kvs:exists(Module,Id), Req, State};
+parse_id(Id) ->
+  List = binary_to_list(Id),
+  Parsed = case string:tokens(List,",") of
+     [X] -> Id;
+       _ -> rest:parse(lists:concat(["{",List,"}."]))
+  end.
+
+resource_exists(#{bindings := #{resource := Module, id := Id}} = Req, State) ->
+  {rest_kvs:exists(Module,parse_id(Id)), Req, State};
 resource_exists(#{bindings := #{resource := Module}} = Req, State) -> {rest_kvs:exists(Module), Req, State};
 resource_exists(#{bindings := #{resource := Module}} = Req, State) -> {rest_kvs:exists(Module), Req, State};
 resource_exists(#{bindings := #{id := _}} = Req, State) -> {true, Req, State}.
 resource_exists(#{bindings := #{id := _}} = Req, State) -> {true, Req, State}.
 
 
@@ -62,7 +71,7 @@ default_html_layout(Body) -> [<<"<html><body>">>, Body, <<"</body></html>">>].
 % JSON seems fine
 % JSON seems fine
 
 
 to_json(#{bindings := #{resource := Module, id := Id}} = Req, State) ->
 to_json(#{bindings := #{resource := Module, id := Id}} = Req, State) ->
-    {ok,Resource} = kvs:get(c(Module),c(Id)),
+    {ok,Resource} = kvs:get(c(Module),c(parse_id(Id))),
     Type = element(1,Resource),
     Type = element(1,Resource),
     {iolist_to_binary([?REST_JSON:encode(Type:to_json(Resource)),"\n"]), Req, State};
     {iolist_to_binary([?REST_JSON:encode(Type:to_json(Resource)),"\n"]), Req, State};
 to_json(#{bindings := #{resource := Module}} = Req, State) ->
 to_json(#{bindings := #{resource := Module}} = Req, State) ->

+ 9 - 0
src/step.erl

@@ -0,0 +1,9 @@
+-module(step).
+-include_lib("bpe/include/bpe.hrl").
+-compile({parse_transform, rest}).
+-compile(export_all).
+-rest_record(step).
+new() -> #step{}.
+
+uri({step,No,Proc}) when is_integer(Proc) -> {step,No,integer_to_list(Proc)};
+uri(X) -> X.

+ 9 - 0
src/ts.erl

@@ -0,0 +1,9 @@
+-module(ts).
+-include_lib("bpe/include/bpe.hrl").
+-compile(export_all).
+new() -> {ts,{{0,0,0},{0,0,0}}}.
+to_json(#ts{time=X}) -> [{<<"time">>,lists:flatten(io_lib:format("~p.",[X]))}].
+from_json([{<<"time">>,X}],_) -> #ts{time = rest:parse(X) };
+from_json([{time,X}],_) -> #ts{time = rest:parse(X) }.
+
+