]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.ui/src/org/simantics/ui/workbench/ResourceEditorInput.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.ui / src / org / simantics / ui / workbench / ResourceEditorInput.java
diff --git a/bundles/org.simantics.ui/src/org/simantics/ui/workbench/ResourceEditorInput.java b/bundles/org.simantics.ui/src/org/simantics/ui/workbench/ResourceEditorInput.java
new file mode 100644 (file)
index 0000000..30dd1d1
--- /dev/null
@@ -0,0 +1,363 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.ui.workbench;\r
+\r
+import java.lang.ref.Reference;\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.eclipse.core.runtime.IAdaptable;\r
+import org.eclipse.core.runtime.PlatformObject;\r
+import org.eclipse.jface.resource.ImageDescriptor;\r
+import org.eclipse.ui.IMemento;\r
+import org.eclipse.ui.IPersistableElement;\r
+import org.simantics.Simantics;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.common.ResourceArray;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.exception.AdaptionException;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.service.LifecycleSupport;\r
+import org.simantics.ui.icons.ImageDescriptorProvider;\r
+import org.simantics.ui.workbench.editor.input.ResourceEditorInputMatchingStrategy;\r
+import org.simantics.utils.ObjectUtils;\r
+import org.simantics.utils.datastructures.cache.ProvisionException;\r
+import org.simantics.utils.ui.ErrorLogger;\r
+import org.simantics.utils.ui.workbench.StringMemento;\r
+\r
+/**\r
+ * A basic editor input for Simantics database {@link Resource} instances.\r
+ * \r
+ * Editor extensions requiring these as input should always use\r
+ * {@link ResourceEditorInputMatchingStrategy} as their matchingStrategy.\r
+ * \r
+ * @author Tuukka Lehtonen\r
+ * \r
+ * @see ResourceEditorInput2\r
+ * @see ResourceEditorInputMatchingStrategy\r
+ */\r
+public class ResourceEditorInput extends PlatformObject implements IResourceEditorInput, IPersistableElement {\r
+\r
+    static final String                        NO_NAME         = "(no name)";\r
+\r
+    private final String                       editorID;\r
+\r
+    private List<String>                       resourceIds;\r
+\r
+    private transient Reference<ResourceArray> resources;\r
+\r
+    private transient boolean                  exists;\r
+\r
+    private transient String                   name;\r
+\r
+    private transient String                   tooltip;\r
+\r
+    private transient ImageDescriptor          imageDesc;\r
+\r
+    /** Persistent memento for external data */\r
+    private final StringMemento                persistentStore = new StringMemento();\r
+\r
+    /**\r
+     * @param editorID\r
+     * @param r\r
+     */\r
+    public ResourceEditorInput(String editorID, Resource r) {\r
+        this(editorID, new ResourceArray(r));\r
+    }\r
+\r
+    /**\r
+     * @param editorID\r
+     * @param ra\r
+     */\r
+    public ResourceEditorInput(String editorID, ResourceArray ra) {\r
+        if (editorID == null)\r
+            throw new IllegalArgumentException("null editor id");\r
+        if (ra == null)\r
+            throw new IllegalArgumentException("null resource array");\r
+        if (ra.isEmpty())\r
+            throw new IllegalArgumentException("input resource array is empty, expected non-empty list");\r
+        for (Resource r : ra.resources)\r
+            if (r == null)\r
+                throw new IllegalArgumentException("input resource array contains null resources: " + ra);\r
+\r
+        this.editorID = editorID;\r
+        this.resources = ResourceInputs.makeReference(ra);\r
+        this.resourceIds = ResourceInputs.getRandomAccessIds(ra);\r
+\r
+        setNonExistant();\r
+    }\r
+\r
+    /**\r
+     * @param editorID\r
+     * @param randomAccessResourceId\r
+     */\r
+    public ResourceEditorInput(String editorID, String randomAccessResourceId) {\r
+        this(editorID, Collections.singletonList(randomAccessResourceId));\r
+    }\r
+\r
+    /**\r
+     * @param editorID\r
+     * @param randomAccessResourceId a non-empty list of random access resource\r
+     *        ids\r
+     * @throws IllegalArgumentException if the specified random access id list\r
+     *         is <code>null</code> or empty\r
+     */\r
+    public ResourceEditorInput(String editorID, List<String> randomAccessResourceId) {\r
+        if (randomAccessResourceId == null)\r
+            throw new IllegalArgumentException("null resource id list");\r
+        if (randomAccessResourceId.isEmpty())\r
+            throw new IllegalArgumentException("input resource id list is empty, expected non-empty list");\r
+        for (String id : randomAccessResourceId)\r
+            if (id == null)\r
+                throw new IllegalArgumentException("input resource id list contains null IDs: " + randomAccessResourceId);\r
+\r
+        this.editorID = editorID;\r
+        if (editorID == null)\r
+            editorID = "";\r
+        this.resourceIds = Collections.unmodifiableList(new ArrayList<String>(randomAccessResourceId));\r
+        this.resources = ResourceInputs.makeReference(ResourceArray.EMPTY);\r
+\r
+        setNonExistant();\r
+    }\r
+\r
+    @Override\r
+    public void init(IAdaptable adapter) throws DatabaseException {\r
+        // Initialize resource array if at all possible\r
+        ResourceArray ra = getResourceArray();\r
+        if (!ra.isEmpty())\r
+            updateCaches(true);\r
+    }\r
+\r
+    @Override\r
+    public void dispose() {\r
+        //System.out.println("dispose resource editor input: " + name);\r
+        // NOTE: this has to be done since Eclipse will cache these IEditorInput\r
+        // instances within EditorHistoryItem's that are stored in an EditorHistory\r
+        // instance. They are held by strong reference which means that the session\r
+        // cannot be collected if it is not nulled here.\r
+        resources = null;\r
+    }\r
+\r
+    @Override\r
+    public boolean exists() {\r
+        return exists;\r
+    }\r
+\r
+    @Override\r
+    public boolean exists(ReadGraph graph) throws DatabaseException {\r
+        for (Resource r : getResourceArray().resources)\r
+            if (!graph.hasStatement(r))\r
+                return false;\r
+        return true;\r
+    }\r
+\r
+    @Override\r
+    public Resource getResource() {\r
+        ResourceArray ra = getResourceArray();\r
+        return ra.isEmpty() ? null : ra.resources[0];\r
+    }\r
+\r
+    public ResourceArray getResourceArray0() throws DatabaseException {\r
+        ResourceArray ra = tryGetResourceArray();\r
+        if (!ra.isEmpty())\r
+            return ra;\r
+\r
+        Session s = ResourceInputs.peekSession();\r
+        if (s == null)\r
+            return ResourceArray.EMPTY;\r
+\r
+        ra = ResourceInputs.makeResourceArray( s, resourceIds );\r
+        this.resources = ResourceInputs.makeReference( ra );\r
+        return ra;\r
+    }\r
+\r
+    @Override\r
+    public ResourceArray getResourceArray() {\r
+        try {\r
+            return getResourceArray0();\r
+        } catch (DatabaseException e) {\r
+            ErrorLogger.defaultLogError(e);\r
+            return ResourceArray.EMPTY;\r
+        }\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see org.eclipse.ui.IEditorInput#getImageDescriptor()\r
+     */\r
+    @Override\r
+    public ImageDescriptor getImageDescriptor() {\r
+        return imageDesc;\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see org.eclipse.ui.IEditorInput#getName()\r
+     */\r
+    @Override\r
+    public String getName() {\r
+        return name;\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see org.eclipse.ui.IEditorInput#getToolTipText()\r
+     */\r
+    @Override\r
+    public String getToolTipText() {\r
+        return tooltip;\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see org.eclipse.ui.IEditorInput#getPersistable()\r
+     */\r
+    @Override\r
+    public IPersistableElement getPersistable() {\r
+        // Don't allow persistability when it's not possible.\r
+        if (!isPersistable())\r
+            return null;\r
+        return this;\r
+    }\r
+\r
+    protected boolean isPersistable() {\r
+        Session session = Simantics.peekSession();\r
+        if (session == null)\r
+            return false;\r
+        LifecycleSupport lc = session.peekService(LifecycleSupport.class);\r
+        if (lc == null)\r
+            return false;\r
+        if (lc.isClosed())\r
+            return false;\r
+        return true;\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see org.eclipse.ui.IPersistableElement#getFactoryId()\r
+     */\r
+    @Override\r
+    public String getFactoryId() {\r
+        return ResourceEditorInputFactory.getFactoryId();\r
+    }\r
+\r
+    /**\r
+     * Saves the state of the given resource editor input into the given memento.\r
+     *\r
+     * @param memento the storage area for element state\r
+     * @see org.eclipse.ui.IPersistable#saveState(org.eclipse.ui.IMemento)\r
+     */\r
+    @Override\r
+    public void saveState(IMemento memento) {\r
+        for (String id : resourceIds) {\r
+            IMemento child = memento.createChild(ResourceEditorInputFactory.TAG_RESOURCE_ID);\r
+            child.putTextData(id);\r
+        }\r
+        memento.putString(ResourceEditorInputFactory.TAG_EDITOR_ID, editorID);\r
+        memento.putString(ResourceEditorInputFactory.TAG_EXTERNAL_MEMENTO_ID, persistentStore.toString());\r
+    }\r
+\r
+    @Override\r
+    public int hashCode() {\r
+        final int prime = 31;\r
+        int result = 1;\r
+        result = prime * result + editorID.hashCode();\r
+        result = prime * result + ObjectUtils.hashCode(resourceIds);\r
+        return result;\r
+    }\r
+\r
+    @Override\r
+    public boolean equals(Object obj) {\r
+        if (this == obj)\r
+            return true;\r
+        if (obj == null)\r
+            return false;\r
+        if (getClass() != obj.getClass())\r
+            return false;\r
+        final ResourceEditorInput other = (ResourceEditorInput) obj;\r
+        if (!editorID.equals(other.editorID))\r
+            return false;\r
+        if (!ObjectUtils.objectEquals(resourceIds, other.resourceIds))\r
+            return false;\r
+        return true;\r
+    }\r
+\r
+    private void updateCaches(boolean sync) throws DatabaseException {\r
+        ReadRequest req = new ReadRequest() {\r
+            @Override\r
+            public void run(ReadGraph g) throws DatabaseException {\r
+                update(g);\r
+            }\r
+        };\r
+        Session s = ResourceInputs.getSession();\r
+        if (sync) {\r
+            s.syncRequest(req);\r
+        } else {\r
+            s.asyncRequest(req);\r
+        }\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see org.simantics.ui.workbench.IResourceEditorInput#update(org.simantics.db.Graph)\r
+     */\r
+    @Override\r
+    public void update(ReadGraph g) throws DatabaseException {\r
+        Resource r = getResource();\r
+        if (r == null)\r
+            return;\r
+\r
+        exists = g.hasStatement(r);\r
+        if (exists) {\r
+            name = g.syncRequest(new TitleRequest(editorID, this));\r
+            if (name == null)\r
+                name = NO_NAME;\r
+\r
+            tooltip = g.syncRequest(new ToolTipRequest(editorID, this));\r
+            if (tooltip == null)\r
+                tooltip = NO_NAME;\r
+\r
+            try {\r
+                ImageDescriptorProvider idp = g.adapt(r, ImageDescriptorProvider.class);\r
+                imageDesc = idp.get();\r
+            } catch (AdaptionException e) {\r
+                imageDesc = ImageDescriptor.getMissingImageDescriptor();\r
+            } catch (ProvisionException e) {\r
+                imageDesc = ImageDescriptor.getMissingImageDescriptor();\r
+                ErrorLogger.defaultLogError(e);\r
+            }\r
+        } else {\r
+            setNonExistant();\r
+        }\r
+    }\r
+\r
+    private void setNonExistant() {\r
+        exists = false;\r
+        tooltip = name = NO_NAME;\r
+        imageDesc = ImageDescriptor.getMissingImageDescriptor();\r
+    }\r
+\r
+    public IMemento getPersistentStore() {\r
+        return persistentStore;\r
+    }\r
+\r
+    @Override\r
+    public String toString() {\r
+        return getClass().getSimpleName() + " [name=" + getName() + ", resourceIds=" + resourceIds + ", resources=" + resources + "]";\r
+    }\r
+\r
+    private ResourceArray tryGetResourceArray() {\r
+        Reference<ResourceArray> ref = resources;\r
+        if (ref == null)\r
+            return ResourceArray.EMPTY;\r
+        ResourceArray ra = ref.get();\r
+        return ra == null ? ResourceArray.EMPTY : ra;\r
+    }\r
+\r
+}
\ No newline at end of file