/******************************************************************************* * Copyright (c) 2009 Fraunhofer IWU 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: * Fraunhofer IWU - initial API and implementation *******************************************************************************/ package net.enilink.komma.rdfs.edit; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Set; import net.enilink.commons.iterator.IExtendedIterator; import net.enilink.komma.common.command.CommandResult; import net.enilink.komma.common.command.CompositeCommand; import net.enilink.komma.common.command.ICommand; import net.enilink.komma.common.command.IdentityCommand; import net.enilink.komma.common.command.UnexecutableCommand; import net.enilink.komma.common.util.ICollector; import net.enilink.komma.common.util.IResourceLocator; import net.enilink.komma.core.IEntity; import net.enilink.komma.core.IEntityManager; import net.enilink.komma.core.IReference; import net.enilink.komma.edit.command.AddCommand; import net.enilink.komma.edit.command.CommandParameter; import net.enilink.komma.edit.command.CreateChildCommand; import net.enilink.komma.edit.command.DragAndDropCommand; import net.enilink.komma.edit.domain.IEditingDomain; import net.enilink.komma.edit.provider.ISearchableItemProvider; import net.enilink.komma.edit.provider.IViewerNotification; import net.enilink.komma.edit.provider.ReflectiveItemProvider; import net.enilink.komma.edit.provider.SparqlSearchableItemProvider; import net.enilink.komma.edit.provider.ViewerNotification; import net.enilink.komma.em.concepts.IClass; import net.enilink.komma.em.concepts.IProperty; import net.enilink.komma.em.concepts.IResource; import net.enilink.komma.model.ModelUtil; import net.enilink.komma.model.event.IStatementNotification; import net.enilink.vocab.owl.OWL; import net.enilink.vocab.rdfs.RDFS; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; public class RDFSClassItemProvider extends ReflectiveItemProvider { public RDFSClassItemProvider(RDFSItemProviderAdapterFactory adapterFactory, IResourceLocator resourceLocator, Collection<IClass> supportedTypes) { super(adapterFactory, resourceLocator, supportedTypes); } protected void addViewerNotifications( Collection<IViewerNotification> viewerNotifications, IStatementNotification notification) { if (RDFS.PROPERTY_SUBCLASSOF.equals(notification.getPredicate())) { IEntity superClass = resolveReference(notification.getObject()); if (superClass != null) { viewerNotifications.add(new ViewerNotification(superClass)); } IEntity thing = resolveReference(OWL.TYPE_THING); if (thing != null) { // manually refresh cached values for owl:Thing thing.getEntityManager().refresh(thing); viewerNotifications.add(new ViewerNotification(thing)); } return; } super.addViewerNotifications(viewerNotifications, notification); } @Override protected void collectChildrenProperties(Object object, Collection<IProperty> childrenProperties) { } @Override protected void collectNewChildDescriptors( ICollector<Object> newChildDescriptors, Object object) { if (object instanceof IClass) { IEntityManager em = ((IEntity) object).getEntityManager(); newChildDescriptors.add(createChildParameter( em.find(RDFS.PROPERTY_SUBCLASSOF), new ChildDescriptor(Arrays.asList(em.find(RDFS.TYPE_CLASS, IClass.class)), true))); } } @Override protected ICommand createCreateChildCommand(IEditingDomain domain, IResource owner, IReference property, Object value, int index, Collection<?> collection) { if (RDFS.PROPERTY_SUBCLASSOF.equals(property)) { return new CreateChildCommand(domain, owner, property, value, index, collection, this) { @Override protected CommandResult doExecuteWithResult( IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException { child = helper.createChild(owner, property, childDescription, info); if (child != null) { addAndExecute(AddCommand.create(domain, child, property, owner, index), progressMonitor, info); } affectedObjects = helper.getCreateChildResult(child); Collection<?> result = helper.getCreateChildResult(child); return CommandResult .newOKCommandResult(result == null ? Collections.EMPTY_LIST : result); } @Override public boolean prepare() { if (owner == null || property == null || childDescription == null) { return false; } return true; } }; } return super.createCreateChildCommand(domain, owner, property, value, index, collection); } @Override protected ICommand createDragAndDropCommand(IEditingDomain domain, Object owner, float location, int operations, int operation, Collection<?> collection) { return new DragAndDropCommand(domain, owner, location, operations, operation, collection) { @Override protected boolean isNonContainment(IReference property) { if (RDFS.PROPERTY_SUBCLASSOF.equals(property)) { return false; } return super.isNonContainment(property); } @Override protected boolean prepareDropCopyOn() { // simply link dropped class to parent class by rdfs:subClassOf dragCommand = IdentityCommand.INSTANCE; dropCommand = AddCommand .create(domain, owner, null, collection); return dropCommand.canExecute(); } @Override protected boolean prepareDropLinkOn() { return prepareDropCopyOn(); } }; } @Override protected ICommand factorAddCommand(IEditingDomain domain, CommandParameter commandParameter) { if (commandParameter.getCollection() == null || commandParameter.getCollection().isEmpty()) { return UnexecutableCommand.INSTANCE; } CompositeCommand addCommand = new CompositeCommand(); Object owner = commandParameter.getOwner(); for (Object value : commandParameter.getCollection()) { if (owner instanceof IClass && value instanceof IClass && !owner.equals(value) && !((IClass) owner).getRdfsSubClassOf().contains(value)) { addCommand.add(new AddCommand(domain, (IResource) value, ((IResource) value).getEntityManager().find( RDFS.PROPERTY_SUBCLASSOF), Arrays.asList(owner), CommandParameter.NO_INDEX) { @Override public Collection<?> doGetAffectedObjects() { if (affectedObjects.contains(owner)) { return collection; } else { return owner == null ? Collections.emptySet() : Collections.singleton(owner); } } }); } else { addCommand.dispose(); return UnexecutableCommand.INSTANCE; } } return addCommand.reduce(); } @Override protected ICommand factorMoveCommand(IEditingDomain domain, CommandParameter commandParameter) { return UnexecutableCommand.INSTANCE; } @Override protected ICommand factorRemoveCommand(IEditingDomain domain, CommandParameter commandParameter) { final IResource owner = commandParameter.getOwnerResource(); CompositeCommand removeCommand = new CompositeCommand(); for (Object value : commandParameter.getCollection()) { if (owner.equals(value)) { removeCommand.dispose(); return UnexecutableCommand.INSTANCE; } removeCommand.add(createRemoveCommand( domain, (IResource) value, ((IResource) value).getEntityManager().find( RDFS.PROPERTY_SUBCLASSOF), Arrays.asList(commandParameter.getOwner()))); } return removeCommand.reduce(); } @Override public Collection<?> getChildren(Object object) { if (object instanceof IClass) { Set<IClass> subClasses = ((IClass) object) .getDirectNamedSubClasses().toSet(); if (RDFS.TYPE_RESOURCE.equals(object)) { if (!subClasses.contains(OWL.TYPE_THING)) { subClasses.add((IClass) ((IClass) object) .getEntityManager().find(OWL.TYPE_THING)); } } // avoid recursive containment if (OWL.TYPE_THING.equals(object)) { subClasses.remove(RDFS.TYPE_RESOURCE); } // sort results List<IClass> sortedClasses = new ArrayList<IClass>(subClasses); Collections.sort(sortedClasses, new Comparator<IClass>() { @Override public int compare(IClass c1, IClass c2) { return ModelUtil.LABEL_COLLATOR.compare(getText(c1), getText(c2)); } }); return sortedClasses; } return super.getChildren(object); } @Override protected ISearchableItemProvider getSearchableItemProvider() { return new SparqlSearchableItemProvider() { @Override protected String getQueryFindPatterns(Object parent) { if (RDFS.TYPE_RESOURCE.equals(parent) || OWL.TYPE_THING.equals(parent)) { return "{ ?s a rdfs:Class } union { ?s a owl:Class }"; } return "?s rdfs:subClassOf* ?parent"; } }; } @Override public Object getParent(Object object) { if (object instanceof IClass) { if (RDFS.TYPE_RESOURCE.equals(object)) { return null; } // always return rdfs:Resource as parent of owl:Thing if (OWL.TYPE_THING.equals(object)) { return ((IEntity) object).getEntityManager().find( RDFS.TYPE_RESOURCE); } IExtendedIterator<?> it = ((IClass) object) .getDirectNamedSuperClasses(); try { if (it.hasNext()) { return it.next(); } return ((IEntity) object).getEntityManager().find( OWL.TYPE_THING); } finally { it.close(); } } return super.getParent(object); } @Override protected Collection<? extends IReference> getTypes(Object object) { if (object.equals(OWL.TYPE_OBJECTPROPERTY) || object.equals(OWL.TYPE_DATATYPEPROPERTY)) { return Arrays.asList((IReference) object); } return super.getTypes(object); } @Override public boolean hasChildren(Object object) { if (object instanceof IClass) { return ((IClass) object).hasNamedSubClasses(true); } return hasChildren(object, false); } }