Lookup Fields
The LookupFields desktop sample demonstrates how to add lookup fields, which derive or "look up" their values from a field in another table's field, to a DADataTable.
Getting Started
The Desktop sample is typically located in /Developer/RemObjects Software/Samples/Data Abstract/Desktop/LookupFields
, though you may have installed the Data Abstract for Cocoa and it's samples in another location.
To build it, you will of course need Xcode, and like all the samples provided with Data Abstract for Cocoa you will need to be running the Relativity Server with the DASamples
Domain and the Simple
Schema available.
Running the Sample
This sample retrieves the records from the "Orders" where their type is "2", it then adds 4 lookup fields which uses values from 4 other tables ("Workers", "Clients", "OrderStatus" and "OrderType") and displays the results in the table.
When this sample is run you will see an empty table and a toolbar which contains a button and a pop-up. The button "Load Orders" will retrieve the required tables and then add the lookup fields before displaying the results in the table. The "Servers" popup contains a list of available servers discovered by the Zeroconf discovery system. When the sample is run, it starts a Zeroconf discovery service that looks for instances of Relativity Server running on the local network. Any discovered servers will be added to the popup, if no servers are discovered then the dropbox on the toolbar will be empty. You can specify a server address yourself by clicking on the popup and then clicking on "Specify custom URL...".
Examining the Code
The code for creating the connection to the server and handling logging in is covered by other samples. In this section we shall focus solely on how you add calculated and lookup fields.
NOTE If the table name, or the field names do not exist then an ROException
will be raised and should be handled appropriately.
App Structure
The sample is built around four classes; AppDelegate
, DataAccess
, ServiceAccess
, and RegisterServiceWindowController
.
The DataAccess
class handles everything related to interacting with the Data Abstract SDK; including retrieving data from an instance of Relativity Server and applying changes back to the server. Here beginGetData
retrieves all of the tables required (Providers
, Clients
, OrderType
, Orders
and OrderDetails
) using the methods getReferences
and getOrders
, then setupData
makes use of those tables to add the calculated and lookup fields; the code below comes from this class.
The ServiceAccess
class handles the discovery of any instances of Relativity Server that are available on the local network using ROZeroConf which is a feature available with the Remoting SDK that Data Abstract is built upon. ServiceAccess
sets up a ROZeroConfBrowser Class object which searches for any servers that broadcast a value matching the value defined for RELATIVITY_SERVICE_NAME
. When a service is found, or indeed disappears, the server list is updated and the popup with the list of available servers is also updated. It also handles the registration of custom server addresses. To explore further the ServiceAccess
class and Zeroconf discovery see the article: The ServiceAccess Class and Zeroconf discovery.
The RegisterServiceWindowController
class is a subclass of NSWindowController
which handles the UI aspects of a user manually adding a server url.
Lastly the AppDelegate
class handles the primary setup of the application, registers that it will listen for notifications broadcast by the ServiceAccess
and DataAccess
classes, and acts as a delegate to the RegisterServiceWindowController
, DataAccess
and NSTableView
classes. The main thing of note is that the dataIsReady
method is called when the NOTIFICATION_DATA_READY
notification is received, which causes the table to update the table with the newly received data.
Adding a Lookup Field
There are two ways to add a lookup field, the first is by using the addLookupFieldName:sourceField:lookupTable:lookupKeyField:lookupResultField: method of DADataTable, the other way is to manually define a DALookupFieldDefinition object and pass it to the table using the addLookupField: method.
Here the addLookupFieldName:sourceField:lookupTable:lookupKeyField:lookupResultField: method is used, which takes the following arguments:
- Name a unique name to be given to the lookup field.
- sourceField the field that will be used as the key value for matching against the
lookupKeyField
- lookupTable takes a reference to the lookup table
- lookupKeyField the key field in the
lookupTable
that will be used to match against thesourceField
- lookupResultField the field in the lookup table that will be used as the result when the
sourceField
andlookupKeyField
match
In the code below there are four lookup fields being added to the "Orders" table. For the first one we are adding a new field with the name "StatusName", whose source field is the Status
field of the Orders
table, this will act as the key we will use to look up a value. The "OrderStatus" table is assigned as the lookup table and the Id
field is field we are going to match against the Status
field. If a match is found the value in the Name
field of the appropriate row is returned.
//DataAccess.m
- (void)setupData {
[self.ordersTable addLookupFieldName:@"StatusName"
sourceField:[self.ordersTable fieldByName:@"Status"]
lookupTable:self.orderStatusTable
lookupKeyField:[self.orderStatusTable fieldByName:@"Id"]
lookupResultField:[self.orderStatusTable fieldByName:@"Name"]];
[self.ordersTable addLookupFieldName:@"TypeName"
sourceField:[self.ordersTable fieldByName:@"Type"]
lookupTable:self.orderTypeTable
lookupKeyField:[self.orderTypeTable fieldByName:@"Id"]
lookupResultField:[self.orderTypeTable fieldByName:@"Name"]];
[self.ordersTable addLookupFieldName:@"ManagerName"
sourceField:[self.ordersTable fieldByName:@"Manager"]
lookupTable:self.workersTable
lookupKeyField:[self.workersTable fieldByName:@"WorkerId"]
lookupResultField:[self.workersTable fieldByName:@"WorkerName"]];
[self.ordersTable addLookupFieldName:@"ClientName"
sourceField:[self.ordersTable fieldByName:@"Contractor"]
lookupTable:self.clientsTable
lookupKeyField:[self.clientsTable fieldByName:@"ClientId"]
lookupResultField:[self.clientsTable fieldByName:@"ClientName"]];
}