1// Copyright (c) 2012 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#include "chromeos/network/onc/onc_mapper.h"
6
7#include "base/logging.h"
8#include "base/values.h"
9#include "chromeos/network/onc/onc_signature.h"
10
11namespace chromeos {
12namespace onc {
13
14Mapper::Mapper() {
15}
16
17Mapper::~Mapper() {
18}
19
20scoped_ptr<base::Value> Mapper::MapValue(const OncValueSignature& signature,
21                                         const base::Value& onc_value,
22                                         bool* error) {
23  scoped_ptr<base::Value> result_value;
24  switch (onc_value.GetType()) {
25    case base::Value::TYPE_DICTIONARY: {
26      const base::DictionaryValue* dict = NULL;
27      onc_value.GetAsDictionary(&dict);
28      result_value = MapObject(signature, *dict, error);
29      break;
30    }
31    case base::Value::TYPE_LIST: {
32      const base::ListValue* list = NULL;
33      onc_value.GetAsList(&list);
34      result_value = MapArray(signature, *list, error);
35      break;
36    }
37    default: {
38      result_value = MapPrimitive(signature, onc_value, error);
39      break;
40    }
41  }
42
43  return result_value.Pass();
44}
45
46scoped_ptr<base::DictionaryValue> Mapper::MapObject(
47    const OncValueSignature& signature,
48    const base::DictionaryValue& onc_object,
49    bool* error) {
50  scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue);
51
52  bool found_unknown_field = false;
53  MapFields(signature, onc_object, &found_unknown_field, error, result.get());
54  if (found_unknown_field)
55    *error = true;
56  return result.Pass();
57}
58
59scoped_ptr<base::Value> Mapper::MapPrimitive(const OncValueSignature& signature,
60                                             const base::Value& onc_primitive,
61                                             bool* error) {
62  return make_scoped_ptr(onc_primitive.DeepCopy());
63}
64
65void Mapper::MapFields(const OncValueSignature& object_signature,
66                       const base::DictionaryValue& onc_object,
67                       bool* found_unknown_field,
68                       bool* nested_error,
69                       base::DictionaryValue* result) {
70  for (base::DictionaryValue::Iterator it(onc_object); !it.IsAtEnd();
71       it.Advance()) {
72    bool current_field_unknown = false;
73    scoped_ptr<base::Value> result_value = MapField(it.key(),
74                                                    object_signature,
75                                                    it.value(),
76                                                    &current_field_unknown,
77                                                    nested_error);
78
79    if (current_field_unknown)
80      *found_unknown_field = true;
81    else if (result_value.get() != NULL)
82      result->SetWithoutPathExpansion(it.key(), result_value.release());
83    else
84      DCHECK(*nested_error);
85  }
86}
87
88scoped_ptr<base::Value> Mapper::MapField(
89    const std::string& field_name,
90    const OncValueSignature& object_signature,
91    const base::Value& onc_value,
92    bool* found_unknown_field,
93    bool* error) {
94  const OncFieldSignature* field_signature =
95      GetFieldSignature(object_signature, field_name);
96
97  if (field_signature != NULL) {
98    DCHECK(field_signature->value_signature != NULL)
99        << "Found missing value signature at field '" << field_name << "'.";
100
101    return MapValue(*field_signature->value_signature, onc_value, error);
102  } else {
103    DVLOG(1) << "Found unknown field name: '" << field_name << "'";
104    *found_unknown_field = true;
105    return scoped_ptr<base::Value>();
106  }
107}
108
109scoped_ptr<base::ListValue> Mapper::MapArray(
110    const OncValueSignature& array_signature,
111    const base::ListValue& onc_array,
112    bool* nested_error) {
113  DCHECK(array_signature.onc_array_entry_signature != NULL)
114      << "Found missing onc_array_entry_signature.";
115
116  scoped_ptr<base::ListValue> result_array(new base::ListValue);
117  int original_index = 0;
118  for (base::ListValue::const_iterator it = onc_array.begin();
119       it != onc_array.end(); ++it, ++original_index) {
120    const base::Value* entry = *it;
121
122    scoped_ptr<base::Value> result_entry;
123    result_entry = MapEntry(original_index,
124                            *array_signature.onc_array_entry_signature,
125                            *entry,
126                            nested_error);
127    if (result_entry.get() != NULL)
128      result_array->Append(result_entry.release());
129    else
130      DCHECK(*nested_error);
131  }
132  return result_array.Pass();
133}
134
135scoped_ptr<base::Value> Mapper::MapEntry(int index,
136                                         const OncValueSignature& signature,
137                                         const base::Value& onc_value,
138                                         bool* error) {
139  return MapValue(signature, onc_value, error);
140}
141
142}  // namespace onc
143}  // namespace chromeos
144