Agile Product Lifecycle Management SDK Developer Guide - Using APIs Release 9.3.3 E39307-02 |
|
![]() Previous |
![]() Next |
This chapter includes the following:
About Attachments and File Folders
Working with File Folders
Working with Attachments Table of an Object
Checking Out a File Folder
Canceling a File Folder Checkout
Adding Files and URLs to the Attachments Table
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.
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. |
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.
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.
A description of these classes and objects appears in the table below.
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."
The File Folder object supports the following tables and corresponding 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 |
IFileFolder is the interface that corresponds to the file folder business object. The following example shows how to create a file folder.
Example: Creating a file folder
Example 13-1 Creating a file folder
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 automatically 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.
Example 13-2 Creating a Design object
// autoNum is autoNumber as usual IFileFolder obj = (IFileFolder) m_session.createObject( FileFolderConstants.CLASS_DESIGN, autoNum); }
Example 13-3 Adding Design objects to a Structure tree
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();
Example 13-4 Loading a Structure table
public void testLoadingDesignStructureTable() throws Exception {addCaseInfo("Design Object", "load Structure table", "");// assuming Design object Design00004 existed with some data in StructureIFileFolder obj = (IFileFolder) m_session.getObject(FileFolderConstants.CLASS_DESIGN, "Design00004");IAgileClass agileClass = obj.getAgileClass();// load Structure tableITable table = obj.getTable(FileFolderConstants.TABLE_STRUCTURE);Integer tableId = (Integer) table.getTableDescriptor().getId();// ITable performs related tasks}
Example 13-5 Loading a Structure table as a tree
public void testLoadingDesignStructureTree() throws Exception{ addCaseInfo("Design Object", "load Structure tree", "");// 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(); printRow(agileClass, print, tableId, (IRow) node); 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); } }}
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.
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;
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.
Example 13-7 Adding files and URLs to the Files table of a file folder
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();}
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. |
The results returned from IAttachmentFile methods vary depending on the object you're working with, as shown in the following table.
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.
Example 13-8 Using isSecure() and getFile()
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;}
To work with the Attachments table of an object, follow this sequence.
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.
Get the Attachments table. Use the IDataObject.getTable() or IAttachmentContainer.getAttachments() methods to get the table.
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.
Example 13-9
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);}
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.
Example 13-10
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); }}
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."
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.
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. These two examples are Process Extensions. For information on Process Extensions, refer to SDK Developer Guide - Developing PLM Extensions and for information about checking if a revision is incorporated, see "Changing the Incorporated Status of a Revision."
Example 13-11 Incorporating Attachments
class IncorporateItem implements ICustomAction { public ActionResult doAction(IAgileSession session, INode actionNode, IDataObject affectedObject) { try { System.out.println("Workflow action kicked off...."); IItem object = (IItem)affectedObject; System.out.println("Incorporating..."); IItem loItem = (IItem) session.getObject(IItem.OBJECT_TYPE, object.getName()); //this will get the latest version. Make sure the latest is against a MCO loItem.setIncorporated(true); //incorporate the attachment System.out.println("Attachment added."); String message = ("Incorporated"+object); return new ActionResult(ActionResult.STRING, message); } catch (APIException ae) { ae.printStackTrace(); return new ActionResult(ActionResult.EXCEPTION, ae); } }}
Example 13-12 Un-incorporating Attachments
class IncorporateItem implements ICustomAction { public ActionResult doAction(IAgileSession session, INode actionNode, IDataObject affectedObject) { try { System.out.println("Workflow action kicked off...."); IItem object = (IItem)affectedObject; System.out.println("Un-incorporating..."); IItem loItem = (IItem) session.getObject(IItem.OBJECT_TYPE, object.getName()); //this will get the latest released version ssage); loItem.setIncorporated(false); System.out.println("Attachment added."); String message = ("Un-incorporated"+object); return new ActionResult(ActionResult.STRING, message } catch (APIException ae) { ae.printStackTrace(); return new ActionResult(ActionResult.EXCEPTION, ae); } } }
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.
Example 13-13 Checking out a file folder
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." |
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 shows how to cancel a checkout of a file folder.
Example 13-14 Canceling checkout of a file folder
void cancelCheckOut(IFileFolder ff) {// Show a confirmation dialog box int i = JOptionPane.showConfirmDialog(null, "Are you sure you want to cancel checkout?", "Cancel Checkout", JOptionPane.YES_NO_OPTION);// If the user clicks Yes, cancel checkout try { if (i == 0) { ff.cancelCheckout(); } } catch (APIException ex) { System.out.println(ex); }}
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." |
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.
Example 13-15 Creating a file folder by adding a row to the Attachments table
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.
Example 13-16 Adding files to the Attachments table
// 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 { I Row 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; }
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.
Example 13-17 Deep cloning an Attachments table row
// 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);}
Example 13-18 Deep cloning the Files table row of a File Folder
// 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(); }
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.
Example 13-19 Specifying the file folder subclass when adding attachments
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);
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 shows how to retrieve a copy of an attached file.
Example 13-20 Getting attachment files
// 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.
Example 13-21 Extracting files from a zipped file stream
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.
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.
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
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 object
IItem object
IManufacturerPart object
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.
Example 13-22 Getting thumbnail details from TitleBlock of IItem or IFileFolder objects
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(); }}
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.
Example 13-23 Regenerating a thumbnail for an IFileFolder object
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);
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.
Example 13-24 Setting a master thumbnail
IFileFolder ff = (IFileFolder)session.getObject(IFileFolder.OBJECT_TYPE, "FOLDER00037");ff.setCurrentVersion(new Integer(1));ITable attachmentTable = ff.getTable(FileFolderConstants.TABLE_FILES);Iterator i = attachmentTable.getTableIterator();while (i.hasNext()) { IRow row = (IRow)i.next(); IRow masterRow = null; } //set one of the rows as the master row ff.setMasterThumbnail(masterRow);
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.
Example 13-25 Replacing a thumbnail for an IFileFolder object
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";
Example 13-26 Replacing 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 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);
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.
Example 13-27 Sequencing thumbnails
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);
A Design object is a business object that specifies one or more URLs or files stored in Agile PLM's File Management Server. It contains information about the binary files 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 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."
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.
Example 13-28 Creating a Design by class name
IDesign des = (IDesign) m_session.createObject("Design", "DESIGN00133");
m_session.createObject(FileFolderConstants.CLASS_DESIGN, "DESIGN00133");
m_session.createObject(desClass, "DESIGN00133");
m_session.getObject(IDesign.OBJECT_TYPE, "DESIGN00133");
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
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);
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);
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();
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);
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.
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.