/* * Constellation - An open source and standard compliant SDI * http://www.constellation-sdi.org * * Copyright 2014 Geomatys. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.constellation.swing; import org.apache.sis.util.logging.Logging; import org.constellation.ServiceDef; import org.constellation.admin.service.ConstellationClient; import org.constellation.configuration.Instance; import org.constellation.configuration.InstanceReport; import org.constellation.configuration.ServiceStatus; import org.constellation.dto.Details; import org.constellation.security.RoleController; import org.constellation.swing.action.Action; import org.constellation.swing.action.ActionEditor; import org.constellation.swing.action.ActionRenderer; import org.jdesktop.swingx.JXTable; import org.openide.util.Exceptions; import javax.swing.*; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableModel; import javax.swing.tree.DefaultMutableTreeNode; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.logging.Level; import java.util.logging.Logger; import static org.constellation.security.ActionPermissions.NEW_SERVICE; /** * Top component to manage constellation services. * * @author Johann Sorel (Geomatys) */ public final class JServicesPane extends JPanel implements ActionListener, PropertyChangeListener { private static final Logger LOGGER = Logging.getLogger("org.constellation.swing"); private final List<Action> actions = new ArrayList<>(); private final JXTable guiTable = new JXTable(); private final ConstellationClient cstlV2; private final FrameDisplayer displayer; public JServicesPane(final ConstellationClient cstlV2, final FrameDisplayer displayer) { this(cstlV2, displayer, null); } public JServicesPane(final ConstellationClient cstlV2, final FrameDisplayer displayer, RoleController roleController, Action ... actions) { initComponents(); for(Action act : actions){ if(roleController == null || roleController.hasPermission(act.getName())){ this.actions.add(act); act.addPropertyChangeListener(this); } } this.cstlV2 = cstlV2; if (displayer == null) { this.displayer = new DefaultFrameDisplayer(); } else { this.displayer = displayer; } try { final Map<String,List<String>> listServices = cstlV2.services.getAvailableService(); final List<String> types = new ArrayList<>(listServices.keySet()); Collections.sort(types); guiAll.addActionListener(this); for(String type : types) { final JToggleButton btn = new JToggleButton(type); btn.setActionCommand(type); btn.addActionListener(this); guiTypeGroup.add(btn); guiToolBar.add(btn); } } catch (IOException ex) { Exceptions.printStackTrace(ex); } guiNew.setVisible(roleController == null || roleController.hasPermission(NEW_SERVICE)); guiTable.setDefaultRenderer(Action.class, new ActionRenderer(cstlV2)); guiTable.setDefaultEditor(Action.class, new ActionEditor(cstlV2)); guiTable.setDefaultRenderer(Entry.class, new DefaultTableCellRenderer(){ @Override public Component getTableCellRendererComponent(JTable table, Object o, boolean isSelected, boolean hasFocus, int row, int column) { final JLabel lbl = (JLabel) super.getTableCellRendererComponent( table, o, isSelected, hasFocus, row, column); lbl.setIcon(null); if(o instanceof DefaultMutableTreeNode){ o = ((DefaultMutableTreeNode)o).getUserObject(); } if(o instanceof Entry){ final Entry entry = (Entry) o; final Instance inst = (Instance) entry.getKey(); final String type = (String) entry.getValue(); final Color bgColor; if (ServiceStatus.STARTED.equals(inst.getStatus())) { bgColor = new Color(130, 160, 50); } else if (ServiceStatus.STOPPED.equals(inst.getStatus()) || ServiceStatus.ERROR.equals(inst.getStatus())) { bgColor = Color.GRAY; } else if (ServiceStatus.STARTING.equals(inst.getStatus()) || ServiceStatus.STOPPING.equals(inst.getStatus())) { bgColor = Color.ORANGE; } else { bgColor = new Color(180, 60, 60); } final Font fontBig = new Font("Monospaced", Font.BOLD, 16); final BufferedImage img = JServicesPane.createImage(type, null, Color.WHITE,fontBig, bgColor); lbl.setIcon(new ImageIcon(img)); lbl.setText(inst.getIdentifier()); } return lbl; } }); add(BorderLayout.CENTER,new JScrollPane(guiTable)); updateInstanceList(); } public FrameDisplayer getDisplayer() { return displayer; } private void updateInstanceList(){ String action = "all"; if(guiTypeGroup.getSelection() != null){ action = guiTypeGroup.getSelection().getActionCommand(); } //list all services final List<Entry<Instance,String>> instances = new ArrayList<> (); try { final Map<String,List<String>> services = cstlV2.services.getAvailableService(); for(Map.Entry<String,List<String>> service : services.entrySet()){ if("all".equals(action) || action.equalsIgnoreCase(service.getKey())){ final String serviceType = service.getKey().toUpperCase(); final InstanceReport report = cstlV2.services.getInstances(ServiceDef.Specification.valueOf(serviceType)); if (report != null) { if (report.getInstances() == null) continue; for(Instance instance : report.getInstances()){ instances.add(new AbstractMap.SimpleImmutableEntry<>(instance, service.getKey())); } } else { LOGGER.log(Level.WARNING, "Unable to get the report for service: {0}", service.getKey()); } } } } catch (IOException ex) { Exceptions.printStackTrace(ex); } Collections.sort(instances,new Comparator<Entry<Instance,String>>(){ @Override public int compare(Entry<Instance, String> o1, Entry<Instance, String> o2) { if(o1.getValue().equals(o2.getValue())){ //compare instance names return o1.getKey().getIdentifier().compareTo(o2.getKey().getIdentifier()); }else{ //compare types return o1.getValue().compareTo(o2.getValue()); } } }); final TableModel model = new InstanceModel(instances); guiTable.setModel(model); final int width = 140; for (int i = 1; i < guiTable.getColumnCount(); i++) { guiTable.getColumn(i).setMinWidth(width); guiTable.getColumn(i).setPreferredWidth(width); guiTable.getColumn(i).setMaxWidth(width); } guiTable.setTableHeader(null); guiTable.setRowHeight(37); guiTable.setFillsViewportHeight(true); guiTable.setBackground(Color.WHITE); guiTable.setShowGrid(true); guiTable.setShowHorizontalLines(true); guiTable.setShowVerticalLines(false); guiTable.revalidate(); guiTable.repaint(); } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { guiTypeGroup = new javax.swing.ButtonGroup(); jPanel1 = new javax.swing.JPanel(); jToolBar0 = new javax.swing.JToolBar(); guiRefresh = new javax.swing.JButton(); jSeparator1 = new javax.swing.JToolBar.Separator(); guiToolBar = new javax.swing.JToolBar(); guiAll = new javax.swing.JToggleButton(); jToolBar1 = new javax.swing.JToolBar(); jSeparator2 = new javax.swing.JToolBar.Separator(); guiNew = new javax.swing.JButton(); setLayout(new java.awt.BorderLayout()); jPanel1.setLayout(new java.awt.BorderLayout()); jToolBar0.setFloatable(false); guiRefresh.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/constellation/swing/reload.png"))); // NOI18N java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/constellation/swing/Bundle"); // NOI18N guiRefresh.setText(bundle.getString("refresh")); // NOI18N guiRefresh.setFocusable(false); guiRefresh.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); guiRefresh.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { guiRefreshActionPerformed(evt); } }); jToolBar0.add(guiRefresh); jToolBar0.add(jSeparator1); jPanel1.add(jToolBar0, java.awt.BorderLayout.WEST); guiToolBar.setFloatable(false); guiTypeGroup.add(guiAll); guiAll.setSelected(true); guiAll.setText(bundle.getString("all")); // NOI18N guiAll.setActionCommand("all"); guiAll.setFocusable(false); guiAll.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); guiAll.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); guiToolBar.add(guiAll); jPanel1.add(guiToolBar, java.awt.BorderLayout.CENTER); jToolBar1.setFloatable(false); jToolBar1.add(jSeparator2); guiNew.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/constellation/swing/edit_add.png"))); // NOI18N guiNew.setText(bundle.getString("creation")); // NOI18N guiNew.setFocusable(false); guiNew.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); guiNew.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { guiNewActionPerformed(evt); } }); jToolBar1.add(guiNew); jPanel1.add(jToolBar1, java.awt.BorderLayout.EAST); add(jPanel1, java.awt.BorderLayout.NORTH); }// </editor-fold>//GEN-END:initComponents private void guiRefreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_guiRefreshActionPerformed updateInstanceList(); }//GEN-LAST:event_guiRefreshActionPerformed private void guiNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_guiNewActionPerformed final String[] params = JServiceCreationPane.showDialog(cstlV2); if(params != null){ try { final Details metadata = new Details(); metadata.setIdentifier(params[1]); final String serviceType = params[0].toUpperCase(); cstlV2.services.newInstance(ServiceDef.Specification.valueOf(serviceType), metadata); updateInstanceList(); } catch (IOException ex) { Exceptions.printStackTrace(ex); } } }//GEN-LAST:event_guiNewActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JToggleButton guiAll; private javax.swing.JButton guiNew; private javax.swing.JButton guiRefresh; private javax.swing.JToolBar guiToolBar; private javax.swing.ButtonGroup guiTypeGroup; private javax.swing.JPanel jPanel1; private javax.swing.JToolBar.Separator jSeparator1; private javax.swing.JToolBar.Separator jSeparator2; private javax.swing.JToolBar jToolBar0; private javax.swing.JToolBar jToolBar1; // End of variables declaration//GEN-END:variables @Override public void actionPerformed(ActionEvent e) { updateInstanceList(); } @Override public void propertyChange(PropertyChangeEvent evt) { updateInstanceList(); } private class InstanceModel extends AbstractTableModel{ private final List<Entry<Instance,String>> entries; public InstanceModel(final List<Entry<Instance,String>> entries) { this.entries = entries; } @Override public Class<?> getColumnClass(int columnIndex) { if(columnIndex == 0){ return Entry.class; }else{ return Action.class; } } @Override public int getRowCount() { return entries.size(); } @Override public int getColumnCount() { return 1+actions.size(); } @Override public Object getValueAt(int rowIndex, int columnIndex) { if(columnIndex>0){ final Action act = actions.get(columnIndex-1).clone(); act.setTarget(entries.get(rowIndex)); act.setDisplayer(displayer); return act; } return entries.get(rowIndex); } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return columnIndex>0; } } public static BufferedImage createImage(String text, ImageIcon icon, Color textColor, Font font,Color bgColor){ final int border = 5; BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); Graphics2D g = img.createGraphics(); final FontMetrics fm = g.getFontMetrics(font); final int textSize = fm.stringWidth(text); int width = textSize+border*2; int height = fm.getHeight()+border*2; if(icon != null){ width += icon.getIconWidth() + 2; height = Math.max(height, icon.getIconHeight()); } img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); g = img.createGraphics(); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); final RoundRectangle2D rect = new RoundRectangle2D.Double(0, 0, width-1, img.getHeight()-1, border, border); g.setColor(bgColor); g.fill(rect); int x = border; //draw icon if(icon != null){ g.drawImage(icon.getImage(), x, (height-icon.getIconHeight())/2, null); x += icon.getIconWidth()+2; } //draw text g.setColor(textColor); g.setFont(font); g.drawString(text, x, fm.getMaxAscent()+border); return img; } }