Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / tools / json_schema_compiler / schema_loader.py
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.
4
5 import os
6 import re
7 import sys
8
9 import idl_schema
10 import json_schema
11 from cpp_namespace_environment import CppNamespaceEnvironment
12 from model import Model, UnixName
13
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
33
34 class SchemaLoader(object):
35   '''Resolves a type name into the namespace the type belongs to.
36
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)
53
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
65
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
77
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)
82
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))
91
92     return api_defs