/* * Copyright (C) 2014 GG-Net GmbH - Oliver Günther * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package eu.ggnet.dwoss.redtape.dossier; import eu.ggnet.dwoss.rules.DocumentType; import eu.ggnet.dwoss.rules.PaymentMethod; import java.awt.Dialog; import java.awt.event.ActionEvent; import java.util.*; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.regex.PatternSyntaxException; import javax.swing.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import eu.ggnet.saft.core.Client; import eu.ggnet.saft.core.Workspace; import eu.ggnet.dwoss.customer.api.CustomerService; import eu.ggnet.dwoss.redtape.RedTapeAgent; import eu.ggnet.dwoss.redtape.entity.Document; import eu.ggnet.dwoss.redtape.entity.Document.Condition; import eu.ggnet.dwoss.redtape.entity.Document.Directive; import eu.ggnet.dwoss.redtape.entity.Dossier; import eu.ggnet.dwoss.redtape.RedTapeUiUtil; import eu.ggnet.dwoss.common.DwOssCore; import eu.ggnet.dwoss.util.HtmlDialog; import eu.ggnet.dwoss.util.table.PojoFilter; import static eu.ggnet.saft.core.Client.lookup; /** * @author bastian.venz * @author oliver.guenther * @author pascal.perau */ public class DossierFilterController { protected class DossierFilter implements PojoFilter<Dossier> { private boolean isDossierId; private boolean isDirective; private boolean isConditions; private String dossierId = ""; private boolean shouldSysCustomer; private boolean shouldNormalCustomer; private boolean isBookingClosed; private boolean isExactlyBriefed; private boolean isNotBookingClosed; private boolean isNotExactlyBriefed; private boolean isType; private boolean isPaymentMethod; private PaymentMethod paymentMethod = null; private DocumentType type = null; private Directive directive = null; private boolean inverse; private boolean inverseType; private EnumSet<Condition> conditions = EnumSet.noneOf(Condition.class); private final List<Long> systemCustomerIds; public DossierFilter(List<Long> systemCustomerIds) { this.systemCustomerIds = systemCustomerIds; } @Override public boolean filter(Dossier dossier) { //Collect Data Set<Condition> docConditions = new HashSet<>(); for (Document doc : dossier.getActiveDocuments()) { docConditions.addAll(doc.getConditions()); } Document activeDocument = null; for (Document document : dossier.getActiveDocuments()) { if ( document.getDirective() != Directive.NONE ) activeDocument = dossier.getActiveDocuments(document.getType()).get(0); } if ( !dossier.getActiveDocuments(DocumentType.INVOICE).isEmpty() ) { activeDocument = dossier.getActiveDocuments(DocumentType.INVOICE).get(0); } else { activeDocument = dossier.getActiveDocuments().get(dossier.getActiveDocuments().size() - 1); } //Apply Filter boolean isApply; try { isApply = !isDossierId || dossier.getIdentifier().matches("(?i).*" + dossierId + ".*"); } catch (PatternSyntaxException e) { isApply = !isDossierId; } isApply &= !isDirective || dossier.getCrucialDirective() == directive; isApply &= !isConditions || inverse ^ docConditions.containsAll(conditions); if ( shouldSysCustomer && !shouldNormalCustomer ) { isApply &= systemCustomerIds.contains(dossier.getCustomerId()); } else if ( !shouldSysCustomer && shouldNormalCustomer ) { isApply &= !systemCustomerIds.contains(dossier.getCustomerId()); } if ( isBookingClosed && !isNotBookingClosed ) { isApply &= dossier.isClosed(); } else if ( !isBookingClosed && isNotBookingClosed ) { isApply &= !dossier.isClosed(); } if ( isExactlyBriefed && !isNotExactlyBriefed ) { isApply &= activeDocument.getFlags().contains(Document.Flag.CUSTOMER_BRIEFED); } else if ( !isExactlyBriefed && isNotExactlyBriefed ) { isApply &= !activeDocument.getFlags().contains(Document.Flag.CUSTOMER_BRIEFED); } if ( type == DocumentType.ORDER ) isApply &= !isType || inverseType ^ dossier.getActiveDocuments(DocumentType.INVOICE).isEmpty(); else isApply &= !isType || inverseType ^ !dossier.getActiveDocuments(type).isEmpty(); isApply &= !isPaymentMethod || dossier.getPaymentMethod().equals(paymentMethod); return isApply; } } private class DossierLoader extends SwingWorker<Void, Dossier> { private final Logger L = LoggerFactory.getLogger(this.getClass()); @Override protected Void doInBackground() throws Exception { view.progressBar.setIndeterminate(true); List<Dossier> foundDossiers; int amount = 10; int last = nextToLoad; do { L.debug("loading dossiers from {} to {}", last, amount); foundDossiers = lookup(RedTapeAgent.class).findAllEagerDescending(last, amount); last += amount; publish(foundDossiers.toArray(new Dossier[0])); L.debug("T({}) published: {}", Thread.currentThread().getName(), identifiers(foundDossiers)); } while (last < (nextToLoad + 100) && !isCancelled()); L.debug("T({}) is complete", Thread.currentThread().getName()); return null; } @Override protected void process(List<Dossier> dossiers) { if ( isCancelled() ) return; for (Dossier dossier : dossiers) { model.add(dossier); } L.debug("processed: {}", identifiers(dossiers)); } @Override protected void done() { try { get(); view.progressBar.setIndeterminate(false); } catch (CancellationException ex) { // Do nothing, normal cancel. } catch (ExecutionException | InterruptedException ex) { DwOssCore.show(lookup(Workspace.class).getMainFrame(), ex); } } private List<String> identifiers(List<Dossier> dossiers) { List<String> result = new ArrayList<>(); for (Dossier dossier : dossiers) { result.add("(id=" + dossier.getId() + "," + dossier.getIdentifier() + ")"); } return result; } }; private final DossierFilter filter = new DossierFilter(Client.lookup(CustomerService.class).allSystemCustomerIds()); private DossierFilterModel model; private DossierFilterView view; private final List<Dossier> dossiers = new ArrayList<>(); private DossierLoader dossierLoader; private int nextToLoad = 0; public void setView(DossierFilterView view) { this.view = view; setAvaibleConditionsButtons(); } public void setModel(final DossierFilterModel model) { this.model = model; this.model.setFilter(filter); for (Dossier dossier : dossiers) { this.model.add(dossier); } restartDossierLoader(); } public void filterDossierId(String id, boolean enable) { filter.dossierId = id; filter.isDossierId = enable; model.fireTableDataChanged(); } public void filterDirective(Directive d, boolean enable) { filter.directive = d; filter.isDirective = enable; model.fireTableDataChanged(); } public void filterConditions(EnumSet<Condition> conditions, boolean enable) { filter.conditions = conditions; filter.isConditions = enable; model.fireTableDataChanged(); } public void filterInvers(boolean enable) { filter.inverse = enable; model.fireTableDataChanged(); } public void filterBookingClosed(boolean isBookingClosed, boolean isNotBookingClosed) { filter.isBookingClosed = isBookingClosed; filter.isNotBookingClosed = isNotBookingClosed; model.fireTableDataChanged(); } public void filterExcatlyBriefed(boolean isExactlyBriefed, boolean isNotExactlyBriefed) { filter.isExactlyBriefed = isExactlyBriefed; filter.isNotExactlyBriefed = isNotExactlyBriefed; model.fireTableDataChanged(); } public void filterType(DocumentType type, boolean enable) { filter.type = type; filter.isType = enable; model.fireTableDataChanged(); } public void filterCustomer(boolean sysCustomer, boolean normalCustomer) { filter.shouldNormalCustomer = normalCustomer; filter.shouldSysCustomer = sysCustomer; model.fireTableDataChanged(); } public void filterInverseType(boolean inversType) { filter.inverseType = inversType; model.fireTableDataChanged(); } public void filterPaymentMethod(PaymentMethod paymentMethod, boolean isEnable) { filter.paymentMethod = paymentMethod; filter.isPaymentMethod = isEnable; model.fireTableDataChanged(); } public void toogleActive(String conditionName) { Condition condition = null; for (Condition forCondition : Condition.values()) { if ( forCondition.getName().equals(conditionName) ) { condition = forCondition; } } if ( filter.conditions.contains(condition) ) { filter.conditions.remove(condition); } else { filter.conditions.add(condition); } filterConditions(filter.conditions, !filter.conditions.isEmpty()); } public void showSelectedDossier() { new HtmlDialog(view, Dialog.ModalityType.MODELESS).setText(RedTapeUiUtil.toHtmlDetailed(model.getSelected())).setVisible(true); } /** * This Method sets on the view all avaible conditions as a checkbox. * In detail, this method gets the Enum of Condition and create for every Condition a Action. * This action will be setted at a JCheckbox and this will be added ad the conditionPanel. */ public void setAvaibleConditionsButtons() { for (Condition condition : Condition.values()) { AbstractAction abstractAction = new AbstractAction(condition.getName()) { @Override public void actionPerformed(ActionEvent ae) { DossierFilterController.this.toogleActive(ae.getActionCommand()); } }; view.conditionPanel.add(new JCheckBox(abstractAction)); } view.repaint(); view.revalidate(); } public void cancelLoader() { if ( !dossierLoader.isDone() ) dossierLoader.cancel(false); } private void restartDossierLoader() { nextToLoad = 0; dossierLoader = new DossierLoader(); dossierLoader.execute(); } public void loadNextHundred() { dossierLoader = new DossierLoader(); dossierLoader.execute(); nextToLoad += 100; } public void openDossierDetailViewer(Dossier dos) { new HtmlDialog(view, Dialog.ModalityType.MODELESS).setText(RedTapeUiUtil.toHtmlDetailed(dos)).setVisible(true); } }