buffet: Add command definition support for GCD command manager

Rudimentary framework of classes to represent GCD command manager
and list of registered device command definitions/schemas.

BUG=chromium:374861
TEST=USE=buffet P2_TEST_FILTER="buffet::*" FEATURES=test emerge-link platform

Change-Id: I3cd3d776879e8bd506aecd20df5cd89c65247d35
Reviewed-on: https://chromium-review.googlesource.com/208464
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Reviewed-by: Christopher Wiley <wiley@chromium.org>
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/commands/command_dictionary.h b/buffet/commands/command_dictionary.h
new file mode 100644
index 0000000..11295c9
--- /dev/null
+++ b/buffet/commands/command_dictionary.h
@@ -0,0 +1,72 @@
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BUFFET_COMMANDS_COMMAND_DICTIONARY_H_
+#define BUFFET_COMMANDS_COMMAND_DICTIONARY_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <base/basictypes.h>
+
+#include "buffet/error.h"
+
+namespace base {
+class Value;
+class DictionaryValue;
+}  // namespace base
+
+namespace buffet {
+
+class CommandDefinition;
+
+// CommandDictionary is a wrapper around a map of command name and the
+// corresponding command definition schema. The command name (the key in
+// the map) is a compound name in a form of "package_name.command_name",
+// where "package_name" is a name of command package such as "base", "printers",
+// and others. So the full command name could be "base.reboot", for example.
+class CommandDictionary {
+ public:
+  CommandDictionary() = default;
+
+  // Gets the list of names of commands that belong to the given category.
+  std::vector<std::string> GetCommandNamesByCategory(
+      const std::string& category) const;
+
+  // Loads command definitions from a JSON object. This is done at the daemon
+  // startup and whenever a device daemon decides to update its command list.
+  // |json| is a JSON dictionary that describes the complete commands contained
+  // in a particular |category|. Usually, |categories| are 1:1 with daemons on
+  // a device. For instance, the power manager daemon might provide a category
+  // "power_man" that provides the "base.reboot" and "base.shutdown" commands.
+  // However, nothing prohibits a daemon providing commands in two categories.
+  // When LoadCommands is called, all previous definitions of commands from the
+  // same category are removed, effectively replacing all the commands in the
+  // given category.
+  // Returns false on failure and |error| provides additional error information
+  // when provided.
+  bool LoadCommands(const base::DictionaryValue& json,
+                    const std::string& category, ErrorPtr* error);
+  // Returns the number of command definitions in the dictionary.
+  size_t GetSize() const { return definitions_.size(); }
+  // Checks if the dictionary has no command definitions.
+  bool IsEmpty() const { return definitions_.empty(); }
+  // Remove all the command definitions from the dictionary.
+  void Clear();
+  // Finds a definition for the given command.
+  const CommandDefinition* FindCommand(const std::string& command_name) const;
+
+ private:
+  using CommandMap = std::map<std::string,
+                              std::shared_ptr<const CommandDefinition>>;
+
+  CommandMap definitions_;  // List of all available command definitions.
+  DISALLOW_COPY_AND_ASSIGN(CommandDictionary);
+};
+
+}  // namespace buffet
+
+#endif  // BUFFET_COMMANDS_COMMAND_DICTIONARY_H_