'Setup the pipelines according to config.
The configuration is supported as follows:
Decoupled: the source and sink configuration are separately
specified before being linked together. This allows source-
specific configuration, such as meter handling, to be
kept focused only on the fine-grained source while avoiding
the necessity for wide duplication of sink-related config.
The configuration is provided in the form of separate lists
of dictionaries defining sources and sinks, for example:
{"sources": [{"name": source_1,
"meters" : ["meter_1", "meter_2"],
"sinks" : ["sink_1", "sink_2"]
{"name": source_2,
"meters" : ["meter_3"],
"sinks" : ["sink_2"]
"sinks": [{"name": sink_1,
"transformers": [
{"name": "Transformer_1",
"parameters": {"p1": "value"}},
{"name": "Transformer_2",
"parameters": {"p1": "value"}},
"publishers": ["publisher_1", "publisher_2"]
{"name": sink_2,
"publishers": ["publisher_3"]
Valid meter format is \'*\', \'!meter_name\', or \'meter_name\'.
\'*\' is wildcard symbol means any meters; \'!meter_name\' means
"meter_name" will be excluded; \'meter_name\' means \'meter_name\'
will be included.
Valid meters definition is all "included meter names", all
"excluded meter names", wildcard and "excluded meter names", or
only wildcard.
Transformer\'s name is plugin name in setup.cfg.
Publisher\'s name is plugin name in setup.cfg'

def __init__(self, conf, cfg_file, transformer_manager, p_type=SAMPLE_TYPE):

    super(PipelineManager, self).__init__(conf)
    cfg = self.load_config(cfg_file)
    self.pipelines = []
    if (not (('sources' in cfg) and ('sinks' in cfg))):
        raise PipelineException('Both    sources    &    sinks    are    required', cfg)
    LOG.info('detected    decoupled    pipeline    config    format')
    publisher_manager = PublisherManager(self.conf, p_type['name'])
    unique_names = set()
    sources = []
    for s in cfg.get('sources'):
        name = s.get('name')
        if (name in unique_names):
            raise PipelineException(('Duplicated    source    names:    %s' % name), self)
        else:
            unique_names.add(name)
            sources.append(p_type['source'](s))
    unique_names.clear()
    sinks = {}
    for s in cfg.get('sinks'):
        name = s.get('name')
        if (name in unique_names):
            raise PipelineException(('Duplicated    sink    names:    %s' % name), self)
        else:
            unique_names.add(name)
            sinks[s['name']] = p_type['sink'](self.conf, s, transformer_manager, publisher_manager)
    unique_names.clear()
    for source in sources:
        source.check_sinks(sinks)
        for target in source.sinks:
            pipe = p_type['pipeline'](self.conf, source, sinks[target])
            if (pipe.name in unique_names):
                raise PipelineException(('Duplicate    pipeline    name:    %s.    Ensure    pipeline    names    are    unique.    (name    is    the    source    and    sink    names    combined)' % pipe.name), cfg)
            else:
                unique_names.add(pipe.name)
                self.pipelines.append(pipe)
    unique_names.clear()
