=======
Go to primary content
Agile Product Lifecycle Management SDK Developer Guide - Using APIs
Release 9.3.6
E71152-01
  Go To Table Of Contents
Contents

Previous
Previous
 
Next
Next
 

4 Working with Tables


This chapter includes the following:

4.1 About Tables

When 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.

Surrounding text describes Figure 4-1 .

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 4-3.

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, similar to IFolder, extends java.util.Collection and supports all methods provided by that superinterface. Consequently, you can work with an ITable object as you would with 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 Affected Read Through Tables Supported by SDK

SDK supports the Affected Read Through tables listed below.

  • 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 data object. Tables for change objects are different from tables for items. Each table for a particular data object is identified by a constant in the constants class for that data object. 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 constant, or mapped into a new constant, see Appendix B, "Migrating Table Constants to Release 9.2.2."

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 is designed 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 the 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 later releases:

    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.

4.3.2.4 Retrieving the BOM table of an Item

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

Example 4-1 Retrieving a BOM table

//Load an item IItem item =         (IItem)m_session.getObject(ItemConstants.CLASS_PART, number);//Get the BOM table    ITable table =          item.getTable(ItemConstants.TABLE_BOM);

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 4-2 Retrieving the metadata of a table

private IAttribute[] getBOMAttributes() throws APIException {IAgileClass cls = admin.getAgileClass(ItemConstants.CLASS_PART);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 Chapter 9, "Accessing Metadata Using the APIName Field." For information to use the Agile API to work with metadata, see Chapter 23, "Performing Administrative Tasks."

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 createRow() which creates an empty row. Avoid using this method because it may not be supported in future Agile PLM releases. Also, you must initialize a row with data when you create it.

You can add table rows in a batch format with ITable.createRow(). See ”Adding and Updating Multiple Table Rows” on page 4-9.

4.5.1 Adding an Item to a BOM Table

The following example uses ITable.createRow() to add an item to a BOM table.

Example 4-3 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.

Example 4-4 Adding a row to an Attachments table

private static void (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 as follow:

    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.

Example 4-5 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");

ManufacturerPart mfrPart = 
          (IManufacturerPart)(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 4-6 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);}

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 4-7 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 4-8 Adding Multiple Team members to a Program with Bulk API

private static void createTeamRows(String[] addTeamMembers) throws APIException {//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 4-9 Adding multiple rows and setting values

private static void createBOMRows(String partNumber) throws APIException {
  IItem[] child = new IItem [3];
  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 4-10 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 Managing PSR Affected Items Tables Using Bulk Edit APIs

Bulk Edit APIs are designed to improve PLM server performance by reducing the duration of the PSR Affected Items (AIs) edits (create, update, remove), when editing the status of these AIs. Invoking the ITable interface (See Metadata Interface under Types of Agile API Classes and Interfaces) deteriorates server performance because it edits a single PSR AI which triggers the entire set of the associated Events, and each associated Event in turn, invokes several additional unnecessary server calls. Thus, the resolution of this issue was sought in a similar interface that performs the functions of the ITable interfaceFoot 1 , in the Bulk execution mode.

4.7.1 The Bulk Edit Interface

The com.agile.api.IServiceRequestAITable interface enables creating, updating, and removing the entire rows of a service Request Action Item table, thus reducing a multitude of often unnecessary remote server calls to a single call. This proves to be most valuable when updating PSR AI tables having large numbers of rows.

You can cast ITable to IServiceRequestAITable table and use the methods defined in this interface.

IRow [] bulkCreateRows (Object[] rows) throws APIException

This bulk operation creates multiple rows with a single remote call. Rather than calling ITable.createRow(...) to create multiple rows, this API can improve performance and reduce unnecessary event invocations. However, if an error/warning occurred, all operations are rolled back. This method accepts an array of objects and returns an array of IRow corresponding objects. See createRow(Object) for more information on the possible makeup of each element in the rows array.

boolean bulkRemoveAll ( Collection c ) throws APIException

This operation removes all of this collection's elements from this table in a single remote call. This API can improve the performance and reduce unnecessary event Invocations. This collection's elements must be IRow. If an error/warning occurred, all operations are rolled back.

void bulkUpdateRows ( Map rows ) throws APIException

This bulk operation updates multiple rows with a single remote call. Rather than call IRow.setValues(...) for multiple rows in a table, this API can potentially improve the performance and reduce unnecessary event Invocation. If an error/warning occurred, all operations are rolled back.

4.7.2 Managing Table Rows in the Bulk Execution Mode

The following three bulk APIs aim to improve the performance of PLM when creating, updating, or deleting the PSR Affected Items tab rows:

  • ServiceRequestAITable.bulkCreateRows(Object[] rows) throws APIException;ServiceRequestAITable.bulkUpdateRows(Map rows) throws APIException;ServiceRequestAITable.bulkRemoveAll(Collection c) throws APIException;

Example 4-11 Creating table rows in the Bulk execution mode

//Bulk Create  List<Map> list = new ArrayList<Map>();  Map map = new HashMap();      map.put(ServiceRequestConstants.ATT_AFFECTED_ITEMS_ITEM_NUMBER,             (IItem)session.getObject(IItem.OBJECT_TYPE,"PARTXXX"));  list.add(map);  aiTable.bulkCreateRows(list.toArray());//Bulk Update  Map retmap = new HashMap();  Iterator it = aiTable.iterator();  while (it.hasNext()) {     IRow row = (IRow) it.next();     Map map = new HashMap();     map.put(ServiceRequestConstants.ATT_AFFECTED_ITEMS_TEXT01, "AI.Text01");     retmap.put(row, map);  }  aiTable.bulkUpdateRows(retmap);//Bulk Remove  List list = new ArrayList();  Iterator it = aiTable.iterator();  while (it.hasNext()) {     IRow row = (IRow) it.next();     list.add(row);  }  aiTable.bulkRemoveAll(list);

4.7.3 Casting ITable Variables to IServiceRequestAITable Variables

Because the input and outputs parameters of ServiceRequestAITable APIs are similar to those of ITable, you can cast ITable variables to those of IServiceRequestAITable by renaming the method, as shown below, and performing the required tasks in the Bulk mode.

Example 4-12 ITable inputs, processes, and outputs

ITable affectedItemsTab = null;affectedItemsTab = getAffectedItemsTab(isr);affectedItemsTab.updateRows(createRowsMap);

Example 4-13 IServiceRequestAITable inputs, processes, and outputs

IServiceRequestAITable affectedItemsTab = null;affectedItemsTab = (IServiceRequestAITable)getAffectedItemsTab(isr);affectedItemsTab.bulkUpdateRows(createRowsMap);

4.8 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 4-14 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 displayed in Figure 4–2 below.

Figure 4-2 Navigation controls

Surrounding text describes Figure 4-2 .

4.8.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.

To update 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.9 Sorting Table Rows

To sort the rows in a table by a particular attribute, use getTableIterator(ITable.ISortBy[]) which will 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 4-15 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 modify 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 either 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."

4.10 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 4-5. 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 4-16 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 bom component 6642-01 and remove it from the table row   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 the Collection methods to remove table rows. To remove all rows in a table, use Collection.clear().

Example 4-17 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.11 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 4-18 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 4-19 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.12 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 4-20 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.13 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 PLM's Page One, Page Two, and Page Three are 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.

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 4-21 Editing Page Two cells

// Edit Page Two cells by first getting the Page Two tableprivate 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.14 Working with Revisions and Relationships

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

4.14.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 a revision change and track flags.

Example 4-22 Using attributes that set Revisions 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.14.1.1 Getting Flags on Relationships 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.14.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. This is shown in Example 4-23.

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

// When Revision specific relationship is enabled on Change Object, you can add// two different Revisions of the same Part object into one Change Object's // relationship table. IChange change = (IChange) session.getObject(ChangeConstants.CLASS_ECO, "C00001");IRelationshipTable table = (IRelationshipTable) change.getRelationship();IItem item = (IItem) session.getObject(ItemConstants.CLASS_PART, "P00001");item.setRevision('A C00001');// Add Part "P00001" with Rev "A" into Change "C00001"'s relationshiptable.addRevSpecificRelationship(item, null);item.setRevision('B C00002');// Add Part "P00002" with Rev "B" into Change "C00002"'s relationshiptable.addRevSpecificRelationship(item, null);

4.15 Redlining

When you issue a change for a released item or a price agreement, the you can invoke Agile API to redline certain tables affected by the change. In the Agile PLM Clients, redline tables visually identify values that were modified from the previous revision. Red underlined text, thus the term ”redline” indicates values that were added, and red strikeout text indicates values that were deleted. Users 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.

4.15.1 Redlining BOMs, Manufacturers, and Price Lines Tables

Use the following procedure to redline these tables.

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 enable modifying an item's BOM or Manufacturers tables

    • MCOs enable modifying an item's Manufacturers table

    • SCOs enable modifying an item's site-specific BOM, Manufacturers

    • PCOs enable modifying 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.

4.15.1.1 Redlining the Manufacturers table of an item

Example 4-24 redlines the Manufacturers table (AML) of an item.

Example 4-24 Redlining the Manufacturers table of an item

private void redlineAML() throws APIException {IAttribute attrPrefStat = null;IAgileList listvalues = null;Map params = new HashMap();

// Get a released itemIItem item = (IItem)m_session.getObject("Part", "1000-02");

// Get the Preferrred status valueIAgileClass cls = item.getAgileClass();attrPrefStat = cls.getAttribute(ItemConstants.ATT_MANUFACTURERS_PREFERRED_STATUS);listvalues = attrPrefStat.getAvailableValues();

// Create an MCOIChange change = (IChange)m_session.createObject(ChangeConstants.CLASS_MCO, "M000024");

// Set the Workflow ID of the MCOchange.setWorkflow(change.getWorkflows()[0]);

// Get the Affected Items tableITable affectedItems = change.getTable(ChangeConstants.TABLE_AFFECTEDITEMS);

// Add a new row to the Affected Items tableIRow affectedItemRow = affectedItems.createRow(item);

// Get the Redline Manufacturers tableITable redlineAML = item.getTable(ItemConstants.TABLE_REDLINEMANUFACTURERS);

// Add a manufacturer part to the tableparams.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 tableparams.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);
}

4.15.2 Redlining the Title Block 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 4-25 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.16 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 4-26 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.16.1 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 with the aid of the following interfaces:

  • IRedlinedTable.undoRedline(Collection rows);

  • IRedlinedTable.undoAllRedline();

Example 4-27 Typecasting Redline tables to IRedlinedTable interface

IItem item = 
   (IItem) session.getObject(ItemConstants.CLASS_PART, "PART_001");   item.setRevision("B"); // Unreleased changeITable 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);}

Note:

Only Redline tables can be typecasted to IRedlinedTable interface in the following two ways. For more information, see "Redlining."
  • ((IRedlinedTable)bomTable).undoRedline(rows);((IRedlinedTable)bomTable).undoAllRedline();


4.17 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.

    Example 4-28 Identifying redlined rows and cells

    public boolean isRedlineModified()     throws APIException;
    

Note:

The IRedlined.isRedlineModified() method returns a boolean value. This value is TRUE when cells or rows are redlined and FALSE value for all cells on redline added or redline removed rows.

4.17.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.



Footnote Legend

Footnote 1: See Metadata Interface under "Types of Agile API Classes and Interfaces."