/*
   Project: Adun

   Copyright (C) 2006 Michael Johnston & Jordi Villa-Freixa

   Author: Michael Johnston

   Created: 2006-06-26 17:34:11 +0200 by michael johnston

   This application is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This application is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/

#ifndef _ADMODELOBJECT_H_
#define _ADMODELOBJECT_H_

#include <Foundation/Foundation.h>

/**
Superclass for objects that can be stored to a database.
AdModelObject gives metadata and input/output reference management
abilities to its subclasses aswell as a globally unique identification 
assigned on initialisation.


AdModelObject allows two types of metadata to be associated with an object
, peristent and volatile. Persistent metadata is stored and retrieved when
an object is archived/unarchived while volatile metadata only exists 
when an object is in memory i.e. it is discarded when the object is archived.
An example of persistent metadata is the database where the object is stored while
an example of volatile metadata is the client that was used to retrieve the object.


Subclasses of AdModelObject automatically have the following metadata keys
when they are created - Name, Database & Keywords - all with value "None". In addition
to these metadata keys AdModelObjects also have the following non-mutable attributes,
called general data, assigned on creation: Identification, Created & Creator.
*/

@interface AdModelObject : NSObject <NSCoding>
{
	NSDate* date;
	NSDateFormatter* dateFormatter;
	NSMutableDictionary* dataDict;
	NSMutableDictionary* generaldata; 	//!< Stuff you cant change
	NSMutableDictionary* metadata; 		//!< Stuff you can change
	NSMutableDictionary* inputReferences;
	NSMutableDictionary* outputReferences;
	NSMutableDictionary* volatileMetadata;
	id identification;
}
/**
Returns the unique string identification for this object
*/
- (NSString*) identification;
/**
Deprecated: This method should not be used.
*/
- (void) setIdentification: (NSString*) value;
/**
Returns a dictionary with two keys @"General" and @"Metadata" each of which
is also a dictionary. 
*/
- (NSMutableDictionary*) dataDictionary;
/**
Returns a dictionary containing the persisten metadata name:value pairs. This is the same dictionary obtained
through the key @"Metatdata" of the dictionary returned by \b dataDictionary.
*/
- (NSMutableDictionary*) metadata;
/**
Returns a dictionary of containing the key:value pairs of both the metadata and generaldata
dictionaries. Note: volatile metadata is not included.
*/
- (NSMutableDictionary*) allData;
/**
Updates the objects persistent metadata with the values in \e values.
Subclasses should override this method if they add extra class specific persistent metadata keywords.
*/
- (void) updateMetadata: (NSDictionary*) values;
/**
Returns the value for the metadata key \e aString or nil
if the key doesnt exist.
*/
- (NSString*) valueForMetadataKey: (NSString*) aString;
/**
Sets the value for the metadata key \e aString to \e value.
The metadata key is created if it doesnt exist
*/
- (void) setValue: (id) value forMetadataKey: (NSString*) aString;
/**
Removed the metadata key \e aString from the object. Does nothing
if the key doesnt exist.
*/
- (void) removeMetadataKey: (NSString*) aString;
/**
Returns the value for the volatile metadata key \e aString or nil
if the key doesnt exist.
*/
- (NSString*) valueForVolatileMetadataKey: (NSString*) aString;
/**
Sets the value for the volatile metadata key \e aString to \e value.
The metadata key is created if it doesnt exist
*/
- (void) setValue: (id) value forVolatileMetadataKey: (NSString*) aString;
/**
Removed the volatile metadata key \e aString from the object. Does nothing
if the key doesnt exist.
*/
- (void) removeVolatileMetadataKey: (NSString*) aString;
/**
Returns the (non-unique) name associated with the object.
*/
- (id) name;
/**
Returns the creator of this object (as determined by the username)
*/
- (id) creator;
/**
Returns the date this object was created
*/
- (id) created;
/**
Returns an array of strings, each representing a keyword, associated with this object.
*/
- (id) keywords;
/**
Returns the name of the database the object is stored in i.e. was unarchived from.
*/
- (NSString*) database;
/**
Returns the name of the schema in the database that the object is stored in (or nil if 
none)
*/
- (NSString*) schema;
/**
Returns a dictionary whose keys are the ids of objects who created this object
and whose values are dictionaries containing information about the location of those obejcts. 
These dictionaries have the following keys

- Identification - The objects id (same as the key that returned this dict)
- DatabaseName - The database the object was located in when the reference was added.
- SchemaName - The schema the object was located in when the reference was added.
- Name - The objects name
- Class - The objects class

*/
- (NSArray*) inputReferencesToObjectsOfClass: (NSString*) className;
/**
Returns a dictionary whose keys are object types (usually class names) and
whose values are dictionaries of ident:location pairs referencing the objects of \e className
that generated this model object.
*/
- (NSArray*) inputReferences;
/**
Adds an input reference for the object \e obj. If \e obj does not respond to \b identification this method
raises an NSInvalidArguementException
*/
- (void) addInputReferenceToObject: (id) obj;
/**
Adds the ID given by \e ident, along with the location specified by \e schema and \e databaseName 
to the list of object ids of type \e type that generated this model object
*/
- (void) addInputReferenceToObjectWithID: (NSString*) ident 
		name: (NSString*) objectName
		ofType: (NSString*) type
		inSchema: (NSString*) schema
		ofDatabase: (NSString*) databaseName;
/**
Removes the input reference for the object \e obj. If \e obj does not respond to \b identification this method
raises an NSInvalidArguementException. If no reference to \e obj exists this method does nothing.
*/
- (void) removeInputReferenceToObject: (id) obj;
/**
Removes the ID given by \e aString from the list of object ids of type \e type that generated this
model object.
*/
- (void) removeInputReferenceToObjectWithID: (NSString*) ident ofType: (NSString*) type;
/**
Returns a dictionary whose keys are ids of objects who were created from this object
and whose values are dictionaries containing information about the location of each object. 
These dictionaries have the following keys

- Identification - The objects id (same as the key that returned this dict)
- DatabaseName - The database the object was located in when the reference was added.
- SchemaName - The schema the object was located in when the reference was added.
- Name - The objects name
- Class - The objects class
*/
- (NSArray*) outputReferencesToObjectsOfClass: (NSString*) className;
/**
Returns a dictionary whose keys are object types (usually class names) and
whose values are dictionaries of ident:location pairs referencing the objects of \e className
that were generated from this model object.
*/
- (NSArray*) outputReferences;
/**
Adds an output reference for the object \e obj. If \e obj does not respond to \b identification this method
raises an NSInvalidArguementException
*/
- (void) addOutputReferenceToObject: (id) obj;
/**
Adds the ID given by \e aString along with the location information specified by 
\e schema and \e databaseName to the list of object ids of type \e type that were 
generated by this model object.
*/
- (void) addOutputReferenceToObjectWithID: (NSString*) ident 
		name: (NSString*) objectName
		ofType: (NSString*) type
		inSchema: (NSString*) schema
		ofDatabase: (NSString*) databaseName;
/**
Removes the output reference for the object \e obj. If \e obj does not respond to \b identification this method
raises an NSInvalidArguementException. If no reference to \e obj exists this method does nothing.
*/
- (void) removeOutputReferenceToObject: (id) obj;
/**
Removes the ID given by \e aString from the list of object ids of type \e type that were
generated by this model object. \e type can be nil but the method will take longer to execute.
*/
- (void) removeOutputReferenceToObjectWithID: (NSString*) ident ofType: (NSString*) type ;
/**
As removeOutputReferenceToObjectWithID:ofType with a nil value for \type
*/
- (void) removeOutputReferenceToObjectWithID: (NSString*) ident;
@end

#endif // _ADMODELOBJECT_H_

