1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef COMPONENTS_CLOUD_DEVICES_COMMON_DESCRIPTION_DESCRIPTION_ITEMS_INL_H_
6#define COMPONENTS_CLOUD_DEVICES_COMMON_DESCRIPTION_DESCRIPTION_ITEMS_INL_H_
7
8#include <vector>
9
10#include "base/numerics/safe_conversions.h"
11#include "components/cloud_devices/common/description_items.h"
12
13// Implementation of templates defined in header file.
14// This file should be included from CC file with implementation of device
15// specific capabilities.
16
17namespace cloud_devices {
18
19template <class Option, class Traits>
20ListCapability<Option, Traits>::ListCapability() {
21  Reset();
22}
23
24template <class Option, class Traits>
25ListCapability<Option, Traits>::~ListCapability() {
26}
27
28template <class Option, class Traits>
29bool ListCapability<Option, Traits>::IsValid() const {
30  if (empty())
31    return false;  // This type of capabilities can't be empty.
32  for (size_t i = 0; i < options_.size(); ++i) {
33    if (!Traits::IsValid(options_[i]))
34      return false;
35  }
36  return true;
37}
38
39template <class Option, class Traits>
40bool ListCapability<Option, Traits>::LoadFrom(
41    const CloudDeviceDescription& description) {
42  Reset();
43  const base::ListValue* options =
44      description.GetListItem(Traits::GetCapabilityPath());
45  if (!options)
46    return false;
47  for (size_t i = 0; i < options->GetSize(); ++i) {
48    const base::DictionaryValue* option_value = NULL;
49    if (!options->GetDictionary(i, &option_value))
50      return false;  // Every entry must be a dictionary.
51    Option option;
52    if (!Traits::Load(*option_value, &option))
53      return false;
54    AddOption(option);
55  }
56  return IsValid();
57}
58
59template <class Option, class Traits>
60void ListCapability<Option, Traits>::SaveTo(
61    CloudDeviceDescription* description) const {
62  DCHECK(IsValid());
63  base::ListValue* options_list =
64      description->CreateListItem(Traits::GetCapabilityPath());
65  for (size_t i = 0; i < options_.size(); ++i) {
66    base::DictionaryValue* option_value = new base::DictionaryValue;
67    options_list->Append(option_value);
68    Traits::Save(options_[i], option_value);
69  }
70}
71
72template <class Option, class Traits>
73SelectionCapability<Option, Traits>::SelectionCapability() {
74  Reset();
75}
76
77template <class Option, class Traits>
78SelectionCapability<Option, Traits>::~SelectionCapability() {
79}
80
81template <class Option, class Traits>
82bool SelectionCapability<Option, Traits>::IsValid() const {
83  if (empty())
84    return false;  // This type of capabilities can't be empty
85  for (size_t i = 0; i < options_.size(); ++i) {
86    if (!Traits::IsValid(options_[i]))
87      return false;
88  }
89  return default_idx_ >= 0 && default_idx_ < base::checked_cast<int>(size());
90}
91
92template <class Option, class Traits>
93bool SelectionCapability<Option, Traits>::LoadFrom(
94    const CloudDeviceDescription& description) {
95  Reset();
96  const base::DictionaryValue* item =
97      description.GetItem(Traits::GetCapabilityPath());
98  if (!item)
99    return false;
100  const base::ListValue* options = NULL;
101  if (!item->GetList(json::kKeyOption, &options))
102    return false;
103  for (size_t i = 0; i < options->GetSize(); ++i) {
104    const base::DictionaryValue* option_value = NULL;
105    if (!options->GetDictionary(i, &option_value))
106      return false;  // Every entry must be a dictionary.
107    Option option;
108    if (!Traits::Load(*option_value, &option))
109      return false;
110    bool is_default = false;
111    option_value->GetBoolean(json::kKeyIsDefault, &is_default);
112    if (is_default && default_idx_ >= 0) {
113      return false;  // Multiple defaults.
114    }
115    AddDefaultOption(option, is_default);
116  }
117  return IsValid();
118}
119
120template <class Option, class Traits>
121void SelectionCapability<Option, Traits>::SaveTo(
122    CloudDeviceDescription* description) const {
123  DCHECK(IsValid());
124  base::ListValue* options_list = new base::ListValue;
125  description->CreateItem(Traits::GetCapabilityPath())
126      ->Set(json::kKeyOption, options_list);
127  for (size_t i = 0; i < options_.size(); ++i) {
128    base::DictionaryValue* option_value = new base::DictionaryValue;
129    options_list->Append(option_value);
130    if (base::checked_cast<int>(i) == default_idx_)
131      option_value->SetBoolean(json::kKeyIsDefault, true);
132    Traits::Save(options_[i], option_value);
133  }
134}
135
136template <class Traits>
137BooleanCapability<Traits>::BooleanCapability() {
138  Reset();
139}
140
141template <class Traits>
142BooleanCapability<Traits>::~BooleanCapability() {
143}
144
145template <class Traits>
146bool BooleanCapability<Traits>::LoadFrom(
147    const CloudDeviceDescription& description) {
148  Reset();
149  const base::DictionaryValue* dict =
150      description.GetItem(Traits::GetCapabilityPath());
151  if (!dict)
152    return false;
153  default_value_ = Traits::kDefault;
154  dict->GetBoolean(json::kKeyDefault, &default_value_);
155  return true;
156}
157
158template <class Traits>
159void BooleanCapability<Traits>::SaveTo(
160    CloudDeviceDescription* description) const {
161  base::DictionaryValue* dict =
162      description->CreateItem(Traits::GetCapabilityPath());
163  if (default_value_ != Traits::kDefault)
164    dict->SetBoolean(json::kKeyDefault, default_value_);
165}
166
167template <class Traits>
168bool EmptyCapability<Traits>::LoadFrom(
169    const CloudDeviceDescription& description) {
170  return description.GetItem(Traits::GetCapabilityPath()) != NULL;
171}
172
173template <class Traits>
174void EmptyCapability<Traits>::SaveTo(
175    CloudDeviceDescription* description) const {
176  description->CreateItem(Traits::GetCapabilityPath());
177}
178
179template <class Option, class Traits>
180ValueCapability<Option, Traits>::ValueCapability() {
181  Reset();
182}
183
184template <class Option, class Traits>
185ValueCapability<Option, Traits>::~ValueCapability() {
186}
187
188template <class Option, class Traits>
189bool ValueCapability<Option, Traits>::IsValid() const {
190  return Traits::IsValid(value());
191}
192
193template <class Option, class Traits>
194bool ValueCapability<Option, Traits>::LoadFrom(
195    const CloudDeviceDescription& description) {
196  Reset();
197  const base::DictionaryValue* option_value =
198      description.GetItem(Traits::GetCapabilityPath());
199  if (!option_value)
200    return false;
201  Option option;
202  if (!Traits::Load(*option_value, &option))
203    return false;
204  set_value(option);
205  return IsValid();
206}
207
208template <class Option, class Traits>
209void ValueCapability<Option, Traits>::SaveTo(
210    CloudDeviceDescription* description) const {
211  DCHECK(IsValid());
212  Traits::Save(value(), description->CreateItem(Traits::GetCapabilityPath()));
213}
214
215template <class Option, class Traits>
216TicketItem<Option, Traits>::TicketItem() {
217  Reset();
218}
219
220template <class Option, class Traits>
221TicketItem<Option, Traits>::~TicketItem() {
222}
223
224template <class Option, class Traits>
225bool TicketItem<Option, Traits>::IsValid() const {
226  return Traits::IsValid(value());
227}
228
229template <class Option, class Traits>
230bool TicketItem<Option, Traits>::LoadFrom(
231    const CloudDeviceDescription& description) {
232  Reset();
233  const base::DictionaryValue* option_value =
234      description.GetItem(Traits::GetTicketItemPath());
235  if (!option_value)
236    return false;
237  Option option;
238  if (!Traits::Load(*option_value, &option))
239    return false;
240  set_value(option);
241  return IsValid();
242}
243
244template <class Option, class Traits>
245void TicketItem<Option, Traits>::SaveTo(
246    CloudDeviceDescription* description) const {
247  DCHECK(IsValid());
248  Traits::Save(value(), description->CreateItem(Traits::GetTicketItemPath()));
249}
250
251}  // namespace cloud_devices
252
253#endif  // COMPONENTS_CLOUD_DEVICES_COMMON_DESCRIPTION_DESCRIPTION_ITEMS_INL_H_
254