+
+ @Override
+ protected ExtensionStatement createDeclared(final StmtContext<QName, ExtensionStatement, ?> ctx,
+ final ImmutableList<? extends DeclaredStatement<?>> substatements) {
+ return new RegularExtensionStatement(ctx.coerceStatementArgument(), substatements);
+ }
+
+ @Override
+ protected ExtensionStatement createEmptyDeclared(final StmtContext<QName, ExtensionStatement, ?> ctx) {
+ return new EmptyExtensionStatement(ctx.coerceStatementArgument());
+ }
+
+ @Override
+ public ExtensionEffectiveStatement createEffective(
+ final StmtContext<QName, ExtensionStatement, ExtensionEffectiveStatement> ctx) {
+ Map<StmtContext<?, ?, ?>, ExtensionEffectiveStatementImpl> tl = TL_BUILDERS.get();
+ if (tl == null) {
+ tl = new IdentityHashMap<>();
+ TL_BUILDERS.set(tl);
+ }
+
+ final ExtensionEffectiveStatementImpl existing = tl.get(ctx);
+ if (existing != null) {
+ // Implies non-empty map, no cleanup necessary
+ return existing;
+ }
+
+ try {
+ final ExtensionEffectiveStatementImpl created = new ExtensionEffectiveStatementImpl(ctx.buildDeclared(),
+ ctx.getSchemaPath().get());
+ verify(tl.put(ctx, created) == null);
+ try {
+ return super.createEffective(ctx);
+ } finally {
+ verify(tl.remove(ctx) == created);
+
+ }
+ } finally {
+ if (tl.isEmpty()) {
+ TL_BUILDERS.remove();
+ }
+ }
+ }
+
+ @Override
+ protected ExtensionEffectiveStatement createEffective(
+ final StmtContext<QName, ExtensionStatement, ExtensionEffectiveStatement> ctx,
+ final ExtensionStatement declared,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+ return finishCreate(ctx, substatements);
+ }
+
+ @Override
+ protected ExtensionEffectiveStatement createEmptyEffective(
+ final StmtContext<QName, ExtensionStatement, ExtensionEffectiveStatement> ctx,
+ final ExtensionStatement declared) {
+ return finishCreate(ctx, ImmutableList.of());
+ }
+
+ private static @NonNull ExtensionEffectiveStatement finishCreate(final StmtContext<?, ?, ?> ctx,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+ final ExtensionEffectiveStatementImpl ret = verifyNotNull(verifyNotNull(TL_BUILDERS.get(),
+ "Statement build state not initialized").get(ctx), "No build state found for %s", ctx);
+ ret.setSubstatements(substatements);
+ return ret;
+ }