/*Paul Johnson  March 1, 2002. Updated some syntax for Swarm2.2*/

/*Marcus Daniels Mar 29, 2000 swarm-support

Below is an example that demonstrates loading and saving Lists and
Maps using shallow serialization.  In the HDF5 configuration, the data
can be recovered as a R data frame.  (The default configuration is for
List and HDF5, i.e. the absence of -DUSE_MAP and the presence of -DUSE_HDF5
in the compile-command.)

To save data use:
   ./collectionArchiving -m create

To load it, use:
   
   ./collectionArchiving

To load it in R 1.0, use:

    library(hdf5) # need to load the HDF5 module
    hdf5load("collection.hdf") # load the file specified per the code below
    myCollection # the variable it is loaded to per the code below

Saving in R is as below.  Note that the need to specify variable names
as quoted strings.

    x <- 1 # assign 1 to "x"
    hdf5save("newCollection.hdf", "myCollection", "x")

LRA> I'm not finding it in the version distributed on the Swarm 2.1
LRA> CD- either via the Help command or in the extensive reference
LRA> manual. 

Did you install the HDF5 module and do "library(hdf5)" upon R startup?
*/

#import <simtools.h> // initSwarm
#import <defobj.h> // Archivers
#import <defobj/Create.h> // CreateDrop
#import <defobj/defalloc.h> // getZone

@interface Data: CreateDrop
{
#ifndef USE_MAP
  const char *date;
#endif
  double value;
}
#ifndef USE_MAP
- setDate: (const char *)date;
- (void)describe: stream;
#else
- (double)getVal;
#endif
- setVal: (double)value;
@end

@implementation Data
#ifndef USE_MAP
- setDate: (const char *)theDate
{
  date = STRDUP (theDate);
  return self;
}
#endif

- setVal: (double)theValue
{
  value = theValue;
  return self;
}

#ifndef USE_MAP
- (void)describe: stream
{
  [stream catC: "Date: "];
  [stream catC: date];
  [stream catC: " Value: "];
  [stream catDouble: value];
  [stream catC: "\n"];
}
#else
- (double)getVal
{
  return value;
}
#endif

@end

@interface Controller: CreateDrop
{
  id collection;
}

-(void)drop;

#ifdef USE_MAP
- (void)createMap;
#else
- createList;
#endif
@end

#define NAME "myCollection"

@implementation Controller

#ifdef USE_MAP
- (void)createMap
{
#define DATA(value) [[[Data createBegin: getZone (self)] setVal: value] createEnd]
  collection = [[[Map createBegin: getZone (self)]
            setCompareCStrings]
           createEnd];
  [collection at: (id) "1999-01-01" insert: DATA(1.0)];
  [collection at: (id) "1999-01-02" insert: DATA(2.0)];
  [collection at: (id) "1999-12-31" insert: DATA(3.0)];
}
#else
#define DATA(date,value) \
  [[[[Data createBegin: getZone (self)] setDate: date] setVal: value] createEnd]

- createList
{
  collection = [List create: getZone (self)];
  [collection addLast: DATA ("1999-01-01", 1.0)];
  [collection addLast: DATA ("1999-01-02", 2.0)];
  [collection addLast: DATA ("1999-12-31", 3.0)];
  return collection;
}
#endif

- (void) updateArchiver: archiver
{
  //[archiver putShallow: NAME object: collection];
     [archiver putDeep: NAME object: collection];
}
- (void)drop
{
  [collection drop];
  [super drop];
 }

@end

int
main (int argc, const char **argv) 
{
  initSwarmBatch (argc, argv);

  id archiver;
  id controller;
  id aCollection;
 
#ifdef USE_HDF5
  archiver = [[[HDF5Archiver createBegin: globalZone]
		setPath: "collection.hdf"]
	       createEnd];
#else
  archiver = [[[LispArchiver createBegin: globalZone]
		setPath: "collection.scm"]
	       createEnd];
#endif
  controller = [Controller create: globalZone];
  
  if (strcmp ([arguments getAppModeString], "create") == 0)
    {
#ifdef USE_MAP
      aCollection = [controller createMap];
#else
      aCollection = [controller createList];
#endif
      /**********************************************************************/
      //pj: 2002-03-03 I can't get the "registerClient" way to work with hdf5 saves!
      //it does not give errors, but it does not create hdf5 output either.
      [archiver registerClient: controller];
      //[archiver putDeep: NAME object: aCollection]; 
      //[archiver putDeep: NAME object: controller]; 
#ifndef USE_HDF5
      [archiver sync];
#endif
    }
  else
    {
#ifdef USE_MAP
      id collection, index, obj, key;
      
      collection = [archiver getObject: NAME];
      if (collection)
	{
	  index = [collection begin: scratchZone];
	  
	  for (obj = [index next: &key];
	       [index getLoc] == Member;
	       obj = [index next: &key])
	    {
	      printf ("Date: %s Value: %f\n",
		      (const char *) key,
		      [obj getVal]);
	    }
	  [index drop];
	}
#else
      xfprint ([archiver getObject: NAME]);
#endif
    }
  [controller drop];
  [archiver drop];
  return 0;
}

/*
Local Variables:
compile-command: "$SWARMHOME/bin/libtool-swarm --mode=link gcc3 -D_GNU_SOURCE -o collection  -g -Wno-import -I$SWARMHOME/include -I$SWARMHOME/include/swarm -L$SWARMHOME/lib -L$SWARMHOME/lib/swarm HDF5orLispListsInOut.m  -lswarm -lobjc "
End:
*/
