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