Working with Attachments and Images
Working with attachments and images via the Java SDK is slightly different from other types of assets in that it involves working with specialized endpoints. These specialized endpoints are used for uploading and downloading the attachment and image data, which in most cases is in a binary format. Adding attachment and images to a Digital.ai Agility asset is a two step process:
Creating an Attachment
Prior to the 15.1.0 release of the SDK, creating an attachment for an asset involved first creating an Attachment asset then using theAttachmentsobject to upload the attachment data. Starting with the 15.1.0 release, a much simplersaveAttachmentmethod is available on theServicesobject.With thesaveAttachmentmethod, you no longer have to create a specialV1Connectorto the attachment.img endpoint to upload attachments to Agility.
Creating an Attachment Using the Services Object
To create an attachment and associate it with an asset in Agility, call thesaveAttachmentmethod of theServicesobject passing in the path and name of the file, the asset to associate with, and the name to use for the attachment. This example first creates a new story then adds the attachment to it:
Oid projectId = services.getOid("Scope:0");
IAssetType storyType = services.getMeta().getAssetType("Story");
Asset newStory = services.createNew(storyType, projectId);
IAttributeDefinition nameAttribute = storyType.getAttributeDefinition("Name");
newStory.setAttributeValue(nameAttribute, "Story with Attachment");
services.save(newStory);
String file = "C:\\Temp\\versionone.jpg";
services.saveAttachment(file, newStory, "Attachment for " + newStory.getOid().toString());
Creating an Attachment Using the Attachment Object
To create an attachment and associate it with an asset in Agility, you must first create an Attachment asset and retain its OID value which will be used to upload the attachment. This example creates an attachment asset for the Story with ID 1317.
Oid storyOid = services.getOid("Story:1317");
String file = "C:\\Temp\\versionone.png";
String mimeType = MimeType.resolve(file);
IAssetType attachmentType = services.getMeta().getAssetType("Attachment");
IAttributeDefinition attachmentAssetDef = attachmentType.getAttributeDefinition("Asset");
IAttributeDefinition attachmentContent = attachmentType.getAttributeDefinition("Content");
IAttributeDefinition attachmentContentType = attachmentType.getAttributeDefinition("ContentType");
IAttributeDefinition attachmentFileName = attachmentType.getAttributeDefinition("Filename");
IAttributeDefinition attachmentName = attachmentType.getAttributeDefinition("Name");
Asset attachment = services.createNew(attachmentType, Oid.Null);
attachment.setAttributeValue(attachmentName, "Attachment for " + storyOid.getMomentless());
attachment.setAttributeValue(attachmentFileName, file);
attachment.setAttributeValue(attachmentContentType, mimeType);
attachment.setAttributeValue(attachmentContent, "");
attachment.setAttributeValue(attachmentAssetDef, storyOid);
services.save(attachment);
Oid attachmentOid = attachment.getOid()
Note the use of the MimeTypehelper object. The resolve method of this object is used to determine the content type to use for the attachment asset. Also note that an empty string is passed for the Content attribute.
Once you've created the attachment asset and have its OID, you can then use the Attachments object to upload the binary data of the attachment. To use the Attachments object, you'll need to create a new V1Connector object, using the useEndpoint method to set the attachment.img endpoint. You then use the java.iopackage to read the binary data of the attachment, and then methods of the attachment class to write the stream.
V1Connector attachmentConnector = V1Connector
.withInstanceUrl("<Server Base URI>")
.withUserAgentHeader("AppName", "1.0")
.withAccessToken("1.rWM8lKLk+PnyFxkEWVX5Kl2u6Jk=")
.useEndpoint("attachment.img/")
.build();
IAttachments attachments = new Attachments(attachmentConnector);
FileInputStream inStream = new FileInputStream(file);
OutputStream output = attachments.getWriter(attachmentOid.getKey().toString(), mimeType);
byte[] buffer = new byte[inStream.available() + 1];
while (true) {
int read = inStream.read(buffer, 0, buffer.length);
if (read <= 0)
break;
output.write(buffer, 0, read);
}
attachments.setWriter(attachmentOid.getKey().toString());
inStream.close();
Note that as of the 15.1.0release of the SDK, both theuseEndpointmethod and theAttachmentsobject have been marked for deprecation.
Querying an Attachment
Prior to the 15.1.0 release of the SDK, querying an attachment for an asset involved using thegetReadStreammethod of theAttachmentsobject to download the attachment data. Starting with the 15.1.0.0 release, a much simplergetAttachmentmethod is available on theServicesobject. With thegetAttachmentmethod, you no longer have to create a specialV1Connectorto the attachment.img endpoint to download attachments from Digital.ai Agility.
Querying an Attachment Using the Services Object
Getting an attachment from Agility involves getting the OID of the attachment, then using thegetAttachmentmethod of theServicesobject. In this example, a query is used to get all the attachments associated with Story ID 6052, and then write each attachment as a file:
Oid assetOid = services.getOid("Story:1181");
IAssetType attachmentType = services.getMeta().getAssetType("Attachment");
Query query = new Query(attachmentType);
IAttributeDefinition filenameAttribute = attachmentType.getAttributeDefinition("Filename");
IAttributeDefinition assetAttribute = attachmentType.getAttributeDefinition("Asset");
query.getSelection().add(filenameAttribute);
query.getSelection().add(assetAttribute);
FilterTerm term = new FilterTerm(assetAttribute);
term.equal(assetOid.getMomentless());
query.setFilter(term);
QueryResult result = services.retrieve(query);
for (Asset attachment : result.getAssets()) {
String fileName = attachment.getAttribute(filenameAttribute).getValue().toString();
File file = new File(fileName);
InputStream inStream = _services.getAttachment(attachment.getOid());
if (null != inStream) {
FileOutputStream outStream = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len;
while ((len = inStream.read(buf)) > 0) {
try {
outStream.write(buf, 0, len);
} catch (IndexOutOfBoundsException e) {
System.out.println("\nIndexOutOfBoundsException occurred, please try again........\n");
}
}
outStream.close();
inStream.close();
}
System.out.println(fileName);
}
/***** OUTPUT *****
Test Image Attachment.png
Test Document Attachment.pdf
******************/
Querying an Attachment Using the Attachment Object
Getting an attachment from Agility involves getting the OID of the attachment, then using the getReadermethod of the Attachments object. In this example, a query is used to get all the attachments associated with Story ID 1317, and then write the attachments as files to the C:\Temp directory:
Oid assetOid = services.getOid("Story:1317");
V1Connector attachmentConnector = V1Connector
.withInstanceUrl("<Server Base URI>")
.withUserAgentHeader("AppName", "1.0")
.withAccessToken("1.rWM8lKLk+PnyFxkEWVX5Kl2u6Jk=")
.useEndpoint("attachment.img/")
.build();
IAttachments attachments = new Attachments(attachmentConnector);
IAssetType attachmentType = services.getMeta().getAssetType("Attachment");
Query query = new Query(attachmentType);
IAttributeDefinition filenameAttribute = attachmentType.getAttributeDefinition("Filename");
IAttributeDefinition assetAttribute = attachmentType.getAttributeDefinition("Asset");
query.getSelection().add(filenameAttribute);
query.getSelection().add(assetAttribute);
FilterTerm term = new FilterTerm(assetAttribute);
term.equal(assetOid.getMomentless());
query.setFilter(term);
QueryResult result = services.retrieve(query);
String filePath = "C:\\Temp\\";
for (Asset attachment : result.getAssets()) {
String fileName = attachment.getAttribute(filenameAttribute).getValue().toString();
String attachmentKey = attachment.getOid().getKey().toString();
File file = new File(filePath + "v1_" + fileName);
InputStream inStream = attachments.getReader(attachmentKey);
if (null != inStream) {
OutputStream outStream = new FileOutputStream(file);
byte buf[] = new byte[1024];
int len;
while ((len = inStream.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
outStream.close();
inStream.close();
}
System.out.println(fileName);
}
/***** OUTPUT *****
Test Image Attachment.png
Test Document Attachment.pdf
******************/
Note that as of the 15.1.0 release of the SDK, both theuseEndpointmethod and theAttachmentsobject have been marked for deprecation.
Deleting an Attachment
Deleting an attachment is the same process as used for any other Agility asset, you use thegetOperation method to get the operation to execute, then call the executeOperation method of the Services object, passing in the operation and the OID of the asset:
IOperation deleteOperation = services.getMeta().getOperation("Attachment.Delete");
services.executeOperation(deleteOperation, services.getOid("Attachment:6640"));
Adding an Embedded Image
Prior to the 15.1.0 release of the SDK, creating an embedded image for an asset involved first creating an EmbeddedImage asset then using theAttachmentsobjectto upload the embedded image data. Starting with the 15.1.0release, a much simpler saveEmbeddedImagemethod is available on theServicesobject.With thesaveEmbeddedImagemethod, you no longer have to create a specialV1Connectorto the embedded.img endpoint to upload embedded images to Agility.
Adding an Embedded Image Using the Services Object
Adding an embedded image using theServicesobject involves calling theSaveEmbeddedImagemethod and specifying the path and name to the image to embed, and the asset that it should be associated with.
In this example, a new story is created, an embedded image is associated with it, then the story's description field is modified to include the embedded image:
//Create a new story.
IAssetType storyType = services.getMeta().getAssetType("Story");
Asset newStory = services.createNew(storyType, services.getOid("Scope:0"));
IAttributeDefinition nameAttribute = storyType.getAttributeDefinition("Name");
IAttributeDefinition descriptionAttribute = storyType.getAttributeDefinition("Description");
String name = "Story with an embedded image";
newStory.setAttributeValue(nameAttribute, name);
services.save(newStory);
//Add the embedded image to the story.
String file = "C:\\Temp\\versionone.jpg";
Oid embeddedImageOid = services.saveEmbeddedImage(file, newStory);
String embeddedImageTag = "<img src="+"embedded.img/" + embeddedImageOid.getKey() + " alt=\"\" data-oid=" + embeddedImageOid.getMomentless() + " />";
newStory.setAttributeValue(descriptionAttribute, embeddedImageTag);
services.save(newStory);
Adding an Embedded Image Using the Attachments Object
An embedded image is an image that you add to the Description attribute of an asset, and adding an embedded image follows a similar process as that of an attachment, except that it makes use of the embedded.img endpoint, and involves using the EmbeddedImage asset and adding a bit of HTML.
In the following example, a story is created in Scope:0 and an image file is read from the C:\Temp directory and added as an embedded image to the description of the story:
//Create a new story.
IAssetType storyType = services.getMeta().getAssetType("Story");
Asset newStory = services.createNew(storyType, services.getOid("Scope:0"));
IAttributeDefinition nameAttribute = storyType.getAttributeDefinition("Name");
IAttributeDefinition descriptionAttribute = storyType.getAttributeDefinition("Description");
String name = "Story with an embedded image";
newStory.setAttributeValue(nameAttribute, name);
services.save(newStory);
//Create an embedded image asset.
String fileName = "versionone.png";
String filePath = "C:\\Temp\\";
String mimeType = MimeType.resolve(fileName);
IAssetType embeddedImageType = services.getMeta().getAssetType("EmbeddedImage");
Asset newEmbeddedImage = services.createNew(embeddedImageType, Oid.Null);
IAttributeDefinition assetAttribute = embeddedImageType.getAttributeDefinition("Asset");
IAttributeDefinition contentAttribute = embeddedImageType.getAttributeDefinition("Content");
IAttributeDefinition contentTypeAttribute = embeddedImageType.getAttributeDefinition("ContentType");
newEmbeddedImage.setAttributeValue(assetAttribute, newStory.getOid());
newEmbeddedImage.setAttributeValue(contentTypeAttribute, mimeType);
newEmbeddedImage.setAttributeValue(contentAttribute, "");
services.save(newEmbeddedImage);
String key = newEmbeddedImage.getOid().getKey().toString();
//Save the embedded image file data.
V1Connector attachmentConnector = V1Connector
.withInstanceUrl("<Server Base URI>")
.withUserAgentHeader("AppName", "1.0")
.withAccessToken("1.rWM8lKLk+PnyFxkEWVX5Kl2u6Jk=")
.useEndpoint("embedded.img/")
.build();
IAttachments attachments = new Attachments(attachmentConnector);
FileInputStream inStream = new FileInputStream(filePath + fileName);
OutputStream output = attachments.getWriter(key, mimeType);
byte[] buffer = new byte[inStream.available() + 1];
while (true) {
int read = inStream.read(buffer, 0, buffer.length);
if (read <= 0)
break;
output.write(buffer, 0, read);
}
attachments.setWriter(key);
inStream.close();
//Add the embedded image to the story.
newStory.setAttributeValue(descriptionAttribute, "<img src="+"embedded.img/" + key+ " alt=\"\" data-oid=" +newEmbeddedImage.getOid().getMomentless()+" />");
services.save(newStory);
Note that as of the 15.1.0.0 release of the SDK, both theuseEndpointmethod and theAttachmentsobject have been marked for deprecation.