|
1 # |
|
2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 # All rights reserved. |
|
4 # This component and the accompanying materials are made available |
|
5 # under the terms of "Eclipse Public License v1.0" |
|
6 # which accompanies this distribution, and is available |
|
7 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 # |
|
9 # Initial Contributors: |
|
10 # Nokia Corporation - initial contribution. |
|
11 # |
|
12 # Contributors: |
|
13 # |
|
14 # Description: |
|
15 # |
|
16 |
|
17 import logging |
|
18 |
|
19 from cone.public import api, exceptions, plugin, utils, parsecontext |
|
20 from cone.validation.parsecontext import ValidationParseContext |
|
21 import cone.validation.common |
|
22 |
|
23 class ValidationContext(object): |
|
24 def __init__(self, configuration): |
|
25 self.configuration = configuration |
|
26 self.problems = [] |
|
27 |
|
28 #: Flat list of all implementations, including containers |
|
29 self.all_impls = [] |
|
30 |
|
31 class ValidatorBase(object): |
|
32 """ |
|
33 Base class for implementation validators. |
|
34 |
|
35 NOTE THAT THIS CLASS SHOULD NOT BE DIRECTLY SUB-CLASSED. |
|
36 Sub-class either ImplValidatorBase or GlobalValidatorBase |
|
37 instead. |
|
38 """ |
|
39 PROBLEM_TYPES = None |
|
40 |
|
41 def __init__(self, context): |
|
42 self.context = context |
|
43 |
|
44 class ImplValidatorBase(ValidatorBase): |
|
45 """ |
|
46 Base class for validators that validate only a single implementation. |
|
47 """ |
|
48 SUPPORTED_IMPL_CLASSES = [] |
|
49 |
|
50 def __init__(self, context, impl): |
|
51 self.context = context |
|
52 self.impl = impl |
|
53 |
|
54 def validate(self): |
|
55 """ |
|
56 Called to validate an implementation instance. |
|
57 """ |
|
58 pass |
|
59 |
|
60 def check_feature_reference(self, ref, line, problem_type): |
|
61 """ |
|
62 Check that a feature with the given reference exists, and if |
|
63 not, add a problem. |
|
64 |
|
65 @param ref: The feature reference to check. |
|
66 @param line: The line number to set to the created problem. |
|
67 @param line: The problem type to set to the created problem. |
|
68 """ |
|
69 dview = self.context.configuration.get_default_view() |
|
70 try: |
|
71 dview.get_feature(ref) |
|
72 except exceptions.NotFound: |
|
73 prob = api.Problem( |
|
74 msg = u"Setting '%s' not found in configuration" % ref, |
|
75 type = problem_type, |
|
76 line = line, |
|
77 file = self.impl.ref) |
|
78 self.context.problems.append(prob) |
|
79 |
|
80 class GlobalValidatorBase(ValidatorBase): |
|
81 """ |
|
82 Base class for validators that validate the entire implementation set at once. |
|
83 """ |
|
84 def validate(self): |
|
85 pass |
|
86 |
|
87 def get_validator_classes(problem_type_filter=None): |
|
88 """ |
|
89 Return a list of all ImplML validator classes that match the given |
|
90 problem type filter (i.e. all validator classes that yield problems |
|
91 that will not be filtered out). |
|
92 |
|
93 @param problem_type_filter: The filter, if None, all validator |
|
94 classes will be returned. |
|
95 """ |
|
96 classes = [] |
|
97 |
|
98 # Validators from plug-in entry points |
|
99 classes.extend(cone.validation.common.load_plugin_classes( |
|
100 'cone.plugins.implvalidators', |
|
101 ValidatorBase)) |
|
102 |
|
103 # Built-in validators |
|
104 from cone.validation.builtinvalidators.implml import VALIDATOR_CLASSES |
|
105 classes.extend(VALIDATOR_CLASSES) |
|
106 |
|
107 return cone.validation.common.filter_classes(classes, problem_type_filter) |
|
108 |
|
109 def validate_impl_set(impl_set, configuration, validator_classes=None): |
|
110 """ |
|
111 Validate the given implementation set. |
|
112 @param impl_set: The implementations to validate. |
|
113 @param configuration: The configuration used in the validation. |
|
114 @param validator_classes: The validator classes to use for the validation. |
|
115 If None, all validator classes will be used. |
|
116 @return: A list of Problem objects. |
|
117 """ |
|
118 context = ValidationContext(configuration) |
|
119 context.all_impls = _get_flat_impl_list(impl_set) |
|
120 |
|
121 if validator_classes is None: |
|
122 validator_classes = get_validator_classes() |
|
123 |
|
124 # Run global validation first |
|
125 for vc in validator_classes: |
|
126 if issubclass(vc, GlobalValidatorBase): |
|
127 try: |
|
128 validator = vc(context) |
|
129 validator.validate() |
|
130 except Exception, e: |
|
131 utils.log_exception(logging.getLogger('cone'), |
|
132 "Error while validating: %s: %s" \ |
|
133 % (e.__class__.__name__, e)) |
|
134 |
|
135 # Then run validation for individual implementations |
|
136 for impl in context.all_impls: |
|
137 for vc in validator_classes: |
|
138 if issubclass(vc, ImplValidatorBase) and isinstance(impl, vc.SUPPORTED_IMPL_CLASSES): |
|
139 try: |
|
140 validator = vc(context, impl) |
|
141 validator.validate() |
|
142 except Exception, e: |
|
143 utils.log_exception(logging.getLogger('cone'), |
|
144 "Error validating '%s': %s: %s" \ |
|
145 % (impl, e.__class__.__name__, e)) |
|
146 return context.problems |
|
147 |
|
148 def _get_flat_impl_list(impl_set): |
|
149 """ |
|
150 Return a flat list of all implementations in the given set. |
|
151 """ |
|
152 result = [] |
|
153 def add_to_result(impl): |
|
154 result.append(impl) |
|
155 if isinstance(impl, plugin.ImplContainer): |
|
156 for sub_impl in impl.impls: |
|
157 add_to_result(sub_impl) |
|
158 for impl in impl_set: |
|
159 add_to_result(impl) |
|
160 return result |
|
161 |
|
162 def validate_impls(configuration, filter='.*', validator_classes=None): |
|
163 """ |
|
164 Validate all implementations in the given configuration. |
|
165 @param filter: Regex for filtering the implementations to validate. |
|
166 @param validator_classes: The validator classes to use for the validation. |
|
167 If None, all validator classes will be used. |
|
168 """ |
|
169 # Set up the parse context to collect problems from the parsing phase |
|
170 context = ValidationParseContext() |
|
171 parsecontext.set_implml_context(context) |
|
172 |
|
173 impl_set = plugin.get_impl_set(configuration, filter=filter) |
|
174 problems = validate_impl_set(impl_set, configuration, validator_classes) |
|
175 |
|
176 return context.problems + problems |