import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
-import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
import org.opendaylight.yangtools.yang.model.api.stmt.MandatoryStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.MinElementsStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.PresenceStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.PresenceEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.RevisionStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
import org.opendaylight.yangtools.yang.model.api.stmt.SubmoduleStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.UnrecognizedStatement;
-import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
-import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToPrefixToModuleName;
import org.opendaylight.yangtools.yang.parser.spi.source.ImportPrefixToModuleCtx;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
public final class StmtContextUtils {
- public static final Splitter LIST_KEY_SPLITTER = Splitter.on(' ').omitEmptyStrings().trimResults();
-
private StmtContextUtils() {
- throw new UnsupportedOperationException("Utility class");
+ // Hidden on purpose
}
@SuppressWarnings("unchecked")
public static <A, D extends DeclaredStatement<A>> A firstAttributeOf(
final Iterable<? extends StmtContext<?, ?, ?>> contexts, final Class<D> declaredType) {
for (final StmtContext<?, ?, ?> ctx : contexts) {
- if (producesDeclared(ctx, declaredType)) {
+ if (ctx.producesDeclared(declaredType)) {
return (A) ctx.getStatementArgument();
}
}
@SuppressWarnings("unchecked")
public static <A, D extends DeclaredStatement<A>> A firstAttributeOf(final StmtContext<?, ?, ?> ctx,
final Class<D> declaredType) {
- return producesDeclared(ctx, declaredType) ? (A) ctx.getStatementArgument() : null;
+ return ctx.producesDeclared(declaredType) ? (A) ctx.getStatementArgument() : null;
}
public static <A, D extends DeclaredStatement<A>> A firstSubstatementAttributeOf(
public static <A, D extends DeclaredStatement<A>> StmtContext<A, ?, ?> findFirstDeclaredSubstatement(
final StmtContext<?, ?, ?> stmtContext, final Class<D> declaredType) {
for (final StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
- if (producesDeclared(subStmtContext, declaredType)) {
+ if (subStmtContext.producesDeclared(declaredType)) {
return (StmtContext<A, ?, ?>) subStmtContext;
}
}
}
@SafeVarargs
+ @SuppressWarnings({ "rawtypes", "unchecked" })
public static StmtContext<?, ?, ?> findFirstDeclaredSubstatement(final StmtContext<?, ?, ?> stmtContext,
int startIndex, final Class<? extends DeclaredStatement<?>>... types) {
if (startIndex >= types.length) {
}
for (final StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
- if (producesDeclared(subStmtContext, types[startIndex])) {
+ if (subStmtContext.producesDeclared((Class) types[startIndex])) {
return startIndex + 1 == types.length ? subStmtContext : findFirstDeclaredSubstatement(subStmtContext,
++startIndex, types);
}
final StmtContext<?, ?, ?> stmtContext, final Class<D> declaredType) {
final ImmutableList.Builder<StmtContext<A, D, ?>> listBuilder = ImmutableList.builder();
for (final StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
- if (producesDeclared(subStmtContext, declaredType)) {
+ if (subStmtContext.producesDeclared(declaredType)) {
listBuilder.add((StmtContext<A, D, ?>) subStmtContext);
}
}
final StmtContext<?, ?, ?> stmtContext, final Class<D> type) {
final ImmutableList.Builder<StmtContext<A, D, ?>> listBuilder = ImmutableList.builder();
for (final StmtContext<?, ?, ?> subStmtContext : stmtContext.effectiveSubstatements()) {
- if (producesDeclared(subStmtContext, type)) {
+ if (subStmtContext.producesDeclared(type)) {
listBuilder.add((StmtContext<A, D, ?>) subStmtContext);
}
}
public static <A, D extends DeclaredStatement<A>> StmtContext<A, ?, ?> findFirstEffectiveSubstatement(
final StmtContext<?, ?, ?> stmtContext, final Class<D> declaredType) {
for (final StmtContext<?, ?, ?> subStmtContext : stmtContext.effectiveSubstatements()) {
- if (producesDeclared(subStmtContext, declaredType)) {
+ if (subStmtContext.producesDeclared(declaredType)) {
return (StmtContext<A, ?, ?>) subStmtContext;
}
}
* @param <A> statement argument type
* @param <D> declared statement type
* @return statement context that was searched for or null if was not found
+ * @deprecated Use {@link StmtContext#findSubstatementArgument(Class)} instead.
*/
+ @Deprecated(forRemoval = true)
public static <A, D extends DeclaredStatement<A>> StmtContext<A, ?, ?> findFirstSubstatement(
final StmtContext<?, ?, ?> stmtContext, final Class<D> declaredType) {
final StmtContext<A, ?, ?> effectiveSubstatement = findFirstEffectiveSubstatement(stmtContext, declaredType);
}
public static <D extends DeclaredStatement<?>> StmtContext<?, ?, ?> findFirstDeclaredSubstatementOnSublevel(
- final StmtContext<?, ?, ?> stmtContext, final Class<D> declaredType, int sublevel) {
+ final StmtContext<?, ?, ?> stmtContext, final Class<? super D> declaredType, int sublevel) {
for (final StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
- if (sublevel == 1 && producesDeclared(subStmtContext, declaredType)) {
+ if (sublevel == 1 && subStmtContext.producesDeclared(declaredType)) {
return subStmtContext;
}
if (sublevel > 1) {
}
public static <D extends DeclaredStatement<?>> StmtContext<?, ?, ?> findDeepFirstDeclaredSubstatement(
- final StmtContext<?, ?, ?> stmtContext, final Class<D> declaredType) {
+ final StmtContext<?, ?, ?> stmtContext, final Class<? super D> declaredType) {
for (final StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
- if (producesDeclared(subStmtContext, declaredType)) {
+ if (subStmtContext.producesDeclared(declaredType)) {
return subStmtContext;
}
return null;
}
- public static boolean producesDeclared(final StmtContext<?, ?, ?> ctx,
- final Class<? extends DeclaredStatement<?>> type) {
- return type.isAssignableFrom(ctx.getPublicDefinition().getDeclaredRepresentationClass());
- }
-
public static boolean isInExtensionBody(final StmtContext<?, ?, ?> stmtCtx) {
StmtContext<?, ?, ?> current = stmtCtx;
- while (current.getParentContext().getParentContext() != null) {
- current = current.getParentContext();
- if (isUnknownStatement(current)) {
+
+ while (true) {
+ final StmtContext<?, ?, ?> parent = current.coerceParentContext();
+ if (parent.getParentContext() == null) {
+ return false;
+ }
+ if (isUnknownStatement(parent)) {
return true;
}
+ current = parent;
}
-
- return false;
}
/**
* if supplied statement context is null
*/
public static boolean isUnrecognizedStatement(final StmtContext<?, ?, ?> stmtCtx) {
- return UnrecognizedStatement.class
- .isAssignableFrom(stmtCtx.getPublicDefinition().getDeclaredRepresentationClass());
+ return stmtCtx.producesDeclared(UnrecognizedStatement.class);
}
public static boolean checkFeatureSupport(final StmtContext<?, ?, ?> stmtContext,
for (final StmtContext<?, ?, ?> stmt : stmtContext.declaredSubstatements()) {
if (YangStmtMapping.IF_FEATURE.equals(stmt.getPublicDefinition())) {
containsIfFeature = true;
- if (((Predicate<Set<QName>>) stmt.getStatementArgument()).test(supportedFeatures)) {
+ @SuppressWarnings("unchecked")
+ final Predicate<Set<QName>> argument = (Predicate<Set<QName>>) stmt.coerceStatementArgument();
+ if (argument.test(supportedFeatures)) {
isSupported = true;
} else {
isSupported = false;
}
private static boolean containsPresenceSubStmt(final StmtContext<?, ?, ?> stmtCtx) {
- return findFirstSubstatement(stmtCtx, PresenceStatement.class) != null;
+ return stmtCtx.hasSubstatement(PresenceEffectiveStatement.class);
}
/**
requireNonNull(ancestorType);
requireNonNull(ancestorChildType);
- StmtContext<?, ?, ?> current = ctx.getParentContext();
+ StmtContext<?, ?, ?> current = ctx.coerceParentContext();
StmtContext<?, ?, ?> parent = current.getParentContext();
while (parent != null) {
- if (ancestorType.equals(current.getPublicDefinition())) {
- @SuppressWarnings("unchecked")
- final Class<D> ancestorChildTypeClass = (Class<D>) ancestorChildType.getDeclaredRepresentationClass();
- if (findFirstSubstatement(current, ancestorChildTypeClass) == null) {
- return false;
- }
+ if (ancestorType.equals(current.getPublicDefinition())
+ && !current.hasSubstatement(ancestorChildType.getEffectiveRepresentationClass())) {
+ return false;
}
current = parent;
public static boolean hasParentOfType(final StmtContext<?, ?, ?> ctx, final StatementDefinition parentType) {
requireNonNull(parentType);
final StmtContext<?, ?, ?> parentContext = ctx.getParentContext();
- return parentContext != null ? parentType.equals(parentContext.getPublicDefinition()) : false;
+ return parentContext != null && parentType.equals(parentContext.getPublicDefinition());
}
/**
return;
}
- final StmtContext<?, ?, ?> listStmtCtx = ctx.getParentContext();
- final StmtContext<Collection<SchemaNodeIdentifier>, ?, ?> keyStmtCtx =
- StmtContextUtils.findFirstDeclaredSubstatement(listStmtCtx, KeyStatement.class);
+ final StmtContext<?, ?, ?> listStmtCtx = ctx.coerceParentContext();
+ final StmtContext<Set<QName>, ?, ?> keyStmtCtx = findFirstDeclaredSubstatement(listStmtCtx, KeyStatement.class);
if (YangStmtMapping.LEAF.equals(ctx.getPublicDefinition())) {
if (isListKey(ctx, keyStmtCtx)) {
disallowIfFeatureAndWhenOnListKeys(ctx);
}
} else if (YangStmtMapping.USES.equals(ctx.getPublicDefinition())) {
- StmtContextUtils.findAllEffectiveSubstatements(listStmtCtx, LeafStatement.class).forEach(leafStmtCtx -> {
+ findAllEffectiveSubstatements(listStmtCtx, LeafStatement.class).forEach(leafStmtCtx -> {
if (isListKey(leafStmtCtx, keyStmtCtx)) {
disallowIfFeatureAndWhenOnListKeys(leafStmtCtx);
}
}
private static boolean isRelevantForIfFeatureAndWhenOnListKeysCheck(final StmtContext<?, ?, ?> ctx) {
- return YangVersion.VERSION_1_1.equals(ctx.getRootVersion())
- && StmtContextUtils.hasParentOfType(ctx, YangStmtMapping.LIST)
- && StmtContextUtils.findFirstDeclaredSubstatement(ctx.getParentContext(), KeyStatement.class) != null;
+ return YangVersion.VERSION_1_1.equals(ctx.getRootVersion()) && hasParentOfType(ctx, YangStmtMapping.LIST)
+ && findFirstDeclaredSubstatement(ctx.coerceParentContext(), KeyStatement.class) != null;
}
private static boolean isListKey(final StmtContext<?, ?, ?> leafStmtCtx,
- final StmtContext<Collection<SchemaNodeIdentifier>, ?, ?> keyStmtCtx) {
- for (final SchemaNodeIdentifier keyIdentifier : keyStmtCtx.getStatementArgument()) {
- if (leafStmtCtx.getStatementArgument().equals(keyIdentifier.getLastComponent())) {
- return true;
- }
- }
-
- return false;
+ final StmtContext<Set<QName>, ?, ?> keyStmtCtx) {
+ return keyStmtCtx.coerceStatementArgument().contains(leafStmtCtx.getStatementArgument());
}
private static void disallowIfFeatureAndWhenOnListKeys(final StmtContext<?, ?, ?> leafStmtCtx) {
switch (namesParts.length) {
case 1:
localName = namesParts[0];
- qnameModule = StmtContextUtils.getRootModuleQName(ctx);
+ qnameModule = getRootModuleQName(ctx);
break;
default:
prefix = namesParts[0];
localName = namesParts[1];
- qnameModule = StmtContextUtils.getModuleQNameByPrefix(ctx, prefix);
+ qnameModule = getModuleQNameByPrefix(ctx, prefix);
// in case of unknown statement argument, we're not going to parse it
if (qnameModule == null && isUnknownStatement(ctx)) {
localName = value;
- qnameModule = StmtContextUtils.getRootModuleQName(ctx);
+ qnameModule = getRootModuleQName(ctx);
}
if (qnameModule == null && ctx.getCopyHistory().getLastOperation() == CopyType.ADDED_BY_AUGMENTATION) {
ctx = ctx.getOriginalCtx().orElse(null);
- qnameModule = StmtContextUtils.getModuleQNameByPrefix(ctx, prefix);
+ qnameModule = getModuleQNameByPrefix(ctx, prefix);
}
- break;
}
- qnameModule = InferenceException.throwIfNull(qnameModule, ctx.getStatementSourceReference(),
- "Cannot resolve QNameModule for '%s'", value);
- return ctx.getFromNamespace(QNameCacheNamespace.class, QName.create(qnameModule, localName));
+ return internedQName(ctx,
+ InferenceException.throwIfNull(qnameModule, ctx.getStatementSourceReference(),
+ "Cannot resolve QNameModule for '%s'", value), localName);
+ }
+
+ /**
+ * Parse a YANG identifier string in context of a statement.
+ *
+ * @param ctx Statement context
+ * @param str String to be parsed
+ * @return An interned QName
+ * @throws NullPointerException if any of the arguments are null
+ * @throws SourceException if the string is not a valid YANG identifier
+ */
+ public static QName parseIdentifier(final StmtContext<?, ?, ?> ctx, final String str) {
+ SourceException.throwIf(str.isEmpty(), ctx.getStatementSourceReference(),
+ "Identifier may not be an empty string");
+ return internedQName(ctx, str);
+ }
+
+ public static QName parseNodeIdentifier(StmtContext<?, ?, ?> ctx, final String prefix,
+ final String localName) {
+ final QNameModule module = getModuleQNameByPrefix(ctx, prefix);
+ if (module != null) {
+ return internedQName(ctx, module, localName);
+ }
+
+ if (ctx.getCopyHistory().getLastOperation() == CopyType.ADDED_BY_AUGMENTATION) {
+ final Optional<? extends StmtContext<?, ?, ?>> optOrigCtx = ctx.getOriginalCtx();
+ if (optOrigCtx.isPresent()) {
+ ctx = optOrigCtx.get();
+ final QNameModule origModule = getModuleQNameByPrefix(ctx, prefix);
+ if (origModule != null) {
+ return internedQName(ctx, origModule, localName);
+ }
+ }
+ }
+
+ throw new InferenceException(ctx.getStatementSourceReference(), "Cannot resolve QNameModule for '%s'", prefix);
+ }
+
+ /**
+ * Parse a YANG node identifier string in context of a statement.
+ *
+ * @param ctx Statement context
+ * @param str String to be parsed
+ * @return An interned QName
+ * @throws NullPointerException if any of the arguments are null
+ * @throws SourceException if the string is not a valid YANG node identifier
+ */
+ public static QName parseNodeIdentifier(final StmtContext<?, ?, ?> ctx, final String str) {
+ SourceException.throwIf(str.isEmpty(), ctx.getStatementSourceReference(),
+ "Node identifier may not be an empty string");
+
+ final int colon = str.indexOf(':');
+ if (colon == -1) {
+ return internedQName(ctx, str);
+ }
+
+ final String prefix = str.substring(0, colon);
+ SourceException.throwIf(prefix.isEmpty(), ctx.getStatementSourceReference(),
+ "String '%s' has an empty prefix", str);
+ final String localName = str.substring(colon + 1);
+ SourceException.throwIf(localName.isEmpty(), ctx.getStatementSourceReference(),
+ "String '%s' has an empty identifier", str);
+
+ return parseNodeIdentifier(ctx, prefix, localName);
+ }
+
+ private static QName internedQName(final StmtContext<?, ?, ?> ctx, final String localName) {
+ return internedQName(ctx, getRootModuleQName(ctx), localName);
+ }
+
+ private static QName internedQName(final StmtContext<?, ?, ?> ctx, final QNameModule module,
+ final String localName) {
+ final QName template;
+ try {
+ template = QName.create(module, localName);
+ } catch (IllegalArgumentException e) {
+ throw new SourceException(ctx.getStatementSourceReference(), e, "Invalid identifier '%s'", localName);
+ }
+ return template.intern();
}
public static QNameModule getRootModuleQName(final StmtContext<?, ?, ?> ctx) {
final StmtContext<?, ?, ?> rootCtx = ctx.getRoot();
final QNameModule qnameModule;
- if (producesDeclared(rootCtx, ModuleStatement.class)) {
+ if (rootCtx.producesDeclared(ModuleStatement.class)) {
qnameModule = rootCtx.getFromNamespace(ModuleCtxToModuleQName.class, rootCtx);
- } else if (producesDeclared(rootCtx, SubmoduleStatement.class)) {
+ } else if (rootCtx.producesDeclared(SubmoduleStatement.class)) {
final String belongsToModuleName = firstAttributeOf(rootCtx.declaredSubstatements(),
BelongsToStatement.class);
qnameModule = rootCtx.getFromNamespace(ModuleNameToModuleQName.class, belongsToModuleName);
}
public static QNameModule getModuleQNameByPrefix(final StmtContext<?, ?, ?> ctx, final String prefix) {
- final StmtContext<?, ?, ?> importedModule = ctx.getRoot().getFromNamespace(ImportPrefixToModuleCtx.class,
- prefix);
+ final StmtContext<?, ?, ?> root = ctx.getRoot();
+ final StmtContext<?, ?, ?> importedModule = root.getFromNamespace(ImportPrefixToModuleCtx.class, prefix);
final QNameModule qnameModule = ctx.getFromNamespace(ModuleCtxToModuleQName.class, importedModule);
if (qnameModule != null) {
return qnameModule;
}
- if (producesDeclared(ctx.getRoot(), SubmoduleStatement.class)) {
- final String moduleName = ctx.getRoot().getFromNamespace(BelongsToPrefixToModuleName.class, prefix);
+ if (root.producesDeclared(SubmoduleStatement.class)) {
+ final String moduleName = root.getFromNamespace(BelongsToPrefixToModuleName.class, prefix);
return ctx.getFromNamespace(ModuleNameToModuleQName.class, moduleName);
}
return null;
}
- public static SourceIdentifier createSourceIdentifier(final StmtContext<?, ?, ?> root) {
- final QNameModule qNameModule = root.getFromNamespace(ModuleCtxToModuleQName.class, root);
- if (qNameModule != null) {
- // creates SourceIdentifier for a module
- if (qNameModule.getFormattedRevision() == null) {
- return RevisionSourceIdentifier.create((String) root.getStatementArgument());
- }
-
- return RevisionSourceIdentifier.create((String) root.getStatementArgument(),
- qNameModule.getFormattedRevision());
- }
-
- // creates SourceIdentifier for a submodule
- final Optional<Revision> revision = getLatestRevision(root.declaredSubstatements());
- return revision.isPresent()
- ? RevisionSourceIdentifier.create((String) root.getStatementArgument(), revision.get().toString())
- : RevisionSourceIdentifier.create((String) root.getStatementArgument());
- }
-
public static Optional<Revision> getLatestRevision(final Iterable<? extends StmtContext<?, ?, ?>> subStmts) {
Revision revision = null;
for (final StmtContext<?, ?, ?> subStmt : subStmts) {
- if (subStmt.getPublicDefinition().getDeclaredRepresentationClass().isAssignableFrom(
- RevisionStatement.class)) {
+ if (subStmt.producesDeclared(RevisionStatement.class)) {
if (revision == null && subStmt.getStatementArgument() != null) {
revision = (Revision) subStmt.getStatementArgument();
- } else if (subStmt.getStatementArgument() != null
- && ((Revision) subStmt.getStatementArgument()).compareTo(revision) > 0) {
- revision = (Revision) subStmt.getStatementArgument();
+ } else {
+ final Revision subArg = (Revision) subStmt.getStatementArgument();
+ if (subArg != null && subArg.compareTo(revision) > 0) {
+ revision = subArg;
+ }
}
}
}