Camera: Docs XML - allow multiple kinds per section

- When adding a new entry and maintaining ABI, make a new kind if can't be
  semantically part of the last kind. Don't add to the end of an existing
  non-last kind.

- Print generated file names in metadata-generate

(Aside) New sections should also be ended at the end of the root namespace to
  maintain ABI compatibility.

Change-Id: I5df0a701763af3cc91ee6eead4fe9fd423c9aa86
diff --git a/camera/docs/metadata_model.py b/camera/docs/metadata_model.py
index e2a2f0e..2091698 100644
--- a/camera/docs/metadata_model.py
+++ b/camera/docs/metadata_model.py
@@ -34,6 +34,7 @@
 """
 
 import sys
+import itertools
 from collections import OrderedDict
 
 class Node(object):
@@ -429,42 +430,35 @@
 
   # 'controls', 'static' 'dynamic'. etc
   def _construct_kinds(self, section):
-
-    kinds_dict = self._dictionary_by_name(section.kinds)
-    for name, kind in kinds_dict.iteritems():
+    for kind in section.kinds:
       kind._leafs = []
       section.validate_tree()
 
-    for p in section._leafs:
-      kind = kinds_dict.get(p.kind, Kind(p.kind, section))
-      kinds_dict[p.kind] = kind
-      section.validate_tree()
+    group_entry_by_kind = itertools.groupby(section._leafs, lambda x: x.kind)
+    leaf_it = ((k, g) for k, g in group_entry_by_kind)
 
-      if p not in kind._leafs:
-        kind._leafs.append(p)
+    # allow multiple kinds with the same name. merge if adjacent
+    # e.g. dynamic,dynamic,static,static,dynamic -> dynamic,static,dynamic
+    # this helps maintain ABI compatibility when adding an entry in a new kind
+    for idx, (kind_name, entry_it) in enumerate(leaf_it):
+      if idx >= len(section._kinds):
+        kind = Kind(kind_name, section)
+        section._kinds.append(kind)
+        section.validate_tree()
 
-    if len(kinds_dict) > 3:
-      sec = section
-      if sec is not None:
-        sec_name = sec.name
-      else:
-        sec_name = "Unknown"
+      kind = section._kinds[idx]
 
-      print >> sys.stderr, ("ERROR: Kind '%s' has too many children(%d) " +    \
-                            "in section '%s'") %(name, len(kc), sec_name)
+      for p in entry_it:
+        if p not in kind._leafs:
+          kind._leafs.append(p)
 
-
-    for name, kind in kinds_dict.iteritems():
-
+    for kind in section._kinds:
       kind.validate_tree()
       self._construct_inner_namespaces(kind)
       kind.validate_tree()
       self._construct_entries(kind)
       kind.validate_tree()
 
-      if kind not in section.kinds:
-        section._kinds.append(kind)
-
       if not section.validate_tree():
         print >> sys.stderr, ("ERROR: Failed to validate tree in " +           \
                              "construct_kinds, with kind = '%s'") %(kind)
@@ -604,6 +598,8 @@
     parent: An edge to the parent, which is always an OuterNamespace instance.
     description: A string description of the section, or None.
     kinds: A sequence of Kind children.
+    merged_kinds: A sequence of virtual Kind children,
+                  with each Kind's children merged by the kind.name
   """
   def __init__(self, name, parent, description=None, kinds=[]):
     self._name = name
@@ -635,6 +631,27 @@
   def _get_children(self):
     return (i for i in self.kinds)
 
+  @property
+  def merged_kinds(self):
+
+    def aggregate_by_name(acc, el):
+      existing = [i for i in acc if i.name == el.name]
+      if existing:
+        k = existing[0]
+      else:
+        k = Kind(el.name, el.parent)
+        acc.append(k)
+
+      k._namespaces.extend(el._namespaces)
+      k._entries.extend(el._entries)
+
+      return acc
+
+    new_kinds_lst = reduce(aggregate_by_name, self.kinds, [])
+
+    for k in new_kinds_lst:
+      yield k
+
 class Kind(Node):
   """
   A node corresponding to one of: <static>,<dynamic>,<controls> under a