/* * This file is part of ADDIS (Aggregate Data Drug Information System). * ADDIS is distributed from http://drugis.org/. * Copyright © 2009 Gert van Valkenhoef, Tommi Tervonen. * Copyright © 2010 Gert van Valkenhoef, Tommi Tervonen, Tijs Zwinkels, * Maarten Jacobs, Hanno Koeslag, Florin Schimbinschi, Ahmad Kamal, Daniel * Reid. * Copyright © 2011 Gert van Valkenhoef, Ahmad Kamal, Daniel Reid, Florin * Schimbinschi. * Copyright © 2012 Gert van Valkenhoef, Daniel Reid, Joël Kuiper, Wouter * Reckman. * Copyright © 2013 Gert van Valkenhoef, Joël Kuiper. * * 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 org.drugis.addis.presentation; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeConstants; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.Duration; import org.drugis.addis.entities.Epoch; import org.drugis.addis.entities.TypeWithDuration; import org.drugis.common.beans.AbstractObservable; public class DurationPresentation<T extends TypeWithDuration> extends AbstractObservable { public static class Data { public DateUnits units; public final int quantity; public Data(DateUnits units, int quantity) { this.units = units; this.quantity = quantity; } public Duration getDuration() { return generateDuration(units.asDurationString(quantity)); } public DateUnits getDateunits() { return units; } @Override public String toString() { return (quantity == 1 ? units.getSingular() : quantity + " " + units.toString()).toLowerCase(); } } public static final String PROPERTY_DEFINED = "defined"; public static final String PROPERTY_DURATION_QUANTITY = "quantity"; public static final String PROPERTY_DURATION_UNITS = "units"; public static final String PROPERTY_LABEL = "label"; private static final Data DEFAULT_DATA = new Data(DateUnits.Weeks, 0); private final T d_bean; private Data d_data = DEFAULT_DATA; public static enum DateUnits { Months, Weeks, Days, Hours, Minutes, Seconds; /** * Convert a quantity of this unit into a XML Duration string. * @param q The quantity * @return The corresponding duration string. */ public String asDurationString(int q) { switch (this) { case Seconds: return "PT" + q + "S"; case Minutes: return "PT" + q + "M"; case Hours: return "PT" + q + "H"; case Days: return "P" + q + "D"; case Weeks: return "P" + (q * 7) + "D"; case Months: return "P" + q + "M"; default: return null; } } public String getSingular() { return toString().substring(0, this.toString().length() - 1); } } /** * Create a presentation model for the duration in epoch. * @param bean */ public DurationPresentation(T bean) { d_bean = bean; d_bean.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if(evt.getPropertyName().equals(Epoch.PROPERTY_DURATION)) { Data oldData = d_data; d_data = parseDuration(); if (oldData != null && d_data == null) { firePropertyChange(PROPERTY_DEFINED, true, false); firePropertyChange(PROPERTY_DURATION_QUANTITY, oldData.quantity, DEFAULT_DATA.quantity); firePropertyChange(PROPERTY_DURATION_UNITS, oldData.units, DEFAULT_DATA.units); } else if (oldData != null) { if (oldData.quantity != d_data.quantity) { firePropertyChange(PROPERTY_DURATION_QUANTITY, oldData.quantity, d_data.quantity); } if (oldData.units != d_data.units) { firePropertyChange(PROPERTY_DURATION_UNITS, oldData.units, d_data.units); } } else if (d_data != null) { firePropertyChange(PROPERTY_DEFINED, false, true); firePropertyChange(PROPERTY_DURATION_QUANTITY, DEFAULT_DATA.quantity, d_data.quantity); firePropertyChange(PROPERTY_DURATION_UNITS, DEFAULT_DATA.units, d_data.units); } } } }); addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if (!evt.getPropertyName().equals(PROPERTY_LABEL)) { firePropertyChange(PROPERTY_LABEL, null, getLabel()); } } }); d_data = parseDuration(); } public static Data parseDuration(Duration duration, DateUnits prevUnits) { if (duration == null) { return null; } else if (duration.isSet(DatatypeConstants.SECONDS)) { return new Data(DateUnits.Seconds, duration.getSeconds()); } else if (duration.isSet(DatatypeConstants.MINUTES)) { return new Data(DateUnits.Minutes, duration.getMinutes()); } else if (duration.isSet(DatatypeConstants.HOURS)) { return new Data(DateUnits.Hours, duration.getHours()); } else if (duration.isSet(DatatypeConstants.DAYS)) { if(duration.getDays() % 7 == 0 && prevUnits != DateUnits.Days) { return new Data(DateUnits.Weeks, duration.getDays() / 7); } else { return new Data(DateUnits.Days, duration.getDays()); } } else if (duration.isSet(DatatypeConstants.MONTHS)) { return new Data(DateUnits.Months, duration.getMonths()); } else { throw new RuntimeException("Unhandled Duration: " + duration); } } private Data parseDuration() { if(d_data == null) { d_data = new Data(DateUnits.Weeks, 0); } return parseDuration(d_bean.getDuration(), d_data.units); } public DateUnits getUnits() { d_data = parseDuration(); return d_data == null ? DEFAULT_DATA.units : d_data.units; } public void setUnits(DateUnits units) { if (getDefined()) { DateUnits oldValue = d_data.units; d_data = new Data(units, d_data.quantity); d_bean.setDuration(d_data.getDuration()); firePropertyChange(PROPERTY_DURATION_UNITS, oldValue, units); } } public int getQuantity() { d_data = parseDuration(); return d_data == null ? DEFAULT_DATA.quantity : d_data.quantity; } public void setQuantity(int quantity) { if (getDefined()) { int oldValue = d_data.quantity; d_data = new Data(d_data.units, quantity); d_bean.setDuration(d_data.getDuration()); firePropertyChange(PROPERTY_DURATION_QUANTITY, oldValue, quantity); } } public boolean getDefined() { return d_bean.getDuration() != null; } public void setDefined(boolean defined) { if (defined) { if (!getDefined()) { d_bean.setDuration(DEFAULT_DATA.getDuration()); } } else if (getDefined()) { d_bean.setDuration(null); } } public static Duration generateDuration(String duration) { try { return DatatypeFactory.newInstance().newDuration(duration); } catch (DatatypeConfigurationException e) { throw new RuntimeException(e); } } public String getLabel() { return getDefined() ? d_data.quantity + " " + d_data.units : "Undefined"; } @Override public String toString() { return getLabel(); } }