/** * Copyright (c) 2015 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.data.impl.leafref; import com.google.common.collect.Lists; import java.net.URI; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.antlr.v4.runtime.tree.TerminalNode; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.IdentifierContext; import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Node_identifierContext; import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Path_argContext; import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Path_equality_exprContext; import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Path_predicateContext; import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.PrefixContext; import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Rel_path_keyexprContext; import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Relative_pathContext; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.ModuleImport; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaNode; final class LeafRefPathParserListenerImpl extends LeafRefPathParserBaseListener{ private final SchemaContext schemaContext; private final Module module; private LeafRefPath leafRefPath; private boolean relativePath=false; private QNameWithPredicateBuilder currentLeafRefPathQName; private QNamePredicateBuilder currentPredicate; private QNameModule currentQnameModule; private String currentQNameLocalName; private final List<QNameWithPredicateBuilder> leafRefPathQnameList; private List<QNameWithPredicateBuilder> predicatePathKeyQnameList; private final SchemaNode node; //FIXME use for identifier path completion private ParsingState currentParsingState; private enum ParsingState { LEAF_REF_PATH, PATH_PREDICATE, PREDICATE_PATH_EQUALITY_EXPR, PATH_KEY_EXPR } public LeafRefPathParserListenerImpl(final SchemaContext schemaContext, final Module currentModule, final SchemaNode currentNode) { this.schemaContext = schemaContext; this.module = currentModule; this.leafRefPathQnameList = new LinkedList<>(); this.node=currentNode; this.currentParsingState = ParsingState.LEAF_REF_PATH; } @Override public void enterPath_predicate(final Path_predicateContext ctx) { currentParsingState=ParsingState.PATH_PREDICATE; currentPredicate = new QNamePredicateBuilder(); } @Override public void exitPath_predicate(final Path_predicateContext ctx) { currentLeafRefPathQName.addQNamePredicate(currentPredicate.build()); currentPredicate = null; currentParsingState=ParsingState.LEAF_REF_PATH; } @Override public void enterRel_path_keyexpr(final Rel_path_keyexprContext ctx) { currentParsingState=ParsingState.PATH_KEY_EXPR; predicatePathKeyQnameList = new LinkedList<>(); final List<TerminalNode> dots = ctx.DOTS(); for (final TerminalNode parent : dots) { predicatePathKeyQnameList.add(QNameWithPredicateBuilder.UP_PARENT_BUILDER); } } @Override public void exitRel_path_keyexpr(final Rel_path_keyexprContext ctx) { final LeafRefPath pathKeyExpression = LeafRefPath.create(Lists.transform(predicatePathKeyQnameList, QNameWithPredicateBuilder::build), false); currentPredicate.setPathKeyExpression(pathKeyExpression); currentParsingState=ParsingState.PREDICATE_PATH_EQUALITY_EXPR; } @Override public void enterRelative_path(final Relative_pathContext ctx) { relativePath = true; final List<TerminalNode> dots = ctx.DOTS(); for (final TerminalNode parent : dots) { leafRefPathQnameList.add(QNameWithPredicateBuilder.UP_PARENT_BUILDER); } } @Override public void enterPath_equality_expr(final Path_equality_exprContext ctx) { currentParsingState=ParsingState.PREDICATE_PATH_EQUALITY_EXPR; } @Override public void exitPath_equality_expr(final Path_equality_exprContext ctx) { currentParsingState=ParsingState.PATH_PREDICATE; } @Override public void enterPrefix(final PrefixContext ctx) { if (module.getPrefix().equals(ctx.getText())) { currentQnameModule = module.getQNameModule(); } else { currentQnameModule = getQNameModuleForImportPrefix(ctx.getText()); } } @Override public void exitPath_arg(final Path_argContext ctx) { leafRefPath = LeafRefPath.create(Lists.transform(leafRefPathQnameList, QNameWithPredicateBuilder::build), !relativePath); } @Override public void enterIdentifier(final IdentifierContext ctx) { currentQNameLocalName = ctx.getText(); } @Override public void exitNode_identifier(final Node_identifierContext ctx) { if (currentQnameModule == null) { currentQnameModule = module.getQNameModule(); } if (currentParsingState == ParsingState.PREDICATE_PATH_EQUALITY_EXPR) { final QName qname = QName.create(currentQnameModule, currentQNameLocalName); currentPredicate.setIdentifier(qname); } else { final QNameWithPredicateBuilder qnameBuilder = new QNameWithPredicateBuilder( currentQnameModule, currentQNameLocalName); if (currentParsingState == ParsingState.PATH_KEY_EXPR) { predicatePathKeyQnameList.add(qnameBuilder); } else if (currentParsingState == ParsingState.LEAF_REF_PATH) { currentLeafRefPathQName = qnameBuilder; leafRefPathQnameList.add(qnameBuilder); } } currentQnameModule = null; currentQNameLocalName = null; } public LeafRefPath getLeafRefPath() { return leafRefPath; } private URI getNamespaceForImportPrefix(final String prefix) { final ModuleImport moduleImport = getModuleImport(prefix); final Module findedModule = schemaContext.findModuleByName(moduleImport.getModuleName(), moduleImport.getRevision()); return findedModule.getNamespace(); } private QNameModule getQNameModuleForImportPrefix(final String prefix) { final ModuleImport moduleImport = getModuleImport(prefix); if (moduleImport == null) { throw new LeafRefPathParseException("No module import for prefix: " + prefix + " in module: " + module.getName()); } final String moduleName = moduleImport.getModuleName(); final Date revision = moduleImport.getRevision(); final Module findedModule = schemaContext.findModuleByName(moduleName, revision); return findedModule.getQNameModule(); } private ModuleImport getModuleImport(final String prefix) { final Set<ModuleImport> imports = module.getImports(); for (final ModuleImport moduleImport : imports) { if (moduleImport.getPrefix().equals(prefix)) { return moduleImport; } } return null; } }