Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package ru.apertum.qsky.web; import java.io.IOException; import java.io.InputStream; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Optional; import java.util.Properties; import java.util.function.Predicate; import java.util.stream.Stream; import javax.naming.NamingException; import org.hibernate.Session; import org.hibernate.criterion.Restrictions; import org.zkoss.bind.annotation.AfterCompose; 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.util.resource.Labels; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.Sessions; import org.zkoss.zk.ui.event.DropEvent; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.select.Selectors; import org.zkoss.zk.ui.select.annotation.Listen; import org.zkoss.zk.ui.select.annotation.Wire; import org.zkoss.zul.Filedownload; import org.zkoss.zul.Footer; import org.zkoss.zul.Grid; import org.zkoss.zul.GroupsModelArray; import org.zkoss.zul.Hlayout; import org.zkoss.zul.Image; import org.zkoss.zul.Intbox; import org.zkoss.zul.Label; import org.zkoss.zul.Messagebox; import org.zkoss.zul.Panel; import org.zkoss.zul.PieModel; import org.zkoss.zul.SimplePieModel; import org.zkoss.zul.Textbox; import org.zkoss.zul.Tree; import org.zkoss.zul.Treecell; import org.zkoss.zul.Treeitem; import org.zkoss.zul.TreeitemRenderer; import org.zkoss.zul.Treerow; import org.zkoss.zul.Window; import org.zkoss.zul.event.TreeDataEvent; import ru.apertum.qsky.common.Multilingual; import ru.apertum.qsky.controller.branch_tree.AdvancedTreeModel; import ru.apertum.qsky.controller.branch_tree.BranchTreeNode; import ru.apertum.qsky.ejb.IHibernateEJBLocal; import ru.apertum.qsky.model.Branch; import ru.apertum.qsky.model.BranchTreeModel; import ru.apertum.qsky.model.Customer; import ru.apertum.qsky.model.Dicts; import ru.apertum.qsky.model.StatisticViewModel; import ru.apertum.qsky.model.Step; /** * * @author Evgeniy Egorov */ public class Dashboard { public String l(String resName) { return Labels.getLabel(resName); } @Init public void init() { } @Command public void about() { final Properties settings = new Properties(); final InputStream inStream = this.getClass().getResourceAsStream("/qskyapi.properties"); try { settings.load(inStream); } catch (IOException ex) { throw new RuntimeException("Cant read version. " + ex); } Messagebox.show( "*** QSkyAPI ***\n" + " version " + settings.getProperty("version") + "\n date " + settings.getProperty("date") + "\n for QSkySenderPlugin version=" + settings.getProperty("support_clients"), "QMS Apertum-QSystem", Messagebox.OK, Messagebox.INFORMATION); } private User user; @AfterCompose public void afterCompose(@ContextParam(ContextType.VIEW) Component view) { final org.zkoss.zk.ui.Session sess = Sessions.getCurrent(); user = (User) sess.getAttribute("USER"); Selectors.wireComponents(view, this, false); Selectors.wireEventListeners(view, this); doAfterCompose(null); } //***************************************************** //**** Multilingual //***************************************************** public ArrayList<Multilingual.Lng> getLangs() { return Multilingual.LANGS; } private Multilingual.Lng lang = new Multilingual().init(); public Multilingual.Lng getLang() { return lang; } public void setLang(Multilingual.Lng lang) { this.lang = lang; } @Command("changeLang") public void changeLang() { if (lang != null) { final org.zkoss.zk.ui.Session session = Sessions.getCurrent(); final Locale prefer_locale = lang.code.length() > 2 ? new Locale(lang.code.substring(0, 2), lang.code.substring(3)) : new Locale(lang.code); session.setAttribute(org.zkoss.web.Attributes.PREFERRED_LOCALE, prefer_locale); Executions.sendRedirect(null); } } //**** Multilingual ////////////************************************************** ////////////************************************************** ////////////************************************************** private static final long serialVersionUID = 3814570327995355261L; @Wire private Window dashboardWindow; @Wire private Tree tree; // *** ? ???? @Wire("#incBranchPropsDialog #branchPropsDialog") Window branchPropsDialog; private AdvancedTreeModel contactTreeModel; // @Override public void doAfterCompose(Component comp)/* throws Exception*/ { // super.doAfterCompose(comp); contactTreeModel = new AdvancedTreeModel(new BranchTreeModel(user).getRoot()); tree.setItemRenderer(new ContactTreeRenderer()); tree.setModel(contactTreeModel); } private IHibernateEJBLocal hib; public IHibernateEJBLocal getHib() { try { if (hib == null) { hib = (IHibernateEJBLocal) ((new javax.naming.InitialContext()) .lookup("java:comp/env/" + "qskyapi/HibernateEJB")); } } catch (NamingException ex) { throw new RuntimeException("No EJB Hib factory! " + ex); } return hib; } /** * The structure of tree * * <pre> * <treeitem> * <treerow> * <treecell>...</treecell> * </treerow> * <treechildren> * <treeitem>...</treeitem> * </treechildren> * </treeitem> * </pre> */ private final class ContactTreeRenderer implements TreeitemRenderer<BranchTreeNode> { @Override public void render(final Treeitem treeItem, BranchTreeNode treeNode, int index) throws Exception { final BranchTreeNode ctn = treeNode; final Branch branch = (Branch) ctn.getData(); final Treerow dataRow = new Treerow(); dataRow.setParent(treeItem); treeItem.setValue(ctn); treeItem.setOpen(ctn.isOpen()); final Hlayout hl = new Hlayout(); hl.appendChild(new Image("/resources/img/label32.png")); hl.appendChild(new Label(branch.getName())); hl.setSclass("h-inline-block"); final Treecell treeCell = new Treecell(); treeCell.appendChild(hl); dataRow.setDraggable("true"); dataRow.appendChild(treeCell); dataRow.appendChild( new Treecell("" + branch.getBranchId() + " " + (branch.getActive() ? "Active" : "Disable"))); dataRow.addEventListener(Events.ON_DOUBLE_CLICK, (Event event) -> { final BranchTreeNode clickedNodeValue = (BranchTreeNode) ((Treeitem) event.getTarget().getParent()) .getValue(); final Branch br = clickedNodeValue.getData(); final Window w = branchPropsDialog; w.setTitle(br.toString()); ((Textbox) w.getFellow("nameBranch")).setText(br.getName()); ((Intbox) w.getFellow("idBranch")).setValue(br.getBranchId().intValue()); ((Intbox) w.getFellow("timeZone")).setValue(br.getTimeZone()); w.setVisible(true); w.setPosition("center"); w.doModal(); }); // Both category row and contact row can be item dropped dataRow.setDroppable("true"); dataRow.addEventListener(Events.ON_DROP, (Event event) -> { // The dragged target is a TreeRow belongs to an // Treechildren of TreeItem. final Treeitem draggedItem = (Treeitem) ((DropEvent) event).getDragged().getParent(); final BranchTreeNode draggedValue = (BranchTreeNode) draggedItem.getValue(); //System.out.println("--------------------------START draggedValue " + draggedValue.getData().getId() + " to " + ((BranchTreeNode) treeItem.getValue()).getData().getId()); // ? if (draggedValue.getData().getParent() == null && !user.getBranches().isEmpty()) { return; } if (!draggedValue.isParentOf((BranchTreeNode) treeItem.getValue())) {// ? if (draggedValue.getData().getParent() == null || !draggedValue.getData().getParent().getId() .equals(((BranchTreeNode) treeItem.getValue()).getData().getId())) {// ? contactTreeModel.remove(draggedValue); contactTreeModel.add((BranchTreeNode) treeItem.getValue(), new BranchTreeNode[] { draggedValue }); final boolean remove = draggedValue.getData().getParent() == null ? true : draggedValue.getData().getParent().getChildren().remove(draggedValue.getData()); if (!remove) { //System.out.println("--------------- "+draggedValue.getData().getParent() + " -- " + draggedValue.getData() + " - " + draggedValue.getData().getParent()..getChildren().); throw new RuntimeException("Not delete the child "); } draggedValue.getData().setParent(((BranchTreeNode) treeItem.getValue()).getData()); ((BranchTreeNode) treeItem.getValue()).getData().getChildren().add(draggedValue.getData()); final Session ses = getHib().openSession(); try { ses.beginTransaction(); ses.saveOrUpdate(((BranchTreeNode) treeItem.getValue()).getData()); ses.saveOrUpdate(draggedValue.getData()); ses.getTransaction().commit(); } catch (Exception ex) { ses.getTransaction().rollback(); throw new RuntimeException("Not updated the tree "); } finally { ses.close(); } } } }); } } @Command public void addBranch() { if (tree.getSelectedItem() == null && !user.getBranches().isEmpty()) { return; } final long l = new Date().getTime() % 10000; Branch br = new Branch("New branch " + l); br.setBranchId(l); if (user.getBranches().isEmpty()) { ((BranchTreeNode) tree.getModel().getRoot()).insert(new BranchTreeNode(br), 0); } else { br.setParent(((BranchTreeNode) tree.getSelectedItem().getValue()).getData()); ((BranchTreeNode) tree.getSelectedItem().getValue()).getData().getChildren().add(br); final BranchTreeNode node = new BranchTreeNode(br); ((BranchTreeNode) tree.getSelectedItem().getValue()).add(node); } final Session ses = getHib().openSession(); try { ses.beginTransaction(); ses.save(br); ses.getTransaction().commit(); } catch (Exception ex) { ses.getTransaction().rollback(); throw new RuntimeException("Not created the new branch " + ex); } finally { ses.close(); } } @Command public void removeBranch() { if (tree.getSelectedItem() != null) { if (((BranchTreeNode) tree.getSelectedItem().getValue()).getParent().getData() == null && !user.getBranches().isEmpty()) { return; } if (((BranchTreeNode) tree.getSelectedItem().getValue()).getChildCount() != 0) { Messagebox.show(l("mess_del_branch_not_empty_tree"), l("del_impossible"), Messagebox.OK, Messagebox.ERROR); return; } final Branch br = ((BranchTreeNode) tree.getSelectedItem().getValue()).getData(); Messagebox.show(l("shure_del_branch") + " \"" + br + "\"?", l("removing"), Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION, (Event evt) -> { if (evt.getName().equals("onOK")) { if (br.getParent() != null && !br.getParent().getChildren().remove(br)) { throw new RuntimeException("Not delete the child "); } final Session ses = getHib().openSession(); try { ses.beginTransaction(); ses.delete(br); ses.getTransaction().commit(); } catch (Exception ex) { ses.getTransaction().rollback(); throw new RuntimeException("Not deleted the branch " + ex); } finally { ses.close(); } ((BranchTreeNode) tree.getSelectedItem().getValue()).getParent() .remove(((BranchTreeNode) tree.getSelectedItem().getValue())); } }); } } @Command public void closeBranchPropsDialog() { if (tree.getSelectedItem() != null) { BranchTreeNode br_node = (BranchTreeNode) tree.getSelectedItem().getValue(); Branch br = ((BranchTreeNode) tree.getSelectedItem().getValue()).getData(); br.setName(((Textbox) branchPropsDialog.getFellow("nameBranch")).getText()); br.setBranchId(((Intbox) branchPropsDialog.getFellow("idBranch")).getValue().longValue()); br.setBranchId(((Intbox) branchPropsDialog.getFellow("idBranch")).getValue().longValue()); br.setTimeZone(((Intbox) branchPropsDialog.getFellow("timeZone")).getValue()); final Session ses = getHib().openSession(); try { ses.beginTransaction(); ses.saveOrUpdate(br); ses.getTransaction().commit(); } catch (Exception ex) { ses.getTransaction().rollback(); throw new RuntimeException("Not saved the branch " + ex); } finally { ses.close(); } final int[] ii1 = contactTreeModel.getPath(br_node); final int[] ii2 = (new int[ii1.length - 1]); System.arraycopy(ii1, 0, ii2, 0, ii2.length); contactTreeModel.fireEvent(TreeDataEvent.CONTENTS_CHANGED, ii2, tree.getSelectedItem().getIndex(), tree.getSelectedItem().getIndex()); branchPropsDialog.setVisible(false); } } @Wire private Label branchName; @Wire private Panel statPapamPanel; private Branch selectedBranch = null; @Listen("onSelect = #tree") @NotifyChange(value = { "branchName", "statPapamPanel" }) public void selectBranch() { BranchTreeNode selectedNode = (BranchTreeNode) tree.getSelectedItem().getValue(); System.out.println("SELECTED " + selectedNode); Sessions.getCurrent().setAttribute("BRANCH", selectedNode.getData()); selectedBranch = selectedNode.getData(); branchName.setValue(selectedNode.getData().getName()); statPapamPanel.setTitle(selectedNode.getData().getName()); } public static class Pair implements Comparable<Pair> { Long l; Integer i; String st; public Long getL() { return l; } public void setL(Long l) { this.l = l; } public Integer getI() { return i; } public void setI(Integer i) { this.i = i; } public String getSt() { return st; } public void setSt(String st) { this.st = st; } public Pair(Long l, Integer i) { this.l = l; this.i = i; } public Pair(String st, Integer i) { this.st = st; this.i = i; } @Override public int compareTo(Pair o) { return i.compareTo(o.i); } } @Command("showBranchSituation") @NotifyChange(value = { "pieChart", "dialChart", "servicesCustList" }) public synchronized void showBranchSituation() { if (selectedBranch == null) { return; } final Session ses = getHib().openSession(); final List<Customer> custs; try { ses.beginTransaction(); final GregorianCalendar day = new GregorianCalendar(); day.set(GregorianCalendar.HOUR_OF_DAY, 0); day.set(GregorianCalendar.MINUTE, 0); final Date today_m = day.getTime(); day.set(GregorianCalendar.HOUR_OF_DAY, 23); day.set(GregorianCalendar.MINUTE, 59); custs = ses.createCriteria(Customer.class) .add(Restrictions.eq("branchId", selectedBranch.getBranchId())) .add(Restrictions.between("visitTime", today_m, day.getTime())).list(); } catch (Exception ex) { throw new RuntimeException("Not loaded a list of customers. " + ex); } finally { ses.getTransaction().rollback(); ses.close(); } final Predicate<? super Customer> filter = (cust) -> { return cust.getState() != 0 && cust.getState() != 10; }; final HashMap<Long, Integer> cnt = new HashMap<>(); Stream<Customer> scu = custs.stream().filter(filter); final long clntsCnt = custs.stream().filter(filter).count(); scu.forEach((cust) -> { Integer serv = cnt.get(cust.getServiceId()); if (serv != null) { cnt.put(cust.getServiceId(), ++serv); } else { cnt.put(cust.getServiceId(), 1); } }); scu = custs.stream().filter(filter); final Optional<Customer> mw = scu.max((cust1, cust2) -> { return (cust1.getWaiting() == 0 ? (new Long(new Date().getTime() - cust1.getVisitTime().getTime())) : cust1.getWaiting()).compareTo( cust2.getWaiting() == 0 ? (new Date().getTime() - cust2.getVisitTime().getTime()) : cust2.getWaiting()); }); long maxWaiting = mw.isPresent() ? (mw.get().getWaiting() == 0 ? (new Date().getTime() - mw.get().getVisitTime().getTime()) : mw.get().getWaiting()) : 0; int i = 0; long avg = 0; for (Customer cust : custs) { if (cust.getState() != 0 && cust.getWaiting() != null) { avg = avg + (cust.getWaiting() == 0 ? (new Date().getTime() - cust.getVisitTime().getTime()) : cust.getWaiting()); i++; } } final List<Pair> ls = new ArrayList<>(); cnt.keySet().stream().forEach((l) -> { ls.add(new Pair(l, cnt.get(l))); }); final PieModel model = new SimplePieModel(); ls.sort((Pair o1, Pair o2) -> { return Integer.compare(o2.i, o1.i); }); ls.stream().limit(10).forEach((Pair p) -> { final String name = Dicts.getInstance().getServiceName(selectedBranch.getBranchId(), p.l); model.setValue((name.length() > 30 ? name.substring(0, 30) + "..." : name) + "(" + p.i + ")", p.i); }); servicesCustList.clear(); ls.stream().forEach((Pair p) -> { final String name = Dicts.getInstance().getServiceName(selectedBranch.getBranchId(), p.l); servicesCustList.add(new Pair(name, p.i)); }); pieChart.setModel(model); dialChart.averageModel.setValue(0, i == 0 ? 0 : avg / i / 1000 / 60); dialChart.customersModel.setValue(0, clntsCnt); dialChart.waitingModel.setValue(0, maxWaiting < 1000 * 60 ? (clntsCnt == 0 ? 0 : 1) : maxWaiting / 1000 / 60); } private final ArrayList<Pair> servicesCustList = new ArrayList(); public ArrayList<Pair> getServicesCustList() { return servicesCustList; } private final PieChartVM pieChart = new PieChartVM(); public PieChartVM getPieChart() { return pieChart; } private final DialChartVM dialChart = new DialChartVM(); public DialChartVM getDialChart() { return dialChart; } private final StatisticViewModel statVM = new StatisticViewModel(); public StatisticViewModel getStatVM() { return statVM; } @Wire private Grid statisticGrid; @Wire private Footer footer_category; @Command("showBranchStatistic") @NotifyChange(value = { "statVM", "statisticGrid", "footer_category" }) public synchronized void showBranchStatistic() { if (selectedBranch == null) { return; } final List<Step> stst; final Session ses = getHib().openSession(); try { stst = statVM.loadStats(selectedBranch.getBranchId(), ses); } catch (Exception ex) { throw new RuntimeException(ex); } finally { ses.close(); } GroupsModelArray mo = statVM.getRegim() == 0 ? new StatisticViewModel.StaticticGroupingEmplsModel(statVM.prepareDataByUser(stst), new StatisticViewModel.RecordEmployeeComparator()) : new StatisticViewModel.StaticticGroupingServsModel(statVM.prepareDataByUser(stst), new StatisticViewModel.RecordServiceComparator()); statVM.setStatisticModel(mo); statisticGrid.setModel(mo); footer_category.setLabel((statVM.getRegim() == 0 ? l("amount_users") + " : " : l("amount_services") + " : ") + mo.getGroupCount()); } @Command("downloadBranchStatistic") public synchronized void downloadBranchStatistic() { if (selectedBranch == null) { return; } final Session ses = getHib().openSession(); final List<Customer> custs; try { ses.beginTransaction(); final GregorianCalendar day = new GregorianCalendar(); day.setTime(statVM.getStart()); day.set(GregorianCalendar.HOUR_OF_DAY, 0); day.set(GregorianCalendar.MINUTE, 0); final Date today_m = day.getTime(); day.setTime(statVM.getFinish()); day.set(GregorianCalendar.HOUR_OF_DAY, 23); day.set(GregorianCalendar.MINUTE, 59); custs = ses.createCriteria(Customer.class) .add(Restrictions.eq("branchId", selectedBranch.getBranchId())) .add(Restrictions.between("visitTime", today_m, day.getTime())).list(); } catch (Exception ex) { throw new RuntimeException("Not loaded a list of customers. " + ex); } finally { ses.getTransaction().rollback(); ses.close(); } final StringBuffer sb; sb = new StringBuffer(l("captions_csv") + "\n"); int nom = 0; for (Customer cust : custs) { Step step = cust.getFirstStep(); while (step != null) { sb.append(++nom).append(";"); sb.append(selectedBranch.getName()).append(";"); sb.append(Dicts.getInstance().getServiceName(selectedBranch.getBranchId(), step.getServiceId())) .append(";"); sb.append(Dicts.getInstance().getEmployeeName(selectedBranch.getBranchId(), step.getEmployeeId())) .append(";"); sb.append(cust.getPrefix()).append(cust.getNumber()).append(";"); sb.append(SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT) .format(step.getStandTime())).append(";"); if (step.getFinishState() == null || step.getFinishState() == 0) { sb.append(";;;;"); } else { sb.append(SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT) .format(step.getStartTime())).append(";"); sb.append(SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT) .format(step.getFinishTime())).append(";"); sb.append(step.getWaiting() / 1000 / 60).append(";"); sb.append(step.getWorking() / 1000 / 60).append(";"); } sb.append(step.getStartState()).append(";"); sb.append(step.getFinishState() == null ? "" : step.getFinishState()).append(";"); step = step.getAfter(); sb.append("\n"); } } Filedownload.save(sb.toString().getBytes(), "text/csv", "qstat_" + SimpleDateFormat.getDateInstance().format(statVM.getStart()) + "-" + SimpleDateFormat.getDateInstance().format(statVM.getFinish()) + ".csv"); sb.setLength(0); } }