%% 
%% %CopyrightBegin%
%% 
  Copyright Ericsson AB 2006 - 2009 . All Rights Reserved .
%% 
  The contents of this file are subject to the Erlang Public License ,
  Version 1.1 , ( the " License " ) ; you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at /.
%% 
  Software distributed under the License is distributed on an " AS IS "
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
%% 
%% %CopyrightEnd%
%% 

-module(snmp_mini_mib).

  need definition of mib record
-include("snmp_types.hrl").

-export([
	 create/1, 
	 delete/1,
	 aliasname/2,	
	 oid/2, 
	 type/2
	]).


-record(mini_mib, {cache, db = []}).


%%%--------------------------------------------------
  The Mini MIB representation
%%%--------------------------------------------------

%% Returns a Mini MIB
create(Mibs) ->
    Loaded = lists:append([load_mib(Mib) || Mib <- Mibs]),
    Sorted = lists:keysort(1, Loaded),
    Db     = remove_dubbletts(Sorted), 
    Cache  = ets:new(snmp_mini_mib_cache, [set, {keypos, 1}]),
    #mini_mib{cache = Cache, 
	      db    = Db}.

delete(#mini_mib{cache = Cache}) ->
    ets:delete(Cache),
    ok.


%%----------------------------------------------------------------------
  Returns : A list of { Oid , Aliasname , Type }
%%----------------------------------------------------------------------
load_mib(MIB) ->
    F1 = snmp_misc:strip_extension_from_filename(MIB, ".bin"),
    ActualFileName = lists:append(F1, ".bin"),
    case snmp_misc:read_mib(ActualFileName) of
	{ok, #mib{mes = MEs, traps = Traps}} -> 
	    make_mini_mib_elem(MEs++Traps);
	{error, Reason} -> 
	    exit({error, {MIB, Reason}})
    end.


%%----------------------------------------------------------------------
%% Pre: List is sorted (dublettes are list neighbours)
%%----------------------------------------------------------------------
remove_dubbletts([])      -> [];
remove_dubbletts([X])     -> [X];
remove_dubbletts([X,X|T]) -> remove_dubbletts([X|T]);
remove_dubbletts([X|T])   -> [X|remove_dubbletts(T)].


%%----------------------------------------------------------------------
   : A list if 
  Returns : a list of { Oid , Aliasname , Type }
%%----------------------------------------------------------------------
make_mini_mib_elem([]) -> [];
make_mini_mib_elem([#me{aliasname = N, oid = Oid, entrytype = variable,
			 asn1_type = #asn1_type{bertype = Type}} | T]) ->
    [{Oid, N, Type} | make_mini_mib_elem(T)];
make_mini_mib_elem([#me{aliasname = N, oid = Oid, entrytype = table_column,
			 asn1_type = ASN1}|T]) when record(ASN1, asn1_type)->
    [{Oid, N, ASN1#asn1_type.bertype} | make_mini_mib_elem(T)];
make_mini_mib_elem([#me{aliasname = N, oid = Oid,
			 asn1_type = undefined}|T]) ->
    [{Oid, N, undefined} | make_mini_mib_elem(T)];
make_mini_mib_elem([#notification{trapname = N, oid = Oid}|T]) ->
    [{Oid, N, undefined} | make_mini_mib_elem(T)];
make_mini_mib_elem([_|T]) ->
    make_mini_mib_elem(T).


%%----------------------------------------------------------------------
  Returns : false | { Oid , Aliasname , Type }
%%----------------------------------------------------------------------

aliasname(#mini_mib{cache = Cache, db = Db}, Oid) ->
    Key = {Oid, aliasname}, 
    case ets:lookup(Cache, Key) of
	[{_, Value}] ->
	    Value;
	_ ->
	    Value = aliasname(Db, Oid, false),
	    ets:insert(Cache, {Key, Value}),
	    Value
    end.

aliasname([], _Oid, Res) -> 
    Res;
aliasname([{Oid, _Aliasname, _Type} = OidData|T], OidX, Res) 
  when Oid =< OidX ->
    case lists:prefix(Oid, OidX) of
	true ->
	    aliasname(T, OidX, OidData);
	false ->
	    aliasname(T, OidX, Res)
    end;
aliasname([{_Oid, _Aliasname, _Type}|_T], _OidX, Res) ->
    Res.


oid(#mini_mib{db = Db}, AliasName) ->
    case lists:keysearch(AliasName, 2, Db) of
	{value, {Oid, _Aliasname, _Type}} -> 
	    Oid;
	false -> 
	    false
    end.

	    
type(MiniMIB, Oid) ->
    case aliasname(MiniMIB, Oid) of
	{_Oid, _AliasName, Type} ->
	    Type;
	Else ->
	    Else
    end.



 
 %CopyrightBegin%
 
 
 compliance with the License. You should have received a copy of the
 Erlang Public License along with this software. If not, it can be
 retrieved online at /.
 
 basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 the License for the specific language governing rights and limitations
 under the License.
 
 %CopyrightEnd%
 
--------------------------------------------------
--------------------------------------------------
 Returns a Mini MIB
----------------------------------------------------------------------
----------------------------------------------------------------------
----------------------------------------------------------------------
 Pre: List is sorted (dublettes are list neighbours)
----------------------------------------------------------------------
----------------------------------------------------------------------
----------------------------------------------------------------------
----------------------------------------------------------------------
----------------------------------------------------------------------
  Copyright Ericsson AB 2006 - 2009 . All Rights Reserved .
  The contents of this file are subject to the Erlang Public License ,
  Version 1.1 , ( the " License " ) ; you may not use this file except in
  Software distributed under the License is distributed on an " AS IS "

-module(snmp_mini_mib).

  need definition of mib record
-include("snmp_types.hrl").

-export([
	 create/1, 
	 delete/1,
	 aliasname/2,	
	 oid/2, 
	 type/2
	]).


-record(mini_mib, {cache, db = []}).


  The Mini MIB representation

create(Mibs) ->
    Loaded = lists:append([load_mib(Mib) || Mib <- Mibs]),
    Sorted = lists:keysort(1, Loaded),
    Db     = remove_dubbletts(Sorted), 
    Cache  = ets:new(snmp_mini_mib_cache, [set, {keypos, 1}]),
    #mini_mib{cache = Cache, 
	      db    = Db}.

delete(#mini_mib{cache = Cache}) ->
    ets:delete(Cache),
    ok.


  Returns : A list of { Oid , Aliasname , Type }
load_mib(MIB) ->
    F1 = snmp_misc:strip_extension_from_filename(MIB, ".bin"),
    ActualFileName = lists:append(F1, ".bin"),
    case snmp_misc:read_mib(ActualFileName) of
	{ok, #mib{mes = MEs, traps = Traps}} -> 
	    make_mini_mib_elem(MEs++Traps);
	{error, Reason} -> 
	    exit({error, {MIB, Reason}})
    end.


remove_dubbletts([])      -> [];
remove_dubbletts([X])     -> [X];
remove_dubbletts([X,X|T]) -> remove_dubbletts([X|T]);
remove_dubbletts([X|T])   -> [X|remove_dubbletts(T)].


   : A list if 
  Returns : a list of { Oid , Aliasname , Type }
make_mini_mib_elem([]) -> [];
make_mini_mib_elem([#me{aliasname = N, oid = Oid, entrytype = variable,
			 asn1_type = #asn1_type{bertype = Type}} | T]) ->
    [{Oid, N, Type} | make_mini_mib_elem(T)];
make_mini_mib_elem([#me{aliasname = N, oid = Oid, entrytype = table_column,
			 asn1_type = ASN1}|T]) when record(ASN1, asn1_type)->
    [{Oid, N, ASN1#asn1_type.bertype} | make_mini_mib_elem(T)];
make_mini_mib_elem([#me{aliasname = N, oid = Oid,
			 asn1_type = undefined}|T]) ->
    [{Oid, N, undefined} | make_mini_mib_elem(T)];
make_mini_mib_elem([#notification{trapname = N, oid = Oid}|T]) ->
    [{Oid, N, undefined} | make_mini_mib_elem(T)];
make_mini_mib_elem([_|T]) ->
    make_mini_mib_elem(T).


  Returns : false | { Oid , Aliasname , Type }

aliasname(#mini_mib{cache = Cache, db = Db}, Oid) ->
    Key = {Oid, aliasname}, 
    case ets:lookup(Cache, Key) of
	[{_, Value}] ->
	    Value;
	_ ->
	    Value = aliasname(Db, Oid, false),
	    ets:insert(Cache, {Key, Value}),
	    Value
    end.

aliasname([], _Oid, Res) -> 
    Res;
aliasname([{Oid, _Aliasname, _Type} = OidData|T], OidX, Res) 
  when Oid =< OidX ->
    case lists:prefix(Oid, OidX) of
	true ->
	    aliasname(T, OidX, OidData);
	false ->
	    aliasname(T, OidX, Res)
    end;
aliasname([{_Oid, _Aliasname, _Type}|_T], _OidX, Res) ->
    Res.


oid(#mini_mib{db = Db}, AliasName) ->
    case lists:keysearch(AliasName, 2, Db) of
	{value, {Oid, _Aliasname, _Type}} -> 
	    Oid;
	false -> 
	    false
    end.

	    
type(MiniMIB, Oid) ->
    case aliasname(MiniMIB, Oid) of
	{_Oid, _AliasName, Type} ->
	    Type;
	Else ->
	    Else
    end.


