vFW and vDNS support added to azure-plugin
[multicloud/azure.git] / azure / aria / aria-extension-cloudify / src / aria / aria / parser / reading / locator.py
diff --git a/azure/aria/aria-extension-cloudify/src/aria/aria/parser/reading/locator.py b/azure/aria/aria-extension-cloudify/src/aria/aria/parser/reading/locator.py
new file mode 100644 (file)
index 0000000..57b4d50
--- /dev/null
@@ -0,0 +1,119 @@
+# Licensed 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 ...utils.console import puts, Colored, indent
+
+
+# We are inheriting the primitive types in order to add the ability to set
+# an attribute (_locator) on them.
+
+class LocatableString(unicode):
+    pass
+
+
+class LocatableInt(int):
+    pass
+
+
+class LocatableFloat(float):
+    pass
+
+
+def wrap(value):
+    if isinstance(value, basestring):
+        return True, LocatableString(value)
+    elif isinstance(value, int) and \
+            not isinstance(value, bool):  # Note: bool counts as int in Python!
+        return True, LocatableInt(value)
+    elif isinstance(value, float):
+        return True, LocatableFloat(value)
+    return False, value
+
+
+class Locator(object):
+    """
+    Stores location information (line and column numbers) for agnostic raw data.
+    """
+    def __init__(self, location, line, column, children=None):
+        self.location = location
+        self.line = line
+        self.column = column
+        self.children = children
+
+    def get_child(self, *names):
+        if (not names) or (not isinstance(self.children, dict)):
+            return self
+        name = names[0]
+        if name not in self.children:
+            return self
+        child = self.children[name]
+        return child.get_child(names[1:])
+
+    def link(self, raw, path=None):
+        if hasattr(raw, '_locator'):
+            # This can happen when we use anchors
+            return
+
+        try:
+            setattr(raw, '_locator', self)
+        except AttributeError:
+            return
+
+        if isinstance(raw, list):
+            for i, raw_element in enumerate(raw):
+                wrapped, raw_element = wrap(raw_element)
+                if wrapped:
+                    raw[i] = raw_element
+                child_path = '%s.%d' % (path, i) if path else str(i)
+                try:
+                    self.children[i].link(raw_element, child_path)
+                except KeyError:
+                    raise ValueError('location map does not match agnostic raw data: %s' %
+                                     child_path)
+        elif isinstance(raw, dict):
+            for k, raw_element in raw.iteritems():
+                wrapped, raw_element = wrap(raw_element)
+                if wrapped:
+                    raw[k] = raw_element
+                child_path = '%s.%s' % (path, k) if path else k
+                try:
+                    self.children[k].link(raw_element, child_path)
+                except KeyError:
+                    raise ValueError('location map does not match agnostic raw data: %s' %
+                                     child_path)
+
+    def merge(self, locator):
+        if isinstance(self.children, dict) and isinstance(locator.children, dict):
+            for k, loc in locator.children.iteritems():
+                if k in self.children:
+                    self.children[k].merge(loc)
+                else:
+                    self.children[k] = loc
+
+    def dump(self, key=None):
+        if key:
+            puts('%s "%s":%d:%d' %
+                 (Colored.red(key), Colored.blue(self.location), self.line, self.column))
+        else:
+            puts('"%s":%d:%d' % (Colored.blue(self.location), self.line, self.column))
+        if isinstance(self.children, list):
+            with indent(2):
+                for loc in self.children:
+                    loc.dump()
+        elif isinstance(self.children, dict):
+            with indent(2):
+                for k, loc in self.children.iteritems():
+                    loc.dump(k)
+
+    def __str__(self):
+        # Should be in same format as Issue.locator_as_str
+        return '"%s":%d:%d' % (self.location, self.line, self.column)