%% Copyright 2010, 2011, 2012 Tony Garnock-Jones . %% %% This file is part of Hop. %% %% Hop is free software: you can redistribute it and/or modify it %% under the terms of the GNU General Public License as published by %% the Free Software Foundation, either version 3 of the License, or %% (at your option) any later version. %% %% Hop is distributed in the hope that it will be useful, but WITHOUT %% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY %% or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public %% License for more details. %% %% You should have received a copy of the GNU General Public License %% along with Hop. If not, see . -module(hop_factory). -behaviour(gen_server). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]). -export([start_link/1, register_class/2]). start_link(Args) -> gen_server:start_link({local, ?MODULE}, ?MODULE, Args, []). register_class(ClassName, ClassModule) -> gen_server:call(?MODULE, {register_class, ClassName, ClassModule}). %%--------------------------------------------------------------------------- -record(state, {classes}). init([]) -> yes = global:register_name(<<"factory">>, self()), {ok, #state{classes = []}}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. handle_call({register_class, ClassName, ClassModule}, _From, State = #state{classes = Classes}) -> {reply, ok, State#state{classes = [{ClassName, ClassModule} | Classes]}}; handle_call(_Request, _From, State) -> {stop, {bad_call, _Request}, State}. handle_cast(_Request, State) -> {stop, {bad_cast, _Request}, State}. handle_info({hop, Sexp}, State = #state{classes = Classes}) -> case Sexp of [<<"create">>, ClassName, Arg, ReplySink, ReplyName] -> Reply = case lists:keysearch(ClassName, 1, Classes) of false -> error_logger:warning_report({?MODULE, class_not_found, ClassName}), [<<"create-failed">>, [<<"factory">>, <<"class-not-found">>]]; {value, {_, ClassModule}} -> case catch ClassModule:hop_create(Arg) of {ok, Info} -> [<<"create-ok">>, Info]; {error, Info} -> [<<"create-failed">>, [<<"constructor">>, Info]]; Otherwise -> error_logger:warning_report({?MODULE, creation_failed, Sexp, Otherwise}), [<<"create-failed">>, [<<"constructor">>]] end end, hop:post(ReplySink, ReplyName, Reply, <<>>), {noreply, State}; _ -> error_logger:warning_report({?MODULE, message_not_understood, Sexp}), {noreply, State} end; handle_info(_Message, State) -> {stop, {bad_info, _Message}, State}.