Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Piskarev2017-04-19 14:47:14 +0000
committerVladimir Piskarev2017-04-19 14:47:14 +0000
commit7c0577929394ec32fd550b23733c407cee339795 (patch)
treed849413d02c766b102fdc0f5a1dd79e920fe1627
parent3dd93c9b31c6ba9be43e34fb59323b94c1a206f6 (diff)
downloadorg.eclipse.handly-7c0577929394ec32fd550b23733c407cee339795.tar.gz
org.eclipse.handly-7c0577929394ec32fd550b23733c407cee339795.tar.xz
org.eclipse.handly-7c0577929394ec32fd550b23733c407cee339795.zip
Bug 515461 - Extract *ImplExtension interfaces for elements
-rw-r--r--org.eclipse.handly.examples.basic.ui.tests/src/org/eclipse/handly/internal/examples/basic/ui/model/FooWorkingCopyTest.java9
-rw-r--r--org.eclipse.handly.examples.basic.ui/src/org/eclipse/handly/internal/examples/basic/ui/model/FooDeltaProcessor.java8
-rw-r--r--org.eclipse.handly.examples.javamodel/src/org/eclipse/handly/internal/examples/javamodel/DeltaProcessor.java8
-rw-r--r--org.eclipse.handly/src/org/eclipse/handly/model/impl/Element.java252
-rw-r--r--org.eclipse.handly/src/org/eclipse/handly/model/impl/ElementCache.java9
-rw-r--r--org.eclipse.handly/src/org/eclipse/handly/model/impl/ElementDifferencer.java9
-rw-r--r--org.eclipse.handly/src/org/eclipse/handly/model/impl/ElementManager.java6
-rw-r--r--org.eclipse.handly/src/org/eclipse/handly/model/impl/IElementImplExtension.java201
-rw-r--r--org.eclipse.handly/src/org/eclipse/handly/model/impl/ISourceConstructImplExtension.java40
-rw-r--r--org.eclipse.handly/src/org/eclipse/handly/model/impl/SourceConstruct.java23
-rw-r--r--org.eclipse.handly/src/org/eclipse/handly/model/impl/StructureHelper.java27
11 files changed, 341 insertions, 251 deletions
diff --git a/org.eclipse.handly.examples.basic.ui.tests/src/org/eclipse/handly/internal/examples/basic/ui/model/FooWorkingCopyTest.java b/org.eclipse.handly.examples.basic.ui.tests/src/org/eclipse/handly/internal/examples/basic/ui/model/FooWorkingCopyTest.java
index 6795da77..c1b9a05d 100644
--- a/org.eclipse.handly.examples.basic.ui.tests/src/org/eclipse/handly/internal/examples/basic/ui/model/FooWorkingCopyTest.java
+++ b/org.eclipse.handly.examples.basic.ui.tests/src/org/eclipse/handly/internal/examples/basic/ui/model/FooWorkingCopyTest.java
@@ -10,7 +10,8 @@
*******************************************************************************/
package org.eclipse.handly.internal.examples.basic.ui.model;
-import static org.eclipse.handly.context.Contexts.*;
+import static org.eclipse.handly.context.Contexts.EMPTY_CONTEXT;
+import static org.eclipse.handly.context.Contexts.of;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
@@ -26,7 +27,7 @@ import org.eclipse.handly.examples.basic.ui.model.IFooProject;
import org.eclipse.handly.examples.basic.ui.model.IFooVar;
import org.eclipse.handly.junit.WorkspaceTestCase;
import org.eclipse.handly.model.ISourceElementInfo;
-import org.eclipse.handly.model.impl.Element;
+import org.eclipse.handly.model.impl.IElementImplExtension;
import org.eclipse.handly.model.impl.SourceFile;
import org.eclipse.handly.model.impl.WorkingCopyInfo;
import org.eclipse.handly.util.TextRange;
@@ -252,9 +253,9 @@ public class FooWorkingCopyTest
{
IFooDef def = workingCopy.getDef("f", 0);
assertTrue(def.exists());
- ((Element)def).hClose();
+ ((IElementImplExtension)def).hClose();
assertNotNull("non-openable elements cannot be closed",
- ((Element)def).hPeekAtBody());
+ ((IElementImplExtension)def).hPeekAtBody());
}
};
// non-openable elements cannot be closed, in working copy or not
diff --git a/org.eclipse.handly.examples.basic.ui/src/org/eclipse/handly/internal/examples/basic/ui/model/FooDeltaProcessor.java b/org.eclipse.handly.examples.basic.ui/src/org/eclipse/handly/internal/examples/basic/ui/model/FooDeltaProcessor.java
index fcb06a7e..5ac9d2df 100644
--- a/org.eclipse.handly.examples.basic.ui/src/org/eclipse/handly/internal/examples/basic/ui/model/FooDeltaProcessor.java
+++ b/org.eclipse.handly.examples.basic.ui/src/org/eclipse/handly/internal/examples/basic/ui/model/FooDeltaProcessor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014, 2016 1C-Soft LLC and others.
+ * Copyright (c) 2014, 2017 1C-Soft LLC and others.
* 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
@@ -36,8 +36,8 @@ import org.eclipse.handly.examples.basic.ui.model.IFooProject;
import org.eclipse.handly.model.IElement;
import org.eclipse.handly.model.IElementDelta;
import org.eclipse.handly.model.impl.Body;
-import org.eclipse.handly.model.impl.Element;
import org.eclipse.handly.model.impl.ElementDelta;
+import org.eclipse.handly.model.impl.IElementImplExtension;
/**
* This class is used by the <code>FooModelManager</code> to convert
@@ -420,12 +420,12 @@ class FooDeltaProcessor
private static Body findBody(IFooElement element)
{
- return (Body)((Element)element).hFindBody();
+ return (Body)((IElementImplExtension)element).hFindBody();
}
private static void close(IFooElement element)
{
- ((Element)element).hClose();
+ ((IElementImplExtension)element).hClose();
}
private static IResource getResource(IPath fullPath, int resourceType)
diff --git a/org.eclipse.handly.examples.javamodel/src/org/eclipse/handly/internal/examples/javamodel/DeltaProcessor.java b/org.eclipse.handly.examples.javamodel/src/org/eclipse/handly/internal/examples/javamodel/DeltaProcessor.java
index 49d7bf20..a26aa802 100644
--- a/org.eclipse.handly.examples.javamodel/src/org/eclipse/handly/internal/examples/javamodel/DeltaProcessor.java
+++ b/org.eclipse.handly.examples.javamodel/src/org/eclipse/handly/internal/examples/javamodel/DeltaProcessor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2015, 2016 1C-Soft LLC.
+ * Copyright (c) 2015, 2017 1C-Soft LLC.
* 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
@@ -32,8 +32,8 @@ import org.eclipse.handly.examples.javamodel.JavaModelCore;
import org.eclipse.handly.model.IElement;
import org.eclipse.handly.model.IElementDelta;
import org.eclipse.handly.model.impl.Body;
-import org.eclipse.handly.model.impl.Element;
import org.eclipse.handly.model.impl.ElementDelta;
+import org.eclipse.handly.model.impl.IElementImplExtension;
import org.eclipse.jdt.core.IClasspathEntry;
/**
@@ -605,12 +605,12 @@ class DeltaProcessor
private static Body findBody(IJavaElement element)
{
- return (Body)((Element)element).hFindBody();
+ return (Body)((IElementImplExtension)element).hFindBody();
}
private static void close(IJavaElement element)
{
- ((Element)element).hClose();
+ ((IElementImplExtension)element).hClose();
}
private static IResource getResource(IPath fullPath, int resourceType)
diff --git a/org.eclipse.handly/src/org/eclipse/handly/model/impl/Element.java b/org.eclipse.handly/src/org/eclipse/handly/model/impl/Element.java
index 99aeef92..94fb3491 100644
--- a/org.eclipse.handly/src/org/eclipse/handly/model/impl/Element.java
+++ b/org.eclipse.handly/src/org/eclipse/handly/model/impl/Element.java
@@ -53,7 +53,7 @@ import org.eclipse.handly.util.ToStringOptions.FormatStyle;
*/
public abstract class Element
extends PlatformObject
- implements IElementImpl, IModelManager.Provider
+ implements IElementImplExtension, IModelManager.Provider
{
private final IElement parent;
private final String name;
@@ -162,99 +162,87 @@ public abstract class Element
return hChildren(hBody());
}
- /**
- * Returns the cached body for this element, or <code>null</code>
- * if none.
- *
- * @return the cached body for this element, or <code>null</code>
- * if none
- */
+ @Override
+ public IElement[] hChildren(Object body)
+ {
+ return ((Body)body).getChildren();
+ }
+
+ @Override
public Object hFindBody()
{
return hElementManager().get(this);
}
- /**
- * Returns the cached body for this element without disturbing
- * cache ordering, or <code>null</code> if none.
- *
- * @return the cached body for this element, or <code>null</code>
- * if none
- */
+ @Override
public Object hPeekAtBody()
{
return hElementManager().peek(this);
}
/**
- * Closes this element iff the current state of this element permits closing.
- * <p>
- * Closing of an element removes its body from the body cache. In general,
- * closing of a parent element also closes its children. If the current state
- * of an open child element does not permit closing, the child element
- * remains open, which generally does not prevent its parent from closing.
- * Closing of an element which is not open has no effect.
- * </p>
+ * {@inheritDoc}
* <p>
- * Shortcut to <code>hClose(EMPTY_CONTEXT)</code>.
+ * This implementation creates and initializes bodies for this element,
+ * its ancestors and its children as necessary and then atomically puts
+ * them into the body cache.
* </p>
- *
- * @see #hClose(IContext)
+ * @throws CoreException {@inheritDoc}
+ * @throws OperationCanceledException {@inheritDoc}
*/
- public final void hClose()
- {
- hClose(EMPTY_CONTEXT);
- }
-
- /**
- * Closing hint.
- */
- public enum CloseHint
+ @Override
+ public Object hOpen(IContext context, IProgressMonitor monitor)
+ throws CoreException
{
- /**
- * Closing due to cache overflow.
- */
- CACHE_OVERFLOW,
- /**
- * Closing due to parent closing.
- */
- PARENT_CLOSING
+ if (monitor == null)
+ monitor = new NullProgressMonitor();
+ ElementManager elementManager = hElementManager();
+ boolean hadTemporaryCache = elementManager.hasTemporaryCache();
+ try
+ {
+ Map<IElement, Object> newElements =
+ elementManager.getTemporaryCache();
+ hGenerateBodies(with(of(NEW_ELEMENTS, newElements), context),
+ monitor);
+ Object body = newElements.get(this);
+ if (body == null)
+ {
+ // the openable parent did not create a body for this element
+ throw hDoesNotExistException();
+ }
+ if (monitor.isCanceled())
+ throw new OperationCanceledException();
+ if (!hadTemporaryCache)
+ {
+ if (context.getOrDefault(FORCE_OPEN))
+ elementManager.put(this, newElements);
+ else
+ {
+ Object existingBody = elementManager.putIfAbsent(this,
+ newElements);
+ if (existingBody != null)
+ body = existingBody;
+ }
+ }
+ return body;
+ }
+ finally
+ {
+ if (!hadTemporaryCache)
+ {
+ elementManager.resetTemporaryCache();
+ }
+ }
}
/**
- * Close hint property.
- * @see #hClose(IContext)
- */
- public static final Property<CloseHint> CLOSE_HINT = Property.get(
- Element.class.getName() + ".closeHint", //$NON-NLS-1$
- CloseHint.class);
-
- /**
- * Closes this element iff the current state of this element permits closing
- * according to options specified in the given context.
- * <p>
- * Closing of an element removes its body from the body cache. In general,
- * closing of a parent element also closes its children. If the current state
- * of an open child element does not permit closing, the child element
- * remains open, which generally does not prevent its parent from closing.
- * Closing of an element which is not open has no effect.
- * </p>
- * <p>
- * Implementations are encouraged to support the following standard options,
- * which may be specified in the given context:
- * </p>
- * <ul>
- * <li>
- * {@link #CLOSE_HINT} - Closing hint.
- * </li>
- * </ul>
+ * {@inheritDoc}
* <p>
* If the current state of this element permits closing, this implementation
* invokes {@link #hRemove(IContext)} method, which closes this element.
* </p>
- *
- * @param context the operation context (not <code>null</code>)
*/
+ @Override
public void hClose(IContext context)
{
CloseHint hint = context.get(CLOSE_HINT);
@@ -444,128 +432,6 @@ public abstract class Element
IProgressMonitor monitor) throws CoreException;
/**
- * Returns the cached body for this element. If this element is not
- * already present in the body cache, its body will be created,
- * initialized, and put in the cache.
- *
- * @return the cached body for this element (never <code>null</code>)
- * @throws CoreException if this element does not exist or if an
- * exception occurs while accessing its corresponding resource
- */
- protected final Object hBody() throws CoreException
- {
- return hBody(EMPTY_CONTEXT, null);
- }
-
- /**
- * Returns the cached body for this element. If this element is not
- * already present in the body cache, its body will be created,
- * initialized, and put in the cache.
- *
- * @param context the operation context (not <code>null</code>)
- * @param monitor a progress monitor, or <code>null</code>
- * if progress reporting is not desired
- * @return the cached body for this element (never <code>null</code>)
- * @throws CoreException if this element does not exist or if an
- * exception occurs while accessing its corresponding resource
- * @throws OperationCanceledException if this method is canceled
- */
- protected final Object hBody(IContext context, IProgressMonitor monitor)
- throws CoreException
- {
- Object body = hFindBody();
- if (body != null)
- return body;
- return hOpen(context, monitor);
- }
-
- /**
- * Given a body, returns the immediate children of this element.
- *
- * @param body the body corresponding to this element
- * (never <code>null</code>)
- * @return the immediate children of this element (not <code>null</code>)
- */
- protected IElement[] hChildren(Object body)
- {
- return ((Body)body).getChildren();
- }
-
- /**
- * Indicates whether to forcibly reopen this element if it is already open
- * (i.e. already present in the body cache). Default value: <code>false</code>.
- */
- static final Property<Boolean> FORCE_OPEN = Property.get(
- Element.class.getName() + ".forceOpen", Boolean.class).withDefault( //$NON-NLS-1$
- false);
-
- /**
- * Creates and initializes bodies for this element, its ancestors and its
- * children as necessary and then atomically puts them into the body cache.
- * Returns the cached body for this element.
- * <p>
- * The following context options influence the operation's behavior:
- * </p>
- * <ul>
- * <li>
- * {@link #FORCE_OPEN} - Indicates whether to forcibly reopen this element
- * if it is already open (i.e. already present in the body cache).
- * </li>
- * </ul>
- *
- * @param context the operation context (not <code>null</code>)
- * @param monitor a progress monitor, or <code>null</code>
- * if progress reporting is not desired
- * @return the cached body for this element (never <code>null</code>)
- * @throws CoreException if this element does not exist or if an
- * exception occurs while accessing its corresponding resource
- * @throws OperationCanceledException if this method is canceled
- */
- final Object hOpen(IContext context, IProgressMonitor monitor)
- throws CoreException
- {
- if (monitor == null)
- monitor = new NullProgressMonitor();
- ElementManager elementManager = hElementManager();
- boolean hadTemporaryCache = elementManager.hasTemporaryCache();
- try
- {
- Map<IElement, Object> newElements =
- elementManager.getTemporaryCache();
- hGenerateBodies(with(of(NEW_ELEMENTS, newElements), context),
- monitor);
- Object body = newElements.get(this);
- if (body == null)
- {
- // the openable parent did not create a body for this element
- throw hDoesNotExistException();
- }
- if (monitor.isCanceled())
- throw new OperationCanceledException();
- if (!hadTemporaryCache)
- {
- if (context.getOrDefault(FORCE_OPEN))
- elementManager.put(this, newElements);
- else
- {
- Object existingBody = elementManager.putIfAbsent(this,
- newElements);
- if (existingBody != null)
- body = existingBody;
- }
- }
- return body;
- }
- finally
- {
- if (!hadTemporaryCache)
- {
- elementManager.resetTemporaryCache();
- }
- }
- }
-
- /**
* Returns whether this element is "openable".
* <p>
* An openable element knows how to open itself on demand (i.e. initialize
diff --git a/org.eclipse.handly/src/org/eclipse/handly/model/impl/ElementCache.java b/org.eclipse.handly/src/org/eclipse/handly/model/impl/ElementCache.java
index ae18b735..78792b1e 100644
--- a/org.eclipse.handly/src/org/eclipse/handly/model/impl/ElementCache.java
+++ b/org.eclipse.handly/src/org/eclipse/handly/model/impl/ElementCache.java
@@ -13,8 +13,8 @@
package org.eclipse.handly.model.impl;
import static org.eclipse.handly.context.Contexts.of;
-import static org.eclipse.handly.model.impl.Element.CLOSE_HINT;
-import static org.eclipse.handly.model.impl.Element.CloseHint.CACHE_OVERFLOW;
+import static org.eclipse.handly.model.impl.IElementImplExtension.CLOSE_HINT;
+import static org.eclipse.handly.model.impl.IElementImplExtension.CloseHint.CACHE_OVERFLOW;
import static org.eclipse.handly.util.ToStringOptions.FORMAT_STYLE;
import static org.eclipse.handly.util.ToStringOptions.INDENT_POLICY;
import static org.eclipse.handly.util.ToStringOptions.FormatStyle.MEDIUM;
@@ -95,13 +95,14 @@ public class ElementCache
*/
protected int getChildCount(IElement element, Object body)
{
- return ((Element)element).hChildren(body).length;
+ return ((IElementImplExtension)element).hChildren(body).length;
}
@Override
protected boolean close(LruCacheEntry<IElement, Object> entry)
{
- ((Element)entry.key).hClose(of(CLOSE_HINT, CACHE_OVERFLOW));
+ ((IElementImplExtension)entry.key).hClose(of(CLOSE_HINT,
+ CACHE_OVERFLOW));
// closing of an element removes it from the cache, so...
return false; // ...no need to remove the cache entry after close
}
diff --git a/org.eclipse.handly/src/org/eclipse/handly/model/impl/ElementDifferencer.java b/org.eclipse.handly/src/org/eclipse/handly/model/impl/ElementDifferencer.java
index 862f9084..3e9e4d0a 100644
--- a/org.eclipse.handly/src/org/eclipse/handly/model/impl/ElementDifferencer.java
+++ b/org.eclipse.handly/src/org/eclipse/handly/model/impl/ElementDifferencer.java
@@ -211,7 +211,7 @@ public class ElementDifferencer
Object body;
try
{
- body = ((Element)element).hBody();
+ body = ((IElementImplExtension)element).hBody();
}
catch (CoreException e)
{
@@ -220,7 +220,7 @@ public class ElementDifferencer
recordBody(body, element);
- IElement[] children = ((Element)element).hChildren(body);
+ IElement[] children = ((IElementImplExtension)element).hChildren(body);
insertPositions(children, false);
for (IElement child : children)
{
@@ -302,7 +302,7 @@ public class ElementDifferencer
Object newBody;
try
{
- newBody = ((Element)newElement).hBody();
+ newBody = ((IElementImplExtension)newElement).hBody();
}
catch (CoreException e)
{
@@ -311,7 +311,8 @@ public class ElementDifferencer
findContentChange(oldBody, newBody, newElement);
- for (IElement child : ((Element)newElement).hChildren(newBody))
+ for (IElement child : ((IElementImplExtension)newElement).hChildren(
+ newBody))
{
findAdditions(child, depth + 1);
}
diff --git a/org.eclipse.handly/src/org/eclipse/handly/model/impl/ElementManager.java b/org.eclipse.handly/src/org/eclipse/handly/model/impl/ElementManager.java
index cd5b6e00..fadc250d 100644
--- a/org.eclipse.handly/src/org/eclipse/handly/model/impl/ElementManager.java
+++ b/org.eclipse.handly/src/org/eclipse/handly/model/impl/ElementManager.java
@@ -12,8 +12,8 @@ package org.eclipse.handly.model.impl;
import static org.eclipse.handly.context.Contexts.EMPTY_CONTEXT;
import static org.eclipse.handly.context.Contexts.of;
-import static org.eclipse.handly.model.impl.Element.CLOSE_HINT;
-import static org.eclipse.handly.model.impl.Element.CloseHint.PARENT_CLOSING;
+import static org.eclipse.handly.model.impl.IElementImplExtension.CLOSE_HINT;
+import static org.eclipse.handly.model.impl.IElementImplExtension.CloseHint.PARENT_CLOSING;
import java.util.HashMap;
import java.util.Map;
@@ -90,7 +90,7 @@ public class ElementManager
*/
protected void close(IElement element, IContext context)
{
- ((Element)element).hClose(context);
+ ((IElementImplExtension)element).hClose(context);
}
/**
diff --git a/org.eclipse.handly/src/org/eclipse/handly/model/impl/IElementImplExtension.java b/org.eclipse.handly/src/org/eclipse/handly/model/impl/IElementImplExtension.java
new file mode 100644
index 00000000..350b2753
--- /dev/null
+++ b/org.eclipse.handly/src/org/eclipse/handly/model/impl/IElementImplExtension.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2017 1C-Soft LLC and others.
+ * 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:
+ * Vladimir Piskarev (1C) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.handly.model.impl;
+
+import static org.eclipse.handly.context.Contexts.EMPTY_CONTEXT;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.handly.context.IContext;
+import org.eclipse.handly.model.IElement;
+import org.eclipse.handly.util.Property;
+
+/**
+ * Extension of {@link IElementImpl} that introduces the notion of the element's
+ * cached body. {@link IElement}s may implement this interface.
+ *
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface IElementImplExtension
+ extends IElementImpl
+{
+ @Override
+ default IElement[] hChildren() throws CoreException
+ {
+ return hChildren(hBody());
+ }
+
+ /**
+ * Given a body, returns the immediate children of this element.
+ *
+ * @param body the body corresponding to this element
+ * (never <code>null</code>)
+ * @return the immediate children of this element (not <code>null</code>)
+ */
+ IElement[] hChildren(Object body);
+
+ /**
+ * Returns the cached body for this element, or <code>null</code>
+ * if none.
+ *
+ * @return the cached body for this element, or <code>null</code>
+ * if none
+ */
+ Object hFindBody();
+
+ /**
+ * Returns the cached body for this element without disturbing
+ * cache ordering, or <code>null</code> if none.
+ *
+ * @return the cached body for this element, or <code>null</code>
+ * if none
+ */
+ Object hPeekAtBody();
+
+ /**
+ * Returns the cached body for this element. If this element is not
+ * already present in the body cache, it will be {@link #hOpen(IContext,
+ * IProgressMonitor) opened}. Shortcut to <code>hBody(EMPTY_CONTEXT, null)</code>.
+ *
+ * @return the cached body for this element (never <code>null</code>)
+ * @throws CoreException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ */
+ default Object hBody() throws CoreException
+ {
+ return hBody(EMPTY_CONTEXT, null);
+ }
+
+ /**
+ * Returns the cached body for this element. If this element is not
+ * already present in the body cache, it will be {@link #hOpen(IContext,
+ * IProgressMonitor) opened} according to options specified in the given
+ * context.
+ *
+ * @param context the operation context (not <code>null</code>)
+ * @param monitor a progress monitor, or <code>null</code>
+ * if progress reporting is not desired
+ * @return the cached body for this element (never <code>null</code>)
+ * @throws CoreException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @throws OperationCanceledException if this method is canceled
+ */
+ default Object hBody(IContext context, IProgressMonitor monitor)
+ throws CoreException
+ {
+ Object body = hFindBody();
+ if (body != null)
+ return body;
+ return hOpen(context, monitor);
+ }
+
+ /**
+ * Indicates whether to forcibly reopen this element if it is already open
+ * (i.e. already present in the body cache). Default value: <code>false</code>.
+ * @see #hOpen(IContext, IProgressMonitor)
+ */
+ Property<Boolean> FORCE_OPEN = Property.get(
+ IElementImplExtension.class.getName() + ".forceOpen", //$NON-NLS-1$
+ Boolean.class).withDefault(false);
+
+ /**
+ * Makes sure this element is open, i.e. it exists and is present in the
+ * body cache. Performs atomically. Returns the cached body for this element.
+ * <p>
+ * Implementations are encouraged to support the following standard options,
+ * which may be specified in the given context:
+ * </p>
+ * <ul>
+ * <li>
+ * {@link #FORCE_OPEN} - Indicates whether to forcibly reopen this element
+ * if it is already open (i.e. already present in the body cache).
+ * </li>
+ * </ul>
+ *
+ * @param context the operation context (not <code>null</code>)
+ * @param monitor a progress monitor, or <code>null</code>
+ * if progress reporting is not desired
+ * @return the cached body for this element (never <code>null</code>)
+ * @throws CoreException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @throws OperationCanceledException if this method is canceled
+ */
+ Object hOpen(IContext context, IProgressMonitor monitor)
+ throws CoreException;
+
+ /**
+ * Closes this element iff the current state of this element permits closing.
+ * <p>
+ * Closing of an element removes its body from the body cache. In general,
+ * closing of a parent element also closes its children. If the current state
+ * of an open child element does not permit closing, the child element
+ * remains open, which generally does not prevent its parent from closing.
+ * Closing of an element which is not open has no effect.
+ * </p>
+ * <p>
+ * Shortcut to <code>hClose(EMPTY_CONTEXT)</code>.
+ * </p>
+ *
+ * @see #hClose(IContext)
+ */
+ default void hClose()
+ {
+ hClose(EMPTY_CONTEXT);
+ }
+
+ /**
+ * Closing hint.
+ */
+ enum CloseHint
+ {
+ /**
+ * Closing due to cache overflow.
+ */
+ CACHE_OVERFLOW,
+ /**
+ * Closing due to parent closing.
+ */
+ PARENT_CLOSING
+ }
+
+ /**
+ * Close hint property.
+ * @see #hClose(IContext)
+ */
+ Property<CloseHint> CLOSE_HINT = Property.get(
+ IElementImplExtension.class.getName() + ".closeHint", //$NON-NLS-1$
+ CloseHint.class);
+
+ /**
+ * Closes this element iff the current state of this element permits closing
+ * according to options specified in the given context.
+ * <p>
+ * Closing of an element removes its body from the body cache. In general,
+ * closing of a parent element also closes its children. If the current state
+ * of an open child element does not permit closing, the child element
+ * remains open, which generally does not prevent its parent from closing.
+ * Closing of an element which is not open has no effect.
+ * </p>
+ * <p>
+ * Implementations are encouraged to support the following standard options,
+ * which may be specified in the given context:
+ * </p>
+ * <ul>
+ * <li>
+ * {@link #CLOSE_HINT} - Closing hint.
+ * </li>
+ * </ul>
+ *
+ * @param context the operation context (not <code>null</code>)
+ */
+ void hClose(IContext context);
+}
diff --git a/org.eclipse.handly/src/org/eclipse/handly/model/impl/ISourceConstructImplExtension.java b/org.eclipse.handly/src/org/eclipse/handly/model/impl/ISourceConstructImplExtension.java
new file mode 100644
index 00000000..17f87e33
--- /dev/null
+++ b/org.eclipse.handly/src/org/eclipse/handly/model/impl/ISourceConstructImplExtension.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2017 1C-Soft LLC and others.
+ * 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:
+ * Vladimir Piskarev (1C) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.handly.model.impl;
+
+/**
+ * Extension of {@link ISourceConstructImpl} that introduces the notion of
+ * the element's occurrence count. {@code ISourceConstruct}s may implement
+ * this interface.
+ *
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface ISourceConstructImplExtension
+ extends ISourceConstructImpl
+{
+ /**
+ * Returns the count used to uniquely identify this element in the case
+ * that a duplicate named element exists. The occurrence count starts at 1
+ * (thus the first occurrence is occurrence 1, not occurrence 0).
+ *
+ * @return the occurrence count for this element
+ */
+ int hOccurrenceCount();
+
+ /**
+ * Increments the occurrence count of this element.
+ * <p>
+ * This method is intended to be used only when building structure of
+ * a source file to distinguish source constructs with duplicate names.
+ * </p>
+ */
+ void hIncrementOccurrenceCount();
+}
diff --git a/org.eclipse.handly/src/org/eclipse/handly/model/impl/SourceConstruct.java b/org.eclipse.handly/src/org/eclipse/handly/model/impl/SourceConstruct.java
index 1bf042ac..67f9b321 100644
--- a/org.eclipse.handly/src/org/eclipse/handly/model/impl/SourceConstruct.java
+++ b/org.eclipse.handly/src/org/eclipse/handly/model/impl/SourceConstruct.java
@@ -20,7 +20,7 @@ import org.eclipse.handly.model.IElement;
*/
public abstract class SourceConstruct
extends SourceElement
- implements ISourceConstructImpl
+ implements ISourceConstructImplExtension
{
private int occurrenceCount = 1;
@@ -48,29 +48,14 @@ public abstract class SourceConstruct
&& occurrenceCount == ((SourceConstruct)obj).occurrenceCount;
}
- /**
- * Returns the count used to uniquely identify this element in the case
- * that a duplicate named element exists. The occurrence count starts at 1
- * (thus the first occurrence is occurrence 1, not occurrence 0).
- *
- * @return the occurrence count for this element
- */
+ @Override
public final int hOccurrenceCount()
{
return occurrenceCount;
}
- /**
- * Increments the occurrence count of this element.
- * <p>
- * This method is intended to be used only when building structure of
- * a source file to distinguish source constructs with duplicate names.
- * </p>
- *
- * @see #hOccurrenceCount()
- * @see StructureHelper
- */
- public final void hIncrementOccurrenceCount()
+ @Override
+ public void hIncrementOccurrenceCount()
{
occurrenceCount++;
}
diff --git a/org.eclipse.handly/src/org/eclipse/handly/model/impl/StructureHelper.java b/org.eclipse.handly/src/org/eclipse/handly/model/impl/StructureHelper.java
index 0d39bfc4..a271128e 100644
--- a/org.eclipse.handly/src/org/eclipse/handly/model/impl/StructureHelper.java
+++ b/org.eclipse.handly/src/org/eclipse/handly/model/impl/StructureHelper.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014, 2016 1C-Soft LLC and others.
+ * Copyright (c) 2014, 2017 1C-Soft LLC and others.
* 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
@@ -19,15 +19,12 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.handly.context.IContext;
import org.eclipse.handly.model.Elements;
import org.eclipse.handly.model.IElement;
/**
- * A helper class for building the structure of {@link Element#hIsOpenable()
- * openable} elements that have non-openable children. Typically, this class
- * is utilized for building the structure of source files.
+ * A helper class for building a subtree of elements. Typically, this class
+ * is used when building the entire structure of a source file.
* <p>
* The structure is being created as calls to {@link #addChild(Body, IElement,
* Object)} are made on the helper. Make sure to complete initialization of each
@@ -37,8 +34,6 @@ import org.eclipse.handly.model.IElement;
* Clients can use this class as it stands or subclass it
* as circumstances warrant.
* </p>
- *
- * @see Element#hBuildStructure(IContext, IProgressMonitor)
*/
public class StructureHelper
{
@@ -74,8 +69,7 @@ public class StructureHelper
* @param parentBody the body of the parent element (not <code>null</code>)
* @param child the handle for the child element (not <code>null</code>)
* @param childBody the body for the child element, or <code>null</code>
- * if no body is to be associated with the child element (e.g. if the
- * child is an {@link Element#hIsOpenable() openable} element)
+ * if no body is to be associated with the child element
*/
public void addChild(Body parentBody, IElement child, Object childBody)
{
@@ -118,19 +112,20 @@ public class StructureHelper
/**
* Allows to make distinctions among elements which would otherwise be equal.
* <p>
- * If the given element is a <code>SourceConstruct</code> which is equal to
- * an already {@link #addChild added} element, this implementation increments
- * its {@link SourceConstruct#hOccurrenceCount() occurrence count} until
- * it is no longer equal to any previously added element.
+ * If the given element is a source construct which is equal to an already
+ * {@link #addChild added} element, this implementation increments its
+ * {@link ISourceConstructImplExtension#hOccurrenceCount() occurrence count}
+ * until it is no longer equal to any previously added element.
* </p>
*
* @param element the given element (never <code>null</code>)
*/
protected void resolveDuplicates(IElement element)
{
- if (!(element instanceof SourceConstruct))
+ if (!(element instanceof ISourceConstructImplExtension))
return;
- SourceConstruct sc = (SourceConstruct)element;
+ ISourceConstructImplExtension sc =
+ (ISourceConstructImplExtension)element;
while (newElements.containsKey(sc))
sc.hIncrementOccurrenceCount();
}

Back to the top