summaryrefslogblamecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureDetailsWindow.java
blob: 12e6fe55c73430c5a454f0cdb8e1c4abe2c71a24 (plain) (tree)
1
2
3
4
5
6
7
8
9




                                      

                                   

                                    
                           
                          

                             
                      
                          
                      
                     

                                        
                          
                               
                          

                               
                                    
                                                      
                                                      
                                                      
                                                         
                                                        
                                                 
                                                  
                                             
                                              

                                         

                                                                   
                                                                                  

                                                                                       
                                                    
                                                 
                                                
                                                                      
                                                                       
                                                 
                                                   
                                                          
                                         
                                               
                                                                
                                                                 
                                                                   
                                             
                                                 
                                            
                                            
                                              
 


                                                      
                           
                                                                                            


                                                                                          


                         

                                                     
           




                                                                                    
 





                                                                            

                                                        
                                           

           




                                                                            
                                                
           
                                              
        
           
                                               
           
                                                                  
 




                                                                     
                                                        
 
                                                                          
        
           


                                                         
                                                                              
           
                                                                                         
                                   
 

                                         

                                                                     
















                                                                                                                      

                                                                                         
                                                                                                     



                                                                                                      
                                         
















                                                                                                                          






                                                        





                                                                                                                                 
                                                                                                                                             




                                                                                    
                                                                                                            
                                     
 

                                                       


                                                                  
                   
 

                                                                                                                          
                                                                     

                                                                    
                                                                                                                                    

















                                                                                                      
                                         

                                                                                              

                         
 


                                                                    
                                            

                         





                                                                         
                                                                  
                                 
                                                                   
                                                                                    

                         


                                                                       
                                                                                 


                                                                                                     


                                                                                                                                          
                                                                              
                                         
                                                                          

                         
                


                                                                                                  
                                 
                                                                   




                                                                                                           

                         

                                                                                    
 






                                                                       


                                                                                       
                                      


           



                                                                                   
           
                                                                 

                                                        
                                                                                                        
                                                           





                                                                                                             
                                                                              
                                                                                                                        

                                                                                                                                         
                                                                      
                                                 

                                         


           
                                                                                            
           
                                    
                                      
                                              

                                                  
                               
                 
 

                                                  
                                                      

                                                                   
                                                                       
                 
                                       
                                                                                     



                                                                                                               

                                                                                   
 
                                     
                                                                     

                                                                                                     
                                                                            
 
                                                           
                                                               
                                                                 
                                                                       
                                                                           




                                                                                      

                                                      

                                                                            
                                                                  

                                                              
                                                            

                                                                        



                                                                           
                                                                                                          
                                                             
                                                                     


                                                                       
                                                                                                    
                                                           
                                                                 
 



                                                                             
                                 
                                      

         
           

                                                                                    
           






                                                       
                                
                                                                                             





                                                                                                    
                                              

                                                                                            
                                                                                             

                         


                                                                                             

                                                                                                                     

         




                                                               
                                                           

                                                                                                                  


                               

                                                                                                                      
                                      





                                                          

         
           


                                                                                   
                                    
                                                                                                 




                                                                    
                                                                               
                                                       
                                                                                                                                  

                                               
                                                               
                                      

                         
                                       
                                                                                                                                
                                              


                                                                                                          
                                                                                                                








                                                                                                          
                                                 

                                         
         
 
           

                                                             

                                    

                                                      
                            
                                  
                        
                                                        
                 

         




                                                                       
                                               




                                                                                                          
                                                                                       



                                                                                                          
 







                                                                                                          








                                                                                                                  
                                                                                         
                                                                     
                                                                                  






                                                                                               
                                                                       



                                                                                                  
                 

                                                                     
                                                       
                                             

                         
                                      
                            

         
           

















                                                                                                         




                                                                                

                                                                           

                                                               

                                                                               

                                                         
                                
                                    



                                                                              
                 
                                      

                             
 
           



                                                                                              
           


                                                                            
                                                                   

                                                                                             
                                                                                                         





                                                            
                                                                          
                                                                           
         



                                                                              







                                                                      

                                                                                                       
                                          
                                     
         
 





                                                     
                 
                             
         
 




                                                                                                

                                          
                                                           




                                         

                            
 




                                                                                    
                                                       
                                                                                                                           
                                                                                        
                               



                                       
                          
         
 
package org.openslx.dozmod.gui.window;

import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import org.apache.log4j.Logger;
import org.apache.thrift.TException;
import org.openslx.bwlp.thrift.iface.ImageDetailsRead;
import org.openslx.bwlp.thrift.iface.ImagePermissions;
import org.openslx.bwlp.thrift.iface.ImageSummaryRead;
import org.openslx.bwlp.thrift.iface.ImageVersionDetails;
import org.openslx.bwlp.thrift.iface.LecturePermissions;
import org.openslx.bwlp.thrift.iface.LectureRead;
import org.openslx.bwlp.thrift.iface.LectureWrite;
import org.openslx.bwlp.thrift.iface.NetRule;
import org.openslx.bwlp.thrift.iface.UserInfo;
import org.openslx.dozmod.gui.Gui;
import org.openslx.dozmod.gui.MainWindow;
import org.openslx.dozmod.gui.changemonitor.AbstractControlWrapper;
import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor;
import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.NotNullConstraint;
import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.TextNotEmptyConstraint;
import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.ValidationConstraint;
import org.openslx.dozmod.gui.helper.DateTimeHelper;
import org.openslx.dozmod.gui.helper.MessageType;
import org.openslx.dozmod.gui.helper.UiFeedback;
import org.openslx.dozmod.gui.window.UserListWindow.UserAddedCallback;
import org.openslx.dozmod.gui.window.layout.LectureDetailsWindowLayout;
import org.openslx.dozmod.permissions.ImagePerms;
import org.openslx.dozmod.permissions.LecturePerms;
import org.openslx.dozmod.thrift.ImageLocalDetailsActions;
import org.openslx.dozmod.thrift.Session;
import org.openslx.dozmod.thrift.ThriftActions;
import org.openslx.dozmod.thrift.ThriftActions.DownloadCallback;
import org.openslx.dozmod.thrift.ThriftActions.ImageMetaCallback;
import org.openslx.dozmod.thrift.ThriftActions.LectureMetaCallback;
import org.openslx.dozmod.thrift.ThriftError;
import org.openslx.dozmod.thrift.cache.UserCache;
import org.openslx.dozmod.util.FormatHelper;
import org.openslx.thrifthelper.Comparators;
import org.openslx.thrifthelper.ThriftManager;

/**
 * Window to display and edit the details of a lecture
 */
@SuppressWarnings("serial")
public class LectureDetailsWindow extends LectureDetailsWindowLayout implements UiFeedback {

	private static final Logger LOGGER = Logger.getLogger(LectureDetailsWindow.class);

	/**
	 * Self-reference
	 */
	private final LectureDetailsWindow me = this;

	/**
	 * Callback interface to refresh lecture list after changing lecture details
	 */
	public interface LectureUpdatedCallback {
		public void updated(boolean success);
	}

	/**
	 * Callback to be called when changing lecture details on the server
	 */
	private LectureUpdatedCallback callback = null;

	/**
	 * Lecture that this window shows the details of
	 */
	private LectureRead lecture = null;

	/**
	 * Action handler proxying thrift calls for image related operations
	 */
	private final ImageLocalDetailsActions actionHandler;

	/**
	 * Image, that the lecture is linked to.
	 */
	private ImageDetailsRead image = null;
	
	/**
	 * Per-User permissions of this lecture
	 */
	private Map<String, LecturePermissions> customPermissions;

	/**
	 * Did the user have admin rights due to default permissions?
	 */
	private boolean adminRightsFromDefaultPermissions;

	private final DialogChangeMonitor changeMonitor;

	private final AbstractControlWrapper<?> changeListenerPermissions;
	
 	/**
	 * Constructor
	 * 
	 * @param modalParent parent of this popup window
	 * @param callback function to be called when a lecture update occured
	 */
	public LectureDetailsWindow(Frame modalParent, LectureUpdatedCallback callback) {
		super(modalParent);

		// save callback
		this.callback = callback;

		setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		
		// Set up change monitor
		changeMonitor = new DialogChangeMonitor(new DialogChangeMonitor.Callback() {
			@Override
			public void validityChanged(String errorMessage) {
				lblError.setText(errorMessage);
				btnSaveChanges.setEnabled(changeMonitor.isValid() && changeMonitor.wasEverModified());
				LOGGER.info("Valid: " + changeMonitor.isValid());
			}
			@Override
			public void modificationChanged() {
				btnSaveChanges.setEnabled(changeMonitor.isValid() && changeMonitor.wasEverModified());
				LOGGER.info("Changed: " + changeMonitor.isCurrentlyModified());
			}
		});

		// Add controls to change monitor
		changeMonitor.addFixedCombo(cboVersions, Comparators.imageVersionDetails)
			.addConstraint(
				new DialogChangeMonitor.ValidationConstraint<ImageVersionDetails>() {
					public String checkStateValid(ImageVersionDetails userInput) {
						if (userInput != null && userInput.isValid)
							return null;
						return "Keine/Ungültige VM-Version ausgewählt";
					}
				});
		// Create constraint for date start/end
		final Date maxValidity;
		Calendar c = Calendar.getInstance();
		c.add(Calendar.DAY_OF_MONTH, Session.getSatelliteConfig().maxLectureValidityDays);
		maxValidity = c.getTime();
		ValidationConstraint<Object> dateRangeValidator = new DialogChangeMonitor.ValidationConstraint<Object>() {
			public String checkStateValid(Object ignored) {
				Date start = DateTimeHelper.getDateFrom(dtpStartDate, spnStartTime);
				Date end = DateTimeHelper.getDateFrom(dtpEndDate, spnEndTime);
				if (!end.after(start))
					return "Enddatum darf nicht vor dem Startdatum liegen";
				if (end.after(maxValidity))
					return "Enddatum liegt nach dem " + FormatHelper.shortDate(maxValidity);
				return null;
			}
		};
		changeMonitor.add(chkAutoUpdate);
		changeMonitor.add(chkIsExam);
		changeMonitor.add(chkHasInternetAccess);
		changeMonitor.add(chkHasUsbAccess);
		changeMonitor.add(chkIsActive);
		changeMonitor.add(chkCustomPermAdmin);
		changeMonitor.add(chkCustomPermEdit);
		changeMonitor.add(txtTitle).addConstraint(new TextNotEmptyConstraint("Veranstaltungsname darf nicht leer sein"));
		changeMonitor.add(txtDescription).addConstraint(new TextNotEmptyConstraint("Beschreibung darf nicht leer sein"));
		changeMonitor.add(dtpEndDate).addConstraint(dateRangeValidator);
		changeMonitor.add(dtpStartDate).addConstraint(dateRangeValidator);
		changeMonitor.add(spnEndTime).addConstraint(dateRangeValidator);
		changeMonitor.add(spnStartTime).addConstraint(dateRangeValidator);
		changeMonitor.add(ctlNetrulesConfigurator).addConstraint(new NotNullConstraint<List<NetRule>>("Fehlerhafte Netzwerkregeln"));
		changeListenerPermissions = changeMonitor.add(ctlPermissionManager);
		ctlLocationSelector.addToChangeMonitor(changeMonitor);
		ctlRunscriptConfigurator.addToChangeMonitor(changeMonitor);
		ctlNetshareConfigurator.addToChangeMonitor(changeMonitor);
		ctlLdapFilterConfigurator.addToChangeMonitor(changeMonitor);
		// TODO: LDAP/NetShare: Having uncommitted changes in the input fields should be handled too
		// End change monitor

		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				safeClose();
			}
		});

		actionHandler = new ImageLocalDetailsActions(JOptionPane.getFrameForComponent(LectureDetailsWindow.this));

		btnLinkImage.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final ImageSummaryRead newImage = LectureChangeImage.open(LectureDetailsWindow.this, changeMonitor);
				if (newImage == null)
					return;
				final ImageMetaCallback callback = new ImageMetaCallback() {
					@Override
					public void fetchedImageDetails(ImageDetailsRead imageDetails,
							Map<String, ImagePermissions> permissions) {
						if (imageDetails == null) {
							return;
						}
						synchronized (me) {
							image = imageDetails;
						}
						lecture.imageBaseId = newImage.imageBaseId;
						lecture.imageVersionId = newImage.latestVersionId;
						fillVersionsCombo();
						cboVersions.setEnabled(false);
						chkAutoUpdate.setSelected(true);
						txtImageName.setText(newImage.getImageName());
					}
				};
				actionHandler.getImageDetails(newImage.imageBaseId, callback);
			}
		});

		btnClose.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				safeClose();
			}
		});
		btnDownloadImage.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				performImageDownload();
			}
		});
		chkAutoUpdate.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				cboVersions.setEnabled(!chkAutoUpdate.isSelected());
			}
		});
		btnChangeOwner.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				UserListWindow.open(me, new UserAddedCallback() {
					@Override
					public void userAdded(UserInfo user, UserListWindow window) {
						window.dispose();
						if (Gui.showMessageBox(me, "Sind Sie sicher, dass sie die Besitzerrechte an "
								+ "einen anderen Account übertragen wollen?", MessageType.QUESTION_YESNO,
								LOGGER, null))
							setLectureOwner(user);
					}
				}, "Besitzer festlegen", lecture.ownerId);
			}
		});
		
		// Update default permissions in the permission manager immediately, so it affects
		// newly added users
		final ItemListener updateDefaultPermissionListener = new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				if (e.getSource() == chkCustomPermAdmin) {
					lecture.defaultPermissions.admin = chkCustomPermAdmin.isSelected();
				} else {
					lecture.defaultPermissions.edit = chkCustomPermEdit.isSelected();
				}
			}
		};
		chkCustomPermAdmin.addItemListener(updateDefaultPermissionListener);
		chkCustomPermEdit.addItemListener(updateDefaultPermissionListener);

		// last step, the save button
		btnSaveChanges.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				saveChanges();
			}
		});
		// disable save button
		btnSaveChanges.setEnabled(false);
		// wait for the image to be loaded before (potentially) enabling fields
		toggleEditable(false);
	}

	/**
	 * Sets the lecture to show the details of by setting the 'lecture' and
	 * 'image'
	 * members to its metadata. This method will fetch the information from the
	 * sat
	 * 
	 * @param lectureId the id of the lecture to be displayed
	 */
	public void setLecture(final String lectureId) {
		ThriftActions.getLectureAndImageDetails(JOptionPane.getFrameForComponent(me), lectureId,
				new LectureMetaCallback() {
					@Override
					public void fetchedLectureAndImageDetails(LectureRead lectureDetails,
							ImageDetailsRead imageDetails) {
						synchronized (me) {
							lecture = lectureDetails;
							image = imageDetails;
							if (lecture != null) {
								customPermissions = ThriftActions.getLecturePermissions(
										JOptionPane.getFrameForComponent(me), lecture.lectureId);
							}
							fillDetails();
						}
					}
				});
	}

	/**
	 * Internal callback function when we received the lecture's details from the server
	 */
	private void fillDetails() {
		if (lecture == null) {
			txtTitle.setText("-");
			lblTitleInfo.setText("-");
			toggleEditable(false);
			return;
		}

		if (image == null) {
			txtImageName.setText("-");
			lblImageNameInfo.setText("-");
		} else {
			txtImageName.setText(image.getImageName());
			lblImageNameInfo.setText(image.getImageName());
		}
		// init permission info
		adminRightsFromDefaultPermissions = lecture.defaultPermissions.admin;
		ctlPermissionManager.initPanel(customPermissions, lecture.defaultPermissions, lecture.ownerId);
		chkCustomPermAdmin.setSelected(lecture.defaultPermissions.admin);
		chkCustomPermEdit.setSelected(lecture.defaultPermissions.edit);
		// init location info
		ctlLocationSelector.setOnlyInSelection(lecture.limitToLocations);
		ctlLocationSelector.setSelectedLocationsAsIds(lecture.locationIds);

		// init advanced info
		ctlRunscriptConfigurator.setState(lecture.runscript);
		ctlNetshareConfigurator.setState(lecture.networkShares, lecture.presetNetworkShares);
		ctlLdapFilterConfigurator.setState(lecture.ldapFilters, lecture.presetLdapFilters);
		ctlNetrulesConfigurator.setState(lecture.networkExceptions);

		txtTitle.setText(lecture.getLectureName());
		lblTitleInfo.setText(lecture.getLectureName());
		txtDescription.setText(lecture.getDescription());
		lblOwner.setUser(UserCache.find(lecture.getOwnerId()));
		lblOwnerInfo.setUser(UserCache.find(lecture.getOwnerId()));
		lblUpdater.setUser(UserCache.find(lecture.getUpdaterId()));
		lblCreateTime.setText(FormatHelper.longDate(lecture.getCreateTime()));
		lblUpdateTime.setText(FormatHelper.longDate(lecture.getUpdateTime()));
		lblStartTime.setText(FormatHelper.longDate(lecture.getStartTime()));
		lblEndTime.setText(FormatHelper.longDate(lecture.getEndTime()));
		txtId.setText(lecture.getLectureId());

		chkIsActive.setSelected(lecture.isEnabled);
		chkHasInternetAccess.setSelected(lecture.hasInternetAccess);
		chkHasUsbAccess.setSelected(lecture.hasUsbAccess);
		chkIsExam.setSelected(lecture.isExam);
		chkAutoUpdate.setSelected(lecture.autoUpdate);
		cboVersions.setEnabled(!lecture.autoUpdate);

		lblUseCount.setText(Integer.toString(lecture.useCount));
		fillVersionsCombo();

		Calendar startCal = Calendar.getInstance();
		startCal.setTime(new Date(lecture.getStartTime() * 1000l));
		dtpStartDate.getModel().setDate(startCal.get(Calendar.YEAR), startCal.get(Calendar.MONTH),
				startCal.get(Calendar.DATE));
		spnStartTime.getModel().setValue(startCal.getTime());

		Calendar endCal = Calendar.getInstance();
		endCal.setTime(new Date(lecture.getEndTime() * 1000l));
		dtpEndDate.getModel().setDate(endCal.get(Calendar.YEAR), endCal.get(Calendar.MONTH),
				endCal.get(Calendar.DATE));
		spnEndTime.getModel().setValue(endCal.getTime());

		// now enable the tabs the user can see given its permissions
		toggleEditable(true);
		// and always switch to the "About" tab
		pnlTabs.setSelectedIndex(pnlTabs.indexOfTab("Übersicht"));
		setVisible(true);
		changeMonitor.reset();
	}

	/**
	 * Helper to fill the combobox with the versions of the image. The list will
	 * be sorted by creation timestamp
	 */
	private void fillVersionsCombo() {
		List<ImageVersionDetails> versions;
		if (image == null) {
			versions = new ArrayList<>(0);
		} else {
			versions = image.getVersions();
		}
		// version combo
		for (Iterator<ImageVersionDetails> it = versions.iterator(); it.hasNext();) {
			ImageVersionDetails version = it.next();
			if (!version.isValid && !lecture.imageVersionId.equals(version.versionId)) {
				it.remove();
			}
		}

		// sort versions by createtime
		Collections.sort(versions, new Comparator<ImageVersionDetails>() {
			public int compare(ImageVersionDetails o1, ImageVersionDetails o2) {
				return -Long.compare(o1.getCreateTime(), o2.getCreateTime());
			}
		});

		cboVersions.setModel(new DefaultComboBoxModel<ImageVersionDetails>(
				versions.toArray(new ImageVersionDetails[versions.size()])));
		cboVersions.setSelectedItem(new ImageVersionDetails(lecture.getImageVersionId(), 0, 0, 0, null, true,
				true, true, null));
	}

	/**
	 * Sets the lecture's owner to the given user
	 * 
	 * @param user UserInfo representation of the new owner
	 */
	private void setLectureOwner(final UserInfo user) {
		if (!ThriftActions.setLectureOwner(JOptionPane.getFrameForComponent(this), lecture.getLectureId(),
				user)) {
			return;
		}
		// success
		Gui.showMessageBox(me, "Besitzrechte übertragen an " + FormatHelper.userName(user), MessageType.INFO,
				null, null);
		toggleEditable(false);
		String lectureId = lecture.getLectureId();
		synchronized (me) {
			image = null;
			lecture = null;
		}
		setLecture(lectureId);
	}

	/**
	 * Triggers the download of the currently used image version of the lecture
	 */
	private void performImageDownload() {
		if (image == null) {
			Gui.showMessageBox(this, "VM ungültig.", MessageType.ERROR, null, null);
			return;
		}
		btnDownloadImage.setEnabled(false);
		long versionSize = 0;
		for (ImageVersionDetails version : image.versions) {
			if (version.versionId.equals(lecture.imageVersionId)) {
				if (!version.isValid) {
					Gui.showMessageBox(this, "Ungültige VM-Version gewählt", MessageType.ERROR, null, null);
					return;
				}
				versionSize = version.fileSize;
				break;
			}
		}
		if (versionSize == 0) {
			Gui.showMessageBox(this, "Fehler bei der Abfrage der Größe des VM-Abbildes.", MessageType.ERROR, null,
					null);
			return;
		}
		ThriftActions.initDownload(JOptionPane.getFrameForComponent(this), lecture.imageVersionId,
				image.imageName, image.virtId, image.osId, versionSize, new DownloadCallback() {
					@Override
					public void downloadInitialized(boolean success) {
						if (!success) {
							Gui.asyncExec(new Runnable() {
								@Override
								public void run() {
									btnDownloadImage.setEnabled(true);
								}
							});
						}
					}
				});
	}

	/**
	 * Triggers the saving of the changes of this lecture
	 * And inform the callback function about the outcome
	 */
	private void saveChanges() {
		boolean saved = saveChangesInternal();
		callback.updated(saved);
		if (saved) {
			dispose();
		} else {
			btnSaveChanges.setEnabled(true);
		}
	}

	/**
	 * Internal helper actually saving the changes to the satellite
	 *
	 * @return true if saving succeeded, false otherwise.
	 */
	private boolean saveChangesInternal() {
		long startTime = DateTimeHelper.getDateFrom(dtpStartDate, spnStartTime).getTime() / 1000L;
		long endTime = DateTimeHelper.getDateFrom(dtpEndDate, spnEndTime).getTime() / 1000L;
		if (!isPeriodValid(startTime, endTime, true))
			return false;
		
		// check, whether autoupdate is selected and choose version accordingly
		if (image != null) {
			lecture.imageVersionId = chkAutoUpdate.isSelected() ? image.latestVersionId
					: cboVersions.getItemAt(cboVersions.getSelectedIndex()).versionId;
		}

		// Special case similar to ImageDetailsWindow:if the user had admin rights
		// through default permissions, first save custom permissions.
		if (adminRightsFromDefaultPermissions && changeListenerPermissions.isCurrentlyChanged()) {
			if (!saveCustomPermissions()) {
				return false;
			}
			changeListenerPermissions.reset();
		}
		// first build the LectureWrite from the GUI fields
		final LectureWrite metadata = new LectureWrite(txtTitle.getText(), txtDescription.getText(),
				lecture.getImageVersionId(), chkAutoUpdate.isSelected(), chkIsActive.isSelected(),
				startTime, endTime,
				ctlRunscriptConfigurator.getState(), null,
				chkIsExam.isSelected(),
				chkHasInternetAccess.isSelected(),
				lecture.getDefaultPermissions(), ctlLocationSelector.getSelectedLocationsAsIds(),
				ctlLocationSelector.getOnlyInSelection(),
				// TODO limitOnlyToAllowedUsers, default to false for now
				false, chkHasUsbAccess.isSelected());
		metadata.setNetworkExceptions(ctlNetrulesConfigurator.getState());
		metadata.setNetworkShares(ctlNetshareConfigurator.getState());
		metadata.setLdapFilters(ctlLdapFilterConfigurator.getState());

		// now trigger the actual action 
		try {
			ThriftManager.getSatClient().updateLecture(Session.getSatelliteToken(),
					lecture.getLectureId(), metadata);
			LOGGER.info("Successfully saved new metadata");
		} catch (TException e) {
			ThriftError.showMessage(JOptionPane.getFrameForComponent(this), LOGGER, e,
					"Fehler beim Speichern der Veranstaltung!");
			return false;
		}

		if (changeListenerPermissions.isCurrentlyChanged()) {
			if (!saveCustomPermissions()) {
				return false;
			}
		}
		changeMonitor.reset();
		return true;
	}

	/**
	 * Helper to save custom user permissions.
	 *
	 * @return true if successfully saved, false otherwise.
	 */
	private boolean saveCustomPermissions() {
		try {
			ThriftManager.getSatClient().writeLecturePermissions(Session.getSatelliteToken(),
					lecture.lectureId, ctlPermissionManager.getPermissions());
			LOGGER.info("Successfully saved custom permissions");
			return true;
		} catch (TException e) {
			ThriftError.showMessage(JOptionPane.getFrameForComponent(this), LOGGER, e,
					"Fehler beim Übertragen der Berechtigungen!");
		}
		return false;
	}

	/**
	 * Checks if the given start and end date represent a valid time period.
	 * This is the case, if start < end and if current time < end
	 * 
	 * @param start date of the period to check
	 * @param end date of the period to check
	 * @param feedback true if the user should be shown feedback, false
	 *            otherwise
	 * @return true if the period is valid, false otherwise
	 */
	private boolean isPeriodValid(long start, long end, boolean feedback) {
		if (start <= 0 || end <= 0)
			return false;
		// analyse time stuff to see if its valid
		if (end > start)
			return true;
		String msg = "Start der Veranstaltung ist nach dem Enddatum!";
		if (feedback) {
			Gui.showMessageBox(me, msg, MessageType.ERROR,
					LOGGER, null);
		}
		lblError.setText(msg);
		return false;
	}

	/**
	 * Enables/Disables the tabs based on the given flag 'editable'.
	 *
	 * @param editable when true, will enable the tabs if the user is allowed to see them.
	 * If false, this will disable all tabs but the first tab "About".
	 */
	protected void toggleEditable(boolean editable) {
		// if we don't have a lecture and an image set, just disable
		editable &= (LecturePerms.canEdit(lecture));
		// enable the standard tabs that are always enabled
		setTabEnabled(pnlTabGeneral, editable);
		setTabEnabled(pnlTabPermissions, editable && LecturePerms.canAdmin(lecture));
		// enable the other tabs that might have been added to the panel (depends on API version)
		setTabEnabled(pnlTabRestrictions, editable);
		setTabEnabled(pnlTabLocations, editable);
		setTabEnabled(pnlTabRunscript, editable);
		setTabEnabled(pnlTabNetshare, editable);
		setTabEnabled(pnlTabLdapFilter, editable);
		setTabEnabled(pnlTabNetrules, editable);
		btnChangeOwner.setEnabled(LecturePerms.canAdmin(lecture));
		btnDownloadImage.setEnabled(ImagePerms.canDownload(image));
	}
	
	private void setTabEnabled(JPanel tab, boolean editable) {
		pnlTabs.setEnabledAt(pnlTabs.indexOfComponent(tab), editable);
	}

	/**
	 * Opens a new LectureDetailsWindow showing the details of the
	 * lecture with ID = lectureId
	 * 
	 * @param modalParent parent of this window
	 * @param lectureId id of the lecture to set the details of
	 */
	public static void open(Frame modalParent, String lectureId, LectureUpdatedCallback callback) {
		LectureDetailsWindow win = new LectureDetailsWindow(modalParent, callback);
		win.setLecture(lectureId);
		win.setVisible(true);
	}

	@SuppressWarnings("deprecation")
	@Override
	public void show() {
		if (!isVisible()) {
			pack();
			MainWindow.centerShell(this);
		}
		super.show();
	}

	/* *******************************************************************************	
	 * 
	 *                        UIFeedback implementation
	 *
	 ********************************************************************************/
	@Override
	public boolean wantConfirmQuit() {
		return changeMonitor.isCurrentlyModified();
	}

	@Override
	public void escapePressed() {
		// Also ask if applicable
		safeClose();
	}

	/*
	 * Safe close helper: checks if we have unsaved work and prompt the user for
	 * confirmation if so
	 */
	private void safeClose() {
		if (changeMonitor.isCurrentlyModified()
				&& !Gui.showMessageBox(me, "Änderungen werden verworfen, wollen Sie wirklich schließen?",
						MessageType.QUESTION_YESNO, null, null))
			return;
		synchronized(me) {
			lecture = null;
			image = null;
		}
		dispose();
	}
}