001/*
002 * Copyright 2010-2015 Institut Pasteur.
003 * 
004 * This file is part of Icy.
005 * 
006 * Icy is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 * 
011 * Icy is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU General Public License for more details.
015 * 
016 * You should have received a copy of the GNU General Public License
017 * along with Icy. If not, see <http://www.gnu.org/licenses/>.
018 */
019package icy.type.value;
020
021import icy.file.xml.XMLPersistent;
022import icy.util.XMLUtil;
023
024import java.util.ArrayList;
025
026import org.w3c.dom.Node;
027
028/**
029 * @author Stephane
030 */
031public abstract class AbstractValue<T> implements Comparable<T>, XMLPersistent
032{
033    public interface ValueChangeListener<T>
034    {
035        public void valueChanged(AbstractValue<T> source);
036    }
037
038    protected static final String ID_VALUE = "value";
039
040    /**
041     * value
042     */
043    protected T value;
044
045    /**
046     * listeners
047     */
048    private final ArrayList<ValueChangeListener<T>> listeners;
049
050    public AbstractValue(T value)
051    {
052        super();
053
054        this.value = value;
055        listeners = new ArrayList<ValueChangeListener<T>>();
056    }
057
058    public AbstractValue()
059    {
060        super();
061
062        this.value = getDefaultValue();
063        listeners = new ArrayList<ValueChangeListener<T>>();
064    }
065
066    public T getValue()
067    {
068        return value;
069    }
070
071    public void setValue(T value)
072    {
073        if (!this.value.equals(value))
074        {
075            this.value = value;
076            changed();
077        }
078    }
079
080    public abstract boolean loadFromString(String s);
081
082    public abstract T getDefaultValue();
083
084    public void loadFromString(String s, T def)
085    {
086        if (!loadFromString(s))
087            value = def;
088    }
089
090    @Override
091    public boolean saveToXML(Node node)
092    {
093        if (node == null)
094            return false;
095
096        XMLUtil.setElementValue(node, ID_VALUE, value.toString());
097
098        return true;
099    }
100
101    @Override
102    public boolean loadFromXML(Node node)
103    {
104        if (node == null)
105            return false;
106
107        return loadFromString(XMLUtil.getElementValue(node, ID_VALUE, ""));
108    }
109
110    // value changed
111    private void changed()
112    {
113        fireChangeEvent();
114    }
115
116    public void addListener(ValueChangeListener<T> listener)
117    {
118        synchronized (listeners)
119        {
120            if (!listeners.contains(listener))
121                listeners.add(listener);
122        }
123    }
124
125    public void removeListener(ValueChangeListener<T> listener)
126    {
127        synchronized (listeners)
128        {
129            listeners.remove(listener);
130        }
131    }
132
133    protected void fireChangeEvent()
134    {
135        final ArrayList<ValueChangeListener<T>> listenersCopy;
136
137        synchronized (listeners)
138        {
139            listenersCopy = new ArrayList<ValueChangeListener<T>>(listeners);
140        }
141
142        for (ValueChangeListener<T> l : listenersCopy)
143            l.valueChanged(this);
144    }
145}