/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.xsd.ui.wizards;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.xsd.XSDComplexTypeDefinition;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDSchema;
import org.teiid.core.designer.util.CoreStringUtil;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.ui.PluginConstants;
import org.teiid.designer.ui.UiConstants;
import org.teiid.designer.ui.common.InternalUiConstants;
import org.teiid.designer.ui.common.util.WidgetUtil;
import org.teiid.designer.ui.common.viewsupport.StatusInfo;
import org.teiid.designer.ui.common.widget.accumulator.AccumulatorPanel;
import org.teiid.designer.ui.common.widget.accumulator.IAccumulatedValuesChangeListener;
import org.teiid.designer.ui.common.widget.accumulator.IAccumulatorSource;
import org.teiid.designer.ui.viewsupport.ModelNameUtil;
import org.teiid.designer.ui.viewsupport.ModelProjectSelectionStatusValidator;
import org.teiid.designer.ui.viewsupport.ModelUtilities;
import org.teiid.designer.ui.viewsupport.ModelingResourceFilter;
import org.teiid.designer.xsd.ui.ModelerXsdUiConstants;
/**
* @since 8.0
*/
public class GlobalEntitiesPage extends WizardPage implements InternalUiConstants.Widgets, IAccumulatedValuesChangeListener {
private static final String TITLE = ModelerXsdUiConstants.Util.getString("ComplexSchemaTypesPage.title"); //$NON-NLS-1$
private static final String DESCRIPTION = ModelerXsdUiConstants.Util.getString("ComplexSchemaTypesPage.description"); //$NON-NLS-1$
private static final int STATUS_OK = 0;
private static final int STATUS_NO_LOCATION = 1;
private static final int STATUS_NO_FILENAME = 2;
//private static final int STATUS_FILE_EXISTS = 3;
private static final int STATUS_BAD_FILENAME = 4;
private static final int STATUS_CLOSED_PROJECT = 5;
private static final int STATUS_NO_PROJECT_NATURE = 6;
private final String leftHeader = ModelerXsdUiConstants.Util.getString("ComplexSchemaTypesPage.leftHeader"); //$NON-NLS-1$
private final String rightHeader = ModelerXsdUiConstants.Util.getString("ComplexSchemaTypesPage.rightHeader"); //$NON-NLS-1$
private final Collection globalElements = new HashSet();
private final Collection globalTypes = new HashSet();
private final ILabelProvider accumulatorLabelProvider = ModelUtilities.getEMFLabelProvider();
Text containerText;
Resource xsdRsrc;
Text fileText;
protected int currentStatus = STATUS_OK;
private String fileNameMessage = null;
private String fileExtension = ".xmi"; //$NON-NLS-1$
private TableViewer typeViewer;
private AccumulatorPanel panel;
private Collection typesToCreate;
private IProject project;
/**
* Constructor for NewModelWizardSpecifyModelPage
*
* @param rsrc The current ISelection selection
*/
public GlobalEntitiesPage( Resource rsrc ) {
super("complexTypesPage"); //$NON-NLS-1$
setTitle(TITLE);
setDescription(DESCRIPTION);
initialize(rsrc);
}
/**
* @see IDialogPage#createControl(Composite)
*/
@Override
public void createControl( Composite parent ) {
Composite container = new Composite(parent, SWT.NULL);
GridLayout layout = new GridLayout();
container.setLayout(layout);
// -----------------
Composite topComposite = new Composite(container, SWT.NULL);
GridData topCompositeGridData = new GridData(GridData.FILL_HORIZONTAL);
topComposite.setLayoutData(topCompositeGridData);
GridLayout topLayout = new GridLayout();
topLayout.numColumns = 3;
topComposite.setLayout(topLayout);
GridData gd = null;
Label locationLabel = new Label(topComposite, SWT.NULL);
locationLabel.setText(UiConstants.Util.getString("NewModelWizard.location")); //$NON-NLS-1$
containerText = new Text(topComposite, SWT.BORDER | SWT.SINGLE);
gd = new GridData(GridData.FILL_HORIZONTAL);
containerText.setLayoutData(gd);
containerText.addModifyListener(new ModifyListener() {
@Override
public void modifyText( ModifyEvent e ) {
checkStatus();
}
});
containerText.setEditable(false);
Button browseButton = new Button(topComposite, SWT.PUSH);
GridData buttonGridData = new GridData();
// buttonGridData.horizontalAlignment = GridData.HORIZONTAL_ALIGN_END;
browseButton.setLayoutData(buttonGridData);
browseButton.setText(UiConstants.Util.getString("NewModelWizard.browse")); //$NON-NLS-1$
browseButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected( SelectionEvent e ) {
handleBrowse();
}
});
Label fileLabel = new Label(topComposite, SWT.NULL);
fileLabel.setText(UiConstants.Util.getString("NewModelWizard.fileName")); //$NON-NLS-1$
fileText = new Text(topComposite, SWT.BORDER | SWT.SINGLE);
gd = new GridData(GridData.FILL_HORIZONTAL);
fileText.setLayoutData(gd);
fileText.addModifyListener(new ModifyListener() {
@Override
public void modifyText( ModifyEvent e ) {
checkStatus();
}
});
// -----------------
Composite bottomComposite = new Composite(container, SWT.NULL);
GridData bottomCompositeGridData = new GridData(GridData.FILL_BOTH);
bottomComposite.setLayoutData(bottomCompositeGridData);
GridLayout bottomLayout = new GridLayout();
bottomLayout.numColumns = 2;
bottomComposite.setLayout(bottomLayout);
final GlobalEntitiesAccumulatorSource source = new GlobalEntitiesAccumulatorSource(this, bottomComposite);
panel = new AccumulatorPanel(bottomComposite, source, new ArrayList(), accumulatorLabelProvider, leftHeader, rightHeader);
panel.addAccumulatedValuesChangeListener(this);
setControl(container);
typeViewer.add(globalElements.toArray());
typeViewer.add(globalTypes.toArray());
setDefaults();
checkStatus();
}
@Override
public void accumulatedValuesChanged( AccumulatorPanel source ) {
typesToCreate = source.getItemsMovedToSelected();
checkStatus();
}
/**
* @return Collection of types
*/
public Collection getTypesToConvert() {
if (this.typesToCreate == null) {
return Collections.EMPTY_LIST;
}
return typesToCreate;
}
/**
* Tests if the current workbench selection is a suitable container to use. All selections must be Relational (Virtual or
* Physical). All Tables and Procedure Results within the selection are added to the Collection of root objects to use for
* building.
*/
private void initialize( Resource rsrc ) {
if (rsrc != null) {
addComplexTypes(rsrc);
this.xsdRsrc = rsrc;
}
}
private void setDefaults() {
this.getControl().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
if (xsdRsrc == null) {
return;
}
final ModelResource xsdMR = ModelerCore.getModelEditor().findModelResource(xsdRsrc);
if (xsdMR != null) {
IContainer parentContainer = (IContainer)xsdMR.getParent().getResource();
if (parentContainer != null && parentContainer.getProject() != null) {
project = parentContainer.getProject();
containerText.setText(project.getName() + File.separator
+ parentContainer.getProjectRelativePath().toString());
}
fileText.setText(xsdMR.getPath().removeFileExtension().lastSegment());
}
}
});
}
private void addComplexTypes( final Resource xsdRsrc ) {
final Iterator eObjects = xsdRsrc.getContents().iterator();
while (eObjects.hasNext()) {
final Object next = eObjects.next();
if (next instanceof XSDSchema) {
final XSDSchema schema = (XSDSchema)next;
final Iterator children = schema.eContents().iterator();
while (children.hasNext()) {
final Object child = children.next();
if (child instanceof XSDComplexTypeDefinition) {
globalTypes.add(child);
} else if (child instanceof XSDElementDeclaration) {
globalElements.add(child);
}
}
}
}
}
/**
* If genOut is selected the user must supply a model name. If genInput is selected the user must supply a model name. User
* must select at least one of genOut or genInput
*/
void checkStatus() {
String container = getContainerName();
if (CoreStringUtil.isEmpty(container)) {
setMessage("No Model Location Selected", IMessageProvider.ERROR); //$NON-NLS-1$
currentStatus = STATUS_NO_LOCATION;
setPageComplete(false);
return;
}
IProject project = getTargetProject();
if (project == null) {
currentStatus = STATUS_NO_LOCATION;
return;
} else if (!project.isOpen()) {
currentStatus = STATUS_CLOSED_PROJECT;
return;
} else {
try {
if (project.getNature(PluginConstants.MODEL_PROJECT_NATURE_ID) == null) {
currentStatus = STATUS_NO_PROJECT_NATURE;
return;
}
} catch (CoreException ex) {
currentStatus = STATUS_NO_PROJECT_NATURE;
return;
}
}
String fileText = getFileText();
if (fileText.length() == 0) {
currentStatus = STATUS_NO_FILENAME;
setMessage("No File Name Provided", IMessageProvider.ERROR); //$NON-NLS-1$
return;
}
IStatus status = ModelNameUtil.validate(fileText, fileExtension, project,
ModelNameUtil.IGNORE_CASE | ModelNameUtil.NO_DUPLICATE_MODEL_NAMES | ModelNameUtil.NO_EXISTING_MODEL_AT_LOCATION );
if( status.getSeverity() == IStatus.ERROR ) {
fileNameMessage = ModelNameUtil.MESSAGES.INVALID_MODEL_NAME + status.getMessage();
currentStatus = STATUS_BAD_FILENAME;
setMessage(fileNameMessage, IMessageProvider.ERROR);
return;
}
if (globalElements.isEmpty() && globalTypes.isEmpty()) {
setMessage(ModelerXsdUiConstants.Util.getString("ComplexSchemaTypesPage.none"), IMessageProvider.ERROR); //$NON-NLS-1$
setPageComplete(false);
return;
} else if (typesToCreate == null || typesToCreate.isEmpty()) {
setMessage(ModelerXsdUiConstants.Util.getString("ComplexSchemaTypesPage.noneSelected"), IMessageProvider.ERROR); //$NON-NLS-1$
setPageComplete(false);
return;
}
setMessage(ModelerXsdUiConstants.Util.getString("ComplexSchemaTypesPage.done"), IMessageProvider.NONE); //$NON-NLS-1$
setPageComplete(true);
}
void typesToConvertChanged() {
}
void typesToConvertRemoved( final Collection values ) {
Iterator it = values.iterator();
while (it.hasNext()) {
Object value = it.next();
typeViewer.add(value);
}
}
void typesToConvertAdded( final Collection values ) {
Iterator it = values.iterator();
while (it.hasNext()) {
Object value = it.next();
typeViewer.remove(value);
}
}
Collection getAvailableTypes() {
final int count = typeViewer.getTable().getItemCount();
final ArrayList values = new ArrayList(count);
for (int i = 0; i < count; i++) {
Object value = typeViewer.getElementAt(i);
values.add(value);
}
return values;
}
int getAvailableTypesCount() {
return typeViewer.getTable().getItemCount();
}
Collection getSelectedAvailableTypes() {
final int[] selectionIndices = typeViewer.getTable().getSelectionIndices();
final ArrayList selectedValues = new ArrayList(selectionIndices.length);
for (int i = 0; i < selectionIndices.length; i++) {
final int index = selectionIndices[i];
selectedValues.add(typeViewer.getElementAt(index));
}
return selectedValues;
}
int getSelectedAvailableTypeCount() {
if (typeViewer != null) {
return typeViewer.getTable().getSelectionCount();
} // endif
return 0;
}
Control createTypeControl( final Composite parent ) {
typeViewer = new TableViewer(parent, SWT.MULTI);
typeViewer.setLabelProvider(accumulatorLabelProvider);
return typeViewer.getControl();
}
void addTypeSelectionListener( final SelectionListener listener ) {
typeViewer.getTable().addSelectionListener(listener);
}
/**
* Uses the standard container selection dialog to choose the new value for the container field.
*/
void handleBrowse() {
final IContainer folder = WidgetUtil.showFolderSelectionDialog((IContainer)getTargetContainer(),
new ModelingResourceFilter(),
new ModelProjectSelectionStatusValidator());
if (folder != null && containerText != null) {
containerText.setText(folder.getFullPath().makeRelative().toString());
}
checkStatus();
}
/**
* @return the target project
*/
public IProject getTargetProject() {
IProject result = null;
String containerName = getContainerName();
if (!CoreStringUtil.isEmpty(containerName)) {
IWorkspaceRoot root = ModelerCore.getWorkspace().getRoot();
IResource resource = root.findMember(new Path(containerName));
if (resource.exists()) {
result = resource.getProject();
}
}
return result;
}
/**
* @return the target container
*/
public IResource getTargetContainer() {
IResource result = null;
String containerName = getContainerName();
if (!CoreStringUtil.isEmpty(containerName)) {
IWorkspaceRoot root = ModelerCore.getWorkspace().getRoot();
IResource resource = root.findMember(new Path(containerName));
if (resource.exists()) {
result = resource;
}
}
return result;
}
/**
* @return the container name
*/
public String getContainerName() {
String result = null;
result = containerText.getText().trim();
return result;
}
/**
* @return the file name
*/
public String getFileName() {
String result = fileText.getText().trim();
if (!result.endsWith(fileExtension)) {
result += fileExtension;
}
return result;
}
/**
* @return the file text
*/
public String getFileText() {
return fileText.getText().trim();
}
/**
* @return the file path
*/
public IPath getFilePath() {
return getTargetProject().getFullPath().append(getFileText() + ModelerCore.MODEL_FILE_EXTENSION);
}
class GlobalEntitiesAccumulatorSource implements IAccumulatorSource {
private final IStatus OK_STATUS = new StatusInfo(ModelerXsdUiConstants.PLUGIN_ID);
private final GlobalEntitiesPage caller;
TableViewer viewer;
public GlobalEntitiesAccumulatorSource( GlobalEntitiesPage cllr,
Composite parent ) {
super();
this.caller = cllr;
}
@Override
public void accumulatedValuesRemoved( Collection values ) {
caller.typesToConvertRemoved(values);
caller.typesToConvertChanged();
}
@Override
public void accumulatedValuesAdded( Collection values ) {
caller.typesToConvertAdded(values);
caller.typesToConvertChanged();
}
@Override
public Collection getAvailableValues() {
return caller.getAvailableTypes();
}
@Override
public int getAvailableValuesCount() {
return caller.getAvailableTypesCount();
}
@Override
public Collection getSelectedAvailableValues() {
return caller.getSelectedAvailableTypes();
}
@Override
public int getSelectedAvailableValuesCount() {
return caller.getSelectedAvailableTypeCount();
}
@Override
public Control createControl( Composite parent ) {
return caller.createTypeControl(parent);
}
@Override
public void addSelectionListener( SelectionListener listener ) {
caller.addTypeSelectionListener(listener);
}
/**
* @see org.teiid.designer.ui.common.widget.accumulator.IAccumulatorSource#supportsAddAll()
*/
@Override
public boolean supportsAddAll() {
return true;
}
/**
* @see org.teiid.designer.ui.common.widget.accumulator.IAccumulatorSource#getSelectionStatus()
*/
@Override
public IStatus getSelectionStatus() {
return OK_STATUS;
}
}
}