/*
 This file is part of the software framework JStatCom, 
 a library for building applications for data based analysis.

 Copyright (C) 2000-2005  Markus Kraetzig

 This library is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as
 published by the Free Software Foundation; either version 2.1 of the
 License, or (at your option) any later version.

 This library 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
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 USA
 */

package com.jstatcom.model;

import javolution37.javolution.xml.XmlElement;
import javolution37.javolution.xml.XmlFormat;

import com.jstatcom.ts.TSDateRange;

/**
 * Adapter to TSDateRange objects that conforms to the
 * JSCData interface. Everytime something changes, a new
 * TSDateRange object is created, because range objects are
 * immutable.
 * 

* Whenever the value of this data object changes, registered * JSCDataListeners are notified via a JSCDataEvent. * If not otherwise stated, the event objects always contain the values before * the change and after the change. *

* This class is thread-safe. All access to mutable data is synchronized. All * events are fired outside the synchronized blocks. * * @author Markus Kraetzig * @see com.jstatcom.ts.TSDateRange */ public final class JSCDRange extends AbstractJSCData { private final String name; private TSDateRange tsRange; private JSCDataEvent clearEvent = null; private JSCDataEvent notEmptyEvent = null; /** * XML format field for (de)serialization. */ public static final XmlFormat JSCDRange_XML = new XmlFormat( JSCDRange.class) { public void format(JSCDRange data, XmlElement xml) { xml.setAttribute("name", data.name); synchronized (data) { xml.setAttribute("value", data.tsRange + ""); } } public JSCDRange parse(XmlElement xml) { String nam = xml.getAttribute("name") + ""; String rangeString = xml.getAttribute("value") + ""; TSDateRange newRange = null; if (!rangeString.equalsIgnoreCase("null")) newRange = TSDateRange.valueOf(rangeString); return new JSCDRange(nam, newRange); } }; /** * Creates an empty JSCDRange. * * @param name * the identifier of that object * @throws IllegalArgumentException * if name is not valid or * if (name == null) * * @see com.jstatcom.model.JSCConstants#isValidName */ public JSCDRange(String name) { this(name, null); } /** * Creates a JSCDRange for a given TSDateRange. * * @param name * the identifier of that object * @param tsRange * the date value * @throws IllegalArgumentException * if name is not valid or * if (name == null) * * @see com.jstatcom.model.JSCConstants#isValidName */ public JSCDRange(String name, TSDateRange tsRange) { super(); if (name == null) throw new IllegalArgumentException("Argument was null."); name = JSCConstants.checkNameThrowEx(name); this.name = name; this.tsRange = tsRange; } /** * Clears this data object. Fires: *

* if it was not empty before. After calling this method * isEmpty returns true. */ public void clear() { TSDateRange oldValue; synchronized (this) { if (tsRange == null) // Nothing changes. return; oldValue = tsRange; tsRange = null; } // Dispatch event outside synchronized block. if (clearEvent == null) clearEvent = JSCDataEvent.valueOfEmptyState(this, true); if (eventSupport == null) return; getEventSupport().dispatchEvent(clearEvent); getEventSupport().dispatchEvent( JSCDataEvent.valueOfChanged(this, oldValue, null)); } /** * @see com.jstatcom.model.JSCData */ public synchronized JSCDRange copy() { return new JSCDRange(name, tsRange); } /** * Gets whether date is enclosed by this range. * * @param date * the JSCDate to be checked * @return true if date ist enclosed by * this * @throws IllegalArgumentException * if (date == null) or * if (date.isEmpty()) or * if (isEmpty()) */ public boolean encloses(JSCDate date) { if (date == null) throw new IllegalArgumentException("Argument was null."); if (date.isEmpty()) throw new IllegalArgumentException("JSCDate arg is empty."); synchronized (this) { if (isEmpty()) throw new IllegalArgumentException("JSCDateRange is empty."); return tsRange.encloses(date.getTSDate()) == null; } } /** * Gets whether dRange is enclosed by this range. * * @param dRange * the JSCDRange to be checked * @return true if dRange ist enclosed by * this * @throws IllegalArgumentException * if (dRange == null) or * if (dRange.isEmpty()) or * if (isEmpty()) */ public boolean encloses(JSCDRange dRange) { if (dRange == null) throw new IllegalArgumentException("Argument was null."); if (dRange.isEmpty()) throw new IllegalArgumentException("JSCDRange arg is empty."); synchronized (this) { if (isEmpty()) throw new IllegalArgumentException("JSCDRange is empty."); return tsRange.encloses(dRange.getTSDateRange()) == null; } } /** * Gets the stored date object. * * @return the used TSDateRange or null if * empty */ public synchronized TSDateRange getTSDateRange() { return tsRange; } /** * Gets whether this is empty. This method returns * true, if value returns null. * * @return true if empty */ public synchronized boolean isEmpty() { return tsRange == null; } /** * @see com.jstatcom.model.JSCData */ public boolean isEqual(JSCData o) { if (o == this) return true; if (!(o instanceof JSCDRange)) return false; JSCDRange otherRange = (JSCDRange) o; boolean ret = true; synchronized (this) { synchronized (o) { if (tsRange != null) ret = tsRange.equals(otherRange.getTSDateRange()); else ret = otherRange.getTSDateRange() == null; } } return ret; } /** * @see com.jstatcom.model.JSCData */ public String name() { return name; } /** * Sets a new value to this date adapter. Fires a JSCDataEvent * of type: * * * @param newRange * the new range, if null it is similar to * clear */ public void setVal(TSDateRange newRange) { if (newRange == null) { clear(); return; } boolean wasEmpty = false; TSDateRange oldValue = null; synchronized (this) { // Nothing changed. if (newRange.equals(tsRange)) return; wasEmpty = isEmpty(); // No copy needed, because TSDateRange is immutable. oldValue = tsRange; tsRange = newRange; } // Dispatch event outside synchronized block. if (eventSupport == null) return; getEventSupport().dispatchEvent( JSCDataEvent.valueOfChanged(this, oldValue, newRange)); if (wasEmpty) { if (notEmptyEvent == null) notEmptyEvent = JSCDataEvent.valueOfEmptyState(this, false); getEventSupport().dispatchEvent(notEmptyEvent); } } /** * Gets the type of this JSCData object. * * @return JSCTypes.DRANGE */ public JSCTypes type() { return JSCTypes.DRANGE; } /** * Gets the underlying value, which is stored as a TSDateRange. * * @return the value object or null if this is * empty */ public synchronized Object value() { return tsRange; } }

Ads help maintain this website.