1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.ui.workbench;
14 import java.lang.ref.Reference;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.List;
19 import org.eclipse.core.runtime.IAdaptable;
20 import org.eclipse.core.runtime.PlatformObject;
21 import org.eclipse.jface.resource.ImageDescriptor;
22 import org.eclipse.ui.IMemento;
23 import org.eclipse.ui.IPersistableElement;
24 import org.simantics.Simantics;
25 import org.simantics.db.ReadGraph;
26 import org.simantics.db.Resource;
27 import org.simantics.db.Session;
28 import org.simantics.db.common.ResourceArray;
29 import org.simantics.db.common.request.ReadRequest;
30 import org.simantics.db.exception.AdaptionException;
31 import org.simantics.db.exception.DatabaseException;
32 import org.simantics.db.service.LifecycleSupport;
33 import org.simantics.ui.icons.ImageDescriptorProvider;
34 import org.simantics.ui.workbench.editor.input.ResourceEditorInputMatchingStrategy;
35 import org.simantics.utils.ObjectUtils;
36 import org.simantics.utils.datastructures.cache.ProvisionException;
37 import org.simantics.utils.ui.ErrorLogger;
38 import org.simantics.utils.ui.workbench.StringMemento;
41 * A basic editor input for Simantics database {@link Resource} instances.
43 * Editor extensions requiring these as input should always use
44 * {@link ResourceEditorInputMatchingStrategy} as their matchingStrategy.
46 * @author Tuukka Lehtonen
48 * @see ResourceEditorInput2
49 * @see ResourceEditorInputMatchingStrategy
51 public class ResourceEditorInput extends PlatformObject implements IResourceEditorInput, IPersistableElement {
53 static final String NO_NAME = "(no name)";
55 private final String editorID;
57 private List<String> resourceIds;
59 private transient Reference<ResourceArray> resources;
61 private transient boolean exists;
63 private transient String name;
65 private transient String tooltip;
67 private transient ImageDescriptor imageDesc;
69 /** Persistent memento for external data */
70 private final StringMemento persistentStore = new StringMemento();
76 public ResourceEditorInput(String editorID, Resource r) {
77 this(editorID, new ResourceArray(r));
84 public ResourceEditorInput(String editorID, ResourceArray ra) {
86 throw new IllegalArgumentException("null editor id");
88 throw new IllegalArgumentException("null resource array");
90 throw new IllegalArgumentException("input resource array is empty, expected non-empty list");
91 for (Resource r : ra.resources)
93 throw new IllegalArgumentException("input resource array contains null resources: " + ra);
95 this.editorID = editorID;
96 this.resources = ResourceInputs.makeReference(ra);
97 this.resourceIds = ResourceInputs.getRandomAccessIds(ra);
104 * @param randomAccessResourceId
106 public ResourceEditorInput(String editorID, String randomAccessResourceId) {
107 this(editorID, Collections.singletonList(randomAccessResourceId));
112 * @param randomAccessResourceId a non-empty list of random access resource
114 * @throws IllegalArgumentException if the specified random access id list
115 * is <code>null</code> or empty
117 public ResourceEditorInput(String editorID, List<String> randomAccessResourceId) {
118 if (randomAccessResourceId == null)
119 throw new IllegalArgumentException("null resource id list");
120 if (randomAccessResourceId.isEmpty())
121 throw new IllegalArgumentException("input resource id list is empty, expected non-empty list");
122 for (String id : randomAccessResourceId)
124 throw new IllegalArgumentException("input resource id list contains null IDs: " + randomAccessResourceId);
126 this.editorID = editorID;
127 if (editorID == null)
129 this.resourceIds = Collections.unmodifiableList(new ArrayList<String>(randomAccessResourceId));
130 this.resources = ResourceInputs.makeReference(ResourceArray.EMPTY);
136 public void init(IAdaptable adapter) throws DatabaseException {
137 // Initialize resource array if at all possible
138 ResourceArray ra = getResourceArray();
144 public void dispose() {
145 //System.out.println("dispose resource editor input: " + name);
146 // NOTE: this has to be done since Eclipse will cache these IEditorInput
147 // instances within EditorHistoryItem's that are stored in an EditorHistory
148 // instance. They are held by strong reference which means that the session
149 // cannot be collected if it is not nulled here.
154 public boolean exists() {
159 public boolean exists(ReadGraph graph) throws DatabaseException {
160 for (Resource r : getResourceArray().resources)
161 if (!graph.hasStatement(r))
167 public Resource getResource() {
168 ResourceArray ra = getResourceArray();
169 return ra.isEmpty() ? null : ra.resources[0];
172 public ResourceArray getResourceArray0() throws DatabaseException {
173 ResourceArray ra = tryGetResourceArray();
177 Session s = ResourceInputs.peekSession();
179 return ResourceArray.EMPTY;
181 ra = ResourceInputs.makeResourceArray( s, resourceIds );
182 this.resources = ResourceInputs.makeReference( ra );
187 public ResourceArray getResourceArray() {
189 return getResourceArray0();
190 } catch (DatabaseException e) {
191 ErrorLogger.defaultLogError(e);
192 return ResourceArray.EMPTY;
197 * @see org.eclipse.ui.IEditorInput#getImageDescriptor()
200 public ImageDescriptor getImageDescriptor() {
205 * @see org.eclipse.ui.IEditorInput#getName()
208 public String getName() {
213 * @see org.eclipse.ui.IEditorInput#getToolTipText()
216 public String getToolTipText() {
221 * @see org.eclipse.ui.IEditorInput#getPersistable()
224 public IPersistableElement getPersistable() {
225 // Don't allow persistability when it's not possible.
226 if (!isPersistable())
231 protected boolean isPersistable() {
232 Session session = Simantics.peekSession();
235 LifecycleSupport lc = session.peekService(LifecycleSupport.class);
244 * @see org.eclipse.ui.IPersistableElement#getFactoryId()
247 public String getFactoryId() {
248 return ResourceEditorInputFactory.getFactoryId();
252 * Saves the state of the given resource editor input into the given memento.
254 * @param memento the storage area for element state
255 * @see org.eclipse.ui.IPersistable#saveState(org.eclipse.ui.IMemento)
258 public void saveState(IMemento memento) {
259 for (String id : resourceIds) {
260 IMemento child = memento.createChild(ResourceEditorInputFactory.TAG_RESOURCE_ID);
261 child.putTextData(id);
263 memento.putString(ResourceEditorInputFactory.TAG_EDITOR_ID, editorID);
264 memento.putString(ResourceEditorInputFactory.TAG_EXTERNAL_MEMENTO_ID, persistentStore.toString());
268 public int hashCode() {
269 final int prime = 31;
271 result = prime * result + editorID.hashCode();
272 result = prime * result + ObjectUtils.hashCode(resourceIds);
277 public boolean equals(Object obj) {
282 if (getClass() != obj.getClass())
284 final ResourceEditorInput other = (ResourceEditorInput) obj;
285 if (!editorID.equals(other.editorID))
287 if (!ObjectUtils.objectEquals(resourceIds, other.resourceIds))
292 private void updateCaches(boolean sync) throws DatabaseException {
293 ReadRequest req = new ReadRequest() {
295 public void run(ReadGraph g) throws DatabaseException {
299 Session s = ResourceInputs.getSession();
308 * @see org.simantics.ui.workbench.IResourceEditorInput#update(org.simantics.db.Graph)
311 public void update(ReadGraph g) throws DatabaseException {
312 Resource r = getResource();
316 exists = g.hasStatement(r);
318 name = g.syncRequest(new TitleRequest(editorID, this));
322 tooltip = g.syncRequest(new ToolTipRequest(editorID, this));
327 ImageDescriptorProvider idp = g.adapt(r, ImageDescriptorProvider.class);
328 imageDesc = idp.get();
329 } catch (AdaptionException e) {
330 imageDesc = ImageDescriptor.getMissingImageDescriptor();
331 } catch (ProvisionException e) {
332 imageDesc = ImageDescriptor.getMissingImageDescriptor();
333 ErrorLogger.defaultLogError(e);
340 private void setNonExistant() {
342 tooltip = name = NO_NAME;
343 imageDesc = ImageDescriptor.getMissingImageDescriptor();
346 public IMemento getPersistentStore() {
347 return persistentStore;
351 public String toString() {
352 return getClass().getSimpleName() + " [name=" + getName() + ", resourceIds=" + resourceIds + ", resources=" + resources + "]";
355 private ResourceArray tryGetResourceArray() {
356 Reference<ResourceArray> ref = resources;
358 return ResourceArray.EMPTY;
359 ResourceArray ra = ref.get();
360 return ra == null ? ResourceArray.EMPTY : ra;