/******************************************************************************* * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.tools.workbench.mappingsplugin.ui.db; import java.awt.Component; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.util.Collection; import java.util.TreeSet; import java.util.Vector; import javax.swing.Action; import javax.swing.DefaultListCellRenderer; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.ListCellRenderer; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.plaf.basic.BasicArrowButton; import org.eclipse.persistence.tools.workbench.framework.action.AbstractFrameworkAction; import org.eclipse.persistence.tools.workbench.framework.context.WorkbenchContext; import org.eclipse.persistence.tools.workbench.framework.ui.dialog.AbstractDialog; import org.eclipse.persistence.tools.workbench.framework.uitools.DoubleClickMouseListener; import org.eclipse.persistence.tools.workbench.framework.uitools.SwingComponentFactory; import org.eclipse.persistence.tools.workbench.mappingsmodel.generation.MWRelationshipHolder; import org.eclipse.persistence.tools.workbench.uitools.LabelArea; /** ** If you want the lists to be sorted, then pass in sorted collections. */ final class RelationshipGenerationDialog extends AbstractDialog implements ActionListener, ListSelectionListener { private TreeSet availableListData; private TreeSet selectedListData; private JList availableList; private JList selectedList; private JButton oneToManyButton; private JButton oneToOneButton; private boolean generateBidirectionalRelationships; private JCheckBox generateBidirectionalRelationshipsCheckBox; protected final static String ID_ONE_TO_ONE = "One-To-One"; protected final static String ID_CREATE = "Create"; protected final static String ID_SKIP = "Skip"; protected final static String ID_ONE_TO_MANY = "One-To-Many"; protected final static String ID_DESELECT_ITEMS = "Deselect Items"; public RelationshipGenerationDialog(Vector relationships, WorkbenchContext workbenchContext) { super(workbenchContext); setAvailableListData(relationships); setSelectedListData(new Vector()); } public boolean getGenerateBidirectionalRelationships() { return this.generateBidirectionalRelationshipsCheckBox.isSelected(); } private ListCellRenderer getListCellRenderer() { return new DefaultListCellRenderer() { public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); MWRelationshipHolder holder = (MWRelationshipHolder) value; label.setText(holder.displayString()); if (holder.isOneToOne()) label.setIcon(resourceRepository().getIcon("mapping.oneToOne")); else if (holder.isOneToMany()) label.setIcon(resourceRepository().getIcon("mapping.oneToMany")); return label; } }; } public Collection getRelationshipsToCreate() { return new Vector(selectedListData); } protected String helpTopicId() { return "dialog.relationshipGenerator"; } protected Component initialFocusComponent() { return availableList; } protected void initialize(WorkbenchContext context) { super.initialize(context); setTitle(resourceRepository().getString("chooseRelationshipsToGenerate.title")); } protected void prepareToShow() { this.setSize(800, 400); this.setLocationRelativeTo(this.getParent()); } protected Component buildMainPanel() { GridBagConstraints constraints = new GridBagConstraints(); JPanel mainPanel = new JPanel(new GridBagLayout()); // Create text message LabelArea messageLabel = new LabelArea(resourceRepository().getString("basedOnTheForeignKeysOfThe")); constraints.gridx = 0; constraints.gridy = 0; constraints.gridwidth = 3; constraints.gridheight = 1; constraints.weightx = 1; constraints.weighty = 0; constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.CENTER; constraints.insets = new Insets(0, 5, 0, 5); mainPanel.add(messageLabel, constraints); // Create separator JSeparator separator = new JSeparator(JSeparator.HORIZONTAL); constraints.gridx = 0; constraints.gridy = 2; constraints.gridwidth = 3; constraints.gridheight = 1; constraints.weightx = 1; constraints.weighty = 0; constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.CENTER; constraints.insets = new Insets(10, 5, 5, 5); mainPanel.add(separator, constraints); // Create available items label, list, and scrollpane JLabel availableLabel = SwingComponentFactory.buildLabel("potentialRelationships", resourceRepository()); constraints.gridx = 0; constraints.gridy = 3; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 0; constraints.weighty = 0; constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.LINE_START; constraints.insets = new Insets(5, 5, 0, 0); mainPanel.add(availableLabel, constraints); availableList = new JList(); availableList.setCellRenderer(getListCellRenderer()); availableList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); availableList.addListSelectionListener(this); availableList.setListData(availableListData.toArray()); availableLabel.setLabelFor(availableList); JScrollPane availableScrollpane = new JScrollPane(availableList); availableScrollpane.getViewport().setPreferredSize(new Dimension(0, 0)); constraints.gridx = 0; constraints.gridy = 4; constraints.gridwidth = 1; constraints.gridheight = 3; constraints.weightx = 0.5; constraints.weighty = 1; constraints.fill = GridBagConstraints.BOTH; constraints.anchor = GridBagConstraints.CENTER; constraints.insets = new Insets(1, 5, 0, 0); mainPanel.add(availableScrollpane, constraints); // Create selected items label, list, and scrollpane JLabel selectedLabel = SwingComponentFactory.buildLabel("selectedRelationships", resourceRepository()); constraints.gridx = 2; constraints.gridy = 3; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 0; constraints.weighty = 0; constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.LINE_START; constraints.insets = new Insets(5, 5, 0, 5); mainPanel.add(selectedLabel, constraints); selectedList = SwingComponentFactory.buildList(); selectedList.setCellRenderer(getListCellRenderer()); selectedList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); selectedList.setListData(selectedListData.toArray()); // setup double clicking in the selected list to remove items SwingComponentFactory.addDoubleClickMouseListener(selectedList, new DoubleClickMouseListener() { public void mouseDoubleClicked(MouseEvent e) { deselectItems(); } }); selectedLabel.setLabelFor(selectedList); JScrollPane selectedScrollpane = new JScrollPane(selectedList); selectedScrollpane.getViewport().setPreferredSize(new Dimension(0, 0)); constraints.gridx = 2; constraints.gridy = 4; constraints.gridwidth = 1; constraints.gridheight = 3; constraints.weightx = 0.5; constraints.weighty = 1; constraints.fill = GridBagConstraints.BOTH; constraints.anchor = GridBagConstraints.CENTER; constraints.insets = new Insets(1, 5, 0, 5); mainPanel.add(selectedScrollpane, constraints); // Create One to One button oneToOneButton = new JButton(); oneToOneButton.setIcon(resourceRepository().getIcon("mapping.oneToOne")); oneToOneButton.setToolTipText(resourceRepository().getString("mapAsOneToOne")); oneToOneButton.setActionCommand(ID_ONE_TO_ONE); oneToOneButton.addActionListener(this); constraints.gridx = 1; constraints.gridy = 4; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 0; constraints.weighty = 0; constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.CENTER; constraints.insets = new Insets(1, 5, 0, 0); mainPanel.add(oneToOneButton, constraints); // Create One to Many button oneToManyButton = new JButton(); oneToManyButton.setIcon(resourceRepository().getIcon("mapping.oneToMany")); oneToManyButton.setToolTipText(resourceRepository().getString("mapAsOneToMany")); oneToManyButton.setActionCommand(ID_ONE_TO_MANY); oneToManyButton.addActionListener(this); constraints.gridx = 1; constraints.gridy = 5; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 0; constraints.weighty = 0; constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.CENTER; constraints.insets = new Insets(5, 5, 0, 0); mainPanel.add(oneToManyButton, constraints); // Left arrow button JButton leftArrowButton = new JButton(); leftArrowButton.addActionListener(buildAction()); leftArrowButton.setIcon(resourceRepository().getIcon("shuttle.left")); leftArrowButton.setEnabled(false); leftArrowButton.setToolTipText(resourceRepository().getString("removeSelectedMappings")); selectedList.addListSelectionListener(buildSelectionListListener(leftArrowButton)); leftArrowButton.setActionCommand(ID_DESELECT_ITEMS); constraints.gridx = 1; constraints.gridy = 6; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 0; constraints.weighty = 1; constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.NORTH; constraints.insets = new Insets(5, 5, 0, 0); mainPanel.add(leftArrowButton, constraints); // Generate Bidirectional Relationships Checkbox generateBidirectionalRelationshipsCheckBox = new JCheckBox(resourceRepository().getString("generateBidirectionalRelationships")); generateBidirectionalRelationshipsCheckBox.setMnemonic(resourceRepository().getMnemonic("generateBidirectionalRelationships")); generateBidirectionalRelationshipsCheckBox.setSelected(generateBidirectionalRelationships); constraints.gridx = 0; constraints.gridy = 7; constraints.gridwidth = 3; constraints.gridheight = 1; constraints.weightx = 0; constraints.weighty = 0; constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.NORTH; constraints.insets = new Insets(5, 5, 0, 0); mainPanel.add(generateBidirectionalRelationshipsCheckBox, constraints); return mainPanel; } private ListSelectionListener buildSelectionListListener(final JButton leftArrowButton) { return new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting()) { return; } if (selectedList.getSelectedValues().length > 0) { leftArrowButton.setEnabled(true); } else { leftArrowButton.setEnabled(false); } } }; } public void actionPerformed(ActionEvent e) { String actionCommand = e.getActionCommand(); if (actionCommand == ID_ONE_TO_ONE) selectItems(ID_ONE_TO_ONE); else if (actionCommand == ID_ONE_TO_MANY) selectItems(ID_ONE_TO_MANY); else if (actionCommand == ID_DESELECT_ITEMS) deselectItems(); } private AbstractFrameworkAction buildAction() { return new AbstractFrameworkAction(getWorkbenchContext()) { public void actionPerformed(ActionEvent e) { RelationshipGenerationDialog.this.actionPerformed(e); } }; } private void deselectItems() { Collection selectedItems = selectedListData; Collection availableItems = availableListData; Object[] selectedSelectedItems = selectedList.getSelectedValues(); for (int i = 0; i < selectedSelectedItems.length; i++) { ((MWRelationshipHolder) selectedSelectedItems[i]).setNoRelationship(); selectedItems.remove(selectedSelectedItems[i]); availableItems.add(selectedSelectedItems[i]); } availableList.setListData(availableItems.toArray()); selectedList.setListData(selectedItems.toArray()); setAvailableListData(availableItems); setSelectedListData(selectedItems); } public void selectItems(String typeOfMapping) { Collection selectedItems = selectedListData; Collection availableItems = availableListData; Object[] selectedAvailableItems = availableList.getSelectedValues(); for (int i = 0; i < selectedAvailableItems.length; i++) { if (!selectedItems.contains(selectedAvailableItems[i])) { MWRelationshipHolder mappingHolder = (MWRelationshipHolder) selectedAvailableItems[i]; if (typeOfMapping.equals(ID_ONE_TO_ONE)) mappingHolder.setOneToOne(); else mappingHolder.setOneToMany(); selectedItems.add(selectedAvailableItems[i]); availableItems.remove(selectedAvailableItems[i]); } } availableList.setListData(availableItems.toArray()); selectedList.setListData(selectedItems.toArray()); setAvailableListData(availableItems); setSelectedListData(selectedItems); } private void setAvailableListData(Collection data) { availableListData = new TreeSet(data); } public void setGenerateBidirectionalRelationships(boolean newValue) { this.generateBidirectionalRelationships = newValue; } private void setSelectedListData(Collection data) { selectedListData = new TreeSet(data); } public void valueChanged(ListSelectionEvent lse) { if (lse.getValueIsAdjusting()) return; Object[] selectedAvailableItems = availableList.getSelectedValues(); int oneToOneCount = 0; int oneToManyCount = 0; for (int i = 0; i < selectedAvailableItems.length; i++) { MWRelationshipHolder holder = (MWRelationshipHolder) selectedAvailableItems[i]; if (holder.canMapOneToOne()) oneToOneCount++; if (holder.canMapOneToMany()) oneToManyCount++; } oneToOneButton.setEnabled(oneToOneCount > 0); oneToManyButton.setEnabled(oneToManyCount > 0 && oneToManyCount == selectedAvailableItems.length); } }