Skip Headers

Agile Product Lifecycle Management SDK Developer Guide - Using APIs Release 9.3.3 E39307-01 |
| Contents

Previous | Next |

# 4 Working with Tables

This chapter includes the following:

- About Tables

- Retrieving a Table

- Accessing the New and Merged Relationships Tables

- Retrieving the Metadata of a Table

- Adding Table Rows

- Adding and Updating Multiple Table Rows

- Iterating Over Table Rows

- Sorting Table Rows

- Removing Table Rows

- Retrieving the Referenced Object for a Row

- Checking the Status Flags of a Row

- Working with Page 1, Page 2, and Page 3

- Getting and Setting Revisions and Flags

- Redlining

- Removing Redline Changes

- Identifying Redlined Rows and Redlined Cells

## 4.1 About Tables

Whenever you work with an Agile PLM object in your program, you inevitably need to get and display the object's data. The data is contained in one or more tables. In Agile Web Client, these tables are equivalent to the separate tabs in a window, such as the Manufacturers and BOM tabs.

Figure 4-1 The BOM tab for an item in Agile Web Client.

In some cases, a tab in Agile Web Client contains multiple tables. For example, the Changes tab for an item contains the Pending Changes table and the Change History table. The tabs and the tables that they contain is not always the same for different Agile products. Also, they are not the same for each Agile PLM Dataobject. For example, tables for Parts objects are different from tables for Manufacturers objects. See Retrieving a Table on page 74.

To work with data in an Agile PLM table, follow these basic steps:

1. Create or get an object (for example, an item or a change order).

2. Retrieve a table (for example, the BOM table).

3. Iterate through the table rows to retrieve a row.

4. Get or set one or more attribute values for the selected row.

ITable, like IFolder, extends java.util.Collection and supports all the methods provided by that superinterface. This means that you can work with an ITable object as you would any Java Collection.

Interface | Inherited methods
--- | ---
java.util.Collection | add(), addAll(), clear(), contains(), containsAll(), equals(), hashCode(), isEmpty(), iterator(), remove(), removeAll(), retainAll(), size(), toArray(), toArray()

### 4.1.1 Supported Affected Read Through Tables

SDK supports the following Affected Read Through tables. For more information, refer to SDK samples folder. You can find this folder at: `http://www.oracle.com/technetwork/indexes/samplecode/agileplm-sample-520945.htm`.

- Item.BOM Item.WU Item.PendingChangeWU Change.AI PSR.AI QCR.AI QCR.PSRItem

## 4.2 Retrieving a Table

After you create or get an object, you can use the IDataObject.getTable() method to retrieve a particular Agile PLM table. IDataObject is a general-purpose object that represents any Agile PLM object that contains tables of data. It is a superinterface of several other objects, including IItem, IChange, and IUser.

Note: When retrieving PG&C's Supplier Declaration of Conformance (SDOC) tables, IDataObject.getTable() retrieves all 14 SDOC tables belonging to this base class. However, six of these tables (Items, Manufacturer Parts, Part Groups, Item Composition, Manufacturer Part Composition, Part Group Composition) are not enabled.

Tables vary for each Agile PLM dataobject. Tables for change objects are different from tables for items. Each table for a particular dataobject is identified by a constant in the constants class for that dataobject. Item constants are contained in the ItemConstants class, change constants are contained in the ChangeConstants class, and so on.

For information to use these tables, refer to the following Agile product administration documents:

- Getting Started with Agile PLM

- Agile PLM Administrator Guide

- Agile PLM Product Governance & Compliance User Guide

- Agile PLM Product Portfolio Management User Guide

## 4.3 Accessing the New and Merged Relationships Tables

In Release 9.2.2, the following tables were merged into a single table called the Relationships table.

- Relationships.AffectedBy

- Relationships.Affects

- Relationships.Reference

In addition, the constants that are used by these tables (TABLE_REFERENCES, TABLE_RELATIONSHIPSAFFECTS, and TABLE_RELATIONSHIPSAFFECTEDBY) were also removed. If you need these constants, you must rewrite them in your routines.

Note: For a complete list of table constants that are merged and mapped into a single constants, or mapped into a new constant, see Migrating Release 9.2.1 and Older Table Constants to Release 9.2.2 on page 399.

For information to use these tables, refer to the following Agile documents:

- To use these tables in Agile PLM products, refer to Getting Started with Agile PLM and Agile PLM Administrator Guide

- To use these tables in Agile PPM products, refer to Agile PLM Product Portfolio Management User Guide

### 4.3.1 Accessing the Relationships Table

The IRelationshipContainer interface was implemented to access this table. Any Agile business object that contains the Relationships table implements this interface. You can access this table using IRelationshipContainer, or IDataObject.getTable() with CommonConstants.TABLE_RELATIONSHIPS constant.

IRelationshipContainer container = (IRelationshipContainer) object;

ITable relationship = container.getRelationship();

### 4.3.2 Accessing the Merged Relationships Tables

If you used these tables in previous releases of Agile PLM, and require the functionalities that they provided, modify your code as shown below.

#### 4.3.2.1 Accessing the Merged Relationships.AffectedBy Table

- Code used in Release 9.2.1.x and earlier releases:

ITable affectedBy =

object.getTable(ChangeConstants.TABLE_RELATIONSHIPSAFFECTEDBY);

- Code recommended for this release:

ITable affectedBy =

object.getTable(CommonConstants.TABLE_RELATIONSHIPS)

.where("[2000007912] == 1", null);

#### 4.3.2.2 Accessing the Merged Relationships.Affects table

- Code used in Release 9.2.1.x and earlier releases:

ITable affects =

object.getTable(ChangeConstants.TABLE_RELATIONSHIPSAFFECTS);

- Code recommended for this release:

ITable affects =

object.getTable(CommonConstants.TABLE_RELATIONSHIPS)

.where("[2000007912] == 2", null);

#### 4.3.2.3 Accessing the Merged Relationships.References Table

- Code used in Release 9.2.1.x and earlier releases:

ITable references =

object.getTable(ChangeConstants.TABLE_RELATIONSHIPS_REFERENCES);

- Code recommended for this release:

ITable references =

object.getTable(CommonConstants.TABLE_RELATIONSHIPS)

.where("[2000007912] == 3", null);

Note: The ITable.where() method is certified for deployment with these three tables only, and it may fail if it is used to access other tables from the SDK.

The following example shows how to retrieve and print the BOM table for an item.

Example: Retrieving the BOM table

    //Load an item
    private static IItem loadPart(String number) throws APIException {

IItem item = (IItem)m_session.getObject(ItemConstants.CLASS_PART, number);

return item;

    }
    //Get the BOM table
    private static void getBOM(IItem item) throws APIException {

IRow row;

ITable table = item.getTable(ItemConstants.TABLE_BOM);

Iterator it = table.iterator();

while (it.hasNext()) {

row = (IRow)it.next();

    //Add code here to do something with the BOM table
    IAgileClass cls = admin.getAgileClass(ItemConstants.CLASS_PART);
    }

}

### 4.3.3 Working with Read-only Tables

Several Agile PLM tables store history information or data about related objects. These tables are read-only and as such, you cannot modify these tables. When you write code to access a table, use the ITable.isReadOnly() method to check if the table is read-only.

## 4.4 Retrieving the Metadata of a Table

The ITableDesc is an interface that represents the metadata of a table which is the underlying data that describes a table's properties. ITableDesc is related to ITable in the same way that IAgileClass is related to IDataObject. At times you may need to identify the attributes for a particular table, its ID, or its table name without loading a dataobject. The following example shows how to use the ITableDesc interface to retrieve the collection of all attributes (including ones that aren't visible) for a table.

Example: Retrieving the metadata of a table

    private IAttribute[] getBOMAttributes() throws APIException {
      ITableDesc td = cls.getTableDescriptor(ItemConstants.TABLE_BOM);
      IAttribute[] attrs = td.getAttributes();
      return attrs;
    }

You can also use the API Name field to identify a table's name or ID. For information to use this field, see Accessing PLM Metadata with APIName Field on page 135. For information to use the Agile API to work with metadata, see Performing Administrative Tasks on page 367.

## 4.5 Adding Table Rows

To create a table row, use the ITable.createRow(java.lang.Object) method, which creates a new row and initializes it with the data specified in the param parameter. The param parameter of createRow is available to pass the following data:

- a set of attributes and values for the row's cells

- files or URLs to add to the Attachments table

- an Agile PLM object (such as an IItem) to add to the table

When you add a row to a table, it's not necessarily added at the end of the table.

Note: There is also a deprecated, parameter-less version of the createRow() method, which creates an empty row. Avoid using that method because it may not be supported in future Agile PLM releases. You must initialize a row with data when you create it.

You can also add table rows in batch format with ITable.createRow(). See Adding and Updating Multiple Table Rows on page 79.

### 4.5.1 Adding an Item to the BOM Table

The following example shows how to use the ITable.createRow() method to add an item to a BOM table.

Adding a row and setting values

    private static void addToBOM(String number) throws APIException {
    }

IItem item =

(IItem)m_session.getObject(ItemConstants.CLASS_PART, number);

ITable table =

item.getTable(ItemConstants.TABLE_BOM);

Map params = new HashMap();

params.put(ItemConstants.ATT_BOM_ITEM_NUMBER, "1543-01");

params.put(ItemConstants.ATT_BOM_QTY, "1");

item.setManufacturingSite(ManufacturingSiteConstants.COMMON_SITE);

    IRow row = table.createRow(params);

Note: To add a site-specific row to the BOM table, use IManufacturerSiteSelectable.setManufacturingSite() to select a specific site before calling ITable.createRow().

### 4.5.2 Adding an Attachment to the Attachments Table

The following example shows how to use the ITable.createRow(java.lang.Object) method to add a row to the Attachments table. The code adds a row to the table and initializes it with the specified file. After adding the row, the code also sets the value of the File Description field.

Adding a row to the Attachments table

    private static void addAttachmentRow(String number) throws APIException {
    File file = new File("d:/MyDocuments/1543-01.dwg");
      IItem item = (IItem)m_session.getObject(ItemConstants.CLASS_PART, number);
      ITable table = item.getTable(ItemConstants.TABLE_ATTACHMENTS);
      IRow row = table.createRow(file);
    }

#### 4.5.2.1 Increasing the Default Value of agile.sso.expirationTime to Add Attachments

Anytime the ITable.createRow(java.lang.Object) method fails to add attachments and generates the java.lang.NullPointerException error, you must modify the value of agile.sso.expirationTime,the duration in seconds, between the time that you log in and authentication by the PLM FileManager. The default value is 120 seconds which is not enough, modify the default setting as shown below.

To modify the value of agile.sso.expirationTime

1. Locate agile.properties file.

   Depending on your installation, the three possible locations for this file are:

   · <Agile_Home>\agileDomain\applications\application.ear\APP-INF\classes\

   Note: This path is generated after PLM is installed.

   · <Agile_Home>\agileDomain\config

   Note: This path is generated after PLM is installed.

   · <Agile_Home>\agileDomain\servers\BEJ301388-AgileServer\tmp\_WL_user\AgilePLM\eokg58\APP-INF\classes

   Note: This path is generated after starting the server. You can delete it, but will regenerate as part the WebLogic Server startup process. The directory eokg58 is generated randomly.

2. In agile.properties file, increase the value of agile.sso.expirationTime from 120 seconds to a larger number, for example, 600 seconds.

3. Restart the Agile PLM server.

### 4.5.3 Adding a Manufacturer Part to the Manufacturers Table

The following example shows how to use the ITable.createRow(java.lang.Object) method to add a row to the Manufacturers table of an item. The code adds a row to the table and initializes it with the specified IManufacturerPart object.

Adding a row to the Manufacturers table

    private static void addMfrPartRow(String number) throws APIException {
    HashMap info = new HashMap();
      info.put(ManufacturerPartConstants.ATT_GENERAL_INFO_MANUFACTURER_PART_NUMBER, "TPS100-256");
      info.put(ManufacturerPartConstants.ATT_GENERAL_INFO_MANUFACTURER_NAME, "TPS_POWER");
      IManufacturerPart mfrPart = (IManufacturerPart)m_session.getObject(
        ManufacturerPartConstants.CLASS_MANUFACTURER_PART, info
      );
      IItem item = (IItem)m_session.getObject(ItemConstants.CLASS_PART, number);
      item.setManufacturingSite(ManufacturingSiteConstants.COMMON_SITE);
      ITable table = item.getTable(ItemConstants.TABLE_MANUFACTURERS);
      IRow row = table.createRow(mfrPart);
    }

Note: To add a site-specific row to the Manufacturers table, use IManufacturerSiteSelectable.setManufacturingSite() to select a specific site before calling ITable.createRow().

### 4.5.4 Adding an Item to the Affected Items Table

The following example shows how to use the ITable.createRow(java.lang.Object) method to add a row to the Affected Items table of a change order. The code adds a row to the table and initializes it with the specified IItem object.

Example: Adding a row to the Affected Items table

    private static void addItemRow(String number) throws APIException {
    IItem item = (IItem)m_session.getObject(ItemConstants.CLASS_PART, "P522-103");
      IChange change = (IChange)m_session.getObject(ChangeConstants.CLASS_ECO, number);
      ITable table = change.getTable(ChangeConstants.TABLE_AFFECTEDITEMS);
      IRow row = table.createRow(item);
    }

Because the BOM table also references IItem objects, you can use code similar to those in Example 49 to add a row to a BOM table.

### 4.5.5 Adding a Task to the Schedule Table

The following example shows how to use the ITable.createRow(java.lang.Object) method to add a row to the Schedule table of a Project. The code adds a row to the table and initializes it with the specified IProgram object.

Example: Adding a row to the Schedule table

    private static void addTaskRow(IProgram program, IProgram task) throws APIException {
    // Get the Schedule table of the program
      ITable table = program.getTable(ProgramConstants.TABLE_SCHEDULE);
      // Add the task to the schedule
      IRow row = table.createRow(task);
    }

## 4.6 Adding and Updating Multiple Table Rows

The ITable interface provides two convenient methods for adding and updating multiple table rows with one API call:

- ITable.createRows()

- ITable.updateRows()

Because these methods group multiple table rows in one API call, they can improve performance by reducing the number of Remote Procedure Calls (RPCs), particularly if you are connecting to the server across a Wide Area Network (WAN). However, these methods do not result in efficient batch operations on the Agile Application Server, which simply iterates through each row being added or updated.

Important: The ITable.createRows() and ITable.updateRows() methods are supported only when you are adding or updating multiple rows on the BOM table of items, or the Affected Items table of Changes.

### 4.6.1 Adding Multiple Team Members to the Team Table of a Project

The following example shows how the ITable.createRows() method supports the Team Table of a Project.

Example: Adding Multiple Team members to a Program using the Bulk API

    private static void createTeamRows(String[] addTeamMembers) throws APIException {
    IItem[] child = new IItem [3];

//Get the Project

IProgram program = (IProgram)session.getObject(IProgram.OBJECT_TYPE, programNumber);

//Get the Team Table

ITable teamTable = program.getTable(ProgramConstants.TABLE_TEAM);

IAgileList attrRolesValues = teamTable.getAvailableValues(ProgramConstants.ATT_TEAM_ROLES);

attrRolesValues.setSelection(new Object[]{"Change Analyst","Program Team Member"});

//Collect team members already on Team Table

Set presentMembers = new HashSet();

Iterator it = teamTable.iterator();

while(it.hasNext()) {

IRow row = (IRow)it.next();

IUser user = (IUser)row.getReferent();

presentMembers.add(user);

}

//Validate new team members and filter out existing members to and to Team Table

IUser user = null;

IUser[] newUsers= new IUser[addTeamMembers.length];

int usrCount = 0;

for(int i =0; i<addTeamMembers.length; i++ ) {

user = (IUser)session.getObject(IUser.OBJECT_TYPE, addTeamMembers[i]);

if(!presentMembers.contains(user) || user==null) {

newUsers[usrCount++]=user;

}

}

//Using createRows() API to add all Team members at onece

//In this bulk approach, make sure each map in array is complete by it self to create a new row in Team Table.

List<Map> newTeam=new ArrayList<Map>();

for (int i=0; i<usrCount; i++) {

Map teamMap = new HashMap();

teamMap.put(ProgramConstants.ATT_TEAM_NAME, newUsers[i]); teamMap.put(ProgramConstants.ATT_TEAM_ROLES, attrRolesValues); teamMap.put(ProgramConstants.ATT_TEAM_ALLOCATION, 0); newTeam.add(teamMap);

}

teamTable.createRows(newTeam.toArray(new Object[0]));

}

### 4.6.2 Adding Multiple Items to the BOM Table

The following example shows how to use the ITable.createRows() method to add multiple items to a BOM table.

Example: Adding multiple rows and setting values

    private static void createBOMRows(String partNumber) throws APIException {
      IItem parent = null;
      ITable tab = null;

      // Get the parent item
      parent = (IItem) m_session.getObject(IItem.OBJECT_TYPE, partNumber);
      // Get the BOM table
      tab = parent.getTable(ItemConstants.TABLE_BOM);

      // Create child items
      child[0] = (IItem) m_session.createObject(ItemConstants.CLASS_PART, partNumber + "-1");
      child[1] = (IItem) m_session.createObject(ItemConstants.CLASS_PART, partNumber + "-2");
      child[2] = (IItem) m_session.createObject(ItemConstants.CLASS_PART, partNumber + "-3");
      // Create a row array
      IRow[] rowArray = new IRow[3];

      // Add the items to the BOM
      rowArray = tab.createRows(new Object[]{child[0], child[1], child[2]});
    }

Note: To add a site-specific row to the BOM table, use IManufacturerSiteSelectable.setManufacturingSite() to select a specific site before calling ITable.createRow().

### 4.6.3 Updating Multiple BOM Rows

To update multiple rows, use the ITable.updateRows() method. This method batches together multiple update operations into a single call. Instead of calling IRow.setValues() for multiple rows in a table, this API updates an entire table in one method call.

The rows parameter of updateRow() can be used to pass a Map containing IRow instances as keys with instances for values. The value Map objects should have attribute IDs as keys and replacement data for values.

Example: Updating multiple BOM rows

    private static void updateBOMRows(String partNumber) throws APIException {
    IItem parent = null;
      ITable tab = null;
      HashMap[] mapx = new HashMap[3];
      Map rows = new HashMap();
      IRow[] rowArray = new IRow[3];

    // Get the parent item
    parent = (IItem) m_session.getObject(IItem.OBJECT_TYPE, partNumber);
    // Get the BOM table
    tab = parent.getTable(ItemConstants.TABLE_BOM);

    // Create three items
    IItem child1 = (IItem) m_session.createObject(ItemConstants.CLASS_PART, partNumber + "-1");
    IItem child2 = (IItem) m_session.createObject(ItemConstants.CLASS_PART, partNumber + "-2");
    IItem child2 = (IItem) m_session.createObject(ItemConstants.CLASS_PART, partNumber + "-3");
    // Add these items to BOM table rowArray = tab.createRows(new Object[]{child1, child2, child3});
    // New values for child[0]
    mapx[0] = new HashMap();
    mapx[0].put(ItemConstants.ATT_BOM_FIND_NUM, new Integer(1));
    mapx[0].put(ItemConstants.ATT_BOM_QTY, new Integer(3));
    mapx[0].put(ItemConstants.ATT_BOM_REF_DES, "A1-A3");
    rows.put(rowArray[0], mapx[0]);
    // New values for child[1]
    mapx[1] = new HashMap();
    mapx[1].put(ItemConstants.ATT_BOM_FIND_NUM, new Integer(2));
    mapx[1].put(ItemConstants.ATT_BOM_QTY, new Integer(3));
    mapx[1].put(ItemConstants.ATT_BOM_REF_DES, "B1-B3");
    rows.put(rowArray[1], mapx[1]);
    // new values for child[2]
    mapx[2] = new HashMap();
    String strA = "BOM-Notes" + System.currentTimeMillis();
    mapx[2].put(ItemConstants.ATT_BOM_BOM_NOTES, strA);
    mapx[2].put(ItemConstants.ATT_BOM_FIND_NUM, new Integer(3));
    rows.put(rowArray[2], mapx[2]);
    // Update the BOM table rows
    tab.updateRows(rows);
    }

## 4.7 Iterating Over Table Rows

When you use the Agile API to get a table, such as a BOM table, your program often needs to browse the rows contained in the table. To access an individual row, you first have to get an iterator for the table. You can then iterate over each row to set cell values.

The Agile API does not support random access of rows in a table. This means that you can't retrieve a specific row by index number and then update it. When you add or remove a row, the entire table is resorted and the existing table iterator is no longer valid.

To browse the data in table, create an iterator for the table using one of these methods:

- ITable.iterator() - returns an Iterator object, allowing you to traverse the table from the first row to the last.

- ITable.getTableIterator() - returns an ITwoWayIterator object, allowing you to traverse the table rows forwards or backwards. You can also use ITwoWayIterator to skip a number of rows. ITwoWayIterator is preferred over Iterator if your program displays table rows in a user interface.

- ITable.getTableIterator(ITable.ISortBy[]) - returns a sorted ITwoWayIterator object.

- ITable.getReferentIterator() - returns an ITwoWayIterator object for the objects referenced in the table.

When you work with an iterator for a table, you don't need to know the total number of rows in the table. Instead, you work with one row at a time. Although the ITable interface provides a size() method, which calculates the total number of rows in the table, it's considered a resource extensive operation performance-wise and as such, is not recommended for large tables, particularly if your code already uses an iterator to browse the table.

The following example demonstrates how to get an iterator for a table and use ITwoWayIterator to traverse forwards and backwards over the table rows.

Example: Iterating over table rows

    try {
    // Get an item
      IItem item = (IItem)m_session.getObject(ItemConstants.CLASS_PART, "1000-02");
      // Get the BOM table
      ITable bom = item.getTable(ItemConstants.TABLE_BOM);
      ITwoWayIterator i = bom.getTableIterator();
      // Traverse forwards through the table
      while (i.hasNext()) {
        IRow row = (IRow)i.next();
        // Add code here to do something with the row
      }
      // Traverse backwards through the table
      while (i.hasPrevious()) {
        IRow row = (IRow)i.previous();
        // Add code here to do something with the row
      }
    } catch (APIException ex) {
      System.out.println(ex);
    }

The ITwoWayIterator object allows a user interface to display table rows on multiple pages, which is perhaps more practical than the use of ITwoWayIterator shown in the preceding example. For example, instead of displaying a single scrolling page of several hundred BOM items, you can break the table into pages displaying 20 BOM items per page. To navigate from page to page, your program should provide navigation controls such as those shown in the figure below.

### 4.7.1 Updating Objects in Query Results with Multiple Page Tables

When you invoke getReferentIterator to update objects in search results tables that contain more than 200 results, getReferentIterator will not update all the objects that are returned by the query. For example, when you run a query to match a value in a field, and then edit the same value while iterating through the results with getReferentIterator, the query completes the first page with no problem. However, when it queries the remaining pages, some table rows are not updated. There are several ways to overcome this limitation. The following is one such example.

Example: Updating all table rows when iterating large query results

1. Increase the table page size for this query so that it can contain the results in a single page.

2. Run the query several times and keep updating the results until query results are empty.

3. Do not query on the same field that you are updating.

## 4.8 Sorting Table Rows

To sort the rows in a table by a particular attribute, use getTableIterator(ITable.ISortBy[]) to return a sorted iterator. The ISortBy parameter of getTableIterator() is an array of ITable.ISortBy objects. To create an ISortBy object, usecreateSortBy(IAttribute, ITable.ISortBy.Order). The order parameter of createSortBy() is one of the ITable.ISortBy.Order constants either ASCENDING or DESCENDING.

Note: The Agile API allows you to sort a table by only one attribute. Therefore, the ISortBy array that you specify for the ISortBy parameter of getTableIterator() must contain only one ISortBy object.

The following example sorts the BOM table by the BOM | Item Number attribute.

Example: Sorting a table iterator

    try {
    // Get an item
      IItem item = (IItem)m_session.getObject(ItemConstants.CLASS_PART, "1000-02");
      // Get the BOM table
      ITable bom = item.getTable(ItemConstants.TABLE_BOM);
      // Get the BOM | Item Number attribute
      IAgileClass cls = item.getAgileClass();
      IAttribute attr = cls.getAttribute(ItemConstants.ATT_BOM_ITEM_NUMBER);

      // Specify the sort attribute for the table iterator
      ITable.ISortBy sortByNumber = bom.createSortBy(attr, ITable.ISortBy.Order.ASCENDING);
      // Create a sorted table iterator
      ITwoWayIterator i = bom.getTableIterator(new ITable.ISortBy[] {sortByNumber});
      // Traverse forwards through the table
      while (i.hasNext()) {
        IRow row = (IRow)i.next();
        // Add code here to do something with the row
      }
    } catch (APIException ex) {
      System.out.println(ex);
    }

The following Product Sourcing and Projects Execution objects load tables a bit differently and therefore cannot be sorted using the getTableIterator(ITable.ISortBy[]) method. For any tables of these objects, create an unsorted iterator using the iterator() or getTableIterator() methods.

- IDiscussion

- IPrice

- IProgram

- IProject

- IRequestForQuote

- ISupplier

- ISupplierResponse

The ITable.ISortBy interface is not supported for query result tables. To sort query results, use SQL syntax and specify an ORDER BY statement with the search criteria. For more information, see Using SQL Syntax for Search Criteria on page 54 .

## 4.9 Removing Table Rows

To remove a row from a table, use the ITable.removeRow() method, which takes one parameter, an IRow object. You can retrieve a row by iterating over the table rows.

If a table is read-only, you can't remove rows from it. For more information, see Working with Read-only Tables (on page 76, http://www.). If you are working with a released revision of an item, you can't remove a row from the item's tables until you create a change order for a new revision.

Example: Removing a table row

    try {
    // get an item
      IItem item = (IItem)m_session.getObject(ItemConstants.CLASS_PART, "1000-02");
      // get the BOM table
      ITable bom = item.getTable(ItemConstants.TABLE_BOM);
      ITwoWayIterator i = bom.getTableIterator();
      // find the bom component 6642-01 and remove it
      while (i.hasNext()) {
        IRow row = (IRow)i.next();
        String bomitem = (String)row.getValue(ItemConstants.ATT_BOM_ITEM_NUMBER);
        if (bomitem.equals("6642-01")) {
          bom.removeRow(row);
          break;
        }
      }
    } catch (APIException ex) {
      System.out.println(ex);
    }
    Because ITable implements the Collection interface, you can use Collection methods to remove table rows. To remove all rows in a table, use Collection.clear().
    Clearing a table
    public void clearAML(IItem item) throws APIException {
      // Get the Manufacturers table
      ITable aml = item.getTable(ItemConstants.TABLE_MANUFACTURERS);
      // Clear the table
      aml.clear();

    }

## 4.10 Retrieving the Referenced Object for a Row

Several Agile PLM tables contain rows of information that reference other Agile PLM objects. For example, the BOM table lists all items that are included in a Bill of Material. Each row of the BOM table represents an item. While working with a row on a BOM table, your program can allow the user to open the referenced item to view or modify its data.

The table below lists Agile PLM tables that reference other Agile PLM objects. All Agile PLM objects are referenced by number (for example, Item Number, Change Number, or Manufacturer Part Number).

Object | Table | Referenced Object(s)
--- | --- | ---
IChange | Affected Items Affected Prices Attachments Relationships | IItem IPrice IAttachmentFile Multiple object types
ICommodity | Attachments Compositions Parts Specifications Substances Suppliers | IAttachmentFile IDeclaration IItem ISpecification ISubstance ISupplier
ICustomer | Attachments Quality PSRs Quality QCRs | IAttachmentFile IServiceRequest IQualityChangeRequest
IDeclaration | Attachments Item Composition Items Manufacturer Part Composition Manufacturer Parts Part Group Composition Part Groups Relationships Specifications | IAttachmentFile ISubstance IItem ISubstance IManufacturerPart ISubstance ICommodity Multiple object types ISpecification
IDiscussion | Attachments Where Used | IAttachmentFile Not supported
IFileFolder | Files Relationships Where Used | IAttachmentFile Multiple object types Multiple object types
IItem | Attachments BOM Change History Compositions Manufacturers Pending Change Where Used Pending Changes Prices Quality Redline BOM Redline Manufacturers Sites Specifications Substances Where Used | IAttachmentFile IItem IChange IDeclaration IManufacturerPart IItem IChange IPrice IServiceRequest or IQualityChangeRequest IItem IManufacturerPart IManufacturingSite ISpecification ISubstance IItem
IManufacturerPart | Attachments Compositions Prices Specifications Substances Suppliers Where Used | IAttachmentFile IDeclaration IPrice ISpecification ISubstance ISupplier IItem
IManufacturer | Attachments Where Used | IAttachmentFile IManufacturerPart
IManufacturingSite | Attachments | IAttachmentFile
IPackage | Attachments | IAttachmentFile
IPrice | Attachments Change History Pending Changes | IAttachmentFile IChange IChange
IProgram | Attachments Deliverables - Affected By Deliverables - Affects Dependencies - Dependent Upon Dependencies - Required For Discussion Links Schedule Team | IAttachmentFile Multiple object types Multiple object types IProgram IProgram IDiscussion Multiple object types IProgram IUser and IUserGroup
IProject | Attachments BOM Item Changes Items Manufacturer Items Pending Change Responses RFQs | IAttachmentFile IItem IChange IItem IManufacturerPart IChange ISupplierResponse IRequestForQuote
IQualityChangeRequest | Affected Items Attachments PSR Items Relationships | IItem IAttachmentFile IItem Multiple object types
IRequestForQuote | Attachments | IAttachmentFile
IServiceRequest | Affected Items Attachments Related PSR Relationships | IItem IAttachmentFile IServiceRequest Multiple object types
ISpecification | Attachments Substances | IAttachmentFile ISubstance
ISubstance | Attachments Composition Where Used | IAttachmentFile ISubstance Multiple object types
ISupplierResponse | Attachments | IAttachmentFile
ISupplier | Attachments Manufacturers Quality PSRs Quality QCRs | IAttachmentFile IManufacturer IServiceRequest IQualityChangeRequest
ITransferOrder | Attachments Selected Objects | IAttachmentFile Multiple object types
IUser | Attachments Subscription User Group | IAttachmentFile Multiple object types IUserGroup
IUserGroup | Attachments Users | IAttachmentFile IUser

The following example shows how to retrieve the referenced IChange object from the Pending Changes table for an item.

Example: Retrieving a referenced Change object

    void getReferencedChangeObject(ITable changesTable) throws APIException {
    Iterator i = changesTable.iterator();
      while (i.hasNext()) {
        IRow row = (IRow)i.next();
        IChange changeObj = (IChange)row.getReferent();
        if (changeObj != null) {
          //Add code here to do something with the IChange object
        }
      }
    }

The following example shows how to simplify the code in the previous example by using the ITable.getReferentIterator() method to iterate through the table's referenced objects.

Example: Iterating through referenced objects

    void iterateReferencedChangeObjects(ITable changesTable) throws APIException {
    Iterator i = changesTable.getReferentIterator();
      while (i.hasNext()) {
        IChange changeObj = (IChange)i.next();
        if (changeObj != null) {
          //Add code here to do something with the IChange object
        }
      }
    }

## 4.11 Checking the Status Flags of a Row

Sometimes you may want to perform an action on an object only if it meets certain status criteria. For example, if the selected object is a released change order, your program may not allow the user to modify it. To check the status of an object, use the IRow.isFlagSet() method. The isFlagSet() method returns a boolean value true or false.

Status flag constants are defined in the following classes:

- CommonConstants - Contains status flag constants common to Agile PLM objects.

- ChangeConstants - Contains status flag constants for IChange objects.

- ItemConstants - Contains status flag constants for IItem objects.

The following example shows how to use the isFlagSet() method to determine whether an item has attachments.

Example: Checking the status flag of an object

    private static void checkAttachments(IRow row) throws APIException {
    try {
        boolean b;
        b = row.isFlagSet(CommonConstants.FLAG_HAS_ATTACHMENTS);
        if (!b) {
          JOptionPane.showMessageDialog(null, "The specified row does not
          have attached files.", "Error", JOptionPane.ERROR_MESSAGE);
        }
      } catch (Exception ex) {}
    }

## 4.12 Working with Page 1, Page 2, and Page 3

Page One (that is, Title Block, Cover Page, and General Info pages), Page Two, and Page Three contain a single row of data and are therefore not tabular in format. All other tables contain multiple rows. Consequently, the data on Page One, Page Two, and Page Three is directly accessible. To get and set values for these pages, you don't need to get a table and then select a row. Instead, get a specified cell, and then use the getValue() and setValue() methods to display or modify the data.

The SDK supports the following Page 2

If you prefer accessing data cells in a consistent way throughout your program, you can still use the Page One, Page Two, and Page Three tables to get and set values. The following example shows two methods that edit the values for several Page Two fields for an item. The first method retrieves the Page Two table and then sets the values for several cells. The second method accesses the Page Two cells directly by calling the IDataObject.getCell() method. Either approach is valid, but you can see that the second approach results in fewer lines of code.

Example: Editing Page Two cells

    // Edit Page Two cells by first getting the Page Two table
    private static void editPageTwoCells(IItem item) throws Exception {
      ICell cell = null;
      DateFormat df = new SimpleDateFormat("MM/dd/yy");
      ITable table = item.getTable(ItemConstants.TABLE_PAGETWO);
      Iterator it = table.iterator();
      IRow row = (IRow)it.next();
      cell = row.getCell(ItemConstants.ATT_PAGE_TWO_TEXT01);
      cell.setValue("Aluminum clips");
      cell = row.getCell(ItemConstants.ATT_PAGE_TWO_MONEY01);
      cell.setValue(new Money(new Double(9.95), "USD"));
      cell = row.getCell(ItemConstants.ATT_PAGE_TWO_DATE01);
      cell.setValue(df.parse("12/01/03"));
    }
    // Edit Page Two cells by calling IDataObject.getCell()
    private static void editPageTwoCells2(IItem item) throws Exception {
      ICell cell = null;
      DateFormat df = new SimpleDateFormat("MM/dd/yy");
      cell = item.getCell(ItemConstants.ATT_PAGE_TWO_TEXT01);
      cell.setValue("Aluminum clips");
      cell = item.getCell(ItemConstants.ATT_PAGE_TWO_MONEY01);
      cell.setValue(new Money(new Double(9.95), "USD"));
      cell = item.getCell(ItemConstants.ATT_PAGE_TWO_DATE01);
      cell.setValue(df.parse("12/01/03"));
    }

## 4.13 Working with Revisions and Relationships

SDK has added additional attributes in the `CommonConstants` Class to support these new features, described below.

### 4.13.1 Setting and Getting Flags for Revision Controlled Relationship Rows

SDK supports setting and getting the following flags for Relationship rows that are Revision controlled.

- RevisionChangeTrack Impact

Note: Because the impacted flag is set by releasing the change, SDK does not need to support setting the impacted flag.

To enable this feature, the following attributes are added in SDK's `CommonConstants` class:

    public static final Integer ATT_RELATIONSHIPS_REVISION = new Integer(2000025267);   public static final Integer ATT_RELATIONSHIPS_IMPACTED = new Integer(2000025266);   public static final Integer ATT_RELATIONSHIPS_TRACK_IMPACT = new Integer(2000025268);   public static final Integer ATT_RELATIONSHIPS_CHANGE = new Integer(2000025422);

The following example uses these attributes to set the revision change and track flags.

    IItem item = (IItem) session.getObject(ItemConstants.CLASS_PART,              "P00001");       IChange change = (IChange) session.getObject(ChangeConstants.CLASS_ECO,              "C00001");       item.setRevision(change);       IRelationshipTable table = (IRelationshipTable) change              .getRelationship();       Iterator it = table.iterator();       while (it.hasNext()) {           IRow row = (IRow) it.next();           Object revision = row.getValue(ItemConstants.ATT_RELATIONSHIPS_REVISION);           Object impacted = row.getValue(ItemConstants.ATT_RELATIONSHIPS_IMPACTED);           Object trackImpact = row.getValue(ItemConstants.ATT_RELATIONSHIPS_TRACK_IMPACT);           Object rchange = row.getValue(ItemConstants.ATT_RELATIONSHIPS_CHANGE);           row.setValue(ItemConstants.ATT_RELATIONSHIPS_TRACK_IMPACT, "Yes");       }

#### 4.13.1.1 Getting Flags on Relationship Tab when Adding Revision Controlled Object Revisions

The IRelationshipTable is the interface for operations that are specific to the Relationships table. Once a Relationships table is retrieved, you can cast the `ITable` object to `IRelationshipTable` and use the following methods:

- getRevisions(IDataObject dataObject) throws APIException: Gets all available revision values including ALL and Latest which can be used for adding revision specific relationships

- addRevSpecificRelationship(IDataObject reatedObject,Object: Gets all available revision values including ALL and Latest which can be used for adding revision specific relationships

- acceptNewRevisions(IRow[] rows) throws APIException: Accepts all new revisions

- rejectNewRevisions(IRow[] rows) throws APIException: Rejects all new revisions

#### 4.13.1.2 Setting Different Relationships and Revisions for Items

Because SDK can interact with Revision, Change, Impacted attributes and the Track Impact attribute, you can set different relationships when setting different revisions for an Item.

Example 4-1 Setting changes for Item's Revisions and Relationships

    item.setRevision(change);IRelationshipTable table = (IRelationshipTable) change.getRelationship();

## 4.14 Redlining

When you issue a change for a released item or a price agreement, the Agile API lets you redline certain tables affected by the change. In the Agile PLM Clients, redline tables visually identify values that have been modified from the previous revision. Red underlined text-thus the term "redline"-indicates values that have been added, and red strikeout text indicates values that have been deleted. People responsible for approving the change can review the redline data.

The Agile PLM system provides the following redline tables:

- Redline BOM

- Redline Manufacturers (AML)

- Redline Price Lines

- Redline Title Block

Note The Web Client supports redlining the Item's Cover Page, Page Two, and Page Three tables together. However, in the SDK, these operations are performed separately, using different tables for each page.

To redline BOM, Manufacturers, or Price Lines tables:

1. Get a released revision of an item or price object.

2. Create a new change, such as an ECO, MCO, SCO, or PCO

   · ECOs let you modify an item's BOM or Manufacturers tables

   · MCOs let you modify an item's Manufacturers table

   · SCOs let you modify an item's site-specific BOM, Manufacturers

   · PCOs let you modify a price's Price Lines table

3. Add the item or price to the Affected Items or Affected Prices table of the change.

4. For ECOs and PCOs, specify the new revision for the change.

5. SCOs and MCOs do not affect an item's revision.

6. Modify a redline table, such as the Redline BOM, Redline Manufacturers (AML), Redline Price Lines.

To redline the Manufacturers table of an item:

This example shows how to redline the Manufacturers table (AML) of an item.

Example: Redlining the Manufacturers table of an item

    private void redlineAML() throws APIException {
    item.setRevision(rev);

IAttribute attrPrefStat = null;

IAgileList listvalues = null;

Map params = new HashMap();

    // Get a released item
    // Get the Preferrred status value

IItem item = (IItem)m_session.getObject("Part", "1000-02");

IAgileClass cls = item.getAgileClass();

attrPrefStat = cls.getAttribute(ItemConstants.ATT_MANUFACTURERS_PREFERRED_STATUS);

listvalues = attrPrefStat.getAvailableValues();

listvalues.setSelection(new Object[] { "Preferred" });

    // Create an MCO
    // Set the Workflow ID of the MCO

IChange change = (IChange)m_session.createObject(ChangeConstants.CLASS_MCO, "M000024");

change.setWorkflow(change.getWorkflows()[0]);

    // Get the Affected Items table
    // Add a new row to the Affected Items table

ITable affectedItems = change.getTable(ChangeConstants.TABLE_AFFECTEDITEMS);

IRow affectedItemRow = affectedItems.createRow(item);

    // Get the Redline Manufacturers table
    // Add a manufacturer part to the table

ITable redlineAML = item.getTable(ItemConstants.TABLE_REDLINEMANUFACTURERS);

params.put(ItemConstants.ATT_MANUFACTURERS_MFR_NAME, "AMD");

params.put(ItemConstants.ATT_MANUFACTURERS_MFR_PART_NUMBER, "1234-009");

params.put(ItemConstants.ATT_MANUFACTURERS_PREFERRED_STATUS, listvalues);

redlineAML.createRow(params);

    // Add another manufacturer part to the table

params.clear();

params.put(ItemConstants.ATT_MANUFACTURERS_MFR_NAME, "DIGITAL POWER");

params.put(ItemConstants.ATT_MANUFACTURERS_MFR_PART_NUMBER, "355355");

params.put(ItemConstants.ATT_MANUFACTURERS_PREFERRED_STATUS, listvalues);

redlineAML.createRow(params);

    }

To redline the Title Block table of an item:

The following is an example of redlining the Title Block table of the item. It assumes Item.Page_Two and the attribute Text01 are visible and Text01 is change controlled.

Example: Redlining the Title Block table of an item

ITable page2Tab = item.getTable(ItemConstants.TABLE_REDLINEPAGETWO);

Iterator it = page2Tab.getTableIterator();

IRow redPage2Row = (IRow)it.next();

ICell cell = redPage2Row.getCell(CommonConstants.ATT_PAGE_TWO_TEXT01);

System.out.println("old value, before update: " + cell.getOldValue());

redPage2Row.getCell(CommonConstants.ATT_PAGE_TWO_TEXT01).setValue("updated Text01")

## 4.15 Removing Redline Changes

When you make redline changes to a table such as a BOM table, you may want to undo the changes for a row and restore it to its original state. You can use the IRedlinedRow.undoRedline() method to undo any redline changes to a row.

If you undo the redlines for a row, any cells that are modified are restored to their original values. A redlined row can also be one that was added or deleted. If you undo the redlines for a row that was added, the entire row is removed from that revision. If you undo the redlines for a row that was deleted, the entire row is restored.

Example: Removing redline changes from the BOM table

    private static undoBOMRedlines(IItem item, String rev) throws APIException {
      ITable redlineBOM = item.getTable(ItemConstants.TABLE_REDLINEBOM);
      Iterator it = redlineBOM.iterator();
      while (it.hasNext()) {
        IRedlinedRow row = (IRedlinedRow)it.next();
        row.undoRedline();
      }
    }

### 4.15.1 Removing Redline Changes in Bulk Mode

Example: Removing Redline Changes in Bulk Mode

Agile SDK enables removing (undoing) redlines with the aid of IRedlinedTable. This interface provides the API to perform bulk redline undos as shown below.

IRedlinedTable.undoRedline(Collection rows);

IRedlinedTable.undoAllRedline();

Note See Redlining on page 93.

Example: Typecasting Redline tables to IRedlinedTable interface

IItem item = (IItem) session.getObject(ItemConstants.CLASS_PART, "PART_001");

item.setRevision("B"); // Unreleased change

ITable bomTable = item.getTable(ItemConstants.TABLE_REDLINEBOM);

Iterator it = bomTable.iterator();

List rows = new ArrayList();

while(it.hasNext()) {

IRow row = (IRow) it.next();

if(((IRedlined)row).isRedlineModified())

rows.add(row);

}

    // Only Redline tables can be typecasted to IRedlinedTable interface
    // Case 1:

((IRedlinedTable)bomTable).undoRedline(rows);

    // Case 2:
    public interface IRedlined {

((IRedlinedTable)bomTable).undoAllRedline();

## 4.16 Identifying Redlined Rows and Redlined Cells

The IRedlined interface is designed to identify redlined rows and redlined cells. It is only supported on redlined tables. The interface works in conjunction with the isRedlineModified() method to show if objects are redlined. The interface typecasts IRow and ICell objects as follows:

- IRow indicates if the row is redline modified

- ICell indicates if the cell is redline modified.

    Identifying redlined rows and cells
    public boolean isRedlineModified()
    throws APIException;
    }

The IRedlined.isRedlineModified() method returns a boolean value. This value is TRUE when cells or rows are redlined.

Note: IRedlined.isRedlineModified() returns a FALSE value for all cells on redline added or redline removed rows.

### 4.16.1 Using ICell.getOldValue

With the introduction of the IRedlined interface, the ICell.getOldValue() method is no longer defined for redline added and redline removed rows. The ICell.getOldValue() method has a meaningful result only when FLAG_IS_REDLINE_MODIFIED is true for the row.

Note: Do not call this method for redline added or redlined removed rows.