package javabeansexample;

import java.io.*;
import java.util.*;
import java.beans.*;

class MyGregCalendar extends GregorianCalendar
{
    public MyGregCalendar () {}
    public MyGregCalendar (int y, int m, int d) { super(y,m,d); }
    
    public String toString ()
    {
        return get(Calendar.DAY_OF_MONTH)+"-"+get(Calendar.MONTH)+"-"+get(Calendar.YEAR);
    }
}

/** klasa ziarna którą można serializować */
class Ziarno implements Serializable
{
    /** wsparcie dla nasłuchu zmian */
    private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    /** wsparcie dla wetowania zmian */
    private VetoableChangeSupport vcs = new VetoableChangeSupport(this);

    /** konstruktor bezparametrowy */
    public Ziarno () {}

    /** przyłączanie i odłączanie słuchaczy zdarzeń związanych ze zmianami właściwości */
    public synchronized void addPropertyChangeListener (PropertyChangeListener lst)
        { pcs.addPropertyChangeListener(lst); }
    public synchronized void removePropertyChangeListener (PropertyChangeListener lst)
        { pcs.removePropertyChangeListener(lst); }
    /** przyłączanie i odłączanie słuchaczy zdarzeń związanych z wetowaniem zmian właściwości*/
    public synchronized void addVetoableChangeListener (VetoableChangeListener lst)
        { vcs.addVetoableChangeListener(lst); }
    public synchronized void removeVetoableChangeListener (VetoableChangeListener lst)
        { vcs.removeVetoableChangeListener(lst); }

    /** właściwość nieograniczana */
    protected String tekst = "teraz jest ";
    /** getter dla właściwości tekst */
    public synchronized String getTekst ()
        { return tekst; }
    /** setter dla właściwości tekst */
    public synchronized void setTekst (String nowyTekst)
    {
        String staryTekst = tekst;
        tekst = nowyTekst;
        pcs.firePropertyChange(new PropertyChangeEvent(this,"tekst",staryTekst,nowyTekst));
    }

    /** właściwość ograniczana */
    protected MyGregCalendar data = new MyGregCalendar();
    /** getter dla właściwości data */
    public synchronized MyGregCalendar getData ()
        { return data; }
    /** setter dla właściwości data */
    public synchronized void setData (MyGregCalendar nowaData) throws PropertyVetoException
    {
        MyGregCalendar staraData = data;
        vcs.fireVetoableChange("data",staraData,nowaData);
        data = nowaData;
        pcs.firePropertyChange("data",staraData,nowaData);
    }

    /** prezentacja obiektu ziarna */
    public String toString ()
    {
        return tekst+data;
    }
}

/** decydent w sprawach zmiany daty w obiekcie Ziarno */
class DatownikDolny implements VetoableChangeListener, Serializable
{
    protected MyGregCalendar granica;
    
    public DatownikDolny ()
    {
        granica = new MyGregCalendar();
    }
    public DatownikDolny (MyGregCalendar d)
    {
        if (d==null) throw new NullPointerException();
        granica = d;
    }

    public void vetoableChange (PropertyChangeEvent ev) throws PropertyVetoException
    {
        if (!ev.getPropertyName().equals("data")) return;
        MyGregCalendar d = (MyGregCalendar)ev.getNewValue();
        if (d.compareTo(granica)<0) { System.out.println("za wcześnie");
            throw new PropertyVetoException("za wcześnie",ev); }
    }
}

/** decydent w sprawach zmiany daty w obiekcie Ziarno */
class DatownikGorny implements VetoableChangeListener, Serializable
{
    protected MyGregCalendar granica;
    
    public DatownikGorny ()
    {
        granica = new MyGregCalendar();
    }
    public DatownikGorny (MyGregCalendar d)
    {
        if (d==null) throw new NullPointerException();
        granica = d;
    }
    
    public void vetoableChange (PropertyChangeEvent ev) throws PropertyVetoException
    {
        if (!ev.getPropertyName().equals("data")) return;
        MyGregCalendar d = (MyGregCalendar)ev.getNewValue();
        if (d.compareTo(granica)>0) { System.out.println("za późno");
            throw new PropertyVetoException("za późno",ev); }
    }
}

/** obserwator zmian tekstu i daty w obiekcie Ziarno */
class Komentator implements PropertyChangeListener, Serializable
{
    protected int granica = 15;
    
    public void propertyChange (PropertyChangeEvent ev)
    {
        System.out.println("zmiana właściwości "+ev.getPropertyName()+": "+ev.getNewValue());
    }
}

public class TestJavaBeans extends Object
{
    public static void main (String[] args)
    {
        Ziarno z = new Ziarno();
        DatownikDolny dolny = new DatownikDolny(new MyGregCalendar(2000,1,1));
        DatownikGorny gorny = new DatownikGorny(new MyGregCalendar(2011,12,31));
        Komentator koment = new Komentator();
        z.addVetoableChangeListener(dolny);
        z.addVetoableChangeListener(gorny);
        z.addPropertyChangeListener(koment);

        System.out.println(z);
        z.setTekst("dziś mamy ");
        try { z.setData(new MyGregCalendar(2010,2,28)); } catch (Exception ex) {}
        System.out.println(z);
        try { z.setData(new MyGregCalendar(1990,12,31)); } catch (Exception ex) {}
        System.out.println(z);
        try { z.setData(new MyGregCalendar(2012,12,31)); } catch (Exception ex) {}
        System.out.println(z);
    }
}
