Roll src/third_party/WebKit f007c95:0171005 (svn 185074:185088)
[chromium-blink-merge.git] / tools / json_schema_compiler / schema_loader.py
blobb8969910c6b693a6eed4c2da1e07f01d73b84997
1 # Copyright (c) 2012 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.
5 import os
6 import re
7 import sys
9 import idl_schema
10 import json_schema
11 from cpp_namespace_environment import CppNamespaceEnvironment
12 from model import Model, UnixName
14 def GenerateFilenames(full_namespace):
15 # Try to find the file defining the namespace. Eg. for
16 # nameSpace.sub_name_space.Type' the following heuristics looks for:
17 # 1. name_space_sub_name_space.json,
18 # 2. name_space_sub_name_space.idl,
19 # 3. sub_name_space.json,
20 # 4. sub_name_space.idl,
21 # 5. etc.
22 sub_namespaces = full_namespace.split('.')
23 filenames = [ ]
24 basename = None
25 for namespace in reversed(sub_namespaces):
26 if basename is not None:
27 basename = UnixName(namespace + '.' + basename)
28 else:
29 basename = UnixName(namespace)
30 for ext in ['json', 'idl']:
31 filenames.append('%s.%s' % (basename, ext))
32 return filenames
34 class SchemaLoader(object):
35 '''Resolves a type name into the namespace the type belongs to.
37 Properties:
38 - |root| path to the root directory.
39 - |path| path to the directory with the API header files, relative to the
40 root.
41 - |include_rules| List containing tuples with (path, cpp_namespace_pattern)
42 used when searching for types.
43 - |cpp_namespace_pattern| Default namespace pattern
44 '''
45 def __init__(self,
46 root,
47 path,
48 include_rules,
49 cpp_namespace_pattern):
50 self._root = root
51 self._include_rules = [(path, cpp_namespace_pattern)]
52 self._include_rules.extend(include_rules)
54 def ResolveNamespace(self, full_namespace):
55 filenames = GenerateFilenames(full_namespace)
56 for path, cpp_namespace in self._include_rules:
57 for filename in reversed(filenames):
58 filepath = os.path.join(path, filename);
59 if os.path.exists(os.path.join(self._root, filepath)):
60 return Model().AddNamespace(
61 self.LoadSchema(filepath)[0],
62 filepath,
63 environment=CppNamespaceEnvironment(cpp_namespace))
64 return None
66 def ResolveType(self, full_name, default_namespace):
67 name_parts = full_name.rsplit('.', 1)
68 if len(name_parts) == 1:
69 if full_name not in default_namespace.types:
70 return None
71 return default_namespace
72 full_namespace, type_name = full_name.rsplit('.', 1)
73 namespace = self.ResolveNamespace(full_namespace)
74 if namespace and type_name in namespace.types:
75 return namespace
76 return None
78 def LoadSchema(self, schema):
79 '''Load a schema definition. The schema parameter must be a file name
80 with the full path relative to the root.'''
81 schema_filename, schema_extension = os.path.splitext(schema)
83 schema_path = os.path.join(self._root, schema)
84 if schema_extension == '.json':
85 api_defs = json_schema.Load(schema_path)
86 elif schema_extension == '.idl':
87 api_defs = idl_schema.Load(schema_path)
88 else:
89 sys.exit('Did not recognize file extension %s for schema %s' %
90 (schema_extension, schema))
92 return api_defs