1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #ifndef avro_Node_hh__
20 #define avro_Node_hh__
21 
22 #include "Config.hh"
23 
24 #include <cassert>
25 #include <boost/noncopyable.hpp>
26 #include <boost/shared_ptr.hpp>
27 
28 #include "Exception.hh"
29 #include "Types.hh"
30 #include "SchemaResolution.hh"
31 
32 namespace internal_avro {
33 
34 class Node;
35 
36 typedef boost::shared_ptr<Node> NodePtr;
37 
38 class AVRO_DECL Name {
39   std::string ns_;
40   std::string simpleName_;
41 
42  public:
Name()43   Name() {}
44   Name(const std::string& fullname);
Name(const std::string & simpleName,const std::string & ns)45   Name(const std::string& simpleName, const std::string& ns)
46       : ns_(ns), simpleName_(simpleName) {
47     check();
48   }
49 
50   const std::string fullname() const;
ns() const51   const std::string& ns() const { return ns_; }
simpleName() const52   const std::string& simpleName() const { return simpleName_; }
53 
ns(const std::string & n)54   void ns(const std::string& n) { ns_ = n; }
simpleName(const std::string & n)55   void simpleName(const std::string& n) { simpleName_ = n; }
56   void fullname(const std::string& n);
57 
58   bool operator<(const Name& n) const;
59   void check() const;
60   bool operator==(const Name& n) const;
operator !=(const Name & n) const61   bool operator!=(const Name& n) const { return !((*this) == n); }
clear()62   void clear() {
63     ns_.clear();
64     simpleName_.clear();
65   }
operator std::string() const66   operator std::string() const { return fullname(); }
67 };
68 
operator <<(std::ostream & os,const Name & n)69 inline std::ostream& operator<<(std::ostream& os, const Name& n) {
70   return os << n.fullname();
71 }
72 
73 /// Node is the building block for parse trees.  Each node represents an avro
74 /// type.  Compound types have leaf nodes that represent the types they are
75 /// composed of.
76 ///
77 /// The user does not use the Node object directly, they interface with Schema
78 /// objects.
79 ///
80 /// The Node object uses reference-counted pointers.  This is so that schemas
81 /// may be reused in other other schemas, without needing to worry about memory
82 /// deallocation for nodes that are added to multiple schema parse trees.
83 ///
84 /// Node has minimal implementation, serving as an abstract base class for
85 /// different node types.
86 ///
87 
88 class AVRO_DECL Node : private boost::noncopyable {
89  public:
Node(Type type)90   Node(Type type) : type_(type), locked_(false) {}
91 
92   virtual ~Node();
93 
type() const94   Type type() const { return type_; }
95 
lock()96   void lock() { locked_ = true; }
97 
locked() const98   bool locked() const { return locked_; }
99 
100   virtual bool hasName() const = 0;
101 
setName(const Name & name)102   void setName(const Name& name) {
103     checkLock();
104     checkName(name);
105     doSetName(name);
106   }
107   virtual const Name& name() const = 0;
108 
addLeaf(const NodePtr & newLeaf)109   void addLeaf(const NodePtr& newLeaf) {
110     checkLock();
111     doAddLeaf(newLeaf);
112   }
113   virtual size_t leaves() const = 0;
114   virtual const NodePtr& leafAt(int index) const = 0;
115 
addName(const std::string & name)116   void addName(const std::string& name) {
117     checkLock();
118     checkName(name);
119     doAddName(name);
120   }
121   virtual size_t names() const = 0;
122   virtual const std::string& nameAt(int index) const = 0;
123   virtual bool nameIndex(const std::string& name, size_t& index) const = 0;
124 
setFixedSize(int size)125   void setFixedSize(int size) {
126     checkLock();
127     doSetFixedSize(size);
128   }
129   virtual int fixedSize() const = 0;
130 
131   virtual bool isValid() const = 0;
132 
133   virtual SchemaResolution resolve(const Node& reader) const = 0;
134 
135   virtual void printJson(std::ostream& os, int depth) const = 0;
136 
137   virtual void printBasicInfo(std::ostream& os) const = 0;
138 
139   virtual void setLeafToSymbolic(int index, const NodePtr& node) = 0;
140 
141  protected:
checkLock() const142   void checkLock() const {
143     if (locked()) {
144       throw Exception("Cannot modify locked schema");
145     }
146   }
147 
checkName(const Name & name) const148   virtual void checkName(const Name& name) const { name.check(); }
149 
150   virtual void doSetName(const Name& name) = 0;
151   virtual void doAddLeaf(const NodePtr& newLeaf) = 0;
152   virtual void doAddName(const std::string& name) = 0;
153   virtual void doSetFixedSize(int size) = 0;
154 
155  private:
156   const Type type_;
157   bool locked_;
158 };
159 
160 }  // namespace internal_avro
161 
162 namespace std {
operator <<(std::ostream & os,const internal_avro::Node & n)163 inline std::ostream& operator<<(std::ostream& os,
164                                 const internal_avro::Node& n) {
165   n.printJson(os, 0);
166   return os;
167 }
168 }
169 
170 #endif
171