Index: trunk/psLib/src/collections/psMetadata.c
===================================================================
--- trunk/psLib/src/collections/psMetadata.c	(revision 3780)
+++ trunk/psLib/src/collections/psMetadata.c	(revision 3945)
@@ -12,6 +12,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.61 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-04-28 19:52:48 $
+*  @version $Revision: 1.62 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-05-16 19:43:53 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -38,6 +38,34 @@
 #include "psAstronomyErrors.h"
 #include "psConstants.h"
+#include "psLogMsg.h"
+
+/******************************************************************************/
+/*  DEFINE STATEMENTS                                                         */
+/******************************************************************************/
+
+/** Maximum size of a string */
+#define MAX_STRING_LENGTH 1024
+
+/******************************************************************************/
+/*  TYPE DEFINITIONS                                                          */
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  GLOBAL VARIABLES                                                         */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  FILE STATIC VARIABLES                                                    */
+/*****************************************************************************/
 
 static psS32 metadataId = 0;
+
+/*****************************************************************************/
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+/*****************************************************************************/
 
 static psMetadataItem* makeMetaMulti(psHash* table, const char* key, psMetadataItem* existing)
@@ -48,11 +76,11 @@
     }
 
+    // move any existing entry into a psList
+    psList* newList = psListAlloc(existing);
 
     psMetadataItem* item = psMetadataItemAlloc(key,
                            PS_META_MULTI,
-                           "List of Metadata Items",
-                           NULL);
-
-    psListAdd(item->data.list,PS_LIST_TAIL,existing);
+                           "",
+                           newList);
 
     if (existing != NULL) {
@@ -60,7 +88,8 @@
     }
 
-    psHashAdd(table, key, item); // put in the new MULTI list entry
-
-    // free local references of newly allocated item.
+    psHashAdd(table, key, item); // put in the new entry
+
+    // free local references of newly allocated items.
+    psFree(newList);
     psFree(item);
 
@@ -80,5 +109,6 @@
     psFree(metadataItem->name);
     psFree(metadataItem->comment);
-    if (! PS_META_IS_PRIMITIVE(type)) {
+
+    if(!PS_META_IS_PRIMITIVE(type)) {
         psFree(metadataItem->data.V);
     }
@@ -104,4 +134,5 @@
     psFree(metadata->list);
     psFree(metadata->table);
+
 }
 
@@ -146,6 +177,5 @@
 {
     psMetadataItem* metadataItem = NULL;
-    char tmp;
-    int nBytes;
+
 
     PS_PTR_CHECK_NULL(name,NULL);
@@ -158,10 +188,11 @@
     psMemSetDeallocator(metadataItem, (psFreeFcn) metadataItemFree);
 
-    // set metadata item comment
+    // Allocate and set metadata item comment
+    metadataItem->comment = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
     if (comment == NULL) {
         // Per SDRS, null isn't allowed, must use "" instead
-        metadataItem->comment = psStringCopy("");
+        strncpy(metadataItem->comment, "", MAX_STRING_LENGTH);
     } else {
-        metadataItem->comment = psStringCopy(comment);
+        strncpy(metadataItem->comment, comment, MAX_STRING_LENGTH);
     }
 
@@ -173,6 +204,5 @@
 
     // Allocate and set metadata item name
-    nBytes = vsnprintf(&tmp, 0, name, argPtr) + 1;
-    metadataItem->name = (char *)psAlloc(sizeof(char) * nBytes);
+    metadataItem->name = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
     vsprintf(metadataItem->name, name, argPtr);
 
@@ -193,9 +223,5 @@
     case PS_META_STR:
         // Perform copy of input strings
-        metadataItem->data.V = psStringCopy(va_arg(argPtr, char *));
-        break;
-    case PS_META_MULTI:
-        // MULTI needs to create a psList entry, value must be NULL
-        metadataItem->data.list = psListAlloc(NULL);
+        metadataItem->data.V = psStringNCopy(va_arg(argPtr, char *), MAX_STRING_LENGTH);
         break;
     case PS_META_LIST:
@@ -207,4 +233,6 @@
     case PS_META_ASTROM:
     case PS_META_UNKNOWN:
+    case PS_META_META:
+    case PS_META_MULTI:
         // Copy of input data not performed due to variability of data types
         metadataItem->data.V = psMemIncrRefCounter(va_arg(argPtr, psPtr));
@@ -258,55 +286,70 @@
 
     // See if key is already in table
-    existingEntry = psMetadataLookup(md, key);
-
-    // if replace is set, remove any existing items of the same key
-    if (existingEntry != NULL && (flags & PS_META_REPLACE) != 0) {
-        psMetadataRemove(md,0,key);
-        existingEntry = NULL;
-    }
-
-    // if the metadataItem is MULTI, just create a MULTI node.
+    existingEntry = (psMetadataItem*)psHashLookup(mdTable, key);
+
     if (metadataItem->type == PS_META_MULTI) {
-        if (metadataItem->data.list == NULL || metadataItem->data.list->size > 0) {
-            psError(PS_ERR_BAD_PARAMETER_VALUE,true,
-                    "Specified PS_META_MULTI item is not defined properly "
-                    "(list allocated with zero size).");
-            return false;
-        }
-
-        // make sure the existing entry is PS_META_MULTI
+        // the incoming entry is PS_META_MULTI
+
+        // force the hash entry to be PS_META_MULTI
         existingEntry = makeMetaMulti(mdTable,key,existingEntry);
 
+        // add all the items in the incoming entry to metadata
+        psList* list = metadataItem->data.list;
+        if (list != NULL) {
+            psListIterator* iter = psListIteratorAlloc(list,PS_LIST_HEAD,true);
+            psMetadataItem* listItem;
+            while ((listItem=(psMetadataItem*)psListGetAndIncrement(iter)) != NULL) {
+                psMetadataAddItem(md,listItem,location,flags);
+            }
+            psFree(iter);
+        }
+
         return true; // all done.
     }
 
     // how the item is added to the hash depends on prior existence, flags, etc.
-    if(existingEntry == NULL) { // no prior existence
-        // Node doesn't already exist - Add new metadata item to metadata collection's hash
-        if(!psHashAdd(mdTable, key, metadataItem)) {
-            psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
-            return false;
-        }
-    } else {
+    if(existingEntry != NULL) { // prior existence
         if (existingEntry->type == PS_META_MULTI || (flags & PS_META_DUPLICATE_OK) != 0) {
             // duplicate entries allowed - add another entry.
 
-            // make sure the existing hash entry is PS_META_MULTI
+            // make sure the existing entry is PS_META_MULTI
             existingEntry = makeMetaMulti(mdTable,key,existingEntry);
 
-            // add to the hash key's list of entries
+            // add to the hash's list of duplicate entries
             if (! psListAdd(existingEntry->data.list, PS_LIST_TAIL, metadataItem) ) {
                 psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
                 return false;
             }
+        } else if ((flags & PS_META_REPLACE) != 0) {
+            // replace entry instead of creating a duplicate entry.
+
+            // remove the existing entry from metadata
+            psMetadataRemove(md,0,key);
+
+            // treat as if new (added to list below)
+            if(!psHashAdd(mdTable, key, metadataItem)) {
+                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
+                return false;
+            }
+
+            // Generate warning that item has been replaced
+            psLogMsg(__func__,PS_LOG_WARN,"Metadata item %s has been replaced",
+                     existingEntry->name);
         } else {
-            // error on duplicate entry.
+            // default is to error on duplicate entry.
             psError(PS_ERR_BAD_PARAMETER_VALUE, true,
                     PS_ERRORTEXT_psMetadata_DUPLICATE_NOT_ALLOWED);
             return false;
         }
-    }
-
-    // finally, add the metadataItem to the metadata's list.
+    } else {
+        // OK, this is a new item.
+
+        // Node doesn't exist - Add new metadata item to metadata collection's hash
+        if(!psHashAdd(mdTable, key, metadataItem)) {
+            psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
+            return false;
+        }
+    }
+
     if(!psListAdd(mdList, location, metadataItem)) {
         psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
@@ -363,4 +406,5 @@
 METADATA_ADD_TYPE(LookupTable,psLookupTable*,PS_META_LOOKUPTABLE)
 METADATA_ADD_TYPE(Unknown,void*,PS_META_UNKNOWN)
+METADATA_ADD_TYPE(Metadata,psMetadata*,PS_META_META)
 
 psBool psMetadataRemove(psMetadata *md, psS32 where, const char *key)
