at.spardat.xma.mdl.list.ListDomWM Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* Copyright (c) 2003, 2007 s IT Solutions AT Spardat GmbH .
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* s IT Solutions AT Spardat GmbH - initial API and implementation
*******************************************************************************/
// @(#) $Id: ListDomWM.java 10268 2013-01-11 10:34:57Z dschwarz $
package at.spardat.xma.mdl.list;
import java.io.IOException;
import java.util.List;
import at.spardat.enterprise.fmt.IFmt;
import at.spardat.xma.mdl.ISelectable;
import at.spardat.xma.mdl.MemoryEstimator;
import at.spardat.xma.mdl.ModelChangeEvent;
import at.spardat.xma.mdl.NewModelEvent;
import at.spardat.xma.mdl.NewModelEventFactory;
import at.spardat.xma.mdl.Notification;
import at.spardat.xma.mdl.WModel;
import at.spardat.xma.mdl.util.DNode;
import at.spardat.xma.mdl.util.TransString;
import at.spardat.xma.mdl.util.TransStringSet1;
import at.spardat.xma.page.Page;
import at.spardat.xma.serializer.XmaInput;
import at.spardat.xma.serializer.XmaOutput;
import at.spardat.xma.test.TestUtil;
import at.spardat.xma.util.Assert;
/**
* The widget model that encapsulates domain values which are usually displayed in
* a combo box.
*
* The displayed entries in the combobox are drawn from a tabular data source
* specified by a parameter in the constructor. The datasource is required to
* provide three columns:
*
* - The first column is a key that uniquely identifies an entry. There
* must be no two entries with the same key. The key is also used to identify the
* entry when it comes to selection (see ISelectable).
*
- The second column is a short value, acting as a short identification
* for the end user. This data item usually is localized. Nevertheless, it is
* optional. If the short value is empty, the key is taken
* instead.
*
- The third column is a long value which fully describes the entry
* to the end user. Programmatically, these values are also optinal, although
* this does not make much sense. If the data source holds an empty long value,
* the key is taken instead.
*
*
* @author YSD, 18.04.2003 09:26:56
*/
public class ListDomWM extends WModel implements ISelectable, IListDomWM {
/**
* Specification of the datasource
*/
private TransString dataSource_ = new TransString();
/**
* This object holds the currently selected entry
*/
private TransStringSet1 selection_ = new TransStringSet1();
/**
* Defines whether the data-source is set in the UI-designer and provided
* as construction parameter or always set at runtime.
*/
private boolean dynamicDataSource_ = false;
/**
* The enclosing page
*/
private Page page_;
/**
* Constructs with a provided data source.
*
* @param id a numeric id which identifies the WidgetModel within its Page.
* @param pm reference to the enclosing Page
* @param dataSource specifies a tabular data source
* @exception IllegalArgumentException if dataSource is null or empty.
* @see at.spardat.xma.datasource.ITabularDataSource
*/
public ListDomWM (short id, Page pm, String dataSource) {
super (id, pm);
page_ = pm;
if (dataSource != null && dataSource.length() > 0) {
dataSource_.set(dataSource);
// mark dataSource_ having not changed since we are at the end of the constructor
dataSource_.commit();
}
}
/**
* @see at.spardat.xma.mdl.list.IListDomWM#setDataSource(java.lang.String)
*/
public void setDataSource (String dataSource) {
dataSource_.set(dataSource);
handle (new DataSourceChangedEvent());
}
/**
* @see at.spardat.xma.mdl.list.IListDomWM#getDataSource()
*/
public String getDataSource () {
return dataSource_.get();
}
/**
* @see at.spardat.xma.mdl.list.IListDomWM#isDynamicDataSource()
*/
public boolean isDynamicDataSource () {
return dynamicDataSource_;
}
/**
* Sets whether the data source is set at runtime or compile-time. This
* method may only be called immediately after construction by the generated
* XMA-code that is created from the UI-designer's generator.
*/
public void setDynamicDataSource (boolean what) {
dynamicDataSource_ = what;
dataSource_.set (null);
// mark dataSource_ having not changed since we are at the end of the constructor
dataSource_.commit();
}
/**
* @see at.spardat.xma.mdl.Transactional#changed()
*/
public boolean changed () {
return dataSource_.changed() || selection_.changed();
}
/**
* @see at.spardat.xma.mdl.Transactional#rollback()
*/
public void rollback () {
dataSource_.rollback();
selection_.rollback();
handle (new DataSourceChangedEvent ());
handle (new SelectionChangedEvent (false));
}
/**
* @see at.spardat.xma.mdl.Transactional#commit()
*/
public void commit () {
dataSource_.commit();
selection_.commit();
}
/**
* @see at.spardat.xma.mdl.WModel#handle(at.spardat.xma.mdl.ModelChangeEvent)
*/
public boolean handle (ModelChangeEvent event) {
return event.execute();
}
/**
* @see at.spardat.xma.mdl.Synchronization#externalize(at.spardat.xma.serializer.XmaOutput, boolean)
*/
public void externalize (XmaOutput xo, boolean forceFull) throws IOException {
// decide on what to write
byte what = 0;
boolean writeDS = forceFull || dataSource_.changed();
boolean writeSel = forceFull || selection_.changed();
if (writeDS) what |= 1;
if (writeSel) what |= 2;
xo.writeByte("DsOrSel", what);
if (writeDS) {
// externalize data source
dataSource_.externalize (xo, forceFull);
}
if (writeSel) {
// externalize selection
selection_.externalize (xo, forceFull);
}
}
/**
* @see at.spardat.xma.mdl.Synchronization#internalize(at.spardat.xma.serializer.XmaInput, List)
*/
public void internalize (XmaInput in, List formattable) throws IOException, ClassNotFoundException {
byte what = in.readByte();
boolean dsChanged = ((what & 1) != 0);
boolean selChanged = ((what & 2) != 0);
if (dsChanged) {
// dataSource
dataSource_.internalize(in, formattable);
}
if (selChanged) {
selection_.internalize(in, formattable);
}
if (dsChanged) {
handle (new DataSourceChangedEvent ());
}
if (selChanged) handle (new SelectionChangedEvent (false));
if (formattable != null && (selChanged || dsChanged)) {
formattable.add(this);
}
}
/**
* @see at.spardat.xma.mdl.ISelectable#deselect(java.lang.String)
*/
public void deselect (String key) {
if (key == null) throw new IllegalArgumentException();
selection_.remove(key);
handle (new SelectionChangedEvent(false));
}
/**
* @see at.spardat.xma.mdl.ISelectable#deselectAll()
*/
public void deselectAll () {
selection_.clear();
handle (new SelectionChangedEvent(false));
}
/**
* @see at.spardat.xma.mdl.ISelectable#getSelected()
*/
public String getSelected() {
return selection_.getSome();
}
/**
* @see at.spardat.xma.mdl.ISelectable#getSelection()
*/
public String[] getSelection() {
return selection_.getAll();
}
/**
* @see at.spardat.xma.mdl.ISelectable#getSelectionCount()
*/
public int getSelectionCount() {
return selection_.size();
}
/**
* @see at.spardat.xma.mdl.ISelectable#isMultiSelect()
*/
public boolean isMultiSelect() {
return false;
}
/**
* @see at.spardat.xma.mdl.ISelectable#isSelected(java.lang.String)
*/
public boolean isSelected(String key) {
return selection_.contains(key);
}
/**
* @see at.spardat.xma.mdl.ISelectable#isStrict()
*/
public boolean isStrict() {
return false;
}
/**
* @see at.spardat.xma.mdl.ISelectable#select(java.lang.String)
*/
public void select (String key) {
if (key == null) throw new IllegalArgumentException();
selection_.add(key);
handle (new SelectionChangedEvent(false));
}
/**
* Sets the selection of this ListDomWM to the given value.
* If value is empty (null or ""), the selection is cleared.
* @param value to select
*/
public void set(String value) {
if(value!=null && value.length()>0) {
select(value);
} else {
deselectAll();
}
}
/**
* @see at.spardat.xma.mdl.util.Descriptive#describe(at.spardat.xma.mdl.util.DNode)
*/
public void describe (DNode n) {
super.describe(n);
n.app("selection", selection_).comma();
n.app("dataSource", dataSource_);
}
/**
* Make random changes to this
*/
public void randomlyChange () {
if (Assert.ON) {
int change = TestUtil.randomInt(0, 3);
switch (change) {
case 0:
deselectAll();
break;
case 1:
deselect(TestUtil.randomString(TestUtil.randomInt(0, 2)));
break;
case 2:
select(TestUtil.randomString(TestUtil.randomInt(0, 2)));
break;
case 3:
setDataSource(TestUtil.draw(0.5) ? "Gender" : "StatusXMA");
break;
}
}
}
/**
* @see at.spardat.xma.mdl.WModel#equalsCS(at.spardat.xma.mdl.WModel, int)
*/
public void equalsCS (WModel mServer, int syncPoint) {
if (Assert.ON) {
ListDomWM ms = (ListDomWM) mServer;
if (!dataSource_.equals(ms.dataSource_)) throw new RuntimeException();
if (!selection_.equals(ms.selection_)) throw new RuntimeException();
}
}
/**
* Returns the page this widget model is part of.
*/
public Page getPage () {
return page_;
}
/**
* Removes the selection from this.
*
* @see at.spardat.xma.mdl.WModel#clear()
*/
public void clear () {
deselectAll();
}
/**
* Estimates the number of bytes this object consumes in memory.
*/
public int estimateMemory () {
return MemoryEstimator.sizeOfObject(4) + dataSource_.estimateMemory() + selection_.estimateMemory();
}
/**
* Event that notifies that a datasource has changed. This event does
* not modify the widget model.
*
* @author YSD, 18.04.2003 09:37:51
*/
class DataSourceChangedEvent extends Notification {
public DataSourceChangedEvent () {
super (ListDomWM.this, false);
}
}
/**
* Event that notifies that the selection has changed. This event does
* not modify the widget model.
*
* @author YSD, 18.04.2003 09:37:51
*/
class SelectionChangedEvent extends Notification {
public SelectionChangedEvent (boolean fromUI) {
super (ListDomWM.this, fromUI);
}
}
/**
* Event that changes a selection.
*
* @author YSD, 22.04.2003 21:35:20
*/
class SelectionChangeEvent extends ModelChangeEvent {
/**
* Constructor
*
* @param newSelection the new selection key or null if any selection
* should be removed
* @param fromUI indicates if UI emenates the event
*/
public SelectionChangeEvent (String newSelection, boolean fromUI) {
super (ListDomWM.this, fromUI);
newSel_ = newSelection;
}
/**
* @see at.spardat.xma.mdl.ModelChangeEvent#execute()
*/
public boolean execute() {
if (newSel_ == null) selection_.clear();
else selection_.add (newSel_);
return true;
}
private String newSel_;
}
/**
* Event class used to notify the dynamic registration of a new ListDomWM.
* @author gub
* @since 2.1.0
* @see Page#addWModel(WModel)
*/
public static class NewListDomWMEvent extends NewModelEvent {
String dataSource;
int style;
/** empty contructor for deserialization */
public NewListDomWMEvent() {}
/**
* constructor which initializes dataSource and style
* @param dataSource specifies a tabular data source
* @param style one of the SHOW_-constants or MANDATORY defined in {@link IListDomWMClient}.
*/
public NewListDomWMEvent(String dataSource,int style) {
this.dataSource=dataSource;
this.style=style;
}
// see at.spardat.xma.mdl.NewModelEvent.getType()
public byte getType() {
return NewModelEventFactory.ListDomWM;
}
// see at.spardat.xma.mdl.NewModelEvent.createModel()
public WModel createModel(short id,Page page) {
return new ListDomWM(id,page,dataSource);
}
// see at.spardat.xma.mdl.NewModelEvent.serialize()
public void serialize(XmaOutput out) throws IOException {
super.serialize(out);
out.writeStringN("dataSource", dataSource);
out.writeInt("style",style);
}
// see at.spardat.xma.mdl.NewModelEvent.deserialize()
public void deserialize(XmaInput in) throws IOException, ClassNotFoundException {
super.deserialize(in);
dataSource=in.readStringN();
style=in.readInt();
}
}
// see at.sparda.xma.mdl.WModel.createNewModelEvent()
public NewModelEvent createNewModelEvent() {
return new NewListDomWMEvent(getDataSource(),0);
}
public boolean isValid() {
IFmt fmt = getFmtInternal();
if (fmt != null) {
// FIXME test with empty domain values
if (getSelected() == null && fmt.isMandatory()) {
return false;
}
return fmt.isLegalInternal(getSelected());
}
return true;
}
}