<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sifzone.com/sifzonecs20085/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Working with SIF Data Objects</title><link>http://sifzone.com/sifzonecs20085/wikis/adkdevguide/working-with-sif-data-objects.aspx</link><description>The SIFWorks® Agent Developer Kit for Java – or ADK® – is a high-level class framework for the Java platform that simplifies the job of writing sophisticated, feature-rich SIF Agents for the Schools Interoperability Framework™. </description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>Working with SIF Data Objects</title><link>http://sifzone.com/sifzonecs20085/wikis/adkdevguide/working-with-sif-data-objects.aspx</link><pubDate>Sat, 07 Feb 2009 02:16:16 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:28</guid><dc:creator>Andrew Elmhorst</dc:creator><comments>http://sifzone.com/sifzonecs20085/wikis/adkdevguide/working-with-sif-data-objects/comments.aspx</comments><description>Current revision posted to SIFWorks ADK Developer&amp;#39;s Guide by Andrew Elmhorst on 2/6/2009 9:16:16 PM&lt;br /&gt;
&lt;h2&gt;Working with SIF Data Objects&lt;/h2&gt;
&lt;h3&gt;SIFElement &amp;amp; SIFDataObject Classes&lt;/h3&gt;
&lt;p&gt;All SIF elements modeled by the ADK are encapsulated by classes derived from a common abstract base class: com.edustructures.sifworks.SIFElement. These in-clude top-level data objects like StudentPersonal as well as complex child elements like Name, Demographics, Transaction, and so on. (A complex element is any element that has attributes or children. In contrast, a simple field element is any element that has only a text value. The ADK does not model field elements as Java classes, but it does supply classes to encapsulate each and every complex element found in the SIF data model.)&lt;/p&gt;
&lt;p&gt;Classes that model top-level SIF Data Objects like StudentPersonal are derived from the SIFDataObject base class, which descends from SIFElement. There are over 115 such data objects in the SIF 2.0r1 Specification.&lt;/p&gt;
&lt;p&gt;The full class hierarchy is as follows:&lt;/p&gt;
&lt;pre&gt;	com.edustructures.sifworks.Element
		com.edustructures.sifworks.SIFElement
			Complex Element Classes
		com.edustructures.sifworks.SIFDataObject
			Data Object Classes
&lt;/pre&gt;
&lt;h3&gt;Class Constructors&lt;/h3&gt;
&lt;p&gt;Each SIFElement class offers two constructors: a default constructor that accepts no parameters, and another that accepts all required or mandatory elements defined by the SIF Specification. The following code illustrates how to use both forms of constructor. In the first example, a StudentPersonal object is created using that class&amp;rsquo;s default constructor. None of the object&amp;rsquo;s required attributes will have values (in this case the RefId attribute), so it is the responsibility of the agent to ensure they are assigned values before published to SIF.&lt;/p&gt;
&lt;p&gt;In the second example, an Address instance is created using the constructor that accepts a value for each required attribute or element (in this case, AddressType, Street/Line1, City, StateProvice, Country, and PostalCode are all denoted as Mandatory in the SIF Specification.) Using this constructor is a shortcut to explicitly assigning values to required attributes and elements, and makes it easy to create a valid Transaction instance in a single line of code:&lt;/p&gt;
&lt;pre&gt;// Create a StudentPersonal object
StudentPersonal sp = new StudentPersonal();
sp.setRefId( ADK.makeGUID() );

// Create an Address
Address addr = new Address( 
  AddressType.MAILING, new Street( &amp;quot;321 Baker Dr&amp;quot; ), 
  &amp;quot;Metropolis&amp;quot;, StatePrCode.IL, CountryCode.US, &amp;quot;98855&amp;quot; );
&lt;/pre&gt;
&lt;p&gt;Dynamic SIFDataObject Construction&lt;/p&gt;
&lt;p&gt;SIFDataObject instances may also be created dynamically by passing an ElementDef constant to the SIFDTD.createSIFDataObject method, identifying the kind of object to create. (SIFDTD and ElementDef&amp;mdash;two classes central to the SIF Data Objects libraries&amp;mdash;are discussed in subsequent sections.)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;// Kinds of objects to create
ElementDef[] kinds = new ElementDef[] {
		StudentDTD.STUDENTPERSONAL, 
		StudentDTD.STAFFPERSONAL,
		LibraryDTD.LIBRARYPATRONSTATUS };

// Create a bunch of SIFDataObject instances...
SIFDTD metadata = ADK.DTD();
SIFDataObject[] objects = new SIFDataObject[ kinds.length ];
for( int i = 0; i &amp;lt; kinds.length; i++ )
	objects[i] = metadata.createSIFDataObject( kinds[i] );
 
&lt;/pre&gt;
&lt;h3&gt;Creating &amp;amp; Manipulating SIFDataObjects&lt;/h3&gt;
&lt;p&gt;The ADK supplies two ways to create and manipulate SIFDataObject instances. The first is to programmatically construct objects and call the methods of the SDO classes to get and set element and attribute values. For example,&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;//Constructing a StudentPersonal object
StudentPersonal sp = new StudentPersonal();
sp.setRefId( ADK.makeGUID() );
sp.setName( NameType.LEGAL, &amp;quot;Johnson&amp;quot;, &amp;quot;Clifford&amp;quot; );

// Examining a StudentPersonal object
Name n = sp.getName();
System.out.println( &amp;quot;Name: &amp;quot; + n.getLastName() + &amp;quot;, &amp;quot; + n.getFirstName() );
OtherIdList ids = sp.getOtherIdList();
System.out.println( &amp;quot;This student has &amp;quot; + ids.size() + &amp;quot; IDs&amp;quot; );
&lt;/pre&gt;
&lt;p&gt;You can also use the setElementOrAttribute method:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;// Dynamically constructing a StudentPersonal object
SIFDataObject sp = ADK.DTD().createSIFDataObject( StudentDTD.STUDENTPERSONAL );
sp.setElementOrAttribute( &amp;quot;@RefId&amp;quot;, ADK.makeGUID() );
sp.setElementOrAttribute( &amp;quot;Name[@Type=&amp;#39;01&amp;#39;]/LastName&amp;quot;, &amp;quot;Johnson&amp;quot; );
sp.setElementOrAttribute( &amp;quot;Name[@Type=&amp;#39;01&amp;#39;]/FirstName&amp;quot;, &amp;quot;Clifford&amp;quot; );

// Dynamically examining a StudentPersonal object
Element refId = sp.getElementOrAttribute( &amp;quot;@RefId&amp;quot; );
Element studentId = sp.getElementOrAttribute( &amp;quot;OtherId[@Type=&amp;#39;06&amp;#39;&amp;quot; );
&lt;/pre&gt;
&lt;p&gt;An alternative and more data-driven approach to working with SIFDataObjects is to use the Mappings class from the com.edustructures.sifworks.tools.Mappings package to convert SIFDataObject instances to and from a data source such as a Map by applying a set of XPath-like mapping rules. These rules are usually stored in an ex-ternal configuration file where they can be modified by system integrators in the field. For example, the following rules for StudentPersonal objects define how to translate the elements and attributes of that object to a flat list of field values:&lt;/p&gt;
&lt;pre&gt;&amp;lt;object object=&amp;quot;StudentPersonal&amp;quot;&amp;gt;
	&amp;lt;field name=&amp;quot;STUDENT_ID&amp;quot;&amp;gt;OtherId[@Type=&amp;rsquo;01&amp;rsquo;]&amp;lt;/field&amp;gt;
	&amp;lt;field name=&amp;quot;LAST_NAME&amp;quot;&amp;gt;Name[@Type=&amp;rsquo;01&amp;rsquo;]/LastName&amp;lt;/field&amp;gt;
	&amp;lt;field name=&amp;quot;FIRST_NAME&amp;quot;&amp;gt;Name[@Type=&amp;rsquo;01&amp;rsquo;]/FirstName&amp;lt;/field&amp;gt;
&amp;lt;/object&amp;gt;
&lt;/pre&gt;
&lt;p&gt;You can then call upon the Mappings class to convert a StudentPersonal instance into a Map of field/value pairs, or to convert a Map into a StudentPersonal object.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In practice, most agents use a combination of these two approaches when working with SIF Data Objects. Refer to the chapter on SIF Data Objects for more information.&lt;/p&gt;
&lt;h3&gt;The SIFDTD Class&lt;/h3&gt;
&lt;p&gt;In order to support all versions of the SIF specification, the ADK has a built-in metadata dictionary. This metadata encompasses information about each element and attribute from all versions of SIF 1.0r1 and later. The class framework relies on this information to determine the versions of SIF each element or attribute supports, its tag name, its sequence number, and various flags such as whether an element is repeatable or not.&lt;/p&gt;
&lt;p&gt;The metadata dictionary is comprised of the static constants defined by a DTD class located within each package in the ADK that contains objects representing SIF elements. Each DTD class defines static ElementDef constants representing each element and attribute of SIF. ElementDef constants identify elements and attributes in a version-independent way so that the class framework knows what your agent is referring to regardless of whether the task at hand involves SIF 1.1, SIF 1.5r1, SIF 2.0r1 or some future version of specification.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Whenever a method requires an ElementDef parameter, you must pass a constant from one of the package-specific DTD classes:&lt;/p&gt;
&lt;pre&gt;	// Create a Topic instance for &amp;quot;BusInfo&amp;quot; and &amp;quot;StudentPersonal&amp;quot; objects
	Topic businfo = getTopicFactory().getInstance( TransDTD.BUSINFO );
	Topic students = getTopicFactory().getInstance( StudentDTD.STUDENTPERSONAL );
&lt;/pre&gt;
&lt;h3&gt;SIFDTD Constants for Elements &amp;amp; Attributes&lt;/h3&gt;
&lt;p&gt;For elements that are part of the SIF Common Objects group or that otherwise are used across more than one SIF Data Object, each DTD class uses a naming convention to distinguish between the objects a common element appears in.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;For example, the common &amp;lt;Name&amp;gt; element is used in StudentPersonal, StaffPersonal, and StudentContact. However, the characteristics of &amp;lt;Name&amp;gt;&amp;mdash; such as its sequential order relative to its parent&amp;mdash;are different when used as a child of &amp;lt;StudentPersonal&amp;gt; than when used as a child of &amp;lt;StaffPersonal&amp;gt; and &amp;lt;StudentContact&amp;gt;. Thus, the StudentDTD class defines multiple ElementDef constants for the &amp;lt;Name&amp;gt; element:&lt;/p&gt;
&lt;pre&gt;	StudentDTD.STUDENTPERSONAL_NAME
	StudentDTD.STAFFPERSONAL_NAME
	StudentDTD.STUDENTCONTACT_NAME
&lt;/pre&gt;
&lt;p&gt;The naming convention employed is the name of the parent SIF Data Object in upper-case, followed by an underscore (&amp;ldquo;_&amp;rdquo;) and the name of the element or attribute, also in upper-case:&lt;/p&gt;
&lt;pre&gt;[DTDClass].PARENT_CHILD&lt;/pre&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;// Query for all BusInfo objects
Query q = new Query( TransDTD.BUSINFO );

// Include only the RefId, VehicleNumber, and Contractor in the response
q.setFieldRestrictions(
	new ElementDef[] {
		TransDTD.BUSINFO_REFID,
		TransDTD.BUSINFO_VEHICLENUMBER,
		TransDTD.BUSINFO_CONTRACTOR
	}
);
&lt;/pre&gt;
&lt;h3&gt;Inspecting the ElementDef of a SIFDataObject&lt;/h3&gt;
&lt;p&gt;You can obtain the ElementDef associated with any SIFDataObject instance by calling its getElementDef method. This is often used in Boolean comparisons to determine if an object is of a certain type:&lt;/p&gt;
&lt;pre&gt;SIFDataObject someObject = ...

if( someObject.getElementDef() == StudentDTD.STUDENTPERSONAL )
{
	// This is a StudentPersonal object
	StudentPersonal sp = (StudentPersonal)someObject;
	System.out.println(&amp;quot;StudentPersonal with RefId &amp;quot; + sp.getRefId() );
}
else
if( someObject.getElementDef() == SIFDTD.STUDENTCONTACT )
{
	etc.
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Getting an Element&amp;rsquo;s Tag Name&lt;/h3&gt;
&lt;p&gt;The tag name of an element or attribute is specific to each version of SIF. With the ADK, each ElementDef is associated with two names: a version-independent name, which is used to identify the element or attribute regardless of the version of SIF you&amp;rsquo;re working with; and a version-dependent tag name, which is used when rendering and parsing the element. Often times it is necessary to use the element tag name in your code; for example, to log a debug message or to lookup an entry in a table that is keyed by element name.&lt;/p&gt;
&lt;p&gt;If you want to obtain the version-independent name of an element or attribute, call the ElementDef.name method. This method returns the string used to identify the element or attribute in the ADK&amp;rsquo;s metadata dictionary. By convention it is usually equivalent to the name of the element as it first appears in the SIF Specification as of SIF 2.0 or later. .&lt;/p&gt;
&lt;p&gt;For example, calling the name method on the LibraryDtd.TRANSACTION constant re-turns the string &amp;ldquo;Transaction&amp;rdquo;:&lt;/p&gt;
&lt;pre&gt;	// Create a Transaction element and show its version-independent name
	Transaction trans = new Transaction();

	System.out.println( trans.getElementDef().name() );
&lt;/pre&gt;
&lt;p&gt;If you want to obtain the version-dependent name of an element or attribute&amp;mdash;that is, the string used when parsing and rendering the element&amp;mdash;call the ElementDef.tag method. This method requires that a SIFVersion instance be passed to it. Unlike the name method, it returns the tag name specific to the version of SIF. For example, calling tag on the LibraryDTD.TRANSACTION constant yields different results for SIF 1.1 than for SIF 2.0. In SIF 1.1, the element is known as &amp;ldquo;CircTx&amp;rdquo; and in SIF 2.0 it is known as &amp;ldquo;Transaction&amp;rdquo;.&lt;/p&gt;
&lt;pre&gt;// Create a Transaction element and show its version-dependent tag name
Transaction trans = new Transaction();

// Show the tag name for SIF 1.1: &amp;quot;CircTX&amp;quot;
System.out.println( trans.getElementDef().tag( SIFVersion.SIF11 ) );

// Show the tag name for SIF 2.0: &amp;quot;Transaction&amp;quot;
System.out.println( trans.getElementDef().tag( SIFVersion.SIF20 ) );
&lt;/pre&gt;
&lt;p&gt;The above code uses SIFVersion constants but in practice you obtain the SIFVersion associated with a SIF Data Object by calling the SIFDataObject.getSIFVersion me-thod:&lt;/p&gt;
&lt;pre&gt;public void onEvent( Event event, Zone zone, MessageInfo info )
		throws ADKException
{
	SIFMessageInfo inf = (SIFMessageInfo)info;

	// Print the version of the SIF_Message envelope 
	System.out.println(&amp;quot;Received a SIF_Event from a SIF &amp;quot; + 
		inf.getSIFVersion() + &amp;quot; agent&amp;quot; );

	// Print the version-dependent tag name of the data contained in the event
	SIFDataObject data = event.getData().readDataObject();
	System.out.println( &amp;quot;A &amp;quot; + data.getElementDef().tag( data.getSIFVersion() ) + 
		&amp;quot; object is contained in the event&amp;quot; );
	System.out.println( &amp;quot;The &amp;quot; + data.getElementDef().name() + &amp;quot; object is a SIF &amp;quot; +
		data.getSIFVersion() + &amp;quot; object&amp;quot; );&lt;br /&gt;&lt;span style="background: SpringGreen;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;The above example might print the following to the Java console:&lt;/p&gt;
&lt;p&gt;&lt;span&gt;	&lt;/span&gt;&lt;em&gt;Received a SIF_Event from a SIF 1.1 agent&lt;br /&gt;A StudentPersonal object is contained in the event&lt;br /&gt;The StudentPersonal object is a SIF 1.1 object&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Building SIF Data Objects Dynamically&lt;/h3&gt;
&lt;p&gt;Most agents retrieve their data from a local database or other data store with its own unique schema and programming interfaces. A common approach to interacting with SIF is to dynamically map elements and attributes from a SIF Data Object to fields in the local application&amp;rsquo;s database. The ADK provides a powerful facility for mapping: the Mappings class found in the com.edustructures.sifworks.tools.mapping package. You could also implement your own mapping routines by using functions such as SIFDataObject.setElementOrAttribute.&lt;/p&gt;
&lt;p&gt;The following code creates a StudentPersonal object by enumerating the fields in a mapping table. This code looks much different from most of the code shown through-out the Developer&amp;rsquo;s Guide and ADK Example agents because it does not directly use the SIF Data Object classes like Name, PhoneNumber, and StudentAddress to build the StudentPersonal object. Instead, it uses XPath-like query strings and the setElemen-tOrAttribute method of the SIFDataObject class. With the ADK, you have the flex-ibility to work with SIF Data Objects however you like.&lt;/p&gt;
&lt;p&gt;Refer to the SIFDataObject class in the Javadoc for more information on the setEle-mentOrAttribute method.&lt;/p&gt;
&lt;pre&gt;	// Build a table that maps fields in the local application to SIF 
  // elements &amp;amp; attributes. The key of each entry is a name of your 
  // choosing that identifies a field in the local database; the value 
  // of each entry is an XPath-link query string that identifies
	// the corresponding SIF element or attribute of the StudentPersonal 
  // object

	HashMap m = new HashMap();
	m.put( &amp;quot;ForeignId&amp;quot;,    &amp;quot;@RefId&amp;quot; );
	m.put( &amp;quot;ID&amp;quot;,           &amp;quot;OtherId[@Type=&amp;rsquo;06&amp;rsquo;]&amp;quot; );
	m.put( &amp;quot;L_Name&amp;quot;,       &amp;quot;Name[@Type=&amp;rsquo;01&amp;rsquo;]/LastName&amp;quot; );
	m.put( &amp;quot;F_Name&amp;quot;,       &amp;quot;Name[@Type=&amp;rsquo;01&amp;rsquo;]/FirstName&amp;quot; );
	m.put( &amp;quot;Addr_Line1&amp;quot;,   &amp;quot;StudentAddress/Address[@Type=&amp;rsquo;M&amp;rsquo;]/Street/Line1&amp;quot; );
	m.put( &amp;quot;Addr_Line2&amp;quot;,   &amp;quot;StudentAddress/Address[@Type=&amp;rsquo;M&amp;rsquo;]/Street/Line2&amp;quot; );
	m.put( &amp;quot;Addr_City&amp;quot;,    &amp;quot;StudentAddress/Address[@Type=&amp;rsquo;M&amp;rsquo;]/City&amp;quot; );
	m.put( &amp;quot;Addr_State&amp;quot;,   &amp;quot;StudentAddress/Address[@Type=&amp;rsquo;M&amp;rsquo;]/StatePr/@Code&amp;quot; );
	m.put( &amp;quot;Addr_Zip&amp;quot;,     &amp;quot;StudentAddress/Address[@Type=&amp;rsquo;M&amp;rsquo;]/PostalCode&amp;quot; );
	m.put( &amp;quot;Pri_Email&amp;quot;,    &amp;quot;Email[@Type=&amp;rsquo;Primary&amp;rsquo;]&amp;quot; );
	m.put( &amp;quot;Sec_Email&amp;quot;,    &amp;quot;Email[@Type=&amp;rsquo;Alternate1&amp;rsquo;]&amp;quot; );

	// Now create a StudentPersonal from the mapping table. For each entry 
  // in the table, lookup the associated value in the local application 
  // database, then call the StudentPersonal.setElementOrAttribute method 
  // to assign that value to the corresponding element or attribute in the 
  // SIF Data Object

	StudentPersonal student = new StudentPersonal();
	for( Iterator it = m.keySet().iterator(); it.hasNext(); )
	{
		String localField = (String)it.next();
		String sifField = (ElementDef)m.get( field );

		// Lookup the value of this field from the local application&amp;rsquo;s database
		String value = myDatabaseView.getFieldValue( localField );

		// Assign the field to the StudentPersonal object
		if( value != null )
			student.setElementOrAttribute( sifField, value );
	}
&lt;/pre&gt;
&lt;h3&gt;Enumerated Types&lt;/h3&gt;
&lt;p&gt;The ADK defines enumerated type classes whenever a set of pre-defined values is ex-pected for an object field. These classes are named the same as the attribute or element they&amp;rsquo;re associated with. For example, the EducationLevel/Code element of the Stu-dentContact data type is represented by the EducationLevelCode class.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As you might expect, the StudentContact.setEducationLevel method accepts a single parameter: an EducationLevelCode object. Valid codes for this object are defined as static constants of the enumerated type class: EducationLevelCode.EMC, EducationLevelCode.E4, etc.&lt;/p&gt;
&lt;p&gt;Enumerated type classes are provided as a convenience to programmers, to enforce type safety, and to help ensure that valid values are used in the construction of SIF messages. There are many cases when referencing one of the pre-defined constants of an enumerated type class is not appropriate: for example, when reading values from a database resultset you will want to assign them directly to an element or attribute. For this reason, all enumerated type classes offer a wrap method that you can use to pass your own string in place of a pre-defined constant. The following code demonstrates:&lt;/p&gt;
&lt;pre&gt;	// Construct a StudentContact object
	StudentContact sc = new StudentContact();

	// Use the enum class to set EducationLevel to &amp;quot;E4&amp;quot;
	sc.setEducationLevel( EducationLevelCode.E4 );

	// Set the code directly
	sc.setEducationLevel( EducationLevelCode.wrap( &amp;quot;E4&amp;quot; ) );

	// Can also set the code to an invalid value
	sc.setEducationLevel( EducationLevelCode.wrap( &amp;quot;Zebra&amp;quot; ) );

&lt;/pre&gt;
&lt;h3&gt;Dates and Times&lt;/h3&gt;
&lt;p&gt;SIF 2.0 uses XSD data types to represent Dates, DateTimes, and Times. The ADK represents each of these fields using the Java Calendar object.&lt;/p&gt;
&lt;h3&gt;Creating RefIds for SIF Data Objects&lt;/h3&gt;
&lt;p&gt;When an agent publishes a data object to a zone for the first time, it must assign the object a globally-unique identifier&amp;mdash;or &amp;nbsp;RefId&amp;mdash;that will forever identify that object in the zone. Both the ADK.makeGUID static function and Agent.makeGUID convenience method create Globally Unique Identifiers (GUIDs).&lt;/p&gt;
&lt;pre&gt;// Create a new StudentPersonal object with a new GUID generated 
// by this agent
StudentPersonal sp = new StudentPersonal();
sp.setRefId( ADK.makeGUID() );
...
&lt;/pre&gt;
&lt;h3&gt;Managing RefIds&lt;/h3&gt;
&lt;p&gt;Because it is specific to your agent&amp;rsquo;s transaction layer and involves interaction with a database or other persistent data store, the ADK does not provide any classes to manage RefIds. You will need to create a mechanism to store RefIds created by your agent when publishing SIF Data Objects for the first time, or imported from other agents when receiving objects in SIF_Response and SIF_Event messages. Although there are a number of ways to go about this, one simple solution is to use a database table to record the RefIds known to your agent. The following schema will usually suffice:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table cellpadding="0" cellspacing="0" border="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="115"&gt;
&lt;p&gt;Column&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="120"&gt;
&lt;p&gt;Data Type&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="288"&gt;
&lt;p&gt;Definition&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="115"&gt;
&lt;p&gt;RefId&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="120"&gt;
&lt;p&gt;Char[32]&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="288"&gt;
&lt;p&gt;The GUID&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="115"&gt;
&lt;p&gt;PrimaryKey&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="120"&gt;
&lt;p&gt;String or Numeric&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="288"&gt;
&lt;p&gt;The primary key
  of the record in your &lt;span style="text-decoration: line-through; color: red;"&gt;appli-cation&lt;/span&gt;&lt;span style="text-decoration: line-through; color: red;"&gt;&amp;rsquo;s&lt;/span&gt; &lt;span style="background: SpringGreen;"&gt;application&lt;/span&gt;&lt;span style="background: SpringGreen;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="background: SpringGreen;"&gt;s&lt;/span&gt; database that is associated with this
  RefId.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="115"&gt;
&lt;p&gt;SecondaryKey&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="120"&gt;
&lt;p&gt;String or Numeric&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="288"&gt;
&lt;p&gt;The optional
  secondary key of the record in your application&lt;span style="text-decoration: line-through; color: red;"&gt;&amp;rsquo;s&lt;/span&gt; &lt;span style="background: SpringGreen;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="background: SpringGreen;"&gt;s&lt;/span&gt; database that is associated
  with this RefId.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="115"&gt;
&lt;p&gt;ObjectType&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="120"&gt;
&lt;p&gt;Numeric&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="288"&gt;
&lt;p&gt;A constant that
  identifies the type of data &lt;span style="text-decoration: line-through; color: red;"&gt;as-sociated&lt;/span&gt; &lt;span style="background: SpringGreen;"&gt;associated&lt;/span&gt; with this RefId. Consider defining
  numeric values for each object type; for &lt;span style="text-decoration: line-through; color: red;"&gt;ex-ample&lt;/span&gt;&lt;span style="background: SpringGreen;"&gt;example&lt;/span&gt;, 1=Students or
  StudentPersonal; 2=Teachers or StaffPersonal; etc.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;When publishing an object to a zone for the first time, assign a RefId to it and record the association between that RefId and the local application database record. You must use this RefId to subsequently identify the object whenever it is included in a SIF message: for example, when reporting a SIF_Event to a zone.&lt;/p&gt;
&lt;p&gt;When receiving an object in a SIF_Event or SIF_Response message, the agent should first lookup its RefId in the above table. Most SIF Data Objects have an attribute named &amp;ldquo;RefId&amp;rdquo; that you can obtain via the SIFDataObject.getRefId method. If the RefId exists in your table, take the appropriate action on the corresponding database record. For example, if you receive a SIF_Event with a Change action that identifies a student you have on file, update the student record appropriately. However, if you receive a Change event for a student that does not exist in your RefId repository, you cannot take action on the event because the agent doesn&amp;rsquo;t know which student record to update.&lt;/p&gt;
&lt;p&gt;How does the RefId repository get created initially? Edustructures recommends that all agents incorporate some form of &amp;ldquo;synchronization procedure&amp;rdquo; that is run the first time the agent is installed and again at the beginning of each school year. This process retrieves all SIF Data Objects from the zone or zones the agent is connected to, and using an algorithm of &amp;nbsp;your choosing, matches them up with corresponding records in the application database. The goal of synchronization is to establish an initial set of RefIds such that your agent knows which SIF Data Objects equate to the record that already exist in the application&amp;rsquo;s database. Once this process is complete, you can begin responding to SIF Events.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There are many ways to implement a synchronization procedure, some more involved than others. For example, you might have a user interface for the administrator to control the synchronization process, to choose the kinds of SIF Data Objects to query from the zone, and to provide a way for the administrator to visually match up application records with their corresponding SIF Data Objects. Or, your might opt for a more automated process where the agent requests objects from the zone and tries to match them with application records using a common field such as Student ID. Re-gardless of the approach you take, be sure to include some form of synchronization procedure in your agent&amp;rsquo;s design.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description></item><item><title>Working with SIF Data Objects</title><link>http://sifzone.com/sifzonecs20085/wikis/adkdevguide/working-with-sif-data-objects/revision/1.aspx</link><pubDate>Sat, 07 Feb 2009 02:11:32 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:31</guid><dc:creator>Andrew Elmhorst</dc:creator><comments>http://sifzone.com/sifzonecs20085/wikis/adkdevguide/working-with-sif-data-objects/comments.aspx</comments><description>Revision 1 posted to SIFWorks ADK Developer&amp;#39;s Guide by Andrew Elmhorst on 2/6/2009 9:11:32 PM&lt;br /&gt;
&lt;p&gt;SIFElement &amp;amp; SIFDataObject Classes&lt;/p&gt;
&lt;p&gt;All SIF elements modeled by the ADK are encapsulated by classes derived from a common abstract base class: com.edustructures.sifworks.SIFElement. These in-clude top-level data objects like StudentPersonal as well as complex child elements like Name, Demographics, Transaction, and so on. (A complex element is any element that has attributes or children. In contrast, a simple field element is any element that has only a text value. The ADK does not model field elements as Java classes, but it does supply classes to encapsulate each and every complex element found in the SIF data model.)&lt;/p&gt;
&lt;p&gt;Classes that model top-level SIF Data Objects like StudentPersonal are derived from the SIFDataObject base class, which descends from SIFElement. There are over 115 such data objects in the SIF 2.0r1 Specification.&lt;/p&gt;
&lt;p&gt;The full class hierarchy is as follows:&lt;/p&gt;
&lt;pre&gt;	com.edustructures.sifworks.Element
		com.edustructures.sifworks.SIFElement
			Complex Element Classes
		com.edustructures.sifworks.SIFDataObject
			Data Object Classes
&lt;/pre&gt;
&lt;p&gt;Class Constructors&lt;/p&gt;
&lt;p&gt;Each SIFElement class offers two constructors: a default constructor that accepts no parameters, and another that accepts all required or mandatory elements defined by the SIF Specification. The following code illustrates how to use both forms of constructor. In the first example, a StudentPersonal object is created using that class&amp;rsquo;s default constructor. None of the object&amp;rsquo;s required attributes will have values (in this case the RefId attribute), so it is the responsibility of the agent to ensure they are assigned values before published to SIF.&lt;/p&gt;
&lt;p&gt;In the second example, an Address instance is created using the constructor that accepts a value for each required attribute or element (in this case, AddressType, Street/Line1, City, StateProvice, Country, and PostalCode are all denoted as Mandatory in the SIF Specification.) Using this constructor is a shortcut to explicitly assigning values to required attributes and elements, and makes it easy to create a valid Transaction instance in a single line of code:&lt;/p&gt;
&lt;pre&gt;// Create a StudentPersonal object
StudentPersonal sp = new StudentPersonal();
sp.setRefId( ADK.makeGUID() );

// Create an Address
Address addr = new Address( 
  AddressType.MAILING, new Street( &amp;quot;321 Baker Dr&amp;quot; ), 
  &amp;quot;Metropolis&amp;quot;, StatePrCode.IL, CountryCode.US, &amp;quot;98855&amp;quot; );
&lt;/pre&gt;
&lt;p&gt;Dynamic SIFDataObject Construction&lt;/p&gt;
&lt;p&gt;SIFDataObject instances may also be created dynamically by passing an ElementDef constant to the SIFDTD.createSIFDataObject method, identifying the kind of object to create. (SIFDTD and ElementDef&amp;mdash;two classes central to the SIF Data Objects libraries&amp;mdash;are discussed in subsequent sections.)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;// Kinds of objects to create
ElementDef[] kinds = new ElementDef[] {
		StudentDTD.STUDENTPERSONAL, 
		StudentDTD.STAFFPERSONAL,
		LibraryDTD.LIBRARYPATRONSTATUS };

// Create a bunch of SIFDataObject instances...
SIFDTD metadata = ADK.DTD();
SIFDataObject[] objects = new SIFDataObject[ kinds.length ];
for( int i = 0; i &amp;lt; kinds.length; i++ )
	objects[i] = metadata.createSIFDataObject( kinds[i] );
 
&lt;/pre&gt;
&lt;p&gt;Creating &amp;amp; Manipulating SIFDataObjects&lt;/p&gt;
&lt;p&gt;The ADK supplies two ways to create and manipulate SIFDataObject instances. The first is to programmatically construct objects and call the methods of the SDO classes to get and set element and attribute values. For example,&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;//Constructing a StudentPersonal object
StudentPersonal sp = new StudentPersonal();
sp.setRefId( ADK.makeGUID() );
sp.setName( NameType.LEGAL, &amp;quot;Johnson&amp;quot;, &amp;quot;Clifford&amp;quot; );

// Examining a StudentPersonal object
Name n = sp.getName();
System.out.println( &amp;quot;Name: &amp;quot; + n.getLastName() + &amp;quot;, &amp;quot; + n.getFirstName() );
OtherIdList ids = sp.getOtherIdList();
System.out.println( &amp;quot;This student has &amp;quot; + ids.size() + &amp;quot; IDs&amp;quot; );
&lt;/pre&gt;
&lt;p&gt;You can also use the setElementOrAttribute method:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;// Dynamically constructing a StudentPersonal object
SIFDataObject sp = ADK.DTD().createSIFDataObject( StudentDTD.STUDENTPERSONAL );
sp.setElementOrAttribute( &amp;quot;@RefId&amp;quot;, ADK.makeGUID() );
sp.setElementOrAttribute( &amp;quot;Name[@Type=&amp;#39;01&amp;#39;]/LastName&amp;quot;, &amp;quot;Johnson&amp;quot; );
sp.setElementOrAttribute( &amp;quot;Name[@Type=&amp;#39;01&amp;#39;]/FirstName&amp;quot;, &amp;quot;Clifford&amp;quot; );

// Dynamically examining a StudentPersonal object
Element refId = sp.getElementOrAttribute( &amp;quot;@RefId&amp;quot; );
Element studentId = sp.getElementOrAttribute( &amp;quot;OtherId[@Type=&amp;#39;06&amp;#39;&amp;quot; );
&lt;/pre&gt;
&lt;p&gt;An alternative and more data-driven approach to working with SIFDataObjects is to use the Mappings class from the com.edustructures.sifworks.tools.Mappings package to convert SIFDataObject instances to and from a data source such as a Map by applying a set of XPath-like mapping rules. These rules are usually stored in an ex-ternal configuration file where they can be modified by system integrators in the field. For example, the following rules for StudentPersonal objects define how to translate the elements and attributes of that object to a flat list of field values:&lt;/p&gt;
&lt;pre&gt;&amp;lt;object object=&amp;quot;StudentPersonal&amp;quot;&amp;gt;
	&amp;lt;field name=&amp;quot;STUDENT_ID&amp;quot;&amp;gt;OtherId[@Type=&amp;rsquo;01&amp;rsquo;]&amp;lt;/field&amp;gt;
	&amp;lt;field name=&amp;quot;LAST_NAME&amp;quot;&amp;gt;Name[@Type=&amp;rsquo;01&amp;rsquo;]/LastName&amp;lt;/field&amp;gt;
	&amp;lt;field name=&amp;quot;FIRST_NAME&amp;quot;&amp;gt;Name[@Type=&amp;rsquo;01&amp;rsquo;]/FirstName&amp;lt;/field&amp;gt;
&amp;lt;/object&amp;gt;
&lt;/pre&gt;
&lt;p&gt;You can then call upon the Mappings class to convert a StudentPersonal instance into a Map of field/value pairs, or to convert a Map into a StudentPersonal object.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In practice, most agents use a combination of these two approaches when working with SIF Data Objects. Refer to the chapter on SIF Data Objects for more information.&lt;/p&gt;
&lt;p&gt;The SIFDTD Class&lt;/p&gt;
&lt;p&gt;In order to support all versions of the SIF specification, the ADK has a built-in metadata dictionary. This metadata encompasses information about each element and attribute from all versions of SIF 1.0r1 and later. The class framework relies on this information to determine the versions of SIF each element or attribute supports, its tag name, its sequence number, and various flags such as whether an element is repeatable or not.&lt;/p&gt;
&lt;p&gt;The metadata dictionary is comprised of the static constants defined by a DTD class located within each package in the ADK that contains objects representing SIF elements. Each DTD class defines static ElementDef constants representing each element and attribute of SIF. ElementDef constants identify elements and attributes in a version-independent way so that the class framework knows what your agent is referring to regardless of whether the task at hand involves SIF 1.1, SIF 1.5r1, SIF 2.0r1 or some future version of specification.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Whenever a method requires an ElementDef parameter, you must pass a constant from one of the package-specific DTD classes:&lt;/p&gt;
&lt;pre&gt;	// Create a Topic instance for &amp;quot;BusInfo&amp;quot; and &amp;quot;StudentPersonal&amp;quot; objects
	Topic businfo = getTopicFactory().getInstance( TransDTD.BUSINFO );
	Topic students = getTopicFactory().getInstance( StudentDTD.STUDENTPERSONAL );
&lt;/pre&gt;
&lt;p&gt;SIFDTD Constants for Elements &amp;amp; Attributes&lt;/p&gt;
&lt;p&gt;For elements that are part of the SIF Common Objects group or that otherwise are used across more than one SIF Data Object, each DTD class uses a naming convention to distinguish between the objects a common element appears in.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;For example, the common &amp;lt;Name&amp;gt; element is used in StudentPersonal, StaffPersonal, and StudentContact. However, the characteristics of &amp;lt;Name&amp;gt;&amp;mdash; such as its sequential order relative to its parent&amp;mdash;are different when used as a child of &amp;lt;StudentPersonal&amp;gt; than when used as a child of &amp;lt;StaffPersonal&amp;gt; and &amp;lt;StudentContact&amp;gt;. Thus, the StudentDTD class defines multiple ElementDef constants for the &amp;lt;Name&amp;gt; element:&lt;/p&gt;
&lt;pre&gt;	StudentDTD.STUDENTPERSONAL_NAME
	StudentDTD.STAFFPERSONAL_NAME
	StudentDTD.STUDENTCONTACT_NAME
&lt;/pre&gt;
&lt;p&gt;The naming convention employed is the name of the parent SIF Data Object in upper-case, followed by an underscore (&amp;ldquo;_&amp;rdquo;) and the name of the element or attribute, also in upper-case:&lt;/p&gt;
&lt;pre&gt;[DTDClass].PARENT_CHILD&lt;/pre&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;// Query for all BusInfo objects
Query q = new Query( TransDTD.BUSINFO );

// Include only the RefId, VehicleNumber, and Contractor in the response
q.setFieldRestrictions(
	new ElementDef[] {
		TransDTD.BUSINFO_REFID,
		TransDTD.BUSINFO_VEHICLENUMBER,
		TransDTD.BUSINFO_CONTRACTOR
	}
);
&lt;/pre&gt;
&lt;p&gt;Inspecting the ElementDef of a SIFDataObject&lt;/p&gt;
&lt;p&gt;You can obtain the ElementDef associated with any SIFDataObject instance by calling its getElementDef method. This is often used in Boolean comparisons to determine if an object is of a certain type:&lt;/p&gt;
&lt;pre&gt;SIFDataObject someObject = ...

if( someObject.getElementDef() == StudentDTD.STUDENTPERSONAL )
{
	// This is a StudentPersonal object
	StudentPersonal sp = (StudentPersonal)someObject;
	System.out.println(&amp;quot;StudentPersonal with RefId &amp;quot; + sp.getRefId() );
}
else
if( someObject.getElementDef() == SIFDTD.STUDENTCONTACT )
{
	etc.
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Getting an Element&amp;rsquo;s Tag Name&lt;/p&gt;
&lt;p&gt;The tag name of an element or attribute is specific to each version of SIF. With the ADK, each ElementDef is associated with two names: a version-independent name, which is used to identify the element or attribute regardless of the version of SIF you&amp;rsquo;re working with; and a version-dependent tag name, which is used when rendering and parsing the element. Often times it is necessary to use the element tag name in your code; for example, to log a debug message or to lookup an entry in a table that is keyed by element name.&lt;/p&gt;
&lt;p&gt;If you want to obtain the version-independent name of an element or attribute, call the ElementDef.name method. This method returns the string used to identify the element or attribute in the ADK&amp;rsquo;s metadata dictionary. By convention it is usually equivalent to the name of the element as it first appears in the SIF Specification as of SIF 2.0 or later. .&lt;/p&gt;
&lt;p&gt;For example, calling the name method on the LibraryDtd.TRANSACTION constant re-turns the string &amp;ldquo;Transaction&amp;rdquo;:&lt;/p&gt;
&lt;pre&gt;	// Create a Transaction element and show its version-independent name
	Transaction trans = new Transaction();

	System.out.println( trans.getElementDef().name() );
&lt;/pre&gt;
&lt;p&gt;If you want to obtain the version-dependent name of an element or attribute&amp;mdash;that is, the string used when parsing and rendering the element&amp;mdash;call the ElementDef.tag method. This method requires that a SIFVersion instance be passed to it. Unlike the name method, it returns the tag name specific to the version of SIF. For example, calling tag on the LibraryDTD.TRANSACTION constant yields different results for SIF 1.1 than for SIF 2.0. In SIF 1.1, the element is known as &amp;ldquo;CircTx&amp;rdquo; and in SIF 2.0 it is known as &amp;ldquo;Transaction&amp;rdquo;.&lt;/p&gt;
&lt;pre&gt;// Create a Transaction element and show its version-dependent tag name
Transaction trans = new Transaction();

// Show the tag name for SIF 1.1: &amp;quot;CircTX&amp;quot;
System.out.println( trans.getElementDef().tag( SIFVersion.SIF11 ) );

// Show the tag name for SIF 2.0: &amp;quot;Transaction&amp;quot;
System.out.println( trans.getElementDef().tag( SIFVersion.SIF20 ) );
&lt;/pre&gt;
&lt;p&gt;The above code uses SIFVersion constants but in practice you obtain the SIFVersion associated with a SIF Data Object by calling the SIFDataObject.getSIFVersion me-thod:&lt;/p&gt;
&lt;pre&gt;	public void onEvent( Event event, Zone zone, MessageInfo info )
		throws ADKException
	{
		SIFMessageInfo inf = (SIFMessageInfo)info;

		// Print the version of the SIF_Message envelope 
		System.out.println(&amp;quot;Received a SIF_Event from a SIF &amp;quot; + 
			inf.getSIFVersion() + &amp;quot; agent&amp;quot; );

		// Print the version-dependent tag name of the data contained in the event
		SIFDataObject data = event.getData().readDataObject();
		System.out.println( &amp;quot;A &amp;quot; + data.getElementDef().tag( data.getSIFVersion() ) + 
			&amp;quot; object is contained in the event&amp;quot; );
		System.out.println( &amp;quot;The &amp;quot; + data.getElementDef().name() + &amp;quot; object is a SIF &amp;quot; +
			data.getSIFVersion() + &amp;quot; object&amp;quot; );
&lt;/pre&gt;
&lt;p&gt;The above example might print the following to the Java console:&lt;/p&gt;
&lt;p&gt;&lt;span&gt;	&lt;/span&gt;Received a SIF_Event from a SIF 1.1 agent&lt;/p&gt;
&lt;p&gt;&lt;span&gt;	&lt;/span&gt;A StudentPersonal object is contained in the event&lt;/p&gt;
&lt;p&gt;&lt;span&gt;	&lt;/span&gt;The StudentPersonal object is a SIF 1.1 object&lt;/p&gt;
&lt;p&gt;Building SIF Data Objects Dynamically&lt;/p&gt;
&lt;p&gt;Most agents retrieve their data from a local database or other data store with its own unique schema and programming interfaces. A common approach to interacting with SIF is to dynamically map elements and attributes from a SIF Data Object to fields in the local application&amp;rsquo;s database. The ADK provides a powerful facility for mapping: the Mappings class found in the com.edustructures.sifworks.tools.mapping package. You could also implement your own mapping routines by using functions such as SIFDataObject.setElementOrAttribute.&lt;/p&gt;
&lt;p&gt;The following code creates a StudentPersonal object by enumerating the fields in a mapping table. This code looks much different from most of the code shown through-out the Developer&amp;rsquo;s Guide and ADK Example agents because it does not directly use the SIF Data Object classes like Name, PhoneNumber, and StudentAddress to build the StudentPersonal object. Instead, it uses XPath-like query strings and the setElemen-tOrAttribute method of the SIFDataObject class. With the ADK, you have the flex-ibility to work with SIF Data Objects however you like.&lt;/p&gt;
&lt;p&gt;Refer to the SIFDataObject class in the Javadoc for more information on the setEle-mentOrAttribute method.&lt;/p&gt;
&lt;pre&gt;	// Build a table that maps fields in the local application to SIF 
  // elements &amp;amp; attributes. The key of each entry is a name of your 
  // choosing that identifies a field in the local database; the value 
  // of each entry is an XPath-link query string that identifies
	// the corresponding SIF element or attribute of the StudentPersonal 
  // object

	HashMap m = new HashMap();
	m.put( &amp;quot;ForeignId&amp;quot;,    &amp;quot;@RefId&amp;quot; );
	m.put( &amp;quot;ID&amp;quot;,           &amp;quot;OtherId[@Type=&amp;rsquo;06&amp;rsquo;]&amp;quot; );
	m.put( &amp;quot;L_Name&amp;quot;,       &amp;quot;Name[@Type=&amp;rsquo;01&amp;rsquo;]/LastName&amp;quot; );
	m.put( &amp;quot;F_Name&amp;quot;,       &amp;quot;Name[@Type=&amp;rsquo;01&amp;rsquo;]/FirstName&amp;quot; );
	m.put( &amp;quot;Addr_Line1&amp;quot;,   &amp;quot;StudentAddress/Address[@Type=&amp;rsquo;M&amp;rsquo;]/Street/Line1&amp;quot; );
	m.put( &amp;quot;Addr_Line2&amp;quot;,   &amp;quot;StudentAddress/Address[@Type=&amp;rsquo;M&amp;rsquo;]/Street/Line2&amp;quot; );
	m.put( &amp;quot;Addr_City&amp;quot;,    &amp;quot;StudentAddress/Address[@Type=&amp;rsquo;M&amp;rsquo;]/City&amp;quot; );
	m.put( &amp;quot;Addr_State&amp;quot;,   &amp;quot;StudentAddress/Address[@Type=&amp;rsquo;M&amp;rsquo;]/StatePr/@Code&amp;quot; );
	m.put( &amp;quot;Addr_Zip&amp;quot;,     &amp;quot;StudentAddress/Address[@Type=&amp;rsquo;M&amp;rsquo;]/PostalCode&amp;quot; );
	m.put( &amp;quot;Pri_Email&amp;quot;,    &amp;quot;Email[@Type=&amp;rsquo;Primary&amp;rsquo;]&amp;quot; );
	m.put( &amp;quot;Sec_Email&amp;quot;,    &amp;quot;Email[@Type=&amp;rsquo;Alternate1&amp;rsquo;]&amp;quot; );

	// Now create a StudentPersonal from the mapping table. For each entry 
  // in the table, lookup the associated value in the local application 
  // database, then call the StudentPersonal.setElementOrAttribute method 
  // to assign that value to the corresponding element or attribute in the 
  // SIF Data Object

	StudentPersonal student = new StudentPersonal();
	for( Iterator it = m.keySet().iterator(); it.hasNext(); )
	{
		String localField = (String)it.next();
		String sifField = (ElementDef)m.get( field );

		// Lookup the value of this field from the local application&amp;rsquo;s database
		String value = myDatabaseView.getFieldValue( localField );

		// Assign the field to the StudentPersonal object
		if( value != null )
			student.setElementOrAttribute( sifField, value );
	}
&lt;/pre&gt;
&lt;p&gt;Enumerated Types&lt;/p&gt;
&lt;p&gt;The ADK defines enumerated type classes whenever a set of pre-defined values is ex-pected for an object field. These classes are named the same as the attribute or element they&amp;rsquo;re associated with. For example, the EducationLevel/Code element of the Stu-dentContact data type is represented by the EducationLevelCode class.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As you might expect, the StudentContact.setEducationLevel method accepts a single parameter: an EducationLevelCode object. Valid codes for this object are defined as static constants of the enumerated type class: EducationLevelCode.EMC, EducationLevelCode.E4, etc.&lt;/p&gt;
&lt;p&gt;Enumerated type classes are provided as a convenience to programmers, to enforce type safety, and to help ensure that valid values are used in the construction of SIF messages. There are many cases when referencing one of the pre-defined constants of an enumerated type class is not appropriate: for example, when reading values from a database resultset you will want to assign them directly to an element or attribute. For this reason, all enumerated type classes offer a wrap method that you can use to pass your own string in place of a pre-defined constant. The following code demonstrates:&lt;/p&gt;
&lt;pre&gt;	// Construct a StudentContact object
	StudentContact sc = new StudentContact();

	// Use the enum class to set EducationLevel to &amp;quot;E4&amp;quot;
	sc.setEducationLevel( EducationLevelCode.E4 );

	// Set the code directly
	sc.setEducationLevel( EducationLevelCode.wrap( &amp;quot;E4&amp;quot; ) );

	// Can also set the code to an invalid value
	sc.setEducationLevel( EducationLevelCode.wrap( &amp;quot;Zebra&amp;quot; ) );

&lt;/pre&gt;
&lt;p&gt;Dates and Times&lt;/p&gt;
&lt;p&gt;SIF 2.0 uses XSD data types to represent Dates, DateTimes, and Times. The ADK represents each of these fields using the Java Calendar object.&lt;/p&gt;
&lt;p&gt;Creating RefIds for SIF Data Objects&lt;/p&gt;
&lt;p&gt;When an agent publishes a data object to a zone for the first time, it must assign the object a globally-unique identifier&amp;mdash;or &amp;nbsp;RefId&amp;mdash;that will forever identify that object in the zone. Both the ADK.makeGUID static function and Agent.makeGUID convenience method create Globally Unique Identifiers (GUIDs).&lt;/p&gt;
&lt;pre&gt;	// Create a new StudentPersonal object with a new GUID generated 
  // by this agent
	StudentPersonal sp = new StudentPersonal();
	sp.setRefId( ADK.makeGUID() );
	...
&lt;/pre&gt;
&lt;p&gt;Managing RefIds&lt;/p&gt;
&lt;p&gt;Because it is specific to your agent&amp;rsquo;s transaction layer and involves interaction with a database or other persistent data store, the ADK does not provide any classes to manage RefIds. You will need to create a mechanism to store RefIds created by your agent when publishing SIF Data Objects for the first time, or imported from other agents when receiving objects in SIF_Response and SIF_Event messages. Although there are a number of ways to go about this, one simple solution is to use a database table to record the RefIds known to your agent. The following schema will usually suffice:&lt;/p&gt;
&lt;p&gt;Column&lt;span&gt;	&lt;/span&gt;Data Type&lt;span&gt;	&lt;/span&gt;Definition&lt;/p&gt;
&lt;p&gt;RefId&lt;span&gt;	&lt;/span&gt;Char[32]&lt;span&gt;	&lt;/span&gt;The GUID&lt;/p&gt;
&lt;p&gt;PrimaryKey&lt;span&gt;	&lt;/span&gt;String or Numeric&lt;span&gt;	&lt;/span&gt;The primary key of the record in your appli-cation&amp;rsquo;s database that is associated with this RefId.&lt;/p&gt;
&lt;p&gt;SecondaryKey&lt;span&gt;	&lt;/span&gt;String or Numeric&lt;span&gt;	&lt;/span&gt;The optional secondary key of the record in your application&amp;rsquo;s database that is associated with this RefId.&lt;/p&gt;
&lt;p&gt;ObjectType&lt;span&gt;	&lt;/span&gt;Numeric&lt;span&gt;	&lt;/span&gt;A constant that identifies the type of data as-sociated with this RefId. Consider defining numeric values for each object type; for ex-ample, 1=Students or StudentPersonal; 2=Teachers or StaffPersonal; etc.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;When publishing an object to a zone for the first time, assign a RefId to it and record the association between that RefId and the local application database record. You must use this RefId to subsequently identify the object whenever it is included in a SIF message: for example, when reporting a SIF_Event to a zone.&lt;/p&gt;
&lt;p&gt;When receiving an object in a SIF_Event or SIF_Response message, the agent should first lookup its RefId in the above table. Most SIF Data Objects have an attribute named &amp;ldquo;RefId&amp;rdquo; that you can obtain via the SIFDataObject.getRefId method. If the RefId exists in your table, take the appropriate action on the corresponding database record. For example, if you receive a SIF_Event with a Change action that identifies a student you have on file, update the student record appropriately. However, if you receive a Change event for a student that does not exist in your RefId repository, you cannot take action on the event because the agent doesn&amp;rsquo;t know which student record to update.&lt;/p&gt;
&lt;p&gt;How does the RefId repository get created initially? Edustructures recommends that all agents incorporate some form of &amp;ldquo;synchronization procedure&amp;rdquo; that is run the first time the agent is installed and again at the beginning of each school year. This process retrieves all SIF Data Objects from the zone or zones the agent is connected to, and using an algorithm of &amp;nbsp;your choosing, matches them up with corresponding records in the application database. The goal of synchronization is to establish an initial set of RefIds such that your agent knows which SIF Data Objects equate to the record that already exist in the application&amp;rsquo;s database. Once this process is complete, you can begin responding to SIF Events.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There are many ways to implement a synchronization procedure, some more involved than others. For example, you might have a user interface for the administrator to control the synchronization process, to choose the kinds of SIF Data Objects to query from the zone, and to provide a way for the administrator to visually match up application records with their corresponding SIF Data Objects. Or, your might opt for a more automated process where the agent requests objects from the zone and tries to match them with application records using a common field such as Student ID. Re-gardless of the approach you take, be sure to include some form of synchronization procedure in your agent&amp;rsquo;s design.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description></item></channel></rss>