Java tutorial
/* * Copyright (C) 2010 {Apertum}Projects. web: www.apertum.ru email: info@apertum.ru * * 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 ru.apertum.qsystem.server.model; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; import java.io.Serializable; import java.util.Collections; import java.util.Date; import java.util.Enumeration; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import javax.persistence.Id; import java.util.PriorityQueue; import java.util.ServiceLoader; import java.util.Set; import java.util.concurrent.LinkedBlockingDeque; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.Transient; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreeNode; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import ru.apertum.qsystem.client.Locales; import ru.apertum.qsystem.common.CustomerState; import ru.apertum.qsystem.common.QLog; import ru.apertum.qsystem.common.Uses; import ru.apertum.qsystem.common.exceptions.ServerException; import ru.apertum.qsystem.common.model.QCustomer; import ru.apertum.qsystem.extra.ICustomerChangePosition; import ru.apertum.qsystem.server.ServerProps; import ru.apertum.qsystem.server.Spring; import ru.apertum.qsystem.server.model.calendar.QCalendar; import ru.apertum.qsystem.server.model.schedule.QBreak; import ru.apertum.qsystem.server.model.schedule.QBreaks; import ru.apertum.qsystem.server.model.schedule.QSchedule; /** * ? ? ??: - ? ? - ? - ? - * ?? . ? ? ? ?. ? ? ? ? * * * @author Evgeniy Egorov * */ @Entity @Table(name = "services") public class QService extends DefaultMutableTreeNode implements ITreeIdGetter, Transferable, Serializable { /** * ? ?, ? ? ? */ @Transient private final PriorityQueue<QCustomer> customers = new PriorityQueue<>(); private PriorityQueue<QCustomer> getCustomers() { return customers; } @Transient //@Expose //@SerializedName("clients") private final LinkedBlockingDeque<QCustomer> clients = new LinkedBlockingDeque<>(customers); /** * ? ? ?? ? ? ?? ? ? * * @return */ public LinkedBlockingDeque<QCustomer> getClients() { return clients; } @Id @Column(name = "id") //@GeneratedValue(strategy = GenerationType.AUTO) ?, .. id ? ? @Expose @SerializedName("id") private Long id = new Date().getTime(); @Override public Long getId() { return id; } public void setId(Long id) { this.id = id; } /** * ? ? ? */ @Column(name = "deleted") @Temporal(javax.persistence.TemporalType.DATE) private Date deleted; public Date getDeleted() { return deleted; } public void setDeleted(Date deleted) { this.deleted = deleted; } /** * ?? ?. 1 - ?, 0 - ?, -1 - . */ @Column(name = "status") @Expose @SerializedName("status") private Integer status; /** * ?? ?. ? ??? ?, * * @return 1 - ?, 0 - ?, -1 - , 2 - ? , 3 - */ public Integer getStatus() { return status; } /** * ? . ? ? . ? ? ?, 0-? ?, -? * ? . */ @Column(name = "point") @Expose @SerializedName("point") private Integer point = 0; public Integer getPoint() { return point; } public void setPoint(Integer point) { this.point = point; } /** * ?. ? ? ? ?. ? ? . ? ?. . */ @Column(name = "duration") @Expose @SerializedName("duration") private Integer duration = 1; public Integer getDuration() { return duration; } public void setDuration(Integer duration) { this.duration = duration; } /** * ? ? ? ??. */ @Column(name = "expectation") @Expose @SerializedName("exp") private Integer expectation = 0; /** * ? ? ? ??. * * @return */ public Integer getExpectation() { return expectation; } public void setExpectation(Integer expectation) { this.expectation = expectation; } /** * ?. null 0... - ? ?. . */ @Column(name = "sound_template") @Expose @SerializedName("sound_template") private String soundTemplate; public String getSoundTemplate() { return soundTemplate; } public void setSoundTemplate(String soundTemplate) { this.soundTemplate = soundTemplate; } public void setStatus(Integer status) { this.status = status; } @Column(name = "advance_limit") @Expose @SerializedName("advance_limit") private Integer advanceLimit = 1; public Integer getAdvanceLimit() { return advanceLimit; } public void setAdvanceLinit(Integer advanceLimit) { this.advanceLimit = advanceLimit; } @Column(name = "day_limit") @Expose @SerializedName("day_limit") private Integer dayLimit = 0; public Integer getDayLimit() { return dayLimit; } public void setDayLimit(Integer dayLimit) { this.dayLimit = dayLimit; } @Column(name = "person_day_limit") @Expose @SerializedName("person_day_limit") private Integer personDayLimit = 0; public Integer getPersonDayLimit() { return personDayLimit; } public void setPersonDayLimit(Integer personDayLimit) { this.personDayLimit = personDayLimit; } /** * ?, ??? ? null 0 ? ? */ @Column(name = "advance_limit_period") @Expose @SerializedName("advance_limit_period") private Integer advanceLimitPeriod = 0; public Integer getAdvanceLimitPeriod() { return advanceLimitPeriod; } public void setAdvanceLimitPeriod(Integer advanceLimitPeriod) { this.advanceLimitPeriod = advanceLimitPeriod; } /** * ? ? */ @Column(name = "advance_time_period") @Expose @SerializedName("advance_time_period") private Integer advanceTimePeriod = 60; public Integer getAdvanceTimePeriod() { return advanceTimePeriod; } public void setAdvanceTimePeriod(Integer advanceTimePeriod) { this.advanceTimePeriod = advanceTimePeriod; } /** * ? 1 - ? 2 - backoffice, .. ? , */ @Column(name = "enable") @Expose @SerializedName("enable") private Integer enable = 1; /** * ? 1 - ? 2 - backoffice, .. ? , * * @return int index */ public Integer getEnable() { return enable; } public void setEnable(Integer enable) { this.enable = enable; } @Column(name = "seq_id") private Integer seqId = 0; public Integer getSeqId() { return seqId; } public void setSeqId(Integer seqId) { this.seqId = seqId; } /** * ? ? ? ? ? ? ? ?? */ @Column(name = "result_required") @Expose @SerializedName("result_required") private Boolean result_required = false; public Boolean getResult_required() { return result_required; } public void setResult_required(Boolean result_required) { this.result_required = result_required; } /** * ? - ? ? ?. */ @Column(name = "input_required") @Expose @SerializedName("input_required") private Boolean input_required = false; public Boolean getInput_required() { return input_required; } public void setInput_required(Boolean input_required) { this.input_required = input_required; } /** * ? ? , ? ? ? , * ? */ @Column(name = "inputed_as_ext") @Expose @SerializedName("inputed_as_ext") private Boolean inputedAsExt = false; /** * ? ?( ) . * * @return */ public Boolean getInputedAsExt() { return inputedAsExt; } public void setInputedAsExt(Boolean inputedAsExt) { this.inputedAsExt = inputedAsExt; } /** * ? - ? ? ?. ?? ? * ? . */ @Column(name = "input_caption") @Expose @SerializedName("input_caption") private String input_caption = ""; public String getInput_caption() { return input_caption; } public void setInput_caption(String input_caption) { this.input_caption = input_caption; } /** * html ? ?? ? ? ? ?, ?? * ? */ @Column(name = "pre_info_html") @Expose @SerializedName("pre_info_html") private String preInfoHtml = ""; public String getPreInfoHtml() { return preInfoHtml; } public void setPreInfoHtml(String preInfoHtml) { this.preInfoHtml = preInfoHtml; } /** * ? ? ? ? */ @Column(name = "pre_info_print_text") @Expose @SerializedName("pre_info_print_text") private String preInfoPrintText = ""; public String getPreInfoPrintText() { return preInfoPrintText; } public void setPreInfoPrintText(String preInfoPrintText) { this.preInfoPrintText = preInfoPrintText; } /** * ? ? ? ? */ @Column(name = "ticket_text") @Expose @SerializedName("ticket_text") private String ticketText = ""; public String getTicketText() { return ticketText; } public void setTicketText(String ticketText) { this.ticketText = ticketText; } /** * ? ? ? */ @Column(name = "tablo_text") @Expose @SerializedName("tablo_text") private String tabloText = ""; /** * ? ? ? * @return ? */ public String getTabloText() { return tabloText; } public void setTabloText(String tabloText) { this.tabloText = tabloText; } /** * ? ? */ @Column(name = "but_x") @Expose @SerializedName("but_x") private Integer butX = 100; @Column(name = "but_y") @Expose @SerializedName("but_y") private Integer butY = 100; @Column(name = "but_b") @Expose @SerializedName("but_b") private Integer butB = 100; @Column(name = "but_h") @Expose @SerializedName("but_h") private Integer butH = 100; public Integer getButB() { return butB; } public void setButB(Integer butB) { this.butB = butB; } public Integer getButH() { return butH; } public void setButH(Integer butH) { this.butH = butH; } public Integer getButX() { return butX; } public void setButX(Integer butX) { this.butX = butX; } public Integer getButY() { return butY; } public void setButY(Integer butY) { this.butY = butY; } /** * ? , ? ? ? ?. . ? ? json - * , ?-? ? ? ? . */ @Transient private int lastNumber = Integer.MIN_VALUE; /** * ? , ? ? ? ? ? ?. ? * ? ? . */ @Transient private static volatile int lastStNumber = Integer.MIN_VALUE; public QService() { super(); } @Override public String toString() { return getName().trim().isEmpty() ? "<NO_NAME>" : getName(); } /** * ? ? ?. ? . * * @return */ public int getNextNumber() { synchronized (QService.class) { if (lastNumber == Integer.MIN_VALUE) { lastNumber = ServerProps.getInstance().getProps().getFirstNumber() - 1; } if (lastStNumber == Integer.MIN_VALUE) { lastStNumber = ServerProps.getInstance().getProps().getFirstNumber() - 1; } if (lastNumber >= ServerProps.getInstance().getProps().getLastNumber()) { clearNextNumber(); } if (lastStNumber >= ServerProps.getInstance().getProps().getLastNumber()) { clearNextStNumber(); } // ?. ? ?? ? final int today = new GregorianCalendar().get(GregorianCalendar.DAY_OF_YEAR); if (today != day) { day = today; setCountPerDay(0); } countPerDay++; // 0 - ? ?, 1 - ? ? ?? ? if (ServerProps.getInstance().getProps().getNumering()) { return ++lastNumber; } else { return ++lastStNumber; } } } // ? ? ?? ? ? @Transient private int day_y = -100; // ? ? ? @Transient private int dayAdvs = -100; // ? ? ? /** * ? ? ? ? ? * * @param date ? ? ? * @param strictStart false - ? ? ? ? , true - ? ? ? ? ? date * @return ? ? */ public int getAdvancedCount(Date date, boolean strictStart) { final GregorianCalendar forDay = new GregorianCalendar(); forDay.setTime(date); final GregorianCalendar today = new GregorianCalendar(); if (!strictStart && forDay.get(GregorianCalendar.DAY_OF_YEAR) == today.get(GregorianCalendar.DAY_OF_YEAR) && day_y != today.get(GregorianCalendar.DAY_OF_YEAR)) { day_y = today.get(GregorianCalendar.DAY_OF_YEAR); dayAdvs = -100; } if (!strictStart && forDay.get(GregorianCalendar.DAY_OF_YEAR) == today.get(GregorianCalendar.DAY_OF_YEAR) && dayAdvs >= 0) { return dayAdvs; } final DetachedCriteria dc = DetachedCriteria.forClass(QAdvanceCustomer.class); dc.setProjection(Projections.rowCount()); if (!strictStart) { forDay.set(GregorianCalendar.HOUR_OF_DAY, 0); forDay.set(GregorianCalendar.MINUTE, 0); } final Date today_m = forDay.getTime(); forDay.set(GregorianCalendar.HOUR_OF_DAY, 23); forDay.set(GregorianCalendar.MINUTE, 59); dc.add(Restrictions.between("advanceTime", today_m, forDay.getTime())); dc.add(Restrictions.eq("service", this)); final Long cnt = (Long) (Spring.getInstance().getHt().findByCriteria(dc).get(0)); final int i = cnt.intValue(); forDay.setTime(date); if (!strictStart && forDay.get(GregorianCalendar.DAY_OF_YEAR) == today.get(GregorianCalendar.DAY_OF_YEAR)) { dayAdvs = i; } QLog.l().logger() .trace("? ? ?? " + getName() + ". " + i); return i; } /** * ??? ? * * @param data * @return true - , ??? ?; false - ? */ public boolean isLimitPersonPerDayOver(String data) { final int today = new GregorianCalendar().get(GregorianCalendar.DAY_OF_YEAR); if (today != day) { day = today; setCountPerDay(0); } return getPersonDayLimit() != 0 && getPersonDayLimit() <= getCountPersonsPerDay(data); } private int getCountPersonsPerDay(String data) { int cnt = 0; cnt = customers.stream().filter((customer) -> (data.equalsIgnoreCase(customer.getInput_data()))) .map((_item) -> 1).reduce(cnt, Integer::sum); if (getPersonDayLimit() <= cnt) { return cnt; } QLog.l().logger().trace( " ? ? \"" + data + "\""); // ? final GregorianCalendar gc = new GregorianCalendar(); gc.set(GregorianCalendar.HOUR, 0); gc.set(GregorianCalendar.MINUTE, 0); gc.set(GregorianCalendar.SECOND, 0); final Date start = gc.getTime(); gc.add(GregorianCalendar.DAY_OF_YEAR, 1); final Date finish = gc.getTime(); QLog.l().logger() .trace("FROM QCustomer a WHERE " + " start_time >'" + Uses.FORMAT_FOR_REP.format(start) + "' " + " and start_time <= '" + Uses.FORMAT_FOR_REP.format(finish) + "' " + " and input_data = '" + data + "' " + " and service_id = " + getId()); final List<QCustomer> custs = Spring.getInstance().getHt() .find("FROM QCustomer a WHERE " + " start_time >'" + Uses.FORMAT_FOR_REP.format(start) + "' " + " and start_time <= '" + Uses.FORMAT_FOR_REP.format(finish) + "' " + " and input_data = '" + data + "' " + " and service_id = " + getId()); QLog.l().logger().trace( " ? ? \"" + data + "\". " + (cnt + custs.size())); return cnt + custs.size(); } /** * ??? ? * * @return true - , ??? ?; false - ? */ public boolean isLimitPerDayOver() { final Date now = new Date(); int advCusts = getAdvancedCount(now, true); //? ? ? ??? ?(true) final int today = new GregorianCalendar().get(GregorianCalendar.DAY_OF_YEAR); if (today != day) { day = today; setCountPerDay(0); } final long p = getPossibleTickets(); final long c = getCountPerDay(); final boolean f = getDayLimit() != 0 && (p <= c + advCusts); if (f) { QLog.l().logger().trace("Customers overflow: DayLimit()=" + getDayLimit() + " && PossibleTickets=" + p + " <= CountPerDay=" + c + " + advCusts=" + advCusts); } return f;// getDayLimit() != 0 && getPossibleTickets(now) <= getCountPerDay() + advCusts; } /** * ? , ? ? ? ? * * @return ??? ? ? / ? ? */ public long getPossibleTickets() { if (getDayLimit() != 0) { // ? final GregorianCalendar gc = new GregorianCalendar(); final Date now = new Date(); gc.setTime(now); long dif = getSchedule().getWorkInterval(gc.getTime()).finish.getTime() - now.getTime(); int ii = gc.get(GregorianCalendar.DAY_OF_WEEK) - 1; if (ii < 1) { ii = 7; } final QBreaks qb; switch (ii) { case 1: qb = getSchedule().getBreaks_1(); break; case 2: qb = getSchedule().getBreaks_2(); break; case 3: qb = getSchedule().getBreaks_3(); break; case 4: qb = getSchedule().getBreaks_4(); break; case 5: qb = getSchedule().getBreaks_5(); break; case 6: qb = getSchedule().getBreaks_6(); break; case 7: qb = getSchedule().getBreaks_7(); break; default: throw new AssertionError(); } if (qb != null) {// for (QBreak br : qb.getBreaks()) { if (br.getTo_time().after(now)) { if (br.getFrom_time().before(now)) { dif = dif - (br.getTo_time().getTime() - now.getTime()); } else { dif = dif - br.diff(); } } } } QLog.l().logger() .trace("?? " + (dif / 1000 / 60) + " . ? " + getDayLimit() + " , ??? ? " + (dif / 1000 / 60 / getDayLimit()) + " ?."); return dif / 1000 / 60 / getDayLimit(); } else { return Integer.MAX_VALUE; } } /** * ? ? ?? */ @Transient @Expose @SerializedName("countPerDay") private int countPerDay = 0; public void setCountPerDay(int countPerDay) { this.countPerDay = countPerDay; } public int getCountPerDay() { return countPerDay; } /** * , ? ? ? ? ? */ @Transient @Expose @SerializedName("day") private int day = 0; public int getDay() { return day; } public void setDay(int day) { this.day = day; } public void clearNextNumber() { lastNumber = ServerProps.getInstance().getProps().getFirstNumber() - 1; } public static void clearNextStNumber() { lastStNumber = ServerProps.getInstance().getProps().getFirstNumber() - 1; } public void addCustomerForRecoveryOnly(QCustomer customer) { if (customer.getPrefix() != null) { final int number = customer.getNumber(); // ? ? ? ? ? ? if (CustomerState.STATE_REDIRECT != customer.getState() && CustomerState.STATE_WAIT_AFTER_POSTPONED != customer.getState() && CustomerState.STATE_WAIT_COMPLEX_SERVICE != customer.getState()) { if (number > lastNumber) { lastNumber = number; } if (number > lastStNumber) { lastStNumber = number; } } } addCustomer(customer); } // *************************************************************************************** // ******************** ?? ?? ************************ // *************************************************************************************** /** * ? ??? ??, ?, ?, ? ? ?, ??? ?. * * @param customer ? ? ? ? */ public void addCustomer(QCustomer customer) { if (customer.getPrefix() == null) { customer.setPrefix(getPrefix()); } if (!getCustomers().add(customer)) { throw new ServerException( "? ? ?."); } // ??? / QCustomer before = null; QCustomer after = null; for (Iterator<QCustomer> itr = getCustomers().iterator(); itr.hasNext();) { final QCustomer c = itr.next(); if (!customer.getId().equals(c.getId())) { if (customer.compareTo(c) == 1) { // c - , ? before if (before == null) { before = c; } else if (before.compareTo(c) == -1) { before = c; } } else if (customer.compareTo(c) != 0) { // c - ?, ? after if (after == null) { after = c; } else if (after.compareTo(c) == 1) { after = c; } } } } // ??? for (final ICustomerChangePosition event : ServiceLoader.load(ICustomerChangePosition.class)) { QLog.l().logger() .info(" SPI ??. ?: " + event.getDescription()); event.insert(customer, before, after); } clients.clear(); clients.addAll(getCustomers()); } /** * ? , ? ?! */ public void freeCustomers() { // ??? for (final ICustomerChangePosition event : ServiceLoader.load(ICustomerChangePosition.class)) { QLog.l().logger() .info(" SPI ??. ?: " + event.getDescription()); for (Iterator<QCustomer> itr = getCustomers().iterator(); itr.hasNext();) { event.remove(itr.next()); } } getCustomers().clear(); clients.clear(); clients.addAll(getCustomers()); } /** * , ?. NoSuchElementException * * @return ? */ public QCustomer getCustomer() { return getCustomers().element(); } /** * . NoSuchElementException * * @return ? */ public QCustomer removeCustomer() { final QCustomer customer = getCustomers().remove(); // ??? for (final ICustomerChangePosition event : ServiceLoader.load(ICustomerChangePosition.class)) { QLog.l().logger() .info(" SPI ??. ?: " + event.getDescription()); event.remove(customer); } clients.clear(); clients.addAll(getCustomers()); return customer; } /** * ?. null * * @return ? */ public QCustomer peekCustomer() { return getCustomers().peek(); } /** * . null * * @return ? */ public QCustomer polCustomer() { final QCustomer customer = getCustomers().poll(); if (customer != null) { // ??? for (final ICustomerChangePosition event : ServiceLoader.load(ICustomerChangePosition.class)) { QLog.l().logger() .info(" SPI ??. ?: " + event.getDescription()); event.remove(customer); } } clients.clear(); clients.addAll(getCustomers()); return customer; } /** * ?. * * @param customer ? ? * @return false */ public boolean removeCustomer(QCustomer customer) { final Boolean res = getCustomers().remove(customer); if (customer != null && res) { // ??? for (final ICustomerChangePosition event : ServiceLoader.load(ICustomerChangePosition.class)) { QLog.l().logger() .info(" SPI ??. ?: " + event.getDescription()); event.remove(customer); } } clients.clear(); clients.addAll(getCustomers()); return res; } /** * ? ?, ?? . * * @return ? ? ? ? */ public int getCountCustomers() { return getCustomers().size(); } public boolean changeCustomerPriorityByNumber(String number, int newPriority) { for (QCustomer customer : getCustomers()) { if (number.equalsIgnoreCase(customer.getPrefix() + customer.getNumber())) { customer.setPriority(newPriority); removeCustomer(customer); // addCustomer(customer);// ? ? ?? return true; } } return false; } public QCustomer gnawOutCustomerByNumber(String number) { for (QCustomer customer : getCustomers()) { if (number.equalsIgnoreCase(customer.getPrefix() + customer.getNumber())) { removeCustomer(customer); // return customer; } } return null; } /** * ? ?. */ @Expose @SerializedName("description") @Column(name = "description") private String description; public void setDescription(String description) { this.description = description; } public String getDescription() { return description; } /** * ? ?. */ @Expose @SerializedName("service_prefix") @Column(name = "service_prefix") private String prefix = ""; public void setPrefix(String prefix) { this.prefix = prefix == null ? "" : prefix; } public String getPrefix() { return prefix == null ? "" : prefix; } /** * ? ?. */ @Expose @SerializedName("name") @Column(name = "name") private String name; public void setName(String name) { this.name = name; } @Override public String getName() { return name; } /** * ?? ?. */ @Expose @SerializedName("buttonText") @Column(name = "button_text") private String buttonText; public String getButtonText() { return buttonText; } public void setButtonText(String buttonText) { this.buttonText = buttonText; } /** * ?. */ @Expose @SerializedName("parentId") @Column(name = "prent_id") private Long parentId; @Override public Long getParentId() { return parentId; } public void setParentId(Long parentId) { this.parentId = parentId; } @OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE }) @JoinColumn(name = "link_service_id") private QService link; public QService getLink() { return link; } public void setLink(QService link) { this.link = link; } @ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE }) @JoinColumn(name = "schedule_id") private QSchedule schedule; public QSchedule getSchedule() { return schedule; } public void setSchedule(QSchedule schedule) { this.schedule = schedule; } @ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE }) @JoinColumn(name = "calendar_id") private QCalendar calendar; public QCalendar getCalendar() { return calendar; } public void setCalendar(QCalendar calendar) { this.calendar = calendar; } @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) @JoinColumn(name = "services_id") @Expose @SerializedName("langs") private Set<QServiceLang> langs = new HashSet<>(); public Set<QServiceLang> getLangs() { return langs; } public void setLangs(Set<QServiceLang> langs) { this.langs = langs; } @Transient private HashMap<String, QServiceLang> qslangs = null; public QServiceLang getServiceLang(String nameLocale) { if (qslangs == null) { qslangs = new HashMap<>(); getLangs().stream().forEach((sl) -> { qslangs.put(sl.getLang(), sl); }); } return qslangs.get(nameLocale); } public static enum Field { /** * ?? */ BUTTON_TEXT, /** * */ INPUT_CAPTION, /** * ? */ PRE_INFO_HTML, /** * ? ? */ PRE_INFO_PRINT_TEXT, /** * ? ? ? */ TICKET_TEXT, /** * ? ? */ DESCRIPTION, /** * ? ? */ NAME }; public String getTextToLocale(Field field) { final String nl = Locales.getInstance().getNameOfPresentLocale(); final QServiceLang sl = getServiceLang(nl); switch (field) { case BUTTON_TEXT: return !Locales.getInstance().isWelcomeMultylangs() || sl == null || sl.getButtonText() == null || sl.getButtonText().isEmpty() ? getButtonText() : sl.getButtonText(); case INPUT_CAPTION: return !Locales.getInstance().isWelcomeMultylangs() || sl == null || sl.getInput_caption() == null || sl.getInput_caption().isEmpty() ? getInput_caption() : sl.getInput_caption(); case PRE_INFO_HTML: return !Locales.getInstance().isWelcomeMultylangs() || sl == null || sl.getPreInfoHtml() == null || sl.getPreInfoHtml().isEmpty() ? getPreInfoHtml() : sl.getPreInfoHtml(); case PRE_INFO_PRINT_TEXT: return !Locales.getInstance().isWelcomeMultylangs() || sl == null || sl.getPreInfoPrintText() == null || sl.getPreInfoPrintText().isEmpty() ? getPreInfoPrintText() : sl.getPreInfoPrintText(); case TICKET_TEXT: return !Locales.getInstance().isWelcomeMultylangs() || sl == null || sl.getTicketText() == null || sl.getTicketText().isEmpty() ? getTicketText() : sl.getTicketText(); case DESCRIPTION: return !Locales.getInstance().isWelcomeMultylangs() || sl == null || sl.getDescription() == null || sl.getDescription().isEmpty() ? getDescription() : sl.getDescription(); case NAME: return !Locales.getInstance().isWelcomeMultylangs() || sl == null || sl.getName() == null || sl.getName().isEmpty() ? getName() : sl.getName(); default: throw new AssertionError(); } } /** * ? NULL ??, ? ? ? ? ? ? ? ? */ @Transient private String tempReasonUnavailable; public String getTempReasonUnavailable() { return tempReasonUnavailable; } public void setTempReasonUnavailable(String tempReasonUnavailable) { this.tempReasonUnavailable = tempReasonUnavailable; } //******************************************************************************************************************* //******************************************************************************************************************* //********************** ? *********************************************************** /** * ? ? ? ? . ? ?. */ @Transient private QService parentService; @Transient @Expose @SerializedName("inner_services") private final LinkedList<QService> childrenOfService = new LinkedList<>(); public LinkedList<QService> getChildren() { return childrenOfService; } @Override public void addChild(ITreeIdGetter child) { if (!childrenOfService.contains((QService) child)) { // ? childrenOfService.add((QService) child); } } @Override public QService getChildAt(int childIndex) { return childrenOfService.get(childIndex); } @Override public int getChildCount() { return childrenOfService.size(); } @Override public QService getParent() { return parentService; } @Override public int getIndex(TreeNode node) { return childrenOfService.indexOf(node); } @Override public boolean getAllowsChildren() { return true; } @Override public boolean isLeaf() { return getChildCount() == 0; } @Override public Enumeration children() { return Collections.enumeration(childrenOfService); } @Override public void insert(MutableTreeNode child, int index) { child.setParent(this); this.childrenOfService.add(index, (QService) child); } @Override public void remove(int index) { this.childrenOfService.remove(index); } @Override public void remove(MutableTreeNode node) { this.childrenOfService.remove((QService) node); } @Override public void removeFromParent() { getParent().remove(getParent().getIndex(this)); } @Override public void setParent(MutableTreeNode newParent) { parentService = (QService) newParent; if (parentService != null) { setParentId(parentService.id); } else { parentId = null; } } /** * data flavor used to get back a DnDNode from data transfer */ public static final DataFlavor DND_NODE_FLAVOR = new DataFlavor(QService.class, "Drag and drop Node"); /** * list of all flavors that this DnDNode can be transfered as */ protected static DataFlavor[] flavors = { QService.DND_NODE_FLAVOR }; @Override public DataFlavor[] getTransferDataFlavors() { return flavors; } @Override public boolean isDataFlavorSupported(DataFlavor flavor) { return true; } @Override public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (this.isDataFlavorSupported(flavor)) { return this; } else { throw new UnsupportedFlavorException(flavor); } } }