using System;
using System.IO;
using System.Text;
using Plumtree.Remote.PRC;
using Plumtree.Remote.PRC.Content;
using Plumtree.Remote.PRC.Content.DataEntryTemplate;
using Plumtree.Remote.PRC.Content.Folder;
using Plumtree.Remote.PRC.Content.Item;
using Plumtree.Remote.PRC.Content.PresentationTemplate;
using Plumtree.Remote.PRC.Content.Property;
using Plumtree.Remote.PRC.Content.SelectionList;
using Plumtree.Remote.PRC.Content.Security;
namespace ContentItemCommandLineExample
{
///
/// Command-line example of Content api
///
///
///This sample demonstrates all of the basic Content Server API
/// objects. It can be run from the command line, creates all of
/// its data, and cleans up after itself when it is done.
///
///This is an example of a programatically creating content items
///(records in the Content Server). The use case is a business
/// process where something triggers a customer support incident.
/// This creates a content item for the incident that can be viewed
///from the portal in a support incident portlet
///
/// Before running this sample
/// 1) Verify the endpointURL and username and password are correct in EstablishSession()
/// 2) Set any break points to observe the sample as it runs
/// 3) Comment out the folderManager.removeFolder(folder); if you want to keep the created items after the sample has run
///
class ContentExample
{
///
/// Runs through the high-level logic of importing records
/// into Content Server.
///
[STAThread]
static void Main(string[] args)
{
Console.WriteLine("Started Sample Application.");
// Step 1: Get an EDK session and Content Server factory.
IRemoteSession session = EstablishSession();
IContentFactory contentFactory = session.GetContentFactory();
Console.WriteLine("Step 1 - Session Established and Content Factory Created");
// Step 2: Get a Content Server folder.
// All Content Server objects are stored in folders. Since
// they are necessary for creating or querying objects, the
// first real step is to get your application's folder(s).
IFolder folder = RetrieveContentFolder(contentFactory);
Console.WriteLine("Step 2 - Folder retrieved with name: " + folder.Name);
// Step 3: Set security on the Content Server folder
// All Content Server folders have access control lists
// or ACLs associated with them. This step adds a user
// and a group to this folder's ACL.
folder = UpdateContentFolderSecurity(folder);
Console.WriteLine("Step 3 - Folder security updated with name: " + folder.Name);
// Step 4: Get the Data Entry Template (DET).
// A DET is used when creating any collection of records.
// It defines the fields within each record and logically
// groups them together. A DET is analogous to creating
// a new database table. In this example the DET represents
// the fields in each customer support incident.
IDataEntryTemplate det = RetrieveDET(contentFactory, folder);
Console.WriteLine("Step 4 - Data Entry Template retrieved with name: " + det.Name);
// Step 5: Get the Presentation Template (PT).
// The PT describes how each record within a collection is
// displayed. For each collection of records, there is
// exactly one DET and PT. Both are needed to publish
// individual records (content items).
IPresentationTemplate pt = RetrievePT(contentFactory, det);
Console.WriteLine("Step 5 - Presentation Template retrieved with name: " + pt.Name);
// Step 6: Create content items.
// Each support incident is a new content item. Content items
// are records and analogous to rows in a database table.
//
// In a real application, we would actually want receive events
// for when new support incidents are registered from some
// other system such as Siebel. This would probably be done
// as a loop, but for this example we will create a single
// record.
IContentItem ci = CreateSupportIncident(contentFactory, det, pt);
Console.WriteLine("Step 6 - Content Item created with name: " + ci.Name);
Console.WriteLine("\nThe Content Item has been created. \nYou may go to the Content Server Manager to observe the objects that have been created");
Console.WriteLine("When you are done, press any key to remove the created items and finish the sample");
Console.ReadLine();
// Step 7: Cleanup.
// Normally an application would not erase all of its data,
// but since this is a sample it should clean up after itself.
// Comment out these lines if you want to see all of the
// content that is created without setting break points.
IFolderManager folderManager = contentFactory.GetFolderManager();
folderManager.RemoveFolder(folder);
Console.WriteLine("Step 7 - Folder deleted");
Console.WriteLine("Finished Sample Application.");
}
///
/// Creates an EDK session. Change this to reference your SOAP endpoint.
///
private static IRemoteSession EstablishSession()
{
// Change the values below to match your configuration.
Uri endpointURL = new Uri("http://localhost/ptapi/services/QueryInterfaceAPI");
string username = "Administrator";
string password = "";
// Create a remote API session.
IRemoteSession remoteSession = RemoteSessionFactory.GetExplicitLoginContext(endpointURL, username, password);
return remoteSession;
}
///
/// Gets the Content Server folder used to store all Content
/// Server objects for our application.
///
/// In this sample, we will create a new folder. In your
/// real application you would likely have created the folder * already and will need to query for it here.
///
private static IFolder RetrieveContentFolder(IContentFactory factory)
{
// Get a folder manager for working with Content Server folders.
IFolderManager folderManager = factory.GetFolderManager();
//If we were looking for an existing folder by path we could
//use the following method
//IFolder subFolder = folderManager.GetFolderByPath("/folder1/folder2");
//Instead, we will create our own folder for the sample
// Get a reference to the root folder. It always exists.
IFolder rootFolder = folderManager.GetRootFolder();
// Create a new folder.
IFolder subFolder = folderManager.CreateFolder(rootFolder, "C# Example - Support Incidents");
subFolder.Store();
return subFolder;
}
/**
* Gets the Content Server ACL for the folder used to store the Content
* Server objects for our application.
*
* In this sample, we will display the current ACL on the folder and will add
* a new user and group entry for this folder.
*/
private static IFolder UpdateContentFolderSecurity(IFolder folder)
{
//get the existing ACL associated with this folder
IFolderACL folderACL = folder.GetFolderACL();
// get the entries off of this ACL
IFolderACLEntry [] entries = folderACL.GetEntries();
// loop through the entries and print out the values of each entry
Console.WriteLine("Printing ACL for folder " + folder.Name);
Console.WriteLine(entries.Length + " entries found in this ACL");
for (int i = 0; i < entries.Length; i++) {
// get the individual entry
IFolderACLEntry aclEntry = entries[i];
// print out its details
Console.WriteLine("---------------------------------------------------------");
Console.Write("ObjectID for this FolderACLEntry " + aclEntry.GetObjectID());
Console.Write("MemberType for this FolderACLEntry " + aclEntry.GetMemberType());
Console.WriteLine("RoleType for this FolderACLEntry " + aclEntry.GetRoleType());
}
// now add a new entry to this acl for the portal Guest user
// the guest user's object id is 2.
folderACL.AddUserEntry(2, RoleTypes.Editor);
// now add a new entry to this acl for the portal Administrator's group
// the portal Administrator's group's object id is 1.
folderACL.AddGroupEntry(1, RoleTypes.Administrator);
// store this acl to persist the changes back to the server
folderACL.Store();
// loop through the entries and print out the values of each entry
Console.WriteLine("Printing ACL for folder " + folder.Name);
Console.WriteLine(entries.Length + " entries found in this ACL");
for (int i = 0; i < entries.Length; i++) {
// get the individual entry
IFolderACLEntry aclEntry = entries[i];
// print out its details
Console.WriteLine("---------------------------------------------------------");
Console.Write("ObjectID for this FolderACLEntry " + aclEntry.GetObjectID());
Console.Write("MemberType for this FolderACLEntry " + aclEntry.GetMemberType());
Console.WriteLine("RoleType for this FolderACLEntry " + aclEntry.GetRoleType());
}
return folder;
}
///
/// Gets the DET that defines what fields are present in each
/// customer support incident.
///
/// In this sample, we will create a new DET. In your real
/// application, this method would probably query for an existing Data Entry Template. * existing DET.
///
private static IDataEntryTemplate RetrieveDET(IContentFactory factory, IFolder folder)
{
//
// A Data Entry Template object is a collection of
// property objects. Each property object represents
// a field in the records associated with the DET.
//
// This sample uses all of the classes of properties
// available in Content Server. Each customer support
// incidents will have:
// (integer) Incident ID
// (boolean) If the incident has been resolved
// (float) Incident severity rating
// (date) Date the incident was opened
// (text line) Customer name
// (item reference) Link to other content item representing the customer
// (selection list) The product the incident was reported in
// (text block) Reported problem
// (file) Logs of problem
// (image) Screen shot of problem
//
// Get manager objects needed for creating a DET.
IDataEntryTemplateManager detManager = factory.GetDataEntryTemplateManager();
IPropertyManager propertyManager = factory.GetPropertyManager();
ISelectionListManager slManager = factory.GetSelectionListManager();
// Create a DET object.
IDataEntryTemplate det = detManager.CreateDataEntryTemplate(folder, "Support Incident Data Entry Template");
// Add an integer property.
IIntegerProperty incident = propertyManager.CreateIntegerProperty("Incident ID", "The ticket number for this incident.");
det.AddProperty(incident);
// Add a boolean property
IBooleanProperty resolved = propertyManager.CreateBooleanProperty("Resolved", "True if the incident has been closed; false if it is still open.");
det.AddProperty(resolved);
// Add a double property.
IDoubleProperty severity = propertyManager.CreateDoubleProperty("Severity", "Percentage stating how severe the incident is.");
det.AddProperty(severity);
// Add a date property.
IDateProperty opened = propertyManager.CreateDateProperty("Date Opened", "The date and time the incident was reported.");
det.AddProperty(opened);
// Add a text line property.
// Text lines are brief strings without newline characters.
// Use the text block property for storing longer strings.
ITextLineProperty customerName = propertyManager.CreateTextLineProperty("Customer Name", "The name of the customer.");
det.AddProperty(customerName);
// Add an item reference property.
// An item reference links to another content item. The
// content item does not have to be associated with the
// same DET. For example, we will link to a fictional
// content item representing the customer that is having
// the support problem; which would be associated with
// a DET representing customers.
//
// Not shown is the item collection property. It is
// similar to the item reference property, but links to
// multiple content items.
IItemReferenceProperty customerData = propertyManager.CreateItemReferenceProperty("Customer Information", "Links to information about the customer such as the contact and their phone number.");
det.AddProperty(customerData);
// Add a selection list property.
// A selection list is a defined set of choices of which
// one may be selected. This can be visualized as a
// drop down box.
string[] listValues = {"Portal", "Search Server", "Collaboration Server", "Content Server", "Analytics"};
ISelectionList selectionList = slManager.CreateSelectionList(folder, "Products Selection List", listValues);
selectionList.Store();
ISelectionListProperty products = propertyManager.CreateSelectionListProperty("Product", "The product which the support incident is opened against", selectionList);
det.AddProperty(products);
// Add a text block property.
// Text block properties are used to store long strings
// that can span many lines. For short strings contained
// on only one line, use the text line property instead.
ITextBlockProperty description = propertyManager.CreateTextBlockProperty("Incident Description", "A writeup summarizing the problem the customer is experiencing.");
det.AddProperty(description);
// Add a file property.
IFileProperty log = propertyManager.CreateFileProperty("Log File", "A log file taken while the problem occurred.");
det.AddProperty(log);
// Add an image property.
IImageProperty screenShot = propertyManager.CreateImageProperty("Screen Shot", "A screen shot of the problem.");
det.AddProperty(screenShot);
// Actually store the DET and all the properties associated with it.
det.Store();
return det;
}
///
/// Gets the PT that defines how to display customer support
/// incident records.
///
/// In this sample, we will create a new PT. In your real
/// application, this method would probably query an already * existing PT.
///
private static IPresentationTemplate RetrievePT(IContentFactory factory, IDataEntryTemplate det)
{
//
// A Presentation Template object defines how content
// items associated with a Data Entry Template should
// be displayed. For content items to be displayed,
// the must have a DET and PT associated with them
// and be published.
//
// Get a PT manager object.
IPresentationTemplateManager ptManager = factory.GetPresentationTemplateManager();
// Create a PT.
StringBuilder templateBuffer = new StringBuilder();
templateBuffer.Append("
\n")
.Append("Incident ID | |
\n")
.Append("Created By | on |
\n")
.Append("Resolved | |
\n")
.Append("Severity | |
\n")
.Append("Date Opened | |
\n")
.Append("Customer Name | |
\n")
.Append("Customer Information | |
\n")
.Append("Product | |
\n")
.Append("Incident Description | |
\n")
.Append("Log File | |
\n")
.Append("Screen Shot | |
\n")
.Append("
\n");
IPresentationTemplate pt = ptManager.CreatePresentationTemplate(det.GetContainingFolder(), "Customer Support Incident Presentation Template", templateBuffer.ToString());
// Store the PT.
pt.Store();
// Validate the template text before using it to publish items
String[] errorsInText = ptManager.ValidateTemplateText(pt, pt.TemplateText);
if(errorsInText.Length != 0)
{
Console.WriteLine("Validate Template Text returned the following errors");
for(int i = 0; i < errorsInText.Length; i++)
{
Console.WriteLine("error[" + i + "]: " + errorsInText[i]);
}
}
// Associate the PT with a DET.
// There is a one-to-one correspondance between Data Entry
// Templates and Presentation Templates. A PT must be attached
// to a DET in order for content items to be published (i.e.
// viewable).
det.AttachPresentationTemplate(pt);
det.Store();
return pt;
}
///
/// Creates a content item representing a single support
/// incident.
///
private static IContentItem CreateSupportIncident(IContentFactory factory, IDataEntryTemplate det, IPresentationTemplate pt)
{
//
// Content items (CI) are associated with a single DET/PT
// combination. There can be zero or more content
// items associated with that pair. The DET defines
// the fields in the content items while the PT
// defines how to display them.
//
// Get a CI manager object.
IContentItemManager ciManager = factory.GetContentItemManager();
// Create a new CI.
IContentItem incident = ciManager.CreateContentItem(det.GetContainingFolder(), "Incident Name", det);
// Assign the fields of the CI.
// Each field is defined by the DET corresponding to the CI.
IBaseProperty[] props = det.GetAllProperties();
// Incident ID.
incident.SetIntegerPropertyValue(props[0], 123);
// Resolved?
incident.SetBooleanPropertyValue(props[1], false);
// Severity.
incident.SetDoublePropertyValue(props[2], 0.90 );
// Date incident opened.
incident.SetDatePropertyValue(props[3], DateTime.Now);
// Customer's name
incident.SetTextLinePropertyValue(props[4], "Customer X");
// Link to another content item (CI) representing the customer's data.
// Assumes there was another content item in the same folder named
// with the customer's name. In reality this will return null since
// we never created it.
//IContentItem customer = ciManager.GetContentItem(det.GetContainingFolder(), "Customer X");
//incident.SetItemReferencePropertyValue(props[5], customer);
// Product name containing problem.
// When setting a selection list value, you must have your string exactly
// match one of the values in the selection list.
incident.SetSelectionListPropertyValue(props[6], "Portal");
// Incident description.
incident.SetTextBlockPropertyValue(props[7], "The widget is broken.\nThe widget is fixed in the latest version and the fix must be back ported.");
// Log file.
//Commented out because we don't automatically have a WidgetBroken.log to upload.
//To test this property, change the file name to a valid file on your system and uncomment
//FileStream log = new FileStream("C:\\uploads\\WidgetBroken.log", FileMode.Open);
//incident.SetFilePropertyValue(props[8], "WidgetBroken.log", log);
// Screen shot.
//Commented out because we don't automatically have a WidgetBroken.log to upload.
//To test this property, change the file name to a valid file on your system and uncomment
//FileStream screenShot = new FileStream("C:\\uploads\\WidgetBroken.gif", FileMode.Open);
//incident.SetImagePropertyValue(props[9], "WidgetBroken.gif", screenShot);
// Store the CI.
ciManager.CheckInItem(incident, "Automatically created support incident.");
// Publish the CI.
// This will make it visible to end users. Simply checking in a content
// item is not enough to make it visible.
ciManager.PublishContentItem(incident);
return incident;
}
}
}