/******************************************************************************* * Copyright (c) 2006, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.wst.xsd.ui.internal.common.properties.sections.appinfo; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.StringTokenizer; import org.apache.xerces.dom.DocumentImpl; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; 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.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.SelectionDialog; import org.eclipse.wst.xsd.contentmodel.internal.XSDImpl; import org.eclipse.wst.xsd.ui.internal.common.util.Messages; import org.eclipse.wst.xsd.ui.internal.editor.XSDEditorCSHelpIds; import org.eclipse.wst.xsd.ui.internal.editor.XSDEditorPlugin; import org.eclipse.xsd.XSDAttributeDeclaration; import org.eclipse.xsd.XSDElementDeclaration; import org.eclipse.xsd.XSDSchema; import org.w3c.dom.Document; import org.w3c.dom.Element; public class AddExtensionsComponentDialog extends SelectionDialog implements ISelectionChangedListener, SelectionListener { protected static final Image DEFAULT_ELEMENT_ICON = XSDEditorPlugin.getXSDImage("icons/XSDElement.gif"); //$NON-NLS-1$ protected static final Image DEFAULT_ATTRIBUTE_ICON = XSDEditorPlugin.getXSDImage("icons/XSDAttribute.gif"); //$NON-NLS-1$ /** A temporary Document in which we create temporary DOM element for each element in the * Element view. (required by LabelProvider) */ protected static Document tempDoc = new DocumentImpl(); Button addButton, removeButton, editButton; public AddExtensionsComponentDialog(Shell parent, ExtensionsSchemasRegistry schemaRegistry) { super(parent); setTitle(Messages._UI_ACTION_ADD_EXTENSION_COMPONENTS); setShellStyle(SWT.APPLICATION_MODAL | SWT.RESIZE | SWT.CLOSE); } private List fInput; private TableViewer categoryTableViewer, elementTableViewer; private ArrayList existingNames; private ViewerFilter elementTableViewerFilter; private SpecificationForExtensionsSchema currentExtCategory; private HashMap specToComponentsList = new HashMap(); private IPreferenceStore prefStore; public void setInput(List input) { this.fInput = input; } public SpecificationForExtensionsSchema getSelectedCategory(){ return currentExtCategory; } public void setInitialCategorySelection(SpecificationForExtensionsSchema spec){ currentExtCategory = spec; } protected IStructuredContentProvider getCategoryContentProvider() { return new CategoryContentProvider(); } protected Control createDialogArea(Composite container) { Composite parent = (Composite) super.createDialogArea(container); Composite categoryComposite = new Composite(parent, SWT.NONE); GridLayout gl = new GridLayout(); gl.numColumns = 2; gl.marginHeight = 0; gl.marginWidth = 0; GridData data = new GridData(GridData.FILL_BOTH); categoryComposite.setLayoutData(data); categoryComposite.setLayout(gl); Label label = new Label(categoryComposite, SWT.LEFT); label.setText(Messages._UI_LABEL_EXTENSION_CATEGORIES); new Label(categoryComposite, SWT.NONE); categoryTableViewer = new TableViewer(categoryComposite, getTableStyle()); categoryTableViewer.setContentProvider(getCategoryContentProvider()); categoryTableViewer.setLabelProvider(new CategoryLabelProvider()); categoryTableViewer.setInput(fInput); categoryTableViewer.addSelectionChangedListener(this); PlatformUI.getWorkbench().getHelpSystem().setHelp(categoryTableViewer.getControl(), XSDEditorCSHelpIds.ADD_EXTENSIONS_COMPONENTS__EXTENSION_CATEGORIES); GridData gd = new GridData(GridData.FILL_BOTH); Table table = categoryTableViewer.getTable(); table.setLayoutData(gd); table.setFont(container.getFont()); Composite buttonComposite = new Composite(categoryComposite, SWT.NONE); gl = new GridLayout(); gl.makeColumnsEqualWidth = true; gl.numColumns = 1; data = new GridData(); data.horizontalAlignment = SWT.FILL; buttonComposite.setLayoutData(data); buttonComposite.setLayout(gl); addButton = new Button(buttonComposite, SWT.PUSH); addButton.setText(Messages._UI_LABEL_ADD_WITH_DOTS); addButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); addButton.addSelectionListener(this); PlatformUI.getWorkbench().getHelpSystem().setHelp(addButton, XSDEditorCSHelpIds.ADD_EXTENSIONS_COMPONENTS__ADD); removeButton = new Button(buttonComposite, SWT.PUSH); removeButton.setText(Messages._UI_LABEL_DELETE); removeButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); removeButton.addSelectionListener(this); PlatformUI.getWorkbench().getHelpSystem().setHelp(removeButton, XSDEditorCSHelpIds.ADD_EXTENSIONS_COMPONENTS__DELETE); editButton = new Button(buttonComposite, SWT.PUSH); editButton.setText(Messages._UI_LABEL_EDIT); editButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); editButton.addSelectionListener(this); PlatformUI.getWorkbench().getHelpSystem().setHelp(editButton, XSDEditorCSHelpIds.ADD_EXTENSIONS_COMPONENTS__EDIT); List initialSelection = getInitialElementSelections(); if (initialSelection != null) categoryTableViewer.setSelection(new StructuredSelection(initialSelection)); Label elementLabel = new Label(categoryComposite, SWT.LEFT); elementLabel.setText(Messages._UI_LABEL_AVAILABLE_COMPONENTS_TO_ADD); new Label(categoryComposite, SWT.NONE); elementTableViewer = new TableViewer(categoryComposite, getTableStyle()); elementTableViewer.setContentProvider(new ElementContentProvider()); elementTableViewer.setLabelProvider(new ElementLabelProvider()); elementTableViewer.setInput(null); elementTableViewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { okPressed(); } }); if ( elementTableViewerFilter != null){ elementTableViewer.addFilter(elementTableViewerFilter); } gd = new GridData(GridData.FILL_BOTH); table = elementTableViewer.getTable(); table.setLayoutData(gd); table.setFont(container.getFont()); elementTableViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { getButton(IDialogConstants.OK_ID).setEnabled(true); } }); PlatformUI.getWorkbench().getHelpSystem().setHelp(elementTableViewer.getControl(), XSDEditorCSHelpIds.ADD_EXTENSIONS_COMPONENTS__AVAILABLE_COMPONENTS_TO_ADD); return parent; } public void create() { super.create(); if (categoryTableViewer.getTable().getItemCount() > 0) { categoryTableViewer.getTable().select(0); StructuredSelection structuredSelection; if (currentExtCategory != null){ structuredSelection = new StructuredSelection(currentExtCategory); } else{ structuredSelection = new StructuredSelection(categoryTableViewer.getElementAt(0)); } categoryTableViewer.setSelection(structuredSelection); } // Setup the list of category names that already exist // and contructs the XSDSchema for each category existingNames = new ArrayList(); TableItem[] categories = categoryTableViewer.getTable().getItems(); for (int i = 0; i < categories.length; i++ ){ existingNames.add(categories[i].getText()); SpecificationForExtensionsSchema spec = (SpecificationForExtensionsSchema) categories[i].getData(); XSDSchema schema = getASISchemaModel(spec); if (schema == null) { continue; } List components = buildInput(schema); specToComponentsList.put(spec, components); // mark category as gray/empty if applicable Object[] remains = components.toArray(); if ( elementTableViewerFilter != null) remains = elementTableViewerFilter.filter(elementTableViewer, elementTableViewer.getTable(), remains); if ( remains.length == 0) { categories[i].setForeground( getShell().getDisplay().getSystemColor(SWT.COLOR_GRAY)); } } getButton(IDialogConstants.OK_ID).setEnabled(false); } public void addElementsTableFilter(ViewerFilter filter){ elementTableViewerFilter = filter; } public void setPrefStore(IPreferenceStore prefStore) { this.prefStore = prefStore; } protected Point getInitialSize() { return getShell().computeSize(400, 300); } /** * Return the style flags for the table viewer. * * @return int */ protected int getTableStyle() { return SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER; } /* * Overrides method from Dialog */ protected void okPressed() { // Build a list of selected children. getShell().setCursor(new Cursor(getShell().getDisplay(), SWT.CURSOR_WAIT)); IStructuredSelection elementSelection = (IStructuredSelection) elementTableViewer.getSelection(); IStructuredSelection categorySelection = (IStructuredSelection) categoryTableViewer.getSelection(); List result = new ArrayList(); result.add(elementSelection.getFirstElement()); result.add(categorySelection.getFirstElement()); if (elementSelection.getFirstElement() != null) { setResult(result); } else { setResult(null); } super.okPressed(); } /* * (non-Javadoc) * * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ public void widgetSelected(SelectionEvent e) { if (e.widget == addButton) { AddNewCategoryDialog addNewCategoryDialog = new AddNewCategoryDialog(getShell()); addNewCategoryDialog.setUnavailableCategoryNames(existingNames); if ( addNewCategoryDialog.open() == Window.OK ){ SpecificationForExtensionsSchema schemaSpec = new SpecificationForExtensionsSchema(); schemaSpec.setDisplayName(addNewCategoryDialog.getNewCategoryName() ); schemaSpec.setLocation(addNewCategoryDialog.getCategoryLocation() ); schemaSpec.setSourceHint(addNewCategoryDialog.getSource()); schemaSpec.setFromCatalog(addNewCategoryDialog.getFromCatalog() ); fInput.add(schemaSpec); existingNames.add(schemaSpec.getDisplayName()); // refresh without updating labels of existing TableItems categoryTableViewer.refresh(false); categoryTableViewer.setSelection(new StructuredSelection(schemaSpec)); getButton(IDialogConstants.OK_ID).setEnabled(false); storeSpecInPref(schemaSpec); // must store after selection changed is called ie. 2 lines above (trung) } } else if (e.widget == removeButton) { TableItem[] selections = categoryTableViewer.getTable().getSelection(); for (int i =0; i < selections.length; i++){ SpecificationForExtensionsSchema spec = (SpecificationForExtensionsSchema) selections[i].getData(); fInput.remove(spec ); existingNames.remove(spec.getDisplayName()); specToComponentsList.remove(spec); removeFromPref(spec); } categoryTableViewer.refresh(false); elementTableViewer.setInput(null); elementTableViewer.refresh(); // TODO auto select either the prev category, the next category or the first category in the Table getButton(IDialogConstants.OK_ID).setEnabled(false); } else if (e.widget == editButton) { // use this dialog not for adding but for editing purpose. AddNewCategoryDialog dialog = new AddNewCategoryDialog(getShell(), Messages._UI_LABEL_EDIT_CATEGORY); TableItem[] selections = categoryTableViewer.getTable().getSelection(); if (selections.length == 0) return; SpecificationForExtensionsSchema spec = (SpecificationForExtensionsSchema) selections[0].getData(); String displayName = spec.getDisplayName(); dialog.setCategoryName(displayName ); dialog.setFromCatalog(spec.isFromCatalog() ); dialog.setSource(spec.getSourceHint() ); dialog.setCategoryLocation(spec.getLocation() ); specToComponentsList.remove(spec); dialog.setUnavailableCategoryNames(existingNames); if ( dialog.open() == Window.OK){ existingNames.remove(displayName); String newDisplayName = dialog.getNewCategoryName(); spec.setDisplayName(newDisplayName); spec.setLocation(dialog.getCategoryLocation()); spec.setSourceHint(dialog.getSource()); spec.setFromCatalog(dialog.getFromCatalog()); spec.setNamespaceURI(null); existingNames.add(newDisplayName); categoryTableViewer.update(spec, null); refreshElementsViewer(spec); editSpecInPref(displayName, spec); } } } /* * (non-Javadoc) * * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent) */ public void widgetDefaultSelected(SelectionEvent event) { } public void selectionChanged(SelectionChangedEvent event) { if (event.getSource() == categoryTableViewer) { ISelection selection = event.getSelection(); if (selection instanceof StructuredSelection) { Object obj = ((StructuredSelection) selection).getFirstElement(); if (obj instanceof SpecificationForExtensionsSchema) { SpecificationForExtensionsSchema spec = (SpecificationForExtensionsSchema) obj; currentExtCategory = spec; refreshElementsViewer(spec); if ( spec.isDefautSchema() ){ editButton.setEnabled(false); removeButton.setEnabled(false); } else{ editButton.setEnabled(true); removeButton.setEnabled(true); } getButton(IDialogConstants.OK_ID).setEnabled(false); } } } } private void refreshElementsViewer(SpecificationForExtensionsSchema spec) { List components = (List) specToComponentsList.get(spec); if ( components != null){ elementTableViewer.setInput(components); return; } XSDSchema xsdSchema = getASISchemaModel(spec); if (xsdSchema == null){ MessageBox errDialog = new MessageBox(getShell(), SWT.ICON_ERROR); errDialog.setText(Messages._UI_ERROR_INVALID_CATEGORY); // TODO (trung) I was forced to use a String in Messages to make the error clearer // When we are back to development phase, use another string: "Extension Category: " // not "Extension Categories:" + " " like we are using here errDialog.setMessage(Messages._UI_LABEL_EXTENSION_CATEGORIES + " " + spec.getDisplayName() //$NON-NLS-1$ + "\n" //$NON-NLS-1$ + Messages._UI_ERROR_FILE_CANNOT_BE_PARSED + "\n" + Messages._UI_ERROR_VALIDATE_THE_FILE); //$NON-NLS-1$ errDialog.open(); elementTableViewer.setInput(new ArrayList(0)); return; } components = buildInput(xsdSchema); specToComponentsList.put(spec, components); List allItems = buildInput(xsdSchema); if ( allItems == null ) return; elementTableViewer.setInput(allItems); } private static List buildInput(XSDSchema xsdSchema) { if ( xsdSchema ==null ) return null; List elements = xsdSchema.getElementDeclarations(); List attributes = xsdSchema.getAttributeDeclarations(); String targetNamespace = xsdSchema.getTargetNamespace(); // For safety purpose: We don't append 'attributes' to 'elements' // ArrayStoreException(or similar one) may occur List allItems = new ArrayList(attributes.size() + elements.size()); { // getElementDeclarations returns a lot of elements from import // statement, we // only add non-imported elements here. (trung) for (int i = 0; i < elements.size(); i++) { XSDElementDeclaration currentElement = (XSDElementDeclaration) elements.get(i); if (currentElement.getTargetNamespace() != null) { if (currentElement.getTargetNamespace().equals(targetNamespace)) allItems.add(currentElement); } else { if (targetNamespace == null) allItems.add(currentElement); } } // getAttributeDeclarations also returns a lot of elements from // import statement, we // only add non-imported elements here. (trung) for (int i = 0; i < attributes.size(); i++) { XSDAttributeDeclaration currentAttribute = (XSDAttributeDeclaration) attributes.get(i); if (currentAttribute.getTargetNamespace() != null) { if (currentAttribute.isGlobal() && currentAttribute.getTargetNamespace().equals(targetNamespace)) allItems.add(currentAttribute); } else { if (targetNamespace == null) allItems.add(currentAttribute); } } } return allItems; } private static XSDSchema getASISchemaModel(SpecificationForExtensionsSchema extensionsSchemaSpec) { String location = extensionsSchemaSpec.getLocation(); if ( location == null) return null; XSDSchema xsdSchema = XSDImpl.buildXSDModel(location); // now that the .xsd file is read, we can retrieve the namespace of this xsd file // and set the namespace for 'properties' if ( extensionsSchemaSpec.getNamespaceURI() == null){ extensionsSchemaSpec.setNamespaceURI( xsdSchema.getTargetNamespace()); } return xsdSchema; } private void storeSpecInPref(SpecificationForExtensionsSchema schemaSpec) { if (prefStore == null) return; String currentValue = prefStore.getString(ExtensionsSchemasRegistry.USER_ADDED_EXT_SCHEMAS); String specDesc = " " + "\t" + schemaSpec.getDisplayName() + "\t"+ schemaSpec.getNamespaceURI() + "\t" + schemaSpec.getLocation() + "\t" + schemaSpec.isDefautSchema() + "\t" + schemaSpec.getSourceHint() + "\t" + schemaSpec.isFromCatalog(); currentValue += specDesc + "\n"; prefStore.setValue(ExtensionsSchemasRegistry.USER_ADDED_EXT_SCHEMAS, currentValue); } private void editSpecInPref(String displayName, SpecificationForExtensionsSchema newSpec) { if (prefStore == null) return; String newValue = ""; String currentValue = prefStore.getString(ExtensionsSchemasRegistry.USER_ADDED_EXT_SCHEMAS); StringTokenizer tokenizer = new StringTokenizer(currentValue, "\n"); while (tokenizer.hasMoreTokens()) { String oneSpecDesc = tokenizer.nextToken(); // get the Display name StringTokenizer _tokenizer_2 = new StringTokenizer(oneSpecDesc, "\t"); _tokenizer_2.nextToken(); String dName = _tokenizer_2.nextToken(); if ( dName.equals(displayName ) ) { oneSpecDesc = " " + "\t" + newSpec.getDisplayName() + "\t"+ newSpec.getNamespaceURI() + "\t" + newSpec.getLocation() + "\t" + newSpec.isDefautSchema() + "\t" + newSpec.getSourceHint() + "\t" + newSpec.isFromCatalog(); } newValue += oneSpecDesc + "\n"; } prefStore.setValue(ExtensionsSchemasRegistry.USER_ADDED_EXT_SCHEMAS, newValue); } private void removeFromPref(SpecificationForExtensionsSchema spec) { if (prefStore == null) return; String newValue = ""; String currentValue = prefStore.getString(ExtensionsSchemasRegistry.USER_ADDED_EXT_SCHEMAS); StringTokenizer tokenizer = new StringTokenizer(currentValue, "\n"); while (tokenizer.hasMoreTokens()) { String oneSpecDesc = tokenizer.nextToken(); // get the Display name StringTokenizer _tokenizer_2 = new StringTokenizer(oneSpecDesc, "\t"); _tokenizer_2.nextToken(); String dName = _tokenizer_2.nextToken(); if ( dName.equals(spec.getDisplayName() ) ) continue; newValue += oneSpecDesc + "\n"; } prefStore.setValue(ExtensionsSchemasRegistry.USER_ADDED_EXT_SCHEMAS, newValue); } static class CategoryContentProvider implements IStructuredContentProvider { /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) */ public Object[] getElements(Object inputElement) { SpecificationForExtensionsSchema[] extensionsSchemaSpecs = null; try { List inputList = (List) inputElement; extensionsSchemaSpecs = (SpecificationForExtensionsSchema[]) inputList.toArray(new SpecificationForExtensionsSchema[0]); } catch (Exception e) { } return extensionsSchemaSpecs; } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IContentProvider#dispose() */ public void dispose() { // Do nothing } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, * java.lang.Object, java.lang.Object) */ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // Do nothing } } static class CategoryLabelProvider extends LabelProvider { /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object) */ public Image getImage(Object element) { return XSDEditorPlugin.getXSDImage("icons/appinfo_category.gif"); //$NON-NLS-1$ } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object) */ public String getText(Object element) { if (element instanceof SpecificationForExtensionsSchema) return ((SpecificationForExtensionsSchema) element).getDisplayName(); return super.getText(element); } } static class ElementContentProvider implements IStructuredContentProvider { /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) */ public Object[] getElements(Object inputElement) { if (inputElement instanceof List) { return ((List) inputElement).toArray(); } return null; } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IContentProvider#dispose() */ public void dispose() { // Do nothing } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, * java.lang.Object, java.lang.Object) */ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // Do nothing } } class ElementLabelProvider extends LabelProvider { /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object) */ public Image getImage(Object element) { if ( element instanceof XSDElementDeclaration){ // Workaround trick: (trung) we create a temporary Dom element and put it in the label provider // to get the image. String namespace = ((XSDElementDeclaration) element).getSchema().getTargetNamespace(); String name = ((XSDElementDeclaration) element).getName(); Element tempElement = tempDoc.createElementNS(namespace, name); ILabelProvider lp = XSDEditorPlugin.getDefault().getNodeCustomizationRegistry().getLabelProvider(namespace); if (lp != null){ Image img = lp.getImage(tempElement); if (img != null){ return img; } } return DEFAULT_ELEMENT_ICON; } else if ( element instanceof XSDAttributeDeclaration){ return DEFAULT_ATTRIBUTE_ICON; } return null; } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object) */ public String getText(Object element) { if (element instanceof XSDElementDeclaration) return ((XSDElementDeclaration) element).getName(); if (element instanceof XSDAttributeDeclaration ) return ((XSDAttributeDeclaration) element).getName(); return super.getText(element); } } public boolean close() { return super.close(); } protected void enableButtons(boolean value) { editButton.setEnabled(value); addButton.setEnabled(value); removeButton.setEnabled(value); } }