/** GSWAssociation.m - GSWeb: Class GSWAssociation Copyright (C) 1999-2004 Free Software Foundation, Inc. Written by: Manuel Guesdon Date: Jan 1999 $Revision$ $Date$ This file is part of the GNUstep Web Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. **/ #include "config.h" RCS_ID("$Id$") #include "GSWeb.h" #include "GSWKeyValueAssociation.h" #include "GSWConstantValueAssociation.h" #include "GSWBindingNameAssociation.h" #include #include #include #ifdef TCSDB #include #endif #if HAVE_GDL2 #include #endif static NSDictionary* localMinMaxDictionary=nil; static NSMutableDictionary* associationsHandlerClasses=nil; static NSLock* associationsLock=nil; static NSMutableArray* associationsLogsHandlerClasses=nil; //==================================================================== @implementation GSWAssociation +(void)initialize { if (self==[GSWAssociation class]) { associationsLock=[NSLock new]; if (!localMinMaxDictionary) { localMinMaxDictionary=[[NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithShort:SCHAR_MIN],@"SCHAR_MIN", [NSNumber numberWithShort:SCHAR_MAX],@"SCHAR_MAX", [NSNumber numberWithShort:UCHAR_MAX],@"UCHAR_MAX", [NSNumber numberWithShort:CHAR_MIN],@"CHAR_MIN", [NSNumber numberWithShort:CHAR_MAX],@"CHAR_MAX", [NSNumber numberWithShort:SHRT_MIN],@"SHRT_MIN", [NSNumber numberWithShort:SHRT_MAX],@"SHRT_MAX", [NSNumber numberWithUnsignedInt:0],@"USHRT_MIN", [NSNumber numberWithUnsignedInt:USHRT_MAX],@"USHRT_MAX", [NSNumber numberWithInt:INT_MIN],@"INT_MIN", [NSNumber numberWithInt:INT_MAX],@"INT_MAX", [NSNumber numberWithUnsignedInt:0],@"UINT_MIN", [NSNumber numberWithUnsignedInt:UINT_MAX],@"UINT_MAX", [NSNumber numberWithLong:LONG_MIN],@"LONG_MIN", [NSNumber numberWithLong:LONG_MAX],@"LONG_MAX", [NSNumber numberWithUnsignedLong:0],@"ULONG_MIN", [NSNumber numberWithUnsignedLong:ULONG_MAX],@"ULONG_MAX", #ifdef LONG_LONG_MAX [NSNumber numberWithLongLong:LONG_LONG_MIN],@"LONG_LONG_MIN", [NSNumber numberWithLongLong:LONG_LONG_MAX],@"LONG_LONG_MAX", #endif #ifdef ULONG_LONG_MAX [NSNumber numberWithUnsignedLongLong:0],@"ULONG_LONG_MIN", [NSNumber numberWithUnsignedLongLong:ULONG_LONG_MAX],@"ULONG_LONG_MAX", #endif [NSNumber numberWithFloat:FLT_MIN],@"FLOAT_MIN", [NSNumber numberWithFloat:FLT_MAX],@"FLOAT_MAX", [NSNumber numberWithFloat:DBL_MIN],@"DOUBLE_MIN", [NSNumber numberWithFloat:DBL_MAX],@"DOUBLE_MAX", nil,nil] retain]; }; }; }; //-------------------------------------------------------------------- +(void)dealloc { DESTROY(localMinMaxDictionary); DESTROY(associationsHandlerClasses); DESTROY(associationsLogsHandlerClasses); DESTROY(associationsLock); }; //-------------------------------------------------------------------- // init -(id)init { if ((self=[super init])) { }; return self; }; -(void)dealloc { DESTROY(_bindingName); DESTROY(_declarationName); DESTROY(_declarationType); [super dealloc]; }; //-------------------------------------------------------------------- -(id)copyWithZone:(NSZone*)zone; { GSWAssociation* clone = [[isa allocWithZone:zone] init]; clone->_debugEnabled=_debugEnabled; [clone setDebugEnabledForBinding:_bindingName declarationName:_declarationName declarationType:_declarationType]; return clone; }; //-------------------------------------------------------------------- -(NSString*)description { GSWLogAssertGood(self); LOGObjectFnNotImplemented(); //TODOFN return [super description]; }; //-------------------------------------------------------------------- -(NSString*)bindingName { return _bindingName; }; //-------------------------------------------------------------------- -(NSString*)declarationName { return _declarationName; }; //-------------------------------------------------------------------- -(NSString*)declarationType { return _declarationType; }; //-------------------------------------------------------------------- // isValueConstant -(BOOL)isValueConstant { //OK [self subclassResponsibility:_cmd]; return NO; }; //-------------------------------------------------------------------- // isValueSettable - (BOOL)isValueSettable { //OK [self subclassResponsibility:_cmd]; return NO; }; //-------------------------------------------------------------------- // setValue:inComponent: -(void)setValue:(id)value inComponent:(GSWComponent*)component { [self subclassResponsibility:_cmd]; }; //-------------------------------------------------------------------- // valueInComponent: -(id)valueInComponent:(GSWComponent*)component; { return [self subclassResponsibility:_cmd]; }; @end //==================================================================== @implementation GSWAssociation (GSWAssociationCreation) //-------------------------------------------------------------------- // associationWithKeyPath: +(GSWAssociation*)associationWithKeyPath:(NSString*)keyPath { //OK if (keyPath) { if ([keyPath hasPrefix:@"^"] || (!WOStrictFlag && [keyPath hasPrefix:@"~"])) return [[[GSWBindingNameAssociation alloc]initWithKeyPath:keyPath] autorelease]; else return [[[GSWKeyValueAssociation alloc]initWithKeyPath:keyPath] autorelease]; } else return nil; }; //-------------------------------------------------------------------- // associationWithValue: +(GSWAssociation*)associationWithValue:(id)value { //OK return [[[GSWConstantValueAssociation alloc]initWithValue:value] autorelease]; }; //-------------------------------------------------------------------- // associationFromString: //NDFN +(GSWAssociation*)associationFromString:(NSString*)string { GSWAssociation* assoc=nil; LOGClassFnStart(); NSDebugMLLog(@"associations",@"string=[%@]",string); if ([string length]<=0) assoc=[self associationWithValue:string]; else { NSString* trimmedString=[string stringByTrimmingSpaces]; if ([trimmedString isEqualToString:NSTYES]) { assoc=[self associationWithValue:GSWNumberYes]; NSDebugMLLog(@"associations",@"assoc=[%@]",assoc); } else if ([trimmedString isEqualToString:NSTNO]) { assoc=[self associationWithValue:GSWNumberNo]; NSDebugMLLog(@"associations",@"assoc=[%@]",assoc); } else if ([trimmedString hasPrefix:@"^"]) { assoc=[self associationWithKeyPath:trimmedString]; NSDebugMLLog(@"associations",@"assoc=[%@]",assoc); } else if ([trimmedString hasPrefix:@"\""]) { if ([trimmedString hasSuffix:@"\""]) { assoc=[self associationWithValue:[[trimmedString stringByDeletingPrefix:@"\""] stringByDeletingSuffix:@"\""]]; NSDebugMLLog(@"associations",@"assoc=[%@]",assoc); } else { ExceptionRaise(@"GSWAssociation",@"String '%@' start with a \" but doesn't finish with a \"", trimmedString); }; } else if ([trimmedString hasPrefix:@"\'"]) { if ([trimmedString hasSuffix:@"\'"]) { assoc=[self associationWithValue:[[trimmedString stringByDeletingPrefix:@"\'"] stringByDeletingSuffix:@"\'"]]; NSDebugMLLog(@"associations",@"assoc=[%@]",assoc); } else { ExceptionRaise(@"GSWAssociation",@"String '%@' start with a character ' but doesn't finish with a character '", trimmedString); }; } else if ([trimmedString hasPrefix:@"#"]) { NSString* numberString=[trimmedString stringByDeletingPrefix:@"#"]; //char* cString=[numberString lossyCString];//TODO const char* cString=[numberString cString];//TODO char* endPtr=NULL; int value=strtol(cString,&endPtr,16); NSDebugMLLog(@"associations",@"value=[%d]",value); if (endPtr && *endPtr) { ExceptionRaise(@"GSWAssociation",@"String '%@' start with a '#' but doesn't countain an hexadecimal number (on %dth Character)", trimmedString, (int)(endPtr-cString+1)); }; assoc=[self associationWithValue:GSWIntNumber(value)]; } else { NSNumber* limit=[localMinMaxDictionary objectForKey:trimmedString]; NSDebugMLLog(@"associations",@"limit=[%@]",limit); if (limit) { assoc=[self associationWithValue:limit]; NSDebugMLLog(@"associations",@"assoc=[%@]",assoc); } else { NSCharacterSet* cset=[NSCharacterSet characterSetWithCharactersInString:@"-+0123456789"]; NSRange firstCharRange=[trimmedString rangeOfCharacterFromSet:cset options:0 range:NSMakeRange(0,1)]; NSDebugMLLog(@"associations",@"firstCharRange.length=%d firstCharRange.location=%d ", firstCharRange.length,firstCharRange.location); if (firstCharRange.length==0 || firstCharRange.location!=0) { assoc=[self associationWithKeyPath:trimmedString]; NSDebugMLLog(@"associations",@"assoc=[%@]",assoc); } else { //char* cString=[trimmedString lossyCString];//TODO const char* cString=[trimmedString cString];//TODO char* endPtr=NULL; int value=strtol(cString,&endPtr,10); NSDebugMLLog(@"associations",@"value=[%d]",value); if (endPtr && *endPtr) { NSDebugMLLog(@"associations",@"endPtr=[%s]",endPtr); NSDebugMLLog(@"associations",@"value=[%d]",value); ExceptionRaise(@"GSWAssociation", @"String '%@' must be a good number", trimmedString); }; assoc=[self associationWithValue:GSWIntNumber(value)]; }; }; }; }; NSDebugMLLog(@"associations",@"assoc=[%@]",assoc); LOGClassFnStop(); return assoc; }; @end //==================================================================== @implementation GSWAssociation (GSWAssociationHandlers) //-------------------------------------------------------------------- +(void)setClasse:(Class)class forHandler:(NSString*)handler { LOGClassFnStart(); NSDebugMLLog(@"associations",@"class=%@",class); NSDebugMLLog(@"associations",@"handler=%@",handler); LoggedLockBeforeDate(associationsLock,GSW_LOCK_LIMIT); if (!associationsHandlerClasses) { if (class) associationsHandlerClasses=[NSMutableDictionary new]; }; if (class) [associationsHandlerClasses setObject:class forKey:handler]; else if (associationsHandlerClasses) [associationsHandlerClasses removeObjectForKey:handler]; LoggedUnlock(associationsLock); LOGClassFnStop(); }; //-------------------------------------------------------------------- +(void)addLogHandlerClasse:(Class)class { LOGClassFnStart(); NSDebugMLLog(@"associations",@"class=%@",class); LoggedLockBeforeDate(associationsLock,GSW_LOCK_LIMIT); if (!associationsLogsHandlerClasses) { if (class) associationsLogsHandlerClasses=[NSMutableArray new]; }; if (class) [associationsLogsHandlerClasses addObject:class]; LoggedUnlock(associationsLock); LOGClassFnStop(); }; //-------------------------------------------------------------------- +(void)removeLogHandlerClasse:(Class)class { LOGClassFnStart(); NSDebugMLLog(@"associations",@"class=%@",class); LoggedLockBeforeDate(associationsLock,GSW_LOCK_LIMIT); if (associationsHandlerClasses) { if (class) [associationsLogsHandlerClasses removeObject:class]; }; LoggedUnlock(associationsLock); LOGClassFnStop(); }; @end /* //==================================================================== @implementation GSWAssociation (GSWAssociationOldFn) //-------------------------------------------------------------------- // value -(id)value { GSWContext* context=[[GSWApplication application] context]; [self valueInComponent:GSWContext_component(context)]; }; //-------------------------------------------------------------------- // setValue:inComponent: //OldFn -(void)setValue:(id)value { GSWContext* context=[[GSWApplication application] context]; [self setValue:(id)value inComponent:GSWContext_component(context)]; }; @end */ //==================================================================== @implementation GSWAssociation (GSWAssociationA) //-------------------------------------------------------------------- -(BOOL)isImplementedForComponent:(NSObject*)component { return YES; }; @end //==================================================================== @implementation GSWAssociation (GSWAssociationB) //-------------------------------------------------------------------- -(NSString*)keyPath { //OK [self subclassResponsibility:_cmd]; return nil; }; //-------------------------------------------------------------------- -(void)logValue:(id)value forSet:(BOOL)set { if (_debugEnabled) { if (associationsLogsHandlerClasses) { LoggedLockBeforeDate(associationsLock,GSW_LOCK_LIMIT); NS_DURING { int i=0; Class class=Nil; int handlerCount=[associationsLogsHandlerClasses count]; NSString* debugDescription=[self debugDescription]; for(i=0;i0) { part=[keys objectAtIndex:0]; [keys removeObjectAtIndex:0]; if (retValue) { NSDebugMLLog(@"associations",@"object_get_class_name(retValue object)=%s", object_get_class_name(retValue)); } NSDebugMLLog(@"associations",@"part=%@",part); NSDebugMLLog(@"associations",@"part class=%@",NSStringFromClass([part class])); if ([part hasPrefix:@"\""]) { part=[part stringByDeletingPrefix:@"\""]; while([keys count]>0) { id tmpPart=[keys objectAtIndex:0]; [keys removeObjectAtIndex:0]; if ([tmpPart hasSuffix:@"\""]) { tmpPart=[tmpPart stringByDeletingSuffix:@"\""]; part=[part stringByAppendingFormat:@".%@",tmpPart]; break; } else part=[part stringByAppendingFormat:@".%@",tmpPart]; } } NSDebugMLLog(@"associations",@"part=%@",part); handlerClass=[associationsHandlerClasses objectForKey:part]; NSDebugMLLog(@"associations",@"_handlerClass=%@",handlerClass); if (handlerClass) retValue=[handlerClass processValueInObject:retValue forHandler:part forKeyPath:keys]; else if ([part isEqualToString:GSASK_Class]) { Class class=Nil; NSAssert2([keys count]>0,@"No class name for handler %@ in %@", GSASK_Class, keyPath); part=[keys objectAtIndex:0]; [keys removeObjectAtIndex:0]; NSDebugMLLog(@"associations",@"part=%@",part); class=NSClassFromString(part); NSAssert3(class>0,@"No class named %@ for handler %@ in %@", part, GSASK_Class, keyPath); if (class) retValue=class; else retValue=nil; } else if ([part isEqualToString:GSASK_Language]) { NSArray* languages=[[GSWApp _context] languages]; int count=[languages count]; id v=nil; int i=0; for(i=0;!v && i inObject: forKeyPath:currentCartArticle.color if (keyPath) { NSRange r = [keyPath rangeOfString: @"."]; if (r.length == 0) { tmpObject = object; tmpKey = keyPath; } else { NSString *key = [keyPath substringToIndex: r.location]; // NSString *path = [keyPath substringFromIndex: NSMaxRange(r)]; //[[self valueForKey: key] smartTakeValue: anObject // forKeyPath: path]; tmpObject = [object valueForKey: key]; tmpKey = [keyPath substringFromIndex: NSMaxRange(r)]; } //NSLog(@"GSWAssociation: tmpKey:%@ tmpObject:%@",tmpKey,tmpObject); if (tmpObject) //&& [object isKindOfClass:[GSWComponent class]] { NSException* exp = [tmpObject validateValue:&value forKey:tmpKey]; if (exp) { NSException* exception=nil; exception=[NSException exceptionWithName:@"EOValidationException" reason:[exp reason] userInfo:[NSDictionary dictionaryWithObjectsAndKeys: (value ? value : @"nil"),@"EOValidatedObjectUserInfoKey", keyPath,@"EOValidatedPropertyUserInfoKey", nil,nil]]; [object validationFailedWithException:exception value:value keyPath:keyPath]; } else { // no exception, set the value [tmpObject takeValue:value forKey:tmpKey]; } } } LOGClassFnStop(); } #else // GDL2 or GDL1 +(void)setValue:(id)value inComponent:(GSWComponent*)object forKeyPath:(NSString*)keyPath { LOGClassFnStart(); NSDebugMLLog(@"associations",@"GSWAssociation: setValue:%@",value); NSDebugMLLog(@"associations",@"value class:%@",[value class]); NSDebugMLLog(@"associations",@"value String class:%@",NSStringFromClass([value class])); NSDebugMLLog(@"associations",@"object String class:%@ superclass=%@", NSStringFromClass([object class]), NSStringFromClass([object superclass])); NSDebugMLLog(@"associations",@"GSWAssociation: keyPath:%@",keyPath); if ([keyPath length]==0) { [NSException raise:NSInvalidArgumentException format:@"No key path when setting value %@ in object of class %@", value,NSStringFromClass([object class])]; }; #if HAVE_GDL2 [object smartTakeValue:value forKeyPath:keyPath]; #else // no GDL2 NSMutableArray* keys=[[keyPath componentsSeparatedByString:@"."] mutableCopy]; id part=nil; id tmpObject=object; Class handlerClass=Nil; NSAssert(tmpObject,@"No Object"); while(tmpObject && [keys count]>0) { part=[keys objectAtIndex:0]; [keys removeObjectAtIndex:0]; NSDebugMLLog(@"associations",@"part=%@",part); NSDebugMLLog(@"associations",@"part class=%@",NSStringFromClass([part class])); if ([part hasPrefix:@"\""]) { part=[part stringByDeletingPrefix:@"\""]; while([keys count]>0) { id tmpPart=[keys objectAtIndex:0]; [keys removeObjectAtIndex:0]; if ([tmpPart hasSuffix:@"\""]) { tmpPart=[tmpPart stringByDeletingSuffix:@"\""]; part=[part stringByAppendingFormat:@".%@",tmpPart]; break; } else part=[part stringByAppendingFormat:@".%@",tmpPart]; } } NSDebugMLLog(@"associations",@"part=%@",part); handlerClass=[associationsHandlerClasses objectForKey:part]; NSDebugMLLog(@"associations",@"handlerClass=%@",handlerClass); if (handlerClass) { tmpObject=[handlerClass processSetValue:value inObject:tmpObject forHandler:part forKeyPath:keys]; } else { if ([keys count]>0) { if ([part isEqualToString:GSASK_Class]) { Class class=Nil; NSAssert2([keys count]>0,@"No class name for handler %@ in %@", GSASK_Class, keyPath); part=[keys objectAtIndex:0]; [keys removeObjectAtIndex:0]; NSDebugMLLog(@"associations",@"part=%@",part); class=NSClassFromString(part); NSAssert3(class>0,@"No class named %@ for handler %@ in %@", part, GSASK_Class, keyPath); if (class) tmpObject=class; else tmpObject=nil; } else { tmpObject=[tmpObject valueForKey:part]; } } else { GSWLogAssertGood(tmpObject); [tmpObject takeValue:value forKey:part]; #ifdef HAVE_GDL2 NSDebugMLLog(@"associations",@"object class=%@",[object class]); NSDebugMLLog(@"associations",@"tmpObject class=%@",[tmpObject class]); // Turbocat if (tmpObject && [tmpObject isKindOfClass:[GSWComponent class]]) { NSException* exp = [tmpObject validateValue:&value forKey:part]; if (exp) { NSException* exception=nil; exception=[NSException exceptionWithName:@"EOValidationException" reason:[exp reason] userInfo:[NSDictionary dictionaryWithObjectsAndKeys: (value ? value : @"nil"),@"EOValidatedObjectUserInfoKey", keyPath,@"EOValidatedPropertyUserInfoKey", nil,nil]]; [object validationFailedWithException:exception value:value keyPath:keyPath]; } } #endif tmpObject=nil; }; }; }; #endif LOGClassFnStop(); }; #endif @end //=================================================================================== @implementation NSDictionary (GSWAssociation) -(BOOL)isAssociationDebugEnabledInComponent:(GSWComponent*)component { BOOL debug=NO; GSWAssociation* debugAssociation=[self objectForKey:@"GSWDebug"]; if (debugAssociation) { id value=[debugAssociation valueInComponent:component]; debug=boolValueWithDefaultFor(value,NO); }; return debug; }; -(void)associationsSetDebugEnabled { NSEnumerator* enumerator=nil; id key=nil; id association=nil; LOGObjectFnStart(); enumerator = [self keyEnumerator]; while ((key = [enumerator nextObject])) { NSDebugMLLog(@"associations",@"key=%@",key); association=[self objectForKey:key]; [association setDebugEnabledForBinding:@"" declarationName:key declarationType:@""]; //TODO }; LOGObjectFnStop(); }; -(void)associationsSetValuesFromObject:(id)from inObject:(id)to { NSEnumerator *enumerator = nil; id key=nil; id varValue=nil; id var=nil; LOGObjectFnStart(); NSDebugMLLog(@"associations",@"from=%@",from); NSDebugMLLog(@"associations",@"to=%@",to); enumerator = [self keyEnumerator]; while ((key = [enumerator nextObject])) { NSDebugMLLog(@"associations",@"key=%@",key); /* NSAssert2([key isKindOfClass:[GSWAssociation class]], @"key is not an GSWAssociation but a %@: %@", [key class], key);*/ var=[self objectForKey:key]; NSDebugMLLog(@"associations",@"var=%@",var); /* NSAssert2([var isKindOfClass:[GSWAssociation class]], @"Variable is not an GSWAssociation but a %@: %@", [var class], var);*/ if ([var isKindOfClass:[GSWAssociation class]]) varValue=[var valueInComponent:from]; else varValue=var; NSDebugMLLog(@"associations",@"varValue=%@",varValue); if (![key isKindOfClass:[GSWAssociation class]]) key=[GSWAssociation associationWithKeyPath:key]; [key setValue:varValue inComponent:to]; }; LOGObjectFnStop(); }; //-------------------------------------------------------------------- -(NSDictionary*)associationsWithoutPrefix:(NSString*)prefix removeFrom:(NSMutableDictionary*)removeFrom { NSMutableDictionary* newAssociation=nil; NSEnumerator *enumerator = nil; id key=nil; id varKey=nil; id varKeyAssociation=nil; id value=nil; LOGObjectFnStart(); newAssociation=(NSMutableDictionary*)[NSMutableDictionary dictionary]; enumerator = [self keyEnumerator]; while ((key = [enumerator nextObject])) { NSDebugMLLog(@"associations",@"key=%@",key); if ([key hasPrefix:prefix]) { value=[self objectForKey:key]; NSDebugMLLog(@"associations",@"value=%@",value); varKey=[key stringByDeletingPrefix:prefix]; NSDebugMLLog(@"associations",@"varKey=%@",varKey); varKeyAssociation=[GSWAssociation associationWithKeyPath:varKey]; NSDebugMLLog(@"associations",@"varKeyAssociation=%@",varKeyAssociation); [newAssociation setObject:value forKey:varKeyAssociation]; [removeFrom removeObjectForKey:key]; }; }; newAssociation=[NSDictionary dictionaryWithDictionary:newAssociation]; LOGObjectFnStop(); return newAssociation; }; //-------------------------------------------------------------------- -(NSDictionary*)dictionaryByReplacingStringsWithAssociations { NSMutableDictionary* newDictionary=[NSMutableDictionary dictionary]; NSEnumerator* enumerator=[self keyEnumerator]; id key=nil; id value=nil; id newValue=nil; while ((key=[enumerator nextObject])) { value=[self objectForKey:key]; NSDebugMLog(@"key=%@ value=%@",key,value); if ([value isKindOfClass:[NSString class]]) { newValue=[GSWAssociation associationFromString:value]; NSAssert(newValue,@"Nil value"); } else if ([value isKindOfClass:[NSArray class]]) { newValue=[value arrayByReplacingStringsWithAssociations]; NSAssert(newValue,@"Nil value"); } else if ([value isKindOfClass:[NSDictionary class]]) { newValue=[value dictionaryByReplacingStringsWithAssociations]; NSAssert(newValue,@"Nil value"); } else newValue=value; [newDictionary setObject:newValue forKey:key]; }; return [NSDictionary dictionaryWithDictionary:newDictionary]; }; @end //=================================================================================== @implementation NSArray (GSWAssociation) -(NSArray*)arrayByReplacingStringsWithAssociations { NSMutableArray* newArray=[NSMutableArray array]; int count=[self count]; int i=0; id value=nil; id newValue=nil; for(i=0;i