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