- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / common / extensions / docs / server2 / manifest_data_source.py
1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import json
6
7 from data_source import DataSource
8 import features_utility
9 from manifest_features import ConvertDottedKeysToNested
10 from third_party.json_schema_compiler.json_parse import Parse
11
12 def _ListifyAndSortDocs(features, app_name):
13   '''Convert a |feautres| dictionary, and all 'children' dictionaries, into
14   lists recursively. Sort lists first by 'level' then by name.
15   '''
16   def sort_key(item):
17     '''Key function to sort items primarily by level (according to index into
18     levels) then subsort by name.
19     '''
20     levels = ('required', 'recommended', 'only_one', 'optional')
21
22     return (levels.index(item.get('level', 'optional')), item['name'])
23
24   def coerce_example_to_feature(feature):
25     '''To display json in examples more clearly, convert the example of
26     |feature| into the feature format, with a name and children, to be rendered
27     by the templates. Only applicable to examples that are dictionaries.
28     '''
29     if not isinstance(feature.get('example'), dict):
30       if 'example' in feature:
31         feature['example'] = json.dumps(feature['example'])
32       return
33     # Add any keys/value pairs in the dict as children
34     for key, value in feature['example'].iteritems():
35       if not 'children' in feature:
36         feature['children'] = {}
37       feature['children'][key] = { 'name': key, 'example': value }
38     del feature['example']
39     del feature['has_example']
40
41   def convert_and_sort(features):
42     for key, value in features.items():
43       if 'example' in value:
44         value['has_example'] = True
45         example = json.dumps(value['example'])
46         if example == '{}':
47           value['example'] = '{...}'
48         elif example == '[]':
49           value['example'] = '[...]'
50         else:
51           coerce_example_to_feature(value)
52       if 'children' in value:
53         features[key]['children'] = convert_and_sort(value['children'])
54     return sorted(features.values(), key=sort_key)
55
56   # Replace {{title}} in the 'name' manifest property example with |app_name|
57   if 'name' in features:
58     name = features['name']
59     name['example'] = name['example'].replace('{{title}}', app_name)
60
61   features = convert_and_sort(features)
62
63   return features
64
65 def _AddLevelAnnotations(features):
66   '''Add level annotations to |features|. |features| and children lists must be
67   sorted by 'level'. Annotations are added to the first item in a group of
68   features of the same 'level'.
69
70   The last item in a list has 'is_last' set to True.
71   '''
72   annotations = {
73     'required': 'Required',
74     'recommended': 'Recommended',
75     'only_one': 'Pick one (or none)',
76     'optional': 'Optional'
77   }
78
79   def add_annotation(item, annotation):
80     if not 'annotations' in item:
81       item['annotations'] = []
82     item['annotations'].insert(0, annotation)
83
84   def annotate(parent_level, features):
85     current_level = parent_level
86     for item in features:
87       level = item.get('level', 'optional')
88       if level != current_level:
89         add_annotation(item, annotations[level])
90         current_level = level
91       if 'children' in item:
92         annotate(level, item['children'])
93     if features:
94       features[-1]['is_last'] = True
95
96   annotate('required', features)
97   return features
98
99 class ManifestDataSource(DataSource):
100   '''Provides access to the properties in manifest features.
101   '''
102   def __init__(self, server_instance, _):
103     self._features_bundle = server_instance.features_bundle
104     self._object_store = server_instance.object_store_creator.Create(
105         ManifestDataSource)
106
107   def _CreateManifestData(self):
108     def for_templates(manifest_features, platform):
109       return _AddLevelAnnotations(
110           _ListifyAndSortDocs(
111               ConvertDottedKeysToNested(
112                   features_utility.Filtered(manifest_features, platform)),
113               app_name=platform.capitalize()))
114     manifest_features = self._features_bundle.GetManifestFeatures()
115     return {
116       'apps': for_templates(manifest_features, 'apps'),
117       'extensions': for_templates(manifest_features, 'extensions')
118     }
119
120   def _GetCachedManifestData(self, force_update=False):
121     data = self._object_store.Get('manifest_data').Get()
122     if data is None or force_update:
123       data = self._CreateManifestData()
124       self._object_store.Set('manifest_data', data)
125     return data
126
127   def Cron(self):
128     self._GetCachedManifestData(force_update=True)
129
130   def get(self, key):
131     return self._GetCachedManifestData().get(key)