is as follows.
package com.ibm.filenet.ps.ciops;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.naming.Context;
import javax.naming.directory.InitialDirContext;
import javax.security.auth.Subject;
import org.apache.commons.io.LineIterator;
import com.asb.ce.utils.AUDITReportConfig;
import com.asb.config.AUDITConfig;
import com.filenet.api.admin.ClassDefinition;
import com.filenet.api.admin.LocalizedString;
import com.filenet.api.admin.PropertyDefinition;
import com.filenet.api.collection.AccessPermissionList;
import com.filenet.api.collection.ChoiceListSet;
import com.filenet.api.collection.ContentElementList;
import com.filenet.api.collection.DocumentSet;
import com.filenet.api.collection.FolderSet;
import com.filenet.api.collection.IndependentObjectSet;
import com.filenet.api.collection.PropertyDefinitionList;
import com.filenet.api.collection.StringList;
import com.filenet.api.collection.VersionableSet;
import com.filenet.api.constants.AutoClassify;
import com.filenet.api.constants.AutoUniqueName;
import com.filenet.api.constants.CheckinType;
import com.filenet.api.constants.ChoiceType;
import com.filenet.api.constants.DefineSecurityParentage;
import com.filenet.api.constants.FilteredPropertyType;
import com.filenet.api.constants.PropertyNames;
import com.filenet.api.constants.RefreshMode;
import com.filenet.api.constants.ReservationType;
import com.filenet.api.constants.TypeID;
import com.filenet.api.constants.VersionStatus;
import com.filenet.api.core.Connection;
import com.filenet.api.core.Document;
import com.filenet.api.core.Domain;
import com.filenet.api.core.EntireNetwork;
import com.filenet.api.core.Factory;
import com.filenet.api.core.Factory.Choice;
import com.filenet.api.core.Factory.ChoiceList;
import com.filenet.api.core.Factory.ContentTransfer;
import com.filenet.api.core.Factory.ReferentialContainmentRelationship;
import com.filenet.api.core.Factory.VersionSeries;
import com.filenet.api.core.Folder;
import com.filenet.api.core.CmTask; //ASB added for Task property retrieval
import com.filenet.api.core.IndependentObject;
import com.filenet.api.core.ObjectStore;
import com.filenet.api.core.UpdatingBatch;
import com.filenet.api.exception.EngineRuntimeException;
import com.filenet.api.exception.ExceptionCode;
import com.filenet.api.property.FilterElement;
import com.filenet.api.property.PropertyFilter;
import com.filenet.api.query.SearchSQL;
import com.filenet.api.query.SearchScope;
import com.filenet.api.util.Id;
import com.ibm.filenet.ps.ciops.database.DatabasePrincipal;
import filenet.vw.api.VWAttachment;
import filenet.vw.api.VWAttachmentType;
import filenet.vw.api.VWException;
import filenet.vw.api.VWLibraryType;
import filenet.vw.api.VWSession;
import filenet.vw.base.logging.Logger;
import java.io.File;
//Q PDF Creation Operations and supporting methods 29th July 2022
import java.io.FileOutputStream;
import java.util.Date;
import java.util.HashMap;
import com.lowagie.text.Anchor;
import com.lowagie.text.BadElementException;
//import com.lowagie.text.BaseColor;
import com.lowagie.text.Chapter;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.Font;
import com.lowagie.text.Image;
import com.lowagie.text.List;
import com.lowagie.text.ListItem;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.Section;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.pdf.RandomAccessFileOrArray;
import com.lowagie.text.pdf.codec.TiffImage;
//
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Vector;
import org.apache.commons.io.FileUtils;
//import org.apache.commons.lang.math.RandomUtils; //ASB removed this import 26-08-2022
//
/**
IBM grants you a non-exclusive copyright license to use all programming code
examples from which you can generate similar function tailored to your own
specific needs.
All sample code is provided by IBM for illustrative purposes only.
These examples have not been thoroughly tested under all conditions. IBM,
therefore cannot guarantee or imply reliability, serviceability, or function of
these programs.
All Programs or code component contained herein are provided to you "AS IS"
without any warranties of any kind.
The implied warranties of non-infringement, merchantability and fitness for a
particular purpose are expressly disclaimed.
© Copyright IBM Corporation 2013, ALL RIGHTS RESERVED.
*/
/**
* Alan S.Bluck 29th July 2022
* Code for QOperations
* Adapted from:
* Custom Java component serving as an example for the article
* "Developing Java components for the Component Integrator".
*
* @author Ricardo Belfor
*
*/
public class QOperations {
private static Logger logger = Logger.getLogger( QOperations.class );
private static final Properties QQidMap = new Properties();
private static final int CardinalityENUM = 1;
private static final int CardinalityLIST = 2;
private static final int CardinalitySINGLE = 0;
//ASB ... Add static types for property type recognition
private static final int BinaryType = 1;
private static final int BoolType = 2;
private static final int DateType = 3;
private static final int DoubleType = 4;
private static final int GUIDType = 5;
private static final int LongType = 6;
private static final int ObjectType = 7;
private static final int StringType = 8;
private static AUDITReportConfig cemc;
private static Connection connection;
private static int processedCount;
private ObjectStore os;
private int maxMin;
private UpdatingBatch ub;
private HashMap classNames;
//PDF Column and Table Section properties
public static String [] ColumnNameT4 = new String[3]; //ASB Array of the Q Table 4 Columns
public static String [] ColumnWidthT4 = new String[3]; //ASB Array of the Q Table 4 Columns
public static String [] TableParams = new String[10]; //ASB Array of the Case task type parameters
//AUDITOR Tab driving arrays
public static String [] TableParams_AUDITOR = new String[10]; //ASB Array of the Case task type parameters
public static String [] TabSECTIONS_AUDITOR = new String[10];
public static String [][] AUDITOR_props = new String[10][50];
//Audit Tab driving arrays
public static String [] TableParams_Audit = new String[10]; //ASB Array of the Case task type parameters
public static String [] TabSECTIONS_Audit = new String[10];
public static String [][] Audit_props = new String[10][50];
//Department Tab driving arrays
public static String [] TableParams_Department = new String[10]; //ASB Array of the Case task type parameters
public static String [] TabSECTIONS_Department = new String[10];
public static String [][] Department_props = new String[10][50];
//PDF Fonts required
private static Font catFont = new Font(Font.TIMES_ROMAN, 18,
Font.BOLD);
private static Font redFont = new Font(Font.TIMES_ROMAN, 12,
Font.NORMAL);
private static Font subFont = new Font(Font.TIMES_ROMAN, 16,
Font.BOLD);
private static Font smallBold = new Font(Font.TIMES_ROMAN, 12,
Font.BOLD);
private static String sTab = "u0009";
public QOperations() {
try {
cemc = new AUDITReportConfig();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} //ASB add our config.xml file methods here!
String fullPath = System.getProperty("user.dir") + File.separator
+ "config" + File.separator + "QQID.properties";
try {
QQidMap.load(new FileInputStream(new File(fullPath)));
return;
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
throw new RuntimeException(fullPath + " cannot load QQid map");
//java.sql.Connection databaseConnection = getDatabaseConnection();
//if ( databaseConnection != null ) {
// logger.debug( databaseConnection.toString() );
//} else {
// logger.debug( "No database connection" );
//}
}
protected Connection getConnection() {
String uri = System.getProperty("filenet.pe.bootstrap.ceuri");
return Factory.Connection.getConnection(uri);
}
protected VWSession getVWSession() throws VWException {
String connectionPoint = System.getProperty("filenet.pe.cm.connectionPoint");
return new VWSession(connectionPoint);
}
protected java.sql.Connection getDatabaseConnection() {
Subject subject = Subject.getSubject( AccessController.getContext() );
Set<DatabasePrincipal> principals = subject.getPrincipals( DatabasePrincipal.class );
if ( principals != null && ! principals.isEmpty() ) {
DatabasePrincipal principal = principals.iterator().next();
return principal.getConnection();
}
return null;
}
private Folder getFolderFromAttachment(VWAttachment folderAttachment) {
ObjectStore objectStore = getObjectStore( folderAttachment.getLibraryName() );
Folder folder = (Folder) objectStore.getObject("Folder", folderAttachment.getId() );
return folder;
}
private Document getDocumentFromAttachment(VWAttachment documentAttachment) {
ObjectStore objectStore = getObjectStore( documentAttachment.getLibraryName() );
Document folder = (Document) objectStore.getObject("Document", documentAttachment.getId() );
return folder;
}
public ObjectStore getObjectStore( String objectStoreName ) {
Connection connection = getConnection();
EntireNetwork entireNetwork = Factory.EntireNetwork.fetchInstance(connection, null);
Domain domain = entireNetwork.get_LocalDomain();
String OSName = cemc.getExportOSName().trim();
//os = Factory.ObjectStore.getInstance( domain, objectStoreName ); //Initial version
os = Factory.ObjectStore.fetchInstance( domain, objectStoreName, null ); //ASB 8th August 2022
return os;
}
/**
* Returns the documents filed in the folder.
*
* @param folderAttachment the input folder.
* @return an array of documents filed in the folder.
* @throws Exception
*/
public VWAttachment[] getFolderDocuments(VWAttachment folderAttachment ) throws Exception {
Folder folder = getFolderFromAttachment(folderAttachment);
DocumentSet containedDocuments = getContainedDocuments(folder);
Iterator<?> iterator = containedDocuments.iterator();
ArrayList<VWAttachment> containedDocumentList = new ArrayList<VWAttachment>();
while ( iterator.hasNext() ) {
com.filenet.api.core.Document document = (com.filenet.api.core.Document) iterator.next();
VWAttachment documentAttachment = getAsVWAttachment(document);
containedDocumentList.add( documentAttachment );
}
return containedDocumentList.toArray( new VWAttachment[0] );
}
private DocumentSet getContainedDocuments(Folder folder) {
PropertyFilter propertyFilter = getContainedDocumentsPropertyFilter();
folder.fetchProperties( propertyFilter );
DocumentSet containedDocuments = folder.get_ContainedDocuments();
return containedDocuments;
}
private PropertyFilter getContainedDocumentsPropertyFilter() {
PropertyFilter propertyFilter = new PropertyFilter();
propertyFilter.addIncludeProperty( new FilterElement( null, null, null, PropertyNames.CONTAINED_DOCUMENTS, null ) );
propertyFilter.addIncludeProperty( new FilterElement( 2, null, null, PropertyNames.ID, null ) );
propertyFilter.addIncludeProperty( new FilterElement( 2, null, null, "DocumentTitle", null ) );
return propertyFilter;
}
private VWAttachment getAsVWAttachment(Document document) throws VWException {
VWAttachment documentAttachment = new VWAttachment();
documentAttachment.setLibraryType( VWLibraryType.LIBRARY_TYPE_CONTENT_ENGINE );
ObjectStore objectStore = document.getObjectStore();
objectStore.fetchProperties( new String[] { PropertyNames.NAME } );
documentAttachment.setLibraryName( objectStore.get_Name() );
document.fetchProperties( new String[] { PropertyNames.ID, PropertyNames.NAME } );
documentAttachment.setId( document.get_Id().toString() );
documentAttachment.setAttachmentName( document.get_Name() );
documentAttachment.setType( VWAttachmentType.ATTACHMENT_TYPE_FOLDER );
return documentAttachment;
}
/**
* Sends an e-mail message using the mail session of the process engine
* session. It uses a document stored in the Content Engine as a template.
* The first content element is considered the main part of the template,
* containing place holders for template values. Template value place
* holders are prefixed in the template with a $-sign.
* <p>
* It may also contain references to images contained in the other content
* elements of the document. The references have the following form:
* <code>cid:contentX</code>, where <code>X</code> stands for the index of
* the content element. So a reference to the first content element after the
* main template will look like <code>cid:content1</code>. This reference
* can be used in an HTML image tag as follows:<br/>
* <code><img src='cid:content1'></code><br/>
* The samples folder contains a example template with a background image
* and an embedded logo.
*
* @param templateAttachment the template document
* @param from
* from address.
* @param to
* to address.
* @param subject
* the subject of the message.
* @param templateNames
* the name of the template variables.
* @param templateValues
* the values of the template variables.
*
* @throws Exception
*/
public void sendMailMessage(VWAttachment templateAttachment, String from, String to, String subject, String[] templateNames, String templateValues[] ) throws Exception {
Document template = getDocumentFromAttachment(templateAttachment);
EmailTemplate emailTemplate = new EmailTemplate(template);
Session session = getVWSession().createMailSession();
MimeMessage message = emailTemplate.getMessage(session, new InternetAddress(from), InternetAddress.parse( to ), subject, templateNames, templateValues );
Transport.send(message);
}
public void writePDFToCaseFolder(String CaseGUID, String TaskGUID, String TaskName, String pdfFileName, String WorkingDirectory, String sQuestions,String sQuestionColumns, String StartQNo, String EndQNo) {
//ASB takes the generated pdf File and imports it to a given Case Folder
try {
// Get Contained Documents in the Case Folder
Folder caseFolder =fetchFolderById( os, CaseGUID);
DocumentSet containedDocuments = getContainedDocuments(caseFolder);
Iterator<?> iterator = containedDocuments.iterator();
String [] docTitles = new String[100]; //TODO set this as a config.xml parameter
com.filenet.api.core.Document [] docList = new com.filenet.api.core.Document[100];
int nDocs = 0;
while ( iterator.hasNext() ) {
com.filenet.api.core.Document document = (com.filenet.api.core.Document) iterator.next();
docTitles[nDocs] = document.get_Name();
docList[nDocs] = document;
nDocs ++;
}
importDocuments(CaseGUID,TaskGUID,TaskName,pdfFileName,WorkingDirectory,docTitles,docList,nDocs);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String generatePDF(String CaseGUID, String TaskGUID, String TaskName, String pdfFileName, String WorkingDirectory, String sQuestions,String sQuestionColumns, String StartQNo, String EndQNo) throws IOException {
// Call the pdf Builder method
int nQuestions = Integer.parseInt(sQuestions);
int questionColumns = Integer.parseInt(sQuestionColumns);
int nStartQNO = Integer.parseInt(StartQNo);
int nEndQNO = Integer.parseInt(EndQNo);
String FileCreated = createPDFFile(CaseGUID, TaskGUID, TaskName, pdfFileName, WorkingDirectory, nQuestions+1,questionColumns,nStartQNO,nEndQNO);
return FileCreated;
}
private String createPDFFile(String CaseGUID, String TaskGUID, String TaskName, String pdfFileName, String WorkingDirectory,int nQuestions,int nQuestionColumns, int nStartQNO,int nEndQNO) throws IOException{
//TODO Detect Linux or Windows environment and set paths accordingly
String MainAUDITORTask =cemc.getAUDITORMainTask();
File fTextFile = new File( pdfFileName);
LineIterator lineIterator = null;
String contentDirectoryName = WorkingDirectory;
//File.separator
String directoryName = contentDirectoryName + File.separator + TaskName + File.separator;
String txtFile = directoryName + pdfFileName;
fTextFile = new File(txtFile);
//Create pdf File from text fileName
String pdfFile = fTextFile.getName().substring(0, fTextFile.getName().lastIndexOf('.') + 1) + "pdf";
//Add the TaskID to give a more unique file name
pdfFile = directoryName + TaskGUID + pdfFile;
// TODO Auto-generated method stub
//Document document = new Document();
com.lowagie.text.Document document = new com.lowagie.text.Document(PageSize.A3.rotate(), 50, 50, 100, 100);
String status = "pdf_create_started";
String sTab = "u0009";
String [][] AUDITOR_propValues;
String [][] AUDITOR_propNames;
String [][] Department_propValues;
String [][] Department_propNames;
String [][] Audit_propValues;
String [][] Audit_propNames;
try {
//Set the PDF parameters required
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(pdfFile));
writer.setPdfVersion(PdfWriter.VERSION_1_3);
//PdfWriter.getInstance(document, new FileOutputStream(pdfFile));
document.open();
//document.add(new Chunk(""));
//TODO Get values from config.xml
document.setMargins(50, 50, 100, 100);
document.addTitle(pdfFileName);
if(TaskName.equalsIgnoreCase(MainAUDITORTask)) { //ASB 22-08-2022 Read from config.xml
document.addSubject("AUDITOR Document");
}else {
document.addSubject("Q Document");
}
document.addKeywords("AUDITOR, Q, Audit, Department");
document.addAuthor("ASB Software Development Limited");
document.addCreator("createPDFFile");
//Retrieve Tabs 1 to 5 Q Case Fields (Audit)
if(TaskName.equalsIgnoreCase(MainAUDITORTask)) {
addAUDITORTitlePage(document);
}else {
addQTitlePage(document);
}
//============P D Q =============================
Integer paramCount = 0;
Integer fieldCount = 0; //set for loading Fields
String fieldVal="";
int nProps = 0;
Integer [] noAUDITORprops = new Integer[10];
//ASB Retrieve the Tab Name parameters from the config.xml
for (String field:TabSECTIONS_AUDITOR){
//ASB Returns NotUsed string for any elements not in the config.xml file
fieldVal = AUDITConfig.getConfigStringValue("config.TabSECTIONS_AUDITOR.T" + String.valueOf(fieldCount), "NotUsed");
if (!fieldVal.equalsIgnoreCase("NotUsed")){
TableParams_AUDITOR = fieldVal.split(",");
TabSECTIONS_AUDITOR[paramCount] = TableParams_AUDITOR[0];
nProps = Integer.parseInt(TableParams_AUDITOR[1]);
noAUDITORprops[paramCount] = nProps;
for (int i = 0; i < nProps; i++) {
AUDITOR_props[paramCount][i] = TableParams_AUDITOR[i+2];
}
paramCount++;
}
fieldCount++;
}
Integer noAUDITORSections = paramCount;
fieldCount = 0;
//===============================================
paramCount = 0;
fieldCount = 0; //set for loading Fields
fieldVal="";
nProps = 0;
Integer [] noAuditprops = new Integer[10];
//ASB Retrieve the Tab Name parameters from the config.xml
for (String field:TabSECTIONS_Audit){
//ASB Returns NotUsed string for any elements not in the config.xml file
fieldVal = AUDITConfig.getConfigStringValue("config.TabSECTIONS_Audit.T" + String.valueOf(fieldCount), "NotUsed");
if (!fieldVal.equalsIgnoreCase("NotUsed")){
TableParams_Audit = fieldVal.split(",");
TabSECTIONS_Audit[paramCount] = TableParams_Audit[0];
nProps = Integer.parseInt(TableParams_Audit[1]);
noAuditprops[paramCount] = nProps;
for (int i = 0; i < nProps; i++) {
Audit_props[paramCount][i] = TableParams_Audit[i+2];
}
paramCount++;
}
fieldCount++;
}
Integer noAuditSections = paramCount;
fieldCount = 0;
//Retrieve Tabs 1 to 5 Q Case Fields (Department)
paramCount = 0;
fieldCount = 0; //set for loading Fields
fieldVal="";
Integer [] noDepartmentprops = new Integer[10];
//ASB Retrieve the Tab Name parameters from the config.xml
for (String field:TabSECTIONS_Department){
//ASB Returns NotUsed string for any elements not in the config.xml file
fieldVal = AUDITConfig.getConfigStringValue("config.TabSECTIONS_Department.T" + String.valueOf(fieldCount), "NotUsed");
if (!fieldVal.equalsIgnoreCase("NotUsed")){
TableParams_Department = fieldVal.split(",");
TabSECTIONS_Department[paramCount] = TableParams_Department[0];
nProps = Integer.parseInt(TableParams_Department[1]);
noDepartmentprops[paramCount] = nProps;
for (int i = 0; i < nProps; i++) {
Department_props[paramCount][i] = TableParams_Department[i+2];
}
paramCount++;
}
fieldCount++;
}
Integer noDepartmentSections = paramCount;
//ASB 15-08-2022 Create tab headers and properties for each section in the pdf
fieldCount = 0;
//Retrieve Tab Q Table parameters and Case Fields
paramCount = 0;
fieldCount = 0; //set for loading Fields
fieldVal="";
float[] columnWidths = {5, 1, 3.2f}; //Defaults for 3 columns
//ASB Retrieve the Column Name parameters from the config.xml
for (String field:ColumnNameT4){
//ASB Returns NotUsed string for any elements not in the config.xml file
fieldVal = AUDITConfig.getConfigStringValue("config.PDFTable4.C" + String.valueOf(fieldCount), "NotUsed");
if (!fieldVal.equalsIgnoreCase("NotUsed")){
TableParams = fieldVal.split(",");
ColumnNameT4[paramCount] = TableParams[0];
ColumnWidthT4[paramCount] = TableParams[1];
columnWidths[paramCount] = Float.parseFloat(ColumnWidthT4[paramCount]);
paramCount++;
}
fieldCount++;
}
fieldCount = 0;
PdfPTable table = new PdfPTable(columnWidths);
try
{ // Get data from the passed Task ID Where CmAcmTaskName = AUD_ProduceFullQ
// From CmAcmCaseTask
SearchSQL sqlObject = new SearchSQL();
sqlObject.setSelectList("f.*");
Integer maxRecords = 10 ;//Should always be just one returned Object anyway!
sqlObject.setFromClauseInitialValue(TaskName, "f", true); //set true to include subclasses
sqlObject.setWhereClause("[Id] = " + TaskGUID ); //ASB 11-08-2022
ObjectStore objectStore = getObjectStore("OS2"); //ASB TODO Change to load from properties
SearchScope search = new SearchScope(objectStore);
PropertyFilter myFilter = new PropertyFilter();
int myFilterLevel = 2; //Changed from 1 to 2 -- For performance !
myFilter.setMaxRecursion(myFilterLevel);
myFilter.addIncludeType(new FilterElement(null, null, null, FilteredPropertyType.ANY, null));
// Set the (Boolean) value for the continuable parameter. This indicates
// whether to iterate requests for subsequent pages of result data when the end of the
// first page of results is reached. If null or false, only a single page of results is
// returned.
Boolean continuable = new Boolean(true); //SET To allow more results to be fetched
// Set the page size (Long) to use for a page of query result data. This value is passed
// in the pageSize parameter. If null, this defaults to the value of
// ServerCacheConfiguration.QueryPageDefaultSize.
Integer myPageSize = new Integer(1000);
// Execute the fetchObjects method using the specified parameters.
//ASB added set myFilter to null REF Best Practice API on FNRCA0024E: API_PROPERTY_NOT_IN_CACHE
IndependentObjectSet myObjects = search.fetchObjects(sqlObject, myPageSize, null, continuable); //ASB myFilter changed to null
//===============================================================S T A R T
// You can then iterate through the collection of rows to access the properties.
String [][] sTableCells = new String[nQuestions +1 ][nQuestionColumns +1]; //Could be max of nQuestion rows in the table
String [] publishYes = new String[nQuestions +1];
String [] questionValue = new String[nQuestions +1];
String [] questionDetails = new String[nQuestions +1];
int rowCount = 0;
Iterator iter = myObjects.iterator();
Paragraph sections = new Paragraph();
while (iter.hasNext()){ //Should be just one Task ID !
try
{
//Folder f = null;
IndependentObject object = (IndependentObject) iter.next();
com.filenet.api.property.Properties props = object.getProperties();
Iterator iterProps = props.iterator();
for (int index = 0; index < nQuestions ; index++)
{
//Initialise to empty
publishYes[index] = "No";
questionDetails[index] ="Not Used";
questionValue[index] ="Not Used";
sTableCells[index][1] = questionValue[index];
sTableCells[index][2] = publishYes[index];
sTableCells[index][3] = questionDetails[index];
}
//============================ S T A R T ================================
// Call Routine to retrieve the Question arrays
CmTask currentTask = (CmTask) object;
String parentTaskClass = "CmTask"; //ASB 11-08-2022
String taskClass = currentTask.getClassName();
//ASB 06-08-2022 Get the Current Case Folder Task Property definitions
com.filenet.api.admin.ClassDefinition tClassDefs = Factory.ClassDefinition.fetchInstance(objectStore,taskClass, null); //update myFilter to null!!! ASB 06/08/2022
PropertyDefinitionList tPropList = tClassDefs.get_PropertyDefinitions();
//ASB Get the Current Task Object properties
//AUDITOR================================
AUDITOR_propValues = new String[noAUDITORSections ][100]; //Could be max of property values in the section
AUDITOR_propNames = new String[noAUDITORSections ][100]; //Could be max of property names in the section
getTaskAUDITORPropsSections(currentTask, taskClass,tClassDefs,tPropList,props,iterProps,AUDITOR_props,TabSECTIONS_AUDITOR,AUDITOR_propValues,AUDITOR_propNames,noAUDITORSections,noAUDITORprops);
//AUDITOR================================
Department_propValues = new String[noDepartmentSections ][20]; //Could be max of property values in the section
Department_propNames = new String[noDepartmentSections ][20]; //Could be max of property names in the section
getTaskDepartmentPropsSections(currentTask, taskClass,tClassDefs,tPropList,props,iterProps,Department_props,TabSECTIONS_Department,Department_propValues,Department_propNames,noDepartmentSections,noDepartmentprops);
Audit_propValues = new String[noAuditSections][20]; //Could be max of property values in the section
Audit_propNames = new String[noAuditSections ][20]; //Could be max of property names in the section
getTaskAuditPropsSections(currentTask, taskClass,tClassDefs,tPropList,props,iterProps,Audit_props,TabSECTIONS_Audit,Audit_propValues,Audit_propNames,noAuditSections,noAuditprops); // 4. Populate the Case level Task Folder properties.
getTaskProps(currentTask, taskClass,tClassDefs,tPropList,props,iterProps,sTableCells, questionValue, publishYes, questionDetails,nQuestions +1,nQuestionColumns);
//=================================== E N D ==============================
//Set Table Column widths (Relative)
//float[] columnWidths = {1, 1, 1, 3, 4};
//float[] columnWidths = {1, 1, 1, 2, 5};
//AUDITOR START OUTPUT TO PDF
for(int iSection=0 ; iSection < noAUDITORSections ; iSection++) {
// We add one empty line
addEmptyLine(sections, 1);
// Lets write a big header
//TODO Pick all text up from the config.xml file
Paragraph paragraph = new Paragraph(TabSECTIONS_AUDITOR[iSection], catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
sections.add(paragraph);
addEmptyLine(sections, 1);
for(int iProp=0 ; iProp < noAUDITORprops[iSection] ; iProp++) {
paragraph = new Paragraph(AUDITOR_propNames[iSection][iProp] + " : " + AUDITOR_propValues[iSection][iProp], catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
sections.add(paragraph);
addEmptyLine(sections, 1);
}
}
document.add(sections);
// Start a new page
document.newPage();
//AUDITOR END OUTPUT TO PDF
//SECTION 0 TO 3 TABS
for(int iSection=0 ; iSection < 4 ; iSection++) {
// We add one empty line
addEmptyLine(sections, 1);
// Lets write a big header
//TODO Pick all text up from the config.xml file
Paragraph paragraph = new Paragraph(TabSECTIONS_Department[iSection], catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
sections.add(paragraph);
addEmptyLine(sections, 1);
for(int iProp=0 ; iProp < noDepartmentprops[iSection] ; iProp++) {
paragraph = new Paragraph(Department_propNames[iSection][iProp] + " : " + Department_propValues[iSection][iProp], catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
sections.add(paragraph);
addEmptyLine(sections, 1);
}
}
document.add(sections);
sections = new Paragraph();
for(int iSection=4 ; iSection < noAuditSections ; iSection++) {
// We add one empty line
addEmptyLine(sections, 1);
// Lets write a big header
//TODO Pick all text up from the config.xml file
Paragraph paragraph = new Paragraph(TabSECTIONS_Department[iSection], catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
sections.add(paragraph);
addEmptyLine(sections, 1);
for(int iProp=0 ; iProp < noDepartmentprops[iSection] ; iProp++) {
paragraph = new Paragraph(Department_propNames[iSection][iProp] + " : " + Department_propValues[iSection][iProp], catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
sections.add(paragraph);
addEmptyLine(sections, 1);
}
}
document.add(sections);
// Start a new page
document.newPage();
//SECTION 4 TAB
table.setWidthPercentage(95);
table.getDefaultCell().setUseAscender(true);
PdfPCell c1 = new PdfPCell(new Phrase(ColumnNameT4[0]));
c1.setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(c1);
PdfPCell c2 = new PdfPCell(new Phrase(ColumnNameT4[1]));
c2.setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(c2);
PdfPCell c3 = new PdfPCell(new Phrase(ColumnNameT4[2]));
c3.setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(c3);
//PdfPCell c4 = new PdfPCell(new Phrase("Description"));
//c4.setHorizontalAlignment(Element.ALIGN_LEFT);
//table.addCell(c4);
//PdfPCell c5 = new PdfPCell(new Phrase("Description"));
//c5.setHorizontalAlignment(Element.ALIGN_LEFT);
//table.addCell(c5);
table.setHeaderRows(1);
//We have all the Questions loaded now
int iCell = 0;
int iRow = 0;
String titleVal = null;
for (String qRow:publishYes) {
//Limit to the passed question number range //ASB 09-08-2022 14:00
if (qRow != null ) {
String [] cellRow = new String[nQuestionColumns];
cellRow[0] = questionValue[iRow+1];
cellRow[1] = publishYes[iRow+1];
cellRow[2] = questionDetails[iRow+1];
if((iRow+1 >= nStartQNO ) && ( iRow+1 <= nEndQNO)) {
for (String sCell:cellRow){
titleVal =sCell;
table.addCell(sCell);
iCell ++;
}
}
}
iCell = 0;
iRow ++;
}
//START
//Audit SECTION 0 TO 9 TABS
for(int iSection=0 ; iSection < noAuditSections ; iSection++) {
// We add one empty line
addEmptyLine(sections, 1);
// Lets write a big header
//TODO Pick all text up from the config.xml file
Paragraph paragraph = new Paragraph(TabSECTIONS_Audit[iSection], catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
sections.add(paragraph);
addEmptyLine(sections, 1);
for(int iProp=0 ; iProp < noAuditprops[iSection] ; iProp++) {
paragraph = new Paragraph(Audit_propNames[iSection][iProp] + " : " + Audit_propValues[iSection][iProp], catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
sections.add(paragraph);
addEmptyLine(sections, 1);
}
}
document.add(sections);
// Start a new page
document.newPage();
//END
}
catch(Exception errprop){
}
// lastGoodPropName = propName;
}
//Add the created table to the PDF Document
document.add(table);
document.close();
//Now delete the Text File created earlier
if(fTextFile.exists()){
fTextFile.delete();
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
status = e.getMessage();
}finally {
status = "processed";
}
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
status = e.getMessage();
} catch (DocumentException e1) {
// TODO Auto-generaed catch block
e1.printStackTrace();
}
return pdfFile;
}
public String SendAlertEmailSSL(String to ,String from, String fromPassword,String host,String Subject, String Body,String SSLPort,String TLSPort )
{
// Uses the SMTP Gateway to send an email notification to the passed user(s)
// Get system properties
Properties properties = System.getProperties();
final String sFrom = from;
final String sFromPassword = fromPassword;
// Setup mail server
properties.setProperty("mail.smtp.host", host);
properties.setProperty("mail.smtp.port", SSLPort); //SSLPort (gmail is 465)
//May need TLS support
properties.put("mail.smtp.starttls.enable","true");
//Need SSL support - mail.smtp.ssl.enable
properties.put("mail.smtp.ssl.enable","true");
properties.put("mail.smtp.auth", "true"); //Authentication is required (At the moment!!)
// Need the following for SSL
properties.put("mail.smtp.socketFactory.port", SSLPort); //SSL Port
properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.put("mail.smtp.socketFactory.fallback", "false");
// Get the default Session object.
Session session = Session.getDefaultInstance(properties,new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(sFrom, sFromPassword);
}
});
// Create a default MimeMessage object.
MimeMessage message = new MimeMessage(session);
// Set From: header field of the header.
message.setFrom(new InternetAddress(sFrom));
// Set To: header field of the header.
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(to));
// Set Subject: header field
message.setSubject(Subject);
// Now set the actual message
message.setText(Body);
Transport t = session.getTransport("smtp");
try {
t.connect(host, sFrom, sFromPassword);
t.sendMessage(message, message.getAllRecipients());
} finally {
t.close();
}
return "Sent message successfully....";
}catch (MessagingException mex) {
return mex.getMessage();
}
}
private void getTaskProps(CmTask object,String taskClass,com.filenet.api.admin.ClassDefinition tClassDefs, PropertyDefinitionList tPropList,com.filenet.api.property.Properties props, Iterator iterProps, String [][] sTableCells, String [] questionValue,String [] publishYes,String [] questionDetails, int nQuestions,int nQuestionColumns)throws Exception {
// private void getTaskProps(Folder currentFolder,Folder f,com.filenet.api.admin.ClassDefinition fClassDefs,Properties props ,Iterator iterProps) throws Exception {
// called as :
// getTaskProps(currentTask, taskClass,tClassDefs,tPropList,props,iterProps,questionValue,publishYes,questionDetails);
// String [][] sTableCells = new String[nQuestions +1 ][nQuestionColumns+1]; //Could be max of nQuestion rows in the table
// String [] publishYes = new String[nQuestions+1];
// String [] questionValue = new String[nQuestions+1];
// String [] questionDetails = new String[nQuestions+1];
//ASB
//Retrieve the current property list to retrieve based on the Task Class definitions from the Object Store
String tClassName = object.getClassName(); //ASB 03-08-2022
com.filenet.api.admin.ClassDefinition classDefs = tClassDefs;
PropertyDefinitionList propList = tPropList;
StringBuffer tempBuf = new StringBuffer();
//Retrieve property names code From writeDocProps to compare
Iterator iter =propList.iterator();
while (iter.hasNext())
{
try {
PropertyDefinition propDef = (PropertyDefinition) iter.next();
String propName = propDef.get_SymbolicName();
//ASB ... 2 011 Need to skip Date Last Accessed etc - ReadOnly error here
// ||propName.equalsIgnoreCase("Permissions") //ASB removed 25/08/2022
if (!(propName.equalsIgnoreCase("Name")
||propName.equalsIgnoreCase("DateCheckedIn")
||propName.equalsIgnoreCase("CurrentState")
||propName.equalsIgnoreCase("PathName")
||propName.equalsIgnoreCase("LockOwner")
||propName.equalsIgnoreCase("Owner") //ASB 28-08-2022
||propName.startsWith("CmAcm") )){
//ASB ... Set to check property cardinality
int CardinalityVal = propDef.get_Cardinality().getValue();
switch (propDef.get_DataType().getValue()){
case StringType:
if (CardinalityVal == CardinalitySINGLE){
String val = object.getProperties().getStringValue(propName);
for (int index = 1; index < nQuestions; index++)
{
// Value for Required Question
String QValue = val ;
if (propName.equalsIgnoreCase("AUD_Report4_QYN_" + index))
{
//Checks if this is set to a required response line
publishYes[index] = QValue;
sTableCells[index][2] = publishYes[index];
}
// Question Value for Required Question Details
if (propName.equalsIgnoreCase("AUD_Report4_QDetails_" + index))
{
questionDetails[index] = QValue;
sTableCells[index][3] = questionDetails[index];
}
// Question Value for Required Question
if (propName.equalsIgnoreCase("AUD_Report4_AUD_" + index))
{
questionValue[index] = QValue;
sTableCells[index][1] = questionValue[index];
}
}
//ASB 11-08-2022
//f.getProperties().putValue(propName, val);
if (propName.equalsIgnoreCase("lastmodifier")){
//f.set_LastModifier(val);
}
if (!propName.equalsIgnoreCase("creator") && !propName.equalsIgnoreCase("lastmodifier")){
//f.getProperties().putValue(propName, val);
}
}else{
//StringList valList = currentFolder.getProperties().getStringListValue(propName);
//f.getProperties().putValue(propName, valList);
}
// Process Multi-value Strings (if required)?
break;
case DateType:
if (CardinalityVal == CardinalitySINGLE){
//Date dateVal = currentFolder.getProperties().getDateTimeValue(propName);
//if (propName.equalsIgnoreCase("datelastmodified")){
// currentFolder.getProperties().removeFromCache("DateLastModified");
// f.set_DateLastModified(dateVal);
}
//ASB ... 4 029 Start
if (propName.equalsIgnoreCase("datecreated")){
//currentFolder.getProperties().removeFromCache("DateCreated");
//f.set_DateCreated(dateVal); //ASB 19-08-2022 Bug fix on Folder Date from dateLast Modified!
//if (lastFolderDateCreated.compareTo(dateVal) < 0) {
// lastFolderDateCreated = dateVal;
//}
}
//ASB ... 4 029 End
if (!propName.equalsIgnoreCase("datecreated") && !propName.equalsIgnoreCase("datelastmodified")){
//f.getProperties().putValue(propName, dateVal);
}
break;
default:
}
}
}catch (Exception writeProp){
logger.error(writeProp.getMessage(), writeProp);
}
} //for (int iProp = 0;iProp < xmlprops.getLength();iProp ++){
}
//========S T A R T C O D E F O R P D F I M P O R T ========
//Main Process loop for the Import Documents process.
//
private void importDocuments(String CaseGUID,String TaskGUID,String TaskName,String pdfFileName,String WorkingDirectory, String[] DocTitles,com.filenet.api.core.Document [] docList, int nDocs) throws Exception {
BufferedWriter auditFileWriter;
Long importStartTime;
Long docImportStartTime;
Long timeToImport;
long maxRunTimeMillis;
// boolean moreDocsToImport=true;
Integer consecutiveErrs=0;
Integer errorCount=0;
this.processedCount = 0;
String LineSave="";
importStartTime = System.currentTimeMillis();
maxRunTimeMillis = cemc.getImportMaxRunTimeMinutes()*60*1000;
Long maxDocCount = new Long(cemc.getImportMaxDocCount());
auditFileWriter = new BufferedWriter(new FileWriter(cemc.getImportAuditFile()));
auditFileWriter.write("Import Start - ");
auditFileWriter.newLine();
auditFileWriter.write("GUID, SOURCEVSID, DESTDOCID, STATE, Millisecs");
auditFileWriter.newLine();
//ub = UpdatingBatch.createUpdatingBatchInstance(os.get_Domain(), RefreshMode.NO_REFRESH);
File pdfFile = new File(pdfFileName);
//get all the files from a directory, based on the config File Filter (default *.pdf)
//File directory = new File(WorkingDirectory); //Set in config.xml
// ArrayList<File> files = new ArrayList<File>();
// this.listf(WorkingDirectory, files,pdfFileName);
// File[] fList = files.toArray(new File[]{});
String documentFile ="";
String documentFileName ="";
String documentFilePath = "";
//for (int i = 0; i < fList.length; i++) {
documentFile = pdfFile.toString();
documentFileName = pdfFile.getName();
for(int idoc=0;idoc < nDocs;idoc++){
if(documentFileName.equalsIgnoreCase(DocTitles[idoc])) {
return; //ASB 14/10/1066
// Change to just ever allow one pdf production as the task is only converted after it is complete
// ie is already immutable!!!
//String mimeType = cemc.getMimeType();
//updateNewDocument(docList[idoc],documentFileName, mimeType, documentFile);
//========END DOCUMENT VERSION PROCESSING==========
//return;
}
}
documentFilePath = pdfFile.getPath();
//ASB ... 022 - Retrieve Date start from config.xml
String sDeltaHours = cemc.getDeltaHours();
String sSearchDate = cemc.getStartSearchDate();
logger.info("Start Search Date : " + sSearchDate);
logger.info("Start Delta Hours : " + sDeltaHours);
//ASB ... 4 002 Now dynamically update the next Loader Date
cemc.updateProcessDate(new Date());
logger.info("File Imported: " + documentFile);
// Integer myPageSize = new Integer(1000);
// Specify a property filter to use for the filter parameter, if needed.
// This can be null if you are not filtering properties.
PropertyFilter myFilter = new PropertyFilter();
int myFilterLevel = 1;
myFilter.setMaxRecursion(myFilterLevel);
//ASB ... 4 020
if(cemc.getDebugOutputFlag().equalsIgnoreCase("off")){
myFilter.addIncludeType(new FilterElement(null, null, null, FilteredPropertyType.ANY_LIST, null));
myFilter.addIncludeType(new FilterElement(null, null, null, FilteredPropertyType.ANY_SINGLETON, null));
}else{
myFilter.addIncludeType(new FilterElement(null, null, null, FilteredPropertyType.ANY, null));
}
//U P D A T E - Iterate through the Directory of input Documents with pdf properties
Id GUID = null;
docImportStartTime = System.currentTimeMillis();
Boolean importFailure = false;
Boolean filedDoc = false;
Document d = null;
String documentTitle = "";
//ASB ... 3 005 - Retrieve Folder list for checks
// - (Only Load documents in config Path)
String [] sDocFolderPath = new String [1000]; //TODO set max document Folders Filed In from config.xml
int folderCount = -1;
String lastGoodPropName = "";
String propName = "";
String propValue = " ";
//Extract the comma separated lines
//String docProps[] = line.split(",");
//String docPropNames[] = new String[docProps.length];
//Integer docPropTypes[] = new Integer[docProps.length];
//Integer docPropCardinality[] = new Integer[docProps.length];
//String docPropFlags[] = new String[docProps.length]; //ASB IBM - Added 2nd October
//for (int j = 0; j < docProps.length; j++) {
//Strip out the double quotes (if present)
// if(docProps[j] != null && docProps[j].length() > 1 && docProps[j].substring(1,2).equalsIgnoreCase(""")){
// docProps[j] = docProps[j].substring(1,docProps[j].length() -1);
// }
// propName = SolutionPrefix + cemc.getPropName(j);
// if(docProps[j]==null || docProps[j].length() == 0){
// docProps[j]=" ";
// }
// propValue = docProps[j].replace("'","");//Remove any single quote values!!
// docPropNames[j]= propName;
// docPropTypes[j]=cemc.getPropType(j);
// docPropCardinality[j]=cemc.getPropCardinality(j);
// docPropFlags[j]=cemc.getPropFlags(j); //ASB IBM - Added 2nd October
//ASB IBM - Added 2nd August - Check if this is a placeholder or a Boolean list property
// if (!docPropFlags[j].equalsIgnoreCase("NONE")){
// docPropFlags[j] = SolutionPrefix + docPropFlags[j];
// }
// try{
// if(cemc.getDebugOutputFlag().equalsIgnoreCase("off")){
// }else{
// logger.info("Property: " + propName );
// logger.info("Value : " + propValue );
// }
// if (propName.equalsIgnoreCase(SolutionPrefix + "FileName"))
// {
// documentTitle = propValue;
// documentFile = propValue;
// }
// sDocFolderPath[1] = cemc.get_DocPathName();
// }catch(Exception errprop){
// logger.info("Document Title :" + documentTitle + " : Property " + propName + " Caused Error : " + errprop.getMessage() + " : Last Good property :" + lastGoodPropName);
// }
// lastGoodPropName = propName;
//}
//E N D -- DEBUG OFF/ON SECTION
documentTitle = documentFileName;
if (documentTitle.equalsIgnoreCase("")) return; //Changed from break
if (!importFailure )
{
docImportStartTime = System.currentTimeMillis();
d = createDocument(documentTitle, auditFileWriter,GUID,documentFile);
Long runTimeMillis = System.currentTimeMillis() - importStartTime;
//Folder the document in the Case Folder
//Get the Case Folder GUID ,String TaskGUID,String TaskName,
String sFolderId = CaseGUID;
Folder caseFolder =fetchFolderById( os, sFolderId);
//Folder caseFolder = getFolderFromID(folderGUID,objectStoreName,CMFolderClass);
if (caseFolder != null){
com.filenet.api.core.ReferentialContainmentRelationship rcr = caseFolder.file(d,AutoUniqueName.NOT_AUTO_UNIQUE,null,DefineSecurityParentage.DO_NOT_DEFINE_SECURITY_PARENTAGE);
rcr.save(RefreshMode.NO_REFRESH);
}
processedCount ++;
//importProcessedDocCount ++;
if (this.processedCount == maxDocCount && maxDocCount>0)
{
completed = true;
logger.info("Processing Completed Max Document Count Reached. ");
}
else if ((runTimeMillis > maxRunTimeMillis)&& maxRunTimeMillis>0 )
{
completed = true;
logger.info("Processing Completed Max Processing Time Reached.");
}
consecutiveErrs=0; // success so initialise the consecutive errs count
}
}
catch (Exception ceme){
}
// }
//}
//ASB 01/12/2020 Need to close Buffered Reader to allow file rename to work
//br.close(); //ASB Close File I/O
// {
//Rename file
//fList[i].renameTo("doc_fact.cvs_" + System.currentTimeMillis());
//File newName = new File(fList[i].getAbsolutePath() + "_" + System.currentTimeMillis() );
//if(fList[i].renameTo(newName)) {
// System.out.println("Renamed " + "doc_fact.csv" + " to " + newName.getName() );
//} else {
// System.out.println("Error");
// }
//}
auditFileWriter.write("Finished - time taken " + (System.currentTimeMillis() - importStartTime) + "milliseconds");
auditFileWriter.newLine();
auditFileWriter.write("Finished - documents processed - " + String.valueOf(processedCount));
auditFileWriter.newLine();
auditFileWriter.write("Finished - documents failed to be processed - " + errorCount.toString());
auditFileWriter.newLine();
//ASB ... 4 031 Add retry count for Content
//auditFileWriter.write("Finished - document total 'Add Content Retry Count' - " + String.valueOf(retryTotalProcessedCount));
auditFileWriter.newLine();
auditFileWriter.close();
//}
}
//ASB 19th November 2020
public void listf(String directoryName, ArrayList<File> files,String filenamePattern) {
File directory = new File(directoryName);
// create new filename
// get all the files from a directory
File[] fList = directory.listFiles();
for (File file : fList) {
if (file.isFile()) {
if(file.toString().endsWith(".pdf")){
files.add(file);
}
} else if (file.isDirectory()) {
listf(file.getAbsolutePath(), files,filenamePattern);
}
}
}
//Creates a com.filenet.api.core.Document object
private Document createDocument(String documentTitle, BufferedWriter auditFileWriter,Id GUID, String documentFile) throws Exception, EngineRuntimeException {
Document d = null;
try
{
Boolean isReserved = false;
String documentclass = cemc.getDocClassName(); //Read the required Class from cemc
Long docImportStartTime;
Long timeToImport;
docImportStartTime = System.currentTimeMillis();
//ASB ... 2 014 Get the Version Numbers of the Document
Integer docMajorVersion = 1;
Integer docMinorVersion = 0;
PropertyFilter myFilter = new PropertyFilter();
int myFilterLevel = 2; //Changed from 4 to 2 -- Set as a parameter
myFilter.setMaxRecursion(myFilterLevel);
myFilter.addIncludeType(new FilterElement(null, null, null, FilteredPropertyType.ANY, null));
try {
docImportStartTime = System.currentTimeMillis();
d = Factory.Document.createInstance(os, documentclass, null);
//Write to audit log
timeToImport = System.currentTimeMillis() - docImportStartTime;
//auditFileWriter.write(d.get_Id().toString() + "," + d.get_VersionSeries().get_Id().toString() + " ,Created," + timeToImport.toString());
//auditFileWriter.newLine();
}catch(Exception e)
{
//If the Exception is this exists then delete and retry add again
logger.error("Error creating the Document: " + documentTitle + "");
}
d.getProperties().putValue("DocumentTitle", documentTitle);
//writeDocProps(d, docPropNames, docPropFlags, docProps, docPropTypes, docPropCardinality,documentTitle );
this.processedCount = this.processedCount +1;
//Write to audit log
timeToImport = System.currentTimeMillis() - docImportStartTime;
//auditFileWriter.write("GUID :" + d.get_Id().toString() + ",Properties Updated," + timeToImport.toString());
//auditFileWriter.newLine();
//ADD CONTENT
int retryCount = 0;
FileInputStream fis = null;
int retryLimit = 5; //TODO Maybe set this as a configuration parameter
while (retryCount < retryLimit){
try {
com.filenet.api.core.ContentTransfer ct = Factory.ContentTransfer.createInstance();
File file = new File(documentFile );
fis = new FileInputStream(file);
InputStream str = fis;
ct.setCaptureSource(str);
// Add Document Title
ct.set_RetrievalName(documentTitle);
// Add Content Mime Type
ct.set_ContentType(cemc.getMimeType());
ContentElementList cel = Factory.ContentElement.createList();
cel.add(ct);
d.set_ContentElements(cel);
break;
}
catch (Exception e){
String testMessage = e.getMessage();
String testCode = e.toString();
if( testMessage.contains("A uniqueness requirement has been violated")){
retryCount = retryLimit;
break;
}
// ASB ... 4 025 Log Exception here
logger.error(e.getMessage(), e);
retryCount ++;
//retryTotalProcessedCount ++;
logger.info("Retry Count - createDocument method : " + retryCount + " of " + retryLimit + " On : " + documentTitle + " : with GUID : " + GUID);
}finally {
}
} //ASB ... 4 031 Above loops Test retryCount less than the retryLimit of 7
//ASB ... 4 028 Change to do not Classify from AutoClassify.AUTO_CLASSIFY, to
d.checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY, CheckinType.MAJOR_VERSION);
d.save(RefreshMode.REFRESH);
return d;
}catch(EngineRuntimeException ere)
{
//ASB ... 2 005
// Create failed. See if it's because the Document exists.
ExceptionCode code = ere.getExceptionCode();
if (code.getErrorId() != ExceptionCode.DB_NOT_UNIQUE.getErrorId() )
{
logger.error("Unexpected Error : " + documentTitle + " Error stack: " + ere.getStackTrace());
throw ere;
}
logger.error("Document already exists: " + documentTitle + "");
//ASB ... 2 006 Delete document in the Target Object Store and Recreate
//this.deleteDoc(GUID.toString());
//ASB ... 2 007 Fetch the Source Object Document to be re-created
PropertyFilter myFilter = new PropertyFilter();
int myFilterLevel = 2; //Changed from 4 to 2 -- Set as a parameter
myFilter.setMaxRecursion(myFilterLevel);
myFilter.addIncludeType(new FilterElement(null, null, null, FilteredPropertyType.ANY, null));
String documentclass = cemc.getDocClassName();
Document dInput = Factory.Document.fetchInstance(os, GUID, myFilter);
//Create Version Series for the document in the Target Object Store
com.filenet.api.core.VersionSeries versions = dInput.get_VersionSeries();
//Get the Document Versions to be added from the Source Document
VersionableSet verSet = versions.get_Versions();
Iterator versIt = verSet.iterator();
int versCount = 0;
int majorVn = 0;
int minorVn = 0;
Document doc = null; //Input Document versions
Id createdGuid = null;
while (versIt.hasNext()){
versCount ++;
doc = (Document)versIt.next();
majorVn = doc.get_MajorVersionNumber();
minorVn = doc.get_MinorVersionNumber();
//if (!isReserved)isReserved = doc.get_IsReserved();
Id nextGUID = doc.get_Id();
createdGuid = d.get_Id();
if (versCount == 1){
FolderSet fs = doc.get_FoldersFiledIn();
Iterator iterFs = fs.iterator();
while (iterFs.hasNext())
{
Folder folder = (Folder)iterFs.next();
//Create/Check and Make link in Target for the Document to this Folder
if(cemc.getDebugOutputFlag().equalsIgnoreCase("off")){
}else{
logger.info("
Folder Name: " + folder.get_FolderName() +
" Folder Path: " + folder.get_PathName());
}
folderDoc(d,folder.get_PathName(),documentTitle);
}
}
}
//ASB ... 2 020 Update Document ACL from source Document security
AccessPermissionList aclIn = dInput.get_Permissions();
// Add the permission to the list for the Object Store.
//Get This group from the config.xml file
// String sExcludeGroup = cemc.getExcludedGroup();
// String sExcludeUser = cemc.getExcludedUser();
//ASB ... 4 027 For Performance check if a full LDAP search is required
// if(cemc.getLDAPSearchFlag().equalsIgnoreCase("on")){
// aclIn = addPermissions(aclIn, sExcludeGroup, sExcludeUser);
// }else {
// aclIn = addPermissionsNoSearch(aclIn, sExcludeGroup, sExcludeUser);
// }
//ASB ... 4 027 aclIn = addPermissions(aclIn, sExcludeGroup, sExcludeUser);
d.set_Permissions(aclIn);
}
return d;
}
private void folderDoc(Document doc, String folderPathName, String documentTitle){
String sContainmentName = documentTitle; //FOR RCR: //ASB 17/02/2011 Add Containment name
if (folderPathName != null && folderPathName.length() > 0){
Folder folder = null;
try {
folder = Factory.Folder.getInstance(os, null, folderPathName);
//folder = Factory.Folder.fetchInstance(os, folderName, null);
com.filenet.api.core.DynamicReferentialContainmentRelationship rcr =
Factory.DynamicReferentialContainmentRelationship.createInstance(os, null,
AutoUniqueName.AUTO_UNIQUE,
DefineSecurityParentage.DO_NOT_DEFINE_SECURITY_PARENTAGE);
rcr.set_Tail(folder);
rcr.set_Head(doc);
rcr.set_ContainmentName(sContainmentName);
rcr.save(RefreshMode.NO_REFRESH);
}
catch (Exception e){
}
}
}
private static Folder fetchFolderById(ObjectStore os, String id)
{
Id id1 = new Id(id);
Folder folderCase = Factory.Folder.fetchInstance(os, id1, null);
return folderCase;
}
//This method returns the count of the number of Document versions
//(Unfortunately java Iterator class does not return size!)
private int countVersions(com.filenet.api.core.VersionSeries versions){
int versionCount=0;
VersionableSet verSet = versions.get_Versions();
Iterator versIt = verSet.iterator();
int versCount = 0;
maxMin = 0;
int min = 0;
Document doc = null; //Input Document versions
while (versIt.hasNext()){
versCount ++;
doc = (Document)versIt.next();
//Record largest minor version value for loop
min = doc.get_MinorVersionNumber();
if (min > maxMin){
maxMin = min;
}
}
versionCount = versCount;
return versionCount;
}
//This method returns the Document versions in ascending order
//(Unfortunately FileNet API iterator returns latest version first! )
private Document[][] getDocumentVersionsArray(com.filenet.api.core.VersionSeries versions, Document [][] docVersions,int maxMin){
int versionCount=0;
VersionableSet verSet = versions.get_Versions();
Iterator versIt = verSet.iterator();
int versCount = 0;
Document doc = null; //Input Document versions
maxMin = 0;
int min=0;
int maj=0;
while (versIt.hasNext()){
versCount ++;
doc = (Document)versIt.next();
maj = doc.get_MajorVersionNumber();
min = doc.get_MinorVersionNumber();
//Record largest minor version value for loop
if (min > maxMin){
maxMin = min;
}
docVersions[maj][min] = doc;
}
versionCount = versCount;
return docVersions;
}
private Document createVersions(String documentTitle, Id GUID, Document object,Boolean isReserved,Document[][] docVersions,Integer majCount,int minCount, BufferedWriter auditFileWriter,com.filenet.api.core.VersionSeries versions)throws Exception{
PropertyFilter myFilter = new PropertyFilter();
int myFilterLevel = 2; //Changed from 4 to 2 -- TODO Set as a parameter
myFilter.setMaxRecursion(myFilterLevel);
myFilter.addIncludeType(new FilterElement(null, null, null, FilteredPropertyType.ANY, null));
Document currentDocument = (Document) object;
String documentclass = currentDocument.getClassName();
Document dInput = Factory.Document.fetchInstance(os, GUID, myFilter);
//Create Version Series for the document in the Target Object Store
//VersionSeries versions = dInput.get_VersionSeries();
//Get the Document Versions to be added from the Source Document
VersionableSet verSet = versions.get_Versions();
Iterator versIt = verSet.iterator();
int versCount = 0;
int majorVn = 0;
int minorVn = 0;
Document doc = null; //Input Document versions
Document d = null; //Output document versions
isReserved = false;
Id createdGuid = null;
Id nextGUID = null;
int foldCount = 0;
//while (versIt.hasNext()){ ASB ... 2
int minVersCount = -1;
while (versCount < majCount){
versCount ++;
while (minVersCount < minCount){
minVersCount ++;
doc = docVersions[versCount][minVersCount];
if(doc == null){
break;
}
foldCount ++;
majorVn = doc.get_MajorVersionNumber();
minorVn = doc.get_MinorVersionNumber();
nextGUID = doc.get_Id();
//ASB ... 4 004 Get the Release Version
VersionStatus dVersionStatus = doc.get_VersionStatus();
if (!isReserved)isReserved = doc.get_IsReserved();
//Need to update for each version in turn
d = createVersion(versCount, d, doc, isReserved, majorVn,minorVn, documentTitle, nextGUID, createdGuid, nextGUID,auditFileWriter);
// try{
//createdGuid = nextGUID;
createdGuid = d.get_Id(); //ASB ... 4 025 Try/Catch Here especially as reservation has no folders!!
// }catch(Exception createdEx){
// logger.info("Version number "+ majorVn + "." + minorVn + " of " + documentTitle + " caused error : " + createdEx.getMessage());
// }
try {
if (foldCount == majCount){
FolderSet fs = doc.get_FoldersFiledIn();
Iterator iterFs = fs.iterator();
while (iterFs.hasNext())
{
Folder folder = (Folder)iterFs.next();
//Create/Check and Make link in Target for the Document to this Folder
if(cemc.getDebugOutputFlag().equalsIgnoreCase("off")){
}else{
logger.info("
Folder Name: " + folder.get_FolderName() +
" Folder Path: " + folder.get_PathName());
}
folderDoc(d,folder.get_PathName(),documentTitle);
}
}
}catch(Exception FileErr){
logger.error(FileErr.getMessage(), FileErr);
}
if (isReserved){
break;
}
}
//ASB ... 4 019 Check at this point if we have reached the completed creation
// If
minVersCount = -1;
} // Next Major Version
if (isReserved)
d = doReservationProperties(versCount, doc, d, isReserved, majorVn,minorVn,documentTitle);
return d;
}
//Called by CreateDocument, creates a version from the information in the XML node specified.
//Creates a new reservation object, specifying properties from XML.
//private Document createVersion(Document d) throws CEMigrateException, Exception {
private Document createVersion(int versCount, Document d, Document dInput, Boolean isReserved, int majorVn, int minorVn,String documentTitle, Id GUID, Id createdGUID, Id nextGUID,BufferedWriter auditFileWriter) throws Exception {
String guid = "";
Long timeToImport = 0l;
Id vGUID =null;
Document res = null;
Long docImportStartTime = System.currentTimeMillis();
PropertyFilter myFilter = new PropertyFilter();
int myFilterLevel = 2; //Changed from 4 to 2 -- For performance!
myFilter.setMaxRecursion(myFilterLevel);
myFilter.addIncludeType(new FilterElement(null, null, null, FilteredPropertyType.ANY, null));
Document currDoc = null;
try
{
int thisMajorVersionNumber = majorVn;
int thisMinorVersionNumber = minorVn; //ASB ... 3 004
String docClass = dInput.getClassName();
//ASB ... 3 006 Now get the current source Doc Version Series ID
Id vId = dInput.get_VersionSeries().get_Id();
if (!isClassExist(docClass))
throw new Exception("Document class " + docClass + " Does not exist");
Id reservationId_null = null; String reservationClass_null = null; // to remind of the parameter types!
boolean isMajorVersion = false;
boolean justCreated = true;
if (d == null){
if (thisMajorVersionNumber > 0)
isMajorVersion = true;
if (thisMinorVersionNumber > 0)
isMajorVersion = false;
//ASB ... 2 015 Added GUID to ensure we get the same later
//ASB ... 3 006 New Version of the first document create to store Version series ID
//ASB ... 3 006 Many thanks to David Greenhouse for supplying the call :-)
res = Factory.Document.createInstance(os, docClass, GUID, vId, com.filenet.api.constants.ReservationType.EXCLUSIVE);
//res = (Document)os.createObject(docClass,GUID); //ASB ... 3 006 Removed Old Creation
//Added this to ensure that these values were correctly set on the initial version
String mimetype = dInput.get_MimeType();
String filename = dInput.get_Name();
Date dateCreated = dInput.get_DateCreated();
res.set_MimeType(mimetype);
res.set_DateCreated(dateCreated); //ASB ... 4 029
//ASB 04/04/2011 - Update Creator and last Modifier and dates
String sCreator = dInput.get_Creator();
res.set_Creator(sCreator); //ASB 04/04/2011
String sLastModifier = dInput.get_LastModifier();
res.set_LastModifier(sLastModifier); //ASB 04/04/2011
Date dateLastModified = dInput.get_DateLastModified();
res.set_DateLastModified(dateLastModified); //ASB 04/04/2011
currDoc = dInput;
com.filenet.api.property.Properties docprops = Factory.Document.createInstance(os, null).getProperties(); //????
com.filenet.api.property.Properties props = res.getProperties();
Iterator iterProps = props.iterator();
writeSpecialDocProps(res, iterProps, justCreated, documentTitle, currDoc);
//ASB ... 4 023 Add Count for first version
this.processedCount = this.processedCount +1;
guid = GUID.toString().trim();
//Write to audit log
timeToImport = System.currentTimeMillis() - docImportStartTime;
auditFileWriter.write(guid + "," + vId.toString() + "," + guid + ",Imported," + timeToImport.toString());
auditFileWriter.newLine();
}
else {
justCreated = false;
//GUID here should be from next iteration set above
//ASB ... 2 016 Changed to osinput from os! try nextGUID
//currDoc = (Document)os.fetchObject("Document", createdGUID, myFilter);
//ASB ... 4 024 Update to support other Document Types
currDoc = (Document)os.fetchObject(docClass, createdGUID, myFilter);
com.filenet.api.property.Properties props = Factory.Document.createInstance(os, null).getProperties();
String sCreator = currDoc.get_Creator();
Date dateCreated = currDoc.get_DateCreated();
String sLastModifier = currDoc.get_LastModifier();
Date dateLastModified = currDoc.get_DateLastModified();
// This collection is used when we do the checkout
props.putValue("Creator", sCreator);
props.putValue("DateCreated", dateCreated);
props.putValue("LastModifier", sLastModifier);
props.putValue("DateLastModified", dateLastModified);
//ASB ... 4 024
//d = (Document)os.fetchObject(docClass, createdGUID, myFilter);
d = currDoc; //No need to fetch again!
//d = (Document)os.fetchObject("Document", createdGUID, myFilter);
//ASB ... 4 014 New Version needs to use the GUID passed in !!
String sNewGuid = GUID.toString();
// ASB Compare : d.checkout(ReservationType.EXCLUSIVE, GUID, docClass, null);
d.checkout(ReservationType.EXCLUSIVE, GUID, docClass, props); //ASB ... 4 029 Changed from null to props
//d.set_DateCreated(dateCreated); //ASB004 029 READONLY AT THIS POINT!!
d.save(RefreshMode.REFRESH);
this.processedCount = this.processedCount +1;
guid = GUID.toString().trim();
//Write to audit log
timeToImport = System.currentTimeMillis() - docImportStartTime;
auditFileWriter.write(guid + "," + d.get_VersionSeries().get_Id().toString() + "," + d.get_Id().toString() + ",Imported," + timeToImport.toString());
auditFileWriter.newLine();
// Get the reservation object
res = (Document)d.get_Reservation();
res.set_LastModifier(sLastModifier); //ASB00 4
res.set_DateLastModified(dateLastModified); //ASB00 4 Uodate from dateCreated ??!!
//res.set_DateCreated(dateCreated); //ASB004 029 READ ONLY AT THIS POINT!!!
String mimetype = currDoc.get_MimeType();
props.putValue("MimeType", mimetype);
int mvn = majorVn;
int minvn = minorVn;
if (thisMajorVersionNumber > 0) isMajorVersion = true;
if (thisMinorVersionNumber > 0) isMajorVersion = false;
dInput = currDoc;
GUID = nextGUID; //Get Current Content from version
}
try {
addContent(dInput, res, documentTitle, myFilter, GUID,docClass);
}
catch (Exception e){
//ASB ... 4 Check if the Content could not be added because the document already exists, if so
// Remove document and retry (next run)
// ASB ... 4 025 Log Exception here
logger.error(e.getMessage(), e);
}
if(isReserved){ //ASB ... 2 012 Required For Checkin the Document must be Status of reserved!!
if (isMajorVersion){
//ASB ... 4 028 Changed from NULL to AutoClassify.DO_NOT_AUTO_CLASSIFY
res.checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY,CheckinType.MAJOR_VERSION);
res.save(RefreshMode.NO_REFRESH);
}
else {
res.checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY,CheckinType.MINOR_VERSION);
res.save(RefreshMode.NO_REFRESH);
}
}
}
catch (Exception e)
{
e.printStackTrace();
//TODO If caused by VSID issue attempt Delete Here
logger.error(e.getMessage(), e);
throw e;
}
return res;
}
private void addContent(Document dSource, Document d, String documentTitle, PropertyFilter myFilterId, Id GUID, String DocClass) throws Exception {
//ADD CONTENT NEW CODE HERE
//ASB ... 4 024
int retryCount = 0;
Document currDoc = null;
//while (retryCount < retryLimit){
try {
currDoc = (Document)os.fetchObject(DocClass, GUID, myFilterId);
//Add substituteDoc above to get Content Stream
//Document currDoc = (Document)osinput.fetchObject("Document", GUID, myFilterId);
com.filenet.api.core.ContentTransfer ct = Factory.ContentTransfer.createInstance();
String dClassName = currDoc.getClassName();
String dMimeType = currDoc.get_MimeType();
String dContentSize = currDoc.get_ContentSize().toString();
String dGUID = currDoc.get_Id().toString();
InputStream str = currDoc.accessContentStream(0);
ct.setCaptureSource(str);
// Add Document Title
ct.set_RetrievalName(documentTitle);
// Add Content Mime Type
ct.set_ContentType(currDoc.get_MimeType());
ContentElementList cel = Factory.ContentElement.createList();
cel.add(ct);
d.set_ContentElements(cel);
//break;
}
catch (Exception e){
String testMessage = e.getMessage();
String testCode = e.toString();
if( testMessage.contains("A uniqueness requirement has been violated")){
//retryCount = retryLimit;
return;
}
//ASB ... 4 Check if the Content could not be added because the document already exists, if so
// Remove document and retry (next run)
// ASB ... 4 025 Log Exception here
logger.error(e.getMessage(), e);
retryCount ++;
//retryTotalProcessedCount ++;
//logger.info("Retry Count - createVersion method : " + retryCount + " of " + retryLimit + " On : " + documentTitle + " : with GUID : " + GUID);
}
//} //ASB ... 4 031 Above loops Test retryCount less than the retryLimit of 7
//ASB ... 2 020 Update Document ACL from source Document security
AccessPermissionList aclIn = null;
aclIn = currDoc.get_Permissions();
d.set_Permissions(aclIn);
Boolean isMajorVersion = false;
if(currDoc.get_MinorVersionNumber() == 0) isMajorVersion = true;
//ASB ... 4 028 Change to do not Classify from AutoClassify.AUTO_CLASSIFY, to
if (isMajorVersion){
d.checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY,CheckinType.MAJOR_VERSION);
}
else {
d.checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY,CheckinType.MINOR_VERSION);
}
//d.checkin(AutoClassify.AUTO_CLASSIFY, CheckinType.MAJOR_VERSION);
//ASB ... 4 25 Try/Catch here ?
Date dateLastModified = dSource.get_DateLastModified();
//Date dateCreated = dSource.get_DateCreated(); //ASB ... 4 029
String sModifier = dSource.get_LastModifier();
Date dateCheckedIn = dSource.get_DateCheckedIn();
// Update Checkin Date etc from Source here
//d.set_DateCreated(dateCreated); //ASB ... 4 029 READONLY AT THIS POINT!!
d.set_DateLastModified(dateLastModified);
d.set_LastModifier(sModifier);
d.set_DateCheckedIn(dateCheckedIn); //ASB ... 2 005
d.save(RefreshMode.REFRESH); //ASB Only save if Not in Bulk mode 21-08-2022
}
//Adds properties such as LastModifier to the document properties.
//Called by doReservationProperties, createVersion
private void writeSpecialDocProps(Document d,Iterator iterProps, Boolean justCreated, String documentTitle, Document dInput) throws Exception {
//ASB ... 2 008 Updated for new property definition objects
//Retrieve the current property list to retrieve based on the Document Class definitions from the Object Store
String dClassName = d.getClassName();
com.filenet.api.admin.ClassDefinition classDefs = Factory.ClassDefinition.fetchInstance(os,dClassName, null);
PropertyDefinitionList propList = classDefs.get_PropertyDefinitions();
StringBuffer tempBuf = new StringBuffer();
//Retrieve property names
Iterator iter = propList.iterator();
while (iter.hasNext())
{
//ASB ... 4 025 Catch any property exceptions here
try{
PropertyDefinition propDef = (PropertyDefinition) iter.next();
String propName = propDef.get_SymbolicName();
//ASB ... 2 011 Need to skip Date Last Accessed etc - ReadOnly error here
if (!(propName.equalsIgnoreCase("DateContentLastAccessed")
||propName.equalsIgnoreCase("LockOwner")
||propName.equalsIgnoreCase("Name")
||propName.equalsIgnoreCase("StorageLocation")
||propName.equalsIgnoreCase("ContentElementsPresent")
||propName.equalsIgnoreCase("DateCheckedIn")
||propName.equalsIgnoreCase("ContentRetentionDate")
||propName.equalsIgnoreCase("CurrentState")
||propName.equalsIgnoreCase("CmThumbnails"))){ //ASB 21-08-2022
//ASB ... 2 011 Set to check cardinality
int CardinalityVal = propDef.get_Cardinality().getValue();
switch (propDef.get_DataType().getValue()){
case StringType:
if (CardinalityVal == CardinalitySINGLE){
String val = dInput.getProperties().getStringValue(propName);
d.getProperties().putValue(propName, val);
if (propName.equalsIgnoreCase("lastmodifier")){
d.set_LastModifier(val);
}
if (!propName.equalsIgnoreCase("creator") && !propName.equalsIgnoreCase("lastmodifier")){
d.getProperties().putValue(propName, val);
}
}else{
//List
StringList valList = dInput.getProperties().getStringListValue(propName);
d.getProperties().putValue(propName, valList);
}
break;
case DateType:
if (CardinalityVal == CardinalitySINGLE){
Date dateVal = dInput.getProperties().getDateTimeValue(propName);
if (propName.equalsIgnoreCase("datelastmodified")){
if (!justCreated){
dInput.getProperties().removeFromCache("DateLastModified");
}
d.set_DateLastModified(dateVal);
}
if (!propName.equalsIgnoreCase("datecreated") && !propName.equalsIgnoreCase("datelastmodified")){
d.getProperties().putValue(propName, dateVal);
}
}
//TODO Process Multi-value Dates (if exists)?
break;
default:
}catch(Exception writeProp){
logger.error(writeProp.getMessage(), writeProp);
}
}
//ASB ... 2 020 Update Document ACL from source Document security
AccessPermissionList aclIn = null;
aclIn = dInput.get_Permissions();
d.set_Permissions(aclIn);
}
//Sets the properties on the reservation object for docs that were checked out on the source system.
//Sets properties but no content. No need to set mime type here - causes problems.
//private Document doReservationProperties(Node verNode, Document d) throws Exception {
private Document doReservationProperties(int versCount, Document dInput, Document d, Boolean isReserved, int majorVn,int minorVn, String documentTitle ) throws Exception{
com.filenet.api.property.Properties props = Factory.Document.createInstance(os, null).getProperties();
String sCreator = dInput.get_Creator();
Date dateCreated = dInput.get_DateCreated();
String sLastModifier = dInput.get_LastModifier();
Date dateLastModified = dInput.get_DateLastModified();
// This collection is used when we do the checkout
props.putValue("Creator", sCreator);
props.putValue("DateCreated", dateCreated);
props.putValue("LastModifier", sLastModifier);
props.putValue("DateLastModified", dateLastModified);
Date dateCheckedIn = dInput.get_DateCheckedIn();
//Update Checkin Date etc from Source here
d.set_LastModifier(sCreator);
d.set_DateLastModified(dateCreated);
d.set_DateCreated(dateCreated); //ASB ... 4 029
Id reservationId_null = null;
String reservationClass_null = null; // to remind of the parameter types!
try
{
// Get Document properties
com.filenet.api.property.Properties docProps = d.getProperties();
Iterator iterProps = props.iterator();
Boolean justCreated = false;
writeSpecialDocProps(d, iterProps, justCreated,documentTitle, dInput);
}
catch (Exception e){
throw new Exception(e.getMessage(), e);
}
d.set_LastModifier(sLastModifier);
// ASB Compare : d.checkout(ReservationType.EXCLUSIVE, GUID, docClass, null);
d.checkout(ReservationType.OBJECT_STORE_DEFAULT, reservationId_null, reservationClass_null, props);
d.set_DateLastModified(dateLastModified);
d.set_DateCreated(dateCreated); //ASB ... 4 029
d.set_LastModifier(sLastModifier);
d.save(RefreshMode.REFRESH);
return d;
}
private boolean isClassExist(String className) throws Exception {
if (classNames.containsKey(className))
return true;
try {
com.filenet.api.admin.ClassDefinition test = Factory.ClassDefinition.fetchInstance(os, className, null);
classNames.put(test.get_Name(), test.get_Name());
return true;
}
catch (EngineRuntimeException e){
if (e.getExceptionCode() == ExceptionCode.E_BAD_CLASSID)
return false;
throw e;
}
}
private void updateNewDocument(Document doc,String docTitle, String mimeType, String FileName) {
// REF
// Page 92-93 of http://www.redbooks.ibm.com/redbooks/pdfs/sg247743.pdf
//
// Get the document (saving a round-trip that a fetch would require)
//Document doc = Factory.Document.getInstance(os,"Document","/Doc1");
// Checkout the document and save
doc.checkout(ReservationType.EXCLUSIVE, null, null, null);
doc.save(RefreshMode.REFRESH);
// Get the reservation object
Document res = (Document)doc.get_Reservation();
// Update the properties
res.getProperties().putValue("DocumentTitle",docTitle);
// Prepare the content for attaching
// Create the element list
ContentElementList list = Factory.ContentElement.createList();
// Create a content transfer element by attaching a simple text file
com.filenet.api.core.ContentTransfer element = Factory.ContentTransfer.createInstance();
// Set the MIME type
element.set_ContentType(mimeType);
// Set the retrieval name
element.set_RetrievalName(FileName);
// Set the content source
try {
element.setCaptureSource(new FileInputStream(new File(FileName)));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Add the item to the list
list.add(element);
// Add the content transfer list to the document
res.set_ContentElements(list);
// Set the PendingAction to be check-in as a major version without
// automatic content classification
res.checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY,
CheckinType.MAJOR_VERSION);
// Save the document to the repository
res.save(RefreshMode.NO_REFRESH);
}
private static void addQTitlePage( com.lowagie.text.Document document)
throws DocumentException, IOException {
// Add the Audit Master Logo
// Creating an ImageData object
String imageLogoFile = "/opt/AuditReport/images/AuditMasterLogo.tif"; //TODO add to config.xml file
RandomAccessFileOrArray ra = new RandomAccessFileOrArray(imageLogoFile);
int pages = TiffImage.getNumberOfPages(ra);
// Creating an Image object
Image image;
image = TiffImage.getTiffImage(ra, 1);
// Adding the Audit Master Logo image to the Audit report document
Rectangle pageSize = new Rectangle(image.getWidth(),
image.getHeight());
document.setPageSize(pageSize);
document.add(image);
// Start a new page
document.newPage();
Paragraph preface = new Paragraph();
// We add one empty line
addEmptyLine(preface, 1);
// Lets write a big header
//TODO Pick all text up from the config.xml file
Paragraph paragraph = new Paragraph("Audit Master - Audit Report", catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
preface.add(paragraph);
addEmptyLine(preface, 1);
// Lets write another big header
//TODO Pick all text up from the config.xml file
paragraph = new Paragraph("ASB Software Development Limited", catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
preface.add(paragraph);
addEmptyLine(preface, 1);
// Lets write another big header
//TODO Pick all text up from the config.xml file
paragraph = new Paragraph(sTab+ "Department Audit Process Task", catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
preface.add(paragraph);
// Lets write another big header
//TODO Pick all text up from the config.xml file
paragraph = new Paragraph(sTab+ "ISO9000/BS5750", catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
preface.add(paragraph);
addEmptyLine(preface, 1);
// Will create: Report generated by: _name, _date
preface.add(new Paragraph(sTab+ "Report generated by: " + System.getProperty("user.name") + ", " + new Date(), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
smallBold));
addEmptyLine(preface, 3);
paragraph = new Paragraph(sTab+ "Note: This is an automatically generated Audit Report, the full Audit results and conclusions are produced following the run of the review tasks. ",
smallBold);
paragraph.setAlignment(Element.ALIGN_LEFT);
paragraph.setIndentationLeft(50);
addEmptyLine(preface, 8);
addEmptyLine(preface, 8);
paragraph = new Paragraph(sTab+ "Once you have completed the initial Department Audit, you should have:
" +
"
" + sTab +
"• Arranged a non-conformance review and a follow-up audit and questions.
" +
"
" + sTab +
"• Allowed the Department sufficient time to correct the non-conformances and
" +
"
" + sTab+
"• Generated the evidence for the required changes to their procedures.
" +
"",
redFont);
paragraph.setAlignment(Element.ALIGN_LEFT);
paragraph.setIndentationLeft(50);
document.add(preface);
// Start a new page
document.newPage();
}
private static void addEmptyLine(Paragraph paragraph, int number) {
for (int i = 0; i < number; i++) {
paragraph.add(new Paragraph(" "));
}
}
private static void getTaskDepartmentPropsSections(CmTask object,String taskClass,com.filenet.api.admin.ClassDefinition tClassDefs, PropertyDefinitionList tPropList,com.filenet.api.property.Properties props, Iterator iterProps, String [][] Departmentprops, String [] TabSECTIONS_Department, String [][] Department_propValues,String [][] Department_propNames,Integer noDepartmentSections, Integer [] noDepartmentprops)throws Exception {
// called as :
// getTaskDepartmentPropsSections(currentTask, taskClass,tClassDefs,tPropList,props,iterProps,Department_props,TabSECTIONS_Department,Department_propValues,noDepartmentSections,noDepartmentprops);
// String [][] Department_props paramCount is the section number, 0-6 i is the noDepartmentprops[paramCount] contains the symbolic property name
// TabSECTIONS_Department[] // has noDepartmentSections
// Integer noDepartmentSections The number of sections to process 0-3
//ASB
//Retrieve the current property list to retrieve based on the Task Class definitions from the Object Store
String tClassName = object.getClassName(); //ASB 15-08-2022
com.filenet.api.admin.ClassDefinition classDefs = tClassDefs;
PropertyDefinitionList propList = tPropList;
StringBuffer tempBuf = new StringBuffer();
//Retrieve property names code From writeDocProps to compare
Iterator iter =propList.iterator();
while (iter.hasNext()){
try {
PropertyDefinition propDef = (PropertyDefinition) iter.next();
String propName = propDef.get_SymbolicName();
String propDisplayName = propDef.get_DisplayName();
//ASB ... 2 011 Need to skip Date Last Accessed etc - ReadOnly error here
if (!(propName.equalsIgnoreCase("Name")
||propName.equalsIgnoreCase("DateCheckedIn")
||propName.equalsIgnoreCase("CurrentState")
||propName.equalsIgnoreCase("PathName")
||propName.equalsIgnoreCase("LockOwner")
||propName.equalsIgnoreCase("Owner") //ASB 15-08-2022
||propName.startsWith("CmAcm") )){
//ASB ... Set to check property cardinality
int CardinalityVal = propDef.get_Cardinality().getValue();
int propIndex;
//===============START
switch (propDef.get_DataType().getValue()){
case StringType:
if (CardinalityVal == CardinalitySINGLE){
String val = object.getProperties().getStringValue(propName);
for (int sectionIndex = 0; sectionIndex < noDepartmentSections; sectionIndex++) {
for (propIndex = 0; propIndex < noDepartmentprops[sectionIndex]; propIndex++) { //Department_propValues
// Value for Required response
String propValue = val;
String propTest = Departmentprops[sectionIndex][propIndex];
if (propName.equalsIgnoreCase(propTest)){
Department_propValues[sectionIndex][propIndex] =propValue;
Department_propNames[sectionIndex][propIndex] = propDisplayName;
}
}
}
//ASB 15-08-2022
}else{
StringList valList = object.getProperties().getStringListValue(propName);
//Iterator itList = valList.iterator();
//String valLists = " ";
//while (itList.hasNext()){
// valLists = valLists +"
" + sTab + itList.toString();
//}
for (int sectionIndex = 0; sectionIndex < noDepartmentSections; sectionIndex++){
for (propIndex = 0; propIndex < noDepartmentprops[sectionIndex]; propIndex++) { //Department_propValues
// Value for Required response
if (propName.equalsIgnoreCase(Department_props[sectionIndex][propIndex])){
// Iterate through the list of values
StringBuffer sb = new StringBuffer();
for( Iterator i = valList.iterator(); i.hasNext(); )
{
// Get the value and cast to an Id property type
String propertyVal = (String)i.next();
sb.append(propertyVal + "
");
}
Department_propValues[sectionIndex][propIndex] =sb.toString();
Department_propNames[sectionIndex][propIndex] = propDisplayName;
}
}
}
}
// Process Multi-value Strings (if required)?
break;
case DateType:
if (CardinalityVal == CardinalitySINGLE){
Date dateVal = object.getProperties().getDateTimeValue(propName);
for (int sectionIndex = 0; sectionIndex < noDepartmentSections; sectionIndex++){
for (propIndex = 0; propIndex < noDepartmentprops[sectionIndex]; propIndex++){ //Department_propValues
// Value for Required response
if (propName.equalsIgnoreCase(Departmentprops[sectionIndex][propIndex])){
if(dateVal != null) {
Department_propValues[sectionIndex][propIndex] =dateVal.toString();
Department_propNames[sectionIndex][propIndex] = propDisplayName;
}
}
}
}
}else{
//
}
break;
default:
}
//===============END
}
}catch (Exception writeProp){
logger.error(writeProp.getMessage(), writeProp);
}
}
}
private static void getTaskAuditPropsSections(CmTask object,String taskClass,com.filenet.api.admin.ClassDefinition tClassDefs, PropertyDefinitionList tPropList,com.filenet.api.property.Properties props, Iterator iterProps, String [][] Auditprops, String [] TabSECTIONS_Audit, String [][] Audit_propValues,String [][] Audit_propNames, Integer noAuditSections, Integer [] noAuditprops)throws Exception {
// called as :
// getTaskAuditPropsSections(currentTask, taskClass,tClassDefs,tPropList,props,iterProps,Audit_props,TabSECTIONS_Audit,Audit_propValues,noAuditSections,noAuditprops);
// String [][] Audit_props paramCount is the section number, 0-6 i is the noAuditprops[paramCount] contains the symbolic property name
// TabSECTIONS_Audit[] // has noAuditSections
// Integer noAuditSections The number of sections to process 0-3
//ASB
//Retrieve the current property list to retrieve based on the Task Class definitions from the Object Store
String tClassName = object.getClassName(); //ASB 15-08-2022
com.filenet.api.admin.ClassDefinition classDefs = tClassDefs;
PropertyDefinitionList propList = tPropList;
StringBuffer tempBuf = new StringBuffer();
//Retrieve property names code From writeDocProps to compare
Iterator iter =propList.iterator();
while (iter.hasNext()){
try {
PropertyDefinition propDef = (PropertyDefinition) iter.next();
String propName = propDef.get_SymbolicName();
String propDisplayName = propDef.get_DisplayName();
//ASB ... 2 011 Need to skip Date Last Accessed etc - ReadOnly error here
if (!(propName.equalsIgnoreCase("Name")
||propName.equalsIgnoreCase("DateCheckedIn")
||propName.equalsIgnoreCase("CurrentState")
||propName.equalsIgnoreCase("PathName")
||propName.equalsIgnoreCase("LockOwner")
||propName.equalsIgnoreCase("Owner") //ASB 15-08-2022
||propName.startsWith("CmAcm") )){
//ASB ... Set to check property cardinality
int CardinalityVal = propDef.get_Cardinality().getValue();
int propIndex;
//===============START
switch (propDef.get_DataType().getValue()){
case StringType:
if (CardinalityVal == CardinalitySINGLE){
String val = object.getProperties().getStringValue(propName);
for (int sectionIndex = 0; sectionIndex < noAuditSections; sectionIndex++) {
for (propIndex = 0; propIndex < noAuditprops[sectionIndex]; propIndex++) { //Audit_propValues
// Value for Required response
String propValue = val;
String propTest = Auditprops[sectionIndex][propIndex];
if (propName.equalsIgnoreCase(propTest)){
Audit_propValues[sectionIndex][propIndex] =propValue;
Audit_propNames[sectionIndex][propIndex] = propDisplayName;
}
}
}
//ASB 15-08-2022
}else{
StringList valList = object.getProperties().getStringListValue(propName);
// Get a multi-value String property
//Iterator itList = valList.iterator();
//String valLists = " ";
//while (itList.hasNext()){
// valLists = valLists +"
" + sTab + itList.toString();
// }
for (int sectionIndex = 0; sectionIndex < noAuditSections; sectionIndex++){
for (propIndex = 0; propIndex < noAuditprops[sectionIndex]; propIndex++) { //Audit_propValues
// Value for Required response
if (propName.equalsIgnoreCase(Audit_props[sectionIndex][propIndex])){
// Iterate through the list of values
StringBuffer sb = new StringBuffer();
for( Iterator i = valList.iterator(); i.hasNext(); )
{
// Get the value and cast to an Id property type
String propertyVal = (String)i.next();
sb.append(propertyVal + "
");
}
Audit_propValues[sectionIndex][propIndex] =sb.toString();
Audit_propNames[sectionIndex][propIndex] = propDisplayName;
}
}
}
}
// Process Multi-value Strings (if required)?
break;
case DateType:
if (CardinalityVal == CardinalitySINGLE){
Date dateVal = object.getProperties().getDateTimeValue(propName);
for (int sectionIndex = 0; sectionIndex < noAuditSections; sectionIndex++){
for (propIndex = 0; propIndex < noAuditprops[sectionIndex]; propIndex++){ //Audit_propValues
// Value for Required response
if (propName.equalsIgnoreCase(Auditprops[sectionIndex][propIndex])){
if(dateVal != null) {
Audit_propValues[sectionIndex][propIndex] =dateVal.toString();
Audit_propNames[sectionIndex][propIndex] = propDisplayName;
}
}
}
}
}else{
//
}
break;
default:
}
//===============END
}
}catch (Exception writeProp){
logger.error(writeProp.getMessage(), writeProp);
}
}
}
private static void getTaskAUDITORPropsSections(CmTask object,String taskClass,com.filenet.api.admin.ClassDefinition tClassDefs, PropertyDefinitionList tPropList,com.filenet.api.property.Properties props, Iterator iterProps, String [][] AUDITORprops, String [] TabSECTIONS_AUDITOR, String [][] AUDITOR_propValues,String [][] AUDITOR_propNames,Integer noAUDITORSections, Integer [] noAUDITORprops)throws Exception {
// called as :
// getTaskAUDITORPropsSections(currentTask, taskClass,tClassDefs,tPropList,props,iterProps,AUDITOR_props,TabSECTIONS_AUDITOR,AUDITOR_propValues,noAUDITORSections,noAUDITORprops);
// String [][] AUDITOR_props paramCount is the section number, 0-6 i is the noAUDITORprops[paramCount] contains the symbolic property name
// TabSECTIONS_AUDITOR[] // has noAUDITORSections
// Integer noAUDITORSections The number of sections to process 0-3
//ASB
//Retrieve the current property list to retrieve based on the Task Class definitions from the Object Store
String tClassName = object.getClassName(); //ASB 15-08-2022
com.filenet.api.admin.ClassDefinition classDefs = tClassDefs;
PropertyDefinitionList propList = tPropList;
StringBuffer tempBuf = new StringBuffer();
//Retrieve property names code From writeDocProps to compare
Iterator iter =propList.iterator();
while (iter.hasNext()){
try {
PropertyDefinition propDef = (PropertyDefinition) iter.next();
String propName = propDef.get_SymbolicName();
String propDisplayName = propDef.get_DisplayName();
//ASB ... 2 011 Need to skip Date Last Accessed etc - ReadOnly error here
if (!(propName.equalsIgnoreCase("Name")
||propName.equalsIgnoreCase("DateCheckedIn")
||propName.equalsIgnoreCase("CurrentState")
||propName.equalsIgnoreCase("PathName")
||propName.equalsIgnoreCase("LockOwner")
||propName.equalsIgnoreCase("Owner") //ASB 15-08-2022
||propName.startsWith("CmAcm") )){
//ASB ... Set to check property cardinality
int CardinalityVal = propDef.get_Cardinality().getValue();
int propIndex;
//===============START
switch (propDef.get_DataType().getValue()){
case StringType:
if (CardinalityVal == CardinalitySINGLE){
String val = object.getProperties().getStringValue(propName);
for (int sectionIndex = 0; sectionIndex < noAUDITORSections; sectionIndex++) {
for (propIndex = 0; propIndex < noAUDITORprops[sectionIndex]; propIndex++) { //AUDITOR_propValues
// Value for Required response
String propValue = val;
String propTest = AUDITORprops[sectionIndex][propIndex];
if (propName.equalsIgnoreCase(propTest)){
AUDITOR_propValues[sectionIndex][propIndex] =propValue;
AUDITOR_propNames[sectionIndex][propIndex] = propDisplayName;
}
}
}
//ASB 15-08-2022
}else{
StringList valList = object.getProperties().getStringListValue(propName);
//Iterator itList = valList.iterator();
//String valLists = " ";
//while (itList.hasNext()){
// valLists = valLists +"
" + sTab + itList.toString();
//}
for (int sectionIndex = 0; sectionIndex < noAUDITORSections; sectionIndex++){
for (propIndex = 0; propIndex < noAUDITORprops[sectionIndex]; propIndex++) { //AUDITOR_propValues
// Value for Required response
if (propName.equalsIgnoreCase(AUDITOR_props[sectionIndex][propIndex])){
// Iterate through the list of values
StringBuffer sb = new StringBuffer();
for( Iterator i = valList.iterator(); i.hasNext(); )
{
// Get the value and cast to an Id property type
String propertyVal = (String)i.next();
sb.append(propertyVal + "
");
}
AUDITOR_propValues[sectionIndex][propIndex] =sb.toString();
AUDITOR_propNames[sectionIndex][propIndex] = propDisplayName;
}
}
}
}
// Process Multi-value Strings (if required)?
break;
case DateType:
if (CardinalityVal == CardinalitySINGLE){
Date dateVal = object.getProperties().getDateTimeValue(propName);
for (int sectionIndex = 0; sectionIndex < noAUDITORSections; sectionIndex++){
for (propIndex = 0; propIndex < noAUDITORprops[sectionIndex]; propIndex++){ //AUDITOR_propValues
// Value for Required response
if (propName.equalsIgnoreCase(AUDITORprops[sectionIndex][propIndex])){
if(dateVal != null) {
AUDITOR_propValues[sectionIndex][propIndex] =dateVal.toString();
AUDITOR_propNames[sectionIndex][propIndex] = propDisplayName;
}
}
}
}
}else{
//
}
break;
// /*
case DoubleType:
if (CardinalityVal == CardinalitySINGLE){
Double doubleVal = object.getProperties().getFloat64Value(propName);
for (int sectionIndex = 0; sectionIndex < noAUDITORSections; sectionIndex++){
for (propIndex = 0; propIndex < noAUDITORprops[sectionIndex]; propIndex++){ //AUDITOR_propValues
// Value for Required response
if (propName.equalsIgnoreCase(AUDITORprops[sectionIndex][propIndex])){
if(doubleVal != null) {
AUDITOR_propValues[sectionIndex][propIndex] =doubleVal.toString();
AUDITOR_propNames[sectionIndex][propIndex] = propDisplayName;
}
}
}
}
}else{
//
}
// */
default:
}
//===============END
}
}catch (Exception writeProp){
logger.error(writeProp.getMessage(), writeProp);
}
}
}
private static void addAUDITORTitlePage( com.lowagie.text.Document document)
throws DocumentException, IOException {
// Add the Audit Master Logo
// Creating an ImageData object
String imageLogoFile = "/opt/AuditReport/images/AuditMasterLogo.tif"; //TODO add to config.xml file
RandomAccessFileOrArray ra = new RandomAccessFileOrArray(imageLogoFile);
int pages = TiffImage.getNumberOfPages(ra);
// Creating an Image object
Image image;
image = TiffImage.getTiffImage(ra, 1);
// Adding the Audit Master Logo image to the Audit report document
Rectangle pageSize = new Rectangle(image.getWidth(),
image.getHeight());
document.setPageSize(pageSize);
document.add(image);
// Start a new page
document.newPage();
Paragraph preface = new Paragraph();
// We add one empty line
addEmptyLine(preface, 1);
// Lets write a big header
//TODO Pick all text up from the config.xml file
Paragraph paragraph = new Paragraph("Audit Master - Audit Report", catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
preface.add(paragraph);
addEmptyLine(preface, 1);
// Lets write another big header
//TODO Pick all text up from the config.xml file
paragraph = new Paragraph("ASB Software Development Limited", catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
preface.add(paragraph);
addEmptyLine(preface, 1);
paragraph = new Paragraph("Department Audit Process Task", catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
preface.add(paragraph);
addEmptyLine(preface, 1);
// Lets write another big header
//TODO Pick all text up from the config.xml file
paragraph = new Paragraph(sTab+ "ISO9000/BS5750", catFont);
paragraph.setAlignment(Element.ALIGN_CENTER);
preface.add(paragraph);
addEmptyLine(preface, 1);
// Will create: Report generated by: _name, _date
preface.add(new Paragraph(sTab+ "Report generated by: " + System.getProperty("user.name") + ", " + new Date(), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
smallBold));
addEmptyLine(preface, 3);
paragraph = new Paragraph(sTab+ "Note: This is an automatically generated Audit Report, the full Audit results and conclusions are produced following the run of the review tasks. ",
smallBold);
paragraph.setAlignment(Element.ALIGN_LEFT);
paragraph.setIndentationLeft(50);
addEmptyLine(preface, 8);
paragraph = new Paragraph(sTab+ "Once you have completed the initial Department Audit, you should have:
" +
"
" + sTab +
"• Arranged a non-conformance review and a follow-up audit and questions.
" +
"
" + sTab +
"• Allowed the Department sufficient time to correct the non-conformances and
" +
"
" + sTab+
"• Generated the evidence for the required changes to their procedures.
" +
"",
redFont);
paragraph.setAlignment(Element.ALIGN_LEFT);
paragraph.setIndentationLeft(50);
document.add(preface);
// Start a new page
document.newPage();
}
//=========E N D C O D E F O R P D F I M P O R T ==========
}
Listing 6-18The QOperations.java source code file