/* * 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.util; import static org.opendaylight.yangtools.yang.model.api.Module.DEFAULT_SEMANTIC_VERSION; import com.google.common.annotations.Beta; import com.google.common.base.Function; import com.google.common.base.Preconditions; import java.util.Optional; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.antlr.v4.runtime.ParserRuleContext; 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; import org.opendaylight.yangtools.yang.parser.impl.util.YangModelDependencyInfo; /** * 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 implements SchemaSourceRepresentation { @Deprecated public static final Function<ASTSchemaSource, SourceIdentifier> GET_IDENTIFIER = ASTSchemaSource::getIdentifier; @Deprecated public static final Function<ASTSchemaSource, SourceIdentifier> GET_SEMVER_IDENTIFIER = ASTSchemaSource::getSemVerIdentifier; @Deprecated public static final Function<ASTSchemaSource, YangModelDependencyInfo> GET_DEPINFO = ASTSchemaSource::getDependencyInformation; @Deprecated public static final Function<ASTSchemaSource, ParserRuleContext> GET_AST = ASTSchemaSource::getAST; private final YangModelDependencyInfo depInfo; private final SemVerSourceIdentifier semVerId; private final ParserRuleContext tree; private final SourceIdentifier id; private final String symbolicName; private ASTSchemaSource(@Nonnull final SourceIdentifier id, @Nonnull final SemVerSourceIdentifier semVerId, @Nonnull final ParserRuleContext tree, @Nonnull final YangModelDependencyInfo depInfo, @Nullable final String symbolicName) { this.depInfo = Preconditions.checkNotNull(depInfo); this.tree = Preconditions.checkNotNull(tree); this.id = Preconditions.checkNotNull(id); this.semVerId = Preconditions.checkNotNull(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 name YANG source name. Used only for error reporting. * @param tree ANTLR abstract syntax tree * @return A new representation instance. * @throws YangSyntaxErrorException if we fail to extract dependency information. */ public static ASTSchemaSource create(@Nonnull final String name, @Nonnull final ParserRuleContext tree) throws YangSyntaxErrorException { final YangModelDependencyInfo depInfo = YangModelDependencyInfo.fromAST(name, tree); final SourceIdentifier id = getSourceId(depInfo); final SemVerSourceIdentifier semVerId = getSemVerSourceId(depInfo); return new ASTSchemaSource(id, semVerId, tree, depInfo, null); } private static SourceIdentifier getSourceId(final YangModelDependencyInfo depInfo) { final String name = depInfo.getName(); return depInfo.getFormattedRevision() == null ? RevisionSourceIdentifier.create(name) : RevisionSourceIdentifier.create(name, depInfo.getFormattedRevision()); } private static SemVerSourceIdentifier getSemVerSourceId(final YangModelDependencyInfo depInfo) { return depInfo.getFormattedRevision() == null ? SemVerSourceIdentifier.create(depInfo.getName(), depInfo.getSemanticVersion().or(DEFAULT_SEMANTIC_VERSION)) : SemVerSourceIdentifier.create(depInfo.getName(), depInfo.getFormattedRevision(), depInfo.getSemanticVersion().or(DEFAULT_SEMANTIC_VERSION)); } /** * Create a new instance of AST representation for a abstract syntax tree, * performing minimal semantic analysis to acquire dependency information. * * @param identifier * SourceIdentifier of yang schema source. * @param tree * ANTLR abstract syntax tree * @param text * YANG text source * @return A new representation instance. * @throws YangSyntaxErrorException * if we fail to extract dependency information. * * @deprecated Use {@link #create(SourceIdentifier, ParserRuleContext)} instead. */ @Deprecated public static ASTSchemaSource create(@Nonnull final SourceIdentifier identifier, @Nonnull final ParserRuleContext tree, final String text) throws YangSyntaxErrorException { return create(identifier, tree); } /** * Create a new instance of AST representation for a abstract syntax tree, performing minimal semantic analysis * to acquire dependency information. * * @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. */ public static ASTSchemaSource create(@Nonnull final SourceIdentifier identifier, @Nonnull final ParserRuleContext tree) throws YangSyntaxErrorException { return create(identifier, null, tree); } /** * 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. */ public static ASTSchemaSource create(@Nonnull final String symbolicName, @Nonnull final SourceIdentifier identifier, @Nonnull final ParserRuleContext tree) throws YangSyntaxErrorException { return create(identifier, symbolicName, tree); } private static ASTSchemaSource create(@Nonnull final SourceIdentifier identifier, @Nullable final String symbolicName, @Nonnull final ParserRuleContext tree) throws YangSyntaxErrorException { final YangModelDependencyInfo depInfo = YangModelDependencyInfo.fromAST(identifier.getName(), 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 SourceIdentifier getIdentifier() { return id; } @Override public Optional<String> getSymbolicName() { return Optional.ofNullable(symbolicName); } public SemVerSourceIdentifier getSemVerIdentifier() { return semVerId; } @Nonnull @Override public Class<? extends SchemaSourceRepresentation> getType() { return ASTSchemaSource.class; } /** * Return the underlying abstract syntax tree. * * @return Underlying AST. */ @Nonnull public ParserRuleContext getAST() { return tree; } /** * Return the dependency information as extracted from the AST. * * FIXME: this method should be extracted into a public interface in the * model.api.repo class, relying solely on model.api types. * * @return Dependency information. */ @Nonnull public YangModelDependencyInfo getDependencyInformation() { return depInfo; } }