// ////////////////////////////////////////////////////////
// Copyright (1994) Columbia University
// Department of Biochemistry and Molecular Biophysics
//
// Author: Weider Chang, Ph.D
// ///////////////////////////////////////////////////////

#include <string.h>
#include "starasso.h"
#include "wstring.h"
#include "llistobj.h"
#include "iterator.h"

@implementation WDCStarItemAssocValue

- free
{
  [_name free];
  [super free];
}

- (const char*)getName;
{
  return [_name cStringValue];
}

- getNameString;
{
  return _name;
}

- getDataBlock;
{
  return [self getItem];
}

- getItemNamed:(const char*)aName
{
  return (![[self getNameString] compareCString:aName ignoreCase:YES])?
    self : [[self nextLink] getItemNamed:aName];
}

- getAllItemsNamed:(const char*)aName
{
  // This method is based on the assumption that the looped items are stored
  // as a linklist of StarAssoc(s).


  id iter, iter1, item=[self getItemNamed:aName], listOfItems=0;
  if (item) 
    listOfItems=[[WDCLListOfObject alloc] setContent:item];
  else 
    {
      if (item=[self getAllLoops])
	{
	  iter=[[WDCListIterator alloc] initFrom: item];
	  iter1=[WDCListIterator alloc];
	  while ([iter goNext])
	    {
	      [iter1 initFrom: [[[iter getCurrentObject] getContent]
				getValue]];
	      while ([iter1 goNext])
		{
		  if (listOfItems)
		    [listOfItems joint:[[[iter1 getCurrentObject] getContent]
					getAllItemsNamed :aName]];
		  else
		    listOfItems=[[[iter1 getCurrentObject] getContent]
					getAllItemsNamed :aName];
		  if (!listOfItems) break;
		  // since all StarAssoc structures are the same in a loop_.
		  // So, if I can't find it in the first object it does not 
		  // exist in the rest of this loop_ at all.
		}
	      if (listOfItems) break;
	      // *******************************************************
	      // if I got a positive result from a loop then stop futher 
	      // query, since itemName can only exist in one loop_
	      // *******************************************************
	    }
	  [item free]; // item was generated by "getAllLoops"
	  [iter free];
	  [iter1 free];
	}
    }
  return listOfItems;
}

- getAllLoops
{
  id listOfLoops=[WDCLListOfObject alloc];
  id currentId=self;
  while (currentId)
    {
      if (![[currentId getNameString] compareCString:"loop_" ignoreCase:YES])
	[listOfLoops addContent: currentId];
      currentId=[currentId nextLink];
    }
  if (![listOfLoops getContent])
    {
      [listOfLoops free];
      listOfLoops=0;
    } 
  return listOfLoops;
}

- deepCopy
{
  id temp=[WDCStarItemAssocValue alloc];
  [temp setItem:[[self getItem] deepCopy]];
  [temp setValue:[[self getValue] deepCopy]];
  [temp setName:[self getName]];
  return [temp addStarAssocValue:[[self nextLink] deepCopy]];
}

- shallowCopy
{
  id temp=[WDCStarItemAssocValue alloc];
  [temp setItem:[self getItem]];
  [temp setValue:[self getValue]];
  [temp setName:[self getName]];
  return temp;
}

- selectedDeepCopy
{
  id value;
  id temp=[WDCStarItemAssocValue alloc];
  [temp setName:[self getName]];
  value=[self getValue];
  if (([value isKindOfClassNamed:"WDCStartAssocValue"]) ||
      ([value isKindOfClassNamed:"WDCLListOfObject"]))
    [temp setValue:[[self getValue] selectedDeepCopy]];
  return [temp addStarAssocValue:[[self nextLink] selectedDeepCopy]];
}

- setName:(const char*)name;
{
  return [self setNameString:[[WDCString alloc] 
			    initFromCString:(char*)name]];
}

- setNameString: string;
{
  if (_name) [_name free];
  _name=string;
  return self;
}

- setDataBlock: dataBlock;
{
  return [self setItem:dataBlock];
}

- addValue: value;
{
  id currentValue=[self getValue];
  if (!currentValue) 
    [self setValue: value];
  else {
    if (![currentValue isKindOfClassNamed:"WDCLListOfObject"])
      {
	[self setValue:[[WDCLListOfObject alloc] setContent:currentValue]];
	currentValue=[self getValue];
      }
    [currentValue addContent:value];
  }
  return self;
}

- addStarAssocValue: starAssocValue
{
  if (![self nextLink])
    [self setNextLink : [starAssocValue setPrevLink : self]];
  else
    [(id)[self nextLink] addStarAssocValue : starAssocValue];
}

- makeItemDefinitionLinkWith:(WDCDictionary*)dictionary
{
  id value;
  char name[80];
  char* myname;
  strcpy(name, "data");
  myname=(char*)[self getName];
  if (myname[0]!='\'')
    strcat(name, myname);
  else
    strncat(name, &myname[1], strlen(myname)-2);
  [self setItem:[dictionary getDefinitionBlockAtKey:name]];
  value=[self getValue];
  if ([value respondsTo:@selector(makeItemDefinitionLinkWith:)])
    [value makeItemDefinitionLinkWith:dictionary];
  return self;
}

- (int)compare: anObject
{
  return ([super compare:anObject] || 
	  [_name compare: [anObject getNameString]]);
}
  

- printForDebuggerAux
{
  printf(" _name:");
  [_name printForDebugger];
  [super printForDebuggerAux];
}

@end


@implementation WDCLoopItemAssocValue


- addValue : value
{
  if (![self getValue]) [self setValue:[[WDCLListOfObject alloc]
					setContent : value ]];
  else [[self getValue] addContent : value];
}

@end


