aboutsummaryrefslogtreecommitdiffstats
path: root/Frameworks/MCPKit/MCPEntrepriseKit/MCPAttribute.m
diff options
context:
space:
mode:
Diffstat (limited to 'Frameworks/MCPKit/MCPEntrepriseKit/MCPAttribute.m')
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPAttribute.m466
1 files changed, 466 insertions, 0 deletions
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPAttribute.m b/Frameworks/MCPKit/MCPEntrepriseKit/MCPAttribute.m
new file mode 100644
index 00000000..34b50284
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPAttribute.m
@@ -0,0 +1,466 @@
+//
+// $Id: MCPAttribute.m 927 2009-06-24 10:53:07Z stuart02 $
+//
+// MCPAttribute.m
+// MCPkit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 09/08/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program 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 program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPAttribute.h"
+
+#import "MCPEntrepriseNotifications.h"
+
+#import "MCPModel.h"
+#import "MCPClassDescription.h"
+#import "MCPRelation.h"
+#import "MCPJoin.h"
+
+static NSArray *MCPRecognisedInternalType;
+
+@interface MCPAttribute (Private)
+
+- (void)setValueClassName:(NSString *) iClassName;
+
+@end
+
+@implementation MCPAttribute
+
+#pragma mark Class methods
++ (void) initialize
+{
+ if (self == [MCPAttribute class]) {
+ [self setVersion:010101]; // Ma.Mi.Re -> MaMiRe
+ MCPRecognisedInternalType = [[NSArray alloc] initWithObjects:@"NSCalendarDate", @"NSData", @"NSNumber", @"NSString", nil];
+ [self setKeys:[NSArray arrayWithObject:@"internalType"] triggerChangeNotificationsForDependentKey:@"valueClassName"];
+ [self setKeys:[NSArray arrayWithObject:@"valueClassName"] triggerChangeNotificationsForDependentKey:@"internalType"];
+ }
+ return;
+}
+
+
+#pragma mark Life cycle
+- (id) initForClassDescription:(MCPClassDescription *) iClassDescription withName:(NSString *) iName
+{
+ self = [super init];
+ {
+ classDescription = iClassDescription;
+ [self setName:iName];
+// relations = (NSMutableArray *)(CFArrayCreateMutable (kCFAllocatorDefault, 0, NULL));
+ joins = [[NSMutableArray alloc] init];
+ }
+ return self;
+}
+
+- (void) dealloc
+{
+// NSArray *theRelations;
+// unsigned int i;
+
+ [name release];
+ [internalType release];
+ [externalName release];
+ [externalType release];
+ [defaultValue release];
+/*
+ while ([relations count]) {
+ [(MCPRelation *)[relations objectAtIndex:0] unjoinAttribute:self];
+ }
+// By now relation should be empty anyway...
+ [relations release];
+ */
+ while ([joins count]) {
+ [[self objectInJoinsAtIndex:0] invalidate];
+ }
+ // By now the joins array should be empty
+ [joins release];
+ [super dealloc];
+}
+
+
+#pragma mark NSCoding protocol
+- (id) initWithCoder:(NSCoder *) decoder
+{
+ self = [super init];
+ if ((self) && ([decoder allowsKeyedCoding])) {
+ NSString *theClassName = [decoder decodeObjectForKey:@"MCPvalueClassName"];
+
+ classDescription = [decoder decodeObjectForKey:@"MCPclassDescription"];
+ [self setName:[decoder decodeObjectForKey:@"MCPname"]];
+ if (theClassName) {
+ [self setValueClass:NSClassFromString(theClassName)];
+ }
+ [self setInternalType:[decoder decodeObjectForKey:@"MCPinternalType"]];
+ [self setExternalName:[decoder decodeObjectForKey:@"MCPexternalName"]];
+ [self setExternalType:[decoder decodeObjectForKey:@"MCPexternalType"]];
+ [self setWidth:(unsigned int)[decoder decodeInt32ForKey:@"MCPwidth"]];
+ [self setAllowsNull:[decoder decodeBoolForKey:@"MCPallowsNull"]];
+ [self setAutoGenerated:[decoder decodeBoolForKey:@"MCPautoGenerated"]];
+ [self setIsPartOfKey:[decoder decodeBoolForKey:@"MCPisPartOfKey"]];
+ [self setIsPartOfIdentity:[decoder decodeBoolForKey:@"MCPisPartOfIdentity"]];
+ [self setHasAccessor:[decoder decodeBoolForKey:@"MCPhasAccessor"]];
+ [self setDefaultValue:[decoder decodeObjectForKey:@"MCPdefaultValue"]];
+// Not sure that the next line is working (getting an array holding weak references), hence doing the thing expelcitly:
+// relations = [[decoder decodeObjectForKey:@"MCPrelations"] retain];
+// relations = (NSMutableArray *)(CFArrayCreateMutable (kCFAllocatorDefault, 0, NULL));
+// [relations addObjectsFromArray:[decoder decodeObjectForKey:@"MCPrelations"]];
+ joins = [[NSMutableArray alloc] init]; // Will be filled in when the relations are read in.
+ }
+ else {
+ NSLog(@"For some reason, unable to decode MCPAttribute from the coder!!!");
+ }
+// NSLog(@"MAKING a new object : %@", self);
+ return self;
+}
+
+- (void) encodeWithCoder:(NSCoder *) encoder
+{
+ NSString *theValueClassName;
+
+ if (! [encoder allowsKeyedCoding]) {
+ NSLog(@"In MCPAttribute -encodeWithCoder : Unable to encode to a non-keyed encoder!!, will not perform encoding!!");
+ return;
+ }
+// theValueClassName = (valueClass) ? [valueClass className] : nil;
+ theValueClassName = (valueClass) ? NSStringFromClass(valueClass) : nil;
+ [encoder encodeObject:[self classDescription] forKey:@"MCPclassDescription"];
+ [encoder encodeObject:[self name] forKey:@"MCPname"];
+ if (theValueClassName) {
+ [encoder encodeObject:theValueClassName forKey:@"MCPvalueClassName"];
+ }
+ [encoder encodeObject:[self internalType] forKey:@"MCPinternalType"];
+ [encoder encodeObject:[self externalName] forKey:@"MCPexternalName"];
+ [encoder encodeObject:[self externalType] forKey:@"MCPexternalType"];
+ [encoder encodeInt32:(int32_t)[self width] forKey:@"MCPwidth"];
+ [encoder encodeBool:[self allowsNull] forKey:@"MCPallowsNull"];
+ [encoder encodeBool:[self autoGenerated] forKey:@"MCPautoGenerated"];
+ [encoder encodeBool:[self isPartOfKey] forKey:@"MCPisPartOfKey"];
+ [encoder encodeBool:[self isPartOfIdentity] forKey:@"MCPisPartOfIdentity"];
+ [encoder encodeBool:[self hasAccessor] forKey:@"MCPhasAccessor"];
+ [encoder encodeObject:[self defaultValue] forKey:@"MCPdefaultValue"];
+// [encoder encodeObject:relations forKey:@"MCPrelation"];
+ // We don't have to save the joins here ... the joins are saving there attributes.
+ // The links are recreated when the joins are decoded.
+}
+
+#pragma mark Setters
+- (void) setName:(NSString *) iName
+{
+ if (iName != name) {
+ [name release];
+ name = [iName retain];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setValueClass:(Class) iValueClass
+{
+ if (iValueClass != valueClass) {
+ valueClass = iValueClass;
+ if (valueClass) { // Not nil : set the internalType accrodingly.
+ // [internalType release];
+ // internalType = [[valueClass className] copy];
+// [self setValue:[NSString stringWithString:[valueClass className]] forKey:@"internalType"];
+ [self setValue:[NSString stringWithString:NSStringFromClass(valueClass)] forKey:@"internalType"];
+ }
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setInternalType:(NSString *) iInternalType
+{
+ if (iInternalType != internalType) {
+ [internalType release];
+ internalType = [iInternalType retain];
+ if ([MCPRecognisedInternalType containsObject:internalType]) {
+ [self setValueClass:NSClassFromString(internalType)];
+// By itself does NOT provide observers the update.
+// but see setKeys:triggerChangeNotificationsForDependentKey... (in +initialize).
+ }
+ else {
+ [self setValueClass:nil];
+ }
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setExternalType:(NSString *) iExternalType
+{
+ if (iExternalType != externalType) {
+ [externalType release];
+ externalType = [iExternalType retain];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setExternalName:(NSString *) iExternalName
+{
+ if (iExternalName != externalName) {
+ [externalName release];
+ externalName = [iExternalName retain];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setWidth:(unsigned int) iWidth
+{
+ if (iWidth != width) {
+ width = iWidth;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setAllowsNull:(BOOL) iAllowsNull
+{
+ if (iAllowsNull != allowsNull) {
+ allowsNull = iAllowsNull;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setAutoGenerated:(BOOL) iAutoGenerated
+{
+ if (iAutoGenerated != autoGenerated) {
+ autoGenerated = iAutoGenerated;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setIsPartOfKey:(BOOL) iIsPartOfKey
+{
+ if (iIsPartOfKey != isPartOfKey) {
+ isPartOfKey = iIsPartOfKey;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setIsPartOfIdentity:(BOOL) iIsPartOfIdentity
+{
+ if (iIsPartOfIdentity != isPartOfIdentity) {
+ isPartOfIdentity = iIsPartOfIdentity;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setHasAccessor:(BOOL) iHasAccessor
+{
+ if (iHasAccessor != hasAccessor) {
+ hasAccessor = iHasAccessor;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setDefaultValue:(id) iDefaultValue
+{
+ if (iDefaultValue != defaultValue) {
+ [defaultValue release];
+ defaultValue = [iDefaultValue retain];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) insertObject:(MCPJoin *) iJoin inJoinsAtIndex:(unsigned int) index
+{
+ [joins insertObject:iJoin atIndex:index];
+}
+
+- (void) removeObjectFromJoinsAtIndex:(unsigned int) index
+{
+ [joins removeObjectAtIndex:index];
+}
+
+/*
+- (void) addRelation:(MCPRelation *) iRelation
+{
+// Following implementation make sure that a given relation is only added once... but I don't see the reason for that to be true.
+ /* if (NSNotFound == [relations indexOfObjectIdenticalTo:iRelation]) {
+ [relations addObject:iRelation];
+ }
+ *//*
+ [relations addObject:iRelation];
+}
+
+- (void) removeRelation:(MCPRelation *) iRelation
+{
+// Following implementation needs only one reference to a given relation to be working properly (not true)
+// [relations removeObjectIdenticalTo:iRelation];
+ unsigned int i;
+
+ i = [relations indexOfObjectIdenticalTo:iRelation];
+ if (NSNotFound != i) {
+ [relations removeObjectAtIndex:i];
+ }
+// If the relation is there more than once, remove it only once.
+}
+*/
+
+#pragma mark Getters
+- (MCPClassDescription *) classDescription
+{
+ return classDescription;
+}
+
+- (NSString *) name
+{
+ return name;
+}
+
+- (Class) valueClass
+{
+ return valueClass;
+}
+
+- (NSString *) valueClassName
+{
+ return NSStringFromClass(valueClass);
+}
+
+- (NSString *) internalType
+{
+ return internalType;
+}
+
+- (NSString *) externalName
+{
+ return externalName;
+}
+
+- (NSString *) externalType
+{
+ return externalType;
+}
+
+- (unsigned int) width
+{
+ return width;
+}
+
+- (BOOL) allowsNull
+{
+ return allowsNull;
+}
+
+- (BOOL) autoGenerated
+{
+ return autoGenerated;
+}
+
+- (BOOL) isPartOfKey
+{
+ return isPartOfKey;
+}
+
+- (BOOL) isPartOfIdentity
+{
+ return isPartOfIdentity;
+}
+
+- (BOOL) hasAccessor
+{
+ return hasAccessor;
+}
+
+- (id) defaultValue
+{
+ return defaultValue;
+}
+
+- (unsigned int) countOfJoins
+{
+ return [joins count];
+}
+
+- (MCPJoin *) objectInJoinsAtIndex:(unsigned int) index
+{
+ return (MCPJoin *)((NSNotFound != index) ? [joins objectAtIndex:index] : nil);
+}
+
+- (unsigned int) indexOfJoinIdenticalTo:(id) iJoin
+{
+ return [joins indexOfObjectIdenticalTo:iJoin];
+}
+
+#pragma mark Some general methods:
+- (BOOL) isEqual:(id) iObject
+// Equal to another attribute, if they have the same name and same class description.
+// Equal to a string (NSString), if the name of the attribute is equal to the string.
+{
+ if ([iObject isKindOfClass:[MCPAttribute class]]) {
+ MCPAttribute *theAttribute = (MCPAttribute *) iObject;
+
+ return ([name isEqualToString:[theAttribute name]]) && ([classDescription isEqual:[theAttribute classDescription]]);
+ }
+ if ([iObject isKindOfClass:[NSString class]]) {
+ return [name isEqualToString:(NSString *)iObject];
+ }
+ return NO;
+}
+
+#pragma mark For debugging the retain counting
+- (id) retain
+{
+ [super retain];
+ return self;
+}
+
+- (void) release
+{
+ [super release];
+ return;
+}
+
+@end
+
+@implementation MCPAttribute (Private)
+
+- (void)setValueClassName:(NSString *) iClassName
+{
+ if (NSClassFromString(iClassName) != valueClass) {
+ [self setValueClass:NSClassFromString(iClassName)];
+ }
+}
+
+@end