/* * This file is part of LibrePlan * * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Desenvolvemento Tecnolóxico de Galicia * Copyright (C) 2010-2012 Igalia, S.L. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.libreplan.web.common; import static org.libreplan.web.I18nHelper._; import java.io.IOException; import java.math.BigDecimal; import java.text.DateFormat; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.LocalTime; import org.libreplan.business.common.BaseEntity; import org.libreplan.business.common.Configuration; import org.libreplan.business.common.Registry; import org.springframework.web.context.ContextLoaderListener; import org.zkoss.bind.DefaultBinder; import org.zkoss.ganttz.util.ComponentsFinder; import org.zkoss.image.AImage; import org.zkoss.image.Image; import org.zkoss.util.Locales; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Execution; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.event.InputEvent; import org.zkoss.zkplus.databind.AnnotateDataBinder; import org.zkoss.zkplus.databind.DataBinder; import org.zkoss.zul.Bandbox; import org.zkoss.zul.Button; import org.zkoss.zul.Checkbox; import org.zkoss.zul.Combobox; import org.zkoss.zul.Comboitem; import org.zkoss.zul.Datebox; import org.zkoss.zul.Decimalbox; import org.zkoss.zul.Hbox; import org.zkoss.zul.Intbox; import org.zkoss.zul.Label; import org.zkoss.zul.Radio; import org.zkoss.zul.Row; import org.zkoss.zul.Textbox; import org.zkoss.zul.Timebox; import org.zkoss.zul.Column; /** * Utilities class. * <br /> * @author Óscar González Fernández <ogonzalez@igalia.com> * @author Manuel Rego Casasnovas <mrego@igalia.com> * @author Susana Montes Pedreira <smontes@wirelessgalicia.com> * @author Vova Perebykivskyi <vova@libreplan-enterprise.com> */ public class Util { private static final Log LOG = LogFactory.getLog(Util.class); /** * Special chars from {@link DecimalFormat} class. */ private static final String[] DECIMAL_FORMAT_SPECIAL_CHARS = { "0", ",", ".", "\u2030", "%", "#", ";", "-" }; private static final String RELOADED_COMPONENTS_ATTR = Util.class.getName() + ":" + "reloaded"; private static final ThreadLocal<Boolean> ignoreCreateBindings = new ThreadLocal<Boolean>() { protected Boolean initialValue() { return false; } }; /** * Static object that contains logo image. */ public static Image logo; private Util() { } /** * Forces to reload the bindings of the provided components if there is an associated {@link DefaultBinder}. * * @param toReload * the components to reload */ public static void reloadBindings(Component... toReload) { reloadBindings(ReloadStrategy.FORCE, toReload); } public enum ReloadStrategy { /** * If the {@link DefaultBinder} exists the bindings are reloaded no matter what. */ FORCE, /** * Once the bindings for a component have been manually loaded in one * request, subsequent calls for reload the bindings of the same * component or descendants using this strategy are ignored. */ ONE_PER_REQUEST; public static boolean isForced(ReloadStrategy reloadStrategy) { return reloadStrategy == ReloadStrategy.FORCE; } } /** * Reload the bindings of the provided components if there is an associated * {@link DefaultBinder} and the {@link ReloadStrategy} allows it. * * @param toReload * the components to reload */ public static void reloadBindings(ReloadStrategy reloadStrategy, Component... toReload) { reloadBindings(ReloadStrategy.isForced(reloadStrategy), toReload); } private static void reloadBindings(boolean forceReload, Component... toReload) { for (Component reload : toReload) { // TODO resolve deprecated DataBinder binder = Util.getBinder(reload); if (binder != null && (forceReload || notReloadedInThisRequest(reload))) { binder.loadComponent(reload); markAsReloadedForThisRequest(reload); } } } private static boolean notReloadedInThisRequest(Component reload) { return !getReloadedComponents(reload).contains(reload); } private static Set<Component> getReloadedComponents(Component component) { Execution execution = component.getDesktop().getExecution(); @SuppressWarnings("unchecked") Set<Component> result = (Set<Component>) execution.getAttribute(RELOADED_COMPONENTS_ATTR); if (result == null) { result = new HashSet<>(); execution.setAttribute(RELOADED_COMPONENTS_ATTR, result); } return result; } private static void markAsReloadedForThisRequest(Component component) { Set<Component> reloadedComponents = getReloadedComponents(component); reloadedComponents.add(component); reloadedComponents.addAll(getAllDescendants(component)); } private static void markAsNotReloadedForThisRequest(Component component) { Set<Component> reloadedComponents = getReloadedComponents(component); reloadedComponents.remove(component); reloadedComponents.removeAll(getAllDescendants(component)); } @SuppressWarnings("unchecked") private static List<Component> getAllDescendants(Component component) { List<Component> result = new ArrayList<>(); for (Component each : component.getChildren()) { result.add(each); result.addAll(getAllDescendants(each)); } return result; } public static void saveBindings(Component... toReload) { for (Component reload : toReload) { /* TODO resolve deprecated */ DataBinder binder = Util.getBinder(reload); if (binder != null) { binder.saveComponent(reload); } } } /** TODO resolve deprecated */ public static DataBinder getBinder(Component component) { return (DataBinder) component.getAttribute("binder", true); } public static void executeIgnoringCreationOfBindings(Runnable action) { try { ignoreCreateBindings.set(true); action.run(); } finally { ignoreCreateBindings.set(false); } } public static void createBindingsFor(Component result) { if (ignoreCreateBindings.get()) { return; } /* TODO resolve deprecated */ AnnotateDataBinder binder = new AnnotateDataBinder(result, true); /* * Before it was: * setAttribute("binder", binder, true) * And it is not correct. Because API changed ( even more before it was setVariable("binder", binder, true) ). * Boolean value for setAttribute() means recursive actions, but in setVariable() it was not so. * And after, it still was calling method setAttribute() with (attr1, attr2, !booleanValue). */ result.setAttribute("binder", binder, false); markAsNotReloadedForThisRequest(result); } /** * Generic interface to represent a class with a typical get method. * * @author Manuel Rego Casasnovas <mrego@igalia.com> * @param <T> * The type of the variable to be returned. */ @FunctionalInterface public interface Getter<T> { /** * Typical get method that returns a variable. * @return A variable of type <T>. */ T get(); } /** * Generic interface to represent a class with a typical set method. * * @author Manuel Rego Casasnovas <mrego@igalia.com> * @param <T> * The type of the variable to be set. */ @FunctionalInterface public interface Setter<T> { /** * Typical set method to store a variable. * @param value * A variable of type <T> to be set. */ void set(T value); } /** * Binds a {@link Textbox} with a {@link Getter}. The {@link Getter} will be * used to get the value that is going to be showed in the {@link Textbox}. * * @param textBox * The {@link Textbox} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @return The {@link Textbox} bound */ public static Textbox bind(Textbox textBox, Getter<String> getter) { textBox.setValue(getter.get()); textBox.setDisabled(true); return textBox; } /** * Binds a {@link Textbox} with a {@link Getter}. The {@link Getter} will be * used to get the value that is going to be showed in the {@link Textbox}. * The {@link Setter} will be used to store the value inserted by the user in the {@link Textbox}. * * @param textBox * The {@link Textbox} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @param setter * The {@link Setter} interface that will implement a set method. * @return The {@link Textbox} bound */ public static Textbox bind(final Textbox textBox, final Getter<String> getter, final Setter<String> setter) { textBox.setValue(getter.get()); textBox.addEventListener(Events.ON_CHANGE, event -> { InputEvent newInput = (InputEvent) event; String value = newInput.getValue(); setter.set(value); textBox.setValue(getter.get()); }); return textBox; } /** * Binds a {@link Textbox} with a {@link Getter}. The {@link Getter} will be * used to get the value that is going to be showed in the {@link Textbox}. * * @param comboBox * The {@link Combobox} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @return The {@link Combobox} bound */ public static Combobox bind(Combobox comboBox, Getter<Comboitem> getter) { comboBox.setSelectedItem(getter.get()); comboBox.setDisabled(true); return comboBox; } /** * Binds a {@link Textbox} with a {@link Getter}. The {@link Getter} will be * used to get the value that is going to be showed in the {@link Textbox}. * The {@link Setter} will be used to store the value inserted by the user in the {@link Textbox}. * * @param comboBox * The {@link Combobox} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @param setter * The {@link Setter} interface that will implement a set method. * @return The {@link Combobox} bound */ public static Combobox bind(final Combobox comboBox, final Getter<Comboitem> getter, final Setter<Comboitem> setter) { comboBox.setSelectedItem(getter.get()); comboBox.addEventListener("onSelect", event -> { setter.set(comboBox.getSelectedItem()); comboBox.setSelectedItem(getter.get()); }); return comboBox; } /** * Binds a {@link Intbox} with a {@link Getter}. The {@link Getter} will be * used to get the value that is going to be showed in the {@link Intbox} * * @param intBox * The {@link Intbox} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @return The {@link Intbox} bound */ public static Intbox bind(Intbox intBox, Getter<Integer> getter) { intBox.setValue(getter.get()); intBox.setDisabled(true); return intBox; } /** * Binds a {@link Intbox} with a {@link Getter}. * The {@link Getter} will be used to get the value that is going to be showed in the {@link Intbox}. * The {@link Setter} will be used to store the value inserted by the user in the {@link Intbox}. * * @param intBox * The {@link Intbox} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @param setter * The {@link Setter} interface that will implement a set method. * @return The {@link Intbox} bound */ public static Intbox bind(final Intbox intBox, final Getter<Integer> getter, final Setter<Integer> setter) { intBox.setValue(getter.get()); intBox.addEventListener(Events.ON_CHANGE, event -> { InputEvent newInput = (InputEvent) event; String value = newInput.getValue().trim(); if (value.isEmpty()) { value = "0"; } setter.set(Integer.valueOf(value)); intBox.setValue(getter.get()); }); return intBox; } /** * Binds a {@link Datebox} with a {@link Getter}. * The {@link Getter} will be used to get the value that is going to be showed in the {@link Datebox}. * * @param dateBox * The {@link Datebox} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @return The {@link Datebox} bound */ public static Datebox bind(final Datebox dateBox, final Getter<Date> getter) { dateBox.setValue(getter.get()); dateBox.setDisabled(true); return dateBox; } /** * Binds a {@link Datebox} with a {@link Getter}. * The {@link Getter} will be used to get the value that is going to be showed in the {@link Datebox}. * The {@link Setter} will be used to store the value inserted by the user in the {@link Datebox}. * * @param dateBox * The {@link Datebox} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @param setter * The {@link Setter} interface that will implement a set method. * @return The {@link Datebox} bound */ public static Datebox bind(final Datebox dateBox, final Getter<Date> getter, final Setter<Date> setter) { dateBox.setValue(getter.get()); dateBox.addEventListener(Events.ON_CHANGE, event -> { setter.set(dateBox.getValue()); dateBox.setValue(getter.get()); }); return dateBox; } /** * Binds a {@link Timebox} with a {@link Getter}. * The {@link Getter} will be used to get the value that is going to be showed in the {@link Timebox}. * * @param timeBox * The {@link Timebox} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @return The {@link Timebox} bound */ public static Timebox bind(final Timebox timeBox, final Getter<Date> getter) { timeBox.setValue(getter.get()); timeBox.setDisabled(true); return timeBox; } /** * Binds a {@link Timebox} with a {@link Getter}. * The {@link Getter} will be used to get the value that is going to be showed in the {@link Timebox}. * The {@link Setter} will be used to store the value inserted by the user in the {@link Timebox}. * * @param timeBox * The {@link Timebox} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @param setter * The {@link Setter} interface that will implement a set method. * @return The {@link Timebox} bound */ public static Timebox bind(final Timebox timeBox, final Getter<Date> getter, final Setter<Date> setter) { timeBox.setValue(getter.get()); timeBox.addEventListener(Events.ON_CHANGE, event -> { setter.set(timeBox.getValue()); timeBox.setValue(getter.get()); }); return timeBox; } /** * Binds a {@link Decimalbox} with a {@link Getter}. * The {@link Getter} will be used to get the value that is going to be showed in the {@link Decimalbox}. * * @param decimalBox * The {@link Decimalbox} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @return The {@link Decimalbox} bound */ public static Decimalbox bind(final Decimalbox decimalBox, final Getter<BigDecimal> getter) { decimalBox.setValue(getter.get()); decimalBox.setDisabled(true); return decimalBox; } /** * Binds a {@link Decimalbox} with a {@link Getter}. * The {@link Getter} will be used to get the value that is going to be showed in the {@link Decimalbox}. * The {@link Setter} will be used to store the value inserted by the user in the {@link Decimalbox}. * * @param decimalBox * The {@link Decimalbox} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @param setter * The {@link Setter} interface that will implement a set method. * @return The {@link Decimalbox} bound */ public static Decimalbox bind(final Decimalbox decimalBox, final Getter<BigDecimal> getter, final Setter<BigDecimal> setter) { decimalBox.setValue(getter.get()); decimalBox.addEventListener(Events.ON_CHANGE, event -> { setter.set(decimalBox.getValue()); decimalBox.setValue(getter.get()); }); return decimalBox; } /** * Binds a {@link Checkbox} with a {@link Getter}. * The {@link Getter} will be used to get the value that is going to be showed in the {@link Checkbox}. * * @param decimalBox * The {@link Checkbox} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @return The {@link Checkbox} bound */ public static Checkbox bind(final Checkbox checkBox, final Getter<Boolean> getter) { checkBox.setChecked(getter.get()); checkBox.setDisabled(true); return checkBox; } /** * Binds a {@link Checkbox} with a {@link Getter}. * The {@link Getter} will be used to get the value that is going to be showed in the {@link Checkbox}. * The {@link Setter} will be used to store the value inserted by the user in the {@link Checkbox}. * * @param checkBox * @param getter * The {@link Getter} interface that will implement a get method. * @param setter * The {@link Setter} interface that will implement a set method. * @return The {@link Checkbox} bound */ public static Checkbox bind(final Checkbox checkBox, final Getter<Boolean> getter, final Setter<Boolean> setter) { checkBox.setChecked(getter.get()); checkBox.addEventListener(Events.ON_CHECK, event -> { setter.set(checkBox.isChecked()); checkBox.setChecked(getter.get()); }); return checkBox; } /** * Binds a {@link Checkbox} with a {@link Getter}. * The {@link Getter} will be used to get the value that is going to be showed in the {@link Checkbox}. * * @param radio * The {@link Radio} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @return The {@link Radio} bound */ public static Radio bind(final Radio radio, final Getter<Boolean> getter) { radio.setSelected(getter.get()); radio.setDisabled(true); return radio; } /** * Binds a {@link Radio} with a {@link Getter}. * The {@link Getter} will be used to get the value that is going to be showed in the {@link Radio}. * The {@link Setter} will be used to store the value inserted by the user in the {@link Radio}. * * @param radio * The {@link Radio} to be bound * @param getter * he {@link Getter} interface that will implement a get method. * @param setter * The {@link Setter} interface that will implement a set method. * @return The {@link Radio} bound */ public static Radio bind(final Radio radio, final Getter<Boolean> getter, final Setter<Boolean> setter) { radio.setSelected(getter.get()); radio.addEventListener(Events.ON_CHECK, event -> { setter.set(radio.isSelected()); radio.setChecked(getter.get()); }); return radio; } /** * Binds a {@link Bandbox} with a {@link Getter}. * The {@link Getter} will be used to get the value that is going to be showed in the {@link Bandbox}. * * @param bandBox * The {@link Bandbox} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @return The {@link Bandbox} bound */ public static Bandbox bind(Bandbox bandBox, Getter<String> getter) { bandBox.setValue(getter.get()); bandBox.setDisabled(true); return bandBox; } /** * Binds a {@link Bandbox} with a {@link Getter}. * The {@link Getter} will be used to get the value that is going to be showed in the {@link Bandbox}. * The {@link Setter} will be used to store the value inserted by the user in the {@link Bandbox}. * * @param bandBox * The {@link Bandbox} to be bound * @param getter * The {@link Getter} interface that will implement a get method. * @param setter * The {@link Setter} interface that will implement a set method. * @return The {@link Bandbox} bound */ public static Bandbox bind(final Bandbox bandBox, final Getter<String> getter, final Setter<String> setter) { bandBox.setValue(getter.get()); bandBox.addEventListener(Events.ON_CHANGE, event -> { InputEvent newInput = (InputEvent) event; String value = newInput.getValue(); setter.set(value); bandBox.setValue(getter.get()); }); return bandBox; } /** * Creates an edit button with class and icon already set. * * @param eventListener * A event listener for {@link Events#ON_CLICK} * @return An edit {@link Button} */ public static Button createEditButton(EventListener eventListener) { Button result = new Button(); result.setTooltiptext(_("Edit")); result.setSclass("icono"); result.setImage("/common/img/ico_editar1.png"); result.setHoverImage("/common/img/ico_editar.png"); result.addEventListener(Events.ON_CLICK, eventListener); return result; } /** * Creates a remove button with class and icon already set. * * @param eventListener * A event listener for {@link Events#ON_CLICK} * @return A remove {@link Button} */ public static Button createRemoveButton(EventListener eventListener) { Button result = new Button(); result.setTooltiptext(_("Remove")); result.setSclass("icono"); result.setImage("/common/img/ico_borrar1.png"); result.setHoverImage("/common/img/ico_borrar.png"); result.addEventListener(Events.ON_CLICK, eventListener); return result; } @SuppressWarnings("unchecked") public static <T extends Component> T findComponentAt(Component container, String idOfComponentToBeFound) { return (T) container.getFellow(idOfComponentToBeFound); } public interface ICreation<T extends Component> { T createAt(Component parent); } public static <T extends Component> T findOrCreate(Component container, Class<T> klassOfComponentToFind, ICreation<T> ifNotFound) { @SuppressWarnings("unchecked") List<T> existent = ComponentsFinder.findComponentsOfType(klassOfComponentToFind, container.getChildren()); if (!existent.isEmpty()) { return existent.get(0); } return ifNotFound.createAt(container); } /** * It removes all listeners registered for eventName and adds the new listener. * It's ensured that the only listener left in the component for events of name eventName is uniqueListener. * * @param component * @param eventName * @param uniqueListener */ public static void ensureUniqueListener(Component component, String eventName, EventListener uniqueListener) { ensureUniqueListeners(component, eventName, uniqueListener); } /** * It removes all listeners registered for eventName and adds the new listeners. * It's ensured that the only listeners left in the component for events of name eventName is uniqueListeners. * * @param component * @param eventName * @param uniqueListeners * new listeners to add */ public static void ensureUniqueListeners(Component component, String eventName, EventListener... uniqueListeners) { // TODO Replace deprecated method Iterator<?> listenerIterator = component.getListenerIterator(eventName); while (listenerIterator.hasNext()) { listenerIterator.next(); listenerIterator.remove(); } for (EventListener each : uniqueListeners) { component.addEventListener(eventName, each); } } public static void setSort(Column column, String sortSpec) { try { column.setSort(sortSpec); } catch (Exception e) { LOG.error("failed to set sort property for: " + column + " with: " + sortSpec, e); } } /** * Gets currency symbol from {@link Configuration} object. * * @return Currency symbol configured in the application */ public static String getCurrencySymbol() { return Registry.getTransactionService().runOnReadOnlyTransaction( () -> Registry.getConfigurationDAO().getConfiguration().getCurrencySymbol()); } /** * Returns the value using the money format, that means, 2 figures for the * decimal part and concatenating the currency symbol from {@link Configuration} object. */ public static String addCurrencySymbol(BigDecimal value) { BigDecimal valueToReturn = value == null ? BigDecimal.ZERO : value; DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat.getInstance(); decimalFormat.applyPattern(getMoneyFormat()); return decimalFormat.format(valueToReturn); } /** * Gets money format for a {@link Decimalbox} using 2 figures for the * decimal part and concatenating the currency symbol. * * @return Format for a {@link Decimalbox} <code>###.##</code> plus currency symbol */ public static String getMoneyFormat() { return "###.## " + escapeDecimalFormatSpecialChars(getCurrencySymbol()); } /** * Escapes special chars used in {@link DecimalFormat} to define the number * format that appear in the <code>currencySymbol</code>. */ private static String escapeDecimalFormatSpecialChars(String currencySymbol) { String stringToReturn = currencySymbol; for (String specialChar : DECIMAL_FORMAT_SPECIAL_CHARS) { stringToReturn = stringToReturn.replace(specialChar, "'" + specialChar + "'"); } return stringToReturn; } /** * Appends the <code>text</code> as a {@link Label} into the specified {@link Row}. */ public static void appendLabel(Row row, String text) { row.appendChild(new Label(text)); } /** * Appends a edit button and a remove button to the {@link Row} inside a * {@link Hbox} and adds the <code>ON_CLICK</code> event over the * {@link Row} for the edit operation.<br /> * * The edit button will call the <code>editButtonListener</code> when * clicked and the remove button the <code>removeButtonListener</code>. * <br /> * * If <code>removeButtonListener</code> is null, it only adds the edit * button and the <code>ON_CLICK</code> event. * * @return An array of 1 or 2 positions (depending if * <code>removeButtonListener</code> param is or not * <code>null</code>) with the edit and remove buttons. As maybe you * need to disable any of them depending on different situations. */ public static Button[] appendOperationsAndOnClickEvent(Row row, EventListener editButtonListener, EventListener removeButtonListener) { Button[] buttons = new Button[removeButtonListener != null ? 2 : 1]; Hbox hbox = new Hbox(); buttons[0] = Util.createEditButton(editButtonListener); hbox.appendChild(buttons[0]); if (removeButtonListener != null) { buttons[1] = Util.createRemoveButton(removeButtonListener); hbox.appendChild(buttons[1]); } row.appendChild(hbox); row.addEventListener(Events.ON_CLICK, editButtonListener); return buttons; } /** * Checks if the <code>entity</code> is contained in the provided <code>list</code>. */ public static boolean contains(List<? extends BaseEntity> list, BaseEntity entity) { for (BaseEntity each : list) { if (each.getId() != null && entity.getId() != null && each.getId().equals(entity.getId())) { return true; } } return false; } /** * Gets the {@link HttpServletResponse} from the current {@link Execution} * and uses the method {@link HttpServletResponse#sendError(int)} with the * code {@link HttpServletResponse#SC_FORBIDDEN}. */ public static void sendForbiddenStatusCodeInHttpServletResponse() { try { HttpServletResponse response = (HttpServletResponse) Executions.getCurrent().getNativeResponse(); response.sendError(HttpServletResponse.SC_FORBIDDEN); } catch (IOException e) { throw new RuntimeException(e); } } /** * Format specific <code>date</code> using the {@link DateFormat#DEFAULT} format and showing only date without time. */ public static String formatDate(Date date) { return date == null ? "" : DateFormat.getDateInstance(DateFormat.DEFAULT, Locales.getCurrent()).format(date); } /** * Format specific <code>date</code> using the {@link DateFormat#DEFAULT} format and showing both date and time. */ public static String formatDateTime(Date dateTime) { return dateTime == null ? "" : DateFormat .getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locales.getCurrent()) .format(dateTime); } /** * Format specific <code>date</code> using the {@link DateFormat#DEFAULT} format and showing only date without time. */ public static String formatDate(DateTime dateTime) { return dateTime == null ? "" : formatDate(dateTime.toDate()); } /** * Format specific <code>date</code> using the {@link DateFormat#DEFAULT} format and showing only date without time. */ public static String formatDate(LocalDate date) { return date == null ? "" : formatDate(date.toDateTimeAtStartOfDay()); } /** * Format specific <code>time</code> using the {@link DateFormat#SHORT} format and showing only the time. */ public static String formatTime(Date time) { return time == null ? "" : DateFormat.getTimeInstance(DateFormat.SHORT, Locales.getCurrent()).format(time); } /** * Format specific <code>time</code> using the {@link DateFormat#SHORT} format and showing only the time. */ public static String formatTime(LocalTime time) { return time == null ? "" : formatTime(time.toDateTimeToday().toDate()); } /** * Setter of {@link Util#logo}. * Will trigger after uploading new image. * * @param name */ static void setLogoFromTarget(String name) { try { logo = new AImage(ContextLoaderListener .getCurrentWebApplicationContext() .getResource(name) .getFile() .getPath()); } catch (IOException ignored) { } } /** * Setter of {@link Util#logo}. * But it will trigger only if {@link Util#logo} is null. * So it is just kind of attempt to find logo with known data. */ static void findLogo() { String name = Registry .getConfigurationDAO() .getConfigurationWithReadOnlyTransaction() .getCompanyLogoURL(); try { if ( !name.isEmpty() ) { logo = new AImage(ContextLoaderListener .getCurrentWebApplicationContext() .getResource(name) .getFile() .getPath()); } } catch (IOException ignored) { } } }