001    /*
002     * Copyright 2011 The Kuali Foundation.
003     * 
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     * http://www.opensource.org/licenses/ecl2.php
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.kfs.fp.document.service.impl;
017    
018    import java.io.File;
019    import java.io.IOException;
020    import java.io.OutputStream;
021    import java.util.HashMap;
022    import java.util.Iterator;
023    import java.util.List;
024    import java.util.Map;
025    
026    import org.apache.commons.lang.StringUtils;
027    import org.kuali.kfs.fp.businessobject.DisbursementVoucherDocumentationLocation;
028    import org.kuali.kfs.fp.businessobject.PaymentReasonCode;
029    import org.kuali.kfs.fp.businessobject.options.PaymentMethodValuesFinder;
030    import org.kuali.kfs.fp.document.DisbursementVoucherConstants;
031    import org.kuali.kfs.fp.document.DisbursementVoucherDocument;
032    import org.kuali.kfs.fp.document.service.DisbursementVoucherCoverSheetService;
033    import org.kuali.rice.kns.bo.PersistableBusinessObject;
034    import org.kuali.rice.kns.lookup.keyvalues.KeyValuesFinder;
035    import org.kuali.rice.kns.service.BusinessObjectService;
036    import org.kuali.rice.kns.service.ParameterEvaluator;
037    import org.kuali.rice.kns.service.ParameterService;
038    import org.kuali.rice.kns.service.PersistenceStructureService;
039    import org.kuali.rice.core.util.KeyLabelPair;
040    import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument;
041    
042    import com.lowagie.text.DocumentException;
043    import com.lowagie.text.pdf.AcroFields;
044    import com.lowagie.text.pdf.PdfReader;
045    import com.lowagie.text.pdf.PdfStamper;
046    
047    /**
048     * This is the default implementation of the DisbursementVoucherCoverSheetService interface.
049     */
050    public class DisbursementVoucherCoverSheetServiceImpl implements DisbursementVoucherCoverSheetService {
051        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DisbursementVoucherCoverSheetServiceImpl.class);
052    
053        private ParameterService parameterService;
054        private BusinessObjectService businessObjectService;
055        private PersistenceStructureService persistenceStructureService;
056    
057        /**
058         * This method uses the values provided to build and populate a cover sheet associated with a given DisbursementVoucher.
059         * 
060         * @param templateDirectory The directory where the cover sheet template can be found.
061         * @param templateName The name of the cover sheet template to be used to build the cover sheet.
062         * @param document The DisbursementVoucher the cover sheet will be populated from.
063         * @param outputStream The stream the cover sheet file will be written to.
064         * @see org.kuali.kfs.fp.document.service.DisbursementVoucherCoverSheetService#generateDisbursementVoucherCoverSheet(java.lang.String,
065         *      java.lang.String, org.kuali.kfs.fp.document.DisbursementVoucherDocument, java.io.OutputStream)
066         */
067        public void generateDisbursementVoucherCoverSheet(String templateDirectory, String templateName, DisbursementVoucherDocument document, OutputStream outputStream) throws DocumentException, IOException {
068            if (this.isCoverSheetPrintable(document)) {
069                String attachment = "";
070                String handling = "";
071                String alien = "";
072                String lines = "";
073                String bar = "";
074                String rlines = "";
075    
076                String docNumber = document.getDocumentNumber();
077                String initiator = document.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId();
078                String payee = document.getDvPayeeDetail().getDisbVchrPayeePersonName();
079    
080                String reason = ((PaymentReasonCode) retrieveObjectByKey(PaymentReasonCode.class, document.getDvPayeeDetail().getDisbVchrPaymentReasonCode())).getName();
081                String check_total = document.getDisbVchrCheckTotalAmount().toString();
082    
083                String currency = getValueForKey(new PaymentMethodValuesFinder(), document.getDisbVchrPaymentMethodCode());
084    
085                String address = retrieveAddress(document.getDisbursementVoucherDocumentationLocationCode());
086    
087                // retrieve attachment label
088                if (document.isDisbVchrAttachmentCode()) {
089                    attachment = parameterService.getParameterValue(DisbursementVoucherDocument.class, DisbursementVoucherConstants.DV_COVER_SHEET_TEMPLATE_ATTACHMENT_PARM_NM);
090                }
091                // retrieve handling label
092                if (document.isDisbVchrSpecialHandlingCode()) {
093                    handling = parameterService.getParameterValue(DisbursementVoucherDocument.class, DisbursementVoucherConstants.DV_COVER_SHEET_TEMPLATE_HANDLING_PARM_NM);
094                }
095                // retrieve data for alien payment code
096                if (document.getDvPayeeDetail().isDisbVchrAlienPaymentCode()) {
097                    String taxDocumentationLocationCode = parameterService.getParameterValue(DisbursementVoucherDocument.class, DisbursementVoucherConstants.TAX_DOCUMENTATION_LOCATION_CODE_PARM_NM);
098    
099                    address = retrieveAddress(taxDocumentationLocationCode);
100                    alien = parameterService.getParameterValue(DisbursementVoucherDocument.class, DisbursementVoucherConstants.DV_COVER_SHEET_TEMPLATE_ALIEN_PARM_NM);
101                    lines = parameterService.getParameterValue(DisbursementVoucherDocument.class, DisbursementVoucherConstants.DV_COVER_SHEET_TEMPLATE_LINES_PARM_NM);
102                }
103                
104                // determine if non-employee travel payment reasons
105                String paymentReasonCode = document.getDvPayeeDetail().getDisbVchrPaymentReasonCode();
106                ParameterEvaluator travelNonEmplPaymentReasonEvaluator = parameterService.getParameterEvaluator(DisbursementVoucherDocument.class, DisbursementVoucherConstants.NONEMPLOYEE_TRAVEL_PAY_REASONS_PARM_NM, paymentReasonCode);
107                boolean isTravelNonEmplPaymentReason = travelNonEmplPaymentReasonEvaluator.evaluationSucceeds();
108    
109                if (isTravelNonEmplPaymentReason) {
110                    bar = parameterService.getParameterValue(DisbursementVoucherDocument.class, DisbursementVoucherConstants.DV_COVER_SHEET_TEMPLATE_BAR_PARM_NM);
111                    rlines = parameterService.getParameterValue(DisbursementVoucherDocument.class, DisbursementVoucherConstants.DV_COVER_SHEET_TEMPLATE_RLINES_PARM_NM);
112                }
113    
114                try {
115                    PdfReader reader = new PdfReader(templateDirectory + templateName);
116    
117                    // populate form with document values
118                    PdfStamper stamper = new PdfStamper(reader, outputStream);
119    
120                    AcroFields populatedCoverSheet = stamper.getAcroFields();
121                    populatedCoverSheet.setField("initiator", initiator);
122                    populatedCoverSheet.setField("attachment", attachment);
123                    populatedCoverSheet.setField("currency", currency);
124                    populatedCoverSheet.setField("handling", handling);
125                    populatedCoverSheet.setField("alien", alien);
126                    populatedCoverSheet.setField("payee_name", payee);
127                    populatedCoverSheet.setField("check_total", check_total);
128                    populatedCoverSheet.setField("docNumber", docNumber);
129                    populatedCoverSheet.setField("payment_reason", reason);
130                    populatedCoverSheet.setField("destination_address", address);
131                    populatedCoverSheet.setField("lines", lines);
132                    populatedCoverSheet.setField("bar", bar);
133                    populatedCoverSheet.setField("rlines", rlines);
134    
135                    stamper.setFormFlattening(true);
136                    stamper.close();
137                }
138                catch (DocumentException e) {
139                    LOG.error("Error creating coversheet for: " + docNumber + ". ::" + e);
140                    throw e;
141                }
142                catch (IOException e) {
143                    LOG.error("Error creating coversheet for: " + docNumber + ". ::" + e);
144                    throw e;
145                }
146            }
147    
148        }
149    
150        /**
151         * @see org.kuali.kfs.fp.document.service.DisbursementVoucherCoverSheetService#isCoverSheetPrintable(org.kuali.kfs.fp.document.DisbursementVoucherDocument)
152         */
153        public boolean isCoverSheetPrintable(DisbursementVoucherDocument document) {
154            KualiWorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
155    
156            return !(workflowDocument.stateIsCanceled() || workflowDocument.stateIsInitiated() || workflowDocument.stateIsDisapproved() || workflowDocument.stateIsException() || workflowDocument.stateIsDisapproved() || workflowDocument.stateIsSaved());
157        }
158    
159        /**
160         * This method is used to retrieve business objects that have a single primary key field without hard-coding the key field name.
161         * 
162         * @param clazz The class type that will be used to retrieve the primary key field names.
163         * @param keyValue The primary key value to be used to lookup the object by.
164         * @return An instance of a business object matching the class type and primary key value given.
165         */
166        protected PersistableBusinessObject retrieveObjectByKey(Class clazz, String keyValue) {
167            List primaryKeyFields = persistenceStructureService.listPrimaryKeyFieldNames(clazz);
168            if (primaryKeyFields.size() != 1) {
169                throw new IllegalArgumentException("multi-part key found. expecting single key field for " + clazz.getName());
170            }
171            Map primaryKeys = new HashMap();
172            primaryKeys.put(primaryKeyFields.get(0), keyValue);
173            PersistableBusinessObject b = businessObjectService.findByPrimaryKey(clazz, primaryKeys);
174    
175            return b;
176        }
177    
178        /**
179         * This method is a helper method to retrieve values from a list based on a primary key provided.
180         * 
181         * @param keyValuesFinder KeyValuesFinder that the value will be retrieved from.
182         * @param key The key to the value being retrieved.
183         * @return The value associated with the key provided, or empty string if no value is found.
184         */
185        protected String getValueForKey(KeyValuesFinder keyValuesFinder, String key) {
186            for (Iterator i = keyValuesFinder.getKeyValues().iterator(); i.hasNext();) {
187                KeyLabelPair pair = (KeyLabelPair) i.next();
188                if (StringUtils.equals((String) pair.getKey(), key)) {
189                    return pair.getLabel();
190                }
191            }
192            return "";
193        }
194    
195        /**
196         * This method contains logic to determine the address the cover sheet should be sent to.
197         * 
198         * @param docLocCd A key used to retrieve the document location.
199         * @return The address the cover sheet will be sent to or empty string if no location is found.
200         */
201        protected String retrieveAddress(String docLocCd) {
202            String address = "";
203            try {
204                address = ((DisbursementVoucherDocumentationLocation) retrieveObjectByKey(DisbursementVoucherDocumentationLocation.class, docLocCd)).getDisbursementVoucherDocumentationLocationAddress();
205            }
206            catch (NullPointerException e) {
207                // ignored
208            }
209    
210            return address;
211        }
212    
213        // spring injected services
214    
215        /**
216         * Sets the businessObjectService attribute value.
217         * 
218         * @param businessObjectService The businessObjectService to set.
219         */
220        public void setBusinessObjectService(BusinessObjectService businessObjectService) {
221            this.businessObjectService = businessObjectService;
222        }
223    
224        /**
225         * Sets the persistenceStructureService attribute value.
226         * 
227         * @param persistenceStructureService The persistenceService to set.
228         */
229        public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
230            this.persistenceStructureService = persistenceStructureService;
231        }
232    
233        /**
234         * Sets the parameterService attribute value.
235         * 
236         * @param parameterService The parameterService to set.
237         */
238        public void setParameterService(ParameterService parameterService) {
239            this.parameterService = parameterService;
240        }
241    }