*/
package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.typedef;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.VarHandle;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
import org.opendaylight.yangtools.yang.model.api.stmt.DefaultEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.UnitsEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.util.type.DerivedTypeBuilder;
-import org.opendaylight.yangtools.yang.model.util.type.DerivedTypes;
-import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractEffectiveSchemaNode;
-import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStmtUtils;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
-import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.model.ri.type.DerivedTypeBuilder;
+import org.opendaylight.yangtools.yang.model.ri.type.DerivedTypes;
+import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredEffectiveStatement.Default;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.SchemaNodeMixin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-final class TypedefEffectiveStatementImpl extends AbstractEffectiveSchemaNode<TypedefStatement> implements
- TypedefEffectiveStatement {
+final class TypedefEffectiveStatementImpl extends Default<QName, TypedefStatement>
+ implements TypedefEffectiveStatement, SchemaNodeMixin<QName, TypedefStatement> {
private static final Logger LOG = LoggerFactory.getLogger(TypedefEffectiveStatementImpl.class);
- private final @NonNull TypeDefinition<?> typeDefinition;
+ private static final VarHandle TYPE_DEFINITION;
+ private static final VarHandle TYPE_STATEMENT;
+
+ static {
+ final Lookup lookup = MethodHandles.lookup();
+ try {
+ TYPE_DEFINITION = lookup.findVarHandle(TypedefEffectiveStatementImpl.class, "typeDefinition",
+ TypeDefinition.class);
+ TYPE_STATEMENT = lookup.findVarHandle(TypedefEffectiveStatementImpl.class, "typeStatement",
+ ProxyTypeEffectiveStatement.class);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ private final @NonNull Object substatements;
+ private final @NonNull Immutable path;
+ private final int flags;
+
+ // Accessed via TYPE_DEFINITION
+ @SuppressWarnings("unused")
+ private volatile TypeDefinition<?> typeDefinition;
+ // Accessed via TYPE_STATEMENT
+ @SuppressWarnings("unused")
+ private volatile ProxyTypeEffectiveStatement typeStatement;
+
+ TypedefEffectiveStatementImpl(final TypedefStatement declared, final Immutable path, final int flags,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+ super(declared);
+ this.path = requireNonNull(path);
+ this.flags = flags;
+ this.substatements = maskList(substatements);
+ }
+
+ @Override
+ public int flags() {
+ return flags;
+ }
- private volatile TypeEffectiveStatement<TypeStatement> typeStatement;
+ @Override
+ public Immutable pathObject() {
+ return path;
+ }
- TypedefEffectiveStatementImpl(final StmtContext<QName, TypedefStatement, ?> ctx) {
- super(ctx);
+ @Override
+ public @NonNull QName argument() {
+ return getQName();
+ }
+
+ @Override
+ public ImmutableList<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
+ return unmaskList(substatements);
+ }
+
+ @Override
+ public TypeDefinition<?> getTypeDefinition() {
+ final TypeDefinition<?> existing = (TypeDefinition<?>) TYPE_DEFINITION.getAcquire(this);
+ return existing != null ? existing : loadTypeDefinition();
+ }
+
+ @Override
+ public TypeEffectiveStatement<TypeStatement> asTypeEffectiveStatement() {
+ final ProxyTypeEffectiveStatement local = (ProxyTypeEffectiveStatement) TYPE_STATEMENT.getAcquire(this);
+ return local != null ? local : loadTypeStatement();
+ }
+
+ private @NonNull TypeDefinition<?> loadTypeDefinition() {
+ final TypeEffectiveStatement<?> type = findFirstEffectiveSubstatement(TypeEffectiveStatement.class).get();
+ final DerivedTypeBuilder<?> builder = DerivedTypes.derivedTypeBuilder(type.getTypeDefinition(), getQName());
- final TypeEffectiveStatement<?> typeEffectiveStmt = firstSubstatementOfType(TypeEffectiveStatement.class);
- final DerivedTypeBuilder<?> builder = DerivedTypes.derivedTypeBuilder(typeEffectiveStmt.getTypeDefinition(),
- ctx.getSchemaPath().get());
- String dflt = null;
for (final EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
if (stmt instanceof DefaultEffectiveStatement) {
- dflt = ((DefaultEffectiveStatement) stmt).argument();
- builder.setDefaultValue(dflt);
+ builder.setDefaultValue(((DefaultEffectiveStatement) stmt).argument());
} else if (stmt instanceof DescriptionEffectiveStatement) {
builder.setDescription(((DescriptionEffectiveStatement)stmt).argument());
} else if (stmt instanceof ReferenceEffectiveStatement) {
} else if (stmt instanceof UnknownSchemaNode) {
// FIXME: should not directly implement, I think
builder.addUnknownSchemaNode((UnknownSchemaNode)stmt);
- } else {
- if (!(stmt instanceof TypeEffectiveStatement)) {
- LOG.debug("Ignoring statement {}", stmt);
- }
+ } else if (!(stmt instanceof TypeEffectiveStatement)) {
+ LOG.debug("Ignoring statement {}", stmt);
}
}
- SourceException.throwIf(
- EffectiveStmtUtils.hasDefaultValueMarkedWithIfFeature(ctx.getRootVersion(), typeEffectiveStmt, dflt),
- ctx.getStatementSourceReference(),
- "Typedef '%s' has default value '%s' marked with an if-feature statement.", ctx.getStatementArgument(),
- dflt);
-
- typeDefinition = builder.build();
- }
-
- @Override
- public TypeDefinition<?> getTypeDefinition() {
- return typeDefinition;
+ final TypeDefinition<?> created = builder.build();
+ final Object witness = TYPE_DEFINITION.compareAndExchangeRelease(this, null, created);
+ return witness == null ? created : (TypeDefinition<?>) witness;
}
- @Override
- public TypeEffectiveStatement<TypeStatement> asTypeEffectiveStatement() {
- TypeEffectiveStatement<TypeStatement> ret = typeStatement;
- if (ret == null) {
- synchronized (this) {
- ret = typeStatement;
- if (ret == null) {
- typeStatement = ret = new ProxyTypeEffectiveStatement();
- }
- }
- }
-
- return ret;
+ private @NonNull ProxyTypeEffectiveStatement loadTypeStatement() {
+ final ProxyTypeEffectiveStatement created = new ProxyTypeEffectiveStatement();
+ final Object witness = TYPE_STATEMENT.compareAndExchangeRelease(this, null, created);
+ return witness == null ? created : (ProxyTypeEffectiveStatement) witness;
}
private final class ProxyTypeEffectiveStatement implements TypeEffectiveStatement<TypeStatement> {
return TypedefEffectiveStatementImpl.this.effectiveSubstatements();
}
- @Override
- public StatementDefinition statementDefinition() {
- return YangStmtMapping.TYPE;
- }
-
@Override
public String argument() {
return getQName().getLocalName();