GNUstep Core Data  0.1
NSEntityDescription.m
00001 /* Implementation of the NSEntityDescription class for the GNUstep
00002    Core Data framework.
00003    Copyright (C) 2005 Free Software Foundation, Inc.
00004 
00005    Written by:  Saso Kiselkov <diablos@manga.sk>
00006    Date: August 2005
00007 
00008    This file is part of the GNUstep Core Data framework.
00009 
00010    This library is free software; you can redistribute it and/or
00011    modify it under the terms of the GNU Lesser General Public
00012    License as published by the Free Software Foundation; either
00013    version 2.1 of the License, or (at your option) any later version.
00014 
00015    This library is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018    Lesser General Public License for more details.
00019 
00020    You should have received a copy of the GNU Lesser General Public
00021    License along with this library; if not, write to the Free
00022    Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
00023  */
00024 
00025 #import "CoreDataHeaders.h"
00026 
00027 // Ensures the entity can be edited. Raises an NSGenericException
00028 // if the passed model is not nil and is not editable, with a reason
00029 // set to `reason'.
00030 static inline void EnsureEntityEditable(NSManagedObjectModel * model,
00031                                         NSString * reason)
00032 {
00033   if (model != nil && [model _isEditable] == NO)
00034     {
00035       [NSException raise: NSGenericException format: reason];
00036     }
00037 }
00038 
00039 
00040 @implementation NSEntityDescription
00041 
00042 
00043 - (NSDictionary *) _filteredPropertiesOfClass: (Class) aClass
00044 {
00045   NSMutableDictionary * dict;
00046   NSEnumerator * e;
00047   NSPropertyDescription * property;
00048 
00049   dict = [NSMutableDictionary dictionaryWithCapacity: [_properties count]];
00050   e = [_properties objectEnumerator];
00051   while ((property = [e nextObject]) != nil)
00052     {
00053       if (aClass == Nil || [property isKindOfClass: aClass])
00054         {
00055           [dict setObject: property forKey: [property name]];
00056         }
00057     }
00058 
00059   return [[dict copy] autorelease];
00060 }
00061 
00062 - (NSDictionary *) _fetchedPropertiesByName
00063 {
00064         return [self _filteredPropertiesOfClass: [NSFetchedPropertyDescription
00065                 class]];
00066 }
00067 
00068 + (NSEntityDescription *) entityForName: (NSString *) entityName
00069                  inManagedObjectContext: (NSManagedObjectContext *) ctxt
00070 {
00071   return [[[[ctxt persistentStoreCoordinator] managedObjectModel]
00072     entitiesByName] objectForKey: entityName];
00073 }
00074 
00075 + (id) insertNewObjectForEntityForName: (NSString *) anEntityName
00076                 inManagedObjectContext: (NSManagedObjectContext *) aContext
00077 {
00078   NSEntityDescription * entity;
00079   Class entityClass;
00080   NSManagedObjectModel * model;
00081 
00082   model = [[aContext persistentStoreCoordinator] managedObjectModel];
00083   entity = [[model entitiesByName] objectForKey: anEntityName];
00084 
00085   entityClass = NSClassFromString([entity managedObjectClassName]);
00086 
00087   return [[[entityClass alloc]
00088     initWithEntity: entity insertIntoManagedObjectContext: aContext]
00089     autorelease];
00090 }
00091 
00092 - (void) dealloc
00093 {
00094   TEST_RELEASE(_name);
00095 
00096   // let go of our properties
00097   [_properties makeObjectsPerformSelector: @selector(_setEntity:)
00098                                withObject: nil];
00099   TEST_RELEASE(_properties);
00100 
00101   TEST_RELEASE(_userInfo);
00102   TEST_RELEASE(_managedObjectClassName);
00103 
00104   [_subentities makeObjectsPerformSelector: @selector(setSuperentity:)
00105                                 withObject: nil];
00106 
00107   TEST_RELEASE(_subentities);
00108 
00109   [super dealloc];
00110 }
00111 
00112 
00113 
00114 - (NSString *) name
00115 {
00116   return _name;
00117 }
00118 
00119 - (void) setName: (NSString *) aName
00120 {
00121   EnsureEntityEditable(_model, _(@"Tried to set the name of an "
00122                                  @"entity alredy in use."));
00123   ASSIGN(_name, aName);
00124 }
00125 
00126 
00127 
00128 - (NSManagedObjectModel *) managedObjectModel
00129 {
00130   return _model;
00131 }
00132 
00133 
00134 
00135 - (NSString *) managedObjectClassName
00136 {
00137   return _managedObjectClassName;
00138 }
00139 
00140 - (void) setManagedObjectClassName: (NSString *) aName
00141 {
00142   EnsureEntityEditable(_model, _(@"Tried to set the managed object "
00143                                  @"class name of an entity already in use"));
00144   ASSIGN(_managedObjectClassName, aName);
00145 }
00146 
00147 
00148 
00149 - (BOOL) isAbstract
00150 {
00151   return _abstract;
00152 }
00153 
00154 - (void) setAbstract: (BOOL) flag
00155 {
00156   EnsureEntityEditable(_model, _(@"Tried to set abstractness "
00157                                  @"of an entity already in use"));
00158   _abstract = flag;
00159 }
00160 
00165 - (BOOL) _isSubentityOfEntity: (NSEntityDescription *) otherEntity
00166 {
00167   NSEntityDescription * entity;
00168 
00169   for (entity = self; entity != nil; entity = [entity superentity])
00170     {
00171       if ([entity isEqual: otherEntity])
00172         {
00173           return YES;
00174         }
00175     }
00176 
00177   return NO;
00178 }
00179 
00180 - (NSDictionary *) subentitiesByName
00181 {
00182   NSMutableDictionary * dict;
00183   NSEnumerator * e;
00184   NSEntityDescription * subentity;
00185 
00186   dict = [NSMutableDictionary dictionaryWithCapacity: [_subentities count]];
00187   e = [_subentities objectEnumerator];
00188   while ((subentity = [e nextObject]) != nil)
00189     {
00190       [dict setObject: subentity forKey: [subentity name]];
00191     }
00192 
00193   return [[dict copy] autorelease];
00194 }
00195 
00196 - (NSArray *) subentities
00197 {
00198   return _subentities;
00199 }
00200 
00201 - (void) setSubentities: (NSArray *) someEntities
00202 {
00203   EnsureEntityEditable(_model, _(@"Tried to set sub-entities of an entity "
00204                                  @"already in use"));
00205   ASSIGN(_subentities, [[someEntities copy] autorelease]);
00206 }
00207 
00208 
00209 - (NSEntityDescription *) superentity
00210 {
00211   return _superentity;
00212 }
00213 
00214 - (void) _setSuperentity: (NSEntityDescription *) entity
00215 {
00216   EnsureEntityEditable(_model, _(@"Tried to set super-entity of an entity "
00217                                  @"already in use"));
00218   _superentity = entity;
00219 }
00220 
00221 
00222 
00223 - (NSDictionary *) propertiesByName
00224 {
00225   return [self filteredPropertiesOfClass: Nil];
00226 }
00227 
00228 - (NSArray *) properties
00229 {
00230   return _properties;
00231 }
00232 
00233 - (void) setProperties: (NSArray *) someProperties
00234 {
00235   EnsureEntityEditable(_model, _(@"Tried to set properties "
00236                                  @"of an entity already in use"));
00237   ASSIGN(_properties, [[someProperties copy] autorelease]);
00238   [_properties makeObjectsPerformSelector: @selector(_setEntity:)
00239                                withObject: self];
00240 }
00241 
00242 - (NSDictionary *) userInfo
00243 {
00244   return _userInfo;
00245 }
00246 
00247 - (void) setUserInfo: (NSDictionary *) userInfo
00248 {
00249   EnsureEntityEditable(_model, _(@"Tried to set properties "
00250                                  @"of an entity already in use"));
00251   ASSIGN(_userInfo, [[userInfo copy] autorelease]);
00252 }
00253 
00254 
00255 
00256 - (NSDictionary *) attributesByName
00257 {
00258   return [self _filteredPropertiesOfClass: [NSAttributeDescription class]];
00259 }
00260 
00261 - (NSDictionary *) relationshipsByName
00262 {
00263   return [self _filteredPropertiesOfClass: [NSRelationshipDescription class]];
00264 }
00265 
00266 - (NSArray *) relationshipsWithDestinationEntity:
00267   (NSEntityDescription *) destEntity
00268 {
00269   NSMutableArray * array;
00270   NSEnumerator * e;
00271   NSRelationshipDescription * relationship;
00272   Class relationshipClass;
00273 
00274   array = [NSMutableArray arrayWithCapacity: [_properties count]];
00275   relationshipClass = [NSRelationshipDescription class];
00276 
00277   e = [_properties objectEnumerator];
00278   while ((relationship = [e nextObject]) != nil)
00279     {
00280       if ([relationship isKindOfClass: relationshipClass] &&
00281           [relationship destinationEntity] == destEntity)
00282         {
00283           [array addObject: relationship];
00284         }
00285     }
00286 
00287   return [[array copy] autorelease];
00288 }
00289 
00290 // NSCopying
00291 
00292 - (id) copyWithZone: (NSZone *) aZone
00293 {
00294   NSEntityDescription * entity;
00295 
00296   entity = [[NSEntityDescription allocWithZone: aZone] init];
00297 
00298   [entity setName: _name];
00299   [entity setManagedObjectClassName: _managedObjectClassName];
00300   [entity setAbstract: _abstract];
00301   [entity setSubentities: _subentities];
00302   [entity _setSuperentity: _superentity];
00303 
00304   return entity;
00305 }
00306 
00307 // NSCoding
00308 
00309 - (id) initWithCoder: (NSCoder *) coder
00310 {
00311   if ((self = [self init]))
00312     {
00313       if ([coder allowsKeyedCoding])
00314         {
00315           ASSIGN(_name, [coder decodeObjectForKey: @"Name"]);
00316           _abstract = [coder decodeBoolForKey: @"Abstract"];
00317           ASSIGN(_managedObjectClassName,
00318             [coder decodeObjectForKey: @"ManagedObjectClassName"]);
00319           ASSIGN(_properties, [coder decodeObjectForKey: @"Properties"]);
00320           ASSIGN(_userInfo, [coder decodeObjectForKey: @"UserInfo"]);
00321           ASSIGN(_subentities, [coder decodeObjectForKey: @"SubEntities"]);
00322           _superentity = [coder decodeObjectForKey: @"SuperEntity"];
00323           _model = [coder decodeObjectForKey: @"ManagedObjectModel"];
00324           _modelRefCount = [coder decodeIntForKey: @"ModelReferenceCount"];
00325         }
00326       else
00327         {
00328           ASSIGN(_name, [coder decodeObject]);
00329           [coder decodeValueOfObjCType: @encode(BOOL) at: &_abstract];
00330           ASSIGN(_managedObjectClassName, [coder decodeObject]);
00331           ASSIGN(_properties, [coder decodeObject]);
00332           ASSIGN(_userInfo, [coder decodeObject]);
00333           ASSIGN(_subentities, [coder decodeObject]);
00334           _superentity = [coder decodeObject];
00335           _model = [coder decodeObject];
00336           [coder decodeValueOfObjCType: @encode(unsigned int)
00337                                     at: &_modelRefCount];
00338         }
00339 
00340     }
00341         return self;
00342 }
00343 
00344 - (void) encodeWithCoder: (NSCoder *) coder
00345 {
00346   if ([coder allowsKeyedCoding])
00347     {
00348       [coder encodeObject: _name forKey: @"Name"];
00349       [coder encodeBool: _abstract forKey: @"Abstract"];
00350       [coder encodeObject: _managedObjectClassName
00351                    forKey: @"ManagedObjectClassName"];
00352       [coder encodeObject: _properties forKey: @"Properties"];
00353       [coder encodeObject: _userInfo forKey: @"UserInfo"];
00354       [coder encodeObject: _subentities forKey: @"SubEntities"];
00355       [coder encodeObject: _superentity forKey: @"SuperEntity"];
00356       [coder encodeObject: _model forKey: @"ManagedObjectModel"];
00357       [coder encodeInt: _modelRefCount forKey: @"ModelReferenceCount"];
00358     }
00359   else
00360     {
00361       [coder encodeObject: _name];
00362       [coder encodeValueOfObjCType: @encode(BOOL) at: &_abstract];
00363       [coder encodeObject: _managedObjectClassName];
00364       [coder encodeObject: _properties];
00365       [coder encodeObject: _userInfo];
00366       [coder encodeObject: _subentities];
00367       [coder encodeObject: _superentity];
00368       [coder encodeObject: _model];
00369       [coder encodeValueOfObjCType: @encode(unsigned int)
00370                                 at: &_modelRefCount];
00371     }
00372 }
00373 
00389 - (void) _addReferenceToManagedObjectModel: (NSManagedObjectModel *) aModel
00390 {
00391   // don't allow re-setting the owner like this
00392   NSAssert(aModel != nil && (_model == nil || _model == aModel),
00393     _(@"Attempted to forcefully change the reference from an entity "
00394       @"to it's managed object model owner or ``nil'' model argument "
00395       @"passed."));
00396 
00397   _model = aModel;
00398   _modelRefCount++;
00399 }
00400 
00401 - (void) _removeReferenceToManagedObjectModel: (NSManagedObjectModel *) aModel
00402 {
00403   NSAssert(_model == aModel, _(@"Attempted to forcefully remove the "
00404     @"reference from an entity to it's managed object model by some other, "
00405     @"unrelated model."));
00406   NSAssert(_modelRefCount > 0, _(@"Attempted to underflow the "
00407     @"reference count from an entity to it's managed object model."));
00408 
00409   _modelRefCount--;
00410   if (_modelRefCount == 0)
00411     {
00412       _model = nil;
00413     }
00414 }
00415 
00416 @end