/** * <copyright> * * Copyright (c) 2002, 2009 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 - Initial API and implementation * * </copyright> * * $Id: PropertyDescriptor.java,v 1.18 2008/12/22 14:26:18 emerks Exp $ */ package net.enilink.komma.edit.ui.provider; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IInputValidator; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.ICellEditorValidator; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TextCellEditor; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.views.properties.IPropertyDescriptor; import net.enilink.vocab.owl.AnnotationProperty; import net.enilink.vocab.owl.DatatypeProperty; import net.enilink.vocab.owl.OntologyProperty; import net.enilink.vocab.xmlschema.XMLSCHEMA; import net.enilink.komma.common.adapter.IAdapterFactory; import net.enilink.komma.common.ui.celleditor.ExtendedComboBoxCellEditor; import net.enilink.komma.common.ui.celleditor.ExtendedDialogCellEditor; import net.enilink.komma.common.util.Diagnostic; import net.enilink.komma.edit.provider.IItemLabelProvider; import net.enilink.komma.edit.provider.IItemPropertyDescriptor; import net.enilink.komma.edit.ui.KommaEditUIPlugin; import net.enilink.komma.edit.ui.celleditor.PropertyEditorDialog; import net.enilink.komma.edit.ui.dialogs.InputDialog; import net.enilink.komma.em.concepts.IProperty; import net.enilink.komma.em.util.KommaUtil; import net.enilink.komma.model.IObject; import net.enilink.komma.model.ModelPlugin; import net.enilink.komma.model.ModelUtil; import net.enilink.komma.core.IEntity; import net.enilink.komma.core.IReference; /** * This is used to encapsulate an {@link IItemPropertyDescriptor} along with the * object for which it is an item property source and make it behave like an * {@link org.eclipse.ui.views.properties.IPropertyDescriptor}. */ public class PropertyDescriptor implements IPropertyDescriptor { /** * This is the object for which this class is a property source. */ protected Object object; protected IAdapterFactory adapterFactory; /** * This is the descriptor to which we will delegate all the * {@link org.eclipse.ui.views.properties.IPropertyDescriptor} methods. */ protected IItemPropertyDescriptor itemPropertyDescriptor; /** * An instance is constructed from an object and its item property source. */ public PropertyDescriptor(Object object, IAdapterFactory adapterFactory, IItemPropertyDescriptor itemPropertyDescriptor) { this.object = object; this.adapterFactory = adapterFactory; this.itemPropertyDescriptor = itemPropertyDescriptor; } public String getCategory() { return itemPropertyDescriptor.getCategory(object); } public String getDescription() { return itemPropertyDescriptor.getDescription(object); } public String getDisplayName() { return itemPropertyDescriptor.getDisplayName(object); } public String[] getFilterFlags() { return itemPropertyDescriptor.getFilterFlags(object); } public Object getHelpContextIds() { return itemPropertyDescriptor.getHelpContextIds(object); } public Object getId() { return itemPropertyDescriptor.getId(object); } public ILabelProvider getLabelProvider() { final IItemLabelProvider itemLabelProvider = itemPropertyDescriptor .getLabelProvider(object); return new LabelProvider() { @Override public String getText(Object object) { return itemLabelProvider.getText(object); } @Override public Image getImage(Object object) { return ExtendedImageRegistry.getInstance().getImage( itemLabelProvider.getImage(object)); } }; } protected ILabelProvider getEditLabelProvider() { return getLabelProvider(); } public boolean isCompatibleWith(IPropertyDescriptor anotherProperty) { return false; } /** * A delegate for handling validation and conversion for data type values. */ protected class DatatypeValueHandler implements ICellEditorValidator, IInputValidator { protected Collection<? extends IReference> datatypes; public DatatypeValueHandler(Collection<? extends IReference> datatypes) { this.datatypes = datatypes; if (this.datatypes == null || this.datatypes.isEmpty()) { this.datatypes = Arrays.asList(XMLSCHEMA.TYPE_STRING); } } public String isValid(Object value) { StringBuilder messages = null; for (Iterator<? extends IReference> it = datatypes.iterator(); it .hasNext();) { IReference datatype = it.next(); Object convertedValue; try { convertedValue = toValue((String) value); } catch (Exception exception) { String message = exception.getClass().getName(); int index = message.lastIndexOf('.'); if (index >= 0) { message = message.substring(index + 1); } if (exception.getLocalizedMessage() != null) { message = message + ": " + exception.getLocalizedMessage(); } if (!it.hasNext()) { return message; } else { if (messages == null) { messages = new StringBuilder(message); } else { messages.append("\n").append(message); } } convertedValue = null; } if (convertedValue != null) { Diagnostic diagnostic = ModelPlugin.getDefault() .getDefaultValidator() .validate(datatype, convertedValue); if (diagnostic.getSeverity() == Diagnostic.OK) { return null; } else { return (diagnostic.getChildren().get(0)).getMessage() .replaceAll("'", "''").replaceAll("\\{", "'{'"); // }} } } } return messages != null ? messages.toString() : null; } public String isValid(String text) { return isValid((Object) text); } public Object toValue(String string) { return KommaUtil.convertToRange( ((IEntity) object).getEntityManager(), datatypes, string); } public String toString(Object value) { String result = ModelUtil.getLabel(value); return result == null ? "" : result; } } public class DatatypeCellEditor extends TextCellEditor { protected DatatypeValueHandler valueHandler; public DatatypeCellEditor(Collection<? extends IReference> datatypes, Composite parent) { super(parent); valueHandler = new DatatypeValueHandler(datatypes); setValidator(valueHandler); } @Override public Object doGetValue() { return valueHandler.toValue((String) super.doGetValue()); } @Override public void doSetValue(Object value) { value = valueHandler.toString(value); super.doSetValue(value); } // CellEditor.setValue() calls isCorrect() to validate the value that is // about to be set. We are doing conversion // between the value and a corresponding string, and we would usually // like to validate the string. Because // setValue() is final, we cannot do that conversion there, so we need // to record what we're trying to validate and // work around the problem in isCorrect(). // protected boolean validateAsValue = true; @Override protected void editOccured(ModifyEvent e) { validateAsValue = false; super.editOccured(e); validateAsValue = true; } @Override protected boolean isCorrect(Object value) { if (validateAsValue) { value = valueHandler.toString(value); } return super.isCorrect(value); } } private static class MultiLineInputDialog extends InputDialog { public MultiLineInputDialog(Shell parentShell, String title, String message, String initialValue, IInputValidator validator) { super(parentShell, title, message, initialValue, validator); setShellStyle(getShellStyle() | SWT.RESIZE); } @Override protected Text createText(Composite composite) { Text text = new Text(composite, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL); data.heightHint = 5 * text.getLineHeight(); data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.ENTRY_FIELD_WIDTH); text.setLayoutData(data); return text; } } protected CellEditor createDatatypeCellEditor( final Collection<? extends IReference> datatypes, Composite composite) { if (itemPropertyDescriptor.isMultiLine(object)) { return new ExtendedDialogCellEditor(composite, getEditLabelProvider()) { protected DatatypeValueHandler valueHandler = new DatatypeValueHandler( datatypes); @Override protected Object openDialogBox(Control cellEditorWindow) { InputDialog dialog = new MultiLineInputDialog( cellEditorWindow.getShell(), KommaEditUIPlugin.INSTANCE.getString( "_UI_FeatureEditorDialog_title", new Object[] { getDisplayName(), getEditLabelProvider().getText( object) }), KommaEditUIPlugin.INSTANCE .getString("_UI_MultiLineInputDialog_message"), valueHandler.toString(getValue()), valueHandler); return dialog.open() == Window.OK ? valueHandler .toValue(dialog.getValue()) : null; } }; } return new DatatypeCellEditor(datatypes, composite); } /** * This returns the cell editor that will be used to edit the value of this * property. This default implementation determines the type of cell editor * from the nature of the structural feature. */ public CellEditor createPropertyEditor(Composite composite) { if (!itemPropertyDescriptor.canSetProperty(object)) { return null; } CellEditor result = null; Object genericProperty = itemPropertyDescriptor.getProperty(object); if (genericProperty instanceof IReference[]) { result = new ExtendedComboBoxCellEditor(composite, new ArrayList<Object>(itemPropertyDescriptor .getChoiceOfValues(object)), getEditLabelProvider(), itemPropertyDescriptor.isSortChoices(object)); } else if (!(genericProperty instanceof AnnotationProperty || genericProperty instanceof DatatypeProperty || genericProperty instanceof OntologyProperty)) { final IProperty property = (IProperty) genericProperty; final Collection<?> choiceOfValues = itemPropertyDescriptor .getChoiceOfValues(object); if (choiceOfValues != null) { if (itemPropertyDescriptor.isMany(object)) { // boolean valid = true; // for (Object choice : choiceOfValues) { // if (!property.isRangeCompatible((IResource) object, // choice)) { // valid = false; // break; // } // } // // if (valid) { final ILabelProvider editLabelProvider = getEditLabelProvider(); result = new ExtendedDialogCellEditor(composite, editLabelProvider) { @Override protected Object openDialogBox(Control cellEditorWindow) { PropertyEditorDialog dialog = new PropertyEditorDialog( cellEditorWindow.getShell(), adapterFactory, editLabelProvider, (IObject) object, property.getNamedRanges( (IObject) object, true).toSet(), (Collection<?>) doGetValue(), getDisplayName(), new ArrayList<Object>( choiceOfValues), false, itemPropertyDescriptor .isSortChoices(object)); dialog.open(); return dialog.getResult(); } }; // } } if (result == null) { result = new ExtendedComboBoxCellEditor(composite, new ArrayList<Object>(choiceOfValues), getEditLabelProvider(), itemPropertyDescriptor.isSortChoices(object)); } } } else if (genericProperty instanceof IProperty) { final IProperty property = (IProperty) genericProperty; if (itemPropertyDescriptor.isMany(object)) { final ILabelProvider editLabelProvider = getEditLabelProvider(); result = new ExtendedDialogCellEditor(composite, editLabelProvider) { @Override protected Object openDialogBox(Control cellEditorWindow) { PropertyEditorDialog dialog = new PropertyEditorDialog( cellEditorWindow.getShell(), adapterFactory, editLabelProvider, (IObject) object, property .getRanges(true).toSet(), (Collection<?>) doGetValue(), getDisplayName(), null, itemPropertyDescriptor.isMultiLine(object), false); dialog.open(); return dialog.getResult(); } }; } else if (property.getRdfsRanges() .contains(XMLSCHEMA.TYPE_BOOLEAN)) { result = new ExtendedComboBoxCellEditor(composite, Arrays.asList(new Object[] { Boolean.FALSE, Boolean.TRUE }), getEditLabelProvider(), itemPropertyDescriptor.isSortChoices(object)); } else { result = createDatatypeCellEditor( property.getNamedRanges((IObject) object, true).toSet(), composite); } } return result; } }