=======
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
 

14 Working with Attachments and File Folder Objects

This chapter includes the following:

14.1 About Attachments and File Folders

Attachments to objects contain information about the object or a manufacturing process. You can attach files and URLs by referencing them in a File Folder object. The File Folder object holds pertinent content, or Attachments. Most primary Agile API objects, such as IItem, IChange, IManufacturer, IManufacturerPart, IPackage, ITransferOrder, IUser, and IUserGroup, have an Attachments table (or tab in the Java Client) that lists indirect references to the files or URLs that are in separate file folders. Each row in an Attachments table can refer to one file or to all files from a referenced file folder.The following illustration is an example of the way files or URLs contained in a file folder are referenced indirectly from the Attachments table of multiple business objects, in this case an item and a change.

Figure 14-1 File Folder objects referenced from Item and Change Attachments

Surrounding text describes Figure 14-1 .

The Agile API does not provide support for viewing or printing an attachment. However, after you download a file, you can use another application to view, edit, or print the attachment.A File Folder is a business object that specifies one or more files or URLs that are stored in the file server vault. In addition, a file folder has its own set of tables. This means that you can create and load an independent file folder and add one or more files to its Files table. You can also search for a file folder, just as you would search for an Item or Change.


Important:

File Manager Internal Locator property is set in Agile Java Client. Choose Admin > Settings > Server Settings > Locations > File Manager > Advanced > File Manager Internal Locator. The format for the value is: <protocol>://<machinename>:<port>/ <virtualPath>/services/FileServer.

For example, http://agileserver.agile.agilesoft.com:8080 /Filemgr/ services/FileServer is a valid value. For more information about Agile PLM server settings, refer to the Agile PLM Administrator Guide.


<<<<<<< .mine

14.2 About SDK's File Load Utility

SDK's File Load Utility supports automated transfer of files of interest into the file vault. The utility therefore enables the SDK to directly load files and eliminate the file loading step.

14.3 Working with File Folders

=======

14.2 About SDK's File Load Utility

SDK's File Load Utility supports automated transfer of files of interest into the file vault. The utility therefore enables the SDK to directly load files and eliminate the file loading step.

The following example shows working with File Load Utility.

Example 14-1 SDK sample code for file load utility

private IRow moveFile_FF(IFileFolder ff, String fileName) throws Exception {Map param = new HashMap();// flag of moving the file - newly introduced constantparam.put(FileFolderConstants.SDK_MOVE_FILE, Boolean.TRUE);     // file nameparam.put(FileFolderConstants.ATT_FILES_FILE_NAME, fileName);// optional file descriptionparam.put(FileFolderConstants.ATT_FILES_FILE_DESCRIPTION, "ile description");ITable filesTable = ff.getTable(FileFolderConstants.TABLE_FILES);IRow row = filesTable.createRow(param);return row;}

14.3 Working with File Folders

>>>>>>> .r346

Similar to Attachments, the SDK exposes APIs to perform File Folders-related tasks such as checking-in and checking-out files associated with objects in the rows of an Attachments table, adding files and URLs to an Attachments table, and deleting attachments. This section lists and describes these features, and provides the necessary procedures to use the SDK to perform these tasks.

<<<<<<< .mine

14.3.1 File Folder Classes and Subclasses

=======

14.3.1 File Folder Classes and Subclasses

>>>>>>> .r346

The File Folder Base Class has two Classes and each of these classes have their own respective Subclasses. The figure below lists the File Folders Base Class, Classes, and Subclasses. The Agile PLM administrator can define new file folder subclasses.

<<<<<<< .mine
=======
>>>>>>> .r346

Figure 14-2 File Folders Classes and Subclasses

Surrounding text describes Figure 14-2 .

A description of these classes and objects appears in Table 14-1 below.

<<<<<<< .mine
=======
>>>>>>> .r346

Table 14-1 PLM Classes and descriptions

Base Class Class Subclass Description

File Folders

Designs

Design

Objects that permit building model structures in CAD


File folders

File Folder

Markup

Objects that include files or URLs; this class includes all file folder objects except historical report file folders.


For information about routing these objects, see "Checking the State of Agile PLM Objects."

<<<<<<< .mine

14.3.2 File Folder Tables and Constants

=======

14.3.2 File Folder Tables and Constants

>>>>>>> .r346

The File Folder object supports the following tables and corresponding constants:

<<<<<<< .mine
=======
>>>>>>> .r346

Table 14-2 Supported tables and constants

Table Constant Read/Write Mode

Title Block

TABLE_TITLEBLOCK

Read/Write

Page Two

TABLE_PAGETWO

Read/Write

Page Three

TABLE_PAGETHREE

Read/Write

Files

TABLE_FILES

Read/Write

Structure

TABLE_STRUCTURE

Read/Write

Routing Slip/Workflow

TABLE_WORKFLOW

Read/Write

Relationships

TABLE_RELATIONSHIPS

Read-only

History

TABLE_HISTORY

Read-only

Where Used

TABLE_WHEREUSED

Read/Write

Where Used Design

TABLE_WHEREUSEDDESIGN

Read-only


<<<<<<< .mine

14.3.3 Creating File Folder Objects

=======

14.3.3 Creating File Folder Objects

>>>>>>> .r346

IFileFolder is the interface that corresponds to the file folder business object. The following example shows how to create a file folder.

<<<<<<< .mine

Example 14-1 Creating a file folder

=======

Example 14-2 Creating a file folder

>>>>>>> .r346
public void createFileFolder() throws Exception {   IAgileClass attClass =      m_admin.getAgileClass(FileFolderConstants.CLASS_FILE_FOLDER);   IAutoNumber an = 
      cls.getAutoNumberSources()[0];   String attNumber = 
      an.getNextNumber();   IFileFolder ff = (      IFileFolder)m_session.createObject(attClass, attNumber);      ff.checkOutEx();}

Note:

Note When you add a file or a URL to the row of the Attachments table of a business object, you will automatically create x a new file folder object that contains the associated file or URL. See "Creating File Folder Objects by Adding Rows to Attachments Table."

The File Folders Design class is similar to the File folder class with the additional Structures table (Tab in the Java Client UI) for CAD objects. The following examples show how to create a Design object, adding a Design object to a the Structure tree, and loading a structure table.

<<<<<<< .mine

Example 14-2 Creating a Design object

=======

Example 14-3 Creating a Design object

>>>>>>> .r346
// autoNum is autoNumber as usual   IFileFolder obj = (IFileFolder) m_session.createObject(   FileFolderConstants.CLASS_DESIGN, autoNum);
   }
<<<<<<< .mine

Example 14-3 Adding Design objects to a Structure tree

=======

Example 14-4 Adding Design objects to a Structure tree

>>>>>>> .r346
IFileFolder obj = // some Design objectIFileFolder childObj1 = // some Design objectIFileFolder childObj2 = // some Design objectobj.checkOutEx();ITable table = obj.getTable(FileFolderConstants.TABLE_STRUCTURE);

// add row   Object[] vers = childObj1.getVersions();   IRow row = table.createRow(childObj1);   row.setValue(FileFolderConstants.
      ATT_STRUCTURE_LABEL,"label modified by creating row 1");row = table.createRow(childObj2);   row.setValue(FileFolderConstants.ATT_STRUCTURE_LABEL,   "label modified by creating row 2");   obj.checkIn();
<<<<<<< .mine

Example 14-4 Loading a Structure table

=======

Example 14-5 Loading a Structure table

>>>>>>> .r346
public void testLoadingDesignStructureTable() throws Exception {// assuming Design object Design00004 existed with some data in StructureIFileFolder obj = (IFileFolder) m_session.getObject(FileFolderConstants.CLASS_DESIGN, "Design00004");// load Structure tableITable table = obj.getTable(FileFolderConstants.TABLE_STRUCTURE);Integer tableId = (Integer) table.getTableDescriptor().getId();// ITable performs related tasks} 
<<<<<<< .mine

Example 14-5 Loading a Structure table as a tree

=======

Example 14-6 Loading a Structure table as a tree

>>>>>>> .r346
public void testLoadingDesignStructureTree() throws Exception{
   // assuming Design object Design00004 existed with some data in Structure   IFileFolder obj = 
      (IFileFolder) m_session.getObject(   FileFolderConstants.CLASS_DESIGN, "Design00004");   IAgileClass agileClass = obj.getAgileClass();// load Structure table   ITable table = obj.getTable(FileFolderConstants.TABLE_STRUCTURE);   Integer tableId = (Integer) table.getTableDescriptor().getId();   ITreeNode root = (ITreeNode) table;   Collection topLevelChildren = root.getChildNodes();   Iterator it;   ITreeNode row;
   if (topLevelChildren != null) {      it = topLevelChildren.iterator();      int level = 0;   while (it.hasNext()) {      row = (ITreeNode) it.next();      if(row instanceof IRow) {         IRow aRow = (IRow) row;         IDataObject referent =         aRow.getReferent();   if(referent != null) {      System.out.println(      "Row Referent Object ID/row:
         "+ referent.getObjectId()+ " / "+referent.getName());
            }      }      iterateTreeNode(agileClass, true,tableId, (ITreeNode) row);      count++;         }      }   System.out.println("The number of rows in top level is " + count);}
private void iterateTreeNode (IAgileClass agileClass, boolean print, Integer       tableId, ITreeNode node) throws APIException {   Collection childNodes = node.getChildNodes();   if (childNodes == null || childNodes.size() <= 0) {      return;   }   Iterator it = childNodes.iterator();   ITreeNode childNode;   IRow row;   while (it.hasNext()) {      childNode = (ITreeNode) it.next();   if (childNode instanceof IRow) {      row = (IRow) childNode;      if(row instanceof IRow) {         IDataObject referent =         row.getReferent();         if(referent != null) {            System.out.println("Row Referent Object ID/row:              "+ referent.getObjectId()+ " / "+ referent.getName());         }
      }
   }iterateTreeNode(agileClass, print, tableId, (ITreeNode) childNode);      }   }}

14.3.4 Creating File Folder Objects by Adding Rows to Attachments Table

When you add a file or a URL to the row of the Attachments table of a business object, you automatically create a new file folder that contains the associated file or URL. You can load the referenced file folder using the IRow.getReferent() method, as shown in the following example.

<<<<<<< .mine

Example 14-6 Creating a file folder by adding a row to the Attachments table

=======

Example 14-7 Creating a file folder by adding a row to the Attachments table

>>>>>>> .r346
public IFileFolder addRowToItemAttachments(IItem item, File file) throws Exception {  ITable attTable = item.getTable(ItemConstants.TABLE_ATTACHMENTS);  IRow row = attTable.createRow(file);  IFileFolder ff = (IFileFolder)row.getReferent();  return ff;}
<<<<<<< .mine

14.3.5 Working with the Files Table of a File Folder

=======

14.3.5 Working with the Files Table of a File Folder

>>>>>>> .r346

The Files table of a file folder lists the files and URLs associated with the object. To edit the table, you must first check out the file folder. You cannot add files or URLs to the Files table or delete them unless the file folder is checked out.

The following example shows how to check out a file folder and then add files and URLs to the Files table.

<<<<<<< .mine

Example 14-7 Adding files and URLs to the Files table of a file folder

=======

Example 14-8 Adding files and URLs to the Files table of a file folder

>>>>>>> .r346
public void addFiles(IFileFolder ff, File[] files, URL[] urls) throws Exception {// Check out the file folder   ff.checkOutEx();// Get the Files table   ITable filesTable = ff.getTable(FileFolderConstants.TABLE_FILES);// Add files to the Files table   for (int i = 0; i < files.length; ++i) {      filesTable.createRow(files[i]);}// Add URLs to the Files table   for (int i = 0; i < urls.length; ++i) {     filesTable.createRow(urls[i]);}// Check in the file folder   ff.checkIn();}
<<<<<<< .mine

14.3.6 Accessing Files in Agile PLM File Vault with IAttachmentFile

=======

14.3.6 Accessing Files in Agile PLM File Vault with IAttachmentFile

>>>>>>> .r346

IAttachmentFile is the interface that provides generalized access to files stored in the Agile PLM file vault. This interface is supported by the following Agile API objects:

  • File folder - you can class cast IFileFolder to IAttachmentFile.

  • A row of the Files table of a file folder - you can class cast IRow from the Files table to IAttachmentFile.

  • A row of the Attachments table of a business object - you can class cast IRow from the Attachments table to IAttachmentFile.

IAttachmentFile provides the following methods for working with attachments:

  • getFile()

  • isSecure()


Note:

IAttachmentFile also has a setFile() method that lets you change the file(s) for an attachment, but it is supported only for rows of the Attachments table.

Results returned by IAttachmentFile methods vary depending on the object that you are working with. See Table 14-3 below.

<<<<<<< .mine
=======
>>>>>>> .r346

Table 14-3 Results returned by IAttachmentFile

Calling object getFile() return value isSecure() return value

Row from the Attachments table of any business object

Returns either a single file InputStream if the row refers to a specific file from the file folder or a zipped InputStream with all the files from the file folder.

true if the referenced file is not URL, or all the files are not URLs.

FileFolder object

Returns a zipped InputStream with all files from the file folder.

true if all the files contained in the file folder are not URLs.

Row from the Files table of a file folder

Returns a single file InputStream that refers to a specific file from the file folder.

true if the referenced file is not a URL.



Note:

To read files in a zipped InputStream, use methods of the java.util.zip.ZipInputStream class.

The following example shows how to use IAttachmentFile.isSecure() and IAttachmentFile.getFile() from the row of an Attachments table for an item.

<<<<<<< .mine

Example 14-8 Using isSecure() and getFile()

=======

Example 14-9 Using isSecure() and getFile()

>>>>>>> .r346
public InputStream getItemAttachment(IItem item) throws Exception {   InputStream content = null;      ITable attachments = item.getTable(ItemConstants.TABLE_ATTACHMENTS);   IRow row = (IRow)attachments.iterator().next();   if (((IAttachmentFile)row).isSecure())      content = ((IAttachmentFile)row).getFile();   return content;}

14.4 Working with Attachments Table of an Object

To work with the Attachments table of an object, follow this sequence.

  1. Get the object that has the attachment you want.

    For example, you can use the IAgileSession.getObject() method to get a particular object, or you can create a query to return objects.

  2. Get the Attachments table. Use the IDataObject.getTable() or IAttachmentContainer.getAttachments() methods to get the table.

  3. Select a row in the Attachments table.

Create an iterator for the table, and then select a particular row. You can use the ITable.getTableIterator() method to get a bidirectional iterator for the table.

The following example below shows how to retrieve an item, get the Attachments table for the item, and then select the first attachment.

<<<<<<< .mine

Example 14-9

=======

Example 14-10

>>>>>>> .r346
try {// Get Item P1000   Map params = new HashMap();   params.put(ItemConstants.ATT_TITLE_BLOCK_NUMBER, "P1000");   IItem item =      (IItem)m_session.getObject(IItem.OBJECT_TYPE, params);// Get the attachment table for file attachments   ITable attTable = item.getAttachments();// Get a table iterator   ITwoWayIterator it = attTable.getTableIterator();// Get the first attachment in the table   if (it.hasNext()) {      IRow row = (IRow)it.next();// Read the contents of the stream   InputSteam stream = ((IAttachmentFile)row).getFile();   }   else {      JOptionPane.showMessageDialog(null, "There are no files listed.",         "Error", JOptionPane.ERROR_MESSAGE);   }} catch (APIException ex) {      System.out.println(ex);}

14.4.1 Checking In and Checking Out Files with ICheckoutable

ICheckoutable is an interface that you can use to check in and check out files that are associated with an object. This applies only to rows of the Attachments table. You can class cast IRow from the Attachments table to ICheckoutable.

ICheckoutable provides the following methods for working with attachments:

  • cancelCheckout()

  • checkIn()

  • checkOutEx()

  • isCheckedOut()

This example shows how to use the ICheckoutable interface to check out and check in a file from a row of the Attachments table.

<<<<<<< .mine

Example 14-10

=======

Example 14-11

>>>>>>> .r346
public InputStream checkOutRow(IRow row) throws APIException {// Check out the attachment   ((ICheckoutable)row).checkOutEx();// Read the contents of the stream   InputStream stream = ((IAttachmentFile)row).getFile();   return stream;}

public checkInRow(IRow row, String filePath) throws APIException {   if (row.isCheckedOut()) {// Set the new file   ((IAttachmentFile)row).setFile(new File(filePath));// Check in the file   ((ICheckoutable)row).checkIn();}   else {      JOptionPane.showMessageDialog(null, 
        "The attachment is not checked out.","Error", JOptionPane.ERROR_MESSAGE);   }}
<<<<<<< .mine

14.4.2 Specifying the Revision of the Item

=======

14.4.2 Specifying the Revision of the Item

>>>>>>> .r346

When you are working with items, each revision can have different attachments. If an item has multiple revisions, your program should allow the user to select a revision. For information about specifying the revision, see "Getting and Setting the Revision of an Item."

<<<<<<< .mine

14.4.3 Checking if the Revision Is Incorporated

=======

14.4.3 Checking if the Revision Is Incorporated

>>>>>>> .r346

When the revision for an item is released, it is possible the revision is also incorporated. The attachments for an incorporated item are locked and cannot be checked out.

<<<<<<< .mine

However, you can still view incorporated attachments, but you cannot modify them. To modify an incorporated attachment, you must either un-incorporate the attachment, or submit a new change order to create a new revision as shown in the examples below.

Example 14-11 Incorporating Attachments

=======

However, you can still view incorporated attachments, but you cannot modify them. To modify an incorporated attachment, you must either un-incorporate the attachment, or submit a new change order to create a new revision as shown in the examples below.

Example 14-12 Incorporating Attachments

>>>>>>> .r346
IItem item = (IItem) session.getObject(IItem.OBJECT_TYPE, "1000");

//Incorporate the itemitem.setIncorporated(true);

//Print appropriate responseif (item.isIncorporated() == true)     System.out.println("Part " + item.getName() + " is Incorporated.");else System.out.println("Part " + item.getName() + " is NOT Incorporated.");
<<<<<<< .mine

Example 14-12 Un-incorporating Attachments

=======

Example 14-13 Un-incorporating Attachments

>>>>>>> .r346
IItem item = 
               (IItem) session.getObject(IItem.OBJECT_TYPE, "1000");

//Incorporate the item    item.setIncorporated(false);

//Print appropriate responseif (item.isIncorporated() == true)     System.out.println("Part " + item.getName() + " is Incorporated.");else System.out.println("Part " + item.getName() + " is NOT Incorporated.");
<<<<<<< .mine

14.5 Checking Out a File Folder

=======

14.5 Checking Out a File Folder

>>>>>>> .r346

Before you can add, delete, or modify the files contained in a file folder, you must check out the file folder. With the appropriate privileges, you can check out a file folder as long as it is not already checked out by another user. Once a file folder is checked out, no one else can check it out or modify it.

The user who checked out a file folder, as well as other users who are change analysts or component engineers, can check it in. If the file folder was checked out to a location on the network, or to a shared drive or directory, anyone who has access to that network location or to that shared directory can check in the file folder.

The following example shows how to check out a file folder.

<<<<<<< .mine

Example 14-13 Checking out a file folder

=======

Example 14-14 Checking out a file folder

>>>>>>> .r346
void checkOutFileFolder(IFileFolder ff) throws Exception {
   ff.checkOutEx();
}

Note:

You can also use ICheckoutable.checkOutEx() to check out a row of the Attachments table. See "Checking In and Checking Out Files with ICheckoutable."

<<<<<<< .mine

14.6 Canceling a File Folder Checkout

=======

14.6 Canceling a File Folder Checkout

>>>>>>> .r346

If you check out a file folder and then decide that you don't want to modify it, or you want to discard your changes and revert to the original file folder, you can cancel the checkout. When you cancel a checkout, you also make the file folder available for other users to check out.


Note:

Only the user who checked out a file folder can cancel the checkout.

This example cancels a file folder checkout.

<<<<<<< .mine

Example 14-14 Canceling checkout of a file folder

=======

Example 14-15 Canceling checkout of a file folder

>>>>>>> .r346
void cancelCheckOut(IFileFolder ff) throws Exception {          ff.cancelCheckout();    }

Note:

You can also use ICheckoutable.cancelCheckout() to cancel checkout of a row of the Attachments table. See "Checking In and Checking Out Files with ICheckoutable."

<<<<<<< .mine

14.7 Adding Files and URLs to the Attachments Table

=======

14.7 Adding Files and URLs to the Attachments Table

>>>>>>> .r346

The Agile API lets you add files and URLs to the Attachments table of many types of objects, such as IItem, IChange, IManufacturerPart, and IManufacturer. An attachment is one or more physical files or an Internet address (URL). A file is considered a secured attachment because it is physically stored in the Agile PLM file vault. A URL, on the other hand, is an unsecured attachment.

When you add a file or a URL to the Attachments table of a business object, the server automatically creates a new file folder containing the associated file or URL. The new row on the Attachments table references the new file folder.

When you add a URL attachment, the server stores a reference to the Internet location but does not upload a file. Therefore, you cannot download a URL attachment. The Agile API validates URL strings that you attempt to check in as an attachment. If a URL is invalid, the Agile API considers the string a filename instead of a URL.

You cannot add a file or URL to the Attachments table of an item if

  • The current revision has a pending or released MCO.

  • The current revision is incorporated.

When you use the ITable.createRow(java.lang.Object) method to add a row to the Attachments table, the param method can be any of the following object types:

  • String - adds one file attachment specified by a local path.

  • String[] - adds multiple file attachments specified by an array of local paths.

  • File - adds one file attachment.

  • File[]- adds multiple file attachments.

  • InputStream - adds one file attachment.

  • InputStream[]- adds multiple file attachments.

  • URL - adds one URL attachment.

  • URL[] - adds multiple URL attachments.

  • IRow (of the Attachments or Files tables) - adds a file or URL attachment.

  • IFileFolder - adds all files and URLs for the specified file folder.

  • Map - adds one or more files specified by a hash table containing Attachment parameters.


Note:

The File object type performs best when adding attachments.

When you add a file or a URL to the row of the Attachments table of a business object, you automatically create a new file folder that contains the associated file or URL. You can load the referenced file folder using the IRow.getReferent() method, as shown in the following example.

<<<<<<< .mine

Example 14-15 Creating a file folder by adding a row to the Attachments table

=======

Example 14-16 Creating a file folder by adding a row to the Attachments table

>>>>>>> .r346
public IFileFolder addRowToItemAttachments      (IItem item, File file) throws Exception; {   ITable attTable = item.getTable(ItemConstants.TABLE_ATTACHMENTS);   IRow row = attTable.createRow(file);   IFileFolder ff = (IFileFolder)row.getReferent();   return ff;}

This example uses several instances of the addAttachment() methods to illustrate the different ways you can add rows to an Attachments table.

<<<<<<< .mine

Example 14-16 Adding files to the Attachments table

=======

Example 14-17 Adding files to the Attachments table

>>>>>>> .r346
// Add a single file to the Attachments table row by specifying a file path   public static IRow addAttachment
      (ITable attTable, String path) throws APIException {      IRow row = attTable.createRow(path);      return row;   }

// Add a single file to the Attachments table   public static IRow addAttachment
      (ITable attTable, File file) throws APIException {      IRow row = attTable.createRow(file);      return row;   }

// Add multiple files to the Attachments table
   public static IRow addAttachment
      (ITable attTable, File[] files) throws APIException {      IRow row = attTable.createRow(files);      return row;   }

// Add a URL attachment to the Attachments table   public static IRow addAttachment
      (ITable attTable, URL url) throws APIException {      IRow row = attTable.createRow(url);      return row;   }

// Add a file folder to the Attachments table   public static IRow addAttachment
      (ITable attTable, IFileFolder ff) throws APIException {      IRow row = attTable.createRow(ff);      return row;   }

// Add a FileFolder.Files row object or a [BusinessObject].Attachments row object// to the Attachments table. The Agile API validates the row object at run time to// determine if it is from a valid table (Files or Attachments).   public static IRow addAttachment
      (ITable attTable, IRow filesRow) throws APIException {      IRow row = attTable.createRow(filesRow);      return row;   }

// Add a file folder to the Attachments table & specify versions for all files
   public static IRow addAttachmentWithVersion
      (ITable attTable, IFileFolder ff) throws APIException {      ff.setCurrentVersion(new Integer(1));      IRow row = attTable.createRow(ff);      return row;   }
<<<<<<< .mine

14.7.1 Deep Cloning Attachments and Files from One Object to Another

=======

14.7.1 Deep Cloning Attachments and Files from One Object to Another

>>>>>>> .r346

To simplify copying file attachments from one object to another, use the CommonConstants.MAKE_DEEP_COPY virtual attribute as a Boolean parameter of ITable.createRow(Object). This parameter allows your program to create a new copy of the file in the Agile File Manager vault instead of referencing the old file.

<<<<<<< .mine

Example 14-17 Deep cloning an Attachments table row

=======

Example 14-18 Deep cloning an Attachments table row

>>>>>>> .r346
// Clone an attachment table row and its file from one item to another   public static cloneAttachment
      (IItem item1, IItem item2, File file) throws APIException {

// Get the attachments tables of item1 and item2   ITable tblAttach1 = item1.getAttachments();   ITable tblAttach2 = item2.getAttachments();

// Prepare params for the first row   HashMap params = new HashMap();   params.put(CommonConstants.ATT_ATTACHMENTS_CONTENT, file);

// Add the file to the attachments table of item1   IRow row1 = tblAttach1.createRow(params);

// Prepare params for the second row   params.clear();   params.put(CommonConstants.ATT_ATTACHMENTS_CONTENT, row1);   params.put(CommonConstants.MAKE_DEEP_COPY, Boolean.TRUE);

// Add the same file to the attachments table of item2   IRow row2 = tblAttach2.createRow(params);}
<<<<<<< .mine

Example 14-18 Deep cloning the Files table row of a File Folder

=======

Example 14-19 Deep cloning the Files table row of a File Folder

>>>>>>> .r346
// Clone a Files table row and its file from one File Folder to another   public static cloneFilesRow
      (IFileFolder folder1, IFileFolder folder2, File file) throws APIException {

// Check out folder1 and folder2   folder1.checkOutEx();   folder2.checkOutEx();

// Get the Files tables of folder1 and folder2   ITable tblFiles1 = folder1.getTable(FileFolderConstants.TABLE_FILES);   ITable tblFiles2 = folder2.getTable(FileFolderConstants.TABLE_FILES);

// Prepare params for the first row   HashMap params = new HashMap();   params.put(CommonConstants.ATT_ATTACHMENTS_CONTENT, file);

// Add the file to the attachments table of folder1   IRow row1 = tblFiles1.createRow(params);

// Prepare params for the second row
   params.clear();   params.put(CommonConstants.ATT_ATTACHMENTS_CONTENT, row1);   params.put(CommonConstants.MAKE_DEEP_COPY, Boolean.TRUE);

// Add the same file to the Files table of folder2   IRow row2 = tblFiles2.createRow(params);

// Check in folder1 and folder2   folder1.checkIn();   folder2.checkIn();   }
<<<<<<< .mine

14.7.2 Specifying the File Folder Subclass When Adding Attachments

=======

14.7.2 Specifying the File Folder Subclass When Adding Attachments

>>>>>>> .r346

You can set up your Agile PLM system with multiple file folder subclasses. If so, when you add a file folder to the Attachments table of a business object, you may want to specify which file folder subclass to use. If you do not specify a subclass, the Agile API uses the default File Folder subclass. The virtual attribute CommonConstants.ATT_ATTACHMENTS_FOLDERCLASS makes it easier to specify the required file folder subclass. It enables you to set the attribute to any file folder subclass.

The following example shows how to use the ATT_ATTACHMENTS_FOLDERCLASS attribute to specify a subclass when you add a file folder to the Attachments table.

<<<<<<< .mine

Example 14-19 Specifying the file folder subclass when adding attachments

=======

Example 14-20 Specifying the file folder subclass when adding attachments

>>>>>>> .r346
IAgileClass ffclass = m_admin.getAgileClass("MyFileFolder");

// init item   IItem item = (IItem)session.createObject(ItemConstants.CLASS_PART, "P0001");

// get attachments table   ITable tab_attachment = item.getAttachments();

// prepare map   HashMap map = new HashMap();   map.put(CommonConstants.ATT_ATTACHMENTS_CONTENT, new File("files/file.txt"));   map.put(CommonConstants.ATT_ATTACHMENTS_FOLDERCLASS, ffclass);

// add file   IRow row = tab_attachment.createRow(map);
<<<<<<< .mine

14.7.3 Retrieving Attachment Files

=======

14.7.3 Retrieving Attachment Files

>>>>>>> .r346

If a file folder is checked out by another user, you can still retrieve a copy of the file folder file(s) and save it to your local machine. The IAttachmentFile.getFile() method returns the file stream associated with a row of the Attachments table. The file stream can be for one file or it can be a zipped file stream for multiple files, depending on how many files the associated file folder has. You can also use IAttachmentFile.getFile() to get one or more files directly from a file folder instead of accessing the Attachments table of another business object. If you call getFile() from the file folder object, you return the zipped file stream for all files listed on the Files table. If you call getFile() from a row of the Files table of a file folder, you return a file stream for the specific file associated with that row.


Note:

When you use IAttachmentFile.getFile(), only file attachments are included in the returned file stream. URL attachments don't have files associated with them.

This example retrieves a copy of an attached file.

<<<<<<< .mine

Example 14-20 Getting attachment files

=======

Example 14-21 Getting attachment files

>>>>>>> .r346
// Get one or more files associated with the row of an Attachments table or a 
// Files table   public InputStream getAttachmentFile(IRow row) throws APIException {      InputStream content = 
         ((IAttachmentFile)row).getFile();
      return content;}

// Get all files associated with a file folderpublic InputStream getAttachmentFiles(IFileFolder ff) throws APIException {InputStream content = ((IAttachmentFile)ff).getFile();return content;}

If you use IFileFolder.getFile() to return a zipped file stream for all files contained in a file folder, you can extract files from the zipped InputStream file using methods of the java.util.zip.ZipInputStream class, as shown in the following example.

<<<<<<< .mine

Example 14-21 Extracting files from a zipped file stream

=======

Example 14-22 Extracting files from a zipped file stream

>>>>>>> .r346
static void unpack(InputStream zippedStream) throws IOException {   ZipInputStream izs = new ZipInputStream(zippedStream);   ZipEntry e = null;   while ((e = izs.getNextEntry()) != null) {      if (!e.isDirectory()) {         FileOutputStream ofs = new FileOutputStream(e.getName());         byte[] buf = new byte[1024];         int amt;      while ((amt = izs.read(buf)) != -1) {         ofs.write(buf, 0, amt);      }      ofs.close();   }}

The Agile API provides no direct method for opening an attachment file. However, you can retrieve a file and then have your program open it in a separate application or display it in a browser window.

<<<<<<< .mine

14.7.4 Deleting Attachments and File Folders

=======

14.7.4 Deleting Attachments and File Folders

>>>>>>> .r346

To delete a file folder, which may contain multiple files, use the IDataObject.delete() method. You must have the Delete privilege for file folders to be able to delete them. For more information about deleting objects, see "Deleting and Undeleting Objects."


Note:

Deleting a file folder does not automatically remove its associated files from the file server. The Agile PLM administrator is responsible for purging deleted files.

To delete a row from the Attachments table of a business object, use the ITable.removeRow() method. For more information, see "Removing Table Rows." Removing a row from the Attachments table does not delete the associated file folder. You cannot delete a row from the Attachments table in the following situations:

  • The parent object is an Item whose revision is incorporated.

  • The selected attachment is currently checked out.

<<<<<<< .mine

14.7.5 Working with Thumbnails

=======

14.7.5 Working with Thumbnails

>>>>>>> .r346

Agile PLM supports adding small static graphical images (thumbnails) to key objects which either represent graphical objects or require images. For example, documents attached as files such as Excel worksheets, text files, PDF files, CAD files and so on, can have associated thumbnail images. Thumbnails display scaled down versions of these files and, in the case of Part objects, show how they relate to each other.

The SDK supports the following Thumbnail-related functions:

  • Regenerating Thumbnails

  • Sequencing Thumbnails

  • Setting Master Thumbnails

  • Generating Thumbnails while adding Files to Attachments tab

<<<<<<< .mine

14.7.5.1 Accessing Thumbnails

=======

14.7.5.1 Accessing Thumbnails

>>>>>>> .r346

Agile SDK provides the IThumbnailContainer interface for generalized access to thumbnail-related operations for file folder and business objects. This interface is supported by the following API objects:

  • IFileFolder

  • IItem

  • IManufacturerPart

For IFileFolder objects, set the applicable version using IFileFolder.setCurrentVersion before calling the above APIs. The default version is LATEST_VERSION. For IItem or IManufacturerPart objects, use the revision that is already set on these objects.

The following example gets thumbnail details from TitleBlock of an IItem or IFileFolder object.

<<<<<<< .mine

Example 14-22 Getting thumbnail details from TitleBlock of IItem or IFileFolder objects

=======

Example 14-23 Getting thumbnail details from TitleBlock of IItem or IFileFolder objects

>>>>>>> .r346
IItem dataObj = (IItem)session.getObject(IItem.OBJECT_TYPE, "P00015");ITable titleBlockTable = dataObj.getTable(TableTypeConstants.TYPE_PAGE_ONE);
Iterator i = titleBlockTable.getTableIterator();while (i.hasNext()) {   IRow row = (IRow)i.next();   Object thumbnailIDDetails =   row.getValue(ThumbnailConstants.ATT_THUMBNAIL_ATTACHMENT_TAB);   IAgileList[] nodes =((IAgileList)thumbnailIDDetails).getSelection();for(int ii=0; ii<nodes.length; ii++) {   IAgileList childNode = nodes[ii];   IThumbnailID thumbnailID = (IThumbnailID)childNode.getValue();   }}
<<<<<<< .mine

14.7.5.2 Regenerating Thumbnails

=======

14.7.5.2 Regenerating Thumbnails

>>>>>>> .r346

Regenerating a thumbnail means generating a thumbnail for an existing (generated) thumbnail for file folder and item objects. This feature is of particular interest in assembly structures where a change in the child of the assembly structure is reflected in the thumbnail after the thumbnail is regenerated.

Agile SDK provides the IThumbnailContainer.generateThumbnail(IThumbnailID) API for this purpose. When invoked, it will generate and return a new thumbnail. In case of IFileFolder objects, API will use the current version of the object. For IItem or IManufacturerPart objects, it will use the current revision of the object. An APIException is thrown when the API fails to regenerate the thumbnail for the specified thumbnailID parameter.

<<<<<<< .mine

Example 14-23 Regenerating a thumbnail for an IFileFolder object

=======

Example 14-24 Regenerating a thumbnail for an IFileFolder object

>>>>>>> .r346
IFileFolder ff =   (IFileFolder)session.getObject(IFileFolder.OBJECT_TYPE, "FOLDER00037");   ff.setCurrentVersion(new Integer(1));   IThumbnailID oldThumbnailID = "";

//get this id from row of supported tables like Title Block   ff.generateThumbnail(oldThumbnailID);   //Regenerating a thumbnail for an IItem object     IItem itemObj =      (IItem)session.getObject(IItem.OBJECT_TYPE, "P00015");      IThumbnailID oldThumbnailID = "";

//get this id from row of supported tables like Title Block   itemObj.generateThumbnail(oldThumbnailID);
<<<<<<< .mine

14.7.5.3 Setting Master Thumbnails

=======

14.7.5.3 Setting Master Thumbnails

>>>>>>> .r346

In Agile PLM, a file folder object is represented by a thumbnail file which can contain several files in its Files tab. Using setMasterThumbnail, you can decide which row in the Files tab will represent the selected thumbnail's file folder.

SDK provides the setMasterThumbnail API to set master thumbnails on file folder objects. An exception is thrown if the function fails to set the master thumbnail represented by the parameter masterRow.

<<<<<<< .mine

Example 14-24 Setting a master thumbnail

=======

Example 14-25 Setting a master thumbnail

>>>>>>> .r346
IFileFolder ff = 
       (IFileFolder)session.getObject(IFileFolder.OBJECT_TYPE, "FOLDER00036");ITable attachmentTable = 
        ff.getTable(FileFolderConstants.TABLE_FILES);Iterator<?> i = 
        attachmentTable.getTableIterator();while (i.hasNext()) {         IRow row = (IRow)i.next();         if (row.getValue("fileName").toString().
                   equals("Resistor Family Data Sheet.pdf")){   ff.setMasterThumbnail(row);         }}
<<<<<<< .mine

14.7.5.4 Replacing Thumbnails

=======

14.7.5.4 Replacing Thumbnails

>>>>>>> .r346

You can replace an Agile PLM generated thumbnail with a user provided image for file folder and item objects. The SDK provides the following API for this purpose.

IThumbnailID replaceThumbnail (IThumbnailID oldThumbnailID, byte[] bytes) throws APIException

This API will replace the thumbnail referred to in oldThumbnailID with the image file referred to in the input stream. That is, it will return the ThumbnailID of the replaced thumbnail.

For IFileFolder objects, the API will use the version that is already set on the object. For IItem or IManufacturerPart objects, it will use the revision that is already set on the object. An APIException is thrown if it fails to replace the thumbnail specified in the oldThumbnailID parameter.

<<<<<<< .mine

Example 14-25 Replacing a thumbnail for an IFileFolder object

=======

Example 14-26 Replacing a thumbnail for an IFileFolder object

>>>>>>> .r346
IFileFolder ff =   (IFileFolder)session.getObject(IFileFolder.OBJECT_TYPE, "FOLDER00037");ff.setCurrentVersion(new Integer(1));IThumbnailID oldThumbnailID = "";
//get this id from row of supported tables like Title Block   String filePath = "C:\\Earth.bmp";   File file1_tmp = new File(filePath);   byte[] b1 = new byte[(int)file1_tmp.length()];   FileInputStream fileInputStream = new FileInputStream(file1_tmp);   fileInputStream.read(b1);   IThumbnailID newThumbnailID = 
      itemObj.replaceThumbnail(oldThumbnailID, b1);
   String filePath = "C:Earth.bmp";
<<<<<<< .mine

Example 14-26 Replacing a thumbnail for an IItem object

=======

Example 14-27 Replacing a thumbnail for an IItem object

>>>>>>> .r346
IItem itemObj =   (IItem)session.getObject(IItem.OBJECT_TYPE, "P00015");   IThumbnailID oldThumbnailID = "";
//get this id from row of supported tables like Title Block   String filePath = "C:Earth.bmp";   File file1_tmp = new File(filePath);   byte[] b1 = new byte[(int)file1_tmp.length()];   FileInputStream fileInputStream = new FileInputStream(file1_tmp);   fileInputStream.read(b1);IThumbnailID newThumbnailID = itemObj.replaceThumbnail(oldThumbnailID, b1);
<<<<<<< .mine

14.7.5.5 Sequencing Thumbnails

=======

14.7.5.5 Sequencing Thumbnails

>>>>>>> .r346

When Web Client users add attachment files to business objects, they can also set the order (sequence) of their appearance in the Thumbnail Navigator. Agile PLM provides the setThumbnailSequence API to enable this feature in the SDK. For IItem or IManufacturerPart objects, the API will use the revision that is already set on the object. The API will sort (sequence) the order of appearance using the thumbnailID parameter. An exception is thrown if the function fails to set the master thumbnail.

<<<<<<< .mine

Example 14-27 Sequencing thumbnails

=======

Example 14-28 Sequencing thumbnails

>>>>>>> .r346
IItem itemObj =   (IItem)session.getObject(IItem.OBJECT_TYPE, "P00015");IThumbnailID[] thumbnailIDs = null;

//get this id from row of Title Block table   IThumbnailID[] newSeqOfThumbnailIDs = null;

//generate new order using thumbnail IDs   itemObj.setThumbnailSequence(newSeqOfThumbnailIDs);
<<<<<<< .mine

14.7.5.6 Generating Thumbnails while Adding Files to Attachments Tab

=======

14.7.5.6 Generating Thumbnails while Adding Files to Attachments Tab

>>>>>>> .r346

There are no APIs specifically for this purpose. When you add a file to the Attachments tab of an Item, a thumbnail is generated for that file provided thumbnail support is enabled in the Web Client.

<<<<<<< .mine

14.7.6 Working with Design Objects

=======

14.7.6 Working with Design Objects

>>>>>>> .r346

A Design object is a business object that specifies one or more URLs or files that are stored in Agile PLM's File Management Server, and contain information about the binary files that are attached to it. Similar to other Agile PLM business objects, Design objects appear in Agile PLM's class hierarchy as a separate base class.

Design class objects are used with Agile PLM's Engineering Collaboration (EC) module which is used to manage CAD data in Agile PLM. Objects created in this class have many of the same properties and behaviors of File folders. In Java Client, users with administrator privileges can enable other users to open and work with Design objects. Agile PLM users can then access and work exclusively with these objects in the Web Client.

Agile SDK supports the following Design object-related functions:

  • Managing (adding, removing, getting, and editing) version specific Relationships between two Design objects

  • Using where-used queries for Design object deployments in Agile PLM Class structures. For information about where-used queries, see "Creating a Where-Used Query."

<<<<<<< .mine

14.7.6.1 Adding and Loading Design Objects

=======

14.7.6.1 Adding and Loading Design Objects

>>>>>>> .r346

To create or get an IDesign object, you can use IAgileSession.createObject() or IAgileSession.getObject(). The following examples show the different methods provided by the SDK to create and get Design objects.

<<<<<<< .mine

Example 14-28 Creating a Design by class name

=======

Example 14-29 Creating a Design by class name

>>>>>>> .r346
IDesign des = 
   (IDesign) m_session.createObject("Design", "DESIGN00133");
<<<<<<< .mine

Example 14-29 Creating a Design by class ID

=======

Example 14-30 Creating a Design by class ID

>>>>>>> .r346
IDesign des = (IDesign)
   m_session.createObject(FileFolderConstants.CLASS_DESIGN, "DESIGN00133");
<<<<<<< .mine

Example 14-30 Creating a Design by IAgileClass reference

=======

Example 14-31 Creating a Design by IAgileClass reference

>>>>>>> .r346
IDesign des = (IDesign)
   m_session.createObject(desClass, "DESIGN00133");
<<<<<<< .mine

Example 14-31 Loading a Design object

=======

Example 14-32 Loading a Design object

>>>>>>> .r346
IDesign des = (IDesign)
m_session.getObject(IDesign.OBJECT_TYPE, "DESIGN00133");
<<<<<<< .mine

14.7.6.2 Managing Version Specific Relationships between Design Objects

=======

14.7.6.2 Managing Version Specific Relationships between Design Objects

>>>>>>> .r346

Agile SDK supports the following version specific Relationships functions between Design objects:


Note:

These version specific functions only apply to Design objects.

  • Adding version specific relationships between Design objects

  • Removing version specific relationships between Design objects

  • Getting version specific relationships for specific versions of Design objects

  • Editing version specific relationships for Design objects

<<<<<<< .mine

14.7.6.3 Adding Relationships for Specific Versions of Design Objects

=======

14.7.6.3 Adding Relationships for Specific Versions of Design Objects

>>>>>>> .r346

The SDK provides the following API to add relationships between two specific versions of Design objects:

IDesign.addVersionSpecificRelationship(Object versionNum, IDesign relatedDesign, Object relatedVersionNum)

The parameters are:

  • versionNum - This an integer showing the version number of this Design object.

  • relatedDesign - The Design object you are creating the Relationships for.

  • relatedversionNum - This an integer showing the version number of the Design object you are creating the Relationship for.

An APIException is thrown if the version specific relationship between the two Design objects was not created.

Alternatively, you can load the object's RelationshipsTable and call createRow(Object params) with the following params:

HashMap params = new HashMap();params.put(DesignConstants.ATT_RELATIONSHIPS_REV_VERSION, versionNum);params.put(DesignConstants.ATT_RELATIONSHIPS_NAME, relatedDesign);params.put(DesignConstants.ATT_DESIGN_VERSION, relatedVersionNum);
<<<<<<< .mine

14.7.6.4 Removing Relationships for Specific Versions of Design Objects

=======

14.7.6.4 Removing Relationships for Specific Versions of Design Objects

>>>>>>> .r346

To remove Version Specific Relationships for IDesign:

IDesign des1 = (IDesign)session.getObject(IFileFolder.OBJECT_TYPE, "DESIGN00001");
des1.setCurrentVersion(new Integer(4));
ITable relationshipTable = des1.getRelationship();
relationshipTable.removeRow(row);
<<<<<<< .mine

14.7.6.5 Getting Relationships for Specific Versions of Design Objects

=======

14.7.6.5 Getting Relationships for Specific Versions of Design Objects

>>>>>>> .r346

To get the Relationships for a specific version of IDesign:

IDesign des1 = (IDesign)session.getObject(IFileFolder.OBJECT_TYPE, "DESIGN00001");
des1.setCurrentVersion(new Integer(4)); //set desired version
ITable relationshipTable = des1.getRelationship();
<<<<<<< .mine

14.7.6.6 Editing Relationships for Specific Versions of Design Objects

=======

14.7.6.6 Editing Relationships for Specific Versions of Design Objects

>>>>>>> .r346

To edit the Relationships for a specific version of the IDesign object:

IDesign des1 = (IDesign)session.getObject(IFileFolder.OBJECT_TYPE, "DESIGN00001");
des1.setCurrentVersion(new Integer(4));
ITable relationshipTable = des1.getRelationship();
HashMap mapForUpdate=new HashMap();
HashMap rowUpdateMap = new HashMap();
rowUpdateMap.put(DesignConstants.ATT_DESIGN_VERSION, new Integer(1));
mapForUpdate.put(row1, rowUpdateMap);
relationshipTable.updateRows(mapForUpdate);
<<<<<<< .mine

14.7.6.7 Purging Specific Versions of Design Objects

=======

14.7.6.7 Purging Specific Versions of Design Objects

>>>>>>> .r346

The SDK provides the IDesign.purgeVersions(Object[] versions) API for purging specific versions of Design objects and relevant versions of its child objects. The versions parameter, an integer value, specifies the version number you want purged. An exception is thrown if the API fails to purge the object.

<<<<<<< .mine

14.7.6.8 Searching Design Object Deployments with Where-Used Queries

=======

14.7.6.8 Searching Design Object Deployments with Where-Used Queries

>>>>>>> .r346

The Structure tab for Design objects enables users to create structures of different Design objects having different versions. The SDK supports searching for Design object usage in Agile PLM Class Structures for the latest checked in versions and all checked in versions with the following queries and query constants:

  • WHERE_USED_IN_STRUCTURE_ONE_LEVEL_LATEST_CHECKEDIN - This WHERE_USED query returns the LATEST version of the immediate parent of the Design object which uses the input Design object as a child in the design structure. The constant QueryConstants.WHERE_USED_IN_STRUCTURE_ONE_LEVEL_LATEST_CHECKEDIN supports this search.

  • WHERE_USED_IN_STRUCTURE_ALL_LEVEL_LATEST_CHECKEDIN - This WHERE_USED query returns ALL versions of the immediate parent of the Design object which uses the input Design object as a child in the design structure. The constant QueryConstants.WHERE_USED_IN_STRUCTURE_ONE_LEVEL_ALL_CHECKEDIN supports this search.

You can find code samples using QueryConstants in SDK_samples.zip folder. To access this file, see the Note in "Client-Side Components." These are the Javadoc generated HTML files in the documentation folder.

The two searches and their respective results are explained with the aid of the following illustration. It shows the Design objects and level one structures. The search parameter Title Block.Number includes the number 11.

<<<<<<< .mine
=======
>>>>>>> .r346

Figure 14-3 Design objects and search results

Surrounding text describes Figure 14-3 .