/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Business Objects nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * GemBlessingDialog.java * Created: 20-Apr-2004 * By: Rick Cameron */ package org.openquark.samples.bam.ui; import java.awt.Component; import java.awt.Frame; import java.awt.GridBagConstraints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.net.URL; import java.util.Collection; import java.util.Set; import javax.swing.BoxLayout; import javax.swing.DefaultListCellRenderer; import javax.swing.DefaultListModel; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.ListModel; import org.openquark.cal.compiler.TypeExpr; import org.openquark.cal.metadata.ScopedEntityMetadata; import org.openquark.cal.module.Cal.Core.CAL_Prelude; import org.openquark.cal.services.GemEntity; import org.openquark.cal.services.GemFilter; import org.openquark.samples.bam.ActionGemFilter; import org.openquark.samples.bam.GemManager; import org.openquark.samples.bam.MetricGemFilter; import org.openquark.samples.bam.MonitorApp; import org.openquark.samples.bam.TriggerGemFilter; import org.openquark.util.ui.DialogBase; /** * * */ class GemBlessingDialog extends DialogBase { private static final long serialVersionUID = -5118454765744523233L; private static final int NO_BLESSING = 0; private static final int TRIGGER_BLESSING = 1; private static final int ACTION_BLESSING = 2; private static final int METRIC_BLESSING = 3; /** * this filter1 only returns gems that return boolean values * @author Magnus Byne */ private static class BooleanGemFilter extends GemFilter { //only select gems that return a boolean @Override public boolean select (GemEntity gemEntity) { TypeExpr gemTypeExpr = gemEntity.getTypeExpr(); return gemTypeExpr.getResultType().isNonParametricType(CAL_Prelude.TypeConstructors.Boolean); } } /** * this filter1 only returns gems of the form [a]->[b], i.e. possible metrics * @author Magnus Byne */ private static class ListGemFilter extends GemFilter { //only select gems that map from a list to a list @Override public boolean select (GemEntity gemEntity) { TypeExpr gemTypeExpr = gemEntity.getTypeExpr(); return (gemTypeExpr.getArgumentType() != null && gemTypeExpr.getArgumentType().isListType() && gemTypeExpr.getResultType().isListType()); } } private static class GemListItem { private static Icon triggerBlessingIcon; private static Icon actionBlessingIcon; private static Icon metricBlessingIcon; private static Icon noBlessingIcon; private final GemEntity gemEntity; private int blessing; /** * Method getNoBlessingIcon * * @return Returns the icon used for gems that have no blessing */ private static Icon getNoBlessingIcon () { if (noBlessingIcon == null) { noBlessingIcon = loadIcon ("smallBlank.gif"); //$NON-NLS-1$ } return noBlessingIcon; } /** * Method getMetricBlessingIcon * * @return Returns the icon used for gems that have no blessing */ private static Icon getMetricBlessingIcon () { if (metricBlessingIcon == null) { metricBlessingIcon = loadIcon ("smallBlank.gif"); //$NON-NLS-1$ } return metricBlessingIcon; } /** * Method getTriggerBlessingIcon * * @return Returns the icon used for gems that are blessed as triggers */ private Icon getTriggerBlessingIcon () { if (actionBlessingIcon == null) { actionBlessingIcon = loadIcon ("smallTrigger.gif"); //$NON-NLS-1$ } return actionBlessingIcon; } /** * Method getActionBlessingIcon * * @return Returns the icon used for gems that are blessed as actions */ private Icon getActionBlessingIcon () { if (triggerBlessingIcon == null) { triggerBlessingIcon = loadIcon ("smallAction.gif"); //$NON-NLS-1$ } return triggerBlessingIcon; } /** * Method loadIcon * * @param iconFileName * @return Returns an Icon loaded from the resource for this class */ private static Icon loadIcon (String iconFileName) { String iconFilePath = "/Resources/" + iconFileName; //$NON-NLS-1$ URL url = GemBlessingDialog.class.getResource (iconFilePath); if (url != null) { return new ImageIcon (url); } else { return null; } } GemListItem (GemEntity gemEntity, int initialBlessing) { this.gemEntity = gemEntity; this.blessing = initialBlessing; } /** * @see java.lang.Object#toString() */ @Override public String toString () { return gemEntity.getName ().getQualifiedName (); } /** * Method getIcon * * @return Returns an icon that represents the blessing state of this gem */ public Icon getIcon () { switch (blessing) { case TRIGGER_BLESSING: return getTriggerBlessingIcon (); case ACTION_BLESSING: return getActionBlessingIcon (); case METRIC_BLESSING: return getMetricBlessingIcon (); default: return getNoBlessingIcon (); } } /** * Method setBlessing * * @param blessing */ public void setBlessing (int blessing) { this.blessing = blessing; } } private static class GemListCellRenderer extends DefaultListCellRenderer { private static final long serialVersionUID = -7547133397739989698L; /** * @see javax.swing.DefaultListCellRenderer#getListCellRendererComponent(javax.swing.JList, java.lang.Object, * int, boolean, boolean) */ @Override public Component getListCellRendererComponent (JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Component renderer = super.getListCellRendererComponent (list, value, index, isSelected, cellHasFocus); if (renderer instanceof JLabel) { if (value instanceof GemListItem) { GemListItem item = (GemListItem)value; ((JLabel)renderer).setIcon (item.getIcon ()); } } return renderer; } } private final MonitorApp app; /** * Constructor GemBlessingDialog * * @param owner */ public GemBlessingDialog (Frame owner, MonitorApp app) { super (owner, "Manage Gems"); this.app = app; createTopLevelPanel (); } private JPanel createBlessingTab(GemFilter allFilter, GemFilter blessedFilter, int blessing ) { GridBagConstraints constraints = new GridBagConstraints (); JPanel panel = new JPanel(); constraints.anchor = GridBagConstraints.NORTHWEST; constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 0; constraints.gridy = 1; constraints.gridheight = 2; constraints.weightx = 2.0; constraints.weighty = 2.0; constraints.fill = GridBagConstraints.BOTH; panel.add ( createBlessingPanel(allFilter, blessedFilter, blessing)); return panel; } /** * Method createControls * * */ private void createTopLevelPanel () { JTabbedPane tabPane = new JTabbedPane(); tabPane.addTab("Triggers", createBlessingTab( new BooleanGemFilter(), new TriggerGemFilter(), TRIGGER_BLESSING)); tabPane.addTab("Actions", createBlessingTab( new BooleanGemFilter(), new ActionGemFilter(), ACTION_BLESSING)); tabPane.addTab("Metrics", createBlessingTab( new ListGemFilter(), new MetricGemFilter(), METRIC_BLESSING)); getContentPane().add (tabPane); pack (); addComponentListener (new SizeConstrainer (getSize ())); } /** * Set the blessing on a gem * @param gem * @param blessing the value to set the gem blessing to - NO_BLESSING to clear existing blessing */ private void blessGem(GemEntity gem, int blessing) { ScopedEntityMetadata metadata = gem.getMetadata(GemManager.getLocaleForMetadata()); metadata.setAttribute(TriggerGemFilter.TRIGGER_ATTRIBUTE_NAME, blessing == TRIGGER_BLESSING ? "trigger" : null); metadata.setAttribute(ActionGemFilter.ACTION_ATTRIBUTE_NAME, blessing == ACTION_BLESSING ? "action" : null); metadata.setAttribute(MetricGemFilter.METRIC_ATTRIBUTE_NAME, blessing == METRIC_BLESSING ? "metric" : null); if (!app.getCalServices().getCALWorkspace().saveMetadata(metadata)) { JOptionPane.showMessageDialog(this, "The metadata for the gem could not be updated.\nIs the metadata XML file read-only?", "BAM Sample", JOptionPane.ERROR_MESSAGE); } } private JPanel createBlessingPanel(GemFilter allFilter, GemFilter blessedFilter, int blessing) { JPanel panel = new JPanel(); GridBagConstraints constraints = new GridBagConstraints (); constraints.anchor = GridBagConstraints.NORTHWEST; constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 0; constraints.gridheight = 2; constraints.weightx = 2.0; constraints.weighty = 2.0; constraints.fill = GridBagConstraints.BOTH; JPanel allGemsPanel = new JPanel(); allGemsPanel.setLayout(new BoxLayout(allGemsPanel, BoxLayout.Y_AXIS)); allGemsPanel.add (new JLabel ("Available Gems"), constraints); Set<GemEntity> avaiableGems = app.getCalServices().getMatchingGems(allFilter); Set<GemEntity> blessedGems = app.getCalServices().getMatchingGems(blessedFilter); avaiableGems.removeAll(blessedGems); JList allGemsList=createGemList(avaiableGems); allGemsPanel.add(new JScrollPane(allGemsList), constraints); panel.add(allGemsPanel); JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS)); JButton buttonAdd=new JButton(">"); JButton buttonRemove=new JButton("<"); buttonPanel.add(buttonAdd); buttonPanel.add(buttonRemove); panel.add(buttonPanel); JPanel selectedGemsPanel = new JPanel(); selectedGemsPanel.setLayout(new BoxLayout(selectedGemsPanel, BoxLayout.Y_AXIS)); selectedGemsPanel.add (new JLabel ("Selected Gems"), constraints); JList blessedGemsList=createGemList(blessedGems); selectedGemsPanel.add(new JScrollPane(blessedGemsList), constraints); panel.add(selectedGemsPanel); buttonAdd.addActionListener (new ChangeBlessingAction (allGemsList, blessedGemsList, blessing)); buttonRemove.addActionListener (new ChangeBlessingAction (blessedGemsList, allGemsList, NO_BLESSING)); return panel; } /** * This class is used to handle the event of moving a gem between the blessed and unblessed lists * @author Magnus Byne */ class ChangeBlessingAction implements ActionListener{ private JList fromList; private JList toList; private int blessing; ChangeBlessingAction(JList fromList, JList toList, int blessing){ this.fromList = fromList; this.toList = toList; this.blessing = blessing; } /** * move selected items from the fromList to the toList and set the blessing * {@inheritDoc} */ public void actionPerformed (ActionEvent e) { Object[] selectedGems= fromList.getSelectedValues(); DefaultListModel fromListModel = (DefaultListModel) fromList.getModel(); DefaultListModel toListModel = (DefaultListModel) toList.getModel(); for (final Object element : selectedGems) { GemListItem listItem = (GemListItem)element; fromListModel.removeElement(listItem); blessGem(listItem.gemEntity, blessing); toListModel.addElement(new GemListItem (listItem.gemEntity, blessing)); } toList.setModel(toListModel); fromList.setModel(fromListModel); fromList.setSelectedIndices(new int[0]); } } /** * Method getGemList * * @return Returns the JList that displays available gems */ private JList createGemList (Collection<GemEntity> gemEntities) { ListModel gemListModel = makeGemListModel (gemEntities); JList gemList = new JList (gemListModel); gemList.setCellRenderer (new GemListCellRenderer ()); return gemList; } /** * Method makeGemListModel * * @return Returns a ListModel filled with the gems that can be blessed */ private ListModel makeGemListModel (Collection<GemEntity> gemEntities) { DefaultListModel listModel = new DefaultListModel (); for (final GemEntity gemEntity : gemEntities) { ScopedEntityMetadata metadata = gemEntity.getMetadata(GemManager.getLocaleForMetadata()); int blessing = NO_BLESSING; if (metadata.getAttribute(TriggerGemFilter.TRIGGER_ATTRIBUTE_NAME) != null) { blessing = TRIGGER_BLESSING; } else if (metadata.getAttribute(ActionGemFilter.ACTION_ATTRIBUTE_NAME) != null) { blessing = ACTION_BLESSING; } else if (metadata.getAttribute(MetricGemFilter.METRIC_ATTRIBUTE_NAME) != null) { blessing = METRIC_BLESSING; } listModel.addElement (new GemListItem (gemEntity, blessing)); } return listModel; } }