# Tai Sakuma <tai.sakuma@gmail.com>

##__________________________________________________________________||
def FactoryDispatcher(path_cfg, **kargs):

    alias_dict = kargs['aliasDict'] if 'aliasDict' in kargs else None
    path_cfg = expand_path_cfg(path_cfg, alias_dict=alias_dict)

    if not isinstance(path_cfg, dict):
        raise ValueError("cannot recognize the path_cfg")

    if 'factory' not in path_cfg:
        raise ValueError("cannot recognize the path_cfg")

    path_cfg_copy = path_cfg.copy()
    factoryName = path_cfg_copy.pop('factory')
    factory = find_factory(factoryName)
    kargs_copy = kargs.copy()
    kargs_copy.update(path_cfg_copy)

    return factory(**kargs_copy)

##__________________________________________________________________||
def expand_path_cfg(path_cfg, alias_dict=None, overriding_kargs=dict()):

    if isinstance(path_cfg, str):
        if alias_dict is not None and path_cfg in alias_dict:
            new_overriding_kargs = dict(alias=path_cfg)
            new_overriding_kargs.update(overriding_kargs)
            return expand_path_cfg(alias_dict[path_cfg], alias_dict=alias_dict, overriding_kargs=new_overriding_kargs)

        ret = dict(factory='LambdaStrFactory', lambda_str=path_cfg)

        overriding_kargs_copy = overriding_kargs.copy()
        if 'alias' in overriding_kargs: ret['name'] = overriding_kargs_copy.pop('alias')
        if 'name' in overriding_kargs: ret['name'] = overriding_kargs_copy.pop('name')
        ret.update(overriding_kargs_copy)

        return ret

    if not isinstance(path_cfg, dict):
        # assume tuple or list
        if isinstance(path_cfg[0], str) and isinstance(path_cfg[1], dict):
            new_overriding_kargs = path_cfg[1].copy()
            new_overriding_kargs.update(overriding_kargs)
            return expand_path_cfg(path_cfg[0], overriding_kargs=new_overriding_kargs, alias_dict=alias_dict)

        raise ValueError("cannot recognize the path_cfg")

    if isinstance(path_cfg, dict):
        if 'factory' in path_cfg: return path_cfg

        if not sum([k in path_cfg for k in ('All', 'Any', 'Not')]) <= 1:
            raise ValueError("Any pair of 'All', 'Any', 'Not' cannot be simultaneously given unless factory is given!")

        if 'All' in path_cfg:
            new_path_cfg = path_cfg.copy()
            new_path_cfg['factory'] = 'AllFactory'
            new_path_cfg['path_cfg_list'] = new_path_cfg.pop('All')
            return new_path_cfg

        if 'Any' in path_cfg:
            new_path_cfg = path_cfg.copy()
            new_path_cfg['factory'] = 'AnyFactory'
            new_path_cfg['path_cfg_list'] = new_path_cfg.pop('Any')
            return new_path_cfg

        if 'Not' in path_cfg:
            new_path_cfg = path_cfg.copy()
            new_path_cfg['factory'] = 'NotFactory'
            new_path_cfg['path_cfg'] = new_path_cfg.pop('Not')
            return new_path_cfg

    raise ValueError("cannot recognize the path_cfg")

##__________________________________________________________________||
def find_factory(name):
    import imp

    top_module_name = 'factories'
    f, filename, description = imp.find_module(top_module_name)
    top_module = imp.load_module(top_module_name, f, filename, description)
    ##______________________________________________________________||

    module_name = "{}.{}".format(top_module_name, name)
    # e.g., 'factories.AllFactory'

    f, filename, description = imp.find_module(name, top_module.__path__)
    module = imp.load_module(module_name, f, filename, description)

    factory = getattr(module, name)

    return factory

##__________________________________________________________________||

@@ -1085,16 +1085,33 @@
 ath_cfg(
+%0A                
 alias_di
@@ -1123,16 +1123,32 @@
 th_cfg%5D,
+%0A               
  alias_d
@@ -1162,16 +1162,32 @@
 as_dict,
+%0A               
  overrid
@@ -1216,16 +1216,29 @@
 ng_kargs
+%0A            
 )%0A%0A     
@@ -1388,32 +1388,44 @@
 verriding_kargs:
+%0A           
  ret%5B'name'%5D = o
@@ -1458,16 +1458,17 @@
 alias')%0A
+%0A
         
@@ -1497,16 +1497,28 @@
 g_kargs:
+%0A           
  ret%5B'na
@@ -1558,16 +1558,17 @@
 'name')%0A
+%0A
         
@@ -1597,25 +1597,24 @@
 kargs_copy)%0A
-%0A
         retu
@@ -1913,28 +1913,61 @@
 ath_cfg(
-path_cfg%5B0%5D,
+%0A                path_cfg%5B0%5D,%0A               
  overrid
@@ -1997,16 +1997,32 @@
 g_kargs,
+%0A               
  alias_d
@@ -2031,24 +2031,37 @@
 t=alias_dict
+%0A            
 )%0A%0A        r

clean up the code in FactoryDispatcher.py