vFW and vDNS support added to azure-plugin
[multicloud/azure.git] / azure / aria / aria-extension-cloudify / src / aria / aria / parser / presentation / utils.py
diff --git a/azure/aria/aria-extension-cloudify/src/aria/aria/parser/presentation/utils.py b/azure/aria/aria-extension-cloudify/src/aria/aria/parser/presentation/utils.py
new file mode 100644 (file)
index 0000000..f0fd390
--- /dev/null
@@ -0,0 +1,187 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from types import FunctionType
+
+from ...utils.formatting import safe_repr
+from ...utils.type import full_type_name
+from ..validation import Issue
+from .null import NULL
+
+
+def get_locator(*values):
+    """
+    Gets the first available locator.
+
+    :rtype: :class:`aria.parser.reading.Locator`
+    """
+
+    for v in values:
+        if hasattr(v, '_locator'):
+            locator = v._locator
+            if locator is not None:
+                return locator
+    return None
+
+
+def parse_types_dict_names(types_dict_names):
+    """
+    If the first element in the array is a function, extracts it out.
+    """
+
+    convert = None
+    if isinstance(types_dict_names[0], FunctionType):
+        convert = types_dict_names[0]
+        types_dict_names = types_dict_names[1:]
+    return types_dict_names, convert
+
+
+def validate_primitive(value, cls, coerce=False):
+    """
+    Checks if the value is of the primitive type, optionally attempting to coerce it
+    if it is not.
+
+    :raises ValueError: if not a primitive type or if coercion failed.
+    """
+
+    if (cls is not None) and (value is not None) and (value is not NULL):
+        if (cls is unicode) or (cls is str): # These two types are interchangeable
+            valid = isinstance(value, basestring)
+        elif cls is int:
+            # In Python, a bool is an int
+            valid = isinstance(value, int) and not isinstance(value, bool)
+        else:
+            valid = isinstance(value, cls)
+        if not valid:
+            if coerce:
+                value = cls(value)
+            else:
+                raise ValueError('not a "%s": %s' % (full_type_name(cls), safe_repr(value)))
+    return value
+
+
+def validate_no_short_form(context, presentation):
+    """
+    Makes sure that we can use short form definitions only if we allowed it.
+    """
+
+    if not hasattr(presentation, 'SHORT_FORM_FIELD') and not isinstance(presentation._raw, dict):
+        context.validation.report('short form not allowed for field "%s"' % presentation._fullname,
+                                  locator=presentation._locator,
+                                  level=Issue.BETWEEN_FIELDS)
+
+
+def validate_no_unknown_fields(context, presentation):
+    """
+    Make sure that we can use unknown fields only if we allowed it.
+    """
+
+    if not getattr(presentation, 'ALLOW_UNKNOWN_FIELDS', False) \
+            and not context.validation.allow_unknown_fields \
+            and isinstance(presentation._raw, dict) \
+            and hasattr(presentation, 'FIELDS'):
+        for k in presentation._raw:
+            if k not in presentation.FIELDS:
+                context.validation.report('field "%s" is not supported in "%s"'
+                                          % (k, presentation._fullname),
+                                          locator=presentation._get_child_locator(k),
+                                          level=Issue.BETWEEN_FIELDS)
+
+
+def validate_known_fields(context, presentation):
+    """
+    Validates all known fields.
+    """
+
+    if hasattr(presentation, '_iter_fields'):
+        for _, field in presentation._iter_fields():
+            field.validate(presentation, context)
+
+
+def get_parent_presentation(context, presentation, *types_dict_names):
+    """
+    Returns the parent presentation according to the ``derived_from`` field, or ``None`` if invalid.
+
+    Checks that we do not derive from ourselves and that we do not cause a circular hierarchy.
+
+    The arguments from the third onwards are used to locate a nested field under
+    ``service_template`` under the root presenter. The first of these can optionally be a function,
+    in which case it will be called to convert type names. This can be used to support shorthand
+    type names, aliases, etc.
+    """
+
+    type_name = presentation.derived_from
+
+    if type_name is None:
+        return None
+
+    types_dict_names, convert = parse_types_dict_names(types_dict_names)
+    types_dict = context.presentation.get('service_template', *types_dict_names) or {}
+
+    if convert:
+        type_name = convert(context, type_name, types_dict)
+
+    # Make sure not derived from self
+    if type_name == presentation._name:
+        return None
+    # Make sure derived from type exists
+    elif type_name not in types_dict:
+        return None
+    else:
+        # Make sure derivation hierarchy is not circular
+        hierarchy = [presentation._name]
+        presentation_copy = presentation
+        while presentation_copy.derived_from is not None:
+            derived_from = presentation_copy.derived_from
+            if convert:
+                derived_from = convert(context, derived_from, types_dict)
+
+            if derived_from == presentation_copy._name or derived_from not in types_dict:
+                return None
+            presentation_copy = types_dict[derived_from]
+            if presentation_copy._name in hierarchy:
+                return None
+            hierarchy.append(presentation_copy._name)
+
+    return types_dict[type_name]
+
+
+def report_issue_for_unknown_type(context, presentation, type_name, field_name, value=None):
+    if value is None:
+        value = getattr(presentation, field_name)
+    context.validation.report('"%s" refers to an unknown %s in "%s": %s'
+                              % (field_name, type_name, presentation._fullname, safe_repr(value)),
+                              locator=presentation._get_child_locator(field_name),
+                              level=Issue.BETWEEN_TYPES)
+
+
+def report_issue_for_parent_is_self(context, presentation, field_name):
+    context.validation.report('parent type of "%s" is self' % presentation._fullname,
+                              locator=presentation._get_child_locator(field_name),
+                              level=Issue.BETWEEN_TYPES)
+
+
+def report_issue_for_unknown_parent_type(context, presentation, field_name):
+    context.validation.report('unknown parent type "%s" in "%s"'
+                              % (getattr(presentation, field_name), presentation._fullname),
+                              locator=presentation._get_child_locator(field_name),
+                              level=Issue.BETWEEN_TYPES)
+
+
+def report_issue_for_circular_type_hierarchy(context, presentation, field_name):
+    context.validation.report('"%s" of "%s" creates a circular type hierarchy'
+                              % (getattr(presentation, field_name), presentation._fullname),
+                              locator=presentation._get_child_locator(field_name),
+                              level=Issue.BETWEEN_TYPES)