Ensures normalization on waitfe/fc-xml operations
[anna.git] / include / anna / diameter / codec / Avp.hpp
index 6677b34..2454d4d 100644 (file)
@@ -1,37 +1,9 @@
-// ANNA - Anna is Not Nothingness Anymore
-//
-// (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
-//
-// https://bitbucket.org/testillano/anna
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Authors: eduardo.ramos.testillano@gmail.com
-//          cisco.tierra@gmail.com
+// ANNA - Anna is Not Nothingness Anymore                                                         //
+//                                                                                                //
+// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
+//                                                                                                //
+// See project site at http://redmine.teslayout.com/projects/anna-suite                           //
+// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
 
 
 #ifndef anna_diameter_codec_Avp_hpp
@@ -42,6 +14,7 @@
 #include <anna/config/defines.hpp>
 #include <anna/diameter/defines.hpp>
 #include <anna/diameter/codec/basetypes/basetypes.hpp>
+#include <anna/diameter/codec/functions.hpp>
 #include <anna/diameter/stack/Avp.hpp>
 
 #include <anna/core/RuntimeException.hpp>
@@ -205,7 +178,7 @@ class Avp {
   static Avp * addAvp(avp_container &avps, int &insertionPositionForChilds, AvpId id, Engine *engine) throw();
   static bool removeAvp(avp_container &avps, find_container &finds, AvpId id, int ocurrence, Engine *engine) throw();
   static void fix(avp_container &avps, find_container &finds, int &insertionPositionForChilds, anna::diameter::stack::const_avprule_iterator ruleBegin, anna::diameter::stack::const_avprule_iterator ruleEnd) throw();
-  static bool validLevel(const avp_container &avps, anna::diameter::stack::const_avprule_iterator ruleBegin, anna::diameter::stack::const_avprule_iterator ruleEnd, Engine * engine, const std::string & parentDescription, Message *answer) throw(anna::RuntimeException); // validates mandatory/fixed and cardinality
+  static bool validLevel(const avp_container &avps, anna::diameter::stack::const_avprule_iterator ruleBegin, anna::diameter::stack::const_avprule_iterator ruleEnd, Engine * engine, const anna::diameter::codec::parent_t & parent, Message *answer) throw(anna::RuntimeException); // validates mandatory/fixed and cardinality
   static const Avp* getAvp(const avp_container &avps, find_container &finds, AvpId id, int ocurrence, Engine *engine, anna::Exception::Mode::_v emode) throw(anna::RuntimeException);
   static int countAvp(const avp_container &avps, AvpId id) throw();
   static const Avp* firstAvp(const avp_container &avps, AvpId id) throw();
@@ -247,12 +220,12 @@ class Avp {
   /**
      Validates an Avp regarding dictionary rules like enumerated range, flags coherence, mandatory and fixed types, cardinality qualifiers, etc.
 
-     @param parentDescription Parent description. Internally used for alarms and tracing
+     @param parent Parent description. Internally used for alarms, tracing and Failed-AVP construction
      @param answer Answer could be modified with any validation problem during requests validation
 
      @return Boolean indicating validation result
   */
-  bool valid(const std::string & parentDescription, Message *answer) const throw(anna::RuntimeException);
+  bool valid(const anna::diameter::codec::parent_t & parent, Message *answer) const throw(anna::RuntimeException);
 
   /**
      Decodes buffer provided over class content. If an error ocurred, decoding will stop launching exception (fatal error) or a warning trace (perhaps the achieved
@@ -260,9 +233,10 @@ class Avp {
      depending on validation depth (codec::Engine::ValidationDepth).
 
      @param db Buffer data block processed
+     @param parent Parent description. Internally used for alarms, tracing and Failed-AVP construction
      @param answer Answer built for request decoding/validation
   */
-  void decode(const anna::DataBlock &db, Message *answer) throw(anna::RuntimeException);
+  void decode(const anna::DataBlock &db, const anna::diameter::codec::parent_t & parent, Message *answer) throw(anna::RuntimeException);
 
 
   /////////////////////////////////////////////
@@ -383,45 +357,51 @@ protected:
   */
   std::string getXMLdata(bool & isHex, const anna::diameter::stack::Format *stackFormat) const throw();
 
-  /**
-     Interpret xml data in order to dump over the class content.
-
-     \param avpNode Avp root node
-  */
-  void fromXML(const anna::xml::Node* avpNode) throw(anna::RuntimeException);
-
-
-  /**
-     Encodes buffer with the class content.
-
-  * @param buffer Raw data to be encoded
-  * @param size Size of raw data to be encoded
-  */
-  void code(char* buffer, int &size) const throw(anna::RuntimeException);
-
 
   /**
      Decodes Avp data part.
 
      @param buffer Avp data part start pointer
      @param size Avp data part size
+     @param parent Parent description. Internally used for alarms, tracing and Failed-AVP construction
      @param answer Answer built for request decoding/validation
   */
-  void decodeDataPart(const char * buffer, int size, Message *answer) throw(anna::RuntimeException);
+  void decodeDataPart(const char * buffer, int size, const anna::diameter::codec::parent_t & parent, Message *answer) throw(anna::RuntimeException);
 
 
 public:
 
   /**
   * Default constructor
+  * @param engine Codec engine used
   */
-  Avp();
+  Avp(Engine *engine = NULL);
 
   /**
   * Identified constructor
   * @param id Avp identifier as pair (code,vendor-id).
+  * @param engine Codec engine used
   */
-  Avp(AvpId id);
+  Avp(AvpId id, Engine *engine = NULL);
+
+
+  /**
+  * Sets the codec engine
+  *
+  * Once assigned (here or at constructor), this method SHALL NOT be used anymore.
+  * Also, the associated dictionary SHOULD NOT BE CHANGED through the engine,
+  * unless you know what are you doing. If you want to reconfigure the engine,
+  * first #clear the avp and then you could reuse the same object with
+  * different configurations (execution contexts).
+  *
+  * Setting a new different engine with different stack, even same engine where the
+  * stack has been dynamically changed, could cause a bad behaviour depending on the
+  * changes: in general, if the dictionary grows, nothing bad will happen, but if
+  * you remove or modified some elements which were processed with a certain format,
+  * will be interpreted as 'unknown' with the new dictionary, and then some problems
+  * may occur. If you add elements (vendors, avps, messages) is not a problem.
+  */
+  void setEngine(Engine *engine) throw();
 
 
   // Length references
@@ -445,7 +425,7 @@ public:
   /**
   * Destructor
   */
-  ~Avp();
+  virtual ~Avp();
 
 
   // setters
@@ -497,7 +477,7 @@ public:
 
   /**
      Adds an avp child providing its identifier and reserve internal memory it.
-     An exception is launched is the Avp is not a grouped avp.
+     An exception is launched is the Avp over which we add the new avp, is not a grouped avp.
 
      @param id Avp identifier as pair (code,vendor-id).
 
@@ -511,16 +491,19 @@ public:
   */
   Avp * addAvp(const char *name) throw(anna::RuntimeException);
 
-
   /**
      Adds an avp child providing a persistent pointer (must be maintained by application).
-     An exception is launched is the Avp is not a grouped avp.
+     An exception is launched is the Avp over which we add the new avp, is not a grouped avp.
+     It is not allowed to add an avp with no codec engine configured, neither if the engine
+     is not the same.
 
      @param avp Avp external pointer. If NULL provided, nothing is done and NULL returned.
+     Also NULL returned for bad engine configuration.
 
      @return Pointer to the added avp (again).
   */
-  Avp * addAvp(Avp * avp) throw(anna::RuntimeException) { if(!avp) return NULL; addChild(avp); return avp; }
+  Avp * addAvp(Avp * avp) throw(anna::RuntimeException);
+
 
   // Data part access
   /** Access content for OctetString Avp in order to set data part */
@@ -687,6 +670,37 @@ public:
   const Unknown *            getUnknown() const throw(anna::RuntimeException) { assertFormat("Unknown"); return a_Unknown; }
 
 
+  /**
+     Decodes buffer provided over class content. If an error ocurred, decoding will stop launching exception (fatal error) or a warning trace (perhaps the achieved
+     avp is valid against all odds then validation will go on). In case that validation is enabled (codec::Engine::ValidationMode) an exception will be launched
+     depending on validation depth (codec::Engine::ValidationDepth).
+
+     Useful as serialization procedure with #code
+
+     @param db Buffer data block processed
+  */
+  void decode(const anna::DataBlock &db) throw(anna::RuntimeException);
+
+
+  /**
+     Interpret xml data in order to dump over the class content.
+
+     \param avpNode Avp root node
+  */
+  void fromXML(const anna::xml::Node* avpNode) throw(anna::RuntimeException);
+
+
+  /**
+    Encodes buffer with the class content. This method is internally used to encode diameter messages, but is declared as public, to allow
+    its use as serialization procedure. Then, it's assumed that this Avp is valid (validation shall be applied as part of a whole diameter
+    message but nothing will be verified now).
+
+  * @param buffer Raw data to be encoded (shall be externally allocated)
+  * @param size Size of raw data to be encoded
+  */
+  void code(char* buffer, int &size) const throw(anna::RuntimeException);
+
+
   // Helpers
 
   /**
@@ -698,9 +712,32 @@ public:
 
   /**
      Class xml string representation
+     @param normalize Optional normalization which sorts attribute names and removes
+     newlines in the xml representation in order to ease regexp matching.
+
      \return XML string representation with relevant information for this instance.
   */
-  std::string asXMLString() const throw();
+  std::string asXMLString(bool normalize = false) const throw();
+
+  /**
+     Comparison operator by mean serialization
+
+     @param a1 Instance 1 for Avp class
+     @param a2 Instance 2 for Avp class
+
+     @return Comparison result
+  */
+  friend bool operator == (const Avp & a1, const Avp & a2) throw() { return (a1.asXMLString() == a2.asXMLString()); }
+
+  /**
+     Match a regular expression (string pattern) regarding xml string serialization for this avp.
+     This works same as #Message::isLike
+
+     @param pattern Pattern to match
+
+     \return Returns the match result
+  */
+  bool isLike(const std::string &pattern) const throw();
 
   /**
      Counts the number of ocurrences of Avps (first level) with the identifier provided
@@ -727,12 +764,10 @@ public:
      Diameter Relay and redirect agents MUST NOT reject messages with unrecognized AVPs.
 
      Default implementation launch alarm and counter indicating the anomaly but don't launch exception (traces at warning level).
-     Realy and Redirect agents could reimplement this method to avoid oam management (another way is avoid alarm/counter registration on
+     Relay and Redirect agents could reimplement this method to avoid oam management (another way is avoid alarm/counter registration on
      these applications). Result-Code DIAMETER_AVP_UNSUPPORTED will be stored for possible answer message.
-
-     @param answer Answer built for request decoding/validation
   */
-  virtual void unknownAvpWithMandatoryBit(Message *answer) const throw(anna::RuntimeException);
+  virtual void unknownAvpWithMandatoryBit() const throw(anna::RuntimeException);
 
 
   friend class Message;