#
# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
# This component and the accompanying materials are made available
# under the terms of "Eclipse Public License v1.0"
# which accompanies this distribution, and is available
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
#
# Initial Contributors:
# Nokia Corporation - initial contribution.
#
# Contributors:
#
# Description:
#
import logging
from cone.public import api, exceptions, plugin, utils, parsecontext
from cone.validation.parsecontext import ValidationParseContext
import cone.validation.common
class ValidationContext(object):
def __init__(self, configuration):
self.configuration = configuration
self.problems = []
#: Flat list of all implementations, including containers
self.all_impls = []
class ValidatorBase(object):
"""
Base class for implementation validators.
NOTE THAT THIS CLASS SHOULD NOT BE DIRECTLY SUB-CLASSED.
Sub-class either ImplValidatorBase or GlobalValidatorBase
instead.
"""
PROBLEM_TYPES = None
def __init__(self, context):
self.context = context
class ImplValidatorBase(ValidatorBase):
"""
Base class for validators that validate only a single implementation.
"""
SUPPORTED_IMPL_CLASSES = []
def __init__(self, context, impl):
self.context = context
self.impl = impl
def validate(self):
"""
Called to validate an implementation instance.
"""
pass
def check_feature_reference(self, ref, line, problem_type):
"""
Check that a feature with the given reference exists, and if
not, add a problem.
@param ref: The feature reference to check.
@param line: The line number to set to the created problem.
@param line: The problem type to set to the created problem.
"""
dview = self.context.configuration.get_default_view()
try:
dview.get_feature(ref)
except exceptions.NotFound:
prob = api.Problem(
msg = u"Setting '%s' not found in configuration" % ref,
type = problem_type,
line = line,
file = self.impl.ref)
self.context.problems.append(prob)
class GlobalValidatorBase(ValidatorBase):
"""
Base class for validators that validate the entire implementation set at once.
"""
def validate(self):
pass
def get_validator_classes(problem_type_filter=None):
"""
Return a list of all ImplML validator classes that match the given
problem type filter (i.e. all validator classes that yield problems
that will not be filtered out).
@param problem_type_filter: The filter, if None, all validator
classes will be returned.
"""
classes = []
# Validators from plug-in entry points
classes.extend(cone.validation.common.load_plugin_classes(
'cone.plugins.implvalidators',
ValidatorBase))
# Built-in validators
from cone.validation.builtinvalidators.implml import VALIDATOR_CLASSES
classes.extend(VALIDATOR_CLASSES)
return cone.validation.common.filter_classes(classes, problem_type_filter)
def validate_impl_set(impl_set, configuration, validator_classes=None):
"""
Validate the given implementation set.
@param impl_set: The implementations to validate.
@param configuration: The configuration used in the validation.
@param validator_classes: The validator classes to use for the validation.
If None, all validator classes will be used.
@return: A list of Problem objects.
"""
context = ValidationContext(configuration)
context.all_impls = _get_flat_impl_list(impl_set)
if validator_classes is None:
validator_classes = get_validator_classes()
# Run global validation first
for vc in validator_classes:
if issubclass(vc, GlobalValidatorBase):
try:
validator = vc(context)
validator.validate()
except Exception, e:
utils.log_exception(logging.getLogger('cone'),
"Error while validating: %s: %s" \
% (e.__class__.__name__, e))
# Then run validation for individual implementations
for impl in context.all_impls:
for vc in validator_classes:
if issubclass(vc, ImplValidatorBase) and isinstance(impl, vc.SUPPORTED_IMPL_CLASSES):
try:
validator = vc(context, impl)
validator.validate()
except Exception, e:
utils.log_exception(logging.getLogger('cone'),
"Error validating '%s': %s: %s" \
% (impl, e.__class__.__name__, e))
return context.problems
def _get_flat_impl_list(impl_set):
"""
Return a flat list of all implementations in the given set.
"""
result = []
def add_to_result(impl):
result.append(impl)
if isinstance(impl, plugin.ImplContainer):
for sub_impl in impl.impls:
add_to_result(sub_impl)
for impl in impl_set:
add_to_result(impl)
return result
def validate_impls(configuration, filter='.*', validator_classes=None):
"""
Validate all implementations in the given configuration.
@param filter: Regex for filtering the implementations to validate.
@param validator_classes: The validator classes to use for the validation.
If None, all validator classes will be used.
"""
# Set up the parse context to collect problems from the parsing phase
context = ValidationParseContext()
parsecontext.set_implml_context(context)
impl_set = plugin.get_impl_set(configuration, filter=filter)
problems = validate_impl_set(impl_set, configuration, validator_classes)
return context.problems + problems