Re: Dynamically altering external names for Entities

Eric Bergerson <[email protected]> Sun, 11 May 2003 14:36:02 -0400
Newsgroups gmane.comp.web.webobjects.eof
Message-ID <104204037.1052663762@[10.2.1.200]>
Mark,
	It was a pleasure speaking with you.  I hope the solution I am using works 
for you.  I am posting this to share the solution with the other readers of 
this list.

	I agree with Chuck Hill, EOF was not designed to do this.  However, give a 
good reason to do it (as I have) here is how I did it.

I make a bunch of template entities that go together into a sub-schema of 
my overall schema.  These are the entities that I need to reproduce for 
different back-end tables.  I then clone those entities and add them back 
in to the model.  I associate the cloned entities together in a container 
class, just to get a handle on the set of entities needed for a particular 
user or purpose.  In my case it looks something like this:

I have template entities Candidate, Match, Master, of which Match is the 
many2many table between Candidate and Master.  These are the templates.  I 
have a container class called EntitySet that
holds a base name for the set of entities, and has functionality to be
able to generate unique entity names (and external names) for the different 
entities from
the base name.  I then clone the template entities, with the new unique 
names for the entities, add it back into the model, and then pass the 
EntitySet around into different "sessions" to identify the entities to use 
as the "candidate", "match" and "master" for that session.

Clearly, the key is how you "clone" the entities. The first problem
you face is in copying the entity, it doesn't have any obvious mechanism 
for making a copy of itself.  The second problem is in making
sure all references to the entity name, that you are changing to the new 
unique name, are replaced.  These references are in the entity itself, as 
well as relationships all over the model.  I guess you could
just write code that makes a new entity, and then copies the entire state 
of the source entity to the new entity, but I am not sure that would 
completely work, since there are hidden relationships that may not get 
filled out correctly.  Plus, I am too lazy for that.

I solved both issues using the plist representation of the entities.  I 
terate through each of the entities extract a plist representation of the 
entity  (EOEntity.encodeIntoPropertyList(NSMutableDictionary).

Then I replace all values in the plist that match the entity name to the 
new entity name.  You have to write this code, which has to be a recursive
method that does a deep replace, as the values of the plist can be 
NSArrays, NSDictionaries, or Strings.

Then I build a new entity from the modifield property list 
(EOEntity(NSDictionary,EOModel). I set the externalName and className of 
the new entity to that of the template entity.  I also save all of the new 
entities and their
plists in arrays to be used in the next step.

Once all the new entities are built, I then iterate over the list of 
entities adding them to the model (EOModel.addEntity(EOEntity)).

Lastly, I iterate over the new entities one more time.  This time I send 
each one EOEntity.awakeWithPropertyList(NSDictionary), passing in
the plist that was used to build each new EOEntity.

I don't remember exactly why I do this in three loops instead of inside 
one, but I believe it didn't work any other way.  I don't think you want to 
add the entities to the model, until they are all build, and you definitely 
don't want to awake them until they are all in the model.

Now, where you used to have Candidate, Match, and Master, you can now have
Candidate_ForSomePurpose_1, Match_ForSomePurpose_1, 
Master_ForSomePurpose_1.  Of course, I don't think the model mechanism was 
meant to be huge, so I wouldn't make a huge amount of entities in one 
model, but for a reasonable number, this has worked well for me.

I hope this works for you.  If not, maybe I forgot to mention something, so 
if you have any questions, feel free to write or call.  I hope this helps.

Sincerely,


Eric Bergerson
Objective Technologies, Inc.
Phone: 718 805 6574


--On Friday, May 09, 2003 12:15 PM -0500 Mark Morris <[email protected]> wrote:

> Hello!  I've been poking around the docs and haven't found a good
> solution to something I think should be quite do-able.  I'm working with
> a schema where there are many multiple instances of the same tables, just
> with different names and data.  You typically only work with one "set" of
> these tables at a time, so:  I want to define just one set of entities in
> my EOModel, the use some WOSession variable to determine which actual
> external table names get built in the SQL.
>
> It's simple to access any EOModels, spin through and setExternalName on
> the appropriate entities, but I get the impression that's a global
> operation, affecting every WOSession, so I'd rather find a solution that
> affects the SQL generation directly.  I was also looking at a delegate on
> the EOAdaptorChannel, but among other things I wasn't clear on how to
> make sure the delegate get set on *all* of the adaptor channels the app
> might create.  After that I might be able to get hold of the
> EOSQLExpression, but I'm not yet sure how to alter that and continue the
> processing.
>
> Thanks for any help!  :-)
>
> -- Mark
>
> _______________________________________________
> EOF mailing list
> [email protected]
> http://www.omnigroup.com/mailman/listinfo/eof