View Javadoc
1   package org.kuali.coeus.s2sgen.impl.generate.support;
2   
3   import com.lowagie.text.*;
4   import com.lowagie.text.Font;
5   import com.lowagie.text.pdf.*;
6   import gov.grants.apply.coeus.personProfile.PersonProfileListDocument;
7   import gov.grants.apply.coeus.personProfile.PersonProfileListDocument.PersonProfileList;
8   import gov.grants.apply.coeus.personProfile.PersonProfileListDocument.PersonProfileList.ExtraKeyPerson;
9   import gov.grants.apply.coeus.personProfile.PersonProfileListDocument.PersonProfileList.ExtraKeyPerson.Address.Country.Enum;
10  import gov.grants.apply.system.attachmentsV10.AttachedFileDataType;
11  import org.apache.commons.lang3.StringUtils;
12  import org.slf4j.Logger;
13  import org.slf4j.LoggerFactory;
14  import org.kuali.coeus.common.api.unit.UnitContract;
15  import org.kuali.coeus.common.api.unit.UnitRepositoryService;
16  import org.kuali.coeus.propdev.api.person.ProposalPersonContract;
17  import org.kuali.coeus.propdev.api.person.attachment.ProposalPersonBiographyContract;
18  import org.kuali.coeus.s2sgen.api.core.S2SException;
19  import org.kuali.coeus.s2sgen.impl.person.S2SProposalPersonService;
20  import org.kuali.coeus.propdev.api.core.ProposalDevelopmentDocumentContract;
21  import org.kuali.coeus.s2sgen.impl.util.FieldValueConstants;
22  import org.kuali.coeus.sys.api.model.KcFile;
23  import org.kuali.coeus.propdev.api.attachment.NarrativeContract;
24  import org.kuali.coeus.s2sgen.impl.generate.S2SBaseFormGenerator;
25  import org.kuali.coeus.s2sgen.impl.print.GenericPrintable;
26  import org.kuali.coeus.s2sgen.impl.print.S2SPrintingService;
27  
28  import org.springframework.beans.factory.annotation.Autowired;
29  import org.springframework.beans.factory.annotation.Qualifier;
30  
31  import javax.xml.transform.Source;
32  import javax.xml.transform.stream.StreamSource;
33  import java.awt.*;
34  import java.io.ByteArrayOutputStream;
35  import java.io.IOException;
36  import java.text.DateFormat;
37  import java.text.SimpleDateFormat;
38  import java.util.*;
39  import java.util.List;
40  
41  public abstract class RRKeyPersonBase extends S2SBaseFormGenerator{
42  	
43  	private static final Logger LOG = LoggerFactory.getLogger(RRKeyPersonBase.class);
44  	protected List<ProposalPersonContract> extraPersons = null;
45  	
46  	protected static final int BIOSKETCH_DOC_TYPE = 16;
47  	protected static final int CURRENTPENDING_DOC_TYPE = 17;
48  	protected static final String BIOSKETCH_TYPE = "1";
49  	protected static final String CURRENT_PENDING_TYPE = "2";
50  	private int WHITESPACE_LENGTH_76 = 76;
51  	private int WHITESPACE_LENGTH_60 = 60;
52  	private static final String COMMENT = "Auto generated document for ";
53  	private static final String BIOSKETCH_COMMENT = "BIOSKETCH";
54  	private static final String CURRENT_PENDING_COMMENT = "CURRENTPENDING";
55  	protected static final String PROFILE_COMMENT = "PROFILE";
56      protected static final int PROFILE_TYPE = 18;
57  	protected static final String ADDITIONALKEYPERSONPROFILES_XSL = "/org/kuali/kra/s2s/stylesheet/additionalkeypersonprofiles.xsl";
58  	protected static final String NIH_CO_INVESTIGATOR = "Co-Investigator";
59      protected static final String ERROR_ERA_COMMON_USER_NAME="eRA Commons User Name is missing for ";
60  
61      @Autowired
62      @Qualifier("unitRepositoryService")
63      private UnitRepositoryService unitRepositoryService;
64  
65      @Autowired
66      @Qualifier("s2SPrintingService")
67      private S2SPrintingService s2SPrintingService;
68  
69      @Autowired
70      @Qualifier("s2SProposalPersonService")
71      protected S2SProposalPersonService s2SProposalPersonService;
72  
73  	protected void saveKeyPersonAttachmentsToProposal() {
74  	    if(extraPersons!=null && !extraPersons.isEmpty()){
75  	        saveKeyPersonAttachments();
76  	        saveKeypersonProfileObject();
77  	    }
78  	}
79  
80  	private NarrativeContract[] saveKeyPersonAttachments() {
81  		List<String> bioSketchBookMarks = new ArrayList<String>();
82  		List<String> curPendBookMarks = new ArrayList<String>();
83  		List<byte[]> bioSketchDataList = new ArrayList<byte[]>();
84  		List<byte[]> curPendDataList = new ArrayList<byte[]>();
85  
86          NarrativeContract[] extraKeyPersonAttachments = new NarrativeContract[2];
87  		for (ProposalPersonContract proposalPerson : extraPersons) {
88  			setBookMarkAndData(bioSketchBookMarks, bioSketchDataList,
89  					proposalPerson, BIOSKETCH_TYPE);
90  			setBookMarkAndData(curPendBookMarks, curPendDataList,
91  					proposalPerson, CURRENT_PENDING_TYPE);
92  		}
93  		byte[] bioSketchData = null;
94  		byte[] curPendData = null;
95  		try {
96  			bioSketchData = mergePdfBytes(bioSketchDataList, bioSketchBookMarks);
97  			curPendData = mergePdfBytes(curPendDataList, curPendBookMarks);
98  			String fileName = null;
99  			if (bioSketchData != null && bioSketchData.length > 0) {
100 				fileName = pdDoc.getDevelopmentProposal().getProposalNumber()
101 						+ "_" + BIOSKETCH_COMMENT+".pdf";
102 				extraKeyPersonAttachments[0] = saveNarrative(bioSketchData, "" + BIOSKETCH_DOC_TYPE, fileName,
103 						COMMENT + BIOSKETCH_COMMENT);
104 			}
105 			if (curPendData != null && curPendData.length > 0) {
106 				fileName = pdDoc.getDevelopmentProposal().getProposalNumber()
107 						+ "_" + CURRENT_PENDING_COMMENT+".pdf";
108 				extraKeyPersonAttachments[1] = saveNarrative(curPendData, "" + CURRENTPENDING_DOC_TYPE,
109 						fileName, COMMENT + CURRENT_PENDING_COMMENT);
110 			}
111 		} catch (S2SException e) {
112 			LOG.error("Auto generation of Biosketch/Currend Pending report for extra Keypersons is failed", e);
113 		}
114 		return extraKeyPersonAttachments;
115 	}
116 	
117 	private void setBookMarkAndData(List<String> bookMarksList,
118 			List<byte[]> dataList, ProposalPersonContract proposalPerson, String docType) {
119 		String personId = null;
120 		if (proposalPerson.getPersonId() != null
121 				&& proposalPerson.getPersonId().length() > 0) {
122 			personId = proposalPerson.getPersonId();
123 		} else {
124 			personId = "" + proposalPerson.getRolodexId();
125 		}
126 
127 		for (ProposalPersonBiographyContract personBiography : getPernonnelAttachments(
128 				pdDoc, proposalPerson, docType)) {
129 			byte[] content = personBiography.getPersonnelAttachment().getData();
130 			if (content != null && content.length > 0) {
131 				dataList.add(content);
132 				bookMarksList.add(personId);
133 			}
134 		}
135 	}
136 	/**
137 	 * @param pdfBytesList
138 	 *            List containing the PDF data bytes
139 	 * @param bookmarksList
140 	 *            List of bookmarks corresponding to the PDF bytes.
141 	 * @return
142 	 * @throws org.kuali.coeus.s2sgen.api.core.S2SException
143 	 */
144 	private byte[] mergePdfBytes(List<byte[]> pdfBytesList,
145 			List<String> bookmarksList) throws S2SException {
146 		Document document = null;
147 		PdfWriter writer = null;
148 		ByteArrayOutputStream mergedPdfReport = new ByteArrayOutputStream();
149 		int totalNumOfPages = 0;
150 		PdfReader[] pdfReaderArr = new PdfReader[pdfBytesList.size()];
151 		int pdfReaderCount = 0;
152 		for (byte[] fileBytes : pdfBytesList) {
153 			LOG.debug("File Size " + fileBytes.length + " For "
154 					+ bookmarksList.get(pdfReaderCount));
155 			PdfReader reader = null;
156 			try {
157 				reader = new PdfReader(fileBytes);
158 				pdfReaderArr[pdfReaderCount] = reader;
159 				pdfReaderCount = pdfReaderCount + 1;
160 				totalNumOfPages += reader.getNumberOfPages();
161 			} catch (IOException e) {
162 				LOG.error(e.getMessage(), e);
163 				throw new S2SException(e.getMessage(), e);
164 			}
165 		}
166 
167 		Calendar calendar = Calendar.getInstance();
168 		DateFormat dateFormat = new SimpleDateFormat("M/d/yy h:mm a");
169 		String dateString = dateFormat.format(calendar.getTime());
170 		StringBuilder footerPhStr = new StringBuilder();
171 		footerPhStr.append(" of ");
172 		footerPhStr.append(totalNumOfPages);
173 		footerPhStr.append(getWhitespaceString(WHITESPACE_LENGTH_76));
174 		footerPhStr.append(getWhitespaceString(WHITESPACE_LENGTH_76));
175 		footerPhStr.append(getWhitespaceString(WHITESPACE_LENGTH_60));
176 		footerPhStr.append(dateString);
177 		Font font = FontFactory.getFont(FontFactory.TIMES, 8, Font.NORMAL,
178 				Color.BLACK);
179 		Phrase beforePhrase = new Phrase("Page ", font);
180 		Phrase afterPhrase = new Phrase(footerPhStr.toString(), font);
181 		HeaderFooter footer = new HeaderFooter(beforePhrase, afterPhrase);
182 		footer.setAlignment(Element.ALIGN_BASELINE);
183 		footer.setBorderWidth(0f);
184 		for (int count = 0; count < pdfReaderArr.length; count++) {
185 			PdfReader reader = pdfReaderArr[count];
186 			int nop;
187 			if (reader == null) {
188 				LOG.debug("Empty PDF byetes found for "
189 						+ bookmarksList.get(count));
190 				continue;
191 			} else {
192 				nop = reader.getNumberOfPages();
193 			}
194 
195 			if (count == 0) {
196 				document = nop > 0 ? new com.lowagie.text.Document(reader
197 						.getPageSizeWithRotation(1))
198 						: new com.lowagie.text.Document();
199 				try {
200 					writer = PdfWriter.getInstance(document, mergedPdfReport);
201 				} catch (DocumentException e) {
202 					LOG.error(e.getMessage(), e);
203 					throw new S2SException(e.getMessage(), e);
204 				}
205 				document.setFooter(footer);
206 				document.open();
207 			}
208 			PdfContentByte cb = writer.getDirectContent();
209 			int pageCount = 0;
210 			while (pageCount < nop) {
211 				document.setPageSize(reader.getPageSize(++pageCount));
212 				document.newPage();
213 				document.setFooter(footer);
214 				PdfImportedPage page = writer
215 						.getImportedPage(reader, pageCount);
216 
217 				cb.addTemplate(page, 1, 0, 0, 1, 0, 0);
218 
219 				PdfOutline root = cb.getRootOutline();
220 				if (pageCount == 1) {
221 					String pageName = bookmarksList.get(count);
222 					cb.addOutline(new PdfOutline(root, new PdfDestination(
223 							PdfDestination.FITH), pageName), pageName);
224 				}
225 			}
226 		}
227 		if (document != null) {
228 			try {
229 				document.close();
230 				return mergedPdfReport.toByteArray();
231 			} catch (Exception e) {
232 				LOG
233 						.error(
234 								"Exception occured because the generated PDF document has no pages",
235 								e);
236 			}
237 		}
238 		return null;
239 	}
240 	private List<ProposalPersonBiographyContract> getPernonnelAttachments(
241 			ProposalDevelopmentDocumentContract pdDoc, ProposalPersonContract proposalPerson,
242 			String documentType) {
243 		List<ProposalPersonBiographyContract> result = new ArrayList<ProposalPersonBiographyContract>();
244 		for (ProposalPersonBiographyContract proposalPersonBiography : pdDoc
245 				.getDevelopmentProposal().getPropPersonBios()) {
246 			String personId = proposalPerson.getPersonId();
247 			Integer rolodexId = proposalPerson.getRolodexId();
248 			if (personId != null
249 					&& proposalPersonBiography.getPersonId() != null
250 					&& proposalPersonBiography.getPersonId().equals(personId)
251 					&& documentType.equals(proposalPersonBiography.getPropPerDocType().getCode())) {
252 				result.add(proposalPersonBiography);
253 			} else if (rolodexId != null
254 					&& proposalPersonBiography.getRolodexId() != null
255 					&& proposalPersonBiography.getRolodexId().toString()
256 							.equals(rolodexId.toString())
257 					&& documentType.equals(proposalPersonBiography
258 							.getPropPerDocType().getCode())) {
259 				result.add(proposalPersonBiography);
260 			}
261 		}
262 		return result;
263 	}
264 	
265 	private String getWhitespaceString(int length) {
266 		StringBuffer sb = new StringBuffer();
267 		char[] whiteSpace = new char[length];
268 		Arrays.fill(whiteSpace, FieldValueConstants.SPACE_SEPARATOR);
269 		sb.append(whiteSpace);
270 		return sb.toString();
271 	}
272 	
273 	protected PersonProfileList.ExtraKeyPerson[] getExtraKeyPersons() {
274 		List<PersonProfileList.ExtraKeyPerson> extraPersonList = new ArrayList<PersonProfileList.ExtraKeyPerson>();
275 
276 		for (ProposalPersonContract proposalPerson : extraPersons) {
277 
278 			PersonProfileList.ExtraKeyPerson extraPerson = PersonProfileList.ExtraKeyPerson.Factory
279 					.newInstance();
280 
281 			extraPerson.setName(getExtraPersonName(proposalPerson));
282 			extraPerson.setAddress(getExtraPersonAddress(proposalPerson));
283 			if (proposalPerson.getPrimaryTitle() != null
284 					&& proposalPerson.getPrimaryTitle().length() > 45)
285 				extraPerson.setTitle(proposalPerson.getPrimaryTitle()
286 						.substring(0, 45));
287 			else {
288 				extraPerson.setTitle(proposalPerson.getPrimaryTitle());
289 			}
290 
291 			if (proposalPerson.getProposalPersonRoleId() != null) {
292 				if (proposalPerson.isPrincipalInvestigator()) {
293 					extraPerson
294 							.setProjectRole(gov.grants.apply.coeus.personProfile.PersonProfileListDocument.PersonProfileList.ExtraKeyPerson.ProjectRole.PD_PI);
295 				} else if (proposalPerson.isCoInvestigator()) {
296 					if (isSponsorNIH(pdDoc)) {
297 						extraPerson
298 								.setProjectRole(gov.grants.apply.coeus.personProfile.PersonProfileListDocument.PersonProfileList.ExtraKeyPerson.ProjectRole.OTHER_SPECIFY);
299 						extraPerson
300 								.setOtherProjectRoleCategory(NIH_CO_INVESTIGATOR);
301 					} else {
302 						extraPerson
303 								.setProjectRole(gov.grants.apply.coeus.personProfile.PersonProfileListDocument.PersonProfileList.ExtraKeyPerson.ProjectRole.CO_PD_PI);
304 					}
305 				} else {
306 					String otherRole = "";
307 					if (proposalPerson.getProjectRole() != null
308 							&& proposalPerson.getProjectRole().length() > 40) {
309 						otherRole = proposalPerson.getProjectRole().substring(
310 								0, 40);
311 					} else {
312 						otherRole = proposalPerson.getProjectRole();
313 					}
314 					extraPerson.setOtherProjectRoleCategory(otherRole);
315 					extraPerson
316 							.setProjectRole(gov.grants.apply.coeus.personProfile.PersonProfileListDocument.PersonProfileList.ExtraKeyPerson.ProjectRole.OTHER_SPECIFY);
317 				}
318 			}
319 
320 			if (proposalPerson.getEraCommonsUserName() != null) {
321 				extraPerson.setCredential(proposalPerson
322 						.getEraCommonsUserName());
323 			}
324 			setDepartmentName(extraPerson, proposalPerson);
325 			setDivisionName(extraPerson, proposalPerson);
326 			if (proposalPerson.getEmailAddress() != null) {
327 				extraPerson.setEmail(proposalPerson.getEmailAddress());
328 			}
329 			if (StringUtils.isNotEmpty(proposalPerson.getFaxNumber())) {
330 				extraPerson.setFax(proposalPerson.getFaxNumber());
331 			}
332             UnitContract unit = unitRepositoryService.findUnitByUnitNumber(proposalPerson.getHomeUnit());
333 
334 			if (unit != null
335 					&& unit.getUnitName() != null) {
336 				extraPerson.setOrganizationName(unit.getUnitName());
337 			}
338 			if (proposalPerson.getOfficePhone() != null)
339 				extraPerson.setPhone(proposalPerson.getOfficePhone());
340 
341 			// degree type and year added for version 1.2 - case 4337
342 			if (proposalPerson.getDegree() != null) {
343 				extraPerson.setDegreeType(proposalPerson.getDegree());
344 			}
345 			if (proposalPerson.getYearGraduated() != null) {
346 				extraPerson.setDegreeYear(proposalPerson.getYearGraduated());
347 			}
348 			AttachedFileDataType bioSketchAttachment = getPernonnelAttachments(
349 					pdDoc, proposalPerson.getPersonId(), proposalPerson
350 							.getRolodexId(), "16");
351 			if (bioSketchAttachment != null) {
352 				extraPerson
353 						.setBioSketchAttached(gov.grants.apply.coeus.personProfile.PersonProfileListDocument.PersonProfileList.ExtraKeyPerson.BioSketchAttached.YES);
354 			}
355 
356 			AttachedFileDataType curPendingAttachment = getPernonnelAttachments(
357 					pdDoc, proposalPerson.getPersonId(), proposalPerson
358 							.getRolodexId(), "16");
359 			if (curPendingAttachment != null) {
360 				extraPerson
361 						.setSupportsAttached(gov.grants.apply.coeus.personProfile.PersonProfileListDocument.PersonProfileList.ExtraKeyPerson.SupportsAttached.YES);
362 			}
363 			extraPersonList.add(extraPerson);
364 		}
365 		return extraPersonList.toArray(new PersonProfileList.ExtraKeyPerson[0]);
366 	}
367 
368 	private PersonProfileList.ExtraKeyPerson.Address getExtraPersonAddress(
369 			ProposalPersonContract proposalPerson) {
370 		PersonProfileList.ExtraKeyPerson.Address address = PersonProfileList.ExtraKeyPerson.Address.Factory
371 				.newInstance();
372 		if (proposalPerson.getAddressLine1() != null) {
373 			if (proposalPerson.getAddressLine1().length() > 55)
374 				address.setStreet1(proposalPerson.getAddressLine1().substring(
375 						0, 55));
376 			else
377 				address.setStreet1(proposalPerson.getAddressLine1());
378 		}
379 		if (proposalPerson.getAddressLine2() != null) {
380 			if (proposalPerson.getAddressLine2().length() > 55)
381 				address.setStreet2(proposalPerson.getAddressLine2().substring(
382 						0, 55));
383 			else
384 				address.setStreet2(proposalPerson.getAddressLine2());
385 		}
386 		if (proposalPerson.getCity() != null)
387 			address.setCity(proposalPerson.getCity());
388 		if (proposalPerson.getCounty() != null)
389 			address.setCounty(proposalPerson.getCounty());
390 
391 		if (proposalPerson.getPostalCode() != null) {
392 			address.setZipCode(proposalPerson.getPostalCode());
393 		}
394 
395 		if (proposalPerson.getCountryCode() != null) {
396 			PersonProfileList.ExtraKeyPerson.Address.Country.Enum county = Enum
397 					.forString(proposalPerson.getCountryCode());
398 			address.setCountry(county);
399 		}
400 		if (proposalPerson.getState() != null) {
401 			address.setState(proposalPerson.getState());
402 		}
403 		return address;
404 	}
405 
406 	private PersonProfileList.ExtraKeyPerson.Name getExtraPersonName(
407 			ProposalPersonContract proposalPerson) {
408 		PersonProfileList.ExtraKeyPerson.Name name = PersonProfileList.ExtraKeyPerson.Name.Factory
409 				.newInstance();
410 		if (proposalPerson.getFirstName() != null)
411 			name.setFirstName(proposalPerson.getFirstName());
412 		if (proposalPerson.getMiddleName() != null)
413 			name.setMiddleName(proposalPerson.getMiddleName());
414 		if (proposalPerson.getLastName() != null)
415 			name.setLastName(proposalPerson.getLastName());
416 		return name;
417 	}
418 
419 	private void setDivisionName(ExtraKeyPerson extraPerson,
420 			ProposalPersonContract proposalPerson) {
421 		String divisionName = "";
422 		if (divisionName != null && divisionName.length() > 29) {
423 			divisionName = divisionName.substring(0, 29);
424 		}
425 		extraPerson.setDivisionName(divisionName);
426 	}
427 
428 	private void setDepartmentName(ExtraKeyPerson extraPerson,
429 			ProposalPersonContract proposalPerson) {
430 		String departmentName = "";
431 		if (departmentName != null && departmentName.length() > 30) {
432 			departmentName = departmentName.substring(0, 29);
433 		}
434 		if (departmentName != null)
435 			extraPerson.setDepartmentName(departmentName);
436 
437 	}
438 	private NarrativeContract saveKeypersonProfileObject() {
439         NarrativeContract narrative = null;
440 		if (extraPersons != null && !extraPersons.isEmpty()) {
441 			PersonProfileList extraPersonProfileList = PersonProfileList.Factory.newInstance();
442 
443 			extraPersonProfileList.setProposalNumber(pdDoc
444 					.getDevelopmentProposal().getProposalNumber());
445 			extraPersonProfileList.setExtraKeyPersonArray(getExtraKeyPersons());
446 
447 			PersonProfileListDocument  extraPersonDoc = PersonProfileListDocument.Factory.newInstance();
448 			extraPersonDoc.setPersonProfileList(extraPersonProfileList);
449 			String xmlData = extraPersonDoc.xmlText();
450 			Map<String, byte[]> streamMap = new HashMap<String, byte[]>();
451 			streamMap.put("", xmlData.getBytes());
452 
453 			Source xsltSource = new StreamSource(getClass()
454 					.getResourceAsStream(ADDITIONALKEYPERSONPROFILES_XSL));
455 			Map<String, Source> xSLTemplateWithBookmarks = new HashMap<String, Source>();
456 			xSLTemplateWithBookmarks.put("", xsltSource);
457 			
458 			
459 			GenericPrintable printable = new GenericPrintable();
460 			printable.setXSLTemplateWithBookmarks(xSLTemplateWithBookmarks);
461 			printable.setStreamMap(streamMap);
462 			try {
463 				KcFile printData = s2SPrintingService.print(printable);
464 				String fileName = pdDoc.getDevelopmentProposal().getProposalNumber() +"_"+PROFILE_COMMENT+".pdf";
465 				narrative = saveNarrative(printData.getData(), ""+PROFILE_TYPE,fileName,COMMENT +PROFILE_COMMENT);
466 			} catch (S2SException e) {
467 				LOG.error("Auto generation of Profile attachment for extra Keypersons failed",e);
468 			}
469 		}
470 		return narrative;
471 	}
472 
473     public UnitRepositoryService getUnitRepositoryService() {
474         return unitRepositoryService;
475     }
476 
477     public void setUnitRepositoryService(UnitRepositoryService unitRepositoryService) {
478         this.unitRepositoryService = unitRepositoryService;
479     }
480 
481     public S2SPrintingService getS2SPrintingService() {
482         return s2SPrintingService;
483     }
484 
485     public void setS2SPrintingService(S2SPrintingService s2SPrintingService) {
486         this.s2SPrintingService = s2SPrintingService;
487     }
488 
489     public S2SProposalPersonService getS2SProposalPersonService() {
490         return s2SProposalPersonService;
491     }
492 
493     public void setS2SProposalPersonService(S2SProposalPersonService s2SProposalPersonService) {
494         this.s2SProposalPersonService = s2SProposalPersonService;
495     }
496 }