Add fake component/trait property to device draft

To enable clients to start developing using the new trait/component
model, add a generated sections for "traits" and "components" to the
device draft. The actual content of these nodes will change once full
support for traits/components are added to libweave.

This change is a temporary stop-gap measure.

Change-Id: I0ec0f76034a2b1dca9870eda3614fe563cecb552
Reviewed-on: https://weave-review.googlesource.com/1720
Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/src/device_registration_info.cc b/src/device_registration_info.cc
index 30e8862..33b1643 100644
--- a/src/device_registration_info.cc
+++ b/src/device_registration_info.cc
@@ -14,6 +14,7 @@
 #include <base/json/json_reader.h>
 #include <base/json/json_writer.h>
 #include <base/strings/string_number_conversions.h>
+#include <base/strings/stringprintf.h>
 #include <base/values.h>
 #include <weave/provider/http_client.h>
 #include <weave/provider/network.h>
@@ -505,6 +506,31 @@
   resource->Set("commandDefs", commands.DeepCopy());
   resource->Set("state", state.DeepCopy());
 
+  // TODO(avakulenko): Temporary code to generate a single top-level component
+  // using the new component-trait model. This is to unblock clients to start
+  // implementation on their side.
+  base::DictionaryValue traits;
+  base::DictionaryValue component;
+  std::set<std::string> all_traits;
+  for (const auto& pair : state_manager_->packages()) {
+    all_traits.insert(pair.first);
+    std::string key = base::StringPrintf("%s.state", pair.first.c_str());
+    traits.Set(key, pair.second->types().DeepCopy());
+    key = base::StringPrintf("state.%s", pair.first.c_str());
+    component.Set(key, pair.second->GetValuesAsJson().DeepCopy());
+  }
+  for (base::DictionaryValue::Iterator it(commands); !it.IsAtEnd();
+       it.Advance()) {
+    all_traits.insert(it.key());
+    std::string key = base::StringPrintf("%s.commands", it.key().c_str());
+    traits.Set(key, it.value().DeepCopy());
+  }
+  resource->Set("traits", traits.DeepCopy());
+  base::ListValue* trait_list = new base::ListValue();
+  for (const std::string& trait : all_traits)
+    trait_list->AppendString(trait);
+  component.Set("traits", trait_list);
+  resource->Set("components.device", component.DeepCopy());
   return resource;
 }
 
diff --git a/src/states/state_manager.h b/src/states/state_manager.h
index c48a57c..bd1eb92 100644
--- a/src/states/state_manager.h
+++ b/src/states/state_manager.h
@@ -58,6 +58,10 @@
     return state_change_queue_;
   }
 
+  const std::map<std::string, std::unique_ptr<StatePackage>>& packages() const {
+    return packages_;
+  }
+
  private:
   friend class BaseApiHandlerTest;
   friend class StateManagerTest;
diff --git a/src/states/state_package.h b/src/states/state_package.h
index 4092948..afc4c52 100644
--- a/src/states/state_package.h
+++ b/src/states/state_package.h
@@ -58,6 +58,8 @@
   // Returns the name of the this package.
   const std::string& GetName() const { return name_; }
 
+  const base::DictionaryValue& types() const { return types_; }
+
  private:
   std::string name_;
   base::DictionaryValue types_;