package net.enilink.komma.edit.util; import java.util.LinkedList; import java.util.Queue; import net.enilink.commons.iterator.IExtendedIterator; import net.enilink.commons.util.Pair; import net.enilink.komma.common.command.CommandResult; import net.enilink.komma.common.command.ICommand; import net.enilink.komma.common.command.ICompositeCommand; import net.enilink.komma.common.command.SimpleCommand; import net.enilink.komma.core.IEntityManager; import net.enilink.komma.core.IReference; import net.enilink.komma.core.IStatement; import net.enilink.komma.edit.command.AddCommand; import net.enilink.komma.edit.command.CommandParameter; import net.enilink.komma.edit.command.RemoveCommand; import net.enilink.komma.edit.command.SetCommand; import net.enilink.komma.edit.domain.IEditingDomain; import net.enilink.komma.em.concepts.IProperty; import net.enilink.komma.em.concepts.IResource; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.commands.operations.IUndoableOperation; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; /** * Helper class for adding, removing and editing of property values. */ public class PropertyUtil { /** * Construct an {@link ICommand} to add the given statement. */ public static ICommand getAddCommand(IEditingDomain editingDomain, IResource subject, IProperty predicate, Object object) { return getAddCommand(editingDomain, subject, predicate, object, CommandParameter.NO_INDEX); } /** * Construct an {@link ICommand} to add the given statement. */ public static ICommand getAddCommand(IEditingDomain editingDomain, IResource subject, IProperty predicate, Object object, int index) { Pair<Integer, Integer> cardinality = subject .getApplicableCardinality(predicate); ICommand addCommand; if (cardinality.getSecond() != 1) { addCommand = AddCommand.create(editingDomain, subject, predicate, object, index); } else { addCommand = SetCommand.create(editingDomain, subject, predicate, object, index); } return addCommand; } /** * Construct an {@link ICommand} to remove the given statement. */ public static ICommand getRemoveCommand(IEditingDomain editingDomain, final IResource subject, final IProperty property, final Object object) { ICommand removeCommand = RemoveCommand.create(editingDomain, subject, property, object); // remove blank node objects which are solely referenced by deleted // subject // this can be optimized by using SPARQL 1.1 removeCommand = removeCommand.compose(new SimpleCommand() { protected boolean canDelete(IEntityManager em, IReference deletedSubject, Object object) { if (!(object instanceof IReference && ((IReference) object) .getURI() == null)) { return false; } // this could also be done with // if (! em.hasMatchAsserted(null, null, node)) // { ... } // iff no transaction is running IExtendedIterator<IStatement> refs = em.matchAsserted(null, null, (IReference) object); boolean canDelete = true; for (IStatement refStmt : refs) { if (!refStmt.getSubject().equals(deletedSubject)) { canDelete = false; break; } } refs.close(); return canDelete; } @Override protected CommandResult doExecuteWithResult( IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException { IEntityManager em = subject.getEntityManager(); if (canDelete(em, subject, object)) { Queue<IReference> bnodes = new LinkedList<IReference>(); bnodes.add(((IReference) object)); while (!bnodes.isEmpty()) { IReference node = bnodes.remove(); for (IStatement stmt : em.matchAsserted(node, null, null)) { Object o = stmt.getObject(); if (canDelete(em, node, o)) { bnodes.add((IReference) o); } } em.remove(node); } } return CommandResult.newOKCommandResult(); } }); return removeCommand; } /** * Determines the index of the first element that has been removed. This * method only returns valid results AFTER the corresponding remove command * has been executed. * * @param operation * A possible composite operation that may contain a remove * command for an element * @return Index of removed element */ public static int getRemovedIndex(IUndoableOperation operation) { Integer index = findRemovedIndex(operation); return index != null ? index : CommandParameter.NO_INDEX; } private static Integer findRemovedIndex(IUndoableOperation operation) { if (operation instanceof RemoveCommand) { int[] indices = ((RemoveCommand) operation).getIndices(); return indices != null && indices.length > 0 ? indices[0] : CommandParameter.NO_INDEX; } if (operation instanceof ICompositeCommand) { for (IUndoableOperation child : (ICompositeCommand) operation) { Integer index = findRemovedIndex(child); if (index != null) { return index; } } } return null; } }