/* * Copyright (c) 2014 Cisco Systems, Inc. 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.parser.rfc7950.repo; import static java.util.Objects.requireNonNull; import com.google.common.annotations.Beta; import java.util.Optional; import org.antlr.v4.runtime.ParserRuleContext; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.yangtools.concepts.AbstractIdentifiable; import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException; import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier; import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation; import org.opendaylight.yangtools.yang.model.repo.api.SemVerSourceIdentifier; import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; /** * Abstract Syntax Tree representation of a schema source. This representation is internal to the YANG parser * implementation, as it relies on ANTLR types. * *

* Instances of this representation are used for caching purposes, as they are a natural intermediate step in YANG text * processing pipeline: the text has been successfully parsed, so we know it is syntactically correct. It also passes * basic semantic validation and we were able to extract dependency information. */ @Beta public final class ASTSchemaSource extends AbstractIdentifiable implements SchemaSourceRepresentation { private final @NonNull YangModelDependencyInfo depInfo; private final @NonNull SemVerSourceIdentifier semVerId; private final @NonNull ParserRuleContext tree; private final @Nullable String symbolicName; private ASTSchemaSource(final @NonNull SourceIdentifier identifier, final @NonNull SemVerSourceIdentifier semVerId, final @NonNull ParserRuleContext tree, final @NonNull YangModelDependencyInfo depInfo, @Nullable final String symbolicName) { super(identifier); this.depInfo = requireNonNull(depInfo); this.tree = requireNonNull(tree); this.semVerId = requireNonNull(semVerId); this.symbolicName = symbolicName; } /** * Create a new instance of AST representation for a abstract syntax tree, performing minimal semantic analysis * to acquire dependency information. * * @param symbolicName * Symbolic name * @param identifier * SourceIdentifier of YANG schema source. * @param tree * ANTLR abstract syntax tree * @return A new representation instance. * @throws YangSyntaxErrorException * if we fail to extract dependency information. */ static @NonNull ASTSchemaSource create(final @NonNull SourceIdentifier identifier, final @Nullable String symbolicName, final @NonNull ParserRuleContext tree) throws YangSyntaxErrorException { final YangModelDependencyInfo depInfo = YangModelDependencyInfo.fromAST(identifier, tree); final SourceIdentifier id = getSourceId(depInfo); final SemVerSourceIdentifier semVerId; if (identifier instanceof SemVerSourceIdentifier && !depInfo.getSemanticVersion().isPresent()) { semVerId = (SemVerSourceIdentifier) identifier; } else { semVerId = getSemVerSourceId(depInfo); } return new ASTSchemaSource(id, semVerId, tree, depInfo, symbolicName); } @Override public Optional getSymbolicName() { return Optional.ofNullable(symbolicName); } public @NonNull SemVerSourceIdentifier getSemVerIdentifier() { return semVerId; } @Override public Class getType() { return ASTSchemaSource.class; } /** * Return the underlying abstract syntax tree. * * @return Underlying AST. */ public @NonNull ParserRuleContext getAST() { return tree; } /** * Return the dependency information as extracted from the AST. * * @return Dependency information. */ // FIXME: this method should be extracted into a public interface in the model.api.repo class, relying solely // on model.api types. public @NonNull YangModelDependencyInfo getDependencyInformation() { return depInfo; } private static @NonNull SourceIdentifier getSourceId(final @NonNull YangModelDependencyInfo depInfo) { final String name = depInfo.getName(); return depInfo.getFormattedRevision() == null ? RevisionSourceIdentifier.create(name) : RevisionSourceIdentifier.create(name, depInfo.getRevision()); } private static @NonNull SemVerSourceIdentifier getSemVerSourceId(final @NonNull YangModelDependencyInfo depInfo) { return depInfo.getFormattedRevision() == null ? SemVerSourceIdentifier.create(depInfo.getName(), depInfo.getSemanticVersion().orElse(null)) : SemVerSourceIdentifier.create(depInfo.getName(), depInfo.getRevision(), depInfo.getSemanticVersion().orElse(null)); } }