org.openvpms.web.workspace.workflow.scheduling.SchedulingHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.openvpms.web.workspace.workflow.scheduling.SchedulingHelper.java

Source

/*
 * Version: 1.0
 *
 * The contents of this file are subject to the OpenVPMS License Version
 * 1.0 (the 'License'); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.openvpms.org/license/
 *
 * Software distributed under the License is distributed on an 'AS IS' basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Copyright 2015 (C) OpenVPMS Ltd. All Rights Reserved.
 */

package org.openvpms.web.workspace.workflow.scheduling;

import org.apache.commons.jxpath.JXPathContext;
import org.openvpms.archetype.rules.workflow.AppointmentStatus;
import org.openvpms.archetype.rules.workflow.ScheduleArchetypes;
import org.openvpms.archetype.rules.workflow.ScheduleEvent;
import org.openvpms.archetype.rules.workflow.TaskStatus;
import org.openvpms.component.business.service.archetype.helper.TypeHelper;
import org.openvpms.component.system.common.jxpath.JXPathHelper;
import org.openvpms.component.system.common.util.PropertySet;
import org.openvpms.web.resource.i18n.Messages;
import org.openvpms.web.resource.i18n.format.DateFormatter;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * Scheduling helper.
 *
 * @author Tim Anderson
 */
public class SchedulingHelper {

    /**
     * Returns the minutes from midnight for the specified time.
     *
     * @param time the time
     * @return the minutes from midnight for {@code time}
     */
    public static int getMinutes(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int mins = calendar.get(Calendar.MINUTE);
        return (hour * 60) + mins;
    }

    /**
     * Returns the minutes from midnight for the specified time, rounded
     * up or down to the nearest slot.
     *
     * @param time     the time
     * @param slotSize the slot size
     * @param roundUp  if {@code true} round up to the nearest slot, otherwise round down
     * @return the minutes from midnight for the specified time
     */
    public static int getSlotMinutes(Date time, int slotSize, boolean roundUp) {
        int mins = getMinutes(time);
        int result = getNearestSlot(mins, slotSize);
        if (result != mins && roundUp) {
            result += slotSize;
        }
        return result;
    }

    /**
     * Returns the time of the slot closest to that of the specified time.
     *
     * @param time     the time
     * @param slotSize the size of the slot, in minutes
     * @param roundUp  if {@code true} round up to the nearest slot, otherwise round down
     * @return the nearest slot time to {@code time}
     */
    public static Date getSlotTime(Date time, int slotSize, boolean roundUp) {
        Date result;
        int mins = getMinutes(time);
        int nearestSlot = getNearestSlot(mins, slotSize);
        if (nearestSlot != mins) {
            if (roundUp) {
                nearestSlot += slotSize;
            }
            GregorianCalendar calendar = new GregorianCalendar();
            calendar.setTime(time);
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.add(Calendar.MINUTE, nearestSlot);
            result = calendar.getTime();
        } else {
            result = time;
        }
        return result;
    }

    /**
     * Evaluates an xpath expression against the supplied event.
     * <p/>
     * This adds a "waiting" time attribute to the event prior to evaluation as determined by {@link #getWaitingTime}.
     * <p/>
     * NOTE: any string sequence containing the characters '\\n' will be treated
     * as new lines.
     *
     * @param expression the expression
     * @param event      the event
     * @return the evaluate result. May be {@code null}
     */
    public static String evaluate(String expression, PropertySet event) {
        String text;
        String waiting = getWaitingTime(event);
        if (waiting != null) {
            waiting = Messages.format("scheduleview.expression.waiting", waiting);
        } else {
            waiting = ""; // makes it easier to use in expressions
        }
        event.set("waiting", waiting);

        JXPathContext context = JXPathHelper.newContext(event);

        // hack to replace all instances of '\\n' with new lines to
        // enable new lines to be included in the text
        // Can't use <br> as all xml is escaped
        expression = expression.replace("\'\\n\'", "\'\n\'");
        try {
            Object value = context.getValue(expression);
            text = (value != null) ? value.toString() : null;
        } catch (Throwable exception) {
            text = "Expression Error";
        }
        return text;
    }

    /**
     * Calculates a waiting time for an event.
     * <p/>
     * This is a formatted string indicating the amount of time spent waiting in an event.
     * <p/>
     * If the event is an appointment with:
     * <ul>
     * <li>an {@link ScheduleEvent#ARRIVAL_TIME} property and is CHECKED_IN,
     * this a formatted string indicating the difference between difference between the arrival time and the
     * current time.</li>
     * <li>any other status, the waiting time is {@code null}</li>
     * </ul>
     * <p/>
     * If the event is a task, the waiting time will be calculated as:
     * <ul>
     * <li>{@code consultStartTime - startTime} if the task is not PENDING</li>
     * <li>{@code now - startTime} if the task is PENDING</li>
     * </ul>
     * <p/>
     *
     * @param event the event
     * @return the waiting time. May be {@code null}
     */
    public static String getWaitingTime(PropertySet event) {
        String waiting = null;
        String status = event.getString(ScheduleEvent.ACT_STATUS);
        boolean appointment = TypeHelper.isA(event.getReference(ScheduleEvent.ACT_REFERENCE),
                ScheduleArchetypes.APPOINTMENT);
        if (appointment) {
            if (status.equals(AppointmentStatus.CHECKED_IN) && event.exists(ScheduleEvent.ARRIVAL_TIME)) {
                Date arrival = event.getDate(ScheduleEvent.ARRIVAL_TIME);
                if (arrival != null) {
                    waiting = DateFormatter.formatTimeDiff(arrival, new Date());
                }
            }
        } else {
            Date start = event.getDate(ScheduleEvent.ACT_START_TIME);
            Date end;
            if (status.equals(TaskStatus.PENDING) || !event.exists(ScheduleEvent.CONSULT_START_TIME)) {
                end = new Date();
            } else {
                end = event.getDate(ScheduleEvent.CONSULT_START_TIME);
            }
            waiting = DateFormatter.formatTimeDiff(start, end);
        }
        return waiting;
    }

    /**
     * Returns the nearest slot.
     *
     * @param mins     the start minutes
     * @param slotSize the slot size
     * @return the minutes from midnight for the specified time
     */
    private static int getNearestSlot(int mins, int slotSize) {
        return (mins / slotSize) * slotSize;
    }

}