|  | # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | # Use of this source code is governed by a BSD-style license that can be | 
|  | # found in the LICENSE file. | 
|  |  | 
|  | import os | 
|  | import re | 
|  | import sys | 
|  |  | 
|  | import idl_schema | 
|  | import json_schema | 
|  | from cpp_namespace_environment import CppNamespaceEnvironment | 
|  | from model import Model, UnixName | 
|  |  | 
|  | def GenerateFilenames(full_namespace): | 
|  | # Try to find the file defining the namespace. Eg. for | 
|  | # nameSpace.sub_name_space.Type' the following heuristics looks for: | 
|  | # 1. name_space_sub_name_space.json, | 
|  | # 2. name_space_sub_name_space.idl, | 
|  | # 3. sub_name_space.json, | 
|  | # 4. sub_name_space.idl, | 
|  | # 5. etc. | 
|  | sub_namespaces = full_namespace.split('.') | 
|  | filenames = [ ] | 
|  | basename = None | 
|  | for namespace in reversed(sub_namespaces): | 
|  | if basename is not None: | 
|  | basename = UnixName(namespace + '.' + basename) | 
|  | else: | 
|  | basename = UnixName(namespace) | 
|  | for ext in ['json', 'idl']: | 
|  | filenames.append('%s.%s' % (basename, ext)) | 
|  | return filenames | 
|  |  | 
|  | class SchemaLoader(object): | 
|  | '''Resolves a type name into the namespace the type belongs to. | 
|  |  | 
|  | Properties: | 
|  | - |root| path to the root directory. | 
|  | - |path| path to the directory with the API header files, relative to the | 
|  | root. | 
|  | - |include_rules| List containing tuples with (path, cpp_namespace_pattern) | 
|  | used when searching for types. | 
|  | - |cpp_namespace_pattern| Default namespace pattern | 
|  | ''' | 
|  | def __init__(self, | 
|  | root, | 
|  | path, | 
|  | include_rules, | 
|  | cpp_namespace_pattern): | 
|  | self._root = root | 
|  | self._include_rules = [(path, cpp_namespace_pattern)] | 
|  | self._include_rules.extend(include_rules) | 
|  |  | 
|  | def ResolveNamespace(self, full_namespace): | 
|  | filenames = GenerateFilenames(full_namespace) | 
|  | for path, cpp_namespace in self._include_rules: | 
|  | cpp_namespace_environment = None | 
|  | if cpp_namespace: | 
|  | cpp_namespace_environment = CppNamespaceEnvironment(cpp_namespace) | 
|  | for filename in reversed(filenames): | 
|  | filepath = os.path.join(path, filename); | 
|  | if os.path.exists(os.path.join(self._root, filepath)): | 
|  | return Model().AddNamespace( | 
|  | self.LoadSchema(filepath)[0], | 
|  | filepath, | 
|  | environment=cpp_namespace_environment) | 
|  | return None | 
|  |  | 
|  | def ResolveType(self, full_name, default_namespace): | 
|  | name_parts = full_name.rsplit('.', 1) | 
|  | if len(name_parts) == 1: | 
|  | if full_name not in default_namespace.types: | 
|  | return None | 
|  | return default_namespace | 
|  | full_namespace, type_name = full_name.rsplit('.', 1) | 
|  | namespace = self.ResolveNamespace(full_namespace) | 
|  | if namespace and type_name in namespace.types: | 
|  | return namespace | 
|  | return None | 
|  |  | 
|  | def LoadSchema(self, schema): | 
|  | '''Load a schema definition. The schema parameter must be a file name | 
|  | with the full path relative to the root.''' | 
|  | _, schema_extension = os.path.splitext(schema) | 
|  |  | 
|  | schema_path = os.path.join(self._root, schema) | 
|  | if schema_extension == '.json': | 
|  | api_defs = json_schema.Load(schema_path) | 
|  | elif schema_extension == '.idl': | 
|  | api_defs = idl_schema.Load(schema_path) | 
|  | else: | 
|  | sys.exit('Did not recognize file extension %s for schema %s' % | 
|  | (schema_extension, schema)) | 
|  |  | 
|  | return api_defs |