/*******************************************************************************
* Copyright (c) 2014, 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 com.cisco.yangide.core.parser;
import static com.cisco.yangide.core.model.YangModelManager.search;
import org.eclipse.core.resources.IProject;
import com.cisco.yangide.core.YangTypeUtil;
import com.cisco.yangide.core.dom.ASTNamedNode;
import com.cisco.yangide.core.dom.ASTVisitor;
import com.cisco.yangide.core.dom.Module;
import com.cisco.yangide.core.dom.ModuleImport;
import com.cisco.yangide.core.dom.QName;
import com.cisco.yangide.core.dom.SimpleNode;
import com.cisco.yangide.core.dom.SubModule;
import com.cisco.yangide.core.dom.SubModuleInclude;
import com.cisco.yangide.core.dom.TypeReference;
import com.cisco.yangide.core.dom.UsesNode;
import com.cisco.yangide.core.indexing.ElementIndexInfo;
import com.cisco.yangide.core.indexing.ElementIndexType;
/**
* @author Konstantin Zaitsev
* @date Jul 14, 2014
*/
public class SemanticValidations {
private IYangValidationListener listener;
private Module module;
private IProject project;
public SemanticValidations(IYangValidationListener validationListener, IProject project, Module module) {
this.listener = validationListener;
this.project = project;
this.module = module;
}
/**
* Validates model for semantics rules.
*/
public void validate() {
validateImports();
validateSubModule();
validatesGrouping();
validateTypes();
}
/**
* Validates for correct submodule relationship.
*/
private void validateSubModule() {
if (module instanceof SubModule) {
SubModule subModule = (SubModule) module;
SimpleNode<String> pmNode = subModule.getParentModule();
if (pmNode != null) {
ElementIndexInfo[] infos = search(null, null, pmNode.getValue(), ElementIndexType.MODULE, project, null);
if (infos.length == 0) {
String msg = String.format("Parent module '%s' not found", pmNode.getValue());
reportError(msg, subModule);
}
}
}
for (SubModuleInclude include : module.getIncludes().values()) {
ElementIndexInfo[] infos = search(null, include.getRevision(), include.getName(),
ElementIndexType.SUBMODULE, project, null);
if (infos.length == 0) {
String msg = String.format("Not existing submodule included: %s:%s by: %s:%s", include.getName(),
include.getRevision(), module.getName(), module.getRevision());
reportError(msg, include);
}
}
}
/**
* Validates for import existence.
*/
private void validateImports() {
for (ModuleImport moduleImport : module.getImports().values()) {
ElementIndexInfo[] infos = search(null, moduleImport.getRevision(), moduleImport.getName(),
ElementIndexType.MODULE, project, null);
if (infos.length == 0) {
String msg = String.format("Not existing module imported: %s:%s by: %s:%s", moduleImport.getName(),
moduleImport.getRevision(), module.getName(), module.getRevision());
reportError(msg, moduleImport);
}
}
}
/**
* Validates grouping existence in <code>uses</code> statement.
*/
private void validatesGrouping() {
module.accept(new ASTVisitor() {
@Override
public boolean visit(UsesNode uses) {
String name = uses.getName();
QName grouping = uses.getGrouping();
if (search(grouping.getModule(), grouping.getRevision(), grouping.getName(), ElementIndexType.GROUPING,
project, null).length == 0) {
reportError(String.format("Grouping '%s' not found", name), uses);
}
return true;
}
});
}
/**
* Validates types existence in <code>type</code> statement.
*/
private void validateTypes() {
module.accept(new ASTVisitor() {
@Override
public boolean visit(TypeReference typeRef) {
String name = typeRef.getName();
QName type = typeRef.getType();
if (YangTypeUtil.isBuiltInType(name)) {
return true;
}
if (search(type.getModule(), type.getRevision(), type.getName(), ElementIndexType.TYPE, project, null).length == 0) {
reportError(String.format("Type '%s' not found", name), typeRef);
}
return true;
}
});
}
/**
* Reports error message to listener.
*
* @param msg message
* @param node related AST node
*/
private void reportError(String msg, ASTNamedNode node) {
listener.validationError(msg, node.getLineNumber(), node.getNameStartPosition(), node.getNameStartPosition()
+ node.getNameLength());
}
}