00001
00019 #ifndef avro_NodeImpl_hh__
00020 #define avro_NodeImpl_hh__
00021
00022 #include <limits>
00023 #include <boost/weak_ptr.hpp>
00024
00025 #include "Node.hh"
00026 #include "NodeConcepts.hh"
00027
00028 namespace avro {
00029
00032
00033 template
00034 <
00035 class NameConcept,
00036 class LeavesConcept,
00037 class LeafNamesConcept,
00038 class SizeConcept
00039 >
00040 class NodeImpl : public Node
00041 {
00042
00043 protected:
00044
00045 NodeImpl(Type type) :
00046 Node(type),
00047 nameAttribute_(),
00048 leafAttributes_(),
00049 leafNameAttributes_(),
00050 sizeAttribute_()
00051 { }
00052
00053 NodeImpl(Type type,
00054 const NameConcept &name,
00055 const LeavesConcept &leaves,
00056 const LeafNamesConcept &leafNames,
00057 const SizeConcept &size) :
00058 Node(type),
00059 nameAttribute_(name),
00060 leafAttributes_(leaves),
00061 leafNameAttributes_(leafNames),
00062 sizeAttribute_(size)
00063 { }
00064
00065 bool hasName() const {
00066 return NameConcept::hasAttribute;
00067 }
00068
00069 void doSetName(const std::string &name) {
00070 nameAttribute_.add(name);
00071 }
00072
00073 const std::string &name() const {
00074 return nameAttribute_.get();
00075 }
00076
00077 void doAddLeaf(const NodePtr &newLeaf) {
00078 leafAttributes_.add(newLeaf);
00079 }
00080
00081 size_t leaves() const {
00082 return leafAttributes_.size();
00083 }
00084
00085 const NodePtr &leafAt(int index) const {
00086 return leafAttributes_.get(index);
00087 }
00088
00089 void doAddName(const std::string &name) {
00090 if(! nameIndex_.add(name, leafNameAttributes_.size())) {
00091 throw Exception(boost::format("Cannot add duplicate name: %1%") % name);
00092 }
00093 leafNameAttributes_.add(name);
00094 }
00095
00096 size_t names() const {
00097 return leafNameAttributes_.size();
00098 }
00099
00100 const std::string &nameAt(int index) const {
00101 return leafNameAttributes_.get(index);
00102 }
00103
00104 bool nameIndex(const std::string &name, size_t &index) const {
00105 return nameIndex_.lookup(name, index);
00106 }
00107
00108 void doSetFixedSize(int size) {
00109 sizeAttribute_.add(size);
00110 }
00111
00112 int fixedSize() const {
00113 return sizeAttribute_.get();
00114 }
00115
00116 virtual bool isValid() const = 0;
00117
00118 void printBasicInfo(std::ostream &os) const;
00119
00120 void setLeafToSymbolic(int index, const NodePtr &node);
00121
00122 SchemaResolution furtherResolution(const Node &node) const;
00123
00124 NameConcept nameAttribute_;
00125 LeavesConcept leafAttributes_;
00126 LeafNamesConcept leafNameAttributes_;
00127 SizeConcept sizeAttribute_;
00128 concepts::NameIndexConcept<LeafNamesConcept> nameIndex_;
00129 };
00130
00131 typedef concepts::NoAttribute<std::string> NoName;
00132 typedef concepts::SingleAttribute<std::string> HasName;
00133
00134 typedef concepts::NoAttribute<NodePtr> NoLeaves;
00135 typedef concepts::SingleAttribute<NodePtr> SingleLeaf;
00136 typedef concepts::MultiAttribute<NodePtr> MultiLeaves;
00137
00138 typedef concepts::NoAttribute<std::string> NoLeafNames;
00139 typedef concepts::MultiAttribute<std::string> LeafNames;
00140
00141 typedef concepts::NoAttribute<int> NoSize;
00142 typedef concepts::SingleAttribute<int> HasSize;
00143
00144 typedef NodeImpl< NoName, NoLeaves, NoLeafNames, NoSize > NodeImplPrimitive;
00145 typedef NodeImpl< HasName, NoLeaves, NoLeafNames, NoSize > NodeImplSymbolic;
00146
00147 typedef NodeImpl< HasName, MultiLeaves, LeafNames, NoSize > NodeImplRecord;
00148 typedef NodeImpl< HasName, NoLeaves, LeafNames, NoSize > NodeImplEnum;
00149 typedef NodeImpl< NoName, SingleLeaf, NoLeafNames, NoSize > NodeImplArray;
00150 typedef NodeImpl< NoName, MultiLeaves, NoLeafNames, NoSize > NodeImplMap;
00151 typedef NodeImpl< NoName, MultiLeaves, NoLeafNames, NoSize > NodeImplUnion;
00152 typedef NodeImpl< HasName, NoLeaves, NoLeafNames, HasSize > NodeImplFixed;
00153
00154 class NodePrimitive : public NodeImplPrimitive
00155 {
00156 public:
00157
00158 explicit NodePrimitive(Type type) :
00159 NodeImplPrimitive(type)
00160 { }
00161
00162 SchemaResolution resolve(const Node &reader) const;
00163
00164 void printJson(std::ostream &os, int depth) const;
00165
00166 bool isValid() const {
00167 return true;
00168 }
00169 };
00170
00171 class NodeSymbolic : public NodeImplSymbolic
00172 {
00173 typedef boost::weak_ptr<Node> NodeWeakPtr;
00174
00175 public:
00176
00177 NodeSymbolic() :
00178 NodeImplSymbolic(AVRO_SYMBOLIC)
00179 { }
00180
00181 explicit NodeSymbolic(const HasName &name) :
00182 NodeImplSymbolic(AVRO_SYMBOLIC, name, NoLeaves(), NoLeafNames(), NoSize())
00183 { }
00184
00185 SchemaResolution resolve(const Node &reader) const;
00186
00187 void printJson(std::ostream &os, int depth) const;
00188
00189 bool isValid() const {
00190 return (nameAttribute_.size() == 1);
00191 }
00192
00193 bool isSet() const {
00194 return (actualNode_.lock() != 0);
00195 }
00196
00197 NodePtr getNode() const {
00198 NodePtr node = actualNode_.lock();
00199 if(!node) {
00200 throw Exception(boost::format("Could not follow symbol %1%") % name());
00201 }
00202 return node;
00203 }
00204
00205 void setNode(const NodePtr &node) {
00206 actualNode_ = node;
00207 }
00208
00209 protected:
00210
00211 NodeWeakPtr actualNode_;
00212
00213 };
00214
00215 class NodeRecord : public NodeImplRecord
00216 {
00217 public:
00218
00219 NodeRecord() :
00220 NodeImplRecord(AVRO_RECORD)
00221 { }
00222
00223 NodeRecord(const HasName &name, const MultiLeaves &fields, const LeafNames &fieldsNames) :
00224 NodeImplRecord(AVRO_RECORD, name, fields, fieldsNames, NoSize())
00225 {
00226 for(size_t i=0; i < leafNameAttributes_.size(); ++i) {
00227 if(!nameIndex_.add(leafNameAttributes_.get(i), i)) {
00228 throw Exception(boost::format("Cannot add duplicate name: %1%") % leafNameAttributes_.get(i));
00229 }
00230 }
00231 }
00232
00233 SchemaResolution resolve(const Node &reader) const;
00234
00235 void printJson(std::ostream &os, int depth) const;
00236
00237 bool isValid() const {
00238 return (
00239 (nameAttribute_.size() == 1) &&
00240 (leafAttributes_.size() > 0) &&
00241 (leafAttributes_.size() == leafNameAttributes_.size())
00242 );
00243 }
00244 };
00245
00246 class NodeEnum : public NodeImplEnum
00247 {
00248 public:
00249
00250 NodeEnum() :
00251 NodeImplEnum(AVRO_ENUM)
00252 { }
00253
00254 NodeEnum(const HasName &name, const LeafNames &symbols) :
00255 NodeImplEnum(AVRO_ENUM, name, NoLeaves(), symbols, NoSize())
00256 {
00257 for(size_t i=0; i < leafNameAttributes_.size(); ++i) {
00258 if(!nameIndex_.add(leafNameAttributes_.get(i), i)) {
00259 throw Exception(boost::format("Cannot add duplicate name: %1%") % leafNameAttributes_.get(i));
00260 }
00261 }
00262 }
00263
00264 SchemaResolution resolve(const Node &reader) const;
00265
00266 void printJson(std::ostream &os, int depth) const;
00267
00268 bool isValid() const {
00269 return (
00270 (nameAttribute_.size() == 1) &&
00271 (leafNameAttributes_.size() > 0)
00272 );
00273 }
00274 };
00275
00276 class NodeArray : public NodeImplArray
00277 {
00278 public:
00279
00280 NodeArray() :
00281 NodeImplArray(AVRO_ARRAY)
00282 { }
00283
00284 explicit NodeArray(const SingleLeaf &items) :
00285 NodeImplArray(AVRO_ARRAY, NoName(), items, NoLeafNames(), NoSize())
00286 { }
00287
00288 SchemaResolution resolve(const Node &reader) const;
00289
00290 void printJson(std::ostream &os, int depth) const;
00291
00292 bool isValid() const {
00293 return (leafAttributes_.size() == 1);
00294 }
00295 };
00296
00297 class NodeMap : public NodeImplMap
00298 {
00299 public:
00300
00301 NodeMap() :
00302 NodeImplMap(AVRO_MAP)
00303 {
00304 NodePtr key(new NodePrimitive(AVRO_STRING));
00305 doAddLeaf(key);
00306 }
00307
00308 explicit NodeMap(const SingleLeaf &values) :
00309 NodeImplMap(AVRO_MAP, NoName(), values, NoLeafNames(), NoSize())
00310 {
00311
00312 NodePtr key(new NodePrimitive(AVRO_STRING));
00313 doAddLeaf(key);
00314
00315
00316 std::swap(leafAttributes_.get(0), leafAttributes_.get(1));
00317 }
00318
00319 SchemaResolution resolve(const Node &reader) const;
00320
00321 void printJson(std::ostream &os, int depth) const;
00322
00323 bool isValid() const {
00324 return (leafAttributes_.size() == 2);
00325 }
00326 };
00327
00328 class NodeUnion : public NodeImplUnion
00329 {
00330 public:
00331
00332 NodeUnion() :
00333 NodeImplUnion(AVRO_UNION)
00334 { }
00335
00336 explicit NodeUnion(const MultiLeaves &types) :
00337 NodeImplUnion(AVRO_UNION, NoName(), types, NoLeafNames(), NoSize())
00338 { }
00339
00340 SchemaResolution resolve(const Node &reader) const;
00341
00342 void printJson(std::ostream &os, int depth) const;
00343
00344 bool isValid() const {
00345 return (leafAttributes_.size() > 1);
00346 }
00347 };
00348
00349 class NodeFixed : public NodeImplFixed
00350 {
00351 public:
00352
00353 NodeFixed() :
00354 NodeImplFixed(AVRO_FIXED)
00355 { }
00356
00357 NodeFixed(const HasName &name, const HasSize &size) :
00358 NodeImplFixed(AVRO_FIXED, name, NoLeaves(), NoLeafNames(), size)
00359 { }
00360
00361 SchemaResolution resolve(const Node &reader) const;
00362
00363 void printJson(std::ostream &os, int depth) const;
00364
00365 bool isValid() const {
00366 return (
00367 (nameAttribute_.size() == 1) &&
00368 (sizeAttribute_.size() == 1)
00369 );
00370 }
00371 };
00372
00373 template < class A, class B, class C, class D >
00374 inline void
00375 NodeImpl<A,B,C,D>::setLeafToSymbolic(int index, const NodePtr &node)
00376 {
00377 if(!B::hasAttribute) {
00378 throw Exception("Cannot change leaf node for nonexistent leaf");
00379 }
00380
00381 NodePtr &replaceNode = const_cast<NodePtr &>(leafAttributes_.get(index));
00382 if(replaceNode->name() != node->name()) {
00383 throw Exception("Symbolic name does not match the name of the schema it references");
00384 }
00385
00386 NodePtr symbol(new NodeSymbolic);
00387 NodeSymbolic *ptr = static_cast<NodeSymbolic *> (symbol.get());
00388
00389 ptr->setName(node->name());
00390 ptr->setNode(node);
00391 replaceNode.swap(symbol);
00392 }
00393
00394 template < class A, class B, class C, class D >
00395 inline void
00396 NodeImpl<A,B,C,D>::printBasicInfo(std::ostream &os) const
00397 {
00398 os << type();
00399 if(hasName()) {
00400 os << " " << nameAttribute_.get();
00401 }
00402 if(D::hasAttribute) {
00403 os << " " << sizeAttribute_.get();
00404 }
00405 os << '\n';
00406 int count = leaves();
00407 count = count ? count : names();
00408 for(int i= 0; i < count; ++i) {
00409 if( C::hasAttribute ) {
00410 os << "name " << nameAt(i) << '\n';
00411 }
00412 if( type() != AVRO_SYMBOLIC && leafAttributes_.hasAttribute) {
00413 leafAt(i)->printBasicInfo(os);
00414 }
00415 }
00416 if(isCompound(type())) {
00417 os << "end " << type() << '\n';
00418 }
00419 }
00420
00421
00422 inline NodePtr resolveSymbol(const NodePtr &node)
00423 {
00424 if(node->type() != AVRO_SYMBOLIC) {
00425 throw Exception("Only symbolic nodes may be resolved");
00426 }
00427 boost::shared_ptr<NodeSymbolic> symNode = boost::static_pointer_cast<NodeSymbolic>(node);
00428 return symNode->getNode();
00429 }
00430
00431 }
00432
00433 #endif