001package votorola.a.count.gwt; // Copyright 2011, Michael Allan.  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Votorola Software"), to deal in the Votorola Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Votorola Software, and to permit persons to whom the Votorola Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Votorola Software. THE VOTOROLA SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE VOTOROLA SOFTWARE OR THE USE OR OTHER DEALINGS IN THE VOTOROLA SOFTWARE.
002
003import com.google.gwt.core.client.*;
004import com.google.gwt.event.logical.shared.*;
005import com.google.gwt.regexp.shared.*;
006import com.google.gwt.user.client.Window;
007import votorola.g.lang.*;
008//import votorola.g.web.gwt.*;
009import votorola.g.web.gwt.event.*;
010
011
012/** A controller to maintain a superaccount selection in sync with the value of an 'a'
013  * switch.
014  *
015  *     @see SacSelection#aSacSwitch()
016  */
017public final class SacSetter extends CoalescingSchedulerS implements Scheduler.ScheduledCommand,
018  ValueChangeHandler<String>
019{
020
021
022    /** Constructs the SacSetter for a given selection model.  Construct at most one for
023      * the entire life of the selection model, as currently it does not unregister its
024      * handlers.
025      *
026      *     @param _sacSelection the superaccount selection model in which this controller
027      *       operates.  This is also the source for all events.
028      *     @param _phaser the scheduling phaser for state changes, which is exposed as
029      *       {@linkplain #phaser phaser}().
030      *     @param eventsPhaser the scheduling phaser for the dispatch of events
031      *       consequent on state changes.
032      */
033    public SacSetter( SacSelection _sacSelection,  Phaser _phaser, final Phaser eventsPhaser )
034    {
035        super( Scheduler.get(), _phaser );
036        sacSelection = _sacSelection;
037        init( SacSetter.this );
038
039        gun = new CoalescingSelectionChangeGun( sacSelection, eventsPhaser );
040        sacSelection.aSacSwitch().addHandler( SacSetter.this ); // no need to unregister, registry does not outlive this listener
041        syncFromSwitch(); // init state
042    }
043
044
045
046   // ------------------------------------------------------------------------------------
047
048
049    /** The superaccount that is currently set, which is also to be used as the return
050      * value in the implementation of SacSelection.{@linkplain SacSelection#getSac()
051      * getSac}().
052      */
053    public SacJS sac() { return sac; }
054
055
056        private SacJS sac;
057
058
059        /** Sets the superaccount without firing an event and returns true if this
060          * resulted in a change, false otherwise.
061          *
062          *     @see #sac()
063          */
064        private boolean setSac( final SacJS newSac )
065        {
066            if( ObjectX.nullEquals( newSac, sac )) return false;
067
068            sac = newSac;
069            return true;
070        }
071
072
073
074   // - S c h e d u l e r . S c h e d u l e d - C o m m a n d ----------------------------
075
076
077    /** Synchronizes the superaccount setting from the 'a' switch, and schedules a
078      * selection change event for any state change that results.
079      */
080    public void execute() { if( syncFromSwitch() ) gun.schedule(); }
081
082
083
084   // - V a l u e - C h a n g e - H a n d l e r ------------------------------------------
085
086
087    public void onValueChange( ValueChangeEvent<String> _e ) { schedule(); }
088
089
090
091//// P r i v a t e ///////////////////////////////////////////////////////////////////////
092
093
094    private final CoalescingSelectionChangeGun gun;
095
096
097
098    private final SacSelection sacSelection;
099
100
101    /** Synchronizes the superaccount from the 'a' switch without firing an event and
102      * returns true if this resulted in a change, false otherwise.
103      *
104      *     @see #sac()
105      *     @see SacSelection#aSacSwitch()
106      */
107    private final @Warning("init call") boolean syncFromSwitch()
108    {
109        final CountJS count = sacSelection.count();
110        if( count == null ) return setSac( null );
111
112        final String a = sacSelection.aSacSwitch().get();
113        if( a == null ) return setSac( count.voteSuperaccount() );
114
115        final MatchResult m = SacSelection.A_PATTERN.exec( a );
116        if( a == null )
117        {
118            Window.alert( "Malformed superaccount switch: a=" + a );
119            return setSac( count.nullSuperaccount() );
120        }
121
122        final CountingMethodJS.SwitchMnemonic countingMethodMnemonic;
123        {
124            final String name = m.getGroup( 1 );
125            try{ countingMethodMnemonic = CountingMethodJS.SwitchMnemonic.valueOf( name ); }
126            catch( final IllegalArgumentException x )
127            {
128                Window.alert( "Malformed superaccount switch, no such counting method \""
129                  + name + "\": a=" + a );
130                return setSac( count.nullSuperaccount() );
131            }
132        }
133
134        final String accountName = m.getGroup( 2 );
135        final SacJS newSac = count.superaccount( countingMethodMnemonic.fullName(), accountName );
136        if( newSac == null )
137        {
138            Window.alert( "Current count has no such superaccount: a=" + a );
139            return setSac( count.nullSuperaccount() );
140        }
141
142        return setSac( newSac );
143    }
144
145
146
147}