X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.modeling%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Fadapters%2FExistingInstancesRemover.java;fp=bundles%2Forg.simantics.modeling%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Fadapters%2FExistingInstancesRemover.java;h=787a400f9439022a4346532bd3c6fce3471127fe;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hp=a2b4fc38e2a4c08338bac1e68c31da51af95f0ed;hpb=24e2b34260f219f0d1644ca7a138894980e25b14;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/ExistingInstancesRemover.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/ExistingInstancesRemover.java index a2b4fc38e..787a400f9 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/ExistingInstancesRemover.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/ExistingInstancesRemover.java @@ -1,272 +1,272 @@ -package org.simantics.modeling.adapters; - -import gnu.trove.map.hash.THashMap; -import gnu.trove.set.hash.THashSet; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.ui.PlatformUI; -import org.simantics.databoard.Bindings; -import org.simantics.databoard.util.URIStringUtils; -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.Session; -import org.simantics.db.WriteGraph; -import org.simantics.db.common.request.PossibleIndexRoot; -import org.simantics.db.common.request.WriteRequest; -import org.simantics.db.common.utils.NameUtils; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.adapter.Instances; -import org.simantics.db.layer0.adapter.Remover; -import org.simantics.db.layer0.adapter.impl.AbstractRemover; -import org.simantics.db.layer0.adapter.impl.EntityRemover; -import org.simantics.db.layer0.exception.CannotRemoveException; -import org.simantics.db.layer0.util.Layer0Utils; -import org.simantics.db.layer0.util.RemoverUtil; -import org.simantics.layer0.Layer0; -import org.simantics.modeling.ModelingResources; -import org.simantics.modeling.adapters.RemoveInstancesDialog.Content; -import org.simantics.utils.strings.AlphanumComparator; -import org.simantics.utils.ui.BundleUtils; - -/** - * @author Tuukka Lehtonen - */ -public class ExistingInstancesRemover extends AbstractRemover { - - protected String typeDescription; - - public ExistingInstancesRemover(Resource resource, String removedTypeDescription) { - super(resource); - this.typeDescription = removedTypeDescription; - } - - @Override - public void remove(WriteGraph graph) throws DatabaseException { - remove(graph, resource, resource, resource); - } - - protected void remove(WriteGraph graph, Resource resource, Resource typeResource, Resource typeNameResource) throws DatabaseException { -// System.out.println("resource: " + NameUtils.getURIOrSafeNameInternal(graph, resource)); -// System.out.println("type resource: " + NameUtils.getURIOrSafeNameInternal(graph, typeResource)); -// System.out.println("type name resource: " + NameUtils.getURIOrSafeNameInternal(graph, typeNameResource)); - if (Layer0Utils.isContainerPublished(graph, resource)) - throw new CannotRemoveException("Items in published libraries cannot be removed. Please create a new version to perform modifications."); - - Resource root = graph.syncRequest(new PossibleIndexRoot(resource)); - if (root == null) { - justRemove(graph); - // Not part of an index root? Just remove everything because - // we can't find instances anyway. - return; - } - - Layer0 L0 = Layer0.getInstance(graph); - final String componentTypeName = graph.getPossibleRelatedValue(typeNameResource, L0.HasName, Bindings.STRING); - if (componentTypeName == null) { - justRemove(graph); - return; - } - - Set instances = discoverInstances(graph, typeResource); - if (!instances.isEmpty()) { - confirmRemoval(graph, instances, typeDescription, componentTypeName); - } else { - justRemove(graph); - } - } - - protected Set discoverInstances(WriteGraph graph, Resource type) throws DatabaseException { - Resource indexRoot = graph.syncRequest(new PossibleIndexRoot(type)); - if (indexRoot == null) - return Collections.emptySet(); - -// @SuppressWarnings("rawtypes") -// Function modules = graph.adapt(Layer0X.getInstance(graph).Dependencies, Function.class); -// @SuppressWarnings("unchecked") -// List> result = (List>) modules.apply(graph, root, "Types:\"" + IndexQueries.escape(componentTypeName) + "\""); -// if (result.isEmpty()) { -// justRemove(graph); -// return; -// } -// -// final Set instances = new HashSet(); -// for (Map entry : result) { -// Resource c = (Resource) entry.get(Dependencies.FIELD_RESOURCE); -// if (c != null && graph.hasStatement(c, L0.InstanceOf, resource)) { -// instances.add(c); -// } -// } - - Set result = new THashSet(); - Instances search = graph.adapt(type, Instances.class); - discoverInstances(graph, type, indexRoot, search, result); - - // It is possible that resource is an instance of the specified type - // also. However we assume that the specified resource is removed last - // only after all the instances have been removed. That's why we remove - // resource from the calculated set of instances at this point. - result.remove(resource); - -// for (Resource r : result) -// System.out.println("found instance: " + NameUtils.getURIOrSafeNameInternal(graph, r)); - - return result; - } - - private void discoverInstances(WriteGraph graph, Resource typeResource, Resource indexRoot, Instances instances, Set result) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); - Collection rs = instances.find(graph, indexRoot); - result.addAll(rs); - - for (Resource linkee : graph.getObjects(indexRoot, L0.IsLinkedTo_Inverse)) { - discoverInstances(graph, typeResource, linkee, instances, result); - } - } - - protected void confirmRemoval(WriteGraph graph, final Set instances, final String typeDescription, final String typeName) throws DatabaseException { - Map instanceAddresses = resolveInstanceAddresses(graph, instances); - Map unremovable = findUnremovable(graph, instances); - final RemoveInstancesDialog.Content[] content = new RemoveInstancesDialog.Content[instanceAddresses.size()]; - int i = 0; - ImageDescriptor problemImage = BundleUtils.getImageDescriptorFromPlugin("com.famfamfam.silk", "icons/error.png"); - for (Map.Entry entry : instanceAddresses.entrySet()) { - content[i] = new RemoveInstancesDialog.Content(entry.getValue()); - content[i].details = unremovable.get(entry.getKey()); - if (content[i].details != null) { - content[i].image = problemImage; - } - ++i; - } - Arrays.sort(content, new Comparator() { - @Override - public int compare(Content o1, Content o2) { - return AlphanumComparator.CASE_INSENSITIVE_COMPARATOR.compare(o1.label, o2.label); - } - }); - - if (!unremovable.isEmpty()) { - if (PlatformUI.isWorkbenchRunning()) { - PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - RemoveInstancesDialog dialog = new RemoveInstancesDialog( - PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), - "Cannot Remove " + typeDescription, - typeDescription + " '" + typeName - + "' is still in use and all of its " - + instances.size() - + " instances cannot be removed.\n\nSelect instances marked with errors from the table below to see why they cannot be removed.", - MessageDialog.ERROR, - new String[] { IDialogConstants.OK_LABEL }, - 0, - content); - dialog.open(); - } - }); - } - return; - } - - final Session session = graph.getSession(); - - if (PlatformUI.isWorkbenchRunning()) { - PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - RemoveInstancesDialog dialog = new RemoveInstancesDialog( - PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), - "Remove " + typeDescription + "?", - typeDescription + " '" + typeName + "' is still in use. Are you sure you want to remove it and all its " + instances.size() + " instances?", - content); - int result = dialog.open(); - boolean doIt = result == IDialogConstants.OK_ID; - if (!doIt) - return; - session.asyncRequest(new WriteRequest() { - @Override - public void perform(WriteGraph graph) throws DatabaseException { - justRemoveWithInstances(graph, instances); - } - }); - } - }); - } else { - // Just do it without confirmation when no user agent is available. - justRemoveWithInstances(graph, instances); - } - } - - protected void justRemoveWithInstances(WriteGraph graph, Collection instances) throws DatabaseException { - for (Resource instance : instances) - RemoverUtil.remove(graph, instance); - justRemove(graph); - } - - protected Map resolveInstanceAddresses(ReadGraph graph, Set instances) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); - ModelingResources MOD = ModelingResources.getInstance(graph); - Map result = new THashMap(); - for (Resource instance : instances) { - Resource component = graph.getPossibleObject(instance, MOD.ElementToComponent); - if (component != null) - instance = component; - String instanceUri = graph.getPossibleURI(instance); - if (instanceUri != null) { - Resource root = graph.syncRequest(new PossibleIndexRoot(instance)); - if (root != null) { - Resource rootParent = graph.getPossibleObject(root, L0.PartOf); - if (rootParent == null) - rootParent = root; - - String rootUri = graph.getPossibleURI(rootParent); - if (rootUri != null) { - String instanceRelativeUri = instanceUri.substring(rootUri.length()); - result.put(instance, URIStringUtils.unescape( instanceRelativeUri )); - continue; - } - } - - result.put(instance, URIStringUtils.unescape( instanceUri )); - continue; - } - - // Fallback logic - result.put(instance, NameUtils.getSafeName(graph, instance, true)); - } - return result; - } - - protected void justRemove(WriteGraph graph) throws DatabaseException { - graph.deny(resource, Layer0.getInstance(graph).PartOf); - EntityRemover.remove(graph, resource); - } - - private Map findUnremovable(ReadGraph graph, Collection instances) throws DatabaseException { - Map result = null; - Map aux = new HashMap(); - for (Resource r : instances) { - Remover remover = graph.getPossibleAdapter(r, Remover.class); - if (remover == null) - continue; - aux.clear(); - String problem = remover.canRemove(graph, aux); - if (problem != null) { - if (result == null) - result = new THashMap(); - result.put(r, problem); - } - } - return result == null ? Collections.emptyMap() : result; - } - +package org.simantics.modeling.adapters; + +import gnu.trove.map.hash.THashMap; +import gnu.trove.set.hash.THashSet; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.PlatformUI; +import org.simantics.databoard.Bindings; +import org.simantics.databoard.util.URIStringUtils; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.PossibleIndexRoot; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.adapter.Instances; +import org.simantics.db.layer0.adapter.Remover; +import org.simantics.db.layer0.adapter.impl.AbstractRemover; +import org.simantics.db.layer0.adapter.impl.EntityRemover; +import org.simantics.db.layer0.exception.CannotRemoveException; +import org.simantics.db.layer0.util.Layer0Utils; +import org.simantics.db.layer0.util.RemoverUtil; +import org.simantics.layer0.Layer0; +import org.simantics.modeling.ModelingResources; +import org.simantics.modeling.adapters.RemoveInstancesDialog.Content; +import org.simantics.utils.strings.AlphanumComparator; +import org.simantics.utils.ui.BundleUtils; + +/** + * @author Tuukka Lehtonen + */ +public class ExistingInstancesRemover extends AbstractRemover { + + protected String typeDescription; + + public ExistingInstancesRemover(Resource resource, String removedTypeDescription) { + super(resource); + this.typeDescription = removedTypeDescription; + } + + @Override + public void remove(WriteGraph graph) throws DatabaseException { + remove(graph, resource, resource, resource); + } + + protected void remove(WriteGraph graph, Resource resource, Resource typeResource, Resource typeNameResource) throws DatabaseException { +// System.out.println("resource: " + NameUtils.getURIOrSafeNameInternal(graph, resource)); +// System.out.println("type resource: " + NameUtils.getURIOrSafeNameInternal(graph, typeResource)); +// System.out.println("type name resource: " + NameUtils.getURIOrSafeNameInternal(graph, typeNameResource)); + if (Layer0Utils.isContainerPublished(graph, resource)) + throw new CannotRemoveException("Items in published libraries cannot be removed. Please create a new version to perform modifications."); + + Resource root = graph.syncRequest(new PossibleIndexRoot(resource)); + if (root == null) { + justRemove(graph); + // Not part of an index root? Just remove everything because + // we can't find instances anyway. + return; + } + + Layer0 L0 = Layer0.getInstance(graph); + final String componentTypeName = graph.getPossibleRelatedValue(typeNameResource, L0.HasName, Bindings.STRING); + if (componentTypeName == null) { + justRemove(graph); + return; + } + + Set instances = discoverInstances(graph, typeResource); + if (!instances.isEmpty()) { + confirmRemoval(graph, instances, typeDescription, componentTypeName); + } else { + justRemove(graph); + } + } + + protected Set discoverInstances(WriteGraph graph, Resource type) throws DatabaseException { + Resource indexRoot = graph.syncRequest(new PossibleIndexRoot(type)); + if (indexRoot == null) + return Collections.emptySet(); + +// @SuppressWarnings("rawtypes") +// Function modules = graph.adapt(Layer0X.getInstance(graph).Dependencies, Function.class); +// @SuppressWarnings("unchecked") +// List> result = (List>) modules.apply(graph, root, "Types:\"" + IndexQueries.escape(componentTypeName) + "\""); +// if (result.isEmpty()) { +// justRemove(graph); +// return; +// } +// +// final Set instances = new HashSet(); +// for (Map entry : result) { +// Resource c = (Resource) entry.get(Dependencies.FIELD_RESOURCE); +// if (c != null && graph.hasStatement(c, L0.InstanceOf, resource)) { +// instances.add(c); +// } +// } + + Set result = new THashSet(); + Instances search = graph.adapt(type, Instances.class); + discoverInstances(graph, type, indexRoot, search, result); + + // It is possible that resource is an instance of the specified type + // also. However we assume that the specified resource is removed last + // only after all the instances have been removed. That's why we remove + // resource from the calculated set of instances at this point. + result.remove(resource); + +// for (Resource r : result) +// System.out.println("found instance: " + NameUtils.getURIOrSafeNameInternal(graph, r)); + + return result; + } + + private void discoverInstances(WriteGraph graph, Resource typeResource, Resource indexRoot, Instances instances, Set result) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + Collection rs = instances.find(graph, indexRoot); + result.addAll(rs); + + for (Resource linkee : graph.getObjects(indexRoot, L0.IsLinkedTo_Inverse)) { + discoverInstances(graph, typeResource, linkee, instances, result); + } + } + + protected void confirmRemoval(WriteGraph graph, final Set instances, final String typeDescription, final String typeName) throws DatabaseException { + Map instanceAddresses = resolveInstanceAddresses(graph, instances); + Map unremovable = findUnremovable(graph, instances); + final RemoveInstancesDialog.Content[] content = new RemoveInstancesDialog.Content[instanceAddresses.size()]; + int i = 0; + ImageDescriptor problemImage = BundleUtils.getImageDescriptorFromPlugin("com.famfamfam.silk", "icons/error.png"); + for (Map.Entry entry : instanceAddresses.entrySet()) { + content[i] = new RemoveInstancesDialog.Content(entry.getValue()); + content[i].details = unremovable.get(entry.getKey()); + if (content[i].details != null) { + content[i].image = problemImage; + } + ++i; + } + Arrays.sort(content, new Comparator() { + @Override + public int compare(Content o1, Content o2) { + return AlphanumComparator.CASE_INSENSITIVE_COMPARATOR.compare(o1.label, o2.label); + } + }); + + if (!unremovable.isEmpty()) { + if (PlatformUI.isWorkbenchRunning()) { + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + RemoveInstancesDialog dialog = new RemoveInstancesDialog( + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), + "Cannot Remove " + typeDescription, + typeDescription + " '" + typeName + + "' is still in use and all of its " + + instances.size() + + " instances cannot be removed.\n\nSelect instances marked with errors from the table below to see why they cannot be removed.", + MessageDialog.ERROR, + new String[] { IDialogConstants.OK_LABEL }, + 0, + content); + dialog.open(); + } + }); + } + return; + } + + final Session session = graph.getSession(); + + if (PlatformUI.isWorkbenchRunning()) { + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + RemoveInstancesDialog dialog = new RemoveInstancesDialog( + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), + "Remove " + typeDescription + "?", + typeDescription + " '" + typeName + "' is still in use. Are you sure you want to remove it and all its " + instances.size() + " instances?", + content); + int result = dialog.open(); + boolean doIt = result == IDialogConstants.OK_ID; + if (!doIt) + return; + session.asyncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + justRemoveWithInstances(graph, instances); + } + }); + } + }); + } else { + // Just do it without confirmation when no user agent is available. + justRemoveWithInstances(graph, instances); + } + } + + protected void justRemoveWithInstances(WriteGraph graph, Collection instances) throws DatabaseException { + for (Resource instance : instances) + RemoverUtil.remove(graph, instance); + justRemove(graph); + } + + protected Map resolveInstanceAddresses(ReadGraph graph, Set instances) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + ModelingResources MOD = ModelingResources.getInstance(graph); + Map result = new THashMap(); + for (Resource instance : instances) { + Resource component = graph.getPossibleObject(instance, MOD.ElementToComponent); + if (component != null) + instance = component; + String instanceUri = graph.getPossibleURI(instance); + if (instanceUri != null) { + Resource root = graph.syncRequest(new PossibleIndexRoot(instance)); + if (root != null) { + Resource rootParent = graph.getPossibleObject(root, L0.PartOf); + if (rootParent == null) + rootParent = root; + + String rootUri = graph.getPossibleURI(rootParent); + if (rootUri != null) { + String instanceRelativeUri = instanceUri.substring(rootUri.length()); + result.put(instance, URIStringUtils.unescape( instanceRelativeUri )); + continue; + } + } + + result.put(instance, URIStringUtils.unescape( instanceUri )); + continue; + } + + // Fallback logic + result.put(instance, NameUtils.getSafeName(graph, instance, true)); + } + return result; + } + + protected void justRemove(WriteGraph graph) throws DatabaseException { + graph.deny(resource, Layer0.getInstance(graph).PartOf); + EntityRemover.remove(graph, resource); + } + + private Map findUnremovable(ReadGraph graph, Collection instances) throws DatabaseException { + Map result = null; + Map aux = new HashMap(); + for (Resource r : instances) { + Remover remover = graph.getPossibleAdapter(r, Remover.class); + if (remover == null) + continue; + aux.clear(); + String problem = remover.canRemove(graph, aux); + if (problem != null) { + if (result == null) + result = new THashMap(); + result.put(r, problem); + } + } + return result == null ? Collections.emptyMap() : result; + } + } \ No newline at end of file