001    package market.stdform;
002    
003    import java.awt.Component;
004    import java.util.ArrayList;
005    import java.util.Collections;
006    import java.util.Comparator;
007    import java.util.Iterator;
008    import java.util.LinkedList;
009    import java.util.List;
010    
011    import javax.swing.JComponent;
012    import javax.swing.JPanel;
013    
014    import market.JDDShowMessage;
015    import market.swing.JTFCheckable;
016    import sale.FormSheet;
017    import sale.FormSheetContentCreator;
018    import data.stdforms.SingleTableFormSheet;
019    
020    /**
021     * This special FormSheet wraps "normal" {@link FormSheet FormSheets} and provides the possibilty to both
022     * check special {@link JTFCheckable checkable text fields} for valid entries and to retrieve those entries.
023     * Furthermore, this class generates error messages in case one or more of those special text fields
024     * contain invalid entries.
025     * However, {@link JTFCheckable checkable text fields} have already to be defined in the original
026     * FormSheet.
027     */
028    public class FSCheckable extends FormSheet implements java.io.Serializable {
029    
030            /**
031             * ID for serialization.
032             */
033            private static final long serialVersionUID = -1694484775963078540L;
034            
035            /**
036         * The original FormSheet to be wrapped.
037         */
038        private FormSheet formSheet;
039        private List<JTFCheckable> checkableComponents, invalidFields;
040        public static final int NO_ERRORMESSAGE = 0;
041        public static final int FIRST_ERRORMESSAGE = 1;
042        public static final int ALL_ERRORMESSAGES_SEQUENTIALLY = 2;
043        public static final int ALL_ERRORMESSAGES_AT_ONCE = 3;
044    
045        /**
046         * Creates an empty FormSheet, sets the content and the buttons of the FormSheet
047         * which is passed as parameter as its own.
048         *
049         * @param fs the FormSheet to be wrapped.
050         */
051        public FSCheckable(FormSheet fs) {
052            super(fs.getCaption(), (JComponent)null);
053            this.formSheet = fs;
054            addContentCreator(new FormSheetContentCreator() {
055                            private static final long serialVersionUID = -3561459139876017583L;
056                            protected void createFormSheetContent(FormSheet fsOrig) {
057                    fsOrig.setComponent(formSheet.getComponent());
058                    setButtons(getButtons());
059                }
060            });
061            invalidFields = new ArrayList<JTFCheckable>();
062        }
063    
064        /**
065         * @return a List of all buttons in the {@link #formSheet formSheet's} button bar
066         */
067        public List getButtons() {
068            List<FormButton> buttonList = new LinkedList<FormButton>();
069            Iterator<FormButton> it = formSheet.buttonIterator(false);
070            while (it.hasNext()) {
071                buttonList.add(it.next());
072            }
073            return buttonList;
074        }
075    
076        /**
077         * Sets buttons to the button bar.
078         *
079         * @param buttonList the list of buttons to be set.
080         */
081        public void setButtons(List buttonList) {
082            removeAllButtons();
083            Iterator it = buttonList.iterator();
084            while (it.hasNext()) {
085                addButton((FormButton)it.next());
086            }
087        }
088    
089    
090        /**
091         * @param number the ID of the desired {@link JTFCheckable}
092         * @return the text of a {@link JTFCheckable}
093         */
094        public String getEntry(int number) {
095            JTFCheckable ctf = null;
096            boolean found = false;
097            checkableComponents = getCheckableComponents(getComponent());
098            Iterator it = checkableComponents.iterator();
099            while (it.hasNext() && !found) {
100                ctf = (JTFCheckable)it.next();
101                found = (ctf.getID() == number);
102            }
103            return found ? ctf.getText() : "";
104        }
105    
106        /**
107         * Checks all {@link JTFCheckable JTFCheckables} for validity entries.
108         * @param option the style of the {@link #generateErrorMessage(int, boolean) error message} to be created.
109         * @param sorted the order of the {@link #generateErrorMessage(int, boolean) error messages} to be created.
110         * @return true, if all checkable text fields contain a valid value, else false.
111         */
112        public boolean checkTextFields(int option, boolean sorted) {
113            boolean returnValue = true;
114            JTFCheckable nextField = null;
115            checkableComponents = getCheckableComponents(getComponent());
116            Iterator<JTFCheckable> it = checkableComponents.iterator();
117            while (it.hasNext()) {
118                nextField = (JTFCheckable)it.next();
119                if (!nextField.hasValidValue()) {
120                    returnValue = false;
121                    invalidFields.add(nextField);
122                };
123            }
124            if (!returnValue) {
125                generateErrorMessage(option, sorted);
126            }
127            invalidFields.clear();
128            return returnValue;
129        }
130    
131        /**
132         * Generates error messages for {@link JTFCheckable checkable text fields} that do not contain
133         * valid values.
134         * @param option defines style of the error message.
135         *  <ul><li>0: show no error messages</li>
136         *      <li>1: show only first error message</li>
137         *      <li>2: show all error messages sequentially</li>
138         *      <li>3: show all error messages at once</l>
139         *  </ul>
140         * @param sorted Select if the error messages should be displayed in the order the associated
141         * {@link JTFCheckable checkable text fields} have been added to the FormSheet (false)<br>
142         * or sorted by their ButtonIDs (true).
143         */
144        private void generateErrorMessage(int option, boolean sorted) {
145            List invF = sorted ? sort(invalidFields) : invalidFields;
146            Iterator it = invF.iterator();
147            JTFCheckable ctf = null;
148            switch (option) {
149                case 1:
150                    JDDShowMessage.showMessageDialog(this, ((JTFCheckable)it.next()).getErrorMessage(),
151                            "Fehlerhafte Eingabe");
152                    break;
153                case 2:
154                    while (it.hasNext()) {
155                        ctf = (JTFCheckable)it.next();
156                        JDDShowMessage.showMessageDialog(this, ctf.getErrorMessage(), "Fehlerhafte Eingabe");
157                    }
158                   break;
159                case 3:
160                    String s = "";
161                    while (it.hasNext()) {
162                        ctf = (JTFCheckable)it.next();
163                        s += "- " + ctf.getErrorMessage() + "\n";
164                    }
165                    JDDShowMessage.showMessageDialog(this, s, "Fehlerhafte Eingabe");
166                    break;
167            }
168        }
169    
170        /**
171         * Sorts a List of {@link JTFCheckable checkable text fields} by their IDs.
172         *
173         * @param toSort the list of checkable text fields to be sorted.
174         * @return the sorted list.
175         */
176        private List<JTFCheckable> sort(List<JTFCheckable> toSort) {
177            Collections.sort(toSort, new Comparator<JTFCheckable>() {
178                public int compare(JTFCheckable o1, JTFCheckable o2) {
179                    return (o1.getID() - o2.getID());
180                }
181            });
182            return toSort;
183        }
184    
185        /**
186         * Recursively searches a given JComponent for CheckableTextFields.
187         *
188         * @param comp the user interface's component to be searched upon.
189         * @return a list of all {@link JTFCheckable checkable text fields}.
190         */
191        private List<JTFCheckable> getCheckableComponents(JComponent comp) {
192            List<JTFCheckable> returnComponents = new ArrayList<JTFCheckable>();
193            Component[] comps = comp.getComponents();
194            for (int i = 0; i < comps.length; i++) {
195                //add all Components following recursions might find
196                if (comps[i] instanceof JPanel) {
197                    returnComponents.addAll(getCheckableComponents((JComponent)comps[i]));
198                };
199                //check for Class market.stdform.JTFCheckable, if found add Component to list
200                if (comps[i] instanceof JTFCheckable) {
201                    returnComponents.add((JTFCheckable) comps[i]);
202                }
203            }
204            return returnComponents;
205        }
206    
207        /**
208         * @return the selected Record of an embedded {@link SingleTableFormSheet}.
209         * If no SingleTableFormSheet is embedded, null is returned.
210         */
211        public Object getSelectedRecord() {
212            if (formSheet instanceof SingleTableFormSheet) {
213                return ((SingleTableFormSheet)formSheet).getSelectedRecord();
214            } else {
215                return null;
216            }
217        }
218    
219        /**
220         * @return the FormSheet which is wrapped by this FSCheckable.
221         */
222        public FormSheet getFormSheet(){
223            return this.formSheet;
224        }
225    }