Google APIs Client Library for C++
|
00001 /* 00002 * \copyright Copyright 2013 Google Inc. All Rights Reserved. 00003 * \license @{ 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 * 00017 * @} 00018 */ 00019 00020 /* 00021 * @defgroup DataLayerJsonCpp Data Layer - JSON Support (using JsonCpp) 00022 * 00023 * The current implementation of JSON support uses the third-party JsonCpp 00024 * lirary (http://jsoncpp.sourceforge.net/) which has some issues that leak 00025 * into the interface. Therefore, I'm grouping these into a 'JsonCpp' module. 00026 * 00027 * The design of the JsonCpp sub-module makes pragmatic tradeoffs in order 00028 * to use this existing implementation. The main thing to be aware of is that 00029 * the signatures of the class methods in this module often use call by 00030 * value-result semantics rather than call by reference as you would expect. 00031 * However, the internal implementation is often actually call by reference. 00032 * So the semantics (and performance) are similar to call-by reference but 00033 * the code feels like cal-by value. This is unfortunate and I hope to address 00034 * it in future releases. 00035 */ 00036 00037 #ifndef APISERVING_CLIENTS_CPP_DATA_JSONCPP_DATA_H_ 00038 #define APISERVING_CLIENTS_CPP_DATA_JSONCPP_DATA_H_ 00039 #include <string> 00040 using std::string; 00041 #include <utility> 00042 using std::make_pair; 00043 using std::pair; 00044 #include <vector> 00045 using std::vector; 00046 00047 #include "googleapis/client/data/serializable_json.h" 00048 #include "googleapis/client/data/jsoncpp_data_helpers.h" 00049 #include <glog/logging.h> 00050 #include "googleapis/base/macros.h" 00051 #include <json/json.h> 00052 namespace googleapis { 00053 00054 namespace client { 00055 00056 class DataReader; 00057 00058 // Forward declaration 00059 template<typename T> class JsonCppConstIndexIterator; 00060 template<typename T> class JsonCppConstAssociativeIterator; 00061 00062 /* 00063 * Base class for data objects using JsonCpp for underlying state. 00064 * @ingroup DataLayerJsonCpp 00065 * 00066 * Class instances are either const or mutable depending on how they are 00067 * constructed. If constructed with a const reference, the instance will not 00068 * allow direct mutation. If constructed with a pointer, the instance will 00069 * allow mutation. It doesnt necessarily have to be like this, just seems like 00070 * a reasonable safety mechanism given the wrapper ipmlementation strategy. 00071 * 00072 * The objects are intended to be used in a call-by-value / value-result syntax 00073 * however the "values" are actually references so semantics are actually 00074 * call-by-reference. Admitedly this is unfortunate (i.e. weird) but it is to 00075 * allow object wrappers to be used in a complete and uniform way when 00076 * accessing and modifying complex composite objects through their various 00077 * parts. Since the wrapper object state is just a pointer (and a bool) the 00078 * copying syntax should not add much runtime overhead. 00079 * 00080 * Keeping all the state in the Json::Value object will likely add runtime 00081 * overhead however. Rather than attributes (of derived classes) being inlined 00082 * member variables, they will be [] operator lookups on string names. The 00083 * tradeoff here is for completeness, correctness, and internal implementation 00084 * convienence in the short term to get things up and running more quickly to 00085 * play with and understand strategic issues beyond performance. 00086 * 00087 * Keeping all the state together allows unknown attributes to be first-class 00088 * citizens along with known ones. Serialization, iteration, and so forth are 00089 * already handled (and in an open soure library) by jsoncpp. Presumably since 00090 * this is cheap to implement, it will be cheap to throw away and replace, 00091 * investing the effort for runtime efficiency (or finding another package) 00092 * at some future point down the road when it is a more pressing impedement. 00093 * 00094 * This class is not thread-safe. 00095 */ 00096 class JsonCppData : public SerializableJson { 00097 public: 00098 /* 00099 * Standard constructor for an immutable instances. 00100 * 00101 * @param[in] value Provides the underlying JsonCpp storage. 00102 * The lifetime of 'value' must be retained over the lifetime of 00103 * this instance, however the state can change internally. 00104 */ 00105 explicit JsonCppData(const Json::Value& value); 00106 00107 /* 00108 * Standard constructor for mutable instances. 00109 * 00110 * @param[in] value Provides the underlying JsonCpp storage. 00111 * Ownership of 'value' is retained by the caller and 00112 * must live beyond the lifecycle of this instance. 00113 */ 00114 explicit JsonCppData(Json::Value* value); 00115 00116 /* 00117 * Standard destructor. 00118 */ 00119 virtual ~JsonCppData(); 00120 00121 /* 00122 * Restores the state of this object from the JSON in the given std::istream. 00123 * 00124 * @param[in] stream The stream to read from. 00125 * @return ok or explaination of failure. 00126 * 00127 * @see LoadFromJsonReader 00128 */ 00129 virtual util::Status LoadFromJsonStream(std::istream* stream); 00130 00131 /* 00132 * Stores the state of this object as JSON in the given std::ostream. 00133 * 00134 * @param[in] stream The stream to write to. 00135 * @return ok or explaination of failure. 00136 * 00137 * @see MakeJsonReader 00138 */ 00139 virtual util::Status StoreToJsonStream(std::ostream* stream) const; 00140 00141 /* 00142 * Clears this instance state to an empty object. 00143 */ 00144 virtual void Clear(); 00145 00146 /* 00147 * Restores the state of this object from the JSON in the given reader. 00148 * 00149 * @param[in] reader The byte-sequence to read from. 00150 * @return ok or explaination of failure. 00151 */ 00152 virtual util::Status LoadFromJsonReader(DataReader* reader); 00153 00154 /* 00155 * Serializes the object into a JSON byte stream. 00156 * 00157 * @return A standard reader interface around the JSON encoded object. 00158 */ 00159 virtual DataReader* MakeJsonReader() const; 00160 00161 /* 00162 * Copies state from another instance into this one. 00163 * 00164 * This will preserve the existing IsMutable-ness of this instance. 00165 * 00166 * @param[in] from The state to copy from. 00167 */ 00168 void CopyFrom(const JsonCppData& from) { 00169 *MutableStorage() = from.Storage(); 00170 } 00171 00172 /* 00173 * Determines if this instance is mutable or not. 00174 * 00175 * Mutability is determined by which constructor was used. 00176 * 00177 * @return true if the instance is mutable. 00178 */ 00179 bool IsMutable() const { return is_mutable_; } 00180 00181 /* 00182 * Determines if the represented JSON value is NULL. 00183 * 00184 * @return true if the underlying Json::Value denotes a null value. 00185 */ 00186 bool IsNull() const { return value_->isNull(); } 00187 00188 /* 00189 * Ensures the instance is mutable or terminate if not. 00190 * 00191 * If the instance is not mutable this call will CHECK-fail and 00192 * terminate the program. It is only intended to make assertions 00193 * that indicate programming errors. 00194 */ 00195 void CheckIsMutable() const { CHECK(is_mutable_); } 00196 00197 /* 00198 * Returns reference to the Json::Value instance used for storage. 00199 * 00200 * @return The instance bound in the constructor. 00201 */ 00202 const Json::Value& Storage() const { return *value_; } 00203 00204 /* 00205 * Returns reference to the Json::Value instance used for storage. 00206 * 00207 * This will create a new subcomponent if one did not already exist. 00208 * 00209 * @param[in] key The JSON name of the desired subcomponent. 00210 * 00211 * @return The instance might be Json::Value::isNull but will be valid. 00212 */ 00213 const Json::Value& Storage(const char* key) const { return (*value_)[key]; } 00214 00215 /* 00216 * Returns a pointer to the storage bound in the constructor. 00217 * 00218 * This method will CHECK fail if the instance is immutable. 00219 */ 00220 Json::Value* MutableStorage() { 00221 CheckIsMutable(); 00222 return value_; 00223 } 00224 00225 /* 00226 * Returns a pointer to the storage for the named subcomponent. 00227 * 00228 * This method will CHECK fail if the instance is immutable. 00229 */ 00230 Json::Value* MutableStorage(const char* key) { 00231 CheckIsMutable(); 00232 return &(*value_)[key]; 00233 } 00234 00235 /* 00236 * Determines if the object instances are equivalent. 00237 */ 00238 bool operator==(const JsonCppData& other) const { 00239 return *value_ == *other.value_; 00240 } 00241 00242 private: 00243 bool is_mutable_; 00244 Json::Value* value_; // reference is not owned 00245 00246 // Disallow assigning but preserve copying because we'll need to return 00247 // wrapped object instances from the APIs due to the call-by-value 00248 // constraints inherited from the underlying JsonCpp API. 00249 void operator=(const JsonCppData& obj); 00250 }; 00251 00252 /* 00253 * Base class template for a JsonCppData object that is an array. 00254 * @ingroup DataLyaerJsonCpp 00255 * 00256 * Arrays currently follow the JsonCpp implementation where they grow on 00257 * demand. Accessing an element wil create it if it did not already exist. 00258 * 00259 * This class is not thread-safe. 00260 * 00261 * @todo(ewiseblatt): 20120825 00262 * Probably change this so the arrays are fixed size unless you resize the 00263 * array or append/remove from it. That means get/set should rangecheck. 00264 */ 00265 template<typename T> 00266 class JsonCppArray : public JsonCppData { 00267 public: 00268 typedef JsonCppConstIndexIterator<T> const_iterator; 00269 00270 /* 00271 * Standard constructor for an immutable array. 00272 * 00273 * @param[in] value Provides the underlying storage for the array. 00274 */ 00275 explicit JsonCppArray(const Json::Value& value) 00276 : JsonCppData(value) { 00277 } 00278 00279 /* 00280 * Standard constructor for a mutable array. 00281 * 00282 * @param[in] value Provides the underlying storage for the array. 00283 */ 00284 explicit JsonCppArray(Json::Value* value) 00285 : JsonCppData(value) { 00286 } 00287 00288 /* 00289 * Determines if array is empty or not. 00290 */ 00291 bool empty() const { return Storage().size() == 0; } 00292 00293 /* 00294 * Determines the number of elements currently in the array. 00295 */ 00296 int size() const { return Storage().size(); } 00297 00298 /* 00299 * Gets the [immutable] underlying JsonCpp storage for a given array element. 00300 * 00301 * @see as_object 00302 * @see get 00303 */ 00304 const Json::Value& as_value(int i) const { return Storage()[i]; } 00305 00306 /* 00307 * Gets the [mutable] underlying JsonCpp storage for a given array element. 00308 * 00309 * This method will CHECK fail if the array is not mutable. 00310 * 00311 * @see as_mutable_object 00312 * @see mutable_get 00313 */ 00314 Json::Value* as_mutable_value(int i) { return &(*MutableStorage())[i]; } 00315 00316 /* 00317 * Gets the [immutable] JsonCppData instance wrapping a given array element. 00318 * 00319 * @see as_value 00320 * @see get 00321 */ 00322 const JsonCppData as_object(int i) const { 00323 return JsonCppData(as_value(i)); 00324 } 00325 00326 /* 00327 * Gets the [mutable] JsonCppData instance wrapping a given array element. 00328 * 00329 * @see as_mutable_value 00330 * @see mutable_get 00331 */ 00332 JsonCppData as_mutable_object(int i) { 00333 return JsonCppData(as_mutable_value(i)); 00334 } 00335 00336 /* 00337 * Returns the starting point for iterating over the elements. 00338 * 00339 * Unfortunately this data model only permits const iterators 00340 * because of the call-by-value-result nature of the api. We cant modify 00341 * the elements unless we create a storage iterator that iterates over the 00342 * storage (which you can already do by saying MutableStorage()->begin/end() 00343 */ 00344 const_iterator begin() const { return const_iterator(Storage().begin()); } 00345 00346 /* 00347 * Returns the ending poitn when iterating over the elements 00348 */ 00349 const_iterator end() const { return const_iterator(Storage().end()); } 00350 00351 /* 00352 * Changes the value for the given element. 00353 * 00354 * This method will CHECK-fail if the array is not mutable. 00355 * 00356 * @param[in] i The index to change will be added if it was not present. 00357 * @param[in] value The value to copy. 00358 */ 00359 void set(int i, const T& value) { 00360 SetJsonValueFromCppValueHelper<T>(value, as_mutable_value(i)); 00361 } 00362 00363 /* 00364 * Returns the value for the given index. 00365 * @param[in] i The element index to get. 00366 */ 00367 const T get(int i) const { 00368 return JsonValueToCppValueHelper<T>(as_value(i)); 00369 } 00370 00371 /* 00372 * Returns a mutable value for the given index. 00373 * 00374 * This method will CHECK-fail if the array is not mutable. 00375 * 00376 * @return The value as opposed to a pointer. See the class description 00377 * for more information about the calling conventions. 00378 * Although the value is not a pointer, it will be mutable if 00379 * <code>T</code> denotes a <code>JsonCppObject</code>. For 00380 * primitive types (and strings) this method will return copy 00381 * that will not actually mutate the underlying element. 00382 */ 00383 T mutable_get(int i) { 00384 return JsonValueToMutableCppValueHelper<T>(as_mutable_value(i)); 00385 } 00386 00387 /* 00388 * Provides syntactic sugar for get using [] operator overloading. 00389 */ 00390 const T operator[](int i) const { return get(i); } 00391 00392 /* 00393 * Provides syntactic sugar for mutable_get using [] operator overloading. 00394 */ 00395 T operator[](int i) { return mutable_get(i); } 00396 00397 00398 /* 00399 * Imports data from a C++ vector into this instance. 00400 * 00401 * This method will clear the current data before importing the new. 00402 * 00403 * @param[in] array The vector to import from. 00404 */ 00405 void Import(const vector<T>& array) { 00406 Clear(); 00407 MutableStorage()->resize(array.size()); 00408 for (int i = 0; i < array.size(); ++i) { 00409 set(i, array[i]); 00410 } 00411 } 00412 00413 /* 00414 * Imports data from a C++ aray into this instance. 00415 * 00416 * This method will clear the current data before importing the new. 00417 * 00418 * @param[in] array The array to import from. 00419 * @param[in] len The number of elements int he array to import. 00420 */ 00421 void Import(const T* array, int len) { 00422 Clear(); 00423 for (int i = 0; i < len; ++i) { 00424 set(i, array[i]); 00425 } 00426 } 00427 00428 /* 00429 * Exports data from this instance into a given C++ vector. 00430 * 00431 * This will clear the array before exporting. 00432 */ 00433 void Export(vector<T>* array) const { Export(0, size(), array); } 00434 00435 /* 00436 * Exports a range of data from this instance into a given C++ vector. 00437 * 00438 * This will clear the array before exporting. 00439 * 00440 * @param[in] offset The first index in this array to eport 00441 * @param[in] count The number of elements to export 00442 * @param[out] array The array to write to will be cleared before writing. 00443 * The element at offset will be written into the 0'th element. 00444 * @return false if the existing bounds of this array are not consistent 00445 * with the arguments. 00446 */ 00447 bool Export(int offset, int count, vector<T>* array) const { 00448 const Json::Value& json = Storage(); 00449 if (offset + count > json.size()) return false; 00450 00451 array->clear(); 00452 array->resize(count); 00453 for (int i = 0; i < count; ++i) { 00454 (*array)[i] = get(offset + i); 00455 } 00456 return true; 00457 } 00458 00459 /* 00460 * Exports a range of data from this instance into a given C++ array. 00461 * 00462 * @param[in] offset The first index in this array to eport 00463 * @param[in] count The number of elements to export 00464 * @param[out] array The caller should ensure that there are count elements 00465 * allocated in the array. 00466 * @return false if the existing bounds of this array are not consistent 00467 * with the arguments. 00468 */ 00469 bool Export(int offset, int count, T* array) const { 00470 const Json::Value& json = Storage(); 00471 if (offset + count > json.size()) return false; 00472 00473 for (int i = 0; i < count; ++i) { 00474 array[i] = get(offset + i); 00475 } 00476 return true; 00477 } 00478 }; 00479 00480 00481 /* 00482 * Denotes a JsonCppData instance that is a dictionary. 00483 * @ingroup DataLayerJsonCpp 00484 * 00485 * The JsonCppData wraps a shared reference to jsoncpp values. 00486 * Multiple objects may reference the same values. A dictionary 00487 * does not have homogenous value types. Usually you want to use 00488 * an associative array instead. 00489 * 00490 * This class is not thread-safe. 00491 * 00492 * @see JsonCppAssociativeArray 00493 */ 00494 class JsonCppDictionary : public JsonCppData { 00495 public: 00496 explicit JsonCppDictionary(const Json::Value& value); 00497 explicit JsonCppDictionary(Json::Value* value); 00498 00499 int size() const { return Storage().size(); } 00500 00501 bool has(const char* key) const { 00502 return Storage().isMember(key); 00503 } 00504 00505 void remove(const char* key) { 00506 MutableStorage()->removeMember(key); 00507 } 00508 00509 // NOTE(ewiseblatt): 20120827 00510 // The data value here is mutable. Currently there isnt a way to have 00511 // just const values in a dictionary. 00512 void put_value(const char* key, const Json::Value& data) { 00513 *MutableStorage(key) = data; 00514 } 00515 00516 void put_object(const char* key, const JsonCppData& value) { 00517 *MutableStorage(key) = value.Storage(); 00518 } 00519 00520 const Json::Value& as_value(const char* key) const { return Storage(key); } 00521 const JsonCppData as_object(const char* key) const { 00522 return JsonCppData(Storage(key)); 00523 } 00524 00525 JsonCppData mutable_object(const char* key) { 00526 return JsonCppData(MutableStorage(key)); 00527 } 00528 }; 00529 00530 /* 00531 * Denotes an associative array from string to values of type <code>T</code>. 00532 * @ingroup DataLayerJsonCpp 00533 * 00534 * This class is not thread-safe. 00535 */ 00536 template<typename T> 00537 class JsonCppAssociativeArray : public JsonCppDictionary { 00538 public: 00539 typedef JsonCppConstAssociativeIterator<T> const_iterator; 00540 00541 explicit JsonCppAssociativeArray(const Json::Value& value) 00542 : JsonCppDictionary(value) { 00543 } 00544 00545 explicit JsonCppAssociativeArray(Json::Value* value) 00546 : JsonCppDictionary(value) { 00547 } 00548 00549 bool get(const char* key, T* value) const { 00550 CHECK_NOTNULL(value); 00551 Json::Value v = Storage().get(key, Json::Value::null); 00552 if (v == Json::Value::null) { 00553 ClearCppValueHelper(value); 00554 return false; 00555 } 00556 SetCppValueFromJsonValueHelper(v, value); 00557 return true; 00558 } 00559 00560 void put(const char* key, const T& value) { 00561 SetJsonValueFromCppValueHelper(value, MutableStorage(key)); 00562 } 00563 00564 const_iterator begin() const { return const_iterator(Storage().begin()); } 00565 const_iterator end() const { return const_iterator(Storage().end()); } 00566 }; 00567 00568 00569 /* 00570 * Helper class for constructing new top-level JsonCppData instances. 00571 * @ingroup DataLayerJsonCpp 00572 * 00573 * The base JsonCppData class requires storage managed externally. When 00574 * creating new top-level instances you do not necessarily have a Json::Value 00575 * instance already nor do you want to worry about managing one. 00576 * 00577 * This capsule creates a specialization of any standard class derived from 00578 * JsonCppData that provides its own storage for a default constructor.It is 00579 * only inteded for actually instantiating new instances. When passing them 00580 * around, the BASE class should be used in the interfaces. 00581 */ 00582 template<typename BASE> 00583 class JsonCppCapsule : public BASE { 00584 public: 00585 /* 00586 * Default constructor 00587 */ 00588 JsonCppCapsule() : BASE(&storage_) {} 00589 00590 /* 00591 * Standard destructor 00592 */ 00593 virtual ~JsonCppCapsule() {} 00594 00595 private: 00596 Json::Value storage_; 00597 DISALLOW_COPY_AND_ASSIGN(JsonCppCapsule); 00598 }; 00599 00600 /* 00601 * A helper class for index or key-based iterators. 00602 * 00603 * It just delegates to the base JsonCpp iterator. 00604 * 00605 * Note that because the data model is call-by-value-result theiterator can 00606 * only return copies and not references. Therefore we'll not be able to 00607 * modify values in place (i.e. this will not support a non-const iterator) 00608 */ 00609 template<typename DATA, typename ITERATOR> 00610 class JsonCppAbstractIterator { 00611 public: 00612 typedef typename ITERATOR::size_t size_t; 00613 typedef JsonCppAbstractIterator<DATA, ITERATOR> SelfType; 00614 00615 explicit JsonCppAbstractIterator(const SelfType& copy) : it_(copy.it_) {} 00616 ~JsonCppAbstractIterator() {} 00617 00618 SelfType& operator=(const JsonCppAbstractIterator& copy) { 00619 it_ = copy.it_; 00620 return *this; 00621 } 00622 SelfType& operator++() { 00623 ++it_; 00624 return *this; 00625 } 00626 bool operator==(const SelfType& it) const { 00627 return it_ == it.it_; 00628 } 00629 bool operator!=(const SelfType& it) const { 00630 return it_ != it.it_; 00631 } 00632 00633 protected: 00634 explicit JsonCppAbstractIterator(const ITERATOR& it) : it_(it) {} 00635 ITERATOR it_; 00636 }; 00637 00638 /* 00639 * Iterator for index-based JsonCppDataArray. 00640 * @ingroup DataLayerJsonCpp 00641 * 00642 * Provides access to the index in the array which might be helpful for 00643 * making modifications directly into the array if needed, 00644 * since we cannot support non-const iterators. 00645 */ 00646 template<typename T> 00647 class JsonCppConstIndexIterator 00648 : public JsonCppAbstractIterator<T, Json::Value::const_iterator> { 00649 public: 00650 typedef JsonCppConstIndexIterator<T> SelfType; 00651 typedef T reference; // Note we're using copy-by-value references 00652 00653 JsonCppConstIndexIterator(const JsonCppConstIndexIterator<T>& copy) 00654 : JsonCppAbstractIterator<T, Json::Value::const_iterator>(copy) {} 00655 ~JsonCppConstIndexIterator() {} 00656 00657 reference operator*() const { 00658 return JsonValueToCppValueHelper<T>( 00659 *JsonCppAbstractIterator<T, Json::Value::const_iterator>::it_); 00660 } 00661 int index() const { 00662 return JsonCppAbstractIterator< 00663 T, Json::Value::const_iterator>::it_.index(); } 00664 00665 private: 00666 friend class JsonCppArray<T>; 00667 explicit JsonCppConstIndexIterator(const Json::Value::const_iterator& it) 00668 : JsonCppAbstractIterator<T, Json::Value::const_iterator>(it) {} 00669 }; 00670 00671 /* 00672 * Iterator for JsonCppDataAssociativeArray. 00673 * @ingroup DataLayerJsonCpp 00674 */ 00675 template<typename T> 00676 class JsonCppConstAssociativeIterator 00677 : public JsonCppAbstractIterator<pair<const string, T>, 00678 Json::Value::const_iterator> { 00679 public: 00680 typedef JsonCppConstAssociativeIterator<T> SelfType; 00681 typedef pair<const string, T> reference; 00682 typedef JsonCppAbstractIterator<pair<const string, T>, 00683 Json::Value::const_iterator> SuperClass; 00684 00685 JsonCppConstAssociativeIterator( 00686 const JsonCppConstAssociativeIterator<T>& copy) : SuperClass(copy) { 00687 } 00688 ~JsonCppConstAssociativeIterator() {} 00689 00690 // If you only care about one part of the pair, consider key() or value(). 00691 reference operator*() const { 00692 return make_pair(key(), value()); 00693 } 00694 00695 // This returns a copy of the string, not a reference to the string. 00696 // Unfortunately this is an implementation detail caused by limitations 00697 // of the underlying data model. 00698 const string key() const { 00699 // The iterator retuns a local object so the CString/string values 00700 // disappear ones it leaves scope, forcing us to have to return a copy. 00701 const Json::Value& temp = SuperClass::it_.key(); 00702 return temp.asString(); 00703 } 00704 00705 T value() const { return JsonValueToCppValueHelper<T>(*SuperClass::it_); } 00706 00707 private: 00708 friend class JsonCppAssociativeArray<T>; 00709 explicit JsonCppConstAssociativeIterator( 00710 const Json::Value::const_iterator& it) : SuperClass(it) { 00711 } 00712 }; 00713 00714 } // namespace client 00715 00716 } // namespace googleapis 00717 #endif // APISERVING_CLIENTS_CPP_DATA_JSONCPP_DATA_H_