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
138
139
140
141
142
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
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 }