package org.openslx.dozmod.gui.window;
import java.awt.Color;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.RowFilter;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.apache.log4j.Logger;
import org.apache.thrift.TException;
import org.openslx.bwlp.thrift.iface.ImageSummaryRead;
import org.openslx.bwlp.thrift.iface.Organization;
import org.openslx.bwlp.thrift.iface.UserInfo;
import org.openslx.dozmod.Branding;
import org.openslx.dozmod.gui.Gui;
import org.openslx.dozmod.gui.MainWindow;
import org.openslx.dozmod.gui.control.table.ListTable.ListModel;
import org.openslx.dozmod.gui.helper.MessageType;
import org.openslx.dozmod.gui.helper.TextChangeListener;
import org.openslx.dozmod.gui.helper.UiFeedback;
import org.openslx.dozmod.gui.window.layout.ImagePublishedWindowLayout;
import org.openslx.dozmod.thrift.ImagePublishedDetailsActions;
import org.openslx.dozmod.thrift.Session;
import org.openslx.dozmod.thrift.ThriftActions;
import org.openslx.dozmod.thrift.ThriftActions.DownloadCallback;
import org.openslx.dozmod.thrift.ThriftError;
import org.openslx.dozmod.thrift.cache.ImagePublishedCache;
import org.openslx.dozmod.thrift.cache.OrganizationCache;
import org.openslx.dozmod.thrift.cache.UserCache;
import org.openslx.sat.thrift.version.Feature;
import org.openslx.thrifthelper.TConst;
import org.openslx.thrifthelper.ThriftManager;
import org.openslx.util.QuickTimer;
import org.openslx.util.QuickTimer.Task;
@SuppressWarnings("serial")
public class ImagePublishedWindow extends ImagePublishedWindowLayout implements UiFeedback, DownloadCallback {
private final static Logger LOGGER = Logger.getLogger(ImagePublishedWindow.class);
private final ImagePublishedWindow me = this;
// Filtering: matches against image's name, user's first/last name or email and organisation name of the owner
private Pattern searchFieldPattern = null;
private final RowFilter<ListModel<ImageSummaryRead>, Integer> filterSearchTerm = new RowFilter<ListModel<ImageSummaryRead>, Integer>() {
public boolean include(Entry<? extends ListModel<ImageSummaryRead>, ? extends Integer> entry) {
// match against image names first
ImageSummaryRead image = imagePublishedTable.getModelRow(entry.getIdentifier());
if (searchFieldPattern.matcher(image.imageName).find())
return true;
// match against users
UserInfo user = UserCache.find(image.ownerId);
if (user == null)
return false;
if (searchFieldPattern.matcher(user.firstName).find())
return true;
if (searchFieldPattern.matcher(user.lastName).find())
return true;
if (searchFieldPattern.matcher(user.eMail).find())
return true;
// match against organizations
Organization org = OrganizationCache.find(user);
if (org == null)
return false;
if (searchFieldPattern.matcher(org.displayName).find())
return true;
return false;
}
};
public ImagePublishedWindow(Frame modalParent) {
super(modalParent);
// Hook when user presses X (top right)
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
dispose();
}
});
btnClose.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dispose();
}
});
btnSatDownload.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ImageSummaryRead item = imagePublishedTable.getSelectedItem();
if (item == null)
return;
String transferToken = null;
try {
transferToken = ThriftManager.getSatClient()
.requestImageReplication(Session.getSatelliteToken(), item.latestVersionId);
} catch (TException ex) {
ThriftError.showMessage(me, LOGGER, ex, "Could not start download");
return;
}
MainWindow.addPassiveTransfer(transferToken, item.imageName, false);
Gui.showMessageBox(ImagePublishedWindow.this,
"Die Übertragung läuft direkt zwischen Satellitenserver und"
+ " dem " + Branding.getServiceName() + " Zentral-Server.\n"
+ "Wenn Sie die " + Branding.getApplicationName() + " schließen, wird der Transfer trotzdem"
+ "weiterlaufen.",
MessageType.INFO, null, null);
}
});
btnDownload.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final ImageSummaryRead item = imagePublishedTable.getSelectedItem();
if (item == null)
return;
btnDownload.setEnabled(false);
ThriftActions.initDownload((JFrame) SwingUtilities.getWindowAncestor(me),
item.latestVersionId, item.imageName, item.virtId, item.osId, item.fileSize, null);
}
});
txtSearch.getDocument().addDocumentListener(new TextChangeListener() {
@Override
public void changed() {
String str = txtSearch.getText();
if (str == null || str.isEmpty()) {
searchFieldPattern = null;
} else {
try {
searchFieldPattern = Pattern.compile(str, Pattern.CASE_INSENSITIVE);
txtSearch.setForeground(UIManager.getColor("TextField.foreground"));
} catch (PatternSyntaxException ex) {
txtSearch.setForeground(Color.RED);
}
}
applyFilterOnTable();
}
});
imagePublishedTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
ImageSummaryRead item = imagePublishedTable.getSelectedItem();
updateAvailableOptions(item);
}
});
imagePublishedTable.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) {
ImageSummaryRead item = imagePublishedTable.getSelectedItem();
if (item == null || item.getImageBaseId() == null)
return;
ImageDetailsWindow.open(JOptionPane.getFrameForComponent(ImagePublishedWindow.this),
item.getImageBaseId(), null, new ImagePublishedDetailsActions(
JOptionPane.getFrameForComponent(ImagePublishedWindow.this)));
}
processClick(e);
}
@Override
public void mousePressed(MouseEvent e) {
processClick(e);
}
@Override
public void mouseReleased(MouseEvent e) {
processClick(e);
}
private void processClick(MouseEvent e) {
// TODO popup menu?
}
});
// init buttons state
btnSatDownload.setVisible(Session.isImagePublishSupported());
updateAvailableOptions(null);
// init data
refreshList(true, 0);
}
private void updateAvailableOptions(ImageSummaryRead item) {
btnDownload.setEnabled(item != null);
if (Session.isImagePublishSupported())
btnSatDownload.setEnabled(item != null);
}
/**
* Called when a change occurs in the filter search field
*/
private void applyFilterOnTable() {
// List for filters
List<RowFilter<ListModel<ImageSummaryRead>, Integer>> filters = new ArrayList<>();
// string for text in filter text field
if (searchFieldPattern != null) {
filters.add(filterSearchTerm);
}
// for using multiple filters if we need it one day
RowFilter<ListModel<ImageSummaryRead>, Integer> andFilters = RowFilter.andFilter(filters);
imagePublishedTable.getRowSorter().setRowFilter(andFilters);
}
/**
* Callback when download initialized
*
* @param success
* true if downloading, false otherwise
*/
@Override
public void downloadInitialized(boolean success) {
if (!success) {
Gui.asyncExec(new Runnable() {
@Override
public void run() {
btnDownload.setEnabled(true);
}
});
}
}
/**
* Refreshes the image list in the table
*
* @param forceRefresh
* true to force a refresh, false to use the cached list
*/
public void refreshList(final boolean forceRefresh, int delay) {
QuickTimer.scheduleOnce(new Task() {
@Override
public void fire() {
final List<ImageSummaryRead> imagePublishedList = ImagePublishedCache.get(forceRefresh);
if (imagePublishedList == null)
return;
// 04.2018: Safety check to hide the non-vmware images from the list
// in case they somehow manage to get published. Remove this when we
// support publishing images from other hypervisors.
if (Session.hasFeature(Feature.MULTIPLE_HYPERVISORS)) {
for (Iterator<ImageSummaryRead> iter = imagePublishedList.listIterator(); iter
.hasNext();) {
ImageSummaryRead current = iter.next();
if (current != null && !current.virtId.equals(TConst.VIRT_VMWARE)) {
iter.remove();
}
}
}
Gui.asyncExec(new Runnable() {
@Override
public void run() {
imagePublishedTable.setData(imagePublishedList, true);
}
});
}
}, delay);
}
/**
* Opens a new ImageDetailsWindow showing the details of the image with ID =
* imageBaseId
*
* @param modalParent
* parent of this window
* @param imageBaseId
* id of the image to set the details of
*/
public static void open(Frame modalParent) {
ImagePublishedWindow win = new ImagePublishedWindow(modalParent);
win.setVisible(true);
}
/* *******************************************************************************
*
* Dialog class overrides
*
* **************************************************************************
* *****
*/
@SuppressWarnings("deprecation")
@Override
public void show() {
if (!isVisible()) {
pack();
MainWindow.centerShell(this);
}
super.show();
}
@Override
public boolean wantConfirmQuit() {
return false;
}
@Override
public void escapePressed() {
dispose();
}
}