001    /**
002     * Copyright 2005-2014 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.rice.kns.document;
017    
018    import org.apache.commons.codec.digest.DigestUtils;
019    import org.apache.commons.collections.CollectionUtils;
020    import org.apache.commons.lang.StringUtils;
021    import org.apache.struts.upload.FormFile;
022    import org.kuali.rice.kns.maintenance.Maintainable;
023    import org.kuali.rice.krad.bo.DocumentAttachment;
024    import org.kuali.rice.krad.bo.MultiDocumentAttachment;
025    import org.kuali.rice.krad.bo.PersistableAttachment;
026    import org.kuali.rice.krad.bo.PersistableAttachmentBase;
027    import org.kuali.rice.krad.bo.PersistableAttachmentList;
028    import org.kuali.rice.krad.bo.PersistableBusinessObject;
029    import org.kuali.rice.krad.service.BusinessObjectSerializerService;
030    import org.kuali.rice.krad.service.KRADServiceLocator;
031    import org.kuali.rice.krad.util.ObjectUtils;
032    
033    import javax.persistence.Transient;
034    import java.io.FileNotFoundException;
035    import java.io.IOException;
036    import java.lang.reflect.Method;
037    import java.util.ArrayList;
038    import java.util.Collections;
039    import java.util.HashMap;
040    import java.util.List;
041    import java.util.Map;
042    
043    /**
044     * @author Kuali Rice Team (rice.collab@kuali.org)
045     *
046     * @deprecated Use {@link org.kuali.rice.krad.maintenance.MaintenanceDocumentBase}.
047     */
048    @Deprecated
049    public class MaintenanceDocumentBase extends org.kuali.rice.krad.maintenance.MaintenanceDocumentBase implements MaintenanceDocument {
050        private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(MaintenanceDocumentBase.class);
051    
052        @Transient
053        protected transient FormFile fileAttachment;
054    
055        public MaintenanceDocumentBase() {
056            super();
057        }
058    
059        public MaintenanceDocumentBase(String documentTypeName) {
060            super(documentTypeName);
061        }
062    
063        @Override
064        public PersistableBusinessObject getDocumentBusinessObject() {
065            return (PersistableBusinessObject) super.getDocumentDataObject();
066        }
067    
068        /**
069         * Checks old maintainable bo has key values
070         */
071        public boolean isOldBusinessObjectInDocument() {
072            boolean isOldBusinessObjectInExistence = false;
073            if (getOldMaintainableObject() == null || getOldMaintainableObject().getBusinessObject() == null) {
074                isOldBusinessObjectInExistence = false;
075            } else {
076                isOldBusinessObjectInExistence = getOldMaintainableObject().isOldBusinessObjectInDocument();
077            }
078            return isOldBusinessObjectInExistence;
079        }
080    
081        public Maintainable getNewMaintainableObject() {
082            return (Maintainable) newMaintainableObject;
083        }
084    
085        public Maintainable getOldMaintainableObject() {
086            return (Maintainable) oldMaintainableObject;
087        }
088    
089        public FormFile getFileAttachment() {
090            return this.fileAttachment;
091        }
092    
093        public void setFileAttachment(FormFile fileAttachment) {
094            this.fileAttachment = fileAttachment;
095        }
096    
097        @Override
098        public void populateDocumentAttachment() {
099            refreshAttachment();
100    
101            if (fileAttachment != null && StringUtils.isNotEmpty(fileAttachment.getFileName())) {
102                //Populate DocumentAttachment BO
103                if (attachment == null) {
104                    attachment = new DocumentAttachment();
105                }
106    
107                byte[] fileContents;
108                try {
109                    fileContents = fileAttachment.getFileData();
110                    if (fileContents.length > 0) {
111                        attachment.setFileName(fileAttachment.getFileName());
112                        attachment.setContentType(fileAttachment.getContentType());
113                        attachment.setAttachmentContent(fileAttachment.getFileData());
114                        PersistableAttachment boAttachment = (PersistableAttachment) newMaintainableObject.getDataObject();
115                        boAttachment.setAttachmentContent(null);
116                        attachment.setDocumentNumber(getDocumentNumber());
117                    }
118                } catch (FileNotFoundException e) {
119                    LOG.error("Error while populating the Document Attachment", e);
120                    throw new RuntimeException("Could not populate DocumentAttachment object", e);
121                } catch (IOException e) {
122                    LOG.error("Error while populating the Document Attachment", e);
123                    throw new RuntimeException("Could not populate DocumentAttachment object", e);
124                }
125            } else {
126                //fileAttachment isn't filled, populate from bo if it exists
127                PersistableAttachment boAttachment = (PersistableAttachment) newMaintainableObject.getDataObject();
128                if (attachment == null
129                        && boAttachment != null
130                        && boAttachment.getAttachmentContent() != null) {
131                    DocumentAttachment newAttachment = new DocumentAttachment();
132                    newAttachment.setDocumentNumber(getDocumentNumber());
133                    newAttachment.setAttachmentContent(boAttachment.getAttachmentContent());
134                    newAttachment.setContentType(boAttachment.getContentType());
135                    newAttachment.setFileName(boAttachment.getFileName());
136                    //null out boAttachment file, will be copied back before final save.
137                    boAttachment.setAttachmentContent(null);
138                    attachment = newAttachment;
139                }
140            }
141        }
142    
143        @Override
144        public void populateAttachmentForBO() {
145            refreshAttachment();
146    
147            PersistableAttachment boAttachment = (PersistableAttachment) newMaintainableObject.getDataObject();
148    
149            if (ObjectUtils.isNotNull(getAttachmentPropertyName())) {
150                    String attachmentPropNm = getAttachmentPropertyName();
151                    String attachmentPropNmSetter = "get" + attachmentPropNm.substring(0, 1).toUpperCase() + attachmentPropNm.substring(1, attachmentPropNm.length());
152                    FormFile attachmentFromBusinessObject;
153    
154                    if((boAttachment.getFileName() == null) && (boAttachment instanceof PersistableAttachment)) {
155                            try {
156                                    Method[] methods = boAttachment.getClass().getMethods();
157                                    for (Method method : methods) {
158                                            if (method.getName().equals(attachmentPropNmSetter)) {
159                                                    attachmentFromBusinessObject =  (FormFile)(boAttachment.getClass().getDeclaredMethod(attachmentPropNmSetter).invoke(boAttachment));
160                                                    if (attachmentFromBusinessObject != null) {
161                                                            //boAttachment.setAttachmentContent(attachmentFromBusinessObject.getFileData());
162                                                            boAttachment.setFileName(attachmentFromBusinessObject.getFileName());
163                                                            boAttachment.setContentType(attachmentFromBusinessObject.getContentType());
164                                                    }
165                                                    break;
166                                            }
167                                    }
168                       } catch (Exception e) {
169                                    LOG.error("Not able to get the attachment " + e.getMessage());
170                                    throw new RuntimeException("Not able to get the attachment " + e.getMessage());
171                       }
172              }
173          }
174    
175          if((boAttachment.getFileName() == null) && (boAttachment instanceof PersistableAttachment) && (attachment != null)) {
176              //byte[] fileContents;
177              //fileContents = attachment.getAttachmentContent();
178              if (attachment.getFileName() != null) {
179                  boAttachment.setAttachmentContent(null);
180                  boAttachment.setFileName(attachment.getFileName());
181                  boAttachment.setContentType(attachment.getContentType());
182              }
183           }
184        }
185    
186        @Override
187        public void populateAttachmentBeforeSave() {
188            PersistableAttachment boAttachment = (PersistableAttachment) newMaintainableObject.getDataObject();
189            if (attachment != null
190                    && attachment.getAttachmentContent() != null) {
191                boAttachment.setAttachmentContent(attachment.getAttachmentContent());
192            } else {
193                boAttachment.setAttachmentContent(null);
194                boAttachment.setFileName(null);
195                boAttachment.setContentType(null);
196            }
197        }
198    
199        @Override
200        public void populateBoAttachmentListBeforeSave() {
201    
202            PersistableAttachmentList<PersistableAttachment> boAttachments = (PersistableAttachmentList<PersistableAttachment>) newMaintainableObject.getDataObject();
203            if (CollectionUtils.isEmpty(attachments)) {
204                //there are no attachments.  Clear out Bo Attachments
205                boAttachments.setAttachments(Collections.<PersistableAttachment>emptyList());
206                return;
207            }
208            Map<String, MultiDocumentAttachment> files = new HashMap<String, MultiDocumentAttachment>();
209            for (MultiDocumentAttachment multiAttach : attachments) {
210                String key = new StringBuffer(multiAttach.getFileName()).append("|").append(multiAttach.getContentType()).toString();
211                files.put(key, multiAttach);
212            }
213    
214    
215            //want to just copy over file if possible, as there can be other fields that are not on PersistableAttachment
216            //these arrays should be somewhat synched by the other populate methods
217            if (CollectionUtils.isNotEmpty(boAttachments.getAttachments())) {
218                for (PersistableAttachment attach : boAttachments.getAttachments()) {
219                    //try to get a new instance of the correct object...
220                    String key = new StringBuffer(attach.getFileName()).append("|").append(attach.getContentType()).toString();
221                    if (files.containsKey(key)) {
222                        attach.setAttachmentContent(files.get(key).getAttachmentContent());
223                        files.remove(key);
224                    }
225                }
226            }
227        }
228    
229        @Override
230        public void populateAttachmentListForBO() {
231            refreshAttachmentList();
232    
233            PersistableAttachmentList<PersistableAttachment> boAttachments = (PersistableAttachmentList<PersistableAttachment>) newMaintainableObject.getDataObject();
234    
235            if (ObjectUtils.isNotNull(getAttachmentListPropertyName())) {
236                //String collectionName = getAttachmentCollectionName();
237                String attachmentPropNm = getAttachmentListPropertyName();
238                String attachmentPropNmSetter = "get" + attachmentPropNm.substring(0, 1).toUpperCase() + attachmentPropNm.substring(1, attachmentPropNm.length());
239    
240    
241                for (PersistableAttachment persistableAttachment : boAttachments.getAttachments()) {
242                    if((persistableAttachment.getFileName() == null)) {
243                        try {
244                            FormFile attachmentFromBusinessObject =  (FormFile)(persistableAttachment.getClass().getDeclaredMethod(attachmentPropNmSetter).invoke(persistableAttachment));
245                            if (attachmentFromBusinessObject != null) {
246                                //persistableAttachment.setAttachmentContent(
247                                //        attachmentFromBusinessObject.getFileData());
248                                persistableAttachment.setFileName(attachmentFromBusinessObject.getFileName());
249                                persistableAttachment.setContentType(attachmentFromBusinessObject.getContentType());
250                            }
251                        } catch (Exception e) {
252                            LOG.error("Not able to get the attachment " + e.getMessage());
253                            throw new RuntimeException("Not able to get the attachment " + e.getMessage());
254                        }
255                    }
256                }
257            }
258            if((CollectionUtils.isEmpty(boAttachments.getAttachments())
259                    && (CollectionUtils.isNotEmpty(attachments)))) {
260    
261                List<PersistableAttachment> attachmentList = new ArrayList<PersistableAttachment>();
262                for (MultiDocumentAttachment multiAttach : attachments) {
263    
264                    //try to get a new instance of the correct object...
265                    if (multiAttach.getAttachmentContent().length > 0) {
266                        PersistableAttachment persistableAttachment = convertDocToBoAttachment(multiAttach, false);
267                        attachmentList.add(persistableAttachment);
268                    }
269                }
270                boAttachments.setAttachments(attachmentList);
271            }
272        }
273    
274        private PersistableAttachment convertDocToBoAttachment(MultiDocumentAttachment multiAttach, boolean copyFile) {
275            PersistableAttachment persistableAttachment = new PersistableAttachmentBase();
276    
277            if (copyFile
278                    && multiAttach.getAttachmentContent() != null) {
279                persistableAttachment.setAttachmentContent(multiAttach.getAttachmentContent());
280            }
281            persistableAttachment.setFileName(multiAttach.getFileName());
282            persistableAttachment.setContentType(multiAttach.getContentType());
283            return persistableAttachment;
284        }
285    
286        @Override
287        public void populateDocumentAttachmentList() {
288            refreshAttachmentList();
289    
290            String attachmentPropNm = getAttachmentListPropertyName();
291            String attachmentPropNmSetter = "get" + attachmentPropNm.substring(0, 1).toUpperCase() + attachmentPropNm.substring(1, attachmentPropNm.length());
292            //don't have form fields to use to fill, but they should be populated on the DataObject.  grab them from there.
293            PersistableAttachmentList<PersistableAttachment> boAttachmentList = (PersistableAttachmentList<PersistableAttachment>) newMaintainableObject.getDataObject();
294    
295            if (CollectionUtils.isNotEmpty(boAttachmentList.getAttachments())) {
296    
297    
298                //build map for comparison
299                Map<String, MultiDocumentAttachment> md5Hashes = new HashMap<String, MultiDocumentAttachment>();
300                if (CollectionUtils.isNotEmpty(attachments)) {
301                    for (MultiDocumentAttachment currentAttachment : attachments) {
302                        md5Hashes.put(DigestUtils.md5Hex(currentAttachment.getAttachmentContent()), currentAttachment);
303                    }
304                }
305    
306                //Populate DocumentAttachment BO
307                attachments = new ArrayList<MultiDocumentAttachment>();
308    
309                for (PersistableAttachment persistableAttachment : boAttachmentList.getAttachments()) {
310                    try {
311                        FormFile attachmentFromBusinessObject =  (FormFile)(persistableAttachment.getClass().getDeclaredMethod(attachmentPropNmSetter).invoke(persistableAttachment));
312                        if (attachmentFromBusinessObject != null) {
313                            //
314                            //byte[] fileContents = attachmentFromBusinessObject.getFileData();
315                            String md5Hex = DigestUtils.md5Hex(attachmentFromBusinessObject.getInputStream());
316                            if (md5Hashes.containsKey(md5Hex)) {
317                                String newFileName = attachmentFromBusinessObject.getFileName();
318                                MultiDocumentAttachment multiAttach = md5Hashes.get(md5Hex);
319                                if (multiAttach.getFileName().equals(newFileName)) {
320                                    attachments.add(multiAttach);
321                                } else {
322                                    multiAttach.setFileName(attachmentFromBusinessObject.getFileName());
323                                    multiAttach.setContentType(attachmentFromBusinessObject.getContentType());
324                                    attachments.add(multiAttach);
325                                }
326                                md5Hashes.remove(md5Hex);
327                            } else {
328                                MultiDocumentAttachment attach = new MultiDocumentAttachment();
329                                attach.setFileName(attachmentFromBusinessObject.getFileName());
330                                attach.setContentType(attachmentFromBusinessObject.getContentType());
331                                attach.setAttachmentContent(attachmentFromBusinessObject.getFileData());
332                                attach.setDocumentNumber(getDocumentNumber());
333                                attachments.add(attach);
334                            }
335                        } else {
336                            if (persistableAttachment.getFileName() != null
337                                    && persistableAttachment.getAttachmentContent() != null) {
338                                MultiDocumentAttachment attach = new MultiDocumentAttachment();
339                                attach.setFileName(persistableAttachment.getFileName());
340                                attach.setContentType(persistableAttachment.getContentType());
341                                attach.setAttachmentContent(persistableAttachment.getAttachmentContent());
342                                attach.setDocumentNumber(getDocumentNumber());
343    
344                                //set Bo's content to null
345                                persistableAttachment.setAttachmentContent(null);
346                                attachments.add(attach);
347                            }
348                        }
349                    } catch (Exception e) {
350                        LOG.error("Not able to get the attachment " + e.getMessage());
351                        throw new RuntimeException("Not able to get the attachment " + e.getMessage());
352                    }
353                }
354    
355            }
356        }
357    
358        /**
359         * {@inheritDoc}
360         */
361        @Override
362        protected BusinessObjectSerializerService getBusinessObjectSerializerService() {
363            return KRADServiceLocator.getBusinessObjectSerializerService();
364        }
365    
366    }