View Javadoc
1   /*
2    * Copyright 2005-2014 The Kuali Foundation.
3    * 
4    * Licensed under the Educational Community License, Version 1.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl1.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.coeus.s2sgen.impl.generate;
17  
18  import gov.grants.apply.system.globalV10.HashValueDocument;
19  import gov.grants.apply.system.headerV10.GrantSubmissionHeaderDocument;
20  import gov.grants.apply.system.metaGrantApplication.GrantApplicationDocument;
21  import gov.grants.apply.system.metaGrantApplication.GrantApplicationDocument.GrantApplication.Forms;
22  import org.apache.xmlbeans.XmlCursor;
23  import org.apache.xmlbeans.XmlObject;
24  import org.kuali.coeus.propdev.api.core.DevelopmentProposalContract;
25  import org.kuali.coeus.propdev.api.s2s.*;
26  import org.kuali.coeus.propdev.api.core.ProposalDevelopmentDocumentContract;
27  import org.kuali.coeus.s2sgen.api.core.InfastructureConstants;
28  import org.kuali.coeus.s2sgen.api.core.S2SException;
29  
30  import org.kuali.coeus.propdev.api.attachment.NarrativeService;
31  import org.kuali.coeus.s2sgen.api.generate.*;
32  import org.kuali.coeus.s2sgen.api.hash.GrantApplicationHashService;
33  import org.kuali.coeus.s2sgen.impl.datetime.S2SDateTimeService;
34  import org.kuali.coeus.s2sgen.impl.validate.S2SValidatorService;
35  import org.kuali.coeus.s2sgen.api.core.AuditError;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  import org.springframework.beans.factory.annotation.Autowired;
39  import org.springframework.beans.factory.annotation.Qualifier;
40  import org.springframework.stereotype.Component;
41  
42  
43  import javax.xml.namespace.QName;
44  import java.util.*;
45  
46  @Component("formGeneratorService")
47  public class FormGeneratorServiceImpl implements FormGeneratorService {
48  	private static final Logger LOG = LoggerFactory.getLogger(FormGeneratorServiceImpl.class);
49  
50      @Autowired
51      @Qualifier("s2SFormGeneratorRetrievalService")
52  	private S2SFormGeneratorRetrievalService s2SFormGeneratorService;
53  
54      @Autowired
55      @Qualifier("s2SValidatorService")
56      private S2SValidatorService s2SValidatorService;
57  
58      @Autowired
59      @Qualifier("narrativeService")
60      private NarrativeService narrativeService;
61  
62      @Autowired
63      @Qualifier("formMappingService")
64      private FormMappingService formMappingService;
65  
66      @Autowired
67      @Qualifier("s2SDateTimeService")
68      private S2SDateTimeService s2SDateTimeService;
69  
70      @Autowired
71      @Qualifier("grantApplicationHashService")
72      private GrantApplicationHashService grantApplicationHashService;
73  
74  	/**
75  	 * 
76  	 * This method is used to validate application before submission.
77  	 * 
78  	 * @param pdDocContract
79  	 *            Proposal Development Document.
80  	 * @throws S2SException
81  	 */
82      @Override
83  	public FormValidationResult validateForms(
84              ProposalDevelopmentDocumentContract pdDocContract)
85  			throws S2SException {
86  
87          if (pdDocContract == null) {
88              throw new IllegalArgumentException("pdDoc is null");
89          }
90  
91          return generateAndValidateForms(null, null,
92                  pdDocContract);
93  	}
94  
95  	/**
96  	 * 
97  	 * This method is to generate and validate the generated forms.
98  	 * 
99  	 * @param forms
100 	 *            Forms
101 	 * @param attList
102 	 *            List of attachments.
103 	 * @param pdDoc
104 	 *            Proposal Development Document.
105 	 * @throws S2SException
106 	 */
107 	protected FormGenerationResult generateAndValidateForms(Forms forms,
108 			List<AttachmentData> attList, ProposalDevelopmentDocumentContract pdDoc) throws S2SException {
109 		boolean validationSucceeded = true;
110 		DevelopmentProposalContract developmentProposal = pdDoc.getDevelopmentProposal();
111 		List<? extends S2sOppFormsContract> opportunityForms = developmentProposal.getS2sOppForms();
112 
113 		if (attList == null) {
114 		    attList = new ArrayList<AttachmentData>();
115 		}
116 
117         List<AuditError> auditErrors = new ArrayList<AuditError>();
118         getNarrativeService().deleteSystemGeneratedNarratives(pdDoc.getDevelopmentProposal().getNarratives());
119 		for (S2sOppFormsContract opportunityForm : opportunityForms) {
120 			if (!opportunityForm.getInclude()) {
121 				continue;
122 			}
123             FormMappingInfo info = formMappingService.getFormInfo(opportunityForm.getOppNameSpace(),developmentProposal.getProposalNumber());
124             if(info==null) continue;
125 			String namespace = info.getNameSpace();
126             S2SFormGenerator s2sFormGenerator = s2SFormGeneratorService.getS2SGenerator(developmentProposal.getProposalNumber(),namespace);
127             auditErrors.addAll(s2sFormGenerator.getAuditErrors());
128 			try {
129 				XmlObject formObject = s2sFormGenerator.getFormObject(pdDoc);
130 				if (s2SValidatorService.validate(formObject, auditErrors)) {
131 					if (forms != null && attList != null) {
132 						setFormObject(forms, formObject);
133 					}
134 				} else {
135 					validationSucceeded = false;
136 				}
137 				attList.addAll(s2sFormGenerator.getAttachments());
138 			} catch (Exception ex) {
139 				LOG.error(
140 						"Unknown error from " + opportunityForm.getFormName(),
141 						ex);
142 				throw new S2SException("Could not generate form for "
143 						+ opportunityForm.getFormName(), ex);
144 			}
145 		}
146         FormGenerationResult result = new FormGenerationResult();
147         result.setValid(validationSucceeded);
148         result.setErrors(auditErrors);
149         result.setAttachments(attList);
150 		return result;
151 	}
152 
153     @Override
154     public FormGenerationResult generateAndValidateForms(ProposalDevelopmentDocumentContract pdDocContract) throws S2SException {
155 
156         if (pdDocContract == null) {
157             throw new IllegalArgumentException("pdDoc is null");
158         }
159 
160         GrantApplicationDocument.GrantApplication.Forms forms = GrantApplicationDocument.GrantApplication.Forms.Factory.newInstance();
161         List<AttachmentData> attList = new ArrayList<AttachmentData>();
162         final FormGenerationResult result = generateAndValidateForms(forms, attList, pdDocContract);
163         if (result.isValid()) {
164             String applicationXml = getGrantApplicationDocument(pdDocContract,forms);
165             result.setApplicationXml(applicationXml);
166         }
167         return result;
168     }
169 
170     /**
171      *
172      * This method populates values for {@link GrantApplicationDocument} for a
173      * given {@link ProposalDevelopmentDocumentContract}
174      *
175      * @param pdDoc
176      *            {@link ProposalDevelopmentDocumentContract}
177      * @param forms
178      *            {@link gov.grants.apply.system.metaGrantApplication.GrantApplicationDocument.GrantApplication.Forms} generated XML forms
179      * @return {@link GrantApplicationDocument} populated with forms
180      * @throws S2SException
181      */
182     protected String getGrantApplicationDocument(
183             ProposalDevelopmentDocumentContract pdDoc, GrantApplicationDocument.GrantApplication.Forms forms) throws S2SException {
184         GrantApplicationDocument grantApplicationDocument = GrantApplicationDocument.Factory.newInstance();
185         GrantApplicationDocument.GrantApplication grantApplication = GrantApplicationDocument.GrantApplication.Factory.newInstance();
186         grantApplication.setForms(forms);
187         GrantSubmissionHeaderDocument.GrantSubmissionHeader grantSubmissionHeader = GrantSubmissionHeaderDocument.GrantSubmissionHeader.Factory.newInstance();
188         grantSubmissionHeader.setActivityTitle(pdDoc.getDevelopmentProposal().getProgramAnnouncementTitle());
189         grantSubmissionHeader.setOpportunityTitle(pdDoc.getDevelopmentProposal().getProgramAnnouncementTitle());
190         grantSubmissionHeader.setAgencyName(pdDoc.getDevelopmentProposal().getSponsor().getSponsorName());
191         if(pdDoc.getDevelopmentProposal().getCfdaNumber()!=null){
192             grantSubmissionHeader.setCFDANumber(pdDoc.getDevelopmentProposal().getCfdaNumber());
193         }
194         S2sOpportunityContract s2sOpportunity = pdDoc.getDevelopmentProposal().getS2sOpportunity();
195         if (s2sOpportunity.getCompetetionId() != null) {
196             grantSubmissionHeader.setCompetitionID(s2sOpportunity.getCompetetionId());
197         }
198         grantSubmissionHeader.setOpportunityID(s2sOpportunity.getOpportunityId());
199         grantSubmissionHeader.setSchemaVersion(FormVersion.v1_0.getVersion());
200         grantSubmissionHeader.setSubmissionTitle(s2sOpportunity.getProposalNumber());
201 
202         // set closing date unless null
203         Calendar closingDate = s2sOpportunity.getClosingDate();
204         if (closingDate != null) {
205             grantSubmissionHeader.setClosingDate(closingDate);
206         }
207 
208         // set opening date unless null
209         Calendar openingDate = s2sOpportunity.getOpeningDate();
210         if (openingDate != null) {
211             grantSubmissionHeader.setOpeningDate(openingDate);
212         }
213         String applicationXml = getXmlFromDocument(grantApplication);
214         String hashVal = grantApplicationHashService.computeGrantFormsHash(applicationXml);
215 
216         HashValueDocument.HashValue hashValue = HashValueDocument.HashValue.Factory.newInstance();
217         hashValue.setHashAlgorithm(InfastructureConstants.HASH_ALGORITHM);
218         hashValue.setStringValue(hashVal);
219         grantSubmissionHeader.setHashValue(hashValue);
220         grantApplication.setGrantSubmissionHeader(grantSubmissionHeader);
221         grantApplicationDocument.setGrantApplication(grantApplication);
222         String schemaUrl = s2sOpportunity.getSchemaUrl();
223 
224         XmlCursor cursor = grantApplicationDocument.newCursor();
225 
226         cursor.toStartDoc();
227         if (cursor.toFirstChild()){
228             String defaultNameSpace = cursor.getName().getNamespaceURI();
229             String schemaLocation = defaultNameSpace+ " "+schemaUrl;
230             cursor.setAttributeText(new QName("http://www.w3.org/2001/XMLSchema-instance","schemaLocation"), schemaLocation);
231         }
232 
233         return getXmlFromDocument(grantApplicationDocument);
234     }
235 
236     private String getXmlFromDocument(XmlObject grantApplicationDocument) {
237         String applicationXmlText = grantApplicationDocument
238                 .xmlText(s2SFormGeneratorService.getXmlOptionsPrefixes());
239         String applicationXml = s2SDateTimeService.removeTimezoneFactor(applicationXmlText);
240         return applicationXml;
241     }
242 
243 
244 
245     /**
246 	 * 
247 	 * This method is to set the formObject to MetaGrants Forms Object. The
248 	 * xmlbeans Schema compiled with xsd:any does not provide a direct method to
249 	 * add individual forms to the Forms object. In this method, an XML Cursor
250 	 * is created from the existing Forms object and use the moveXml method to
251 	 * add the form object to the Forms object.
252 	 * 
253 	 * @param forms
254 	 *            Forms object to which the grants.gov form is added.
255 	 * @param formObject
256 	 *            xml object representing the grants.gov form.
257 	 */
258 	protected void setFormObject(Forms forms, XmlObject formObject) {
259 		// Create a cursor from the grants.gov form
260 		XmlCursor formCursor = formObject.newCursor();
261 		formCursor.toStartDoc();
262 		formCursor.toNextToken();
263 
264 		// Create a cursor from the Forms object
265 		XmlCursor metaGrantCursor = forms.newCursor();
266 		metaGrantCursor.toNextToken();
267 
268 		// Add the form to the Forms object.
269 		formCursor.moveXml(metaGrantCursor);
270 	}
271 
272     @Override
273     public FormValidationResult validateUserAttachedFormFile(S2sUserAttachedFormFileContract s2sUserAttachedFormFile) throws S2SException {
274         if (s2sUserAttachedFormFile == null) {
275             throw new IllegalArgumentException("s2sUserAttachedFormFile is null");
276         }
277         boolean validationSucceeded;
278         List<AuditError> auditErrors = new ArrayList<AuditError>();
279         try {
280             XmlObject xmlObject = XmlObject.Factory.parse(s2sUserAttachedFormFile.getXmlFile());
281             if(!getS2SValidatorService().validate(xmlObject, auditErrors)) {
282                 validationSucceeded = false;
283             }else{
284                 validationSucceeded = true;
285             }
286         } catch (Exception e) {
287             throw new S2SException();
288         }
289 
290         FormGenerationResult result = new FormGenerationResult();
291         result.setValid(validationSucceeded);
292         result.setErrors(auditErrors);
293         return result;
294     }
295 
296 
297 	/**
298 	 * 
299 	 * Setter for {@link S2SFormGeneratorRetrievalService}
300 	 * 
301 	 * @param s2SFormGeneratorService
302 	 */
303 	public void setS2SFormGeneratorService(
304 			S2SFormGeneratorRetrievalService s2SFormGeneratorService) {
305 		this.s2SFormGeneratorService = s2SFormGeneratorService;
306 	}
307 
308 	/**
309 	 * Gets the s2SFormGeneratorService attribute.
310 	 * 
311 	 * @return Returns the s2SFormGeneratorService.
312 	 */
313 	public S2SFormGeneratorRetrievalService getS2SFormGeneratorService() {
314 		return s2SFormGeneratorService;
315 	}
316 
317 	/**
318 	 * Gets the s2SValidatorService attribute.
319 	 * 
320 	 * @return Returns the s2SValidatorService.
321 	 */
322 	public S2SValidatorService getS2SValidatorService() {
323 		return s2SValidatorService;
324 	}
325 
326 	/**
327 	 * Sets the s2SValidatorService attribute value.
328 	 * 
329 	 * @param validatorService
330 	 *            The s2SValidatorService to set.
331 	 */
332 	public void setS2SValidatorService(S2SValidatorService validatorService) {
333 		s2SValidatorService = validatorService;
334 	}
335 
336     public NarrativeService getNarrativeService() {
337         return narrativeService;
338     }
339 
340     public void setNarrativeService(NarrativeService narrativeService) {
341         this.narrativeService = narrativeService;
342     }
343 
344     public S2SDateTimeService getS2SDateTimeService() {
345         return s2SDateTimeService;
346     }
347 
348     public void setS2SDateTimeService(S2SDateTimeService s2SDateTimeService) {
349         this.s2SDateTimeService = s2SDateTimeService;
350     }
351 
352     public FormMappingService getFormMappingService() {
353         return formMappingService;
354     }
355 
356     public void setFormMappingService(FormMappingService formMappingService) {
357         this.formMappingService = formMappingService;
358     }
359 
360     public GrantApplicationHashService getGrantApplicationHashService() {
361         return grantApplicationHashService;
362     }
363 
364     public void setGrantApplicationHashService(GrantApplicationHashService grantApplicationHashService) {
365         this.grantApplicationHashService = grantApplicationHashService;
366     }
367 }