<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>

<title>aem | 4. References</title>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<style type="text/css" media="all"><!--@import url(full.css);--></style>

</head>
<body>

<h1>4. References</h1>

<!-- top navigation -->
<div class="navbar">
	<a href="03_packingandunpackingdata.html">Previous</a> | <a href="index.html">Up</a> | <a href="05_targettingapplications.html">Next</a>
</div>

<!-- content -->
<div id="content">


<h2>About references</h2>

<p>An Apple Event Object Model query (a.k.a. "reference") essentially consists of a linked list made up of one or more Apple event descriptors (AEDescs) of, for the most part, <code>typeObjectSpecifier</code>. Object specifiers are used to identify properties and elements in the application's AEOM. Each object specifer contains four fields:</p>

<dl>
<dt>want</dt>
<dd>four-char-code indicating desired element(s)'s class code (e.g. <code>'docu'</code> = document), or <code>'prop'</code> if it's a property specifier</dd>

<dt>from</dt>
<dd>an object specifer identifying container object(s)</dd>

<dt>form</dt>
<dd>four-char-code indicating how the element(s) should be selected (by index [<code>'indx'</code>], name [<code>'name'</code>], etc.), or <code>'prop'</code> if it's a property specifier</dd>

<dt>seld</dt>
<dd>selector data (e.g. in a by-name specifier, this would be a string)</dd>
</dl>

<p>The Apple Event Manager provides several ways to construct object specifiers and assemble them into a complete reference, but these are all rather verbose and low-level. The aem layer hides all these details behind an object-oriented wrapper that uses chained property and method calls to gather the data needed to create object specifiers and assemble them into linked lists.</p>

<p>For example, consider the reference <code>text of document 1</code>. The code for constructing this reference using a relatively low-level bridge, in this case RubyAEOSA, would be:</p>

<pre><code>ref = OSX::AEDesc.null

ref = OSX::AEDesc.record({
    'want' =&gt; OSX::AEDesc.new('type', 'docu'),
    'from' =&gt; ref,
    'form' =&gt; OSX::AEDesc.new('enum', 'indx'),
    'seld' =&gt; 1,
}).coerce('obj ')

ref = OSX::AEDesc.record({
    'want' =&gt; OSX::AEDesc.new('type', 'prop'),
    'from' =&gt; ref,
    'form' =&gt; OSX::AEDesc.new('enum', 'prop'), 
    'seld' =&gt; OSX::AEDesc.new('type', 'ctxt'),
}).coerce('obj ')

p ref 
#&lt;AEDesc:0x57594 type='obj '&gt;</code></pre>

<p>(The Apple Event Manager API is even lower-level and more verbose.)</p>

<p>This code works by creating each AEDesc of <code>typeAERecord</code> in turn, populating it, then coercing it to <code>typeObjectSpecifier</code>. Each AEDesc is nested within the next to form a linked list of object specifier records; the last (innermost) descriptor in the finished list indicates the reference's root object in the AEOM (in this case, the <code>application</code> object, which is represented by a null descriptor).</p>

<p>Now, compare the above with the aem equivalent:</p>

<pre><code>[[[AEMApp elements: 'docu'] at: 1] property: 'ctxt']</code></pre>

<p>As you can see, aem still uses low-level four-character codes to identify the <code>text</code> property and <code>document</code> class, but is otherwise a high-level object-oriented API. Once again, each reference begins with a root object, in this case <code>AEMApp</code>. New aem specifiers are constructed by method calls; each call returning a new specifier object whose own methods can be called, and so on. This allows clients to build up a chain of aem specifier objects that aem can later pack into AEDescs for sending to applications.</p>

<p>One more thing to notice: in aem, specifying a class of elements and indicating which of those elements should be selected are performed by separate method calls, although the information provided will eventually be packed into a single AEDesc of <code>typeObjectSpecifier</code>. This two-step approach makes it easier to integrate aem with the higher-level appscript bridge, which also uses two calls to construct element specifiers (one to specify the element class, e.g. <code>-document</code>, and another to specify the selection, e.g. <code>-at: 1</code>).</p>

<p>Note that <code>[AEMApp elements: 'docu']</code> is itself a valid reference, identifying <em>all</em> the document elements of the application class. You do not have to call an explicit <code>all</code> selector (indeed, none is provided) as aem automatically handles the details for you. Aem even allows for some convenient shorthand, e.g. writing:</p>

<pre><code>[[[AEMApp.elements: 'docu'] byTest: ...] first]</code></pre>

<p>is equivalent to writing:</p>

<pre><code>[[[[AEMApp.elements: 'docu'] byTest: ...] elements: 'docu'] first]</code></pre>

<p>This allows clients to specify the first document that matches the given condition without having to specify the element class a second time. In AppleScript, the equivalent to this is:</p>

<pre><code>first document whose ...</code></pre>

<p>which is short for:</p>

<pre><code>first document of (documents whose ...)</code></pre>

<p>(Again, this additional behaviour primarily exists to serve the syntactically sugared appscript layer.)</p>



<h2>Reference forms</h2>

<p>Aem defines a number of classes representing each of the AEOM reference forms. There are nine AEOM reference forms:</p>

<ul>
<li>insertion location</li>
<li>property</li>
<li>user property</li>
<li>element by absolute position (index or ordinal)</li>
<li>element by name</li>
<li>element by id</li>
<li>element by relative position</li>
<li>elements by range</li>
<li>elements by test</li>
</ul>

<p>Each of these reference forms is represented by a different aem specifier class, apart from the absolute position form which is represented by three different classes according to the kind of selector used: a numerical index (e.g. <code>1</code>, <code>-3</code>), a named ordinal identifying a single element (<code>first</code>, <code>middle</code>, <code>last</code>, <code>any</code>), or a named ordinal identifying all elements (<code>all</code>).</p>

<p>The following diagram shows the aem reference class hierarchy (slightly simplified for legibility); concrete classes are shown in bold:</p>

<p><img src="aemreferenceinheritance.gif" title="aem reference class hierarchy" />

<p>Note that the user shouldn't instantiate these classes directly; instead, aem will instantiate them as appropriate when the client calls the methods of other aem reference objects, starting with the <code>AEMApp</code>, <code>AEMCon</code> and <code>AEMIts</code> objects that form the root of all aem references.</p>

<p>In fact, it really isn't necessary to remember the reference class hierarchy at all, only to know which concrete classes implement which methods. All user-accessible properties and methods are defined by just four superclasses:</p>

<dl>
<dt><code>AEMQuery</code></dt>
<dd>Defines comparison and hashing methods. See <code>base.h</code>.</dd>

<dt><code>AEMPositionSpecifierBase</code></dt>
<dd>Defines methods for identifying properties and all elements, insertion locations, elements by relative position. Also defines comparison and logical test methods for use in constructing its-based references. See <code>specifier.h</code>.</dd>

<dt><code>AEMMultipleElementsSpecifierBase</code></dt>
<dd>Defines methods for identifying specific elements of a multi-element reference. See <code>specifier.h</code>.</dd>

<dt><code>AEMTest</code></dt>
<dd>Defines logical test methods for use in constructing its-based references. See <code>test.h</code>.</dd>
</dl>



<h2>Base classes</h2>

<h3>Basic methods</h3>

<pre><code>AEMQuery -- Base class for all reference form and test clause classes.

-(unsigned)hash -- aem references can be used as dictionary keys

-(BOOL)isEqual:(id)object -- aem references can be compared for equality</code></pre>


####### TO DO: finish rest of chapter #######


<h3>Methods for all position specifiers</h3>

<pre><code>PositionSpecifier &lt; Specifier -- base class for all property and element
        reference forms (i.e. all forms except insertion location)

start
    Result : AEMInsertionSpecifier

end
    Result : AEMInsertionSpecifier

before
    Result : AEMInsertionSpecifier

after
    Result : AEMInsertionSpecifier

property(code)
    code : str -- four-char property code, e.g. 'pnam'
    Result : AEMProperty

user_property(name)
    name : str
    Result : AEMUserProperty

elements(ccode)
    code : str -- four-char class code, e.g. 'docu'
    Result : AEMAllElements

previous(code)
    code : str -- four-char class code
    Result : AEMElement

next(code)
    code : str -- four-char class code
    Result : AEMElement

-- Note: following methods are for use on
       its-based references only

gt(val) -- self is greater than value
    val : anything
    Result : AEMTest

ge(val) -- self is greater than or equal to value
    val : anything
    Result : AEMTest
    
eq(val) -- self equals value
    val : anything
    Result : AEMTest
    
ne(val) -- self does not equal value
    val : anything
    Result : AEMTest
    
lt(val) -- self is less than value
    val : anything
    Result : AEMTest
    
le(val) -- self is less than or equal to value
    val : anything
    Result : AEMTest
    
starts_with(val) -- self starts with value
    val : anything
    Result : AEMTest
    
ends_with(val) -- self ends with value
    val : anything
    Result : AEMTest
    
contains(val) -- self contains value
    val : anything
    Result : AEMTest
    
is_in(val) -- self is in value
    val : anything
    Result : AEMTest

and(*operands) -- equivalent to self.eq(True).and(*operands)
    operands : Test/Test
    Result : AEMTest

or(*operands) -- equivalent to self.eq(True).or(*operands)
    operands : Test/Test
    Result : AEMTest
    
not
    Result : AEMTest -- equivalent to self.eq(True).not</code></pre>


<h3>Methods for all multi-element specifiers</h3>

<pre><code>MultipleElements &lt; PositionSpecifier -- base class for all multi-
        element reference forms

    Methods:

first
    Result : AEMElement

middle
    Result : AEMElement

last
    Result : AEMElement

any
    Result : AEMElement

by_index(key)
    key : integer -- normally an integer, though some apps may 
    accept other types (e.g. Finder accepts a MacTypes::Alias)
    Result : AEMElementByIndex

by_name(key)
    key : string -- the object's name
    Result : AEMElementByName

by_id(key)
    key : anything -- the object's unique id
    Result : AEMElementByID

by_range(start, stop)
    start : Element -- an app- or con-based reference
    stop : Element -- an app- or con-based reference
    Result : AEMElementByRange

by_filter(test)
    test : Test -- an its-based reference
    Result : AEMElementsByFilter</code></pre>


<h3>Methods for all test clause classes</h3>

<pre><code>Test &lt; BASE -- represents a comparison/logic test

    Methods:

and(*operands) -- apply a logical 'and' test to self and
one or more other operands
    *operands : Test -- one or more comparison/logic test
        objects
    Result : AEMTest
    
or(*operands) -- apply a logical 'or' test to self and one
        or more other operands
    *operands : Test -- one or more comparison/logic test
            objects
    Result : AEMTest

not
    Result : AEMTest -- apply a logical 'not' test to self</code></pre>



<h2>Concrete classes</h2>

<h3>Insertion location reference form</h3>

<pre><code>InsertionSpecifier &lt; Specifier -- refers to insertion point before or after/at
        start or end of element(s); e.g. ref.before</code></pre>

<h3>Property reference forms</h3>

<pre><code>Property &lt; PositionSpecifier -- refers to a property (whose value
        may be a basic type, application object or reference);
        e.g. ref.property('ctxt')


UserProperty &lt; PositionSpecifier -- refers to a user-defined property 
        (typically in an OSA applet); e.g. ref.user_property('myVar')</code></pre>


<h3>Single element reference forms</h3>


<pre><code>ElementByIndex &lt; SingleElement -- refers to a single element in the referenced 
        container object(s) by index; e.g. ref.by_index(3)

ElementByName &lt; SingleElement -- refers to a single element in the referenced 
        container object(s) by name; e.g. ref.by_name('Documents')


ElementByID &lt; SingleElement -- refers to a single element in the referenced container 
        object(s) by unique id; e.g. ref.by_id(3456)


ElementByOrdinal &lt; SingleElement -- refers to first, middle, last or any element in 
        the referenced container object(s); e.g. ref.first


ElementByRelativePosition &lt; SingleElement -- refers to the previous or next element 
        of the given class in the referenced container object(s); 
        e.g. ref.next('cpar')</code></pre>


<h3>Multiple element reference forms</h3>

<pre><code>ElementsByRange &lt; MultipleElements -- refers to a range of elements
        in the referenced container object(s) (including start and 
        end points); e.g. ref.by_range(AEM.con.elements('cpar').by_index(2),
                AEM.con.elements('cpar').last)


ElementsByFilter &lt; MultipleElements -- refers to all elements in the
        referenced container object(s) that fulfill a given condition; 
        e.g. ref.by_filter(AEM.its.name.startswith('a'))


AllElements(MultipleElements) -- refers to all elements of 
        the given class in the referenced container object(s); 
        e.g. ref.elements('docu')</code></pre>


<h3>Tests</h3>

<p>The <code>Test</code> class represents a comparison test or logical test, and defines methods for composing additional logical tests on top of these. Each kind of test clause is represented by a different subclass of the main <code>Test</code> class. The details are not that important, however, so they're not listed here.</p>




<h3>Reference Roots</h3>

<pre><code>ApplicationRoot &lt; PropertySpecifier -- AEM.app returns an instance of
       this class

CurrentContainer &lt; PropertySpecifier -- AEM.con returns an instance of
       this class

ObjectBeingExamined &lt; PropertySpecifier -- AEM.its returns an instance
       of this class</code></pre>



<!-- TO DO: note on AEM_resolve -->


</div>

<!-- bottom navigation -->
<div class="navbar">
	<a href="03_packingandunpackingdata.html">Previous</a> | <a href="index.html">Up</a> | <a href="05_targettingapplications.html">Next</a>
</div>

<!--footer-->
<p class="footer">&copy; 2006 HAS</p>
</body>
</html>