001    package sale;
002    
003    import users.User;
004    
005    /**
006     * A {@link Gate gate} at which a {@link FormSheet} and/or a {@link MenuSheet} can be displayed. The
007     * {@link Transition transition} that leaves the gate will depend on the users interaction with the Form-
008     * and/or MenuSheet.
009     *
010     * @author Steffen Zschaler
011     * @version 2.0 17/08/1999
012     * @since v2.0
013     */
014    public class UIGate extends Object implements Gate {
015    
016        /**
017             * ID for serialization.
018             */
019            private static final long serialVersionUID = -7238925184403757729L;
020    
021            /**
022         * The FormSheet to be displayed.
023         *
024         * @serial
025         */
026        protected FormSheet m_fsFormSheet;
027    
028        /**
029         * The MenuSheet to be displayed.
030         *
031         * @serial
032         */
033        protected MenuSheet m_msMenuSheet;
034    
035        /**
036         * The transition that will leave this gate.
037         */
038        private transient Transition m_tTransition;
039    
040        /**
041         * The monitor synchronizing access to the elements as well as a communications channel.
042         */
043        private transient Object m_oLock;
044    
045        /**
046         * Return the monitor synchronizing access to the elements as well as a communications channel.
047         *
048         * @override Never
049         */
050        private final Object getLock() {
051            if (m_oLock == null) {
052                m_oLock = new Object();
053            }
054    
055            return m_oLock;
056        }
057    
058        /**
059         * Bit field indicating the last change.
060         */
061        private transient int m_nChanged = NOTHING;
062        /**
063         * Nothing changed.
064         */
065        private static final int NOTHING = 0;
066        /**
067         * The FormSheet changed.
068         */
069        private static final int FORMSHEET = 1;
070        /**
071         * The MenuSheet changed.
072         */
073        private static final int MENUSHEET = 2;
074        /**
075         * The transition was set.
076         */
077        private static final int TRANSITION = 8;
078    
079        /**
080         * Create a new UIGate.
081         *
082         * @param fs the FormSheet to be displayed. Can be <code> null</code>.
083         * @param ms the MenuSheet to be displayed. Can be <code> null</code>.
084         */
085        public UIGate(FormSheet fs, MenuSheet ms) {
086            super();
087    
088            m_fsFormSheet = fs;
089            m_msMenuSheet = ms;
090        }
091    
092        /**
093         * Returns the next Transition to jump to.
094         * @override Never
095         */
096        public Transition getNextTransition(SaleProcess pOwner, User usr) throws InterruptedException {
097    
098            synchronized (getLock()) {
099                m_tTransition = null;
100                m_nChanged = FORMSHEET | MENUSHEET;
101                // e.g. 0011 & 1000 == 0000 => something changed, but no transition found yet
102                while ((m_nChanged & TRANSITION) == 0) {
103                    // e.g. 0011 & 0010 == 0010 => MenuSheet changed
104                    if ((m_nChanged & MENUSHEET) != 0) {
105                        pOwner.getContext().setMenuSheet(pOwner, m_msMenuSheet);
106                    }
107                    // e.g. 0011 & 0001 == 0001 => FormSheet changed
108                    if ((m_nChanged & FORMSHEET) != 0) {
109                        if (m_fsFormSheet != null) {
110                            m_fsFormSheet.setWaitResponse(false);
111                        }
112                        pOwner.getContext().setFormSheet(pOwner, m_fsFormSheet);
113                    }
114    
115                    m_nChanged = NOTHING;
116    
117                    getLock().wait();
118                }
119            }
120            return m_tTransition;
121        }
122    
123        /**
124         * Set the FormSheet that is being displayed at this Gate.
125         *
126         * @override Never
127         *
128         * @param fs the new FormSheet
129         */
130        public void setFormSheet(FormSheet fs) {
131            synchronized (getLock()) {
132                m_fsFormSheet = fs;
133                m_nChanged |= FORMSHEET;
134    
135                getLock().notifyAll();
136            }
137        }
138    
139        /**
140         * Set the MenuSheet that is being displayed at this gate.
141         *
142         * @override Never
143         *
144         * @param ms the MenuSheet.
145         */
146        public void setMenuSheet(MenuSheet ms) {
147            synchronized (getLock()) {
148                m_msMenuSheet = ms;
149                m_nChanged |= MENUSHEET;
150    
151                getLock().notifyAll();
152            }
153        }
154    
155        /**
156         * Set the transition that will leave this gate. This will leave the gate at once and enter the Transition.
157         * The transition may return to the gate.
158         *
159         * @override Never
160         *
161         * @param tNext the transition. Must not be <code>null</code>.
162         */
163        public void setNextTransition(Transition tNext) {
164            if (tNext == null) {
165                throw new NullPointerException();
166            }
167    
168            synchronized (getLock()) {
169                m_tTransition = tNext;
170                m_nChanged |= TRANSITION;
171    
172                getLock().notifyAll();
173            }
174        }
175    }