This is an automated email from the ASF dual-hosted git repository. theigl pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/wicket.git
The following commit(s) were added to refs/heads/master by this push: new 931c873 WICKET-6839 Use request flag for caching `isVisibleInHierarchy` new 50a5514 Merge pull request #459 from theigl/WICKET-6839-visible-hierarchy-cache 931c873 is described below commit 931c873e84ebefc1cbb96b5b62e94fce3de6fc0b Author: Thomas Heigl <thomas.he...@gmail.com> AuthorDate: Fri Oct 23 11:31:10 2020 +0200 WICKET-6839 Use request flag for caching `isVisibleInHierarchy` --- .../src/main/java/org/apache/wicket/Component.java | 48 +++++++++++----- .../java/org/apache/wicket/MarkupContainer.java | 12 +--- .../test/java/org/apache/wicket/ComponentTest.java | 65 +++++++++++++++++++++- 3 files changed, 100 insertions(+), 25 deletions(-) diff --git a/wicket-core/src/main/java/org/apache/wicket/Component.java b/wicket-core/src/main/java/org/apache/wicket/Component.java index 779eb61..31b1baa 100644 --- a/wicket-core/src/main/java/org/apache/wicket/Component.java +++ b/wicket-core/src/main/java/org/apache/wicket/Component.java @@ -421,26 +421,34 @@ public abstract class Component private int flags = FLAG_VISIBLE | FLAG_ESCAPE_MODEL_STRINGS | FLAG_VERSIONED | FLAG_ENABLED | FLAG_IS_RENDER_ALLOWED | FLAG_VISIBILITY_ALLOWED | FLAG_RESERVED5 /* page's stateless hint */; - private static final short RFLAG_ENABLED_IN_HIERARCHY_VALUE = 0x1; - private static final short RFLAG_ENABLED_IN_HIERARCHY_SET = 0x2; - private static final short RFLAG_ON_CONFIGURE_SUPER_CALL_VERIFIED = 0x4; - private static final short RFLAG_VISIBLE_IN_HIERARCHY_SET = 0x8; + // @formatter:off + private static final short RFLAG_ENABLED_IN_HIERARCHY_VALUE = 0x1; + private static final short RFLAG_ENABLED_IN_HIERARCHY_SET = 0x2; + private static final short RFLAG_VISIBLE_IN_HIERARCHY_VALUE = 0x4; + private static final short RFLAG_VISIBLE_IN_HIERARCHY_SET = 0x8; /** onconfigure has been called */ - private static final short RFLAG_CONFIGURED = 0x10; + private static final short RFLAG_CONFIGURED = 0x10; private static final short RFLAG_BEFORE_RENDER_SUPER_CALL_VERIFIED = 0x20; - private static final short RFLAG_INITIALIZE_SUPER_CALL_VERIFIED = 0x40; - protected static final short RFLAG_CONTAINER_DEQUEING = 0x80; - private static final short RFLAG_ON_RE_ADD_SUPER_CALL_VERIFIED = 0x100; + private static final short RFLAG_INITIALIZE_SUPER_CALL_VERIFIED = 0x40; + protected static final short RFLAG_CONTAINER_DEQUEING = 0x80; + private static final short RFLAG_ON_RE_ADD_SUPER_CALL_VERIFIED = 0x100; /** * Flag that makes we are in before-render callback phase Set after component.onBeforeRender is * invoked (right before invoking beforeRender on children) */ - private static final short RFLAG_RENDERING = 0x200; - private static final short RFLAG_PREPARED_FOR_RENDER = 0x400; - private static final short RFLAG_AFTER_RENDER_SUPER_CALL_VERIFIED = 0x800; - private static final short RFLAG_DETACHING = 0x1000; + private static final short RFLAG_RENDERING = 0x200; + private static final short RFLAG_PREPARED_FOR_RENDER = 0x400; + private static final short RFLAG_AFTER_RENDER_SUPER_CALL_VERIFIED = 0x800; + private static final short RFLAG_DETACHING = 0x1000; /** True when a component is being removed from the hierarchy */ - private static final short RFLAG_REMOVING_FROM_HIERARCHY = 0x2000; + private static final short RFLAG_REMOVING_FROM_HIERARCHY = 0x2000; + /** + * This flag tracks if removals have been set on this component. Clearing this key is an + * expensive operation. With this flag this expensive call can be avoided. + */ + protected static final short RFLAG_CONTAINER_HAS_REMOVALS = 0x4000; + private static final short RFLAG_ON_CONFIGURE_SUPER_CALL_VERIFIED = (short) 0x8000; + // @formatter:on /** * Flags that only keep their value during the request. Useful for cache markers, etc. At the @@ -2099,15 +2107,25 @@ public abstract class Component */ public final boolean isVisibleInHierarchy() { + if (getRequestFlag(RFLAG_VISIBLE_IN_HIERARCHY_SET)) + { + return getRequestFlag(RFLAG_VISIBLE_IN_HIERARCHY_VALUE); + } + + final boolean state; Component parent = getParent(); if (parent != null && !parent.isVisibleInHierarchy()) { - return false; + state = false; } else { - return determineVisibility(); + state = determineVisibility(); } + + setRequestFlag(RFLAG_VISIBLE_IN_HIERARCHY_SET, true); + setRequestFlag(RFLAG_VISIBLE_IN_HIERARCHY_VALUE, state); + return state; } /** diff --git a/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java b/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java index 6af95d1..d2531a5 100644 --- a/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java +++ b/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java @@ -133,12 +133,6 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp { private static final long serialVersionUID = 1L; }; - - /** - * This flag tracks if the {@link #REMOVALS_KEY} has been set on this component. Clearing this - * key is an expensive operation. With this flag this expensive call can be avoided. - */ - private static final short RFLAG_HAS_REMOVALS = 0x4000; /** * Administrative class for detecting removed children during child iteration. Not intended to @@ -1328,7 +1322,7 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp */ private LinkedList<RemovedChild> removals_get() { - return getRequestFlag(RFLAG_HAS_REMOVALS) ? getMetaData(REMOVALS_KEY) : null; + return getRequestFlag(RFLAG_CONTAINER_HAS_REMOVALS) ? getMetaData(REMOVALS_KEY) : null; } /** @@ -1340,7 +1334,7 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp */ private void removals_set(LinkedList<RemovedChild> removals) { - setRequestFlag(RFLAG_HAS_REMOVALS, removals != null); + setRequestFlag(RFLAG_CONTAINER_HAS_REMOVALS, removals != null); setMetaData(REMOVALS_KEY, removals); } @@ -1349,7 +1343,7 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp */ private void removals_clear() { - if (getRequestFlag(RFLAG_HAS_REMOVALS)) + if (getRequestFlag(RFLAG_CONTAINER_HAS_REMOVALS)) { removals_set(null); } diff --git a/wicket-core/src/test/java/org/apache/wicket/ComponentTest.java b/wicket-core/src/test/java/org/apache/wicket/ComponentTest.java index 12ba73e..2095090 100644 --- a/wicket-core/src/test/java/org/apache/wicket/ComponentTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/ComponentTest.java @@ -16,6 +16,7 @@ */ package org.apache.wicket; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -247,6 +248,38 @@ class ComponentTest extends WicketTestCase assertTrue(component.getFlagReserved5()); } + @Test + void isEnabledInHierarchyCachesResult() + { + final SpyComponent c = new SpyComponent("test"); + + c.isEnabledInHierarchy(); + c.isEnabledInHierarchy(); + assertEquals(1, c.isEnabledCallCount); + + c.setEnabled(false); + + c.isEnabledInHierarchy(); + c.isEnabledInHierarchy(); + assertEquals(2, c.isEnabledCallCount); + } + + @Test + void isVisibleInHierarchyCachesResult() + { + final SpyComponent c = new SpyComponent("test"); + + c.isVisibleInHierarchy(); + c.isVisibleInHierarchy(); + assertEquals(1, c.isVisibleCallCount); + + c.setVisible(false); + + c.isVisibleInHierarchy(); + c.isVisibleInHierarchy(); + assertEquals(2, c.isVisibleCallCount); + } + /** * Component#FLAG_RESERVED5 (Page's STATELESS_HINT) must be initially set to true */ @@ -266,4 +299,34 @@ class ComponentTest extends WicketTestCase protected void onRender() { } } -} \ No newline at end of file + + private static class SpyComponent extends Component + { + + int isEnabledCallCount; + int isVisibleCallCount; + + public SpyComponent(final String id) + { + super(id); + } + + @Override + public boolean isEnabled() + { + isEnabledCallCount++; + return super.isEnabled(); + } + + @Override + public boolean isVisible() + { + isVisibleCallCount++; + return super.isVisible(); + } + + @Override + protected void onRender() { + } + } +}