PDA

View Full Version : Managed Objects


Novo
05-15-2007, 06:42 PM
Example of Usage:


function onCreated()
{
join("managedobjectcontext");
this.entities = null;

// Setting up Party Variables
temp.eparty = loadEntity( "Party" );
if ( temp.eparty == null )
{
temp.eparty = createEntity( "Party" );
// Setting up variable configurations... { inverseRelationship, Multiple Items?, Delete Rule }
temp.eparty.setValueForKey( {null, false, null }, "configName" );
temp.eparty.setValueForKey( {null, false, null }, "configLeader" );
temp.eparty.setValueForKey( {"Party", true, "Cascade" }, "configRanks" );

temp.eparty.setValueForKey( "Party", "customClass" ); // Maybe you have special implementations! This joins class "Party" when creating a new instance!
// Adding a bind to a key... Members now is Ranks.Members
temp.eparty.addValueForKey( {"Members", "Ranks.Members"}, "binds" );
// There is also dependencies... But those are still a little complicated.
// They'll be further elaborated in future releases.
// temp.eparty.addDependency( "Members", "Ranks.Members" ); // It'll be something like that.
}

temp.erank = loadEntity( "Rank" );
if ( temp.erank == null )
{
temp.erank = createEntity( "Rank" );
temp.erank.setValueForKey( {null, true, null}, "configMembers" );
temp.erank.setValueForKey( {null, null, null}, "configRankSyntax" );
temp.erank.setValueForKey( {null, null, null}, "configRankName" );
temp.erank.setValueForKey( {null, true, null}, "configRankRights" );
temp.erank.setValueForKey( {"Ranks", false, null}, "configParty" );
}

// Creating New Party and add two ranks, three members...
// Please Note that each time this is executed, a new party of the same name is created.
temp.mparty = temp.eparty.createManagedObject();
temp.mparty.setValueForKey( "Pluffy's Gang", "Name" );
temp.mparty.setValueForKey( "Pluffy", "Leader" );

temp.mrank = temp.erank.createManagedObject();
temp.mrank.setValueForKey( "Leader", "RankName" );
temp.mrank.setValueForKey( "King %s", "RankSyntax" );
temp.mrank.setValueForKey( {"add", "remove"}, "RankRights" );
temp.mrank.setValueForKey( null, "Members" );
temp.mrank.addValueForKey( "Pluffy", "Members" );
temp.mrank.addValueForKey( "Gerami", "Members" );
temp.mrank.setValueForKey( temp.mparty, "Party" );

temp.mrank = temp.erank.createManagedObject();
temp.mrank.setValueForKey( "Humble Servant", "RankName" );
temp.mrank.setValueForKey( "Slave %s", "RankSyntax" );
temp.mrank.setValueForKey( null, "RankRights" );
temp.mrank.setValueForKey( null, "Members" );
temp.mrank.addValueForKey( "Novo", "Members" );
temp.mrank.setValueForKey( temp.mparty, "Party" );

// Now lets use it!
// Showing Ranks
temp.ranks = temp.mparty.valueForKeyPath( "Ranks.RankName" );
echo( temp.ranks ); // returns: {"Leader", "Humble Servant"};

// Showing Members Divided By Rank
temp.membersByRank = temp.mparty.valueForKeyPath( "Members" );
echo( temp.membersByRank ); // returns {{"Pluffy", "Gerami"}, {"Novo"}};

// Showing all Members
temp.allMembers = null;
for ( temp.rank: temp.membersByRank )
temp.allMembers.addarray( temp.rank );
echo( temp.allMembers ); // returns {"Pluffy", "Gerami", "Novo" };

echo("===");
// Delete a Rank!
for ( temp.rank: temp.mparty.valueForKey( "Ranks" ) )
{
if ( temp.rank.valueForKey("RankName") != "Humble Servant" )
continue;

temp.erank.deleteManagedObject( temp.rank );
}

// Showing Ranks
temp.ranks = temp.mparty.valueForKeyPath( "Ranks.RankName" );
echo( temp.ranks ); // returns: {"Leader"};

// Showing Members Divided By Rank
temp.membersByRank = temp.mparty.valueForKey( "Members" );
echo( temp.membersByRank ); // returns {{"Pluffy", "Gerami"}};

// Showing all Members
temp.allMembers = null;
for ( temp.rank: temp.membersByRank )
temp.allMembers.addarray( temp.rank );
echo( temp.allMembers ); // returns {"Pluffy", "Gerami" };

// Please note that thus far, it doesn't support saving / loading.
// This will be implemented at a later date.
// In the meantime -- avoid resetting NPC-Server!
}



Requires http://forums.graalonline.com/forums...ad.php?t=73780

For those who are interested in what I was replicating... The original concept comes from...

http://developer.apple.com/documentation/Cocoa/Conceptual/CoreData/index.html

For the most part, things are very similar. How you set it up, however, isn't. The terminology, if you want further reference, can be found in the link above.

I hope the globals appreciate my links or else they can just remove it: Ignorance is Bliss, afterall.

Novo
05-15-2007, 07:02 PM
Fine. SOMEONE wants me to tell YOU what it means...

Managed Objects is a data model management system that does a lot of the work for you. In major part, if you can see the example, you can allow various patterns to be developed. Although this is a primitive version, it encompasses major features of Core Data Models.

In basic terms... This is a VERY generic code that can be used for anything: from muds to party systems to even banks...

First... There are four files: Managed Object Context, Managed Objects, Simple Managed Objects, and Entities...

Let start with the simple version. Simple Managed Objects is a simplified version of Managed Objects: It doesn't have a majority of the functions that Managed Objects have... But it is a lot easier to work with!

The Simple Managed Objects _are_ key-value associations. The only implementation that goes so far as to worthy a notice is that... When you alter a value, it sends a notification... ( Oh yea... This uses libnotice, provided at http://forums.graalonline.com/forums/showthread.php?t=73780 ) In other forms, it relays messages with KeyPaths...

KeyPaths are when you use multiple managed objects... If you give a variable a value of another simple managed object, you can access the variables from it by using keypaths. ( For instance, in the example provided, members in a party are a part of the rank. To get the members, you can use the keypath to get them! valueForKeyPath( "Ranks.Members" ) ).

Managed Object Context has more limitations, but these allow it to have better abilities to manage.

In the example provided, we have Ranks that link to Party, and Party that links Ranks... So when you set the Party of a Rank, it INSTANTLY adds it to the corresponding key on the Party managed object. ( As you can see from the example, when I set the value of Party in the object, I can access the Ranks members through the ranks variable... Even if I never touched it! )

This implies that as soon as you remove anything from one side, it affects instantly the next. For this to work, however, you need a model to fix these variables to. This is where Entities come into place. Entities are like maps to Managed Objects. They dictate whether it's an array or not ( "ToMany" means it's an array! ), whether it has an inverse relationship ( "inverse" provides the key to the relationships corresponding key )... There's also Delete Rule... That implies that if you delete the Party for instance, what rule it should do to it's attached variables. By default, it just removes them. But by making it "Cascade", it'll delete the ranks as well. ( This allows for better management and less overhead! ).

Managed Object Context is like the big boss... What it does is manage entities. => Creates, Deletes, and loads.

Entities manages the Managed Objects... Creates, Deletes, Load...

Managed Objects manages relationships between Managed Objects... add/remove/set...

Simple Managed Objects manages the key-value's.

Novo
05-15-2007, 07:25 PM
Further information:

customClasses...

entity.setValueForKey( "party", "customClass" );

This makes the entities derive from the party custom class.

Things of notice are these:

validForKey( aValue, aKey )

valueForKey( aValue, aKey )

allKeys()

These can be used for programmed variables*, access to all the keys available, or for your own error-handling. Try to keep it backward compatible... An example of this:


public function validForKey( aValue, aKey )
{
if ( simplemanagedobject::validForKey( aValue, aKey ) )
{
// Your error-handling here!
if ( player.account == "Novo" )
return true;
return false;
}
return false;
}


* Programmed Variables will surely depend on the 'dependencies' functionality. It is currently AVAILABLE, however, it needs a better set-up for it to work appropiately!

Oh... Attachment shows how it could be implemented for muds.

Inverness
05-15-2007, 11:19 PM
If only we could create custom Object Types in Graal :(

Twinny
05-15-2007, 11:26 PM
If only we could create custom Object Types in Graal :(

Just create a TStaticVar() and make it join a class. Don't complain about limitations so much as find workarounds.

Rapidwolve
05-16-2007, 12:08 AM
Just create a TStaticVar() and make it join a class. Don't complain about limitations so much as find workarounds.

I know, I see him asking for custom object types alot.

Inverness
05-16-2007, 11:58 PM
Just create a TStaticVar() and make it join a class. Don't complain about limitations so much as find workarounds.
I have been doing that for months.
I already know all the workarounds.
I will complain all I want thanks.

Such limitations irritate me so I complain about it, and will continue to do so until I can get a good reason why its not implemented. My use of Java makes me wonder why Graal does not have similar functionality when its obviously capable of it.

Custom Object Types + Joinable Classes = Win.

"Use TStaticVar," does not satisfy.

Twinny
05-17-2007, 01:41 AM
What difference does it make in the end?

When I asked Stefan, I thought it might make the process a bit more efficient: i.e. pre-compiled solutions rather than interpreted but apparently it won't.

ANYHOO, Novo's thread.

killerogue
05-17-2007, 01:54 AM
Novo, realize that each day...my love for you grows more and more. :)

Edit: Read up on this a bit more, and frankly I find it amazing. It's quite a thing, whatever this thing is. This thing, will bring, things about that haven't happened uptil'now!

^ My terrible try at being Dr. Seuss.


Edit 2: One question tho, as to how you came across the "Ranks." prefix in the example, I was reading the script files and some other things and couldn't get it much. :O

Novo
05-17-2007, 09:56 AM
One question tho, as to how you came across the "Ranks." prefix in the example, I was reading the script files and some other things and couldn't get it much. :O

When I set the Party in Rank, it systematically fixes it so that it is added to Ranks in Party.

killerogue
05-17-2007, 10:11 PM
That would be caused by this line?


temp.erank.setValueForKey( {"Ranks", false, null}, "configParty" );
}

Inverness
05-17-2007, 10:54 PM
What difference does it make in the end?
Simpler, organized, readable code.

Novo
05-17-2007, 11:31 PM
That would be caused by this line?
Yes.

While I'm posting: Inverness, please don't saturate this thread with irrelevant debate on the usage of TStaticVars. If you find such usage unacceptable, create your thread in Future Improvements Category. This is not the place.