/*******************************************************************************
* 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.schema;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.Iterator;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.filechooser.FileFilter;
import org.eclipse.persistence.tools.workbench.framework.context.WorkbenchContextHolder;
import org.eclipse.persistence.tools.workbench.framework.ui.view.AbstractPanel;
import org.eclipse.persistence.tools.workbench.framework.uitools.FileChooserPanel;
import org.eclipse.persistence.tools.workbench.framework.uitools.SwingComponentFactory;
import org.eclipse.persistence.tools.workbench.framework.uitools.SwingTools;
import org.eclipse.persistence.tools.workbench.framework.uitools.FileChooserPanel.FileHolder;
import org.eclipse.persistence.tools.workbench.mappingsmodel.project.MWProject;
import org.eclipse.persistence.tools.workbench.mappingsmodel.resource.ClasspathResourceSpecification;
import org.eclipse.persistence.tools.workbench.mappingsmodel.resource.FileResourceSpecification;
import org.eclipse.persistence.tools.workbench.mappingsmodel.resource.ResourceSpecification;
import org.eclipse.persistence.tools.workbench.mappingsmodel.resource.UrlResourceSpecification;
import org.eclipse.persistence.tools.workbench.mappingsmodel.schema.MWXmlSchema;
import org.eclipse.persistence.tools.workbench.mappingsmodel.schema.MWXmlSchemaRepository;
import org.eclipse.persistence.tools.workbench.uitools.app.PropertyValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.SimplePropertyValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.ValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.swing.DocumentAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.swing.RadioButtonModelAdapter;
import org.eclipse.persistence.tools.workbench.utility.CollectionTools;
import org.eclipse.persistence.tools.workbench.utility.io.FileTools;
final class EditableSchemaPropertiesPanel
extends AbstractPanel
{
private PropertyValueModel schemaRepositoryHolder;
private PropertyValueModel schemaNameHolder;
private PropertyValueModel schemaLoadMechanismHolder;
private final static String FILE_MECHANISM = "file";
private final static String CLASSPATH_MECHANISM = "classpath";
private final static String URL_MECHANISM = "url";
private PropertyValueModel fileHolder;
private PropertyValueModel classpathResourceNameHolder;
private PropertyValueModel urlHolder;
public final static String SCHEMA_PROPERTY = "SCHEMA_PROPERTY";
private static final long serialVersionUID = 1L;
// *********** schema directory preference
private final static String MOST_RECENT_SCHEMA_DIRECTORY_PREFERENCE = "recent schema directory";
EditableSchemaPropertiesPanel(PropertyValueModel schemaRepositoryHolder, WorkbenchContextHolder contextHolder) {
super(contextHolder);
this.schemaRepositoryHolder = schemaRepositoryHolder;
this.initialize();
}
private void initialize() {
this.schemaNameHolder = this.buildSchemaNameHolder();
this.schemaLoadMechanismHolder = this.buildSchemaLoadMechanismHolder();
this.fileHolder = this.buildFileHolder();
this.classpathResourceNameHolder = this.buildClasspathResourceNameHolder();
this.urlHolder = this.buildUrlHolder();
this.initializeLayout();
}
private PropertyValueModel buildSchemaNameHolder() {
PropertyValueModel result = new SimplePropertyValueModel("");
result.addPropertyChangeListener(ValueModel.VALUE, this.buildErrorListener());
return result;
}
private PropertyValueModel buildSchemaLoadMechanismHolder() {
PropertyValueModel result = new SimplePropertyValueModel(FILE_MECHANISM);
result.addPropertyChangeListener(ValueModel.VALUE, this.buildErrorListener());
return result;
}
private PropertyValueModel buildFileHolder() {
PropertyValueModel result = new SimplePropertyValueModel(null);
result.addPropertyChangeListener(ValueModel.VALUE, this.buildErrorListener());
result.addPropertyChangeListener(ValueModel.VALUE, this.buildFileListener());
return result;
}
private PropertyChangeListener buildFileListener() {
return new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
File newFile = new File((String) evt.getNewValue());
if (
"".equals(EditableSchemaPropertiesPanel.this.getSchemaName())
// this part is to distinguish between typing and browsing
// so that only "complete" file names are used for the schema name
&& newFile.exists()
// this part is to eliminate folder files
&& newFile.isFile()
) {
EditableSchemaPropertiesPanel.this.setSchemaNameFromFile(newFile);
}
}
};
}
private PropertyValueModel buildClasspathResourceNameHolder() {
PropertyValueModel result = new SimplePropertyValueModel("");
result.addPropertyChangeListener(ValueModel.VALUE, this.buildErrorListener());
return result;
}
private PropertyValueModel buildUrlHolder() {
PropertyValueModel result = new SimplePropertyValueModel("");
result.addPropertyChangeListener(ValueModel.VALUE, this.buildErrorListener());
return result;
}
private PropertyChangeListener buildErrorListener() {
return new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
EditableSchemaPropertiesPanel.this.notifyErrorCheckers(evt);
}
};
}
void notifyErrorCheckers(PropertyChangeEvent evt) {
this.firePropertyChange(EditableSchemaPropertiesPanel.SCHEMA_PROPERTY, evt.getOldValue(), evt.getNewValue());
}
private void initializeLayout() {
this.setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
// Create the schema name label
JLabel schemaNameLabel = new JLabel(resourceRepository().getString("SCHEMA_NAME_LABEL"));
schemaNameLabel.setDisplayedMnemonic(resourceRepository().getMnemonic("SCHEMA_NAME_LABEL"));
constraints.gridx = 0;
constraints.gridy = 0;
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, 5);
this.add(schemaNameLabel, constraints);
// Create the schema name text field
JTextField schemaNameTextField = this.buildSchemaNameTextField();
addHelpTopicId(schemaNameTextField, "dialog.schemaProperties.name");
schemaNameLabel.setLabelFor(schemaNameTextField);
constraints.gridx = 1;
constraints.gridy = 0;
constraints.gridwidth = 2;
constraints.gridheight = 1;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.CENTER;
constraints.insets = new Insets(5, 0, 0, 5);
this.add(schemaNameTextField, constraints);
// Source Radio button panel
JPanel sourcePanel = new JPanel(new GridBagLayout());
addHelpTopicId(schemaNameTextField, "dialog.schemaProperties.source");
sourcePanel.setBorder(BorderFactory.createTitledBorder(resourceRepository().getString("SOURCE_PANEL_LABEL")));
constraints.gridx = 0;
constraints.gridy = 1;
constraints.gridwidth = 3;
constraints.gridheight = 3;
constraints.weightx = 1;
constraints.weighty = 1;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.CENTER;
constraints.insets = new Insets(5, 0, 0, 0);
this.add(sourcePanel, constraints);
// File source button
JRadioButton fileButton = this.buildFileRadioButton();
constraints.gridx = 0;
constraints.gridy = 0;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 0;
constraints.weighty = 1;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.LINE_START;
constraints.insets = new Insets(0, 0, 0, 0);
sourcePanel.add(fileButton, constraints);
// File chooser panel
FileChooserPanel fileChooserPanel = this.buildFileChooserPanel();
constraints.gridx = 0;
constraints.gridy = 1;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 1;
constraints.weighty = 1;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.LINE_START;
constraints.insets = new Insets(0, SwingTools.checkBoxIconWidth(), 10, 5);
sourcePanel.add(fileChooserPanel, constraints);
// URL source button
JRadioButton urlButton = this.buildUrlRadioButton();
constraints.gridx = 0;
constraints.gridy = 2;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 0;
constraints.weighty = 1;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.LINE_START;
constraints.insets = new Insets(0, 0, 0, 0);
sourcePanel.add(urlButton, constraints);
// URL text field
JTextField urlTextField = this.buildUrlTextField();
constraints.gridx = 0;
constraints.gridy = 3;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 1;
constraints.weighty = 1;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.CENTER;
constraints.insets = new Insets(0, SwingTools.checkBoxIconWidth(), 10, 5);
sourcePanel.add(urlTextField, constraints);
// Classpath button
JRadioButton classpathButton = this.buildClasspathRadioButton();
constraints.gridx = 0;
constraints.gridy = 4;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 0;
constraints.weighty = 1;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.LINE_START;
constraints.insets = new Insets(0, 0, 0, 0);
sourcePanel.add(classpathButton, constraints);
// Classpath resource panel
ClasspathResourcePanel classpathResourcePanel = this.buildClasspathResourcePanel();
constraints.gridx = 0;
constraints.gridy = 5;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 1;
constraints.weighty = 1;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.CENTER;
constraints.insets = new Insets(0, SwingTools.checkBoxIconWidth(), 5, 5);
sourcePanel.add(classpathResourcePanel, constraints);
this.setPreferredSize(new Dimension(600, this.getPreferredSize().height));
}
private JTextField buildSchemaNameTextField() {
JTextField schemaNameTextField = new JTextField(new DocumentAdapter(this.schemaNameHolder), null, 1);
/*
this.setFocusComponent(schemaNameTextField);
TODO
*/
return schemaNameTextField;
}
private JRadioButton buildFileRadioButton() {
return SwingComponentFactory.buildRadioButton("FILE_RADIO_BUTTON_LABEL", this.buildFileRadioButtonModel(), this.resourceRepository());
}
private RadioButtonModelAdapter buildFileRadioButtonModel() {
return new RadioButtonModelAdapter(this.schemaLoadMechanismHolder, FILE_MECHANISM);
}
private FileChooserPanel buildFileChooserPanel() {
FileChooserPanel fileChooserPanel = new FileChooserPanel(getApplicationContext(), this.fileHolder, "FILE_RADIO_BUTTON_LABEL") {
protected boolean labelVisible() {
return false;
}
};
fileChooserPanel.setFileChooserFileFilter(this.buildFileFilter());
fileChooserPanel.setFileChooserRootFileHolder(this.buildFileChooserRootFileHolder());
fileChooserPanel.setEnabled(true);
fileChooserPanel.setFileChooserDefaultDirectoryHolder(this.buildFileChooserDefaultDirectoryHolder(MOST_RECENT_SCHEMA_DIRECTORY_PREFERENCE));
this.schemaLoadMechanismHolder.addPropertyChangeListener(ValueModel.VALUE, this.buildLoadMechanismListener(fileChooserPanel, FILE_MECHANISM));
return fileChooserPanel;
}
private FileFilter buildFileFilter() {
return new FileFilter() {
public boolean accept(File pathname) {
return pathname.isDirectory() || pathname.getAbsolutePath().endsWith(".xsd");
}
public String getDescription() {
return EditableSchemaPropertiesPanel.this.resourceRepository().getString("XML_SCHEMA_DEFINITION_DESCRIPTION");
}
};
}
private MWXmlSchemaRepository schemaRepository() {
return (MWXmlSchemaRepository) this.schemaRepositoryHolder.getValue();
}
MWProject project() {
return this.schemaRepository().getProject();
}
private FileHolder buildFileChooserRootFileHolder() {
return new FileHolder() {
public File getFile() {
return project().getSaveDirectory();
}
public void setFile(File file) {
throw new UnsupportedOperationException();
}
};
}
/**
* the default directory for the file chooser is one of the following:
* - project save directory
* - preference setting
* - user home directory
*/
private FileHolder buildFileChooserDefaultDirectoryHolder(final String prefKey) {
return new FileHolder() {
public File getFile() {
File projectSaveDir = EditableSchemaPropertiesPanel.this.project().getSaveDirectory();
if (projectSaveDir != null) {
return projectSaveDir;
}
String prefDirName = EditableSchemaPropertiesPanel.this.preferences().get(prefKey, null);
if (prefDirName != null) {
return new File(prefDirName);
}
return FileTools.userHomeDirectory();
}
public void setFile(File file) {
if (file.equals(FileTools.userHomeDirectory())) {
// don't save the user home
file = null;
} else if (file.equals(EditableSchemaPropertiesPanel.this.project().getSaveDirectory())) {
// don't save the project save directory
file = null;
}
// if the directory is special, save it as a preference, otherwise clear the preference
if (file == null) {
EditableSchemaPropertiesPanel.this.preferences().remove(prefKey);
} else {
EditableSchemaPropertiesPanel.this.preferences().put(prefKey, file.getPath());
}
}
};
}
private JRadioButton buildUrlRadioButton() {
JRadioButton urlButton = new JRadioButton();
urlButton.setModel(this.buildUrlRadioButtonModel());
urlButton.setText(resourceRepository().getString("URL_RADIO_BUTTON_LABEL"));
urlButton.setMnemonic(resourceRepository().getMnemonic("URL_RADIO_BUTTON_LABEL"));
return urlButton;
}
private RadioButtonModelAdapter buildUrlRadioButtonModel() {
return new RadioButtonModelAdapter(this.schemaLoadMechanismHolder, URL_MECHANISM);
}
private JTextField buildUrlTextField() {
JTextField urlTextField = new JTextField();
urlTextField.setEnabled(false);
urlTextField.setDocument(new DocumentAdapter(this.urlHolder));
this.schemaLoadMechanismHolder.addPropertyChangeListener(ValueModel.VALUE, this.buildLoadMechanismListener(urlTextField, URL_MECHANISM));
return urlTextField;
}
private JRadioButton buildClasspathRadioButton() {
JRadioButton classpathButton = new JRadioButton();
classpathButton.setModel(this.buildClasspathRadioButtonModel());
classpathButton.setText(resourceRepository().getString("CLASSPATH_RADIO_BUTTON_LABEL"));
classpathButton.setMnemonic(resourceRepository().getMnemonic("CLASSPATH_RADIO_BUTTON_LABEL"));
return classpathButton;
}
private RadioButtonModelAdapter buildClasspathRadioButtonModel() {
return new RadioButtonModelAdapter(this.schemaLoadMechanismHolder, CLASSPATH_MECHANISM);
}
private ClasspathResourcePanel buildClasspathResourcePanel() {
ClasspathResourcePanel classpathResourcePanel = new ClasspathResourcePanel(this.classpathResourceNameHolder);
classpathResourcePanel.setEnabled(false);
this.schemaLoadMechanismHolder.addPropertyChangeListener(ValueModel.VALUE, this.buildLoadMechanismListener(classpathResourcePanel, CLASSPATH_MECHANISM));
return classpathResourcePanel;
}
private PropertyChangeListener buildLoadMechanismListener(final Component component, final String loadMechanism) {
return new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
component.setEnabled(evt.getNewValue() == loadMechanism);
}
};
}
// **************** API ***************************************************
String getSchemaName() {
return (String) this.schemaNameHolder.getValue();
}
void setSchemaNameFromFile(File schemaFile) {
String schemaName = schemaFile.getName();
if (schemaName.lastIndexOf(".") != -1) {
schemaName = schemaName.substring(0, schemaName.lastIndexOf("."));
}
this.schemaNameHolder.setValue(schemaName);
}
boolean isFileMechanism() {
return this.schemaLoadMechanismHolder.getValue() == FILE_MECHANISM;
}
String getFileName() {
return (String) this.fileHolder.getValue();
}
boolean isUrlMechanism() {
return this.schemaLoadMechanismHolder.getValue() == URL_MECHANISM;
}
String getUrl() {
return (String) this.urlHolder.getValue();
}
boolean isClasspathResourceMechanism() {
return this.schemaLoadMechanismHolder.getValue() == CLASSPATH_MECHANISM;
}
String getClasspathResourceName() {
return (String) this.classpathResourceNameHolder.getValue();
}
void populate(MWXmlSchema schema) {
this.schemaNameHolder.setValue(schema.getName());
ResourceSpecification schemaSource = schema.getSchemaSource();
if (schemaSource instanceof FileResourceSpecification) {
this.schemaLoadMechanismHolder.setValue(FILE_MECHANISM);
this.fileHolder.setValue(schemaSource.getLocation());
}
else if (schemaSource instanceof UrlResourceSpecification) {
this.schemaLoadMechanismHolder.setValue(URL_MECHANISM);
this.urlHolder.setValue(schemaSource.getLocation());
}
if (schemaSource instanceof ClasspathResourceSpecification) {
this.schemaLoadMechanismHolder.setValue(CLASSPATH_MECHANISM);
this.classpathResourceNameHolder.setValue(schemaSource.getLocation());
}
}
// **************** Member classes ****************************************
private class ClasspathResourcePanel
extends JPanel
{
private static final long serialVersionUID = 1L;
private ClasspathResourcePanel(PropertyValueModel resourceNameHolder) {
super();
this.initialize(resourceNameHolder);
}
private void initialize(PropertyValueModel resourceNameHolder) {
this.setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
//Resource name label
JLabel resourceNameLabel = new JLabel(EditableSchemaPropertiesPanel.this.resourceRepository().getString("RESOURCE_NAME_LABEL"));
constraints.gridx = 0;
constraints.gridy = 0;
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(0, 0, 0, 0);
this.add(resourceNameLabel, constraints);
// Resource name text field
JTextField resourceNameTextField = this.buildResourceNameTextField(resourceNameLabel, resourceNameHolder);
constraints.gridx = 1;
constraints.gridy = 0;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.CENTER;
constraints.insets = new Insets(0, 5, 0, 0);
this.add(resourceNameTextField, constraints);
resourceNameLabel.setLabelFor(resourceNameTextField);
}
private JTextField buildResourceNameTextField(JLabel resourceNameLabel, PropertyValueModel resourceNameHolder) {
JTextField resourceNameTextField = new JTextField();
resourceNameTextField.setDocument(new DocumentAdapter(resourceNameHolder));
resourceNameTextField.setPreferredSize(new Dimension(200, (int) resourceNameTextField.getPreferredSize().getHeight()));
resourceNameLabel.setLabelFor(resourceNameTextField);
return resourceNameTextField;
}
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
for (Iterator components = CollectionTools.iterator(this.getComponents()); components.hasNext(); ) {
((Component) components.next()).setEnabled(enabled);
}
}
}
}