Java tutorial
/******************************************************************************* * Copyright (c) 2007-2011 Exadel, Inc. and Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is 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: * Exadel, Inc. and Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.jst.jsp.i18n; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Properties; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.ICellModifier; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.TableLayout; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TextCellEditor; import org.eclipse.jface.viewers.Viewer; 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.VerifyEvent; import org.eclipse.swt.events.VerifyListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IFileEditorInput; import org.eclipse.wst.validation.ValidationFramework; import org.jboss.tools.common.model.ui.ModelUIImages; import org.jboss.tools.jst.jsp.JspEditorPlugin; import org.jboss.tools.jst.jsp.messages.JstUIMessages; import org.jboss.tools.jst.jsp.util.Constants; public class ExternalizeAllStringsKeysListPage extends WizardPage { private static final String KEY_PROPERTY = "key"; //$NON-NLS-1$ private static final String VALUE_PROPERTY = "value"; //$NON-NLS-1$ Color red; Color white; private List<KeyValueElement> initKeys; private IDocument doc; Properties properties; TableViewer tv; protected ExternalizeAllStringsKeysListPage(String pageName) { super(pageName, JstUIMessages.EXTERNALIZE_STRINGS_DIALOG_TITLE, ModelUIImages.getImageDescriptor(ModelUIImages.WIZARD_DEFAULT)); setDescription(JstUIMessages.EXTERNALIZE_STRINGS_DIALOG_DESCRIPTION); setPageComplete(false); } @Override public void createControl(Composite parent) { red = parent.getDisplay().getSystemColor(SWT.COLOR_RED); white = parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND); initKeys = getAllNonExternalizedStrings(); Collections.sort(initKeys); tv = createTable(parent); highlightAllDuplicateKeys(tv); setControl(tv.getTable()); } private List<KeyValueElement> getAllNonExternalizedStrings() { List<KeyValueElement> keys = new ArrayList<KeyValueElement>(); if (getWizard() instanceof ExternalizeAllStringsWizard) { ExternalizeAllStringsWizard wiz = (ExternalizeAllStringsWizard) getWizard(); IEditorInput in = wiz.getEditor().getEditorInput(); if (in instanceof IFileEditorInput) { IFileEditorInput fin = (IFileEditorInput) in; IFile file = fin.getFile(); try { ValidationFramework.getDefault().validate(file, new NullProgressMonitor()); IMarker[] markers = fin.getFile().findMarkers(JspEditorPlugin.I18N_VALIDATION_PROBLEM_ID, true, IResource.DEPTH_ZERO); doc = wiz.getEditor().getDocumentProvider().getDocument(in); /* * Iterate over all the markers */ String text = null; for (IMarker m : markers) { Integer offset = (Integer) m.getAttribute("PROBLEM_OFFSET"); //$NON-NLS-1$ Integer length = (Integer) m.getAttribute("PROBLEM_LENGHT"); //$NON-NLS-1$ try { text = doc.get(offset.intValue(), length.intValue()); keys.add(new KeyValueElement(ExternalizeStringsUtils.generatePropertyKey(text), text, offset.intValue(), length.intValue(), false)); } catch (BadLocationException e) { e.printStackTrace(); } } } catch (CoreException e) { JspEditorPlugin.getDefault().logError(e); } } } markAllDuplicatedKeys(keys); return keys; } private void markAllDuplicatedKeys(List<KeyValueElement> keys) { /* * Check for duplicated keys and mark corresponding elements */ if (properties != null) { for (KeyValueElement k : keys) { if (isDuplicatedBundleKey(k.key)) { k.duplicated = true; } } } } private void markAllDuplicatedKeys(TableViewer tv) { for (int i = 0; i < tv.getTable().getItemCount(); i++) { KeyValueElement k = (KeyValueElement) tv.getElementAt(i); if (isDuplicatedBundleKey(k.key)) { k.duplicated = true; } } } private boolean isDuplicatedBundleKey(String key) { boolean duplicated = false; if (properties != null) { for (Iterator it = properties.keySet().iterator(); it.hasNext();) { String original = (String) it.next(); if (original.equalsIgnoreCase(key)) { duplicated = true; break; } } } return duplicated; } private boolean isDuplicatedStringKey(KeyValueElement element, String newKey) { boolean duplicated = false; for (KeyValueElement k : initKeys) { if (!k.equals(element) && k.key.equalsIgnoreCase(newKey)) { duplicated = true; } } return duplicated; } private void highlightAllDuplicateKeys(TableViewer tv) { for (int i = 0; i < tv.getTable().getItemCount(); i++) { highlightDuplicateKey(tv.getTable().getItem(i), ((KeyValueElement) tv.getElementAt(i)).duplicated); } } private void highlightDuplicateKey(TableItem ti, boolean duplicated) { if (duplicated) { ti.setBackground(0, red); } else { ti.setBackground(0, white); } } private TableViewer createTable(Composite parent) { Table table = new Table(parent, SWT.FULL_SELECTION | SWT.BORDER); TableViewer tv = layoutTableInViewer(table); attachContentProvider(tv); attachLabelProvider(tv); attachCellEditors(tv, table); addInitialKeysValues(tv); return tv; } private TableViewer layoutTableInViewer(Table table) { TableViewer tableViewer = new TableViewer(table); TableLayout layout = new TableLayout(); layout.addColumnData(new ColumnWeightData(200, 200, true)); layout.addColumnData(new ColumnWeightData(200, 200, true)); table.setLayout(layout); TableColumn nameColumn = new TableColumn(table, SWT.LEFT); nameColumn.setText(JstUIMessages.EXTERNALIZE_STRINGS_DIALOG_PROPERTY_NAME); TableColumn valColumn = new TableColumn(table, SWT.LEFT); valColumn.setText(JstUIMessages.EXTERNALIZE_STRINGS_DIALOG_PROPERTY_VALUE); table.setHeaderVisible(true); table.setLinesVisible(true); return tableViewer; } private void attachContentProvider(TableViewer tv) { tv.setContentProvider(new IStructuredContentProvider() { public Object[] getElements(Object inputElement) { return (Object[]) inputElement; } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } public void dispose() { } }); } private void attachLabelProvider(TableViewer tv) { tv.setLabelProvider(new ITableLabelProvider() { public Image getColumnImage(Object element, int columnIndex) { return null; } public String getColumnText(Object element, int columnIndex) { switch (columnIndex) { case 0: return ((KeyValueElement) element).key; case 1: return ((KeyValueElement) element).value; default: return "Invalid column: " + columnIndex; //$NON-NLS-1$ } } public void addListener(ILabelProviderListener listener) { } public void dispose() { } public boolean isLabelProperty(Object element, String property) { return false; } public void removeListener(ILabelProviderListener lpl) { } }); } private void attachCellEditors(final TableViewer viewer, Composite parent) { viewer.setCellModifier(new ICellModifier() { public boolean canModify(Object element, String property) { return true; } public Object getValue(Object element, String property) { if (KEY_PROPERTY.equals(property)) { return ((KeyValueElement) element).key; } else { return ((KeyValueElement) element).value; } } public void modify(Object element, String property, Object value) { TableItem tableItem = (TableItem) element; KeyValueElement kve = (KeyValueElement) tableItem.getData(); if (KEY_PROPERTY.equals(property)) { kve.key = value.toString(); } else { kve.value = value.toString(); } viewer.refresh(kve); /* * Mark/unmark all duplicated keys with red/white. * Change the dialog status. */ for (KeyValueElement k : initKeys) { if (isDuplicatedBundleKey(k.key) || isDuplicatedStringKey(k, k.key)) { k.duplicated = true; } else { k.duplicated = false; } } highlightAllDuplicateKeys(viewer); updateStatus(); } }); TextCellEditor keyEditor = new TextCellEditor(parent); /* * TODO: cell validator should be added after bug * https://bugs.eclipse.org/bugs/show_bug.cgi?id=130854 * is fixed. */ // keyEditor.setValidator(new ICellEditorValidator() { // @Override // public String isValid(Object value) { // return null; // } // }); ((Text) keyEditor.getControl()).addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { Text t = (Text) e.getSource(); String key = t.getText(); Table table = (Table) t.getParent(); int ind = table.getSelectionIndex(); KeyValueElement element = (KeyValueElement) viewer.getElementAt(ind); /* * Check duplicate key, set bkg color to red * Setting new key value is called after this modyfy listener, * thus pass new key value manually. */ if (isDuplicatedBundleKey(key) || isDuplicatedStringKey(element, key)) { element.duplicated = true; t.setBackground(red); } else { element.duplicated = false; t.setBackground(white); } } }); ((Text) keyEditor.getControl()).addVerifyListener(new VerifyListener() { public void verifyText(VerifyEvent e) { for (int i = 0; i < ExternalizeStringsUtils.REPLACED_CHARACTERS.length; i++) { /* * Entering of the forbidden characters will be prevented. */ if (e.character == ExternalizeStringsUtils.REPLACED_CHARACTERS[i]) { e.doit = false; break; } } } }); viewer.setCellEditors(new CellEditor[] { keyEditor, null }); viewer.setColumnProperties(new String[] { KEY_PROPERTY, VALUE_PROPERTY }); } private void addInitialKeysValues(TableViewer viewer) { for (KeyValueElement k : initKeys) { viewer.add(k); } } /** * Gets <code>key=value</code> pair * * @return a pair <code>key=value</code> */ public String getKeyValuePairsList() { StringBuffer sb = new StringBuffer(); for (KeyValueElement k : initKeys) { /* * Element with duplicated key will be excluded. */ if (!k.duplicated) { sb.append(k.key + Constants.EQUAL + k.value); sb.append('\n'); } } return sb.toString(); } /** * Replaces the text in the current file */ public void replaceAllStrings(String bundlePrefix) { if ((doc == null) && (getWizard() instanceof ExternalizeAllStringsWizard)) { doc = ((ExternalizeAllStringsWizard) getWizard()).getDocument(); } if (doc != null) { /* * Go from the end to the top of the file. */ Collections.sort(initKeys); for (int i = initKeys.size() - 1; i >= 0; i--) { KeyValueElement k = initKeys.get(i); try { /* * Element with duplicated key won't be replaced */ if (!k.duplicated) { doc.replace(k.offset, k.length, "#{" + bundlePrefix + Constants.DOT + k.key + "}"); //$NON-NLS-1$ //$NON-NLS-2$ } } catch (BadLocationException e) { JspEditorPlugin.getPluginLog().logError(e); } } } } public void updateTable(Properties p) { this.properties = p; boolean anyDuplicated = false; for (int i = 0; i < tv.getTable().getItemCount(); i++) { KeyValueElement k = (KeyValueElement) tv.getElementAt(i); TableItem ti = tv.getTable().getItem(i); if (isDuplicatedBundleKey(k.key) || isDuplicatedStringKey(k, k.key)) { k.duplicated = true; ti.setBackground(0, red); anyDuplicated = true; } else { k.duplicated = false; ti.setBackground(0, white); } } setDuplicateWarning(anyDuplicated); } private void setDuplicateWarning(boolean anyDuplicated) { if (anyDuplicated) { this.setMessage("Duplicated entries won't be externalized", IMessageProvider.WARNING); this.setErrorMessage(null); } else { this.setMessage(null); this.setErrorMessage(null); } } private void updateStatus() { boolean anyDuplicated = false; for (KeyValueElement k : initKeys) { if (k.duplicated) { anyDuplicated = true; break; } } setDuplicateWarning(anyDuplicated); } @Override public boolean isPageComplete() { /* * User always can complete the page * Duplicate entries simply will be ignored. */ return true; } class KeyValueElement implements Comparable<KeyValueElement> { public String key; public String value; public int offset; public int length; public boolean duplicated; public KeyValueElement(String k, String v, int o, int l, boolean d) { key = k; value = v; offset = o; length = l; duplicated = d; } @Override public int compareTo(KeyValueElement aThat) { final int BEFORE = -1; final int EQUAL = 0; final int AFTER = 1; if (this == aThat) return EQUAL; if (this.offset < aThat.offset) return BEFORE; if (this.offset > aThat.offset) return AFTER; assert this.equals(aThat) : "compareTo inconsistent with equals."; //$NON-NLS-1$ return EQUAL; } @Override public int hashCode() { int result = 47 + super.hashCode(); if (key != null) { result += key.hashCode(); } result = result * 7; if (value != null) { result += value.hashCode(); } result = result * 7; result += offset; result = result * 7; result += length; return result; } @Override public boolean equals(Object aThat) { if (this == aThat) return true; if (!(aThat instanceof KeyValueElement)) return false; KeyValueElement that = (KeyValueElement) aThat; return ((this.key == that.key) && (this.value == that.value) && (this.offset == that.offset) && (this.length == that.length)); } @Override public String toString() { return this.getClass() + "@" + this.hashCode() //$NON-NLS-1$ + " (key=" + this.key + ", value=" + this.value //$NON-NLS-1$ //$NON-NLS-2$ + ", offset=" + this.offset + ", length=" + this.length //$NON-NLS-1$ //$NON-NLS-2$ + ", duplicated=" + this.duplicated + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } } }