All types can be used to set attributes at create time
(SaAnyT and SaNameT added)
Help functions for converting SaAnyT and SaNameT to string is added
See SaAnytToString() and SaNametToString() in immccb.h
---
 src/smf/smfd/imm_modify_config/attribute.cc     | 107 +++++++++++--
 src/smf/smfd/imm_modify_config/attribute.h      |  72 +++++++--
 src/smf/smfd/imm_modify_config/creator.cc       |   2 +-
 src/smf/smfd/imm_modify_config/immccb.cc        |  24 +--
 src/smf/smfd/imm_modify_config/immccb.h         |  59 ++++++-
 src/smf/smfd/imm_modify_demo/ccbdemo1.cc        | 195 ++++++++++++++++++++++--
 src/smf/smfd/imm_modify_demo/democlass.xml      |  16 ++
 src/smf/smfd/imm_om_api/common/imm_attribute.cc |   9 +-
 8 files changed, 427 insertions(+), 57 deletions(-)

diff --git a/src/smf/smfd/imm_modify_config/attribute.cc 
b/src/smf/smfd/imm_modify_config/attribute.cc
index 93bd6f520..28dc6b76f 100644
--- a/src/smf/smfd/imm_modify_config/attribute.cc
+++ b/src/smf/smfd/imm_modify_config/attribute.cc
@@ -17,11 +17,6 @@
  */
 #include "attribute.h"
 
-#if 1 // TODO(Lennart) Remove
-#include <stdio.h>
-#include <iostream>
-#endif
-
 #include <limits.h>
 
 #include <string>
@@ -104,7 +99,8 @@ static bool StringToNumericValue(const std::string& 
str_value,
   return rc;
 }
 
-bool AttributeHandler::AddAttributes(const CreateDescriptor& 
create_descriptor) {
+bool AttributeHandler::AddAttributes(const CreateDescriptor&
+                                     create_descriptor) {
   bool rc = true;
   for (auto& attribute_descriptor : create_descriptor.attributes) {
     rc = AddAttribute(attribute_descriptor);
@@ -134,7 +130,7 @@ bool AttributeHandler::AddAttribute(const 
AttributeDescriptor& attribute) {
     case SA_IMM_ATTR_SAUINT64T:
       rc = StoreNumericAttribute<SaUint64T>(attribute);
       break;
-      
+
     case SA_IMM_ATTR_SATIMET:
       rc = StoreNumericAttribute<CppSaTimeT>(attribute);
       // rc = StoreTimeTAttribute(attribute);
@@ -157,6 +153,15 @@ bool AttributeHandler::AddAttribute(const 
AttributeDescriptor& attribute) {
       set_attributesp_.push_back(std::move(CreatorAttribute));
       break;
     }
+
+    case SA_IMM_ATTR_SANAMET:
+      StoreSaNametAttribute(attribute);
+      break;
+
+    case SA_IMM_ATTR_SAANYT:
+      StoreSaAnytAttribute(attribute);
+      break;
+
     default:
       break;
   }
@@ -171,6 +176,13 @@ bool AttributeHandler::AddAttribute(const 
AttributeDescriptor& attribute) {
 // Save the SetAttribute object in a vector so that the object will be in scope
 // until "this" object goes out of scope which shall happen when the creator
 // has given the create operation to IMM
+
+// All Store methods:
+// For an attribute;
+//  - Convert all Values As a String to its real type and save
+//    those values in a temporary vector.
+//  - Create a new SetAttribute object and give it the converted values
+//  - Store the SetAttribute object
 template<typename T>
 bool AttributeHandler::
 StoreNumericAttribute(const AttributeDescriptor& attribute) {
@@ -179,6 +191,7 @@ StoreNumericAttribute(const AttributeDescriptor& attribute) 
{
   T numeric_value{0};
   std::vector<T> num_values;
   for (auto& value_str : attribute.values_as_strings) {
+    // Create a vector containing all values for this attribute
     if (StringToNumericValue<T>
         (value_str, numeric_value, value_type) == false) {
       LOG_NO("LLDTEST %s: StringToNumericValue() Fail", __FUNCTION__);
@@ -188,15 +201,88 @@ StoreNumericAttribute(const AttributeDescriptor& 
attribute) {
     num_values.push_back(numeric_value);
   }
   if (rc == true) {
+    // Store the attribute for the creator and give it to the creator
     std::unique_ptr<SetAttribute> CreatorAttribute =
         std::unique_ptr<SetAttribute>(new SetAttribute(creator_));
-      CreatorAttribute->SetAttributeValues(attribute.attribute_name,
-                                           num_values);
+    CreatorAttribute->SetAttributeValues(attribute.attribute_name, num_values);
     set_attributesp_.push_back(std::move(CreatorAttribute));
   }
   return rc;
 }
 
+void AttributeHandler::
+StoreSaNametAttribute(const AttributeDescriptor& attribute) {
+  SaNameT name_value;
+  std::vector<SaNameT> name_values;
+  for (auto& value_str : attribute.values_as_strings) {
+    StringToSaNameT(value_str, &name_value);
+    name_values.push_back(name_value);
+  }
+
+  std::unique_ptr<SetAttribute> CreatorAttribute =
+      std::unique_ptr<SetAttribute>(new SetAttribute(creator_));
+  CreatorAttribute->SetAttributeValues(attribute.attribute_name, name_values);
+  set_attributesp_.push_back(std::move(CreatorAttribute));
+}
+
+void AttributeHandler::
+StoreSaAnytAttribute(const AttributeDescriptor& attribute) {
+  // Note: For this type it is also needed to store the buffer pointed to
+  //       from the SaAnyT structure
+  SaAnyT any_value;
+  std::vector<SaAnyT> any_values;
+  //static inline void StringToSaAnyT(std::string str_anyt, SaAnyT* anyt_value)
+  for (auto& value_str : attribute.values_as_strings) {
+    StringToSaAnyT(value_str, &any_value);
+    any_values.push_back(any_value);
+  }
+
+  std::unique_ptr<SetAttribute> CreatorAttribute =
+      std::unique_ptr<SetAttribute>(new SetAttribute(creator_));
+  CreatorAttribute->SetAttributeValues(attribute.attribute_name, any_values);
+  set_attributesp_.push_back(std::move(CreatorAttribute));
+}
+
+// All SetAttributeValues methods:
+// For each attribute type;
+//  - Create a Value Store object
+//  - Add the input values to the Value Store object value vector
+//  - Add pointers to the values to the Value Store object value pointer vector
+//  - Give the value pointer vector to a creator of class ImmOmCcbObjectCreate
+//    that is previously created and stored in creator_
+
+// SaAnyT
+void SetAttribute::SetAttributeValues(const std::string& name,
+                          const std::vector<SaAnyT>& any_values) {
+  AnyValueStore_ =
+      std::unique_ptr<AnyValueStore>(new AnyValueStore);
+  for (auto& any_value : any_values) {
+    AnyValueStore_->Values.push_back(any_value);
+  }
+  SaAnyT* v_ptr = AnyValueStore_->Values.data();
+  for (size_t i = 0; i < AnyValueStore_->Values.size(); i++) {
+    AnyValueStore_->Values_p.push_back(v_ptr++);
+  }
+  creator_->SetAttributeValue(name, AnyValueStore_->Values_p);
+}
+
+
+// SaNameT
+void SetAttribute::SetAttributeValues(const std::string& name,
+                          const std::vector<SaNameT>& name_values) {
+  NameValueStore_ =
+      std::unique_ptr<NameValueStore>(new NameValueStore);
+  for (auto& name_value : name_values) {
+    NameValueStore_->Values.push_back(name_value);
+  }
+  SaNameT* v_ptr = NameValueStore_->Values.data();
+  for (size_t i = 0; i < NameValueStore_->Values.size(); i++) {
+    NameValueStore_->Values_p.push_back(v_ptr++);
+  }
+  creator_->SetAttributeValue(name, NameValueStore_->Values_p);
+}
+
+
 // SaUint32T
 void SetAttribute::SetAttributeValues(const std::string& name,
                                 const std::vector<SaUint32T>& num_values) {
@@ -206,7 +292,6 @@ void SetAttribute::SetAttributeValues(const std::string& 
name,
     Uint32ValueStore_->Values.push_back(num_value);
   }
   SaUint32T* v_ptr = Uint32ValueStore_->Values.data();
-  //for (auto& i : Uint32ValueStore_->Values) {
   for (size_t i = 0; i < Uint32ValueStore_->Values.size(); i++) {
     Uint32ValueStore_->Values_p.push_back(v_ptr++);
   }
@@ -305,8 +390,6 @@ void SetAttribute::SetAttributeValues(const std::string& 
name,
   creator_->SetAttributeValue(name, TimeValueStore_->Values_p);
 }
 
-// DODO(Lennart) Also add SaNameT and SaAnyT
-
 void SetAttribute::SetAttributeValues(const std::string& name,
                                 const std::vector<std::string>& str_values) {
   StringValueStore_ =
diff --git a/src/smf/smfd/imm_modify_config/attribute.h 
b/src/smf/smfd/imm_modify_config/attribute.h
index f6411f787..41112d1d6 100644
--- a/src/smf/smfd/imm_modify_config/attribute.h
+++ b/src/smf/smfd/imm_modify_config/attribute.h
@@ -32,18 +32,38 @@
 #ifndef ATTRVAL_HDL_H
 #define ATTRVAL_HDL_H
 
-#if 0 // All the IMM types
-SA_IMM_ATTR_SAINT32T = 1,      /* SaInt32T */
-SA_IMM_ATTR_SAUINT32T = 2,     /* SaUint32T */
-SA_IMM_ATTR_SAINT64T = 3,      /* SaInt64T */
-SA_IMM_ATTR_SAUINT64T = 4,     /* SaUint64T */
-SA_IMM_ATTR_SATIMET = 5,       /* SaTimeT is SaInt64T */
-SA_IMM_ATTR_SANAMET = 6,       /* SaNameT */
-SA_IMM_ATTR_SAFLOATT = 7,      /* SaFloatT */
-SA_IMM_ATTR_SADOUBLET = 8,     /* SaDoubleT */
-SA_IMM_ATTR_SASTRINGT = 9,     /* SaStringT */
-SA_IMM_ATTR_SAANYT = 10         /* SaAnyT */
-#endif
+// TODO(Lennart) Place within namespace modelmodify?
+
+// Convert std::string to SaNameT or SaAnyT.
+// Shall be used with AttributeDescriptor object where SaNametToString or
+// SaAnytToString has been used to convert the data to std::string
+// Note: There are no rules about what content these types may hold so there
+//       is no validation
+static inline void StringToSaNameT(std::string str_namet,
+                                   SaNameT* namet_value) {
+  osaf_extended_name_lend(str_namet.c_str(), namet_value);
+}
+
+// Note: This function allocates memory for a buffer that can hold the data in
+//       the string and writes the address in the SaAnyT buffer pointer.
+//       This means that this memory must be freed after usage using:
+//       free(<my_anyt>.bufferAddr);
+static inline void StringToSaAnyT(std::string str_anyt, SaAnyT* anyt_value) {
+  size_t anyt_size = str_anyt.size();
+  //SaUint8T* anyt_buffer = static_cast<SaUint8T*>(malloc(anyt_size));
+  SaUint8T* anyt_buffer = static_cast<SaUint8T*>(malloc(anyt_size));
+  if (anyt_buffer == nullptr) {
+    LOG_ER("%s: malloc() Fail", __FUNCTION__);
+    osafassert(0);
+  }
+  size_t i = 0;
+  for (auto& char_data : str_anyt) {
+    anyt_buffer[i++] = char_data;
+  }
+  anyt_value->bufferSize = anyt_size;
+  anyt_value->bufferAddr = anyt_buffer;
+}
+
 namespace modelmodify {
 
 // Store values of different types
@@ -84,6 +104,20 @@ struct NameValueStore {
   std::vector<SaNameT*> Values_p;
 };
 struct AnyValueStore {
+  // Note1: For this set of values a buffer that contains the actual value is
+  //        allocated (C allocation is used). A pointer to this buffer can be
+  //        found as a parameter in the SaAnyT. When this storage goes out of
+  //        scope this buffer must be freed
+  // Note2: The StringToSaAnyT() function is used to create a SaAnyT value.
+  //        This is where memory for the buffer is allocated
+  ~AnyValueStore() {
+    if (Values.empty() == false) {
+      for (auto& value : Values) {
+        if (value.bufferAddr != nullptr) free(value.bufferAddr);
+      }
+    }
+  }
+
   std::vector<SaAnyT> Values;
   std::vector<SaAnyT*> Values_p;
 };
@@ -130,6 +164,12 @@ class SetAttribute {
   void SetAttributeValues(const std::string& name,
                           const std::vector<CppSaTimeT>& time_values);
 
+  void SetAttributeValues(const std::string& name,
+                          const std::vector<SaNameT>& name_values);
+
+  void SetAttributeValues(const std::string& name,
+                          const std::vector<SaAnyT>& any_values);
+
  private:
   // Numeric
   std::unique_ptr<Uint32ValueStore> Uint32ValueStore_;
@@ -150,7 +190,7 @@ class SetAttribute {
 
   immom::ImmOmCcbObjectCreate* creator_;
 
-  //DELETE_COPY_AND_MOVE_OPERATORS(Attribute);
+  DELETE_COPY_AND_MOVE_OPERATORS(SetAttribute);
 };
 
 // Adds all attributes in a create descriptor to a creator
@@ -181,12 +221,14 @@ class AttributeHandler {
   template<typename T>
   bool StoreNumericAttribute(const AttributeDescriptor& attribute);
 
-  bool StoreTimeTAttribute(const AttributeDescriptor& attribute);
+  void StoreSaNametAttribute(const AttributeDescriptor& attribute);
+
+  void StoreSaAnytAttribute(const AttributeDescriptor& attribute);
 
   std::vector<std::unique_ptr<SetAttribute>> set_attributesp_;
   immom::ImmOmCcbObjectCreate* creator_;
 
-  //DELETE_COPY_AND_MOVE_OPERATORS(Attribute);
+  DELETE_COPY_AND_MOVE_OPERATORS(AttributeHandler);
 };
 
 } // namespace modelmodify
diff --git a/src/smf/smfd/imm_modify_config/creator.cc 
b/src/smf/smfd/imm_modify_config/creator.cc
index 8be2124f1..975f6002b 100644
--- a/src/smf/smfd/imm_modify_config/creator.cc
+++ b/src/smf/smfd/imm_modify_config/creator.cc
@@ -57,7 +57,7 @@ int AddObjectCreateToCcbf(const SaImmCcbHandleT& ccb_handle,
   TRACE_ENTER2("LLDTEST1: Parent '%s', Class '%s'",
                create_descriptor.parent_name.c_str(),
                create_descriptor.class_name.c_str());
-  std::cout << "ObjectCreateCcbAddf() >>" << std::endl;
+
   int recovery_info = modelmodify::kNotSet;
 
   // Setup a creator with class name and parent name
diff --git a/src/smf/smfd/imm_modify_config/immccb.cc 
b/src/smf/smfd/imm_modify_config/immccb.cc
index b8aa71e9a..5ea897508 100644
--- a/src/smf/smfd/imm_modify_config/immccb.cc
+++ b/src/smf/smfd/imm_modify_config/immccb.cc
@@ -22,6 +22,9 @@
 // in the smfd/imm_om_api directory.
 // TODO(Lennart) This may affect this code if these wrappers are made 
"official"
 // in current or some modified way in the future
+// TODO(Lennart) Some modifications of the IMM wrappers is suggested. If these
+// modifications (mainly handling of data ownership) are implemented the
+// attribute handling code (see attribute.*) can be simplified.
 
 #include "immccb.h"
 
@@ -97,10 +100,10 @@ bool ObjectModification::DoModification(CcbDescriptor 
modifications) {
     // Create all needed handles
     recovery_info = CreateHandles();
     if (recovery_info == kFail) {
-      LOG_NO("LLDTEST %s: CreateAdminOwner() Fail", __FUNCTION__);
+      LOG_NO("LLDTEST %s: CreateHandles() Fail", __FUNCTION__);
       break;
     } else if (recovery_info == kRestartOm) {
-      TRACE("LLDTEST %s: CreateAdminOwner() Restart", __FUNCTION__);
+      TRACE("LLDTEST %s: CreateHandles() Restart", __FUNCTION__);
       continue;
     }
 
@@ -152,7 +155,7 @@ int ObjectModification::CreateHandles() {
   TRACE_ENTER2("LLDTEST");
   int recovery_info = kNotSet;
 
-  // The Object Manager handle is created
+  // Create Object Manager handle
   recovery_info = CreateObjectManager();
   if (recovery_info == kFail) {
     LOG_NO("LLDTEST %s: CreateOmHandle() Fail", __FUNCTION__);
@@ -160,6 +163,7 @@ int ObjectModification::CreateHandles() {
 
   // The Admin Owner handle is created and an admin owner name is
   // registered. Uses Object Manager handle
+  // Note: Admin Owner Set is not done here
   if (recovery_info == kContinue) {
     recovery_info = CreateAdminOwner();
     if (recovery_info == kFail) {
@@ -226,7 +230,6 @@ int ObjectModification::CreateObjectManager() {
 //          instance of this class. See private variables
 // Output:  A valid Admin Owner (AO) handle. An admin owner handle object and
 //          an Admin Owner Set object is created
-//          created
 // Return:  Recovery information. See Private constants
 int ObjectModification::CreateAdminOwner() {
   TRACE_ENTER2("LLDTEST");
@@ -241,10 +244,12 @@ int ObjectModification::CreateAdminOwner() {
   if (rc == false) {
     SaAisErrorT ais_rc = imm_ao_handle_->ais_error();
     if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
-      TRACE("LLDTEST %s: Admin Owner handle, InitializeHandle() Restart", 
__FUNCTION__);
+      TRACE("LLDTEST %s: Admin Owner handle, InitializeHandle() Restart",
+            __FUNCTION__);
       recovery_info = kRestartOm;
     } else {
-      LOG_NO("LLDTEST %s: Admin Owner handle, InitializeHandle() Fail", 
__FUNCTION__);
+      LOG_NO("LLDTEST %s: Admin Owner handle, InitializeHandle() Fail",
+             __FUNCTION__);
       recovery_info = kFail;
     }
   } else {
@@ -535,8 +540,8 @@ int ObjectModification::AddCreate(CreateDescriptor& 
create_descriptor) {
 }
 
 // Apply the CCB. Based on a valid CCB handle
-// Recovery:  BAD HANDLE; Start from Restart OM
-//            FAILED OPERATION; Start from (1.)
+// Recovery:  BAD HANDLE; Restart CCBhandling
+//            FAILED OPERATION; Restart CCBhandling
 int ObjectModification::ApplyModifications() {
   TRACE_ENTER2("LLDTEST");
   int recovery_info = kNotSet;
@@ -545,7 +550,8 @@ int ObjectModification::ApplyModifications() {
     SaAisErrorT ais_rc = imm_ccb_handle_->ais_error();
     if ((ais_rc == SA_AIS_ERR_BAD_HANDLE) ||
         (ais_rc == SA_AIS_ERR_FAILED_OPERATION)) {
-      TRACE("LLDTEST %s: ApplyCcb() Restart %s", __FUNCTION__, 
saf_error(ais_rc));
+      TRACE("LLDTEST %s: ApplyCcb() Restart %s", __FUNCTION__,
+            saf_error(ais_rc));
       recovery_info = kRestartOm;
     } else {
       LOG_ER("LLDTEST %s: ApplyCcb() Fail", __FUNCTION__);
diff --git a/src/smf/smfd/imm_modify_config/immccb.h 
b/src/smf/smfd/imm_modify_config/immccb.h
index 5604568ab..f7ffbc3d8 100644
--- a/src/smf/smfd/imm_modify_config/immccb.h
+++ b/src/smf/smfd/imm_modify_config/immccb.h
@@ -28,6 +28,7 @@
 
 #include "ais/include/saImm.h"
 #include "ais/include/saAis.h"
+#include "base/osaf_extended_name.h"
 
 #include "smf/smfd/imm_om_api/common/common.h"
 #include "smf/smfd/imm_om_api/om_handle.h"
@@ -63,7 +64,7 @@
  * 2. Create an IMM CCB containing all modifications to be done.
  *    In this step admin ownership is set for objects to be modified
  *    All information needed to create the CCB is stored to make it possible to
- *    try again if the applying the CCB fails but a retry is valid to do.
+ *    try again if applying the CCB fails but a retry is valid to do.
  * 3. Apply the CCB and clear admin ownership
  *
  * RETRY handling is done in three levels:
@@ -75,12 +76,13 @@
  *
  * ERROR handling:
  * The execute API returns a boolean where false means that the modification
- * failed. All non recoverable internal fails are logged to syslog. The user
+ * failed. All non recoverable internal fails are logged to the syslog. The 
user
  * should log a fail in order to track where the modification was requested but
  * does not have to log any detailed information.
  * Example of user logging:
  * LOG_NO("%s: DoModification() Fail", __FUNCTION__);
- * More detailed information about a fail is saved and can be requested.
+ * TODO(Lennart) More detailed information about a fail is saved and can be
+ * requested.
  *
  * Possible reasons for a fail:
  *  * An IMM API has returned an unrecoverable error. This includes try again
@@ -98,6 +100,18 @@
 // This is also the case for Create and Modify
 // Investigate!
 
+// Convert SaNameT to a std::string to be used with an AttributeDescriptor
+// Note: Both types may contain data that cannot be read as text string but
+//       their data can still be contained in a std::string object
+//       Shall be used with AttributeDescriptor object
+static inline std::string SaNametToString(SaNameT* name_value);
+
+// Convert SaAnyT to a std::string to be used with an AttributeDescriptor
+// Note: std::string uses type char (8 bit) for each data but SaAnyT data is
+//       unsigned char. However in this case this does not matter. The
+//       std::string will not be used as a "string"
+static inline std::string SaAnytToString(SaAnyT* anyt_value);
+
 namespace modelmodify {
 
 // AttributeDescriptor: Describes one attribute
@@ -374,4 +388,43 @@ class ObjectModification {
 
 } // namespace modelmodify
 
+// TODO(Lennart) For now functions are added here for converting SaNameT and
+//               SaAnyT to std::string. May be inline methods in the
+//               AttributeDescriptor structure?
+//
+//               Maybe part of modelmodify namespace?
+
+static inline std::string SaNametToString(SaNameT* name_value) {
+  std::string out_string;
+  if (osaf_is_extended_name_empty(name_value)) {
+    out_string = "";
+  } else {
+    SaConstStringT name_data = osaf_extended_name_borrow(name_value);
+    out_string = name_data;
+  }
+
+  return out_string;
+}
+
+static inline std::string SaAnytToString(SaAnyT* anyt_value) {
+  std::cout << __FUNCTION__ << " >>" << std::endl;
+  std::string out_string;
+  if ((anyt_value->bufferSize == 0) || (anyt_value->bufferAddr == nullptr)) {
+    out_string = "";
+    std::cout << "  No data. Empty string created" << std::endl;
+  } else {
+    SaSizeT anyt_size = anyt_value->bufferSize;
+    std::cout << "  bufferSize = " << anyt_size << std::endl;
+    SaUint8T* anyt_buffer = anyt_value->bufferAddr;
+    printf("  bufferAddr = %p\n", anyt_buffer);
+    for (SaSizeT i = 0; i < anyt_size; i++) {
+      //printf("  buffer[%lld] = 0x%x\n", i, *anyt_buffer);
+      out_string.push_back(static_cast<char>(*anyt_buffer++));
+    }
+  }
+
+  std::cout << __FUNCTION__ << " <<" << std::endl;
+  return out_string;
+}
+
 #endif // IMMCCB_H
diff --git a/src/smf/smfd/imm_modify_demo/ccbdemo1.cc 
b/src/smf/smfd/imm_modify_demo/ccbdemo1.cc
index 7f40800c2..bea650975 100644
--- a/src/smf/smfd/imm_modify_demo/ccbdemo1.cc
+++ b/src/smf/smfd/imm_modify_demo/ccbdemo1.cc
@@ -24,9 +24,9 @@
 #include <utility>
 #include <iostream>
 
-//#include "osaf/configmake.h"
 #include "ais/include/saImm.h"
 #include "ais/include/saAis.h"
+#include "base/osaf_extended_name.h"
 
 #include "smf/smfd/imm_modify_config/immccb.h"
 
@@ -44,6 +44,18 @@
 
 using namespace std;
 
+void PrintSaAnyT(SaAnyT *value) {
+  std::cout << "PrintSaAnyT --------------" << std::endl;
+  std::cout << "  bufferSize = " << value->bufferSize << std::endl;
+  printf("  bufferAddr = %p\n", value->bufferAddr);
+#if 1
+  for (SaSizeT i = 0; i < value->bufferSize; i++) {
+      printf("    %lld. bufval = 0x%x\n", i, value->bufferAddr[i]);
+  }
+#endif
+  std::cout << "---------------------------" << std::endl;
+}
+
 void PrintAttributeValues(modelmodify::AttributeDescriptor& attr) {
   for (auto& value : attr.values_as_strings) {
     cout << " * " << value << endl;
@@ -61,15 +73,30 @@ void PrintCreateDescriptor(modelmodify::CreateDescriptor 
create) {
 }
 
 void PrintCcbDescriptor(modelmodify::CcbDescriptor ccb) {
+  int i = 1;
   for (auto& create_descriptor : ccb.create_descriptors) {
+    cout << i++ << ". " << "CcbDescriptor" << endl;
     PrintCreateDescriptor(create_descriptor);
+    cout << endl;
   }
 }
 
+void PrintName(SaNameT* name) {
+  cout << "PrintName()" << endl;
+  SaConstStringT test_string = osaf_extended_name_borrow(name);
+  cout << "String length = " << osaf_extended_name_length(name) << endl;
+  cout << "test_string = " << test_string << endl;
+}
+
 #if 0 // LLDTEST Working code using om API directly
 int main() {
+  cout << "Creating an object using 'immom' directly" << endl;
   cout << "Creating: TestObj1=1,safApp=safSmfService" << endl << endl;
 
+  // Prepare extended name
+  setenv("SA_ENABLE_EXTENDED_NAMES", "1", 1);
+  osaf_extended_name_init();
+
   immom::ImmOmHandle om_handle;
   if (om_handle.InitializeHandle() == false) {
     cout << "OM handle Fail" << endl;
@@ -125,24 +152,62 @@ int main() {
     int64_values_pointers.push_back(int64_p++);
   }
 
-  std::vector<SaTimeT> time_values;
-  std::vector<SaTimeT*> time_values_pointers;
-  for (SaTimeT i = 100; i < 105; i++) {
-    time_values.push_back(i);
+  CppSaTimeT time_value;
+  std::vector<CppSaTimeT> time_values;
+  std::vector<CppSaTimeT*> time_values_pointers;
+  SaTimeT t = 100;
+  for (size_t i = 100; i < 105; i++) {
+    time_value = t++;
+    time_values.push_back(time_value);
   }
-  SaTimeT* time_p = time_values.data();
+  CppSaTimeT* time_p = time_values.data();
   for (size_t i = 0; i < time_values.size(); i++) {
     time_values_pointers.push_back(time_p++);
   }
 
+  // SaNameT
+  std::vector<SaNameT> name_values;
+  std::vector<SaNameT*> name_values_pointers;
+  SaNameT name_value;
+
+  osaf_extended_name_lend("test_name1", &name_value);
+  PrintName(&name_value);
+  name_values.push_back(name_value);
+  osaf_extended_name_lend("test_name2", &name_value);
+  PrintName(&name_value);
+  name_values.push_back(name_value);
+  SaNameT* name_p = name_values.data();
+  name_values_pointers.push_back(name_p++);
+  name_values_pointers.push_back(name_p);
+
+  // SaAnyT
+  SaAnyT any_value1;
+  SaUint8T buffer1[] = {1, 2, 3, 4, 5};
+  any_value1.bufferAddr = buffer1;
+  any_value1.bufferSize = sizeof(buffer1);
+  SaAnyT any_value2;
+  SaUint8T buffer2[] = {6, 7, 8, 9, 10};
+  any_value2.bufferAddr = buffer2;
+  any_value2.bufferSize = sizeof(buffer2);
+  std::vector<SaAnyT> any_values;
+  std::vector<SaAnyT*> any_values_pointers;
+
+  any_values.push_back(any_value1);
+  any_values.push_back(any_value2);
+  SaAnyT* any_p = any_values.data();
+  any_values_pointers.push_back(any_p++);
+  any_values_pointers.push_back(any_p);
+
   creator.SetAttributeValue("SaUint32TValues", uint32_values_pointers);
-  creator.SetAttributeValue("SaUint32TValues", int64_values_pointers);
-  creator.SetAttributeValue("SaTimeTValues", time_values_pointers);
-//  creator.SetAttributeValue("SaInt64TValues", time_values_pointers);
+  //creator.SetAttributeValue("SaInt64TValues", int64_values_pointers);
+  //creator.SetAttributeValue("SaTimeTValues", time_values_pointers);
+  creator.SetAttributeValue("SaNameTValues", name_values_pointers);
+  creator.SetAttributeValue("SaAnyTValues", any_values_pointers);
 
   cout << "AddObjectCreateToCcb()" << endl;
   if (creator.AddObjectCreateToCcb() == false) {
-    cout << "AddObjectCreateToCcb() Fail" << endl;
+    cout << "AddObjectCreateToCcb() Fail, " << creator.ais_error_string()
+         << endl;
     return -1;
   }
 
@@ -158,8 +223,10 @@ int main() {
 
 #if 1 // Using modelmofify immccb
 int main(void) {
-  cout << "I am ccbdemo1" << std::endl << std::endl;
-  cout << "Creating: TestObj1=1,safApp=safSmfService" << endl << endl;
+  cout << "I am ccbdemo1 creating an object using 'modelmodify'" << std::endl;
+  cout << "Class name: ImmTestValuesConfig" << endl;
+  cout << "Creating: TestObj1=1,safApp=safSmfService" << endl;
+  cout << "Creating: TestObj2=1,safApp=safSmfService" << endl << endl;
 
 #if 0// Enable trace
   unsigned int category_mask = 0xffffffff;
@@ -173,6 +240,15 @@ int main(void) {
   }
 #endif
 
+  // Prepare/enable extended name
+  // ----------------------------
+  setenv("SA_ENABLE_EXTENDED_NAMES", "1", 1);
+  osaf_extended_name_init();
+  // Note: Long DN must be configured in IMM configuration object before
+  // running ccbdemo1
+  // DN for that object is opensafImm=opensafImm,safApp=safImmService
+
+
   // Create an object TestObj1=1 of class ImmTestValuesConfig
   // Parent is safApp=safSmfService
   // Name of rdn attribute is immTestValuesCfg
@@ -183,10 +259,15 @@ int main(void) {
   modelmodify::CreateDescriptor test_object_create;
   modelmodify::AttributeDescriptor object_name;
   modelmodify::AttributeDescriptor uint32_values;
+  modelmodify::AttributeDescriptor uint32_value;
   modelmodify::AttributeDescriptor int32_values;
   modelmodify::AttributeDescriptor uint64_values;
   modelmodify::AttributeDescriptor int64_values;
   modelmodify::AttributeDescriptor time_values;
+  modelmodify::AttributeDescriptor float_values;
+  modelmodify::AttributeDescriptor double_values;
+  modelmodify::AttributeDescriptor name_values;
+  modelmodify::AttributeDescriptor any_values;
   modelmodify::AttributeDescriptor string_values;
 
   cout << "Construct attribute descriptors" << endl;
@@ -198,10 +279,15 @@ int main(void) {
   object_name.AddValue("TestObj1=1");
 
   // SA_IMM_ATTR_SAUINT32T
+  // Multi value
   uint32_values.attribute_name = "SaUint32TValues";
   uint32_values.value_type = SA_IMM_ATTR_SAUINT32T;
   uint32_values.AddValue(std::to_string(1));
   uint32_values.AddValue(std::to_string(2));
+  // Single value
+  uint32_value.attribute_name = "SaUint32TValue";
+  uint32_value.value_type = SA_IMM_ATTR_SAUINT32T;
+  uint32_value.AddValue(std::to_string(9));
 
   // SA_IMM_ATTR_SAINT32T
   int32_values.attribute_name = "SaInt32TValues";
@@ -227,7 +313,59 @@ int main(void) {
   time_values.AddValue(std::to_string(100));
   time_values.AddValue(std::to_string(200));
 
-  // SA_IMM_ATTR_SASTRINGT Other string values
+  // SA_IMM_ATTR_SAFLOATT
+  float_values.attribute_name = "SaFloatValues";
+  float_values.value_type = SA_IMM_ATTR_SAFLOATT;
+  float_values.AddValue(std::to_string(1.1));
+  float_values.AddValue(std::to_string(1.2));
+
+  // SA_IMM_ATTR_SADOUBLET
+  double_values.attribute_name = "SaDoubleValues";
+  double_values.value_type = SA_IMM_ATTR_SADOUBLET;
+  double_values.AddValue(std::to_string(2.1));
+  double_values.AddValue(std::to_string(2.2));
+
+  // SA_IMM_ATTR_SANAMET
+  SaNameT a_name;
+  name_values.attribute_name = "SaNameTValues";
+  name_values.value_type = SA_IMM_ATTR_SANAMET;
+  // Short name
+  osaf_extended_name_lend("a_name1", &a_name);
+  name_values.AddValue(SaNametToString(&a_name));
+  osaf_extended_name_lend("a_name2", &a_name);
+  name_values.AddValue(SaNametToString(&a_name));
+  // Long name
+  char long_name[300];
+  for (size_t i = 0; i < 299; i++) {
+    long_name[i] = 'a';
+  }
+  long_name[299] = '\0';
+  osaf_extended_name_lend(long_name, &a_name);
+  name_values.AddValue(SaNametToString(&a_name));
+  osaf_extended_name_lend("a_name3", &a_name);
+  name_values.AddValue(SaNametToString(&a_name));
+
+
+
+  // SA_IMM_ATTR_SAANYT
+  any_values.attribute_name = "SaAnyTValues";
+  any_values.value_type = SA_IMM_ATTR_SAANYT;
+
+  SaAnyT any_value1;
+  SaUint8T buffer1[] = {1, 2, 3, 4, 5};
+  any_value1.bufferAddr = buffer1;
+  any_value1.bufferSize = sizeof(buffer1);
+  //PrintSaAnyT(&any_value1); //LLDTEST
+  any_values.AddValue(SaAnytToString(&any_value1));
+
+  SaAnyT any_value2;
+  SaUint8T buffer2[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+  any_value2.bufferAddr = buffer2;
+  any_value2.bufferSize = sizeof(buffer2);
+  //PrintSaAnyT(&any_value2); //LLDTEST
+  any_values.AddValue(SaAnytToString(&any_value2));
+
+  // SA_IMM_ATTR_SASTRINGT
   string_values.attribute_name = "SaStringValues";
   string_values.value_type = SA_IMM_ATTR_SASTRINGT;
   string_values.AddValue("str_value1");
@@ -240,19 +378,48 @@ int main(void) {
   test_object_create.parent_name = "safApp=safSmfService";
   test_object_create.AddAttribute(object_name);
   test_object_create.AddAttribute(uint32_values);
+  test_object_create.AddAttribute(uint32_value);
   test_object_create.AddAttribute(int32_values);
   test_object_create.AddAttribute(uint64_values);
   test_object_create.AddAttribute(int64_values);
   test_object_create.AddAttribute(time_values);
+  test_object_create.AddAttribute(float_values);
+  test_object_create.AddAttribute(double_values);
+
+  test_object_create.AddAttribute(name_values);
+  test_object_create.AddAttribute(any_values);
   test_object_create.AddAttribute(string_values);
 
+  // =======================================
+  // A second create request.
+  // Parent and class is the same
+  // Reuse some attribute descriptors
+  // =======================================
+  modelmodify::CreateDescriptor test_object_create2;
+  test_object_create2.class_name = "ImmTestValuesConfig";
+  // If the following line is commented out a root object will be created
+  // test_object_create2.parent_name = "safApp=safSmfService";
+
+  // SA_IMM_ATTR_SASTRINGT The object name. Structure reused and value modified
+
+  // Modify by deleting the old value and add a new value for object name
+  object_name.values_as_strings.clear();
+  object_name.AddValue("TestObj2=1");
+
+  // SA_IMM_ATTR_SAUINT32T. Structure is reused without modifications
+
+  test_object_create2.AddAttribute(object_name);
+  test_object_create2.AddAttribute(uint32_values);
+
   cout << "Construct a CCB descriptor" << endl;
   // Construct a CCB descriptor:
   // ---------------------------
   test_ccb.AddCreate(test_object_create);
+  test_ccb.AddCreate(test_object_create2);
 
+  cout << "CCB descriptor for test_ccb created" << endl;
   PrintCcbDescriptor(test_ccb);
-  cout << "ccbdemo1 ccb descriptor printed" << endl << endl;
+  cout << endl;
 
   modelmodify::ObjectModification obj_creator;
   obj_creator.SetCcbFlags(0);
diff --git a/src/smf/smfd/imm_modify_demo/democlass.xml 
b/src/smf/smfd/imm_modify_demo/democlass.xml
index 1f012fd41..a7f14dfda 100644
--- a/src/smf/smfd/imm_modify_demo/democlass.xml
+++ b/src/smf/smfd/imm_modify_demo/democlass.xml
@@ -2,12 +2,20 @@
 <imm:IMM-contents xmlns:imm="http://www.saforum.org/IMMSchema"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:noNamespaceSchemaLocation="SAI-AIS-IMM-XSD-A.02.13.xsd">
     <class name="ImmTestValuesConfig">
         <category>SA_CONFIG</category>
+        <!--> Single value attributes <-->
         <rdn>
             <name>immTestValuesCfg</name>
             <type>SA_STRING_T</type>
             <category>SA_CONFIG</category>
             <flag>SA_INITIALIZED</flag>
         </rdn>
+        <attr>
+            <name>SaUint32TValue</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <!--> Multi value attributes <-->
         <attr>
             <name>SaUint32TValues</name>
             <type>SA_UINT32_T</type>
@@ -80,5 +88,13 @@
             <flag>SA_MULTI_VALUE</flag>
             <flag>SA_NO_DUPLICATES</flag>
         </attr>
+        <attr>
+            <name>SaAnyTValues</name>
+            <type>SA_ANY_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+            <flag>SA_MULTI_VALUE</flag>
+            <flag>SA_NO_DUPLICATES</flag>
+        </attr>
     </class>
 </imm:IMM-contents>
diff --git a/src/smf/smfd/imm_om_api/common/imm_attribute.cc 
b/src/smf/smfd/imm_om_api/common/imm_attribute.cc
index 62c22b504..8e1a19cce 100644
--- a/src/smf/smfd/imm_om_api/common/imm_attribute.cc
+++ b/src/smf/smfd/imm_om_api/common/imm_attribute.cc
@@ -34,7 +34,8 @@ void AttributeProperty::FormSearchOneAttrT_2(
   assert(output != nullptr);
   output->attrName = const_cast<char*>(attribute_name_.c_str());
   output->attrValueType = attribute_type_;
-  void* value = (attribute_values_pointers_ == nullptr) ? nullptr : 
attribute_values_pointers_[0];
+  void* value = (attribute_values_pointers_ == nullptr) ? nullptr :
+    attribute_values_pointers_[0];
   output->attrValue = value;
 }
 
@@ -44,7 +45,8 @@ void AttributeProperty::FormAdminOperationParamsT_2(
   assert(output != nullptr);
   output->paramName = const_cast<char*>(attribute_name_.c_str());
   output->paramType = attribute_type_;
-  void* value = (attribute_values_pointers_ == nullptr) ? nullptr : 
attribute_values_pointers_[0];
+  void* value = (attribute_values_pointers_ == nullptr) ? nullptr :
+    attribute_values_pointers_[0];
   output->paramBuffer = value;
 }
 
@@ -55,7 +57,8 @@ void AttributeDefinition::FormAttrDefinitionT_2(
   output->attrName = const_cast<char*>(attribute_name_.c_str());
   output->attrValueType = attribute_type_;
   output->attrFlags = attribute_flags_;
-  void* value = (attribute_values_pointers_ == nullptr) ? nullptr : 
attribute_values_pointers_[0];
+  void* value = (attribute_values_pointers_ == nullptr) ? nullptr :
+    attribute_values_pointers_[0];
   output->attrDefaultValue = value;
 }
 
-- 
2.15.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to