15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
50529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#ifndef COMPONENTS_CLOUD_DEVICES_COMMON_DESCRIPTION_DESCRIPTION_ITEMS_INL_H_
60529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#define COMPONENTS_CLOUD_DEVICES_COMMON_DESCRIPTION_DESCRIPTION_ITEMS_INL_H_
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <vector>
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/numerics/safe_conversions.h"
110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/cloud_devices/common/description_items.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Implementation of templates defined in header file.
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This file should be included from CC file with implementation of device
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// specific capabilities.
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace cloud_devices {
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Option, class Traits>
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ListCapability<Option, Traits>::ListCapability() {
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Reset();
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Option, class Traits>
250529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochListCapability<Option, Traits>::~ListCapability() {
260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Option, class Traits>
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ListCapability<Option, Traits>::IsValid() const {
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (empty())
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;  // This type of capabilities can't be empty.
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < options_.size(); ++i) {
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!Traits::IsValid(options_[i]))
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Option, class Traits>
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ListCapability<Option, Traits>::LoadFrom(
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const CloudDeviceDescription& description) {
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Reset();
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::ListValue* options =
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      description.GetListItem(Traits::GetCapabilityPath());
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!options)
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < options->GetSize(); ++i) {
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::DictionaryValue* option_value = NULL;
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!options->GetDictionary(i, &option_value))
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;  // Every entry must be a dictionary.
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Option option;
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!Traits::Load(*option_value, &option))
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddOption(option);
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return IsValid();
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Option, class Traits>
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ListCapability<Option, Traits>::SaveTo(
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CloudDeviceDescription* description) const {
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(IsValid());
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* options_list =
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      description->CreateListItem(Traits::GetCapabilityPath());
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < options_.size(); ++i) {
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* option_value = new base::DictionaryValue;
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    options_list->Append(option_value);
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Traits::Save(options_[i], option_value);
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Option, class Traits>
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SelectionCapability<Option, Traits>::SelectionCapability() {
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Reset();
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Option, class Traits>
780529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochSelectionCapability<Option, Traits>::~SelectionCapability() {
790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Option, class Traits>
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool SelectionCapability<Option, Traits>::IsValid() const {
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (empty())
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;  // This type of capabilities can't be empty
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < options_.size(); ++i) {
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!Traits::IsValid(options_[i]))
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return default_idx_ >= 0 && default_idx_ < base::checked_cast<int>(size());
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Option, class Traits>
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool SelectionCapability<Option, Traits>::LoadFrom(
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const CloudDeviceDescription& description) {
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Reset();
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* item =
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      description.GetItem(Traits::GetCapabilityPath());
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!item)
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::ListValue* options = NULL;
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!item->GetList(json::kKeyOption, &options))
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < options->GetSize(); ++i) {
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::DictionaryValue* option_value = NULL;
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!options->GetDictionary(i, &option_value))
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;  // Every entry must be a dictionary.
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Option option;
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!Traits::Load(*option_value, &option))
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool is_default = false;
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    option_value->GetBoolean(json::kKeyIsDefault, &is_default);
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (is_default && default_idx_ >= 0) {
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;  // Multiple defaults.
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddDefaultOption(option, is_default);
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return IsValid();
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Option, class Traits>
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SelectionCapability<Option, Traits>::SaveTo(
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CloudDeviceDescription* description) const {
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(IsValid());
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* options_list = new base::ListValue;
1250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  description->CreateItem(Traits::GetCapabilityPath())
1260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      ->Set(json::kKeyOption, options_list);
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < options_.size(); ++i) {
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* option_value = new base::DictionaryValue;
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    options_list->Append(option_value);
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (base::checked_cast<int>(i) == default_idx_)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      option_value->SetBoolean(json::kKeyIsDefault, true);
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Traits::Save(options_[i], option_value);
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Traits>
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)BooleanCapability<Traits>::BooleanCapability() {
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Reset();
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Traits>
1420529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochBooleanCapability<Traits>::~BooleanCapability() {
1430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Traits>
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BooleanCapability<Traits>::LoadFrom(
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const CloudDeviceDescription& description) {
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Reset();
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* dict =
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      description.GetItem(Traits::GetCapabilityPath());
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!dict)
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  default_value_ = Traits::kDefault;
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dict->GetBoolean(json::kKeyDefault, &default_value_);
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Traits>
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BooleanCapability<Traits>::SaveTo(
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CloudDeviceDescription* description) const {
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* dict =
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      description->CreateItem(Traits::GetCapabilityPath());
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (default_value_ != Traits::kDefault)
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dict->SetBoolean(json::kKeyDefault, default_value_);
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Traits>
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool EmptyCapability<Traits>::LoadFrom(
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const CloudDeviceDescription& description) {
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return description.GetItem(Traits::GetCapabilityPath()) != NULL;
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Traits>
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void EmptyCapability<Traits>::SaveTo(
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CloudDeviceDescription* description) const {
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  description->CreateItem(Traits::GetCapabilityPath());
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Option, class Traits>
180effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochValueCapability<Option, Traits>::ValueCapability() {
181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  Reset();
182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
183effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
184effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochtemplate <class Option, class Traits>
1850529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochValueCapability<Option, Traits>::~ValueCapability() {
1860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
187effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
188effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochtemplate <class Option, class Traits>
189effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool ValueCapability<Option, Traits>::IsValid() const {
190effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return Traits::IsValid(value());
191effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
192effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
193effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochtemplate <class Option, class Traits>
194effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool ValueCapability<Option, Traits>::LoadFrom(
195effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const CloudDeviceDescription& description) {
196effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  Reset();
197effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const base::DictionaryValue* option_value =
198effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      description.GetItem(Traits::GetCapabilityPath());
199effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!option_value)
200effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return false;
201effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  Option option;
202effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!Traits::Load(*option_value, &option))
203effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return false;
204effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  set_value(option);
205effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return IsValid();
206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochtemplate <class Option, class Traits>
209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ValueCapability<Option, Traits>::SaveTo(
210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    CloudDeviceDescription* description) const {
211effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(IsValid());
212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  Traits::Save(value(), description->CreateItem(Traits::GetCapabilityPath()));
213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
214effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochtemplate <class Option, class Traits>
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TicketItem<Option, Traits>::TicketItem() {
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Reset();
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Option, class Traits>
2210529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTicketItem<Option, Traits>::~TicketItem() {
2220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Option, class Traits>
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool TicketItem<Option, Traits>::IsValid() const {
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return Traits::IsValid(value());
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Option, class Traits>
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool TicketItem<Option, Traits>::LoadFrom(
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const CloudDeviceDescription& description) {
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Reset();
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* option_value =
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      description.GetItem(Traits::GetTicketItemPath());
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!option_value)
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Option option;
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!Traits::Load(*option_value, &option))
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  set_value(option);
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return IsValid();
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <class Option, class Traits>
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TicketItem<Option, Traits>::SaveTo(
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CloudDeviceDescription* description) const {
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(IsValid());
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Traits::Save(value(), description->CreateItem(Traits::GetTicketItemPath()));
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace cloud_devices
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#endif  // COMPONENTS_CLOUD_DEVICES_COMMON_DESCRIPTION_DESCRIPTION_ITEMS_INL_H_
254