'Convert this map to a nested dictionary structure matching the JSON
configuration for GXP Viewers.
The ``added_layers`` parameter list allows a list of extra MapLayer
instances to append to the Map\'s layer list when generating the
configuration. These are not persisted; if you want to add layers you
should use ``.layer_set.create()``.'

def viewer_json(self, user, access_token, *added_layers):

    if (self.id and (len(added_layers) == 0)):
        cfg = cache.get(((('viewer_json_' + str(self.id)) + '_') + str((0 if (user is None) else user.id))))
        if (cfg is not None):
            return cfg
    layers = list(self.layers)
    layers.extend(added_layers)
    server_lookup = {}
    sources = {}
    def uniqify(seq):
        '\n                                                get    a    list    of    unique    items    from    the    input    sequence.\n\n                                                This    relies    only    on    equality    tests,    so    you    can    use    it    on    most\n                                                things.        If    you    have    a    sequence    of    hashables,    list(set(seq))    is\n                                                better.\n                                                '
        results = []
        for x in seq:
            if (x not in results):
                results.append(x)
        return results
    configs = [l.source_config(access_token) for l in layers]
    i = 0
    for source in uniqify(configs):
        while (str(i) in sources):
            i = (i + 1)
        sources[str(i)] = source
        server_lookup[json.dumps(source)] = str(i)
    def source_lookup(source):
        for (k, v) in sources.iteritems():
            if (v == source):
                return k
        return None
    def layer_config(l, user=None):
        cfg = l.layer_config(user=user)
        src_cfg = l.source_config(access_token)
        source = source_lookup(src_cfg)
        if source:
            cfg['source'] = source
        return cfg
    source_urls = [source['url'] for source in sources.values() if ('url' in source)]
    if ('geonode.geoserver' in settings.INSTALLED_APPS):
        if ((len(sources.keys()) > 0) and (not (settings.MAP_BASELAYERS[0]['source']['url'] in source_urls))):
            keys = sorted(sources.keys())
            settings.MAP_BASELAYERS[0]['source']['title'] = 'Local    Geoserver'
            sources[str((int(keys[(-1)]) + 1))] = settings.MAP_BASELAYERS[0]['source']
    def _base_source(source):
        base_source = copy.deepcopy(source)
        for key in ['id', 'baseParams', 'title']:
            if (key in base_source):
                del base_source[key]
        return base_source
    for (idx, lyr) in enumerate(settings.MAP_BASELAYERS):
        if (_base_source(lyr['source']) not in map(_base_source, sources.values())):
            if (len(sources.keys()) > 0):
                sources[str((int(max(sources.keys(), key=int)) + 1))] = lyr['source']
    from geonode.services.models import Service
    index = (int(max(sources.keys())) if (len(sources.keys()) > 0) else 0)
    for service in Service.objects.all():
        remote_source = {'url': service.base_url, 'remote': True, 'ptype': 'gxp_wmscsource', 'name': service.name}
        if (remote_source['url'] not in source_urls):
            index += 1
            sources[index] = remote_source
    config = {'id': self.id, 'about': {'title': self.title, 'abstract': self.abstract}, 'aboutUrl': '../about', 'defaultSourceType': 'gxp_wmscsource', 'sources': sources, 'map': {'layers': [layer_config(l, user=user) for l in layers], 'center': [self.center_x, self.center_y], 'projection': self.projection, 'zoom': self.zoom}}
    if any(layers):
        config['map']['layers'][(len(layers) - 1)]['selected'] = True
    else:
        (def_map_config, def_map_layers) = default_map_config(None)
        config = def_map_config
        layers = def_map_layers
    config['map'].update(_get_viewer_projection_info(self.projection))
    if (self is not None):
        cache.set(((('viewer_json_' + str(self.id)) + '_') + str((0 if (user is None) else user.id))), config)
    return config
