summaryrefslogtreecommitdiffstats
path: root/yang-comparator/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'yang-comparator/src/main')
-rw-r--r--yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/WhenMustComparator.java34
-rw-r--r--yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangComparator.java594
-rw-r--r--yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangComparatorRegister.java136
-rw-r--r--yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangCompareResult.java65
-rw-r--r--yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangCompareResultSerializer.java69
-rw-r--r--yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangCompareResultXmlSerializer.java259
-rw-r--r--yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangStatementComparator.java31
-rw-r--r--yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangStatementCompareResult.java119
-rw-r--r--yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangTreeCompareResult.java209
-rw-r--r--yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangTreeMetaCompareResult.java124
-rw-r--r--yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/app/YangComparatorPlugin.java157
-rw-r--r--yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/app/YangComparatorRunner.java218
-rw-r--r--yang-comparator/src/main/resources/plugins.json34
-rw-r--r--yang-comparator/src/main/resources/rules.xml563
14 files changed, 2612 insertions, 0 deletions
diff --git a/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/WhenMustComparator.java b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/WhenMustComparator.java
new file mode 100644
index 0000000..cc6992a
--- /dev/null
+++ b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/WhenMustComparator.java
@@ -0,0 +1,34 @@
+/*
+Copyright 2023 Huawei Technologies
+
+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.onap.modeling.yangkit.comparator;
+
+import org.yangcentral.yangkit.model.api.stmt.YangStatement;
+
+public class WhenMustComparator extends CommonYangStatementComparator {
+ @Override
+ protected CompatibilityInfo defaultCompatibility(YangStatement left, YangStatement right,
+ CompatibilityRule.ChangeInfo changeInfo) {
+ if (changeInfo == CompatibilityRule.ChangeInfo.ADDED) {
+ return new CompatibilityInfo(CompatibilityRule.Compatibility.NBC,
+ "add a new when/must, it's non-backward-compatible.");
+ } else if (changeInfo == CompatibilityRule.ChangeInfo.CHANGED) {
+ return new CompatibilityInfo(CompatibilityRule.Compatibility.UNKNOWN,
+ "change a when/must, the compatibility is unknown.");
+ }
+ return super.defaultCompatibility(left, right, changeInfo);
+ }
+}
diff --git a/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangComparator.java b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangComparator.java
new file mode 100644
index 0000000..0650879
--- /dev/null
+++ b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangComparator.java
@@ -0,0 +1,594 @@
+/*
+Copyright 2023 Huawei Technologies
+
+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.onap.modeling.yangkit.comparator;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.dom4j.Attribute;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+import org.yangcentral.yangkit.base.YangElement;
+import org.yangcentral.yangkit.common.api.Namespace;
+import org.yangcentral.yangkit.model.api.schema.YangSchemaContext;
+import org.yangcentral.yangkit.model.api.stmt.Augment;
+import org.yangcentral.yangkit.model.api.stmt.MainModule;
+import org.yangcentral.yangkit.model.api.stmt.Module;
+import org.yangcentral.yangkit.model.api.stmt.SchemaNode;
+import org.yangcentral.yangkit.model.api.stmt.SchemaNodeContainer;
+import org.yangcentral.yangkit.model.api.stmt.Status;
+import org.yangcentral.yangkit.model.api.stmt.StatusStmt;
+import org.yangcentral.yangkit.model.api.stmt.SubModule;
+import org.yangcentral.yangkit.model.api.stmt.VirtualSchemaNode;
+import org.yangcentral.yangkit.model.api.stmt.YangBuiltinStatement;
+import org.yangcentral.yangkit.model.api.stmt.YangStatement;
+import org.yangcentral.yangkit.model.api.stmt.YangUnknown;
+
+
+public class YangComparator {
+ private final YangSchemaContext leftContext;
+ private final YangSchemaContext rightContext;
+ private CompatibilityRules compatibilityRules;
+
+ /**
+ * constructor.
+ *
+ * @param leftContext left schema context (older)
+ * @param rightContext right schema context (newer)
+ */
+ public YangComparator(YangSchemaContext leftContext, YangSchemaContext rightContext) {
+ this.leftContext = leftContext;
+ this.rightContext = rightContext;
+ }
+
+ /**
+ * get compatibility rules.
+ *
+ * @return rules
+ */
+ public CompatibilityRules getCompatibilityRules() {
+ return compatibilityRules;
+ }
+
+ /**
+ * set compatibility rules.
+ *
+ * @param compatibilityRules rules
+ */
+ public void setCompatibilityRules(CompatibilityRules compatibilityRules) {
+ this.compatibilityRules = compatibilityRules;
+ }
+
+ /**
+ * get module tree nodes from module.
+ *
+ * @param module module
+ * @return list of tree nodes
+ */
+ public static List<SchemaNode> getModuleTreeNodes(MainModule module) {
+ List<SchemaNode> effectiveSchemaNodeChildren = new ArrayList<>();
+ effectiveSchemaNodeChildren.addAll(getEffectiveSchemaNodeChildren(module));
+ for (Augment augment : module.getAugments()) {
+ effectiveSchemaNodeChildren.addAll(getEffectiveSchemaNodeChildren(augment));
+ }
+ return effectiveSchemaNodeChildren;
+ }
+
+ /**
+ * get effective schema node children.
+ *
+ * @param schemaNodeContainer schema node container.
+ * @return list of children
+ */
+ public static List<SchemaNode> getEffectiveSchemaNodeChildren(SchemaNodeContainer schemaNodeContainer) {
+ List<SchemaNode> effectiveSchemaNodeChildren = new ArrayList<>();
+ for (SchemaNode schemaNode : schemaNodeContainer.getSchemaNodeChildren()) {
+ if (schemaNode instanceof VirtualSchemaNode) {
+ VirtualSchemaNode virtualSchemaNode = (VirtualSchemaNode) schemaNode;
+ effectiveSchemaNodeChildren.addAll(getEffectiveSchemaNodeChildren(virtualSchemaNode));
+ } else {
+ if (schemaNodeContainer instanceof YangStatement) {
+ YangStatement parent = (YangStatement) schemaNodeContainer;
+ Namespace parentNs = parent.getContext().getNamespace();
+ Namespace childNs = schemaNode.getContext().getNamespace();
+ if (parentNs != null && childNs != null && parentNs.getUri().equals(childNs.getUri())) {
+ effectiveSchemaNodeChildren.add(schemaNode);
+ }
+ } else {
+ effectiveSchemaNodeChildren.add(schemaNode);
+ }
+ }
+
+
+ }
+ return effectiveSchemaNodeChildren;
+ }
+
+ /**
+ * compare the left and right statement.
+ *
+ * @param left left statement
+ * @param right right statement
+ * @return compare result.
+ */
+ public List<YangCompareResult> compareStatement(YangStatement left, YangStatement right) {
+ return compareStatement(left, right, false);
+ }
+
+ /**
+ * compare the left and right statements
+ *
+ * @param leftElements list of left statements
+ * @param rightElements list of right statements
+ * @param exceptSchemaNode whether except schema node
+ * @return list of compare results.
+ */
+ public List<YangCompareResult> compareStatement(List<? extends YangElement> leftElements,
+ List<? extends YangElement> rightElements,
+ boolean exceptSchemaNode) {
+ List<YangCompareResult> compareResults = new ArrayList<>();
+ List<YangStatement> foundStatements = new ArrayList<>();
+
+ if (leftElements.size() > 0) {
+ for (YangElement subElement : leftElements) {
+ if (!(subElement instanceof YangStatement)) {
+ continue;
+ }
+ YangStatement leftSubStatement = (YangStatement) subElement;
+ if (exceptSchemaNode) {
+ if (leftSubStatement instanceof SchemaNode) {
+ continue;
+ }
+ }
+
+ List<YangStatement> rightSubStatements = new ArrayList<>();
+ for (YangElement rightElement : rightElements) {
+ if (!(rightElement instanceof YangStatement)) {
+ continue;
+ }
+ if (leftSubStatement.getYangKeyword().equals(((YangStatement) rightElement).getYangKeyword())) {
+ rightSubStatements.add((YangStatement) rightElement);
+ }
+ }
+ if (rightSubStatements.size() == 0) {
+ //no right statement, so change type is delete
+ YangStatementCompareResult yangStatementCompareResult =
+ new YangStatementCompareResult(ChangeType.DELETE, leftSubStatement, null);
+ compareResults.add(yangStatementCompareResult);
+ continue;
+ }
+ YangStatement matchedRightSubStatement =
+ CommonYangStatementComparator.searchStatement(leftSubStatement, rightSubStatements,
+ foundStatements);
+ if (null == matchedRightSubStatement) {
+ YangStatementCompareResult yangStatementCompareResult =
+ new YangStatementCompareResult(ChangeType.DELETE, leftSubStatement, null);
+ compareResults.add(yangStatementCompareResult);
+ } else {
+ foundStatements.add(matchedRightSubStatement);
+ compareResults.addAll(
+ compareStatement(leftSubStatement, matchedRightSubStatement, exceptSchemaNode));
+ }
+ }
+ }
+ if (rightElements.size() > 0) {
+ for (YangElement subElement : rightElements) {
+ if (!(subElement instanceof YangStatement)) {
+ continue;
+ }
+ if (exceptSchemaNode) {
+ if (subElement instanceof SchemaNode) {
+ continue;
+ }
+ }
+ YangStatement rightSubElement = (YangStatement) subElement;
+ if (CommonYangStatementComparator.contains(foundStatements, rightSubElement)) {
+ continue;
+ }
+ YangStatementCompareResult yangStatementCompareResult = new YangStatementCompareResult(ChangeType.ADD,
+ null, rightSubElement);
+ compareResults.add(yangStatementCompareResult);
+ }
+ }
+ return compareResults;
+ }
+
+ /**
+ * compare left and right statement.
+ *
+ * @param left left statement
+ * @param right right statement
+ * @param exceptSchemaNode whether except schema node
+ * @return list of compare result.
+ */
+ public List<YangCompareResult> compareStatement(YangStatement left, YangStatement right, boolean exceptSchemaNode) {
+ List<YangCompareResult> compareResults = new ArrayList<>();
+ if (left == null && right == null) {
+ return compareResults;
+ }
+ if (left == null && right != null) {
+ YangStatementCompareResult compareResult = new YangStatementCompareResult(ChangeType.ADD, left, right);
+ compareResults.add(compareResult);
+ return compareResults;
+ }
+ if (left != null && right == null) {
+ YangStatementCompareResult compareResult = new YangStatementCompareResult(ChangeType.DELETE, left, right);
+ compareResults.add(compareResult);
+ return compareResults;
+ }
+
+ if (!CommonYangStatementComparator.yangStatementIsEqual(left, right)) {
+ YangStatementCompareResult yangStatementCompareResult = new YangStatementCompareResult(ChangeType.MODIFY,
+ left, right);
+ compareResults.add(yangStatementCompareResult);
+ }
+ compareResults.addAll(compareStatement(left.getSubElements(), right.getSubElements(), exceptSchemaNode));
+ return compareResults;
+ }
+
+ /**
+ * compare statements of left and right schema context.
+ *
+ * @return list of compare results
+ */
+ public List<YangCompareResult> compareStatement() {
+ List<YangCompareResult> compareResults = new ArrayList<>();
+ List<Module> foundModules = new ArrayList<>();
+ List<Module> modules = leftContext.getModules();
+ for (Module module : modules) {
+ List<Module> rightModules = rightContext.getModule(module.getArgStr());
+ if (rightModules == null || rightModules.size() == 0) {
+ //not find
+ YangStatementCompareResult yangStatementCompareResult =
+ new YangStatementCompareResult(ChangeType.DELETE,
+ module, null);
+ compareResults.add(yangStatementCompareResult);
+ } else {
+ Module rightModule = rightModules.get(0);
+ foundModules.add(rightModule);
+ compareResults.addAll(compareStatement(module, rightModule));
+ }
+ }
+ for (Module rightModule : rightContext.getModules()) {
+ if (rightModule instanceof SubModule) {
+ continue;
+ }
+ if (CommonYangStatementComparator.contains(foundModules, rightModule)) {
+ continue;
+ }
+ YangStatementCompareResult yangStatementCompareResult =
+ new YangStatementCompareResult(ChangeType.ADD, null, rightModule);
+ compareResults.add(yangStatementCompareResult);
+ }
+ return compareResults;
+ }
+
+ /**
+ * resort the compare results.
+ *
+ * @param results original results
+ * @return sorted results
+ */
+ public Map<String, List<YangCompareResult>> resortYangCompareResult(List<YangCompareResult> results) {
+ Map<String, List<YangCompareResult>> map = new HashMap<>();
+ for (YangCompareResult yangCompareResult : results) {
+ String module = yangCompareResult.getModule().getArgStr();
+ List<YangCompareResult> mapResults = map.get(module);
+ if (null == mapResults) {
+ mapResults = new ArrayList<>();
+ map.put(module, mapResults);
+ }
+ mapResults.add(yangCompareResult);
+
+ }
+ return map;
+ }
+
+ private String outputCompareResult(List<YangCompareResult> compareResults) {
+ Map<String, List<YangCompareResult>> resortedResults = resortYangCompareResult(compareResults);
+ StringBuffer sb = new StringBuffer();
+ Iterator<Map.Entry<String, List<YangCompareResult>>> it = resortedResults.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<String, List<YangCompareResult>> entry = it.next();
+ sb.append("module:").append(entry.getKey()).append("\n");
+ sb.append("\t").append("added:\n");
+ List<YangCompareResult> value = entry.getValue();
+ for (YangCompareResult result : value) {
+ if (result.getChangeType() != ChangeType.ADD) {
+ continue;
+ }
+ sb.append(result.getChangeDescription("\t\t")).append("\n");
+ }
+ sb.append("\t").append("deleted:\n");
+ for (YangCompareResult result : value) {
+ if (result.getChangeType() != ChangeType.DELETE) {
+ continue;
+ }
+ sb.append(result.getChangeDescription("\t\t")).append("\n");
+ }
+ sb.append("\t").append("changed:\n");
+ for (YangCompareResult result : value) {
+ if (result.getChangeType() != ChangeType.MODIFY) {
+ continue;
+ }
+ sb.append(result.getChangeDescription("\t\t")).append("\n");
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * output the xml format results.
+ *
+ * @param compareResults original results
+ * @param compareType compare type
+ * @return xml format results
+ */
+ public Document outputXmlCompareResult(List<YangCompareResult> compareResults, CompareType compareType) {
+ return outputXmlCompareResult(compareResults, true, compareType);
+ }
+
+ /**
+ * output the xml format results.
+ *
+ * @param compareResults original results
+ * @param needCompatible whether need compatibility result.
+ * @param compareType compare type
+ * @return xml format results
+ */
+ public Document outputXmlCompareResult(List<YangCompareResult> compareResults, boolean needCompatible,
+ CompareType compareType) {
+ Map<String, List<YangCompareResult>> resortedResults = resortYangCompareResult(compareResults);
+ Element root = DocumentHelper.createElement("modules");
+ Document document = DocumentHelper.createDocument(root);
+ Iterator<Map.Entry<String, List<YangCompareResult>>> it = resortedResults.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<String, List<YangCompareResult>> entry = it.next();
+ List<YangCompareResult> value = entry.getValue();
+ if (value.size() == 0) {
+ continue;
+ }
+ Element moduleElement = DocumentHelper.createElement("module");
+ root.add(moduleElement);
+ Attribute name = DocumentHelper.createAttribute(moduleElement, "name", entry.getKey());
+ moduleElement.add(name);
+ if (compareType == CompareType.COMPATIBLE_CHECK || compareType == CompareType.STMT) {
+ Element addedStmts = DocumentHelper.createElement("added-statements");
+ moduleElement.add(addedStmts);
+ Element deletedStmts = DocumentHelper.createElement("deleted-statements");
+ moduleElement.add(deletedStmts);
+ Element changedStmts = DocumentHelper.createElement("changed-statements");
+ moduleElement.add(changedStmts);
+ for (YangCompareResult result : value) {
+ if (!(result instanceof YangStatementCompareResult)) {
+ continue;
+ }
+ if (result.getChangeType() != ChangeType.ADD) {
+ continue;
+ }
+ addedStmts.add((Element) YangCompareResultSerializer.getXmlSerializer(result)
+ .serialize(false, false, false, needCompatible));
+ }
+ for (YangCompareResult result : value) {
+ if (!(result instanceof YangStatementCompareResult)) {
+ continue;
+ }
+ if (result.getChangeType() != ChangeType.DELETE) {
+ continue;
+ }
+ deletedStmts.add((Element) YangCompareResultSerializer.getXmlSerializer(result)
+ .serialize(false, false, false, needCompatible));
+ }
+ for (YangCompareResult result : value) {
+ if (!(result instanceof YangStatementCompareResult)) {
+ continue;
+ }
+ if (result.getChangeType() != ChangeType.MODIFY) {
+ continue;
+ }
+ changedStmts.add((Element) YangCompareResultSerializer.getXmlSerializer(result)
+ .serialize(false, false, false, needCompatible));
+ }
+ }
+
+ if (compareType == CompareType.COMPATIBLE_CHECK || compareType == CompareType.TREE) {
+ Element addedPaths = DocumentHelper.createElement("added-paths");
+ moduleElement.add(addedPaths);
+ Element deletedPaths = DocumentHelper.createElement("deleted-paths");
+ moduleElement.add(deletedPaths);
+ Element changedPaths = DocumentHelper.createElement("changed-paths");
+ moduleElement.add(changedPaths);
+
+ for (YangCompareResult result : value) {
+ if (!(result instanceof YangTreeCompareResult)) {
+ continue;
+ }
+ if (result.getChangeType() != ChangeType.ADD) {
+ continue;
+ }
+ addedPaths.add((Element) YangCompareResultSerializer.getXmlSerializer(result)
+ .serialize(false, false, false, needCompatible));
+ }
+ for (YangCompareResult result : value) {
+ if (!(result instanceof YangTreeCompareResult)) {
+ continue;
+ }
+ if (result.getChangeType() != ChangeType.DELETE) {
+ continue;
+ }
+ deletedPaths.add((Element) YangCompareResultSerializer.getXmlSerializer(result)
+ .serialize(false, false, false, needCompatible));
+ }
+ for (YangCompareResult result : value) {
+ if (!(result instanceof YangTreeCompareResult)) {
+ continue;
+ }
+ if (result.getChangeType() != ChangeType.MODIFY) {
+ continue;
+ }
+ changedPaths.add((Element) YangCompareResultSerializer.getXmlSerializer(result)
+ .serialize(false, false, true, needCompatible));
+ }
+ Element obsoleted = DocumentHelper.createElement("obsoleted-paths");
+ moduleElement.add(obsoleted);
+ for (YangCompareResult result : value) {
+ if (!(result instanceof YangTreeCompareResult)) {
+ continue;
+ }
+ if (result.getChangeType() != ChangeType.MODIFY) {
+ continue;
+ }
+ YangTreeCompareResult yangTreeCompareResult = (YangTreeCompareResult) result;
+ if (yangTreeCompareResult.getMetaCompareResults().size() == 0) {
+ continue;
+ }
+ YangTreeMetaCompareResult find = null;
+ for (YangCompareResult metaCompareResult : yangTreeCompareResult.getMetaCompareResults()) {
+ YangStatementCompareResult yangStatementCompareResult =
+ (YangStatementCompareResult) metaCompareResult;
+ if (yangStatementCompareResult.getRight() instanceof StatusStmt) {
+ StatusStmt right = (StatusStmt) yangStatementCompareResult.getRight();
+ if (right.getStatus() == Status.OBSOLETE) {
+ obsoleted.add(
+ (Element) YangCompareResultSerializer.getXmlSerializer(result)
+ .serialize(false, false, false, false));
+ }
+ }
+ }
+
+ }
+ Element deprecated = DocumentHelper.createElement("deprecated-paths");
+ moduleElement.add(deprecated);
+ for (YangCompareResult result : value) {
+ if (!(result instanceof YangTreeCompareResult)) {
+ continue;
+ }
+ if (result.getChangeType() != ChangeType.MODIFY) {
+ continue;
+ }
+ YangTreeCompareResult yangTreeCompareResult = (YangTreeCompareResult) result;
+ if (yangTreeCompareResult.getMetaCompareResults().size() == 0) {
+ continue;
+ }
+ YangTreeMetaCompareResult find = null;
+ for (YangCompareResult metaCompareResult : yangTreeCompareResult.getMetaCompareResults()) {
+ YangStatementCompareResult yangStatementCompareResult =
+ (YangStatementCompareResult) metaCompareResult;
+ if (yangStatementCompareResult.getRight() instanceof StatusStmt) {
+ StatusStmt right = (StatusStmt) yangStatementCompareResult.getRight();
+ if (right.getStatus() == Status.DEPRECATED) {
+ obsoleted.add(
+ (Element) YangCompareResultSerializer.getXmlSerializer(result)
+ .serialize(false, false, false, false));
+ }
+ }
+ }
+
+ }
+ }
+ }
+ return document;
+ }
+
+ /**
+ * output statement to string.
+ *
+ * @param statement yang statement
+ * @return string
+ */
+ public static String outputStatement(YangStatement statement) {
+ StringBuffer sb = new StringBuffer();
+ if (statement instanceof YangBuiltinStatement) {
+ sb.append(statement.getYangKeyword().getLocalName());
+ } else {
+ YangUnknown unknown = (YangUnknown) statement;
+ sb.append(unknown.getKeyword());
+ }
+ if (statement.getArgStr() != null) {
+ sb.append(" ").append(statement.getArgStr());
+ }
+ return sb.toString();
+ }
+
+ /**
+ * compare statements according to compare type and rule.
+ *
+ * @param compareType compare type
+ * @param rule rule file path
+ * @return list of results
+ * @throws DocumentException document exception
+ */
+ public List<YangCompareResult> compare(CompareType compareType, String rule) throws DocumentException {
+ if (rule != null) {
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new File(rule));
+ CompatibilityRules.getInstance().deserialize(document);
+ }
+ List<YangCompareResult> compareResults = new ArrayList<>();
+ if (compareType == CompareType.STMT) {
+ compareResults = compareStatement();
+
+ } else if (compareType == CompareType.TREE) {
+ List<Module> matched = new ArrayList<>();
+ for (Module leftModule : leftContext.getModules()) {
+ if (!(leftModule instanceof MainModule)) {
+ continue;
+ }
+ List<SchemaNode> leftSchemaNodes = getModuleTreeNodes((MainModule) leftModule);
+ Module matchedModule = null;
+ for (Module rightModule : rightContext.getModules()) {
+ if (rightModule.getArgStr().equals(leftModule.getArgStr())) {
+ matched.add(rightModule);
+ matchedModule = rightModule;
+ break;
+ }
+ }
+ List<SchemaNode> rightSchemaNodes = new ArrayList<>();
+ if (null != matchedModule) {
+ rightSchemaNodes.addAll(getModuleTreeNodes((MainModule) matchedModule));
+ }
+ compareResults.addAll(CommonYangStatementComparator.compareStatements(leftSchemaNodes, rightSchemaNodes,
+ CommonYangStatementComparator.OPTION_ONLY_SCHEMA));
+ }
+ for (Module rightModule : rightContext.getModules()) {
+ if (matched.contains(rightModule)) {
+ continue;
+ }
+ if (!(rightModule instanceof MainModule)) {
+ continue;
+ }
+ compareResults.addAll(
+ CommonYangStatementComparator.compareStatements(new ArrayList<>(), getModuleTreeNodes(
+ (MainModule) rightModule), CommonYangStatementComparator.OPTION_ONLY_SCHEMA));
+ }
+ } else if (compareType == CompareType.COMPATIBLE_CHECK) {
+ compareResults = CommonYangStatementComparator.compareStatements(
+ leftContext.getModules(), rightContext.getModules(), CommonYangStatementComparator.OPTION_ALL
+ );
+ }
+ return compareResults;
+ }
+
+
+}
diff --git a/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangComparatorRegister.java b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangComparatorRegister.java
new file mode 100644
index 0000000..db54d35
--- /dev/null
+++ b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangComparatorRegister.java
@@ -0,0 +1,136 @@
+/*
+Copyright 2023 Huawei Technologies
+
+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.onap.modeling.yangkit.comparator;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import org.yangcentral.yangkit.base.YangBuiltinKeyword;
+
+
+public class YangComparatorRegister {
+ private static final YangComparatorRegister ourInstance = new YangComparatorRegister();
+ private final Map<String, YangStatementComparator> policyMap = new ConcurrentHashMap<>();
+
+ /**
+ * get register instance.
+ *
+ * @return instance
+ */
+ public static YangComparatorRegister getInstance() {
+ return ourInstance;
+ }
+
+ private YangComparatorRegister() {
+ inlineRegister();
+ }
+
+ /**
+ * register comparator.
+ *
+ * @param yangKeyword keyword
+ * @param comparator comparator
+ */
+ public void registerComparator(String yangKeyword, YangStatementComparator comparator) {
+ policyMap.put(yangKeyword, comparator);
+ }
+
+ /**
+ * get comparator by yang keyword.
+ *
+ * @param yangKeyword yang keyword
+ * @return comparator
+ */
+ public YangStatementComparator getComparator(String yangKeyword) {
+ if (yangKeyword == null) {
+ return new CommonYangStatementComparator();
+ }
+ YangStatementComparator comparator = policyMap.get(yangKeyword);
+ if (comparator == null) {
+ return new CommonYangStatementComparator();
+ }
+ return comparator;
+ }
+
+ private void inlineRegister() {
+ //config
+ registerComparator(YangBuiltinKeyword.CONFIG.getKeyword(), new ConfigComparator());
+ //enum,bit
+ registerComparator(YangBuiltinKeyword.ENUM.getKeyword(), new EnumBitComparator());
+ registerComparator(YangBuiltinKeyword.BIT.getKeyword(), new EnumBitComparator());
+ //module
+ registerComparator(YangBuiltinKeyword.MODULE.getKeyword(), new ModuleComparator());
+ registerComparator(YangBuiltinKeyword.SUBMODULE.getKeyword(), new ModuleComparator());
+ //namespace
+ registerComparator(YangBuiltinKeyword.NAMESPACE.getKeyword(), new NamespaceComparator());
+ //schema node
+ registerComparator(YangBuiltinKeyword.CONTAINER.getKeyword(), new SchemaNodeComparator());
+ registerComparator(YangBuiltinKeyword.LIST.getKeyword(), new SchemaNodeComparator());
+ registerComparator(YangBuiltinKeyword.CHOICE.getKeyword(), new SchemaNodeComparator());
+ registerComparator(YangBuiltinKeyword.CASE.getKeyword(), new SchemaNodeComparator());
+ registerComparator(YangBuiltinKeyword.RPC.getKeyword(), new OperationComparator());
+ registerComparator(YangBuiltinKeyword.ACTION.getKeyword(), new OperationComparator());
+ registerComparator(YangBuiltinKeyword.INPUT.getKeyword(), new SchemaNodeComparator());
+ registerComparator(YangBuiltinKeyword.OUTPUT.getKeyword(), new SchemaNodeComparator());
+ registerComparator(YangBuiltinKeyword.NOTIFICATION.getKeyword(), new SchemaNodeComparator());
+ registerComparator(YangBuiltinKeyword.LEAFLIST.getKeyword(), new SchemaNodeComparator());
+ registerComparator(YangBuiltinKeyword.LEAF.getKeyword(), new SchemaNodeComparator());
+ registerComparator(YangBuiltinKeyword.ANYDATA.getKeyword(), new SchemaNodeComparator());
+ registerComparator(YangBuiltinKeyword.ANYXML.getKeyword(), new SchemaNodeComparator());
+ registerComparator(YangBuiltinKeyword.AUGMENT.getKeyword(), new AugmentComparator());
+ //type
+ registerComparator(YangBuiltinKeyword.TYPE.getKeyword(), new TypeStatementComparator());
+ //value
+ registerComparator(YangBuiltinKeyword.VALUE.getKeyword(), new ValuePositionComparator());
+ //position
+ registerComparator(YangBuiltinKeyword.POSITION.getKeyword(), new ValuePositionComparator());
+ //range
+ registerComparator(YangBuiltinKeyword.RANGE.getKeyword(), new RangeLengthComparator());
+ //length
+ registerComparator(YangBuiltinKeyword.LENGTH.getKeyword(), new RangeLengthComparator());
+ //pattern
+ registerComparator(YangBuiltinKeyword.PATTERN.getKeyword(), new PatternComparator());
+ //default
+ registerComparator(YangBuiltinKeyword.DEFAULT.getKeyword(), new DefaultComparator());
+ //units
+ registerComparator(YangBuiltinKeyword.UNITS.getKeyword(), new UnitsComparator());
+ //description
+ registerComparator(YangBuiltinKeyword.DESCRIPTION.getKeyword(), new DescriptionComparator());
+ //reference
+ registerComparator(YangBuiltinKeyword.REFERENCE.getKeyword(), new ReferenceComparator());
+ //when/must
+ registerComparator(YangBuiltinKeyword.WHEN.getKeyword(), new WhenMustComparator());
+ registerComparator(YangBuiltinKeyword.MUST.getKeyword(), new WhenMustComparator());
+ //mandatory
+ registerComparator(YangBuiltinKeyword.MANDATORY.getKeyword(), new MandatoryComparator());
+ //max-elements
+ registerComparator(YangBuiltinKeyword.MAXELEMENTS.getKeyword(), new MaxElementsComparator());
+ //min-elements
+ registerComparator(YangBuiltinKeyword.MINELEMENTS.getKeyword(), new MinElementsComparator());
+ //base
+ registerComparator(YangBuiltinKeyword.BASE.getKeyword(), new BaseComparator());
+ //typedef,extension,feature,identity
+ registerComparator(YangBuiltinKeyword.TYPEDEF.getKeyword(), new IdentifierComparator());
+ registerComparator(YangBuiltinKeyword.EXTENSION.getKeyword(), new IdentifierComparator());
+ registerComparator(YangBuiltinKeyword.FEATURE.getKeyword(), new IdentifierComparator());
+ registerComparator(YangBuiltinKeyword.IDENTITY.getKeyword(), new IdentifierComparator());
+ //if-feature
+ registerComparator(YangBuiltinKeyword.IFFEATURE.getKeyword(), new IfFeatureComparator());
+ //unique
+ registerComparator(YangBuiltinKeyword.UNIQUE.getKeyword(), new UniqueComparator());
+
+ }
+}
diff --git a/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangCompareResult.java b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangCompareResult.java
new file mode 100644
index 0000000..24cafff
--- /dev/null
+++ b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangCompareResult.java
@@ -0,0 +1,65 @@
+/*
+Copyright 2023 Huawei Technologies
+
+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.onap.modeling.yangkit.comparator;
+
+import org.yangcentral.yangkit.model.api.stmt.Module;
+
+
+public interface YangCompareResult<T> {
+ /**
+ * get change type.
+ * @return change type.
+ */
+ ChangeType getChangeType();
+
+ /**
+ * get left.
+ * @return left
+ */
+ T getLeft();
+
+ /**
+ * get right.
+ * @return right
+ */
+ T getRight();
+
+ /**
+ * get change description.
+ * @param indent indent
+ * @return string
+ */
+ String getChangeDescription(String indent);
+
+ /**
+ * get module.
+ * @return module
+ */
+ Module getModule();
+
+ /**
+ * get compatibility info.
+ * @return compatibility info.
+ */
+ CompatibilityInfo getCompatibilityInfo();
+
+ /**
+ * set compatibility info.
+ * @param compatibilityInfo compatibility info
+ */
+ void setCompatibilityInfo(CompatibilityInfo compatibilityInfo);
+}
diff --git a/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangCompareResultSerializer.java b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangCompareResultSerializer.java
new file mode 100644
index 0000000..d96acdc
--- /dev/null
+++ b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangCompareResultSerializer.java
@@ -0,0 +1,69 @@
+/*
+Copyright 2023 Huawei Technologies
+
+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.onap.modeling.yangkit.comparator;
+
+
+public abstract class YangCompareResultSerializer<T> {
+ private final YangCompareResult yangCompareResult;
+
+ /**
+ * constructor.
+ *
+ * @param yangCompareResult result
+ */
+ public YangCompareResultSerializer(YangCompareResult yangCompareResult) {
+ this.yangCompareResult = yangCompareResult;
+ }
+
+ /**
+ * serialize result.
+ *
+ * @return the result of T format.
+ */
+ public abstract T serialize();
+
+ /**
+ * serialize result.
+ *
+ * @param needChangeType whether need change type
+ * @param needMetaPath whether need meta path
+ * @param needMeta whether need meta
+ * @param needCompatibility whether need compatibility.
+ * @return the result of T format.
+ */
+ public abstract T serialize(boolean needChangeType, boolean needMetaPath, boolean needMeta,
+ boolean needCompatibility);
+
+ /**
+ * get compare result.
+ *
+ * @return result.
+ */
+ public YangCompareResult getYangCompareResult() {
+ return yangCompareResult;
+ }
+
+ /**
+ * get xml serializer.
+ *
+ * @param yangCompareResult result
+ * @return xml serializer
+ */
+ public static YangCompareResultSerializer getXmlSerializer(YangCompareResult yangCompareResult) {
+ return new YangCompareResultXmlSerializer(yangCompareResult);
+ }
+}
diff --git a/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangCompareResultXmlSerializer.java b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangCompareResultXmlSerializer.java
new file mode 100644
index 0000000..59ac35a
--- /dev/null
+++ b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangCompareResultXmlSerializer.java
@@ -0,0 +1,259 @@
+/*
+Copyright 2023 Huawei Technologies
+
+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.onap.modeling.yangkit.comparator;
+
+import org.dom4j.Attribute;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+
+
+public class YangCompareResultXmlSerializer extends YangCompareResultSerializer<Element> {
+ /**
+ * constructor.
+ *
+ * @param yangCompareResult result
+ */
+ public YangCompareResultXmlSerializer(YangCompareResult yangCompareResult) {
+ super(yangCompareResult);
+ }
+
+ private void serializeYangStatementCompareResult(YangStatementCompareResult yangStatementCompareResult,
+ Element element,
+ boolean needType, boolean needCompatibility) {
+ //change type
+ if (needType) {
+ Element changeType = DocumentHelper.createElement("type");
+ changeType.setText(yangStatementCompareResult.getChangeType().getName());
+ element.add(changeType);
+ }
+
+ StringBuffer sb = new StringBuffer();
+ sb.append("module:").append(yangStatementCompareResult.getModule().getArgStr()).append(" ");
+ switch (yangStatementCompareResult.getChangeType()) {
+ case ADD: {
+ //statement
+ Attribute name = DocumentHelper.createAttribute(element, "text",
+ YangComparator.outputStatement(yangStatementCompareResult.getRight()));
+ element.add(name);
+ //position
+ Element position = DocumentHelper.createElement("position");
+ element.add(position);
+ position.setText(sb.append(yangStatementCompareResult.getRight()
+ .getElementPosition().getLocation().getLocation()).toString());
+
+
+ break;
+ }
+ case DELETE: {
+ //statement
+ Attribute name = DocumentHelper.createAttribute(element, "text",
+ YangComparator.outputStatement(yangStatementCompareResult.getLeft()));
+ element.add(name);
+ //position
+ Element position = DocumentHelper.createElement("position");
+ element.add(position);
+ position.setText(sb.append(yangStatementCompareResult.getLeft()
+ .getElementPosition().getLocation().getLocation()).toString());
+ break;
+ }
+ case MODIFY: {
+ Attribute name = DocumentHelper.createAttribute(element, "text",
+ YangComparator.outputStatement(yangStatementCompareResult.getRight()));
+ element.add(name);
+ //position
+ Element toPosition = DocumentHelper.createElement("position");
+ element.add(toPosition);
+ toPosition.setText(sb.toString()
+ + yangStatementCompareResult.getRight().getElementPosition().getLocation().getLocation());
+
+ Element from = DocumentHelper.createElement("previous");
+ //statement
+ Element fromStatement = DocumentHelper.createElement("statement");
+ from.add(fromStatement);
+ Attribute fromName = DocumentHelper.createAttribute(fromStatement, "text",
+ YangComparator.outputStatement(yangStatementCompareResult.getLeft()));
+ fromStatement.add(fromName);
+ //position
+ Element fromPosition = DocumentHelper.createElement("position");
+ from.add(fromPosition);
+ fromPosition.setText(sb.toString()
+ + yangStatementCompareResult.getLeft().getElementPosition().getLocation().getLocation());
+ element.add(from);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ //compatible
+ if (needCompatibility) {
+ Element compatibility = DocumentHelper.createElement("compatibility");
+ element.add(compatibility);
+ Attribute type = DocumentHelper.createAttribute(compatibility, "type",
+ yangStatementCompareResult.getCompatibilityInfo().getCompatibility().getName());
+ compatibility.add(type);
+ if (yangStatementCompareResult.getCompatibilityInfo().getDescription() != null) {
+ Element description = DocumentHelper.createElement("description");
+ compatibility.add(description);
+ description.setText(yangStatementCompareResult.getCompatibilityInfo().getDescription());
+ }
+ }
+ }
+
+ private void serializeYangTreeCompareResult(YangTreeCompareResult yangTreeCompareResult, Element element,
+ boolean needType, boolean needMeta,
+ boolean needCompatibility) {
+
+ //change type
+ if (needType) {
+ Element changeType = DocumentHelper.createElement("type");
+ changeType.setText(yangTreeCompareResult.getChangeType().getName());
+ element.add(changeType);
+ }
+
+ //schema-path
+ if (yangTreeCompareResult.getSchemaPath() != null) {
+ Attribute link =
+ DocumentHelper.createAttribute(element, "link", yangTreeCompareResult.getSchemaPath().toString());
+ element.add(link);
+ } else {
+ System.out.println(yangTreeCompareResult.getChangeDescription(" "));
+ }
+
+ //position
+ Element position = DocumentHelper.createElement("position");
+ StringBuffer sb = new StringBuffer();
+ sb.append("module:").append(yangTreeCompareResult.getModule().getArgStr()).append(" ");
+ switch (yangTreeCompareResult.getChangeType()) {
+ case ADD:
+ case MODIFY: {
+ if (yangTreeCompareResult.getRight().getElementPosition() == null) {
+ break;
+ }
+ sb.append(yangTreeCompareResult.getRight().getElementPosition().getLocation().getLocation());
+ position.setText(sb.toString());
+ break;
+ }
+ case DELETE: {
+ sb.append(yangTreeCompareResult.getLeft().getElementPosition().getLocation().getLocation());
+ position.setText(sb.toString());
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ element.add(position);
+ if (needCompatibility) {
+ //compatible
+ Element compatibility = DocumentHelper.createElement("compatibility");
+ element.add(compatibility);
+ Attribute type = DocumentHelper.createAttribute(compatibility, "type",
+ yangTreeCompareResult.getCompatibilityInfo().getCompatibility().getName());
+ compatibility.add(type);
+ if (yangTreeCompareResult.getCompatibilityInfo().getDescription() != null) {
+ Element description = DocumentHelper.createElement("description");
+ compatibility.add(description);
+ description.setText(yangTreeCompareResult.getCompatibilityInfo().getDescription());
+ }
+ }
+
+ //meta difference
+ if (needMeta) {
+ if (yangTreeCompareResult.getMetaCompareResults().size() > 0) {
+ Element metaDiff = DocumentHelper.createElement("metas");
+ for (YangCompareResult yangCompareResult : yangTreeCompareResult.getMetaCompareResults()) {
+ metaDiff.add(new YangCompareResultXmlSerializer(yangCompareResult).serialize(true, false, true,
+ needCompatibility));
+ }
+ element.add(metaDiff);
+ }
+ }
+ }
+
+ private void serializeYangTreeMetaCompareResult(YangTreeMetaCompareResult yangTreeMetaCompareResult,
+ Element element,
+ boolean needType, boolean needPath) {
+ //change type
+ if (needType) {
+ Element changeType = DocumentHelper.createElement("type");
+ changeType.setText(yangTreeMetaCompareResult.getChangeType().getName());
+ element.add(changeType);
+ }
+ if (needPath) {
+ Attribute link = DocumentHelper.createAttribute(element, "link",
+ yangTreeMetaCompareResult.getTarget().getSchemaPath().toString());
+ element.add(link);
+ }
+ //meta
+ Attribute name = DocumentHelper.createAttribute(element, "name", yangTreeMetaCompareResult.getMeta());
+ element.add(name);
+ switch (yangTreeMetaCompareResult.getChangeType()) {
+ case ADD: {
+ Element value = DocumentHelper.createElement("value");
+ value.setText(yangTreeMetaCompareResult.getRight());
+ element.add(value);
+ break;
+ }
+ case DELETE: {
+ Element value = DocumentHelper.createElement("value");
+ value.setText(yangTreeMetaCompareResult.getLeft());
+ element.add(value);
+ break;
+ }
+ case MODIFY: {
+ Element from = DocumentHelper.createElement("from");
+ from.setText(yangTreeMetaCompareResult.getLeft());
+ element.add(from);
+ Element to = DocumentHelper.createElement("to");
+ to.setText(yangTreeMetaCompareResult.getRight());
+ element.add(to);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
+
+ @Override
+ public Element serialize() {
+ return serialize(true, false, true, true);
+ }
+
+ @Override
+ public Element serialize(boolean needChangeType, boolean needMetaPath, boolean needMeta,
+ boolean needCompatibility) {
+ YangCompareResult yangCompareResult = getYangCompareResult();
+ Element element = null;
+ if (yangCompareResult instanceof YangStatementCompareResult) {
+ YangStatementCompareResult yangStatementCompareResult = (YangStatementCompareResult) yangCompareResult;
+ element = DocumentHelper.createElement("statement");
+ serializeYangStatementCompareResult(yangStatementCompareResult, element, needChangeType, needCompatibility);
+ } else if (yangCompareResult instanceof YangTreeCompareResult) {
+ YangTreeCompareResult yangTreeCompareResult = (YangTreeCompareResult) yangCompareResult;
+ element = DocumentHelper.createElement("path");
+ serializeYangTreeCompareResult(yangTreeCompareResult, element, needChangeType, needMeta, needCompatibility);
+ } else if (yangCompareResult instanceof YangTreeMetaCompareResult) {
+ YangTreeMetaCompareResult yangTreeMetaCompareResult = (YangTreeMetaCompareResult) yangCompareResult;
+ element = DocumentHelper.createElement("meta");
+ serializeYangTreeMetaCompareResult(yangTreeMetaCompareResult, element, needChangeType, needMetaPath);
+ }
+ return element;
+ }
+
+}
diff --git a/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangStatementComparator.java b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangStatementComparator.java
new file mode 100644
index 0000000..62bfc9b
--- /dev/null
+++ b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangStatementComparator.java
@@ -0,0 +1,31 @@
+/*
+Copyright 2023 Huawei Technologies
+
+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.onap.modeling.yangkit.comparator;
+
+import java.util.List;
+import org.yangcentral.yangkit.model.api.stmt.YangStatement;
+
+
+public interface YangStatementComparator<T extends YangStatement> {
+ /**
+ * compare statements.
+ * @param left left statement.
+ * @param right right statement.
+ * @return result.
+ */
+ List<YangCompareResult> compare(T left, T right);
+}
diff --git a/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangStatementCompareResult.java b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangStatementCompareResult.java
new file mode 100644
index 0000000..9d8847c
--- /dev/null
+++ b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangStatementCompareResult.java
@@ -0,0 +1,119 @@
+/*
+Copyright 2023 Huawei Technologies
+
+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.onap.modeling.yangkit.comparator;
+
+import org.yangcentral.yangkit.model.api.stmt.Module;
+import org.yangcentral.yangkit.model.api.stmt.YangStatement;
+
+
+public class YangStatementCompareResult implements YangCompareResult<YangStatement> {
+ private final ChangeType changeType;
+ private final YangStatement left;
+ private final YangStatement right;
+ private CompatibilityInfo compatibilityInfo;
+
+ /**
+ * constructor.
+ *
+ * @param changeType change type
+ * @param left left statement
+ * @param right right statement
+ */
+ public YangStatementCompareResult(ChangeType changeType, YangStatement left, YangStatement right) {
+ this.changeType = changeType;
+ this.left = left;
+ this.right = right;
+ }
+
+ @Override
+ public ChangeType getChangeType() {
+ return changeType;
+ }
+
+ @Override
+ public YangStatement getLeft() {
+ return left;
+ }
+
+ @Override
+ public YangStatement getRight() {
+ return right;
+ }
+
+
+ @Override
+ public String getChangeDescription(String indent) {
+ StringBuffer sb = new StringBuffer();
+ if (null != indent) {
+ sb.append(indent);
+ }
+
+ switch (changeType) {
+ case ADD: {
+ sb.append(YangComparator.outputStatement(right));
+ sb.append("\t@").append("module:").append(right.getContext().getCurModule().getArgStr()).append(" ")
+ .append(right.getElementPosition().getLocation().getLocation());
+ break;
+ }
+ case MODIFY: {
+ sb.append("FROM ");
+ sb.append(YangComparator.outputStatement(left));
+ sb.append(" TO ");
+ sb.append(YangComparator.outputStatement(right));
+ sb.append("\t@").append("module:").append(right.getContext().getCurModule().getArgStr()).append(" ")
+ .append(right.getElementPosition().getLocation().getLocation());
+ break;
+ }
+ case DELETE: {
+ sb.append(YangComparator.outputStatement(left));
+ sb.append("\t@").append("module:").append(left.getContext().getCurModule().getArgStr()).append(" ")
+ .append(left.getElementPosition().getLocation().getLocation());
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public Module getModule() {
+ switch (changeType) {
+ case ADD:
+ case MODIFY: {
+ return right.getContext().getCurModule();
+ }
+ case DELETE: {
+ return left.getContext().getCurModule();
+ }
+ default: {
+ return null;
+ }
+ }
+ }
+
+ @Override
+ public CompatibilityInfo getCompatibilityInfo() {
+ return compatibilityInfo;
+ }
+
+ @Override
+ public void setCompatibilityInfo(CompatibilityInfo compatibility) {
+ this.compatibilityInfo = compatibility;
+ }
+}
diff --git a/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangTreeCompareResult.java b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangTreeCompareResult.java
new file mode 100644
index 0000000..b3c2792
--- /dev/null
+++ b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangTreeCompareResult.java
@@ -0,0 +1,209 @@
+/*
+Copyright 2023 Huawei Technologies
+
+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.onap.modeling.yangkit.comparator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.yangcentral.yangkit.model.api.schema.SchemaPath;
+import org.yangcentral.yangkit.model.api.stmt.Module;
+import org.yangcentral.yangkit.model.api.stmt.SchemaNode;
+
+
+public class YangTreeCompareResult implements YangCompareResult<SchemaNode> {
+ private final SchemaPath.Absolute schemaPath;
+ private final ChangeType changeType;
+ private SchemaNode left;
+ private SchemaNode right;
+ private String changeDescription;
+ private List<YangCompareResult> metaCompareResults = new ArrayList<>();
+ private CompatibilityInfo compatibilityInfo;
+
+ /**
+ * constructor.
+ *
+ * @param schemaPath schema path
+ * @param changeType change type
+ */
+ public YangTreeCompareResult(SchemaPath.Absolute schemaPath, ChangeType changeType) {
+ this.schemaPath = schemaPath;
+ this.changeType = changeType;
+ }
+
+ /**
+ * get meta compare results.
+ *
+ * @return list of compare results
+ */
+ public List<YangCompareResult> getMetaCompareResults() {
+ return metaCompareResults;
+ }
+
+ /**
+ * set meta compare results.
+ *
+ * @param metaCompareResults list of meta compare results
+ */
+ public void setMetaCompareResults(List<YangCompareResult> metaCompareResults) {
+ this.metaCompareResults = metaCompareResults;
+ }
+
+ /**
+ * add meta compare result.
+ *
+ * @param metaResult result
+ */
+ public void addMetaCompareResult(YangCompareResult metaResult) {
+ metaCompareResults.add(metaResult);
+ return;
+ }
+
+ @Override
+ public SchemaNode getLeft() {
+ return left;
+ }
+
+ /**
+ * set left schema node.
+ *
+ * @param left left schema node.
+ */
+ public void setLeft(SchemaNode left) {
+ this.left = left;
+ }
+
+ @Override
+ public SchemaNode getRight() {
+ return right;
+ }
+
+ /**
+ * set right schema node.
+ *
+ * @param right right schema node
+ */
+ public void setRight(SchemaNode right) {
+ this.right = right;
+ }
+
+ /**
+ * get schema path.
+ *
+ * @return schema path
+ */
+ public SchemaPath.Absolute getSchemaPath() {
+ return schemaPath;
+ }
+
+ @Override
+ public ChangeType getChangeType() {
+ return changeType;
+ }
+
+ /**
+ * set change description.
+ *
+ * @param changeDescription description.
+ */
+ public void setChangeDescription(String changeDescription) {
+ this.changeDescription = changeDescription;
+ }
+
+ @Override
+ public String getChangeDescription(String indent) {
+ StringBuffer sb = new StringBuffer();
+ if (indent != null) {
+ sb.append(indent);
+ }
+ if (changeDescription != null) {
+ sb.append("\t").append(changeDescription);
+ return sb.toString();
+ }
+ if (null != schemaPath) {
+ sb.append(schemaPath.toString());
+ }
+ sb.append("\t@").append("module:");
+ switch (changeType) {
+ case ADD:
+ case MODIFY: {
+ sb.append(right.getContext().getCurModule().getArgStr()).append(" ")
+ .append(right.getElementPosition().getLocation().getLocation());
+ break;
+ }
+ case DELETE: {
+ sb.append(left.getContext().getCurModule().getArgStr()).append(" ")
+ .append(left.getElementPosition().getLocation().getLocation());
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ if (metaCompareResults.size() > 0) {
+ for (YangCompareResult compareResult : metaCompareResults) {
+ sb.append("\n").append(indent).append("\t");
+ switch (compareResult.getChangeType()) {
+ case ADD: {
+ sb.append("added:");
+ break;
+ }
+ case DELETE: {
+ sb.append("deleted:");
+ break;
+ }
+ case MODIFY: {
+ sb.append("changed:");
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ sb.append(" ");
+ sb.append(compareResult.getChangeDescription(null));
+ }
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public Module getModule() {
+ switch (changeType) {
+ case ADD:
+ case MODIFY: {
+ return right.getContext().getCurModule();
+ }
+ case DELETE: {
+ return left.getContext().getCurModule();
+ }
+ default: {
+ return null;
+ }
+ }
+ }
+
+ @Override
+ public CompatibilityInfo getCompatibilityInfo() {
+ return compatibilityInfo;
+ }
+
+ @Override
+ public void setCompatibilityInfo(CompatibilityInfo compatibility) {
+ this.compatibilityInfo = compatibility;
+ }
+}
diff --git a/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangTreeMetaCompareResult.java b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangTreeMetaCompareResult.java
new file mode 100644
index 0000000..3a160d0
--- /dev/null
+++ b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/YangTreeMetaCompareResult.java
@@ -0,0 +1,124 @@
+/*
+Copyright 2023 Huawei Technologies
+
+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.onap.modeling.yangkit.comparator;
+
+import org.yangcentral.yangkit.model.api.stmt.Module;
+import org.yangcentral.yangkit.model.api.stmt.SchemaNode;
+
+
+public class YangTreeMetaCompareResult implements YangCompareResult<String> {
+ private final SchemaNode target;
+ private final String meta;
+ private final String left;
+ private final String right;
+ private final ChangeType changeType;
+ private CompatibilityInfo compatibilityInfo;
+
+ /**
+ * constructor.
+ *
+ * @param target target schema node
+ * @param meta meta
+ * @param changeType change type
+ * @param left left
+ * @param right right
+ */
+ public YangTreeMetaCompareResult(SchemaNode target, String meta, ChangeType changeType, String left,
+ String right) {
+ this.target = target;
+ this.left = left;
+ this.right = right;
+ this.changeType = changeType;
+ this.meta = meta;
+ }
+
+ @Override
+ public ChangeType getChangeType() {
+ return changeType;
+ }
+
+ @Override
+ public String getLeft() {
+ return left;
+ }
+
+ @Override
+ public String getRight() {
+ return right;
+ }
+
+ /**
+ * get meta.
+ *
+ * @return meta
+ */
+ public String getMeta() {
+ return meta;
+ }
+
+ /**
+ * get target.
+ *
+ * @return target
+ */
+ public SchemaNode getTarget() {
+ return target;
+ }
+
+ @Override
+ public String getChangeDescription(String indent) {
+ StringBuffer sb = new StringBuffer();
+ if (indent != null) {
+ sb.append(indent);
+ }
+ sb.append(changeType.getName()).append(":").append(meta).append(" ");
+ switch (changeType) {
+ case ADD: {
+ sb.append(right);
+ break;
+ }
+ case DELETE: {
+ sb.append(left);
+ break;
+ }
+ case MODIFY: {
+ sb.append("FROM:").append(left).append(" TO:")
+ .append(right);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public Module getModule() {
+ return getTarget().getContext().getCurModule();
+ }
+
+ @Override
+ public CompatibilityInfo getCompatibilityInfo() {
+ return compatibilityInfo;
+ }
+
+ @Override
+ public void setCompatibilityInfo(CompatibilityInfo compatibility) {
+ this.compatibilityInfo = compatibility;
+ }
+}
diff --git a/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/app/YangComparatorPlugin.java b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/app/YangComparatorPlugin.java
new file mode 100644
index 0000000..8b513cc
--- /dev/null
+++ b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/app/YangComparatorPlugin.java
@@ -0,0 +1,157 @@
+/*
+Copyright 2023 Huawei Technologies
+
+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.onap.modeling.yangkit.comparator.app;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.onap.modeling.yangkit.comparator.CompareType;
+import org.onap.modeling.yangkit.comparator.YangComparator;
+import org.onap.modeling.yangkit.comparator.YangCompareResult;
+import org.yangcentral.yangkit.common.api.validate.ValidatorResult;
+
+import org.yangcentral.yangkit.compiler.Settings;
+import org.yangcentral.yangkit.compiler.YangCompiler;
+import org.yangcentral.yangkit.compiler.YangCompilerException;
+import org.yangcentral.yangkit.model.api.schema.YangSchemaContext;
+import org.yangcentral.yangkit.plugin.YangCompilerPlugin;
+import org.yangcentral.yangkit.plugin.YangCompilerPluginParameter;
+import org.yangcentral.yangkit.utils.file.FileUtil;
+import org.yangcentral.yangkit.utils.xml.XmlWriter;
+
+
+/**
+ * yang comparator plugin.
+ */
+public class YangComparatorPlugin implements YangCompilerPlugin {
+ @Override
+ public YangCompilerPluginParameter getParameter(Properties properties, String name, String value)
+ throws YangCompilerException {
+ if (!name.equals("old-yang") && !name.equals("settings")
+ && !name.equals("compare-type") && !name.equals("rule")
+ && !name.equals("result")) {
+ throw new YangCompilerException("unrecognized parameter:" + name);
+ }
+ YangCompilerPluginParameter yangCompilerPluginParameter = new YangCompilerPluginParameter() {
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public Object getValue() throws YangCompilerException {
+ if (name.equals("old-yang") || name.equals("settings")
+ || name.equals("rule") || name.equals("result")) {
+ Iterator<Map.Entry<Object, Object>> it = properties.entrySet().iterator();
+ String formatStr = value;
+ while (it.hasNext()) {
+ Map.Entry<Object, Object> entry = it.next();
+ formatStr = formatStr.replaceAll("\\{" + entry.getKey() + "\\}", (String) entry.getValue());
+ }
+ return formatStr;
+ }
+
+ if (name.equals("compare-type")) {
+ if (value.equals("stmt")) {
+ return CompareType.STMT;
+ } else if (value.equals("tree")) {
+ return CompareType.TREE;
+ } else if (value.equals("compatible-check")) {
+ return CompareType.COMPATIBLE_CHECK;
+ }
+ throw new YangCompilerException("unrecognized value:" + value);
+ }
+ return null;
+ }
+
+ };
+ return yangCompilerPluginParameter;
+ }
+
+ @Override
+ public void run(YangSchemaContext yangSchemaContext, YangCompiler yangCompiler,
+ List<YangCompilerPluginParameter> list) throws YangCompilerException {
+ CompareType compareType = null;
+ String oldYangPath = null;
+ String rulePath = null;
+ String resultPath = null;
+ for (YangCompilerPluginParameter parameter : list) {
+ //System.out.println("para name="+parameter.getName() + " para value="+parameter.getValue());
+ if (parameter.getName().equals("old-yang")) {
+ oldYangPath = (String) parameter.getValue();
+ yangCompiler.setYang(new File(oldYangPath));
+ } else if (parameter.getName().equals("settings")) {
+ String settingsPath = (String) parameter.getValue();
+ try {
+ yangCompiler.setSettings(Settings.parse(FileUtil.readFile2String(settingsPath)));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ } else if (parameter.getName().equals("compare-type")) {
+ compareType = (CompareType) parameter.getValue();
+ } else if (parameter.getName().equals("rule")) {
+ rulePath = (String) parameter.getValue();
+ } else if (parameter.getName().equals("result")) {
+ resultPath = (String) parameter.getValue();
+ }
+
+ }
+ if (oldYangPath == null) {
+ throw new YangCompilerException("missing mandatory parameter:old-yang");
+ }
+ if (compareType == null) {
+ throw new YangCompilerException("missing mandatory parameter:compare-type");
+ }
+ if (resultPath == null) {
+ throw new YangCompilerException("missing mandatory parameter:result");
+ }
+ YangSchemaContext oldSchemaContext = yangCompiler.buildSchemaContext();
+ ValidatorResult oldResult = oldSchemaContext.validate();
+ if (!oldResult.isOk()) {
+ throw new YangCompilerException("fail to validate the schema context of "
+ + oldYangPath
+ + ".\n"
+ + oldResult);
+ }
+ //System.out.println(oldSchemaContext.getValidateResult());
+ YangComparator yangComparator = new YangComparator(oldSchemaContext, yangSchemaContext);
+ try {
+ List<YangCompareResult> results = yangComparator.compare(compareType, rulePath);
+ boolean needCompatible = false;
+ if (compareType == CompareType.COMPATIBLE_CHECK) {
+ needCompatible = true;
+ }
+ Document document = yangComparator.outputXmlCompareResult(results, needCompatible, compareType);
+ //System.out.println(XmlWriter.transDom4jDoc2String(document));
+ XmlWriter.writeDom4jDoc(document, resultPath);
+ } catch (DocumentException e) {
+ throw new RuntimeException(e);
+ } catch (RuntimeException e) {
+ for (StackTraceElement traceElement : e.getStackTrace()) {
+ System.out.println(traceElement);
+ }
+
+ }
+
+ }
+}
diff --git a/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/app/YangComparatorRunner.java b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/app/YangComparatorRunner.java
new file mode 100644
index 0000000..1e76a75
--- /dev/null
+++ b/yang-comparator/src/main/java/org/onap/modeling/yangkit/comparator/app/YangComparatorRunner.java
@@ -0,0 +1,218 @@
+/*
+Copyright 2023 Huawei Technologies
+
+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.onap.modeling.yangkit.comparator.app;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import org.dom4j.DocumentException;
+import org.onap.modeling.yangkit.comparator.CompareType;
+import org.onap.modeling.yangkit.comparator.YangComparator;
+import org.onap.modeling.yangkit.comparator.YangCompareResult;
+import org.yangcentral.yangkit.common.api.validate.ValidatorResult;
+
+import org.yangcentral.yangkit.model.api.schema.YangSchemaContext;
+import org.yangcentral.yangkit.parser.YangParserException;
+import org.yangcentral.yangkit.parser.YangYinParser;
+import org.yangcentral.yangkit.utils.xml.XmlWriter;
+
+
+/**
+ * yang comparator runner.
+ */
+public class YangComparatorRunner {
+ /**
+ * main method.
+ * usage: -left --y {yang file or dir]} [--dep {dependency file or dir}] [--cap {capabilities.xml}]
+ * -right --y {yang file or dir]} [--dep {dependency file or dir}] [--cap {capabilities.xml}]
+ * -o {output.xml}
+ * {-tree | -stmt | -compatible-check [--rule rule.xml ]}
+ *
+ * @param args arguments
+ * @throws DocumentException document exception
+ * @throws IOException io exception
+ * @throws YangParserException yang parser exception
+ */
+
+ public static void main(String[] args) throws DocumentException, IOException, YangParserException {
+ int leftBeginPos = -1;
+ int rightBeginPos = -1;
+ int outBegin = -1;
+ int typeBegin = -1;
+ for (int i = 0; i < args.length; i++) {
+ String arg = args[i];
+ if (arg.equalsIgnoreCase("-left")) {
+ leftBeginPos = i;
+ } else if (arg.equalsIgnoreCase("-right")) {
+ rightBeginPos = i;
+ } else if (arg.equalsIgnoreCase("-o")) {
+ outBegin = i;
+ } else if (arg.equalsIgnoreCase("-tree")
+ || arg.equalsIgnoreCase("-stmt")
+ || arg.equalsIgnoreCase("-compatible-check")) {
+ typeBegin = i;
+ }
+ }
+ if (leftBeginPos != 0) {
+ System.out.println("no left argument or left argument is not the 1st argument.");
+ System.out.println(
+ "usage: -left --y {yang file or dir]} [--dep {dependency file or dir}]"
+ + " [--cap {capabilities.xml}]\n"
+ + " -right --y {yang file or dir]} [--dep {dependency file or dir}]"
+ + " [--cap {capabilities.xml}]\n"
+ + " -o {output.xml}\n"
+ + " {-tree | -stmt [--filter filter.xml] | -compatible-check [--rule rule.xml]"
+ + " [--filter filter.xml]}");
+ return;
+ }
+ if (rightBeginPos == -1) {
+ System.out.println("no right argument.");
+ System.out.println(
+ "usage: -left --y {yang file or dir]} [--dep {dependency file or dir}] [--cap {capabilities.xml}]\n"
+ + " -right --y {yang file or dir]} [--dep {dependency file or dir}] "
+ + "[--cap {capabilities.xml}]\n"
+ + " -o {output.xml}\n"
+ + " {-tree | -stmt [--filter filter.xml] | -compatible-check [--rule rule.xml]"
+ + " [--filter filter.xml]}");
+ return;
+ }
+ if (outBegin == -1) {
+ System.out.println("no output argument.");
+ System.out.println(
+ "usage: -left --y {yang file or dir]} [--dep {dependency file or dir}] [--cap {capabilities.xml}]\n"
+ + " -right --y {yang file or dir]} [--dep {dependency file or dir}] "
+ + "[--cap {capabilities.xml}]\n"
+ + " -o {output.xml}\n"
+ + " {-tree | -stmt [--filter filter.xml] | -compatible-check [--rule rule.xml]"
+ + " [--filter filter.xml]}");
+ return;
+ }
+ if (typeBegin == -1) {
+ System.out.println("no compare type argument, it should be '-tree' or '-stmt' or '-compatible-check' ");
+ System.out.println(
+ "usage: -left --y {yang file or dir]} [--dep {dependency file or dir}] [--cap {capabilities.xml}]\n"
+ + " -right --y {yang file or dir]} [--dep {dependency file or dir}] "
+ + "[--cap {capabilities.xml}]\n"
+ + " -o {output.xml}\n"
+ + " {-tree | -stmt [--filter filter.xml] | -compatible-check [--rule rule.xml] "
+ + "[--filter filter.xml]}");
+ return;
+ }
+ String leftYangDir = null;
+ String leftDepDir = null;
+ String leftCap = null;
+ for (int i = leftBeginPos; i < rightBeginPos; i++) {
+ String arg = args[i];
+ if (arg.equalsIgnoreCase("--y")) {
+ leftYangDir = args[i + 1];
+ } else if (arg.equalsIgnoreCase("--dep")) {
+ leftDepDir = args[i + 1];
+ } else if (arg.equalsIgnoreCase("--cap")) {
+ leftCap = args[i + 1];
+ }
+ }
+ if (leftYangDir == null) {
+ System.out.println("left yang file should be specified using --y argument.");
+ System.out.println(
+ "usage: -left --y {yang file or dir]} [--dep {dependency file or dir}] [--cap {capabilities.xml}]\n"
+ + " -right --y {yang file or dir]} [--dep {dependency file or dir}] "
+ + "[--cap {capabilities.xml}]\n"
+ + " -o {output.xml}\n"
+ + " {-tree | -stmt [--filter filter.xml] | -compatible-check [--rule rule.xml]"
+ + " [--filter filter.xml]}");
+ return;
+ }
+ String rightYangDir = null;
+ String rightDepDir = null;
+ String rightCap = null;
+ for (int i = rightBeginPos; i < outBegin; i++) {
+ String arg = args[i];
+ if (arg.equalsIgnoreCase("--y")) {
+ rightYangDir = args[i + 1];
+ } else if (arg.equalsIgnoreCase("--dep")) {
+ rightDepDir = args[i + 1];
+ } else if (arg.equalsIgnoreCase("--cap")) {
+ rightCap = args[i + 1];
+ }
+ }
+ if (rightYangDir == null) {
+ System.out.println("right yang file should be specified using --y argument.");
+ System.out.println(
+ "usage: -left --y {yang file or dir]} [--dep {dependency file or dir}] [--cap {capabilities.xml}]\n"
+ + " -right --y {yang file or dir]} [--dep {dependency file or dir}] "
+ + "[--cap {capabilities.xml}]\n"
+ + " -o {output.xml}\n"
+ + " {-tree | -stmt [--filter filter.xml] | -compatible-check [--rule rule.xml]"
+ + " [--filter filter.xml]}");
+ return;
+ }
+ String output = args[outBegin + 1];
+ File outputFile = new File(output);
+ if (!outputFile.exists()) {
+ if (outputFile.getParentFile() != null && !outputFile.getParentFile().exists()) {
+ outputFile.getParentFile().mkdirs();
+ }
+ outputFile.createNewFile();
+ }
+ String compareTypeStr = args[typeBegin];
+ String rule = null;
+ String filter = null;
+ if (compareTypeStr.equalsIgnoreCase("-compatible-check")
+ || compareTypeStr.equalsIgnoreCase("-tree")) {
+ for (int i = typeBegin; i < args.length; i++) {
+ String arg = args[i];
+ if (arg.equalsIgnoreCase("--rule")) {
+ rule = args[i + 1];
+ } else if (arg.equalsIgnoreCase("--filter")) {
+ filter = args[i + 1];
+ }
+ }
+ }
+ YangSchemaContext leftSchemaContext = YangYinParser.parse(leftYangDir, leftDepDir, leftCap);
+ ValidatorResult leftValidatorResult = leftSchemaContext.validate();
+ if (!leftValidatorResult.isOk()) {
+ System.out.println("The yang files in directory:" + leftYangDir + " have something wrong.");
+ System.out.println(leftValidatorResult);
+ }
+
+ YangSchemaContext rightSchemaContext = YangYinParser.parse(rightYangDir, rightDepDir, rightCap);
+ ValidatorResult rightValidatorResult = rightSchemaContext.validate();
+ if (!rightValidatorResult.isOk()) {
+ System.out.println("The yang files in directory:" + rightYangDir + " have something wrong.");
+ System.out.println(rightValidatorResult);
+ }
+
+ YangComparator comparator = new YangComparator(leftSchemaContext, rightSchemaContext);
+ CompareType compareType = null;
+ if (compareTypeStr.equalsIgnoreCase("-stmt")) {
+ compareType = CompareType.STMT;
+ } else if (compareTypeStr.equalsIgnoreCase("-tree")) {
+ compareType = CompareType.TREE;
+ } else if (compareTypeStr.equalsIgnoreCase("-compatible-check")) {
+ compareType = CompareType.COMPATIBLE_CHECK;
+ }
+
+ List<YangCompareResult> compareResults = comparator.compare(compareType, rule);
+ boolean needCompatible = false;
+ if (compareType == CompareType.COMPATIBLE_CHECK) {
+ needCompatible = true;
+ }
+ XmlWriter.writeDom4jDoc(comparator.outputXmlCompareResult(compareResults, needCompatible, compareType), output);
+ }
+
+}
diff --git a/yang-comparator/src/main/resources/plugins.json b/yang-comparator/src/main/resources/plugins.json
new file mode 100644
index 0000000..4534d4d
--- /dev/null
+++ b/yang-comparator/src/main/resources/plugins.json
@@ -0,0 +1,34 @@
+{
+ "plugins": {
+ "plugin": [
+ {
+ "name": "yang_comparator",
+ "class-path": "yang-comparator-1.0-SNAPSHOT.jar",
+ "class": "com.huawei.yang.comparator.app.YangComparatorPlugin",
+ "description": "a plugin for comparing two yang schema.",
+ "parameter": [
+ {
+ "name": "old-yang",
+ "description": "mandatory,the old version yang directory."
+ },
+ {
+ "name": "settings",
+ "description": "optional,the settings file path."
+ },
+ {
+ "name": "compare-type",
+ "description": "mandatory, specify compare-type, one of stmt,tree,or compatible-check"
+ },
+ {
+ "name": "rule",
+ "description": "optional, specify the path of compatible-rule file."
+ },
+ {
+ "name": "result",
+ "description": "mandatory, specify the compare result file path, the result file is a xml format."
+ }
+ ]
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/yang-comparator/src/main/resources/rules.xml b/yang-comparator/src/main/resources/rules.xml
new file mode 100644
index 0000000..15a6520
--- /dev/null
+++ b/yang-comparator/src/main/resources/rules.xml
@@ -0,0 +1,563 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<rules>
+ <rule>
+ <rule-id>schema-node-rule1</rule-id>
+ <statements>
+ <statement>container</statement>
+ <statement>list</statement>
+ <statement>choice</statement>
+ <statement>case</statement>
+ <statement>rpc</statement>
+ <statement>action</statement>
+ <statement>input</statement>
+ <statement>output</statement>
+ <statement>notification</statement>
+ <statement>leaf</statement>
+ <statement>leaf-list</statement>
+ <statement>anyxml</statement>
+ <statement>anydata</statement>
+ </statements>
+ <condition>added</condition>
+ <compatible>backward-compatible</compatible>
+ <description>add an optional schema node, it's backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>schema-node-rule2</rule-id>
+ <statements>
+ <statement>container</statement>
+ <statement>list</statement>
+ <statement>choice</statement>
+ <statement>case</statement>
+ <statement>rpc</statement>
+ <statement>action</statement>
+ <statement>input</statement>
+ <statement>output</statement>
+ <statement>notification</statement>
+ <statement>leaf</statement>
+ <statement>leaf-list</statement>
+ <statement>anyxml</statement>
+ <statement>anydata</statement>
+ </statements>
+ <condition>deleted</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>delete a schema node, it's non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>schema-node-rule3</rule-id>
+ <statements>
+ <statement>container</statement>
+ <statement>list</statement>
+ <statement>choice</statement>
+ <statement>case</statement>
+ <statement>rpc</statement>
+ <statement>action</statement>
+ <statement>input</statement>
+ <statement>output</statement>
+ <statement>notification</statement>
+ <statement>leaf</statement>
+ <statement>leaf-list</statement>
+ <statement>anyxml</statement>
+ <statement>anydata</statement>
+ </statements>
+ <condition>mandatory-added</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>add a mandatory true schema node, it's non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>typedef-rule1</rule-id>
+ <statements>
+ <statement>typedef</statement>
+ </statements>
+ <condition>added</condition>
+ <compatible>backward-compatible</compatible>
+ <description>add a typedef, it's backward-compatible</description>
+ </rule>
+ <rule>
+ <rule-id>typedef-rule2</rule-id>
+ <statements>
+ <statement>typedef</statement>
+ </statements>
+ <condition>deleted</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>delete a typedef, it's backward-compatible</description>
+ </rule>
+ <rule>
+ <rule-id>type-changed-rule1</rule-id>
+ <statements>
+ <statement>type</statement>
+ </statements>
+ <condition>integer-type-changed</condition>
+ <compatible>backward-compatible</compatible>
+ <description>type changed from one integer to other integer, it's backward-compatible</description>
+ </rule>
+ <rule>
+ <rule-id>type-changed-rule2</rule-id>
+ <statements>
+ <statement>type</statement>
+ </statements>
+ <condition>changed</condition>
+ <except-condition>integer-type-changed</except-condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>type changed, it's non-backward-compatible</description>
+ </rule>
+ <rule>
+ <rule-id>scope-expanded-rule1</rule-id>
+ <statements>
+ <statement>range</statement>
+ <statement>length</statement>
+ <statement>fraction-digits</statement><!-- new value is smaller -->
+ <statement>min-elements</statement><!-- new value is smaller -->
+ <statement>max-elements</statement><!-- new value is greater -->
+ <statement>mandatory</statement><!-- from true to false -->
+ <statement>config</statement><!-- from false to true-->
+ </statements>
+ <condition>expand</condition>
+ <compatible>backward-compatible</compatible>
+ <description> the scope is expanded, it's backward-compatible</description>
+ </rule>
+ <rule>
+ <rule-id>scope-reduced-rule1</rule-id>
+ <statements>
+ <statement>range</statement>
+ <statement>length</statement>
+ <statement>fraction-digits</statement><!-- new value is greater -->
+ <statement>min-elements</statement><!-- new value is greater -->
+ <statement>max-elements</statement><!-- new value is smaller -->
+ <statement>mandatory</statement><!-- from false to true -->
+ <statement>config</statement><!-- from true to false-->
+ </statements>
+ <condition>reduce</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description> the scope is reduced, it's non-backward-compatible</description>
+ </rule>
+ <rule>
+ <rule-id>enumeration-bits-rule1</rule-id>
+ <statements>
+ <statement>enum</statement>
+ <statement>bit</statement>
+ </statements>
+ <condition>added</condition>
+ <compatible>backward-compatible</compatible>
+ <description>add a enum/bit, it's backward-compatible</description>
+ </rule>
+ <rule>
+ <rule-id>enumeration-bits-rule2</rule-id>
+ <statements>
+ <statement>enum</statement>
+ <statement>bit</statement>
+ </statements>
+ <condition>deleted</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>delete a enum/bit, it's non-backward-compatible</description>
+ </rule>
+ <rule>
+ <rule-id>enumeration-bits-rule3</rule-id>
+ <statements>
+ <statement>enum</statement>
+ <statement>bit</statement>
+ </statements>
+ <condition>changed</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>change a enum/bit,for example, the value of this enum is changed, it's non-backward-compatible</description>
+ </rule>
+ <rule>
+ <rule-id>default-rule</rule-id>
+ <statements>
+ <statement>default</statement>
+ </statements>
+ <condition>any</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>any change of default will be treated as non-backward-compatible change</description>
+ </rule>
+ <rule>
+ <rule-id>pattern-rule1</rule-id>
+ <statements>
+ <statement>pattern</statement>
+ </statements>
+ <condition>added</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>add a new pattern ,it's a non-backward-compatible change</description>
+ </rule>
+ <rule>
+ <rule-id>pattern-rule2</rule-id>
+ <statements>
+ <statement>pattern</statement>
+ </statements>
+ <condition>deleted</condition>
+ <compatible>backward-compatible</compatible>
+ <description>delete a pattern ,it's a backward-compatible change</description>
+ </rule>
+ <rule>
+ <rule-id>pattern-rule3</rule-id>
+ <statements>
+ <statement>pattern</statement>
+ </statements>
+ <condition>changed</condition>
+ <compatible>unknown</compatible>
+ <description>pattern is changed ,it's a unknown change</description>
+ </rule>
+ <rule>
+ <rule-id>modifier-rule1</rule-id>
+ <statements>
+ <statement>modifier</statement>
+ </statements>
+ <condition>any</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>any change of modifier will be treated as a non-backward-compatible change</description>
+ </rule>
+ <rule>
+ <rule-id>key-rule</rule-id>
+ <statements>
+ <statement>key</statement>
+ </statements>
+ <condition>any</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>any change of key will be treated as a non-backward-compatible change</description>
+ </rule>
+ <rule>
+ <rule-id>mandatory-rule1</rule-id>
+ <statements>
+ <statement>mandatory</statement>
+ </statements>
+ <condition>reduce</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>from mandatory false to mandatory true, it's non-backward-compatible change</description>
+ </rule>
+ <rule>
+ <rule-id>mandatory-rule2</rule-id>
+ <statements>
+ <statement>mandatory</statement>
+ </statements>
+ <condition>expand</condition>
+ <compatible>backward-compatible</compatible>
+ <description>from mandatory true to mandatory false, it's backward-compatible change</description>
+ </rule>
+ <rule>
+ <rule-id>unique-rule1</rule-id>
+ <statements>
+ <statement>unique</statement>
+ </statements>
+ <condition>added</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>add a new unique, it's a non-backward-compatible change</description>
+ </rule>
+ <rule>
+ <rule-id>unique-rule2</rule-id>
+ <statements>
+ <statement>unique</statement>
+ </statements>
+ <condition>deleted</condition>
+ <compatible>backward-compatible</compatible>
+ <description>delete a unique, it's a backward-compatible change</description>
+ </rule>
+ <rule>
+ <rule-id>unique-rule3</rule-id>
+ <statements>
+ <statement>unique</statement>
+ </statements>
+ <condition>reduce</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>unique attrs are added, it's a non-backward-compatible change</description>
+ </rule>
+ <rule>
+ <rule-id>unique-rule4</rule-id>
+ <statements>
+ <statement>unique</statement>
+ </statements>
+ <condition>expand</condition>
+ <compatible>backward-compatible</compatible>
+ <description>unique attrs are deleted, it's a non-backward-compatible change</description>
+ </rule>
+ <rule>
+ <rule-id>config-rule1</rule-id>
+ <statements>
+ <statement>config</statement>
+ </statements>
+ <condition>expand</condition>
+ <compatible>backward-compatible</compatible>
+ <description>config from false to true, it's a backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>config-rule2</rule-id>
+ <statements>
+ <statement>config</statement>
+ </statements>
+ <condition>reduce</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>config from true to false, it's a non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>support-filter-rule1</rule-id>
+ <statements>
+ <statement>huawei-extension:support-filter</statement>
+ </statements>
+ <condition>expand</condition>
+ <compatible>backward-compatible</compatible>
+ <description>support-filter from false to true, it's backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>support-filter-rule2</rule-id>
+ <statements>
+ <statement>huawei-extension:support-filter</statement>
+ </statements>
+ <condition>reduce</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>support-filter from true to false, it's non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>path-rule1</rule-id>
+ <statements>
+ <statement>path</statement>
+ </statements>
+ <condition>expand</condition>
+ <compatible>backward-compatible</compatible>
+ <description>the node-set which the path points to is expanded, it's backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>path-rule2</rule-id>
+ <statements>
+ <statement>path</statement>
+ </statements>
+ <condition>reduce</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>the node-set which the path points to is reduced, it's non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>path-rule3</rule-id>
+ <statements>
+ <statement>path</statement>
+ </statements>
+ <condition>changed</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>the node-set which the path points to is changed (e.g. from one data node to another data node),
+ it's non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>require-instance-rule1</rule-id>
+ <statements>
+ <statement>require-instance</statement>
+ </statements>
+ <condition>expand</condition>
+ <compatible>backward-compatible</compatible>
+ <description>require-instance from true to false, it's backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>require-instance-rule2</rule-id>
+ <statements>
+ <statement>require-instance</statement>
+ </statements>
+ <condition>reduce</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>require-instance from false to true, it's non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>units-rule1</rule-id>
+ <statements>
+ <statement>units</statement>
+ </statements>
+ <condition>added</condition>
+ <compatible>backward-compatible</compatible>
+ <description>add a units, it's backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>units-rule2</rule-id>
+ <statements>
+ <statement>units</statement>
+ </statements>
+ <condition>deleted</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>delete units, it's non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>units-rule3</rule-id>
+ <statements>
+ <statement>units</statement>
+ </statements>
+ <condition>changed</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>change units, it's non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>when-must-rule1</rule-id>
+ <statements>
+ <statement>when</statement>
+ <statement>must</statement>
+ </statements>
+ <condition>added</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>add a when or must, it's non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>when-must-rule2</rule-id>
+ <statements>
+ <statement>when</statement>
+ <statement>must</statement>
+ </statements>
+ <condition>deleted</condition>
+ <compatible>backward-compatible</compatible>
+ <description>delete a when or must, it's non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>when-must-rule3</rule-id>
+ <statements>
+ <statement>when</statement>
+ <statement>must</statement>
+ </statements>
+ <condition>changed</condition>
+ <compatible>unknown</compatible>
+ <description>when or must is changed, it's unknown change.</description>
+ </rule>
+ <rule>
+ <rule-id>if-feature-rule1</rule-id>
+ <statements>
+ <statement>if-feature</statement>
+ </statements>
+ <condition>added</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>add a if-feature,it's non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>if-feature-rule2</rule-id>
+ <statements>
+ <statement>if-feature</statement>
+ </statements>
+ <condition>deleted</condition>
+ <compatible>backward-compatible</compatible>
+ <description>delete a if-feature,it's backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>if-feature-rule3</rule-id>
+ <statements>
+ <statement>if-feature</statement>
+ </statements>
+ <condition>changed</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description> a if-feature changed,it's non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>belongs-to-rule</rule-id>
+ <statements>
+ <statement>belongs-to</statement>
+ </statements>
+ <condition>any</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>any change for belongs-to is non-backward-compatible.</description>
+ </rule>
+ <rule>
+ <rule-id>prefix-rule</rule-id>
+ <statements>
+ <statement>prefix</statement>
+ </statements>
+ <condition>changed</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>any change for prefix is non-backward-compatible.</description>
+ </rule>
+ <rule>
+ <rule-id>yang-version-rule</rule-id>
+ <statements>
+ <statement>yang-version</statement>
+ </statements>
+ <condition>changed</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>any change for yang-version is non-backward-compatible</description>
+ </rule>
+ <rule>
+ <rule-id>namespace-rule</rule-id>
+ <statements>
+ <statement>namespace</statement>
+ </statements>
+ <condition>changed</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>any change for namespace is non-backward-compatible.</description>
+ </rule>
+ <rule>
+ <rule-id>identity-rule1</rule-id>
+ <statements>
+ <statement>identity</statement>
+ </statements>
+ <condition>added</condition>
+ <compatible>backward-compatible</compatible>
+ <description>add a new identity, it's a backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>identity-rule2</rule-id>
+ <statements>
+ <statement>identity</statement>
+ </statements>
+ <condition>deleted</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>delete a new identity, it's a non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>base-rule1</rule-id>
+ <statements>
+ <statement>base</statement>
+ </statements>
+ <condition>added</condition>
+ <compatible>backward-compatible</compatible>
+ <description>add a new base, it's a backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>base-rule2</rule-id>
+ <statements>
+ <statement>base</statement>
+ </statements>
+ <condition>deleted</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>delete a base, it's a non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>extension-rule1</rule-id>
+ <statements>
+ <statement>extension</statement>
+ </statements>
+ <condition>added</condition>
+ <compatible>backward-compatible</compatible>
+ <description>add a new extension, it's a backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>extension-rule2</rule-id>
+ <statements>
+ <statement>extension</statement>
+ </statements>
+ <condition>deleted</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>delete a new extension, it's a non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>argument-rule</rule-id>
+ <statements>
+ <statement>argument</statement>
+ </statements>
+ <condition>any</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>any chang for argument is a non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>yin-element-rule</rule-id>
+ <statements>
+ <statement>yin-element</statement>
+ </statements>
+ <condition>change</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>any chang for yin-element is a non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>revision-date-rule</rule-id>
+ <statements>
+ <statement>revision-date</statement>
+ </statements>
+ <condition>change</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>any chang for revision-date is a non-backward-compatible change.</description>
+ </rule>
+ <rule>
+ <rule-id>ordered-by-rule</rule-id>
+ <statements>
+ <statement>ordered-by</statement>
+ </statements>
+ <condition>change</condition>
+ <compatible>non-backward-compatible</compatible>
+ <description>any chang for ordered-by is a non-backward-compatible change.</description>
+ </rule>
+</rules> \ No newline at end of file