configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/layer_utils.py
changeset 3 e7e0ae78773e
parent 0 2e8eeb919028
--- a/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/layer_utils.py	Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/common/ConeRulePlugin/ruleplugin/evals/layer_utils.py	Tue Aug 10 14:29:28 2010 +0300
@@ -1,9 +1,9 @@
 # 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"
+# under the terms of the License "Symbian Foundation License v1.0"
 # which accompanies this distribution, and is available
-# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+# at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
 #
 # Initial Contributors:
 # Nokia Corporation - initial contribution.
@@ -17,12 +17,52 @@
 Ruleml eval extension to check is passed ref changed on given layer(range).
 '''
 
-from cone.public import api
+from cone.public import api, plugin
 
 import logging
+import re
 
 logger = logging.getLogger('cone.ruleplugin.evals.layer_utils')
 
+
+def layers_used(config, layers_or_regex, impl_tags):
+    """
+    Return True if matching layers are used by any implementation with given tag.
+    @param config: The configuration.
+    @param layers_or_regex: List of layer objects to check against, or regular
+        expression (string) for resolving the list of layers.
+    @param impl_tags: Implementation tags to use.
+    """
+    # Resolve layer list
+    if isinstance(layers_or_regex, basestring):
+        layers = []
+        for lay in config.list_configurations():
+            if re.search(layers_or_regex, lay):
+                layers.append(config.get_configuration(lay))
+    else:
+        layers = layers_or_regex
+    
+    impls = plugin.filtered_impl_set(config).filter_implementations(tags=impl_tags)
+    context = plugin.GenerationContext(tags=impl_tags,
+                                       configuration=config)
+    for impl in impls:
+        if impl.uses_layers(layers, context) == True:
+            return True
+    return False
+
+
+def get_all_layers(feat):
+    """
+    Returns all layers.
+    """
+    
+    root_conf = feat.get_root_configuration()
+    result = []
+    
+    for i in range(0, len(root_conf.list_configurations())):
+        result.append(root_conf.get_configuration_by_index(i))
+    return result
+
 def give_changed_layers(feat):
     """
     Returns a list of booleans where True means that feature is changed in that layer. Index is
@@ -33,22 +73,9 @@
     
     root_conf = feat.get_root_configuration()
     nro_of_layers = len(root_conf.list_configurations())
-    result = [False] * nro_of_layers
-    
+    result = []
     for i in range(0, nro_of_layers):
-        conf = root_conf.get_configuration_by_index(i)
-        logger.debug("Traversing data from configuration: %s" % conf.get_path())
-        datas = conf._traverse(type=api.Data, filters=[lambda d: d.fqr==feat.fqr])
-        for data in datas:
-            try:
-                if data.get_value() != None:
-                    logger.debug("Feature '%s' is changed in layer %s with data '%s'" % (feat.fqr, i, data.get_value()))
-                    result[i] = True
-            except Exception, e:
-                logger.debug("Failed to check Feature '%s' data in layer %s:", (e,i))
-        if result[i] == False:
-            logger.debug("Feature '%s' is not changed in layer: %s" % (feat.fqr, i))
-    logger.debug("Feature '%s' is changed in layers: %s" % (feat.fqr, result))
+        result.append(_changed_on_layer(feat, root_conf.get_configuration_by_index(i)))
     return result
 
 def changed_on_last_layer(feat):
@@ -58,18 +85,7 @@
     
     root_conf = feat.get_root_configuration()
     conf = root_conf.get_configuration_by_index(-2)#autoconfig layer is ignored 
-    
-    def check(node):
-        if isinstance(node, api.Data) and node.fqr == feat.fqr:
-            return True
-        for obj in node._objects():
-            if check(obj):
-                return True
-    
-    if check(conf):
-        return True
-    else:
-        return False
+    return _changed_on_layer(feat, conf)
 
 def changed_on_autoconfig_layer(feat):
     """
@@ -77,19 +93,8 @@
     """
     
     root_conf = feat.get_root_configuration()
-    conf = root_conf.get_configuration_by_index(-1) 
-    
-    def check(node):
-        if isinstance(node, api.Data) and node.fqr == feat.fqr:
-            return True
-        for obj in node._objects():
-            if check(obj):
-                return True
-    
-    if check(conf):
-        return True
-    else:
-        return False
+    conf = root_conf.get_configuration_by_index(-1)
+    return _changed_on_layer(feat, conf)
 
 def changed_on_layer(feat, layer):
     """
@@ -97,23 +102,72 @@
     """
     try:
         return give_changed_layers(feat)[layer]
-    except IndexError, e:
+    except IndexError:
         logger.warning("Given layer is not found: %s" % (layer))
         return False
 
+def _changed_on_layer(feature, layer_obj):
+    """
+    Return whether the given feature is changed on the given layer.
+    """
+    # Check recursively if the layer contains any data objects with
+    # the same FQR as the feature
+    def check(node):
+        if isinstance(node, api.Data) and node.fqr == feature.fqr:
+            return True
+        for obj in node._objects():
+            if check(obj):
+                return True
+        return False
+    
+    return check(layer_obj)
+
 def changed_on_layers(feat, findex, tindex):
     """
     Returns True if feature is changed in layer of given range.
     """
-    layers = give_changed_layers(feat)
+    root_conf = feat.get_root_configuration()
+    nro_of_layers = len(root_conf.list_configurations())
     
-    if findex == tindex:
-        return changed_on_layer(feat, findex)
+    # Convert negative indices to positive
+    def neg_index_to_pos(index):
+        if index < 0:   return nro_of_layers + index
+        else:           return index
+    begin = neg_index_to_pos(findex)
+    end = neg_index_to_pos(tindex)
     
-    for i in range(findex, tindex):
-        if i > len(layers):
+    if end == begin:
+        return changed_on_layer(feat, begin)
+    
+    # Check the layers inside the range
+    if end > begin: index_range = xrange(begin, end)
+    else:           index_range = xrange(end, begin)
+    for i in index_range:
+        if i < 0 or i >= nro_of_layers:
             continue
-        if layers != None and layers[i] != None and layers[i]:
+        
+        layer = root_conf.get_configuration_by_index(i)
+        if _changed_on_layer(feat, layer):
             return True
     return False
 
+def changed_on_layers_regex(feat, regex):
+    """
+    Return whether the given feature is changed on any layer that matches
+    the given regular expression.
+    """
+    pattern = re.compile(regex)
+    root_conf = feat.get_root_configuration()
+    for config_path in root_conf.list_configurations():
+        if pattern.search(config_path):
+            layer = root_conf.get_configuration(config_path)
+            if _changed_on_layer(feat, layer):
+                return True
+    return False
+
+def changed_on_custvariant_layer(feat):
+    """
+    Return whether the given feature is changed on any of the custvariant layers
+    (layers that match the regex '/custvariant(_.*)?/').
+    """
+    return changed_on_layers_regex(feat, r'/custvariant(_.*)?/')