blob: 8cfe77943c617ada17b029ae168ca9b92400e086 [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.onosproject.yangutils.linker.impl;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.onosproject.yangutils.datamodel.ResolvableType;
import org.onosproject.yangutils.datamodel.YangImport;
import org.onosproject.yangutils.datamodel.YangInclude;
import org.onosproject.yangutils.datamodel.YangNode;
import org.onosproject.yangutils.datamodel.YangReferenceResolver;
import org.onosproject.yangutils.datamodel.YangSubModule;
import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
import org.onosproject.yangutils.linker.YangLinker;
import org.onosproject.yangutils.linker.exceptions.LinkerException;
import static org.onosproject.yangutils.utils.UtilConstants.NEW_LINE;
/**
* Representation of entity which provides linking service of YANG files.
*/
public class YangLinkerManager
implements YangLinker {
/*
* Set of all the YANG nodes, corresponding to the YANG files parsed by
* parser.
*/
Set<YangNode> yangNodeSet = new HashSet<>();
/**
* Returns set of YANG node.
*
* @return set of YANG node
*/
public Set<YangNode> getYangNodeSet() {
return yangNodeSet;
}
/**
* Creates YANG nodes set.
*
* @param yangNodeSet YANG node information set
*/
public void createYangNodeSet(Set<YangNode> yangNodeSet) {
getYangNodeSet().addAll(yangNodeSet);
}
@Override
public void resolveDependencies(Set<YangNode> yangNodeSet) {
// Create YANG node set.
createYangNodeSet(yangNodeSet);
// Carry out linking of sub module with module.
linkSubModulesToParentModule(yangNodeSet);
// Add references to import list.
addRefToYangFilesImportList(yangNodeSet);
// Add reference to include list.
addRefToYangFilesIncludeList(yangNodeSet);
// Update the priority for all the files.
updateFilePriority(yangNodeSet);
// TODO check for circular import/include.
// Carry out inter-file linking.
processInterFileLinking(yangNodeSet);
}
/**
* Resolves sub-module linking by linking sub module with parent module.
*
* @param yangNodeSet set of YANG files info
* @throws LinkerException fails to link sub-module to parent module
*/
public void linkSubModulesToParentModule(Set<YangNode> yangNodeSet)
throws LinkerException {
for (YangNode yangNode : yangNodeSet) {
if (yangNode instanceof YangSubModule) {
try {
((YangSubModule) yangNode).linkWithModule(getYangNodeSet());
} catch (DataModelException e) {
String errorInfo = "YANG file error: " + yangNode.getName() + " at line: "
+ e.getLineNumber() + " at position: " + e.getCharPositionInLine() + NEW_LINE
+ e.getMessage();
throw new LinkerException(errorInfo);
// TODO add file path in exception message in util manager.
}
}
}
}
/**
* Adds imported node information to the import list.
*
* @param yangNodeSet set of YANG files info
* @throws LinkerException fails to find imported module
*/
public void addRefToYangFilesImportList(Set<YangNode> yangNodeSet) throws LinkerException {
for (YangNode yangNode : yangNodeSet) {
if (yangNode instanceof YangReferenceResolver) {
try {
((YangReferenceResolver) yangNode).addReferencesToImportList(getYangNodeSet());
} catch (DataModelException e) {
String errorInfo = "Error in file: " + yangNode.getName() + " at line: "
+ e.getLineNumber() + " at position: " + e.getCharPositionInLine() + NEW_LINE
+ e.getMessage();
throw new LinkerException(errorInfo);
// TODO add file path in exception message in util manager.
}
}
}
}
/**
* Adds included node information to the include list.
*
* @param yangNodeSet set of YANG files info
* @throws LinkerException fails to find included sub-module
*/
public void addRefToYangFilesIncludeList(Set<YangNode> yangNodeSet) throws LinkerException {
for (YangNode yangNode : yangNodeSet) {
if (yangNode instanceof YangReferenceResolver) {
try {
((YangReferenceResolver) yangNode).addReferencesToIncludeList(getYangNodeSet());
} catch (DataModelException e) {
String errorInfo = "Error in file: " + yangNode.getName() + " at line: "
+ e.getLineNumber() + " at position: " + e.getCharPositionInLine() + NEW_LINE
+ e.getMessage();
throw new LinkerException(errorInfo);
// TODO add file path in exception message in util manager.
}
}
}
}
/**
* Processes inter file linking for type and uses.
*
* @param yangNodeSet set of YANG files info
* @throws LinkerException a violation in linker execution
*/
public void processInterFileLinking(Set<YangNode> yangNodeSet)
throws LinkerException {
List<YangNode> yangNodeSortedList = new LinkedList<>();
yangNodeSortedList.addAll(yangNodeSet);
Collections.sort(yangNodeSortedList);
for (YangNode yangNode : yangNodeSortedList) {
try {
((YangReferenceResolver) yangNode)
.resolveInterFileLinking(ResolvableType.YANG_IF_FEATURE);
((YangReferenceResolver) yangNode)
.resolveInterFileLinking(ResolvableType.YANG_USES);
((YangReferenceResolver) yangNode)
.resolveInterFileLinking(ResolvableType.YANG_AUGMENT);
((YangReferenceResolver) yangNode)
.resolveInterFileLinking(ResolvableType.YANG_DERIVED_DATA_TYPE);
((YangReferenceResolver) yangNode)
.resolveInterFileLinking(ResolvableType.YANG_LEAFREF);
((YangReferenceResolver) yangNode)
.resolveInterFileLinking(ResolvableType.YANG_BASE);
((YangReferenceResolver) yangNode)
.resolveInterFileLinking(ResolvableType.YANG_IDENTITYREF);
} catch (DataModelException e) {
String errorInfo = "Error in file: " + yangNode.getName() + " at line: "
+ e.getLineNumber() + " at position: " + e.getCharPositionInLine() + NEW_LINE + e.getMessage();
throw new LinkerException(errorInfo);
// TODO add file path in exception message in util manager.
}
}
}
/**
* Updates the priority for all the input files.
*
* @param yangNodeSet set of YANG files info
*/
public void updateFilePriority(Set<YangNode> yangNodeSet) {
for (YangNode yangNode : yangNodeSet) {
updateFilePriorityOfNode(yangNode);
}
}
/**
* Updates priority of the node.
*
* @param yangNode YANG node information
*/
public void updateFilePriorityOfNode(YangNode yangNode) {
int curNodePriority = yangNode.getPriority();
if (yangNode instanceof YangReferenceResolver) {
List<YangImport> yangImportList = ((YangReferenceResolver) yangNode).getImportList();
if (yangImportList != null && !yangImportList.isEmpty()) {
Iterator<YangImport> importInfoIterator = yangImportList.iterator();
// Run through the imported list to update priority.
while (importInfoIterator.hasNext()) {
YangImport yangImport = importInfoIterator.next();
YangNode importedNode = yangImport.getImportedNode();
if (curNodePriority >= importedNode.getPriority()) {
importedNode.setPriority(curNodePriority + 1);
updateFilePriorityOfNode(importedNode);
}
}
}
List<YangInclude> yangIncludeList = ((YangReferenceResolver) yangNode).getIncludeList();
if (yangIncludeList != null && !yangIncludeList.isEmpty()) {
Iterator<YangInclude> includeInfoIterator = yangIncludeList.iterator();
// Run through the imported list to update priority.
while (includeInfoIterator.hasNext()) {
YangInclude yangInclude = includeInfoIterator.next();
YangNode includedNode = yangInclude.getIncludedNode();
if (curNodePriority >= includedNode.getPriority()) {
includedNode.setPriority(curNodePriority + 1);
updateFilePriorityOfNode(includedNode);
}
}
}
}
}
}