View Javadoc

1   package at.ac.tuwien.ifs.bpse.basic.gui;
2   
3   import java.awt.BorderLayout;
4   import java.awt.GridLayout;
5   import java.awt.event.ActionEvent;
6   import java.awt.event.ActionListener;
7   import java.awt.event.WindowAdapter;
8   import java.awt.event.WindowEvent;
9   import java.util.ArrayList;
10  import java.util.List;
11  import java.util.ResourceBundle;
12  
13  import javax.swing.BorderFactory;
14  import javax.swing.JButton;
15  import javax.swing.JFrame;
16  import javax.swing.JLabel;
17  import javax.swing.JPanel;
18  
19  import org.apache.commons.logging.Log;
20  import org.apache.commons.logging.LogFactory;
21  import org.springframework.beans.factory.xml.XmlBeanFactory;
22  import org.springframework.core.io.ClassPathResource;
23  
24  import at.ac.tuwien.ifs.bpse.basic.dao.IStudentDAO;
25  import at.ac.tuwien.ifs.bpse.basic.domain.Student;
26  import at.ac.tuwien.ifs.bpse.basic.helper.Constants;
27  
28  /**
29   * The EditStudentFrame provides functionality for editing and creating
30   * Students. It utilizes a JPanel with a ContentPane and a BorderLayout. The
31   * CenterPanel contains the DataFields and the SouthPanel all the Buttons.
32   * 
33   * @author The SE-Team
34   * @version 1.2
35   */
36  public class EditStudentFrame extends JFrame implements ActionListener {
37  	/**
38  	 * Default serialVersionUID, generated by eclipse.
39  	 */
40  	private static final long serialVersionUID = 7321985214545293077L;
41  
42  	/**
43  	 * Retrieves the logger for this class.
44  	 */
45  	private static Log log = LogFactory.getLog(EditStudentFrame.class);
46  	
47  	/**
48  	 * ResourceBundle to externalize the Strings used for the GUI components.
49  	 */
50  	private ResourceBundle messageBundle;
51  
52  	/**
53  	 * The Data Access Object for Students.
54  	 */
55  	private IStudentDAO studentDAO;
56  
57  	/**
58  	 * The to-be-edited Student.
59  	 */
60  	private Student student;
61  
62  	/**
63  	 * The XML Bean Factory from Spring.
64  	 */
65  	private XmlBeanFactory xbf;
66  
67  	/**
68  	 * The list of ActionListeners for this Frame.
69  	 */
70  	private List<ActionListener> updateListeners;
71  
72  	/**
73  	 * Enumeration of different Modes the EditStudentFrame can be used with.
74  	 * Possible modes are:
75  	 * <ul>
76  	 * <li><code>Create</code> for creating a new Student.</li>
77  	 * <li><code>Update</code> for updating an existing Student.</li>
78  	 * </ul>
79  	 * 
80  	 * @author The SE-Team
81  	 * @see EditStudentFrame#EditStudentFrame(Student, Mode)
82  	 */
83  	public enum Mode {
84  		/**
85  		 * Use this mode to create a Student.
86  		 */
87  		Create,
88  
89  		/**
90  		 * Use this mode to update a Student.
91  		 */
92  		Update,
93  	};
94  
95  	/**
96  	 * The current mode of operation, gets set in constructor.
97  	 * 
98  	 * @see EditStudentFrame#EditStudentFrame(Student, Mode)
99  	 */
100 	private Mode mode;
101 
102 	/**
103 	 * Textfield for the Database-assigned ID.
104 	 */
105 	private JLabel idLabel;
106 
107 	/**
108 	 * Textfields for StudentData.
109 	 */
110 	private RegexTextField txtMatrNr, txtVorname, txtNachname, txtEmail;
111 
112 	/**
113 	 * associated Regexes.
114 	 */
115 	private final static String regexMatrNr = "\\d{7}", regexVorname = ".+",
116 			regexNachname = ".+",
117 			regexEmail = ".{2,}@[a-zA-Z0-9\\.-]+\\.[a-z]{2,4}";
118 
119 	/**
120 	 * The "Action"-Button.
121 	 */
122 	private JButton saveButton;
123 
124 	private JPanel centerBox;
125 
126 	/**
127 	 * Create and show EditStudentFrame for creating a new student.
128 	 * 
129 	 * @see #EditStudentFrame(Student, Mode)
130 	 */
131 	public EditStudentFrame() {
132 		this(null, Mode.Create);
133 		setResizable(false);
134 	}
135 	
136 	/**
137 	 * Create and show EditStudentFrame with the given student.
138 	 * 
139 	 * @param student
140 	 *            The Student to show.
141 	 * @param mode
142 	 *            Create or Update. Create is default.
143 	 * @see Mode
144 	 * @since 1.1
145 	 */
146 	public EditStudentFrame(Student student, Mode mode) {
147 		super();
148 		this.mode = mode;
149 		initDAO();
150 		initMessageBundle();
151 		log.info("Initializing EditStudentFrame");
152 		this.student = student;
153 		// Handler for WindowClosing
154 		addWindowListener(new WindowAdapter() {
155 			public void windowClosing(WindowEvent arg0) {
156 				super.windowClosing(arg0);
157 				closeFrame();
158 			}
159 		});
160 		initModels();
161 		initComponents();
162 	}
163 
164 	/**
165 	 * Adds ActionListener to be notified when the database has been changed.
166 	 * The component's <code>actionPerformed()</code> method will be invoked
167 	 * on database changes.
168 	 * 
169 	 * @param l
170 	 *            the ActionListener to be added
171 	 * @since 1.1
172 	 */
173 	public void addUpdateListener(ActionListener l) {
174 		updateListeners.add(l);
175 	}
176 
177 	/**
178 	 * Notify all suscribers of the database-change event. UpdateListeners have
179 	 * to register via <code>addUpdateListener()</code> in order to be
180 	 * notified.
181 	 * 
182 	 * @see #addUpdateListener(ActionListener)
183 	 * @since 1.1
184 	 */
185 	private void notifyUpdateListener() {
186 		ActionEvent evt = new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
187 				"Save");
188 		for (ActionListener l : updateListeners) {
189 			l.actionPerformed(evt);
190 		}
191 	}
192 
193 	/**
194 	 * Sets a Log Marker and calls <code>this.dispose()</code>.
195 	 */
196 	private void closeFrame() {
197 		log.info("Close EditStudentFrame");
198 		this.dispose();
199 	}
200 
201 	/**
202 	 * This method is called once by the constructor to initialize the
203 	 * components in the Model.
204 	 */
205 	private void initComponents() {
206 		// InitFrame
207 		switch (this.mode) {
208 		case Create:
209 			setTitle("Create new Student");
210 			break;
211 		case Update:
212 			setTitle("Edit existing Student");
213 			break;
214 		}
215 		// Fill Frame
216 		JPanel mainPanel = new JPanel();
217 		getContentPane().add(mainPanel);
218 		mainPanel.setLayout(new BorderLayout(5, 5));
219 		// CenterPanel contains DataFields
220 		centerBox = new JPanel();
221 		centerBox.setBorder(BorderFactory.createEmptyBorder(10, 10, 5, 10));
222 		centerBox.setLayout(new GridLayout(0, 2, 5, 5));
223 		// ID
224 		idLabel = new JLabel("<assigned from DB>");
225 		if (this.mode != Mode.Create) {
226 			JLabel lblId = new JLabel(messageBundle.getString("lbl.id"));
227 			centerBox.add(lblId);
228 			//idLabel.setEditable(false);
229 			centerBox.add(idLabel);
230 		}
231 		// Matrikel Number
232 		JLabel lblMatrNr = new JLabel(messageBundle.getString("lbl.studentid"));
233 		centerBox.add(lblMatrNr);
234 		txtMatrNr = new RegexTextField("");
235 		txtMatrNr.setRegex(regexMatrNr);
236 		txtMatrNr.setValidationIndicator(lblMatrNr);
237 		centerBox.add(txtMatrNr);
238 		// First Name
239 		JLabel lblVorname = new JLabel(messageBundle.getString("lbl.firstname"));
240 		centerBox.add(lblVorname);
241 		txtVorname = new RegexTextField("");
242 		txtVorname.setRegex(regexVorname);
243 		txtVorname.setValidationIndicator(lblVorname);
244 		centerBox.add(txtVorname);
245 		// Last Name
246 		JLabel lblNachname = new JLabel(messageBundle.getString("lbl.lastname"));
247 		centerBox.add(lblNachname);
248 		txtNachname = new RegexTextField("");
249 		txtNachname.setRegex(regexNachname);
250 		txtNachname.setValidationIndicator(lblNachname);
251 		centerBox.add(txtNachname);
252 		// Email
253 		JLabel lblEmail = new JLabel(messageBundle.getString("lbl.email"));
254 		centerBox.add(lblEmail);
255 		txtEmail = new RegexTextField("");
256 		txtEmail.setRegex(regexEmail);
257 		txtEmail.setValidationIndicator(lblEmail);
258 		centerBox.add(txtEmail);
259 
260 		// Fill with data
261 		if (mode != Mode.Create) {
262 			idLabel.setText(student.getId()+"");
263 			txtMatrNr.setText(student.getMatnr());
264 			txtVorname.setText(student.getFirstname());
265 			txtNachname.setText(student.getLastname());
266 			txtEmail.setText(student.getEmail());
267 		}
268 		mainPanel.add(centerBox, BorderLayout.CENTER);
269 		// SouthPanel contains the Buttons
270 		JPanel south = new JPanel();
271 		saveButton = new JButton();
272 		switch (mode) {
273 		case Create:
274 			saveButton.setText(messageBundle.getString("btn.lbl.create"));
275 			break;
276 		case Update:
277 			saveButton.setText(messageBundle.getString("btn.lbl.save"));
278 			break;
279 		}
280 		saveButton.addActionListener(this);
281 		JButton cancel = new JButton(messageBundle.getString("btn.lbl.close"));
282 		cancel.addActionListener(this);
283 		south.add(saveButton);
284 		south.add(cancel);
285 		mainPanel.add(south, BorderLayout.SOUTH);
286 	}
287 
288 	/**
289 	 * No models are used for now.
290 	 * 
291 	 */
292 	private void initModels() {
293 		// No models here
294 	}
295 
296 	/**
297 	 * Initialize the Student Data Access Object <code>studentDAO</code> via
298 	 * the Spring Bean Factory <code>xbf</code> and the list of
299 	 * ActionListeners <code>updateListeners</code> listening for Database
300 	 * changes.
301 	 */
302 	private void initDAO() {
303 		ClassPathResource res = new ClassPathResource(Constants.SPRINGBEANS);
304 		xbf = new XmlBeanFactory(res);
305 		studentDAO = (IStudentDAO) xbf.getBean("StudentDAO");
306 		updateListeners = new ArrayList<ActionListener>();
307 	}
308 	
309 	/**
310 	 * Initializes the ResourceBundle to externalize the Strings for the
311 	 * components.
312 	 * 
313 	 * @see ResourceBundle
314 	 */
315 	private void initMessageBundle() {
316 		messageBundle = (ResourceBundle) xbf.getBean("resourceBundle");
317 	}
318 
319 	/**
320 	 * Check which Action was performed and notify the UpdateListener.
321 	 * 
322 	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
323 	 */
324 	public void actionPerformed(ActionEvent e) {
325 		String action = e.getActionCommand();
326 		log.info("Action performed: \"" + action + "\"");
327 		if (action.equals(messageBundle.getString("btn.lbl.close"))) {
328 			closeFrame();
329 		} else if (action.equals(messageBundle.getString("btn.lbl.save"))) {
330 			if (validateInput()) {
331 				studentDAO
332 						.updateStudent(getStudentFromFrame());
333 				notifyUpdateListener();
334 			}
335 		} else if (action.equals(messageBundle.getString("btn.lbl.create"))) {
336 			if (validateInput()) {
337 				Student st = getStudentFromFrame();
338 				Student save = studentDAO.saveStudent(st);
339 				log.trace("before");
340 				if (save != null) {
341 					student = st;
342 					this.mode = Mode.Update;
343 					idLabel.setText(student.getId()+"");
344 					log.trace("after");
345 					((JButton) e.getSource()).setText(messageBundle.getString("btn.lbl.save"));
346 					centerBox.add(idLabel, 0);
347 					centerBox.add(new JLabel(messageBundle.getString("lbl.id")), 0);
348 					this.repaint();
349 					this.pack();
350 				}
351 				notifyUpdateListener();
352 			}
353 		} 
354 	}
355 
356 	/**
357 	 * Validate the data entered into the GUI.
358 	 * 
359 	 * @return true iff the data entered is valid.
360 	 * @see #getStudentFromFrame()
361 	 * @see RegexTextField#isMatching()
362 	 */
363 	private boolean validateInput() {
364 		return (txtMatrNr.isMatching() && txtVorname.isMatching()
365 				&& txtNachname.isMatching() && txtEmail.isMatching());
366 	}
367 
368 	/**
369 	 * Converts the data entered into the textFields to a new Student-object.
370 	 * Use in combination with <code>validateInput()</code>
371 	 * 
372 	 * @return a new Student with the data from the GUI.
373 	 * @see #validateInput()
374 	 */
375 	private Student getStudentFromFrame() {
376 		Student stud = new Student();
377         if(!idLabel.getText().equals("<assigned from DB>"))
378             stud.setId(Integer.parseInt(idLabel.getText()));
379         stud.setMatnr(txtMatrNr.getText());
380 		stud.setFirstname(txtVorname.getText());
381 		stud.setLastname(txtNachname.getText());
382 		stud.setEmail(txtEmail.getText());
383 		return stud;
384 	}
385 
386 }