ZNLogo: zopeLogo:
A Journey of Zope Exploration
 
Prev | Next | Transition to Acquisition

Acquisition Behavior
Fri, Nov 26, 1999; by Jeff Shelton.

Unlike the notations for object relationships we have examined so far, acquisition allows us to get to a given location using multiple paths. And based on the path we follow, the value of the object will change. So it is not an overstatement to say, "Acquisition is Different!"
 
 

Why Acquisition?

Most common sense revolves around being able to evaluate the context of a question. If you are watching television and someone asks you, "What are you watching?" they expect you to tell them something about the show you are viewing, not respond with "a collection of small dots projected onto the front panel of a cathode ray tube." Even though your technical response may have been correct, it was not appropriate for the context of the question. Likewise, if you are in a business meeting and someone asks for your phone number, they expect to get your office phone number, not the number of the phone at your summer cottage.

 One programming methodology that was developed to handle the issue of context is called acquisition. One of the characteristics of acquisition is that objects "acquire" attributes only in the context of their environment. Of course, we have five senses and a pretty powerful brain for determining context. How does a software program determine context?

 In the case of object databases like Zope's ZODB, the environment is defined by the path taken to get to the object. This is certainly different than the inheritance and file system paths we examined in Object Relationship Notation. In those cases, there was one and only one path to get to an object. With acquistion, we are suggesting that there are multiple ways to get to the same object. And, on top of that, we are suggesting that the object will take on different attributes depending on the path taken. (Wow!) So just how does this acquisition thing work?
 
 

Acquired Behavior

First of all, we have to keep in mind that acquisition tries to answer the question, "What is the proper response in the context of what is already known?" In an inheritance path, there is only one way to reach an instance, so context is irrelevant. But with acquisition, we have to keep track of what we already know to understand the current context.

 So if I ask, "What do you want to drink?" you might respond with "Give me a soda." But if I say, "You're stranded in the middle of a winter blizzard. What do you want to drink?" you would probably change your response to "hot chocolate" or "hot coffee." If I pester you again and say, "You're stranded in a winter blizzard. But you're stranded inside a log cabin with a roaring fire. What do you want to drink?" you might change your answer back to "a soda." In answering my final query you had to evaluate two pieces of information before responding. First, you had to examine the possible ramifications of being in a blizzard. Then you had to judge what the tradeoffs might be if you were weathering the blizzard inside a warm cabin. You couldn't intelligently respond until you had considered each bit of information in order. This is the way that acquisition works in Zope.

 Introductory texts to Zope typically suggest that when a URL request is handled, the ZPublisher module converts the request into a object database path, and that the specified object is then rendered. While this interpretation works for simple cases, it is not entirely accurate. Using acquisition, the URL path defines the context in which the target object should be interpreted. So for our previous example, we could define an object named drink (for the time being, it doesn't matter where drink is located) that could be reached with either
 
 

http://www.mydomain.com/blizzard/warm_cabin/drink
or
http://www.mydomain.com/blizzard/abandoned_highway/drink
and we would get back two completely different answers, as the context (path) of the two requests are completely different.
 
 

A Contrast in Convention

Just to make sure you don't get too confused, let me assure you that "Acquisition is different!" The way that acquisition uses a path is entirely different from virtually every other convention that you may have come across.

 In an inheritance path, for example, the search for an attribute begins with the rightmost object and proceeds to the left. So in the path
 
 

vehicle.car.passenger_car.my_chevy_cavalier.start()
we would look for the method start() first in the instance my_chevy_cavalier and start working our way to the left. This is the way that most tree structures are traversed.

 With acquistion, however, we have to evaluate the context in the order given. This means that we have to evaluate the URL path from left to right. So for our URL request of 

http://www.mydomain.com/blizzard/warm_cabin/drink
we would start by looking for attributes needed to evaluate drink within the object blizzard. Then, we would look for the attributes needed to evaluate drink in the object warm_cabin, in the context of already knowing about blizzard. Confused? Perhaps an example will make the unique convention of acquisition a bit more clear.
 
 

An Example

Let's say that drink is a method in the blizzard folder that will print out the drink of choice. Let us also assume that blizzard is a top level folder that has a property drinkChoice with a value of "Hot Coffee," and that warm_cabin is another top-level folder with a value of "Cola" for its property drinkChoice. To give us another option, let's create a third top-level folder named abandoned_highway. This folder has a drinkChoice value of "Hot Chocolate." Finally, let's add a folder titled middle_of_nowhere that does not define drinkChoice.
 

blizzardStructure:

Remember now, our four folders are at the same level in our object database. So the URL request no longer has anything to do with the structure of objects in the database. We are now providing the Zope Object Request Broker (ZORB) with contextual information for our request.

 So when we issue a URL request of 

http://www.mydomain.com/blizzard/warm_cabin/drink
Zope evaluates it in the following fashion:

 First, it says "Okay, we are asked to assume there is a blizzard going on. Do we have a blizzard object in the object database?" When it discovers that the blizzard object does exist, it then asks, "Given that we know about the blizzard object, do we know anything about being in a warm cabin?" Since the warm_cabin folder is at top level of the database, it is not contained in the blizzard folder, and it would be found whether we knew about the blizzard object or not.

 Now that the warm_cabin object has been found, it asks "Do we know anything about an attribute named drink?" Since our first contextual assumption was that a blizzard was occurring, we look first in the blizzard object. Indeed, we find a drink method inside the blizzard folder. After finding drink inside the blizzard folder, we would next look for it inside the warm_cabin folder, since we are looking for drink in the context of both blizzard and warm_cabin.

 If there were a drink method inside the warm_cabin folder, we would use that method since it is more specific in terms the environment described to us in the URL path. We always start with the information given to us with the most general context (in this case, blizzard), then keep updating our data with more specific contextual information (from warm_cabin). However, there is no drink method inside of warm_cabin, so we use the drink method from blizzard.

 It is now time to evaluate the drink method, which simply prints out the value of property drinkChoice. Since a value for drinkChoice is needed, Zope looks first in the blizzard object, as that was the first contextual clue given by the URL request. It finds a value of "Hot Coffee" for drinkChoice inside of blizzard. But it does not stop there. It knows that there is additional contextual information. So it next goes looking inside of warm_cabin to see if there is additional information about property drinkChoice. And warm_cabin says that drinkChoice should be "Cola." So Zope say to itself, "Object warm_cabin is overriding some information found in object blizzard, but since we were asked to assume a warm_cabin in the context of a blizzard, the value of drinkChoice must be "Cola." And therefore, method drink prints out a request for cola.
 

blizzardScreen1:

What if we change the request to 

http://www.mydomain.com/warm_cabin/blizzard/drink?
We have switched the positions of our request for warm_cabin and blizzard. This would obviously never work for a object database or file system. But this is the world of ACQUISITION! With acquisition, we will now evaluate blizzard in the context of warm_cabin. The value for drinkChoice inside blizzard is now considered more specific contextual data, and method drink prints out a request for "Hot Coffee."
 

blizzardScreen2:

See what happened? Method drink was found in the context of blizzard in the context of warm_cabin. And when drink needed a value for drinkChoice, it looked first in the most general contextual object, warm_cabin, then it looked in the more specific contextual object, blizzard. Thus, method drink used the blizzard value for drinkChoice as being the most specific to the environment expressed by the URL path.

 What happens if our request is
 
 

http://www.mydomain.com/warm_cabin/drink?
We get an error message! Why? Well, in the context of warm_cabin alone, we don't know anything about the method drink, which is contained inside blizzard. Therefore, in any URL request in which we want to evaluate drink, a reference to blizzard must come first.

 What about
 
 

http://www.mydomain.com/blizzard/drink?
blizzardScreen3:

Since drink is known in the context of blizzard, a "Hot Coffee" is requested. You might note that if you're only referencing one object at each folder level in a acquisition path, it acts just like a file system path.

 What about being stuck along the highway? If we issue a URL request of
 
 

http://www.mydomain.com/blizzard/abandoned_highway/drink
we get a message asking for "Hot Chocolate."
 

blizzardScreen4:

Okay, let's say we can't make up our minds right away. Let's issue a request of

 .../blizzard/abandoned_highway/warm_cabin/abandoned_highway/warm_cabin/drink
 

blizzardScreen5:

If this were a file system or object database path, we would surely get an error message. You just can't do this with normal object pathnames. Remember, though, "Acquisition is different!" In the above example, we are simply giving contextual information to the object broker to evaluate our drink request in terms of the specified environment. So Zope first gets drinkChoice information from blizzard, then abandoned_highway, then warm_cabin, then abandoned_highway again, then finally warm_cabin. So the drink method issues a request for "Cola."

 As a test of your growing knowledge of acquisition, what would happen if we issued the following request?
 
 

http://www.mydomain.com/blizzard/middle_of_nowhere/drink
That's right. The object middle_of_nowhere has no additional information about drinkChoice, so drink prints out the drinkChoice information it found in blizzard.
 

blizzardScreen6:

Okay, one more example. If we add a method cozy_chair inside of the folder warm_cabin, which of the following URL requests are valid?
 
 

http://www.mydomain.com/blizzard/cozy_chair
http://www.mydomain.com/blizzard/warm_cabin/cozy_chair
http://www.mydomain.com/warm_cabin/blizzard/cozy_chair
Right again. The URL path http://www.mydomain.com/blizzard/cozy_chair is invalid, because if we only know about the blizzard object, there is no way we can know about the cozy_chair object that is defined inside of warm_cabin. However, the the other two URL paths are valid because they both give us the contextual clue of warm_cabin prior to asking for cozy_chair. Therefore, we know where to find the method cozy_chair.

 If I've done my job, you now have a better understanding of how acquisition behaves in Zope. But, you may ask, why is it there in the first place? Well, read on, oh seeker of Zope Zen. The next section is "A Case for Acquisition". [ed. Now in development...

discussButton:
 
 
Prev | Next | Transition to Acquisition





Search zopeNewbies:

Search zopeNewbies 2:



Create your own Manila site in minutes. Everyone's doing it!

Last update: Monday, March 27, 2000 at 5:13:16 AM Pacific.