/*
* Copyright (c) 2020 PANTHEON.tech, s.r.o. 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
*/
package org.opendaylight.yangtools.yang.model.spi.meta;
import static com.google.common.base.Verify.verify;
import static java.util.Objects.requireNonNull;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
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.StatementOrigin;
import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeAwareEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
@Beta
public abstract class AbstractUndeclaredEffectiveStatement>
extends AbstractEffectiveStatement {
@Override
public final StatementOrigin statementOrigin() {
return StatementOrigin.CONTEXT;
}
@Override
public final D getDeclared() {
return null;
}
/**
* Base stateless superclass form {@link SchemaTreeAwareEffectiveStatement}s. It maintains the contents of schema
* tree namespace based of effective substatements.
*
* @param Argument type ({@link Void} if statement does not have argument.)
* @param Class representing declared version of this statement.
* @param Class representing effective version of this statement.
*/
public abstract static class WithSchemaTree,
E extends SchemaTreeAwareEffectiveStatement> extends AbstractUndeclaredEffectiveStatement {
@Override
@SuppressWarnings("unchecked")
protected > Optional extends Map> getNamespaceContents(
final Class namespace) {
if (SchemaTreeAwareEffectiveStatement.Namespace.class.equals(namespace)) {
return Optional.of((Map) schemaTreeNamespace());
}
return super.getNamespaceContents(namespace);
}
/**
* Indexing support for {@link DataNodeContainer#findDataChildByName(QName)}.
*/
protected final @Nullable DataSchemaNode dataSchemaNode(final QName name) {
// Only DataNodeContainer subclasses should be calling this method
verify(this instanceof DataNodeContainer);
final SchemaTreeEffectiveStatement> child = schemaTreeNamespace().get(requireNonNull(name));
return child instanceof DataSchemaNode ? (DataSchemaNode) child : null;
}
protected abstract Map> schemaTreeNamespace();
}
/**
* Base stateless superclass form {@link DataTreeAwareEffectiveStatement}s. It maintains the contents of data tree
* namespace based of effective substatements.
*
* @param Argument type ({@link Void} if statement does not have argument.)
* @param Class representing declared version of this statement.
* @param Class representing effective version of this statement.
*/
public abstract static class WithDataTree,
E extends DataTreeAwareEffectiveStatement> extends WithSchemaTree {
@Override
@SuppressWarnings("unchecked")
protected > Optional extends Map> getNamespaceContents(
final Class namespace) {
if (DataTreeAwareEffectiveStatement.Namespace.class.equals(namespace)) {
return Optional.of((Map) dataTreeNamespace());
}
return super.getNamespaceContents(namespace);
}
protected abstract Map> dataTreeNamespace();
}
/**
* Stateful version of {@link WithSchemaTree}. Schema tree namespace is eagerly instantiated (and checked).
*
* @param Argument type ({@link Void} if statement does not have argument.)
* @param Class representing declared version of this statement.
* @param Class representing effective version of this statement.
*/
public abstract static class DefaultWithSchemaTree,
E extends SchemaTreeAwareEffectiveStatement> extends WithSchemaTree {
public abstract static class WithSubstatements,
E extends SchemaTreeAwareEffectiveStatement> extends DefaultWithSchemaTree {
private final @NonNull Object substatements;
protected WithSubstatements(final ImmutableList extends EffectiveStatement, ?>> substatements) {
super(substatements);
this.substatements = maskList(substatements);
}
protected WithSubstatements(final WithSubstatements original) {
super(original);
this.substatements = original.substatements;
}
@Override
public final ImmutableList extends EffectiveStatement, ?>> effectiveSubstatements() {
return unmaskList(substatements);
}
}
private final @NonNull ImmutableMap> schemaTree;
protected DefaultWithSchemaTree(final ImmutableList extends EffectiveStatement, ?>> substatements) {
this.schemaTree = ImmutableMap.copyOf(createSchemaTreeNamespace(substatements));
}
protected DefaultWithSchemaTree(final DefaultWithSchemaTree original) {
this.schemaTree = original.schemaTree;
}
@Override
protected final Map> schemaTreeNamespace() {
return schemaTree;
}
}
/**
* Stateful version of {@link WithDataTree}. Schema tree and data tree namespaces are eagerly instantiated
* (and checked).
*
* @param Argument type ({@link Void} if statement does not have argument.)
* @param Class representing declared version of this statement.
* @param Class representing effective version of this statement.
*/
public abstract static class DefaultWithDataTree,
E extends DataTreeAwareEffectiveStatement> extends WithDataTree {
public abstract static class WithSubstatements,
E extends DataTreeAwareEffectiveStatement> extends DefaultWithDataTree {
private final @NonNull Object substatements;
protected WithSubstatements(final ImmutableList extends EffectiveStatement, ?>> substatements) {
super(substatements);
this.substatements = maskList(substatements);
}
protected WithSubstatements(final WithSubstatements original) {
super(original);
this.substatements = original.substatements;
}
@Override
public final ImmutableList extends EffectiveStatement, ?>> effectiveSubstatements() {
return unmaskList(substatements);
}
}
private final @NonNull ImmutableMap> schemaTree;
private final @NonNull ImmutableMap> dataTree;
protected DefaultWithDataTree(final ImmutableList extends EffectiveStatement, ?>> substatements) {
final Map> schema = createSchemaTreeNamespace(substatements);
this.schemaTree = ImmutableMap.copyOf(schema);
this.dataTree = createDataTreeNamespace(schema.values(), schemaTree);
}
protected DefaultWithDataTree(final DefaultWithDataTree original) {
this.schemaTree = original.schemaTree;
this.dataTree = original.dataTree;
}
@Override
protected final Map> schemaTreeNamespace() {
return schemaTree;
}
@Override
protected final Map> dataTreeNamespace() {
return dataTree;
}
}
}