/**
* <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: ReflectiveItemProvider.java,v 1.22 2008/05/25 17:27:40 emerks Exp $
*/
package net.enilink.komma.edit.provider;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import net.enilink.commons.iterator.IExtendedIterator;
import net.enilink.komma.common.adapter.IAdapterFactory;
import net.enilink.komma.common.notify.INotification;
import net.enilink.komma.common.util.IResourceLocator;
import net.enilink.komma.core.IEntity;
import net.enilink.komma.core.IReference;
import net.enilink.komma.core.URI;
import net.enilink.komma.edit.KommaEditPlugin;
import net.enilink.komma.em.concepts.IResource;
import net.enilink.komma.model.IObject;
import net.enilink.komma.model.ModelUtil;
import net.enilink.komma.model.event.IStatementNotification;
import net.enilink.vocab.rdf.RDF;
import net.enilink.vocab.rdfs.RDFS;
/**
* This adapter implementation provides reflective support that emulates the
* behavior of a default generated item provider.
*/
public class ReflectiveItemProvider extends ItemProviderAdapter
implements IEditingDomainItemProvider, IStructuredItemContentProvider, ITreeItemContentProvider,
IItemColorProvider, IItemFontProvider, IItemLabelProvider, IItemPropertySource, ISearchableItemProvider {
protected IResourceLocator resourceLocator;
protected Collection<? extends IReference> targetTypes;
public ReflectiveItemProvider(IAdapterFactory adapterFactory, IResourceLocator resourceLocator,
Collection<? extends IReference> targetTypes) {
super(adapterFactory);
this.resourceLocator = resourceLocator;
this.targetTypes = targetTypes;
}
public IResourceLocator getResourceLocator() {
return resourceLocator;
}
/**
* This handles model notifications by calling {@link #updateChildren} to
* update any cached children and by creating a viewer notification, which
* it passes to {@link #fireNotifyChanged}.
*/
@Override
public void notifyChanged(Collection<? extends INotification> notifications) {
super.notifyChanged(notifications);
Collection<IViewerNotification> viewerNotifications = new ArrayList<IViewerNotification>(0);
for (INotification notification : notifications) {
if (notification instanceof IStatementNotification) {
IStatementNotification stmtNotification = (IStatementNotification) notification;
// ensure that adapter is replaced by another one that matches
// the current entity types
if (RDF.PROPERTY_TYPE.equals(stmtNotification.getPredicate())
&& adapterFactory instanceof AdapterFactory) {
IEntity object = resolveReference(notification.getSubject());
if (object != null) {
viewerNotifications.add(new ViewerNotification(object, true, true));
}
((AdapterFactory) adapterFactory).unlinkAdapter(stmtNotification.getSubject());
}
addViewerNotifications(viewerNotifications, stmtNotification);
}
}
if (!viewerNotifications.isEmpty()) {
fireNotifications(viewerNotifications);
return;
}
}
protected boolean updateLabel(IStatementNotification notification) {
return RDFS.PROPERTY_LABEL.equals(notification.getPredicate());
}
protected void addViewerNotifications(Collection<IViewerNotification> viewerNotifications,
IStatementNotification notification) {
IEntity object = resolveReference(notification.getSubject());
if (object instanceof IResource) {
((IResource) object).refresh(notification.getPredicate());
boolean labelUpdate = updateLabel(notification);
viewerNotifications.add(new ViewerNotification(object, !labelUpdate, labelUpdate));
}
}
/**
* This should not be implemented as anonymous inner class to prevent
* referencing the item provider instance.
*
* Example: Storing an instance of this class in a global image registry can
* lead to memory leaks if item provider instances are referenced.
*/
static class ComposedCreateChildImage extends ComposedImage {
public ComposedCreateChildImage(Collection<?> images) {
super(images);
}
@Override
public List<Point> getDrawPoints(Size size) {
List<Point> result = super.getDrawPoints(size);
result.get(1).x = size.width - 7;
return result;
}
}
@Override
public Object getCreateChildImage(Object owner, Object property, Object childDescription, Collection<?> selection) {
if (childDescription instanceof ChildDescriptor) {
childDescription = ((ChildDescriptor) childDescription).getValue();
}
String name = "full/ctool16/Create" + getTypes(owner).iterator().next().getURI().localPart() + "_"
+ ((IReference) property).getURI().localPart();
Object childType = childDescription instanceof Collection<?>
? ((Collection<?>) childDescription).iterator().next() : childDescription;
if (childType instanceof net.enilink.vocab.rdfs.Class && ((IReference) childType).getURI() != null) {
name += "_" + ((IReference) childType).getURI().localPart();
}
try {
return getImage(name);
} catch (Exception e) {
List<Object> images = new ArrayList<Object>();
IItemLabelProvider itemLabelProvider = (IItemLabelProvider) ((IComposeableAdapterFactory) adapterFactory)
.getRootAdapterFactory().adapt(childType, IItemLabelProvider.class);
Object itemImage = itemLabelProvider != null ? itemLabelProvider.getImage(childType) : null;
if (itemImage != null) {
images.add(itemLabelProvider.getImage(childType));
images.add(KommaEditPlugin.INSTANCE.getImage("full/ovr16/CreateChild"));
return new ComposedCreateChildImage(images);
}
}
return super.getCreateChildImage(owner, property, childType, selection);
}
@Override
public Object getForeground(Object object) {
if (object instanceof IEntity) {
URI uri = ((IObject) object).getReference().getURI();
if (uri != null && uri.namespace().equals(((IEntity) object).getEntityManager().getNamespace(""))) {
return super.getForeground(object);
}
return IItemColorProvider.GRAYED_OUT_COLOR;
}
return super.getForeground(object);
}
@Override
public Object getFont(Object object) {
if (object instanceof IEntity) {
URI uri = ((IObject) object).getReference().getURI();
if (uri != null && uri.namespace().equals(((IEntity) object).getEntityManager().getNamespace(""))) {
return IItemFontProvider.BOLD_FONT;
}
}
return super.getFont(object);
}
@Override
public Object getImage(Object object) {
for (IReference type : getTypes(object)) {
try {
return overlayImage(object, getImage("full/obj16/" + type.getURI().localPart()));
} catch (Exception missing) {
// ignore
}
}
try {
// try default image from provided resource locator
return overlayImage(object, getImage("full/obj16/Item"));
} catch (Exception missing2) {
// fall back to image provided by edit plugin
return KommaEditPlugin.INSTANCE.getImage("full/obj16/Item");
}
}
protected Collection<? extends IReference> getTypes(Object object) {
return targetTypes;
}
public String getText(Object object) {
return ModelUtil.getLabel(object);
}
protected ISearchableItemProvider getSearchableItemProvider() {
return new SparqlSearchableItemProvider();
}
@Override
public IExtendedIterator<?> find(Object expression, Object parent, int limit) {
return getSearchableItemProvider().find(expression, parent, limit);
}
}