diff --git a/src/main/java/info/bukova/isspst/data/FileMetainfo.java b/src/main/java/info/bukova/isspst/data/FileMetainfo.java index c2697eef..f00b530d 100644 --- a/src/main/java/info/bukova/isspst/data/FileMetainfo.java +++ b/src/main/java/info/bukova/isspst/data/FileMetainfo.java @@ -1,12 +1,13 @@ package info.bukova.isspst.data; +import org.hibernate.annotations.Cascade; +import org.hibernate.annotations.CascadeType; import org.hibernate.search.annotations.Analyze; import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.Index; import org.hibernate.search.annotations.Indexed; import org.hibernate.search.annotations.IndexedEmbedded; -import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; @@ -29,8 +30,9 @@ public class FileMetainfo extends BaseData { @Column(name = "RECORD_ID") private int recordId; - @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) + @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "CONTENT_ID") + @Cascade(CascadeType.SAVE_UPDATE) @IndexedEmbedded private FileContent content; diff --git a/src/main/java/info/bukova/isspst/data/TripBill.java b/src/main/java/info/bukova/isspst/data/TripBill.java index b5dfae2e..cee4c8ac 100644 --- a/src/main/java/info/bukova/isspst/data/TripBill.java +++ b/src/main/java/info/bukova/isspst/data/TripBill.java @@ -1,9 +1,10 @@ package info.bukova.isspst.data; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import info.bukova.isspst.storage.EntityWithAttachment; +import org.hibernate.annotations.LazyCollection; +import org.hibernate.annotations.LazyCollectionOption; +import org.hibernate.search.annotations.Indexed; +import org.hibernate.search.annotations.IndexedEmbedded; import javax.persistence.CascadeType; import javax.persistence.Column; @@ -13,16 +14,15 @@ import javax.persistence.JoinColumn; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.Table; - -import org.hibernate.annotations.LazyCollection; -import org.hibernate.annotations.LazyCollectionOption; -import org.hibernate.search.annotations.Indexed; -import org.hibernate.search.annotations.IndexedEmbedded; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; @Entity @Table(name = "TRIP_BILL") @Indexed -public class TripBill extends BaseData { +public class TripBill extends BaseData implements EntityWithAttachment { @OneToOne(fetch = FetchType.EAGER) @JoinColumn(name = "REQUIREMENT_ID") @@ -47,13 +47,14 @@ public class TripBill extends BaseData { private BigDecimal downPayment; @Column(name = "TOTAL", precision = 15, scale = 4) private BigDecimal total; - @OneToMany + @OneToMany(cascade = CascadeType.ALL) @LazyCollection(LazyCollectionOption.TRUE) @IndexedEmbedded private List attachedFiles; public TripBill() { billItems = new ArrayList(); + attachedFiles = new ArrayList(); } public TripRequirement getRequirement() { @@ -132,6 +133,16 @@ public class TripBill extends BaseData { return attachedFiles; } + @Override + public void addAttachment(FileMetainfo metaInfo) { + attachedFiles.add(metaInfo); + } + + @Override + public void removeAttachment(FileMetainfo metainfo) { + attachedFiles.remove(metainfo); + } + public void setAttachedFiles(List attachedFiles) { this.attachedFiles = attachedFiles; } diff --git a/src/main/java/info/bukova/isspst/services/AbstractOwnedService.java b/src/main/java/info/bukova/isspst/services/AbstractOwnedService.java index 12c8d592..04df419b 100644 --- a/src/main/java/info/bukova/isspst/services/AbstractOwnedService.java +++ b/src/main/java/info/bukova/isspst/services/AbstractOwnedService.java @@ -1,7 +1,7 @@ package info.bukova.isspst.services; -import java.util.Date; - +import info.bukova.isspst.data.OwnedDataModel; +import info.bukova.isspst.data.User; import org.hibernate.NonUniqueResultException; import org.hibernate.Query; import org.springframework.security.access.prepost.PreAuthorize; @@ -9,8 +9,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.transaction.annotation.Transactional; -import info.bukova.isspst.data.OwnedDataModel; -import info.bukova.isspst.data.User; +import java.util.Date; public class AbstractOwnedService extends AbstractService { @@ -32,6 +31,7 @@ public class AbstractOwnedService extends AbstractServ entity.setModifiedBy(getLoggedInUser()); entity.setModified(new Date()); dao.modify(entity); + maintainStorrage(); } @Transactional diff --git a/src/main/java/info/bukova/isspst/services/AbstractService.java b/src/main/java/info/bukova/isspst/services/AbstractService.java index ff6bf9e5..3b633670 100644 --- a/src/main/java/info/bukova/isspst/services/AbstractService.java +++ b/src/main/java/info/bukova/isspst/services/AbstractService.java @@ -1,6 +1,5 @@ package info.bukova.isspst.services; -import static ch.lambdaj.Lambda.filter; import info.bukova.isspst.Module; import info.bukova.isspst.ModuleUtils; import info.bukova.isspst.SessionData; @@ -11,7 +10,15 @@ import info.bukova.isspst.data.NumberSeries; import info.bukova.isspst.filters.Filter; import info.bukova.isspst.reporting.Report; import info.bukova.isspst.services.numberseries.NumberSeriesService; +import info.bukova.isspst.storage.DocumentFileStorage; +import org.hibernate.NonUniqueResultException; +import org.hibernate.Query; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import javax.validation.ConstraintViolation; +import javax.validation.Validator; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -20,14 +27,7 @@ import java.util.Date; import java.util.List; import java.util.Set; -import javax.validation.ConstraintViolation; -import javax.validation.Validator; - -import org.hibernate.NonUniqueResultException; -import org.hibernate.Query; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.transaction.annotation.Transactional; +import static ch.lambdaj.Lambda.filter; public abstract class AbstractService implements Service { @@ -37,9 +37,14 @@ public abstract class AbstractService implements Service protected SessionData sessionData; @Autowired protected QueryDao queryDao; + private DocumentFileStorage documentFileStorage; private NumberSeriesService numberSeriesService; - + + + public void setDocumentFileStorage(DocumentFileStorage storage) { + this.documentFileStorage = storage; + } public NumberSeriesService getNumberSeriesService() { @@ -62,6 +67,12 @@ public abstract class AbstractService implements Service public String getDeleteEntityPermission() { return ""; } + + protected void maintainStorrage() { + if (documentFileStorage != null) { + documentFileStorage.purge(); + } + } @Override @PreAuthorize("hasPermission(this, 'PERM_ADD')") @@ -101,6 +112,7 @@ public abstract class AbstractService implements Service validate(entity); entity.setModified(new Date()); dao.modify(entity); + maintainStorrage(); } @Override @@ -114,8 +126,10 @@ public abstract class AbstractService implements Service if (getModule() != null && !getModule().isActive()) { throw new ModuleNotActiveException(); } - + dao.delete(entity); + + maintainStorrage(); // poklidit přiložené soubory } @Override diff --git a/src/main/java/info/bukova/isspst/services/tripbill/TripBillServiceImpl.java b/src/main/java/info/bukova/isspst/services/tripbill/TripBillServiceImpl.java index 1c6bcca2..22192aa7 100644 --- a/src/main/java/info/bukova/isspst/services/tripbill/TripBillServiceImpl.java +++ b/src/main/java/info/bukova/isspst/services/tripbill/TripBillServiceImpl.java @@ -7,13 +7,7 @@ import info.bukova.isspst.data.TripRequirement; import info.bukova.isspst.services.AbstractOwnedService; import info.bukova.isspst.services.LazyLoader; import info.bukova.isspst.services.settings.GlobalSettingsService; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.List; - +import org.hibernate.Hibernate; import org.hibernate.LazyInitializationException; import org.hibernate.Query; import org.joda.time.DateTime; @@ -24,6 +18,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.List; + public class TripBillServiceImpl extends AbstractOwnedService implements TripBillService { @@ -80,6 +80,14 @@ public class TripBillServiceImpl extends AbstractOwnedService implemen } } + @Transactional + @LazyLoader("form") + public void loadAttachments(TripBill entity) { + TripBill e = dao.getById(entity.getId()); + Hibernate.initialize(e.getAttachedFiles()); + entity.setAttachedFiles(e.getAttachedFiles()); + } + @Override public void calculate(TripBill bill) { bill.setTotal(BigDecimal.ZERO); diff --git a/src/main/java/info/bukova/isspst/storage/DocumentFileStorage.java b/src/main/java/info/bukova/isspst/storage/DocumentFileStorage.java index 6dcaf0e4..28a0360a 100644 --- a/src/main/java/info/bukova/isspst/storage/DocumentFileStorage.java +++ b/src/main/java/info/bukova/isspst/storage/DocumentFileStorage.java @@ -61,6 +61,12 @@ public interface DocumentFileStorage extends FileStorage { * * @param entity Entita s přílohami */ - public void removaAllAttachments(EntityWithAttachment entity); + public void removeAllAttachments(EntityWithAttachment entity); + + /** + * Uklidí soubory, na které neexistuje reference v databázi a z tabulky FILE_CONTENTS vymaže záznamy, na které + * neexistuje refernece z FILE_METAINFO + */ + public void purge(); } diff --git a/src/main/java/info/bukova/isspst/storage/DocumentFileStorageImpl.java b/src/main/java/info/bukova/isspst/storage/DocumentFileStorageImpl.java index 91e5d08c..aea5e78c 100644 --- a/src/main/java/info/bukova/isspst/storage/DocumentFileStorageImpl.java +++ b/src/main/java/info/bukova/isspst/storage/DocumentFileStorageImpl.java @@ -6,6 +6,7 @@ import info.bukova.isspst.services.fulltext.Extractor; import info.bukova.isspst.services.fulltext.ExtractorFactory; import org.apache.commons.codec.binary.Hex; import org.hibernate.Query; +import org.hibernate.SQLQuery; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; @@ -173,7 +174,7 @@ public class DocumentFileStorageImpl extends AbstractFileStorage i } private List infosForPath(String path) { - Query q = queryDao.getQuery("from FileMetainfo info where info.pathInFilesystem = :path"); + Query q = queryDao.getQuery("from FileMetainfo info where info.content.pathInFilesystem = :path"); q.setString("path", path); return q.list(); @@ -224,11 +225,37 @@ public class DocumentFileStorageImpl extends AbstractFileStorage i @Override @Transactional - public void removaAllAttachments(EntityWithAttachment entity) { + public void removeAllAttachments(EntityWithAttachment entity) { for (FileMetainfo metaInfo : entity.getAttachedFiles()) { removeFile(metaInfo); } entity.getAttachedFiles().clear(); } + + @Override + @Transactional + public void purge() { + File folder = new File(rootPath); + File[] allFiles = folder.listFiles(); + Query q = queryDao.getQuery("from FileMetainfo"); + List infos = q.list(); + + for (File f : allFiles) { + boolean fileExists = false; + + for (FileMetainfo info : infos) { + if (info.getContent().getPathInFilesystem().equals(f.getName())) { + fileExists = true; + } + } + + if (!fileExists && f.isFile()) { + f.delete(); + } + } + + SQLQuery sql = queryDao.getSession().createSQLQuery("delete from file_contents where id not in(select CONTENT_ID from file_metainfo)"); + sql.executeUpdate(); + } } diff --git a/src/main/java/info/bukova/isspst/ui/FormWithUpload.java b/src/main/java/info/bukova/isspst/ui/FormWithUpload.java new file mode 100644 index 00000000..4c543d16 --- /dev/null +++ b/src/main/java/info/bukova/isspst/ui/FormWithUpload.java @@ -0,0 +1,72 @@ +package info.bukova.isspst.ui; + +import info.bukova.isspst.data.DataModel; +import info.bukova.isspst.data.FileMetainfo; +import info.bukova.isspst.storage.DocumentFileStorage; +import info.bukova.isspst.storage.EntityWithAttachment; +import org.zkoss.bind.annotation.BindingParam; +import org.zkoss.bind.annotation.Command; +import org.zkoss.bind.annotation.ContextParam; +import org.zkoss.bind.annotation.ContextType; +import org.zkoss.bind.annotation.Init; +import org.zkoss.bind.annotation.NotifyChange; +import org.zkoss.zk.ui.event.UploadEvent; +import org.zkoss.zk.ui.select.annotation.WireVariable; +import org.zkoss.zul.Filedownload; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Pepa Rokos + */ +public class FormWithUpload extends FormViewModel { + + private List attachments; + private List forDelete; + @WireVariable + private DocumentFileStorage documentStorage; + + @Init(superclass = true) + public void initFormWithUpload() { + if (getDataBean() instanceof EntityWithAttachment) { + attachments = ((EntityWithAttachment)getDataBean()).getAttachedFiles(); + } + forDelete = new ArrayList(); // kolekce příloh na smazání v případě uložení záznamu + } + + @Command + @NotifyChange("attachments") + public void uploadAttachment(@ContextParam(ContextType.TRIGGER_EVENT) UploadEvent upEvent) { + FileMetainfo metaInfo = documentStorage.saveAndCreateInfo(upEvent.getMedia().getByteData(), + upEvent.getMedia().getName()); + + ((EntityWithAttachment)getDataBean()).addAttachment(metaInfo); + } + + @Command + @NotifyChange("attachments") + public void deleteAttachment(@BindingParam("attachment") FileMetainfo metaInfo) { + ((EntityWithAttachment)getDataBean()).removeAttachment(metaInfo); + forDelete.add(metaInfo); // smazat až v případě uložení záznamu + } + + @Command + public void downloadAttachment(@BindingParam("attachment") FileMetainfo metaInfo) { + Filedownload.save(documentStorage.fileData(metaInfo), metaInfo.getContentType(), metaInfo.getFileName()); + } + + public List getAttachments() { + return attachments; + } + + @Override + protected void doSave() { + for (FileMetainfo info : forDelete) { + documentStorage.removeFile(info); + } + + super.doSave(); + } + +} diff --git a/src/main/java/info/bukova/isspst/ui/requirement/TripRequirementForm.java b/src/main/java/info/bukova/isspst/ui/requirement/TripRequirementForm.java index f3206d4c..7420bf1b 100644 --- a/src/main/java/info/bukova/isspst/ui/requirement/TripRequirementForm.java +++ b/src/main/java/info/bukova/isspst/ui/requirement/TripRequirementForm.java @@ -1,23 +1,26 @@ package info.bukova.isspst.ui.requirement; -import info.bukova.isspst.data.*; +import info.bukova.isspst.data.SettingsData; +import info.bukova.isspst.data.TripRequirement; +import info.bukova.isspst.data.User; +import info.bukova.isspst.data.Workgroup; import info.bukova.isspst.services.requirement.RequirementTypeService; import info.bukova.isspst.services.requirement.TripRequirementService; import info.bukova.isspst.services.settings.GlobalSettingsService; import info.bukova.isspst.services.users.UserService; import info.bukova.isspst.services.workgroups.WorkgroupService; import info.bukova.isspst.storage.DocumentFileStorage; -import info.bukova.isspst.ui.FormViewModel; +import info.bukova.isspst.ui.FormWithUpload; import info.bukova.isspst.validators.TripRequirementFormValidator; -import org.zkoss.bind.annotation.*; -import org.zkoss.zk.ui.event.UploadEvent; +import org.zkoss.bind.annotation.BindingParam; +import org.zkoss.bind.annotation.Command; +import org.zkoss.bind.annotation.Init; +import org.zkoss.bind.annotation.NotifyChange; import org.zkoss.zk.ui.select.annotation.WireVariable; -import org.zkoss.zul.Filedownload; -import java.util.ArrayList; import java.util.List; -public class TripRequirementForm extends FormViewModel { +public class TripRequirementForm extends FormWithUpload { @WireVariable private UserService userService; @@ -34,8 +37,6 @@ public class TripRequirementForm extends FormViewModel { private List centres; private List users; private List passengers; - private List attachments; - private List forDelete; private User selUser; private TripRequirementFormValidator validator; @@ -45,8 +46,6 @@ public class TripRequirementForm extends FormViewModel { centres = reqTypeService.filterCentres(getDataBean().getType(), workgroupService.getUserCentres(userService.getCurrent())); users = userService.getUsersForCombo(); passengers = getDataBean().getPassengers(); - attachments = getDataBean().getAttachedFiles(); - forDelete = new ArrayList(); // kolekce příloh na smazání v případě uložení záznamu validator = new TripRequirementFormValidator(); } @@ -90,37 +89,4 @@ public class TripRequirementForm extends FormViewModel { return passengers; } - @Command - @NotifyChange("attachments") - public void uploadAttachment(@ContextParam(ContextType.TRIGGER_EVENT) UploadEvent upEvent) { - FileMetainfo metaInfo = documentStorage.saveAndCreateInfo(upEvent.getMedia().getByteData(), - upEvent.getMedia().getName()); - - getDataBean().addAttachment(metaInfo); - } - - @Command - @NotifyChange("attachments") - public void deleteAttachment(@BindingParam("attachment") FileMetainfo metaInfo) { - getDataBean().removeAttachment(metaInfo); - forDelete.add(metaInfo); // smazat až v případě uložení záznamu - } - - @Command - public void downloadAttachment(@BindingParam("attachment") FileMetainfo metaInfo) { - Filedownload.save(documentStorage.fileData(metaInfo), metaInfo.getContentType(), metaInfo.getFileName()); - } - - public List getAttachments() { - return attachments; - } - - @Override - protected void doSave() { - for (FileMetainfo info : forDelete) { - documentStorage.removeFile(info); - } - - super.doSave(); - } } diff --git a/src/main/java/info/bukova/isspst/ui/tripbill/TripBillForm.java b/src/main/java/info/bukova/isspst/ui/tripbill/TripBillForm.java index 3cfa8049..fcfe8c75 100644 --- a/src/main/java/info/bukova/isspst/ui/tripbill/TripBillForm.java +++ b/src/main/java/info/bukova/isspst/ui/tripbill/TripBillForm.java @@ -4,17 +4,16 @@ import info.bukova.isspst.data.TripBill; import info.bukova.isspst.data.Vehicle; import info.bukova.isspst.services.settings.GlobalSettingsService; import info.bukova.isspst.services.tripbill.TripBillService; -import info.bukova.isspst.ui.FormViewModel; - -import java.util.ArrayList; -import java.util.List; - +import info.bukova.isspst.ui.FormWithUpload; import org.zkoss.bind.annotation.Command; import org.zkoss.bind.annotation.Init; import org.zkoss.bind.annotation.NotifyChange; import org.zkoss.zk.ui.select.annotation.WireVariable; -public class TripBillForm extends FormViewModel { +import java.util.ArrayList; +import java.util.List; + +public class TripBillForm extends FormWithUpload { @WireVariable private TripBillService tripBillService; diff --git a/src/main/webapp/WEB-INF/spring/root-context.xml b/src/main/webapp/WEB-INF/spring/root-context.xml index 558f9e61..9bce01b1 100644 --- a/src/main/webapp/WEB-INF/spring/root-context.xml +++ b/src/main/webapp/WEB-INF/spring/root-context.xml @@ -422,11 +422,13 @@ + + diff --git a/src/main/webapp/app/uploadComponents.zul b/src/main/webapp/app/uploadComponents.zul new file mode 100644 index 00000000..fafb5200 --- /dev/null +++ b/src/main/webapp/app/uploadComponents.zul @@ -0,0 +1,37 @@ + + + + + + +