/*******************************************************************************
* 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;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.eclipse.persistence.tools.workbench.framework.context.WorkbenchContext;
import org.eclipse.persistence.tools.workbench.framework.ui.chooser.ClassDescriptionRepository;
import org.eclipse.persistence.tools.workbench.framework.ui.chooser.MultipleClassChooserDialog;
import org.eclipse.persistence.tools.workbench.framework.ui.dialog.AbstractDialog;
import org.eclipse.persistence.tools.workbench.framework.uitools.SwingComponentFactory;
import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWDescriptor;
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.ExternalClassLoadFailureContainer;
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWClass;
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWClassRepository;
import org.eclipse.persistence.tools.workbench.mappingsmodel.project.MWProject;
import org.eclipse.persistence.tools.workbench.mappingsplugin.ui.common.cell.ClassCellRendererAdapter;
import org.eclipse.persistence.tools.workbench.mappingsplugin.ui.meta.ExternalClassDescriptionClassDesciptionAdapter;
import org.eclipse.persistence.tools.workbench.mappingsplugin.ui.meta.ExternalClassDescriptionClassDescriptionRepository;
import org.eclipse.persistence.tools.workbench.mappingsplugin.ui.meta.ExternalClassLoadFailuresDialog;
import org.eclipse.persistence.tools.workbench.uitools.LabelArea;
import org.eclipse.persistence.tools.workbench.uitools.app.swing.ObjectListSelectionModel;
import org.eclipse.persistence.tools.workbench.uitools.cell.AdaptableListCellRenderer;
import org.eclipse.persistence.tools.workbench.utility.Classpath;
import org.eclipse.persistence.tools.workbench.utility.CollectionTools;
import org.eclipse.persistence.tools.workbench.utility.iterators.TransformationIterator;
import org.eclipse.persistence.tools.workbench.utility.string.StringTools;
public final class NonDescriptorClassManagementDialog
extends AbstractDialog
{
// **************** Variables *********************************************
/**
* This is passed in - from it we have access to the class repository
* and the descriptors (so that we may filter them out)
*/
private MWProject project;
/** The list model */
private DefaultListModel classesListModel;
/** The list selection model */
ObjectListSelectionModel classesListSelectionModel;
// **************** Constructors ******************************************
public NonDescriptorClassManagementDialog(WorkbenchContext context, MWProject project) {
super(context);
this.project = project;
this.buildModels();
}
// **************** Initialization ****************************************
protected void initialize() {
super.initialize();
String egg = "";
if (System.getProperty("user.name", "").equalsIgnoreCase("dmahar")) {
egg = "Denise's ";
}
this.setTitle(this.resourceRepository().getString("NON_DESCRIPTOR_CLASS_MANAGEMENT_DIALOG.TITLE", egg));
}
private void buildModels() {
this.classesListModel = new DefaultListModel();
this.rebuildClassesListModel();
this.classesListSelectionModel = this.buildClassesListSelectionModel();
}
private void rebuildClassesListModel() {
Set descriptorClasses = CollectionTools.set(this.descriptorClasses());
List types = new ArrayList(this.project.getClassRepository().userTypesSize());
for (Iterator stream = this.project.getClassRepository().userTypes(); stream.hasNext(); ) {
Object type = stream.next();
if ( ! descriptorClasses.contains(type)) {
types.add(type);
}
}
Collections.sort(types);
this.classesListModel.clear();
for (Iterator stream = types.iterator(); stream.hasNext(); ) {
this.classesListModel.addElement(stream.next());
}
}
private ObjectListSelectionModel buildClassesListSelectionModel() {
return new ObjectListSelectionModel(this.classesListModel);
}
protected Component buildMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
LabelArea label = new LabelArea();
label.setText(this.resourceRepository().getString("NON_DESCRIPTOR_CLASS_MANAGEMENT_DIALOG.EXPLANATION", StringTools.CR));
label.setBorder(BorderFactory.createEmptyBorder(3, 3, 5, 3));
panel.add(label, BorderLayout.NORTH);
JList list = SwingComponentFactory.buildList(this.classesListModel);
list.setSelectionModel(this.classesListSelectionModel);
list.setCellRenderer(this.buildCellRenderer());
JScrollPane scrollPane = new JScrollPane(list);
scrollPane.setPreferredSize(new Dimension(500, 400));
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
private ListCellRenderer buildCellRenderer() {
ClassCellRendererAdapter adapter =
new ClassCellRendererAdapter(this.resourceRepository()) {
public boolean showDetailedIcon() {
return false;
}
};
return new AdaptableListCellRenderer(adapter);
}
protected Iterator buildCustomActions() {
Collection actions = new ArrayList();
actions.add(this.buildAddAction());
actions.add(this.buildRemoveAction());
actions.add(this.buildRefreshAction());
return actions.iterator();
}
private Action buildAddAction() {
return new AbstractAction(this.resourceRepository().getString("NON_DESCRIPTOR_CLASS_MANAGEMENT_DIALOG.ADD_ACTION")) {
public void actionPerformed(ActionEvent e) {
NonDescriptorClassManagementDialog.this.addClasses();
}
};
}
void addClasses() {
this.repository().refreshExternalClassDescriptions();
MultipleClassChooserDialog dialog =
new MultipleClassChooserDialog(
this.getWorkbenchContext(),
this.buildMultiClassChooserDialogClassDescriptionRepository(),
ExternalClassDescriptionClassDesciptionAdapter.instance(),
this
);
dialog.show();
if (dialog.wasCanceled()) {
// try to force all the objects generated by the dialog to be garbage-collected
dialog = null;
MultipleClassChooserDialog.gc();
return;
}
ExternalClassLoadFailureContainer failures =
this.repository().refreshTypesFor(dialog.selectedClassDescriptions());
// try to force all the objects generated by the dialog to be garbage-collected
dialog = null;
MultipleClassChooserDialog.gc();
if (failures.containsFailures()) {
new ExternalClassLoadFailuresDialog(this.getWorkbenchContext(), this, failures).show();
}
this.rebuildClassesListModel();
}
private ClassDescriptionRepository buildMultiClassChooserDialogClassDescriptionRepository() {
return new NonDescriptorExternalClassDescriptionClassDescriptionRepository(this.project.getClassRepository());
}
private Action buildRemoveAction() {
final Action action =
new AbstractAction(this.resourceRepository().getString("NON_DESCRIPTOR_CLASS_MANAGEMENT_DIALOG.REMOVE_ACTION")) {
public void actionPerformed(ActionEvent e) {
NonDescriptorClassManagementDialog.this.removeSelectedClasses();
}
};
action.setEnabled(false);
this.classesListSelectionModel.addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if ( ! e.getValueIsAdjusting()) {
action.setEnabled(! NonDescriptorClassManagementDialog.this.classesListSelectionModel.isSelectionEmpty());
}
}
}
);
return action;
}
void removeSelectedClasses() {
for (Iterator stream = CollectionTools.iterator(this.classesListSelectionModel.getSelectedValues()); stream.hasNext(); ) {
MWClass type = ((MWClass) stream.next());
this.classesListModel.removeElement(type);
type.clear();
}
}
private Action buildRefreshAction() {
final Action action =
new AbstractAction(this.resourceRepository().getString("NON_DESCRIPTOR_CLASS_MANAGEMENT_DIALOG.REFRESH_ACTION")) {
public void actionPerformed(ActionEvent e) {
NonDescriptorClassManagementDialog.this.refreshSelectedClasses();
}
};
action.setEnabled(false);
this.classesListSelectionModel.addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if ( ! e.getValueIsAdjusting()) {
action.setEnabled( ! NonDescriptorClassManagementDialog.this.classesListSelectionModel.isSelectionEmpty());
}
}
}
);
return action;
}
void refreshSelectedClasses() {
this.repository().refreshExternalClassDescriptions();
ExternalClassLoadFailureContainer failures =
this.repository().refreshTypes(CollectionTools.iterator(this.classesListSelectionModel.getSelectedValues()));
if (failures.containsFailures()) {
new ExternalClassLoadFailuresDialog(this.getWorkbenchContext(), this, failures).show();
}
}
// **************** Convenience *******************************************
private MWClassRepository repository() {
return this.project.getClassRepository();
}
Iterator descriptorClasses() {
return new TransformationIterator(this.project.descriptors()) {
protected Object transform(Object next) {
return ((MWDescriptor) next).getMWClass();
}
};
}
// **************** AbstractDialog implementation/overrides ***************
protected boolean cancelButtonIsVisible() {
return false;
}
protected String helpTopicId() {
return "dialog.nonDescriptorManagement";
}
// **************** Member classes ****************************************
/**
* This repository will return "external class descriptions" for all the classes found
* on the "project" classpath, except those that are already mapped
* (and their superclasses and super-interfaces)
*/
private class NonDescriptorExternalClassDescriptionClassDescriptionRepository
extends ExternalClassDescriptionClassDescriptionRepository
{
/** descriptor classes and their superclasses and super-interfaces */
Collection descriptorClassNames;
/** all the classes found on the "project" classpath */
Collection userClassNames;
private NonDescriptorExternalClassDescriptionClassDescriptionRepository(MWClassRepository repository) {
super(repository);
this.descriptorClassNames = this.buildDescriptorClassNames();
this.userClassNames = this.buildUserClassNames();
}
private Collection buildDescriptorClassNames() {
return CollectionTools.set(this.allDescriptorClassNames());
}
private Iterator allDescriptorClassNames() {
return new TransformationIterator(NonDescriptorClassManagementDialog.this.descriptorClasses()) {
protected Object transform(Object next) {
return ((MWClass) next).getName();
}
};
}
private Collection buildUserClassNames() {
Classpath cp = new Classpath(CollectionTools.list(this.repository.fullyQualifiedClasspathEntries()));
Collection result = new HashSet(1000); // start sorta big
cp.addClassNamesTo(result);
return result;
}
protected boolean accept(String externalClassDescriptionName) {
return super.accept(externalClassDescriptionName) &&
this.userClassNames.contains(externalClassDescriptionName) &&
! this.descriptorClassNames.contains(externalClassDescriptionName);
}
}
}