From 0ad6f5a18a6e5cc98f464cfcdb78130acb80d0e6 Mon Sep 17 00:00:00 2001 From: xudan16 Date: Thu, 24 Aug 2023 10:34:04 +0800 Subject: Yang Compiler for YANG Model automation Issue-ID: MODELING-680 Change-Id: I191eef382c080525ec6b8827f8f1e0b4a82994a6 Signed-off-by: xudan16 --- yang-compiler/pom.xml | 194 ++++++ .../onap/modeling/yangkit/catalog/ModuleInfo.java | 130 ++++ .../onap/modeling/yangkit/catalog/YangCatalog.java | 143 +++++ .../modeling/yangkit/compiler/Authentication.java | 64 ++ .../onap/modeling/yangkit/compiler/Builder.java | 112 ++++ .../yangkit/compiler/ParameterBuilder.java | 69 +++ .../modeling/yangkit/compiler/PluginBuilder.java | 86 +++ .../onap/modeling/yangkit/compiler/PluginInfo.java | 188 ++++++ .../yangkit/compiler/PluginParameterInfo.java | 59 ++ .../org/onap/modeling/yangkit/compiler/Proxy.java | 144 +++++ .../onap/modeling/yangkit/compiler/Settings.java | 226 +++++++ .../modeling/yangkit/compiler/YangCompiler.java | 675 +++++++++++++++++++++ .../yangkit/compiler/YangCompilerException.java | 33 + .../yangkit/compiler/app/YangCompilerRunner.java | 54 ++ .../yangkit/plugin/YangCompilerPlugin.java | 74 +++ .../plugin/YangCompilerPluginParameter.java | 35 ++ .../yangkit/plugin/stat/YangNodeDescription.java | 96 +++ .../yangkit/plugin/stat/YangStatistics.java | 278 +++++++++ .../yangkit/plugin/validator/YangValidator.java | 46 ++ .../yangkit/plugin/yangpackage/ModuleInfo.java | 117 ++++ .../yangkit/plugin/yangpackage/PackageInfo.java | 45 ++ .../plugin/yangpackage/SubComponentInfo.java | 171 ++++++ .../yangkit/plugin/yangpackage/SubModuleInfo.java | 125 ++++ .../yangkit/plugin/yangpackage/YangPackage.java | 395 ++++++++++++ .../plugin/yangpackage/YangPackageGenerator.java | 154 +++++ .../plugin/yangpackage/YangPackageMeta.java | 187 ++++++ .../yangtree/GroupingSchemaNodeContainer.java | 141 +++++ .../yangkit/plugin/yangtree/YangTreeGenerator.java | 654 ++++++++++++++++++++ 28 files changed, 4695 insertions(+) create mode 100644 yang-compiler/pom.xml create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/catalog/ModuleInfo.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/catalog/YangCatalog.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Authentication.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Builder.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/ParameterBuilder.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/PluginBuilder.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/PluginInfo.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/PluginParameterInfo.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Proxy.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Settings.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/YangCompiler.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/YangCompilerException.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/app/YangCompilerRunner.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/YangCompilerPlugin.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/YangCompilerPluginParameter.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/stat/YangNodeDescription.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/stat/YangStatistics.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/validator/YangValidator.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/ModuleInfo.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/PackageInfo.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/SubComponentInfo.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/SubModuleInfo.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/YangPackage.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/YangPackageGenerator.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/YangPackageMeta.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangtree/GroupingSchemaNodeContainer.java create mode 100644 yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangtree/YangTreeGenerator.java diff --git a/yang-compiler/pom.xml b/yang-compiler/pom.xml new file mode 100644 index 0000000..cdd6626 --- /dev/null +++ b/yang-compiler/pom.xml @@ -0,0 +1,194 @@ + + + 4.0.0 + + org.onap.modeling.yangkit + yangkit-parent + 1.0.0-SNAPSHOT + + + org.onap.modeling.yangkit + yang-compiler + 1.0.0-SNAPSHOT + + 8 + 8 + UTF-8 + UTF-8 + UTF-8 + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + + + true + org.onap.modeling.yangkit.compiler.app.YangCompilerRunner + libs/ + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + copy-dependencies + package + + copy-dependencies + + + + ${project.build.directory}/libs + + + + + + + + + + io.github.yang-central.yangkit + yangkit-parser + 1.3.3 + + + + jaxen + jaxen + 2.0.0 + + + org.apache.commons + commons-lang3 + 3.12.0 + + + org.antlr + antlr4-runtime + 4.11.1 + + + org.dom4j + dom4j + 2.1.4 + + + + com.google.code.gson + gson + 2.10.1 + + + org.apache.poi + poi + 5.2.3 + + + org.apache.poi + poi-ooxml + 5.2.3 + + + yang compiler + yang compiler: compile yang modules regardless where the dependencies are (by resolve and download + dependencies automatically) + + + release + + true + + + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + true + false + release + deploy + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + + + diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/catalog/ModuleInfo.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/catalog/ModuleInfo.java new file mode 100644 index 0000000..31bb51e --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/catalog/ModuleInfo.java @@ -0,0 +1,130 @@ +/* +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.catalog; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.net.URI; + + +public class ModuleInfo { + private final String name; + private final String revision; + private final String organization; + private URI schema; + + /** + * The constructor of ModuleInfo. + * @param name module name + * @param revision module revision + * @param organization the organization who publish this module + */ + public ModuleInfo(String name, String revision, String organization) { + this.name = name; + this.revision = revision; + this.organization = organization; + } + + /** + * set schema. + * @param schema the URI of schema + */ + public void setSchema(URI schema) { + this.schema = schema; + } + + /** + * get module name. + * @return module name + */ + public String getName() { + return name; + } + + /** + * get module's revision. + * @return revision + */ + public String getRevision() { + return revision; + } + + /** + * get organization. + * @return organization + */ + public String getOrganization() { + return organization; + } + + /** + * get schema. + * @return URI + */ + public URI getSchema() { + return schema; + } + + /** + * parse module info from json. + * @param element json element + * @return ModuleInfo + */ + public static ModuleInfo parse(JsonElement element) { + JsonObject jsonObject = element.getAsJsonObject(); + String name = jsonObject.get("name").getAsString(); + String revision = jsonObject.get("revision").getAsString(); + JsonElement organizationElement = jsonObject.get("organization"); + String organization = null; + if (organizationElement != null) { + organization = organizationElement.getAsString(); + } + JsonElement schemaElement = jsonObject.get("schema"); + if (schemaElement == null) { + return null; + } + URI schema = URI.create(schemaElement.getAsString()); + if (name == null || revision == null) { + return null; + } + ModuleInfo moduleInfo = new ModuleInfo(name,revision,organization); + moduleInfo.setSchema(schema); + return moduleInfo; + } + + /** + * parse module information from json string. + * @param str json string + * @return Module information + */ + public static ModuleInfo parse(String str) { + JsonElement element = JsonParser.parseString(str); + JsonObject modules = element.getAsJsonObject(); + JsonElement moduleElement = modules.get("module"); + if (moduleElement == null) { + return null; + } + JsonArray jsonArray = moduleElement.getAsJsonArray(); + if (jsonArray.size() != 1) { + return null; + } + return parse(jsonArray.get(0)); + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/catalog/YangCatalog.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/catalog/YangCatalog.java new file mode 100644 index 0000000..21673c5 --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/catalog/YangCatalog.java @@ -0,0 +1,143 @@ +/* +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.catalog; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.util.ArrayList; +import java.util.List; + + +public class YangCatalog { + private final List modules = new ArrayList<>(); + + /** + * add module information to yang catalog. + * + * @param moduleInfo module information structure + */ + public void addModule(ModuleInfo moduleInfo) { + if (getModule(moduleInfo.getName(), moduleInfo.getRevision(), moduleInfo.getOrganization()) + != null) { + return; + } + modules.add(moduleInfo); + } + + /** + * get module information from yang catalog. + * + * @param name module name + * @param revision module revision + * @param organization the organization who publish the module + * @return module information + */ + public ModuleInfo getModule(String name, String revision, String organization) { + if (modules.isEmpty()) { + return null; + } + for (ModuleInfo moduleInfo : modules) { + if (moduleInfo.getName().equals(name) && moduleInfo.getRevision().equals(revision) + && moduleInfo.getOrganization().equals(organization)) { + return moduleInfo; + } + } + return null; + } + + /** + * get all modules from yang catalog. + * + * @return list of modules + */ + public List getModules() { + return modules; + } + + /** + * get all modules by module name. + * + * @param moduleName module name + * @return list of matched modules + */ + public List getModules(String moduleName) { + List moduleInfos = new ArrayList<>(); + for (ModuleInfo moduleInfo : modules) { + if (moduleInfo.getName().equals(moduleName)) { + moduleInfos.add(moduleInfo); + } + } + return moduleInfos; + } + + /** + * get the latest module by module name. + * + * @param moduleName module name + * @return the latest module information + */ + public ModuleInfo getLatestModule(String moduleName) { + List matched = getModules(moduleName); + if (matched.isEmpty()) { + return null; + } + if (matched.size() == 1) { + return matched.get(0); + } + ModuleInfo latest = null; + for (ModuleInfo moduleInfo : matched) { + if (latest == null) { + latest = moduleInfo; + } else { + if (moduleInfo.getRevision().compareTo(latest.getRevision()) > 0) { + latest = moduleInfo; + } + } + } + return latest; + } + + /** + * parse yang catalog from json string. + * + * @param str json string + * @return yang catalog + */ + public static YangCatalog parse(String str) { + YangCatalog yangCatalog = new YangCatalog(); + JsonElement element = JsonParser.parseString(str); + JsonObject jsonObject = element.getAsJsonObject(); + JsonElement modulesElement = jsonObject.get("yang-catalog:modules"); + JsonObject modules = modulesElement.getAsJsonObject(); + JsonElement moduleElement = modules.get("module"); + JsonArray moduleArray = moduleElement.getAsJsonArray(); + int size = moduleArray.size(); + for (int i = 0; i < size; i++) { + JsonElement subElement = moduleArray.get(i); + ModuleInfo moduleInfo = ModuleInfo.parse(subElement); + if (moduleInfo == null) { + continue; + } + yangCatalog.addModule(moduleInfo); + } + return yangCatalog; + } + +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Authentication.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Authentication.java new file mode 100644 index 0000000..4684a4d --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Authentication.java @@ -0,0 +1,64 @@ +/* +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.compiler; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + + +public class Authentication { + private final String name; + private final String password; + + /** + * the constructor. + * @param name user name + * @param password password + */ + public Authentication(String name, String password) { + this.name = name; + this.password = password; + } + + /** + * get the username. + * @return user name + */ + public String getName() { + return name; + } + + /** + * get the password. + * @return password + */ + public String getPassword() { + return password; + } + + /** + * parse authentication from json element. + * @param jsonElement json element + * @return the structure of authentication + */ + public static Authentication parse(JsonElement jsonElement) { + JsonObject authenticationObject = jsonElement.getAsJsonObject(); + String name = authenticationObject.get("username").getAsString(); + String passwd = authenticationObject.get("password").getAsString(); + return new Authentication(name, passwd); + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Builder.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Builder.java new file mode 100644 index 0000000..7436447 --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Builder.java @@ -0,0 +1,112 @@ +/* +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.compiler; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import java.util.ArrayList; +import java.util.List; + + +public class Builder { + private String yangDir; + private List plugins = new ArrayList<>(); + + /** + * the constructor. + */ + public Builder() { + } + + /** + * get yang directory where the yang files to be compiled exist. + * + * @return the directory path + */ + public String getYangDir() { + return yangDir; + } + + /** + * set the yang directory. + * + * @param yangDir the path of yang directory + */ + public void setYangDir(String yangDir) { + this.yangDir = yangDir; + } + + /** + * get the plugins. + * + * @return the list of plugins + */ + public List getPlugins() { + return plugins; + } + + /** + * set the list of plugins. + * + * @param plugins the list of plugins + */ + public void setPlugins(List plugins) { + this.plugins = plugins; + } + + /** + * add a plugin. + * + * @param pluginBuilder plugin to be added. + */ + public void addPlugin(PluginBuilder pluginBuilder) { + this.plugins.add(pluginBuilder); + } + + /** + * parse the build.json. + * + * @param jsonElement json element + * @return builder structure + */ + public static Builder parse(JsonElement jsonElement) { + JsonObject jsonObject = jsonElement.getAsJsonObject(); + JsonElement buildElement = jsonObject.get("build"); + Builder builder = new Builder(); + if (buildElement == null) { + return builder; + } + JsonObject buildObj = buildElement.getAsJsonObject(); + JsonElement yangElement = buildObj.get("yang"); + if (yangElement != null) { + String yang = yangElement.getAsString(); + builder.setYangDir(yang); + } + JsonElement pluginsElement = buildObj.get("plugin"); + if (pluginsElement != null) { + JsonArray plugins = pluginsElement.getAsJsonArray(); + for (int i = 0; i < plugins.size(); i++) { + JsonElement pluginElement = plugins.get(i); + PluginBuilder pluginBuilder = PluginBuilder.parse(pluginElement); + builder.addPlugin(pluginBuilder); + } + } + return builder; + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/ParameterBuilder.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/ParameterBuilder.java new file mode 100644 index 0000000..ea8ad7a --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/ParameterBuilder.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.compiler; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + + +public class ParameterBuilder { + private final String name; + private final String value; + + /** + * the constructor. + * + * @param name the name of parameter + * @param value the value of parameter + */ + public ParameterBuilder(String name, String value) { + this.name = name; + this.value = value; + } + + /** + * get the parameter name. + * + * @return name + */ + public String getName() { + return name; + } + + /** + * get the parameter value. + * + * @return value + */ + public String getValue() { + return value; + } + + /** + * parse parameter from json. + * + * @param jsonElement json element + * @return parameter + */ + public static ParameterBuilder parse(JsonElement jsonElement) { + JsonObject jsonObject = jsonElement.getAsJsonObject(); + String name = jsonObject.get("name").getAsString(); + String value = jsonObject.get("value").getAsString(); + ParameterBuilder parameterBuilder = new ParameterBuilder(name, value); + return parameterBuilder; + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/PluginBuilder.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/PluginBuilder.java new file mode 100644 index 0000000..489d1f7 --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/PluginBuilder.java @@ -0,0 +1,86 @@ +/* +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.compiler; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; + +import java.util.ArrayList; +import java.util.List; + + +public class PluginBuilder { + private final String name; + private final List parameters = new ArrayList<>(); + + /** + * the constructor. + * + * @param name the plugin name + */ + public PluginBuilder(String name) { + this.name = name; + } + + /** + * get the plugin name. + * + * @return name + */ + public String getName() { + return name; + } + + /** + * get all parameters of plugin. + * + * @return the list of parameters + */ + public List getParameters() { + return parameters; + } + + /** + * add parameter into plugin. + * + * @param para parameter + */ + public void addParameter(ParameterBuilder para) { + parameters.add(para); + } + + /** + * parse plugin from json. + * + * @param jsonElement json element + * @return plugin builder + */ + public static PluginBuilder parse(JsonElement jsonElement) { + String name = jsonElement.getAsJsonObject().get("name").getAsString(); + PluginBuilder pluginBuilder = new PluginBuilder(name); + JsonElement parasElement = jsonElement.getAsJsonObject().get("parameter"); + if (parasElement != null) { + JsonArray paras = parasElement.getAsJsonArray(); + for (int i = 0; i < paras.size(); i++) { + JsonElement paraElement = paras.get(i); + ParameterBuilder parameterBuilder = ParameterBuilder.parse(paraElement); + pluginBuilder.addParameter(parameterBuilder); + } + } + return pluginBuilder; + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/PluginInfo.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/PluginInfo.java new file mode 100644 index 0000000..a042dd0 --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/PluginInfo.java @@ -0,0 +1,188 @@ +/* +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.compiler; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import org.onap.modeling.yangkit.plugin.YangCompilerPlugin; + + +@SuppressWarnings("ALL") +public class PluginInfo { + private final String pluginName; + private final YangCompilerPlugin plugin; + + private String description; + private final List parameters = new ArrayList<>(); + + /** + * the constructor. + * + * @param pluginName plugin name + * @param plugin plugin + */ + public PluginInfo(String pluginName, YangCompilerPlugin plugin) { + this.pluginName = pluginName; + this.plugin = plugin; + } + + /** + * get the name of plugin. + * + * @return name + */ + public String getPluginName() { + return pluginName; + } + + /** + * get the plugin. + * + * @return plugin + */ + public YangCompilerPlugin getPlugin() { + return plugin; + } + + /** + * get the description. + * + * @return description + */ + public String getDescription() { + return description; + } + + /** + * set the description. + * + * @param description description string + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * get the parameters of the plugin. + * + * @return the parameters + */ + public List getParameters() { + return parameters; + } + + /** + * add a parameter to plugin. + * + * @param parameter parameter + */ + public void addParameter(PluginParameterInfo parameter) { + parameters.add(parameter); + } + + /** + * parse plugin information from json. + * + * @param pluginFile plugins.json File handler + * @param jsonElement json element + * @return plugin information + */ + public static PluginInfo parse(File pluginFile, JsonElement jsonElement) { + JsonObject jsonObject = jsonElement.getAsJsonObject(); + String pluginName = jsonObject.get("name").getAsString(); + String classPath = null; + JsonElement classPathElement = jsonObject.get("class-path"); + if (classPathElement != null) { + classPath = classPathElement.getAsString(); + } + String className = jsonObject.get("class").getAsString(); + try { + Class pluginClass = null; + if (classPath != null && !classPath.trim().isEmpty()) { + Path path = Paths.get(classPath); + File file; + if (!path.isAbsolute()) { + file = new File(pluginFile.getParentFile(), classPath); + } else { + file = new File(classPath); + } + if (!file.exists()) { + System.out.println("[ERROR]the class-path:" + file.getAbsolutePath() + " is not found."); + return null; + } + URL[] cp = {file.toURI().toURL()}; + try (URLClassLoader classLoader = new URLClassLoader(cp)) { + pluginClass = (Class) classLoader.loadClass(className); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else { + pluginClass = (Class) Class.forName(className); + } + + Constructor constructor = pluginClass.getConstructor(); + YangCompilerPlugin yangCompilerPlugin = constructor.newInstance(); + PluginInfo pluginInfo = new PluginInfo(pluginName, yangCompilerPlugin); + if (jsonObject.get("description") != null) { + String description = jsonObject.get("description").getAsString(); + pluginInfo.setDescription(description); + } + JsonElement parasElement = jsonObject.get("parameter"); + if (parasElement != null) { + JsonArray paraArray = parasElement.getAsJsonArray(); + for (int i = 0; i < paraArray.size(); i++) { + JsonElement paraElement = paraArray.get(i); + JsonObject para = paraElement.getAsJsonObject(); + String name = para.get("name").getAsString(); + PluginParameterInfo parameter = new PluginParameterInfo(name); + if (para.get("description") != null) { + String description = para.get("description").getAsString(); + parameter.setDescription(description); + } + pluginInfo.addParameter(parameter); + } + } + return pluginInfo; + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/PluginParameterInfo.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/PluginParameterInfo.java new file mode 100644 index 0000000..526b94a --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/PluginParameterInfo.java @@ -0,0 +1,59 @@ +/* +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.compiler; + + +public class PluginParameterInfo { + private final String name; + private String description; + + /** + * the constructor. + * + * @param name parameter name + */ + public PluginParameterInfo(String name) { + this.name = name; + } + + /** + * get the parameter name. + * + * @return name + */ + public String getName() { + return name; + } + + /** + * get the description. + * + * @return description + */ + public String getDescription() { + return description; + } + + /** + * set the description. + * + * @param description the description to be set + */ + public void setDescription(String description) { + this.description = description; + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Proxy.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Proxy.java new file mode 100644 index 0000000..db183bc --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Proxy.java @@ -0,0 +1,144 @@ +/* +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.compiler; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; + + +public class Proxy { + private final String hostName; + private final int port; + private Authentication authentication; + + /** + * the constructor. + * + * @param hostName the host name + * @param port the port number + */ + public Proxy(String hostName, int port) { + this.hostName = hostName; + this.port = port; + } + + /** + * the constructor. + * + * @param hostName the host name. + */ + + public Proxy(String hostName) { + this.hostName = hostName; + this.port = 80; + } + + /** + * get the host name. + * + * @return host name. + */ + public String getHostName() { + return hostName; + } + + /** + * get the port number. + * + * @return port number. + */ + public int getPort() { + return port; + } + + /** + * get the authentication information. + * + * @return authentication information + */ + public Authentication getAuthentication() { + return authentication; + } + + /** + * set the authentication information. + * + * @param authentication authentication information. + */ + public void setAuthentication(Authentication authentication) { + this.authentication = authentication; + } + + /** + * create a proxy instance from url. + * + * @param url url + * @return proxy + */ + public static Proxy create(URL url) { + return new Proxy(url.getHost(), url.getPort() == -1 ? url.getDefaultPort() : url.getPort()); + } + + /** + * parse proxy from json. + * + * @param jsonElement json element + * @return proxy + */ + public static Proxy parse(JsonElement jsonElement) { + Proxy proxy = null; + JsonObject jsonObject = jsonElement.getAsJsonObject(); + JsonElement urlElement = jsonObject.get("url"); + if (urlElement != null) { + String urlString = urlElement.getAsString(); + try { + URL url = URI.create(urlString).toURL(); + proxy = Proxy.create(url); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } else { + JsonElement hostElement = jsonObject.get("host"); + if (hostElement != null) { + String host = hostElement.getAsString(); + int port = -1; + JsonElement portElement = jsonObject.get("port"); + if (portElement != null) { + port = portElement.getAsInt(); + } + if (port != -1) { + proxy = new Proxy(host, port); + } else { + proxy = new Proxy(host); + } + } + } + JsonElement authenticationElement = jsonObject.get("authentication"); + if (authenticationElement != null) { + Authentication authentication = Authentication.parse(authenticationElement); + if (proxy != null) { + proxy.setAuthentication(authentication); + } + + } + return proxy; + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Settings.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Settings.java new file mode 100644 index 0000000..7acb56b --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/Settings.java @@ -0,0 +1,226 @@ +/* +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.compiler; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.File; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import org.onap.modeling.yangkit.catalog.ModuleInfo; + + +public class Settings { + private URI remoteRepository = URI.create("https://yangcatalog.org/api/"); + private String localRepository = System.getProperty("user.home") + File.separator + ".yang"; + + private Proxy proxy; + + private String token; + private List moduleInfos = new ArrayList<>(); + + /** + * get the remote repository. + * + * @return the URI + */ + public URI getRemoteRepository() { + return remoteRepository; + } + + /** + * set the remote repository. + * + * @param remoteRepository remote repository uri + */ + public void setRemoteRepository(URI remoteRepository) { + this.remoteRepository = remoteRepository; + } + + /** + * get the local repository. + * + * @return the path of local repository + */ + public String getLocalRepository() { + return localRepository; + } + + /** + * set the local repository. + * + * @param localRepository the path of local repository. + */ + public void setLocalRepository(String localRepository) { + this.localRepository = localRepository; + } + + /** + * get the information of modules. + * + * @return the list of module information + */ + public List getModuleInfos() { + return moduleInfos; + } + + /** + * get the information of modules by module name. + * + * @param name module name + * @return the list of matched module information + */ + public List getModuleInfos(String name) { + List matched = new ArrayList<>(); + for (ModuleInfo moduleInfo : moduleInfos) { + if (moduleInfo.getName().equals(name)) { + matched.add(moduleInfo); + } + } + return matched; + } + + /** + * get the latest module information by specified name. + * + * @param name module name + * @return the latest module information + */ + public ModuleInfo getLatestModuleInfo(String name) { + List matched = getModuleInfos(name); + ModuleInfo latest = null; + for (ModuleInfo moduleInfo : matched) { + if (latest == null) { + latest = moduleInfo; + } else { + if (moduleInfo.getRevision().compareTo(latest.getRevision()) > 0) { + latest = moduleInfo; + } + } + } + return latest; + } + + /** + * get the module information by specified module name and revision. + * + * @param name module name + * @param revision module revision + * @return the matched module information + */ + public ModuleInfo getModuleInfo(String name, String revision) { + for (ModuleInfo moduleInfo : moduleInfos) { + if (moduleInfo.getName().equals(name) + && moduleInfo.getRevision().equals(revision)) { + return moduleInfo; + } + } + return null; + } + + /** + * get the proxy. + * + * @return proxy + */ + public Proxy getProxy() { + return proxy; + } + + /** + * set proxy. + * + * @param proxy proxy + */ + public void setProxy(Proxy proxy) { + this.proxy = proxy; + } + + /** + * get token. + * + * @return token string + */ + public String getToken() { + return token; + } + + /** + * set token. + * + * @param token token + */ + public void setToken(String token) { + this.token = token; + } + + /** + * parse settings from json string. + * + * @param str json string + * @return settings + */ + public static Settings parse(String str) { + Settings settings = new Settings(); + JsonElement element = JsonParser.parseString(str); + if (element == null) { + return settings; + } + JsonObject jsonObject = element.getAsJsonObject(); + JsonObject settingInstance = jsonObject.get("settings").getAsJsonObject(); + JsonElement localElement = settingInstance.get("local-repository"); + if (localElement != null) { + String localRepository = localElement.getAsString(); + if (null != localRepository) { + settings.setLocalRepository(localRepository); + } + } + JsonElement remoteElement = settingInstance.get("remote-repository"); + if (remoteElement != null) { + String remoteRepository = remoteElement.getAsString(); + if (null != remoteRepository) { + settings.setRemoteRepository(URI.create(remoteRepository)); + } + } + + JsonElement proxyElement = settingInstance.get("proxy"); + if (proxyElement != null) { + Proxy proxy = Proxy.parse(proxyElement); + settings.setProxy(proxy); + } + JsonElement tokenElement = settingInstance.get("token"); + if (tokenElement != null) { + settings.setToken(tokenElement.getAsString()); + } + JsonElement moduleInfosElement = settingInstance.get("module-info"); + if (moduleInfosElement != null) { + JsonArray moduleInfos = moduleInfosElement.getAsJsonArray(); + for (int i = 0; i < moduleInfos.size(); i++) { + JsonElement moduleElement = moduleInfos.get(i); + ModuleInfo moduleInfo = ModuleInfo.parse(moduleElement); + settings.moduleInfos.add(moduleInfo); + } + } + + return settings; + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/YangCompiler.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/YangCompiler.java new file mode 100644 index 0000000..7d4975d --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/YangCompiler.java @@ -0,0 +1,675 @@ +/* +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.compiler; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.net.Authenticator; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.Proxy; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Scanner; +import java.util.concurrent.ConcurrentHashMap; +import javax.annotation.Nullable; + + +import org.dom4j.DocumentException; +import org.onap.modeling.yangkit.catalog.ModuleInfo; +import org.onap.modeling.yangkit.catalog.YangCatalog; +import org.onap.modeling.yangkit.plugin.YangCompilerPlugin; +import org.onap.modeling.yangkit.plugin.YangCompilerPluginParameter; +import org.yangcentral.yangkit.base.YangBuiltinKeyword; +import org.yangcentral.yangkit.base.YangElement; +import org.yangcentral.yangkit.common.api.validate.ValidatorRecord; +import org.yangcentral.yangkit.common.api.validate.ValidatorResult; +import org.yangcentral.yangkit.common.api.validate.ValidatorResultBuilder; +import org.yangcentral.yangkit.model.api.schema.ModuleId; +import org.yangcentral.yangkit.model.api.schema.YangSchemaContext; +import org.yangcentral.yangkit.model.api.stmt.Module; +import org.yangcentral.yangkit.model.api.stmt.SubModule; +import org.yangcentral.yangkit.model.api.stmt.YangStatement; +import org.yangcentral.yangkit.parser.YangParser; +import org.yangcentral.yangkit.parser.YangParserEnv; +import org.yangcentral.yangkit.parser.YangParserException; +import org.yangcentral.yangkit.parser.YangYinParser; +import org.yangcentral.yangkit.utils.file.FileUtil; +import org.yangcentral.yangkit.utils.url.URLUtil; +import org.yangcentral.yangkit.writter.YangFormatter; +import org.yangcentral.yangkit.writter.YangWriter; + + +public class YangCompiler { + + private Settings settings; + private File yang; + + private final Map pluginInfos = new ConcurrentHashMap(); + + private Builder builder; + + /** + * constructor. + */ + public YangCompiler() { + } + + /** + * get the builder. + * + * @return builder class + */ + public Builder getBuilder() { + return builder; + } + + /** + * set builder. + * + * @param builder builder + */ + public void setBuilder(Builder builder) { + this.builder = builder; + } + + /** + * get plugin information. + * + * @param name plugin name + * @return plugin information + */ + public PluginInfo getPluginInfo(String name) { + if (pluginInfos.isEmpty()) { + return null; + } + return pluginInfos.get(name); + } + + /** + * add a new plugin. + * + * @param pluginInfo plugin information + */ + public void addPluginInfo(PluginInfo pluginInfo) { + if (pluginInfo == null) { + return; + } + if (getPluginInfo(pluginInfo.getPluginName()) != null) { + return; + } + pluginInfos.put(pluginInfo.getPluginName(), pluginInfo); + } + + /** + * get settings. + * + * @return settings + */ + public Settings getSettings() { + return settings; + } + + /** + * set settings. + * + * @param settings settings + */ + public void setSettings(Settings settings) { + this.settings = settings; + } + + /** + * get yang directory file handler. + * + * @return yang directory file handler. + */ + public File getYang() { + return yang; + } + + /** + * set yang directory file handler. + * + * @param yang file handler + */ + public void setYang(File yang) { + this.yang = yang; + } + + /** + * get all dependencies of a specified module. + * + * @param module module + * @return dependencies + */ + private List getDependencies(Module module) { + List dependencies = new ArrayList<>(); + if (module == null) { + return dependencies; + } + List importStatements = module.getSubStatement(YangBuiltinKeyword.IMPORT.getQName()); + for (YangStatement importStatement : importStatements) { + String moduleName = importStatement.getArgStr(); + String revision = null; + List revisions = importStatement.getSubStatement(YangBuiltinKeyword.REVISIONDATE.getQName()); + if (revisions.isEmpty()) { + revision = ""; + } else { + revision = revisions.get(0).getArgStr(); + } + ModuleId moduleId = new ModuleId(moduleName, revision); + dependencies.add(moduleId); + } + List includeStatements = module.getSubStatement(YangBuiltinKeyword.INCLUDE.getQName()); + for (YangStatement includeStatement : includeStatements) { + String moduleName = includeStatement.getArgStr(); + String revision = null; + List revisions = + includeStatement.getSubStatement(YangBuiltinKeyword.REVISIONDATE.getQName()); + if (revisions.isEmpty()) { + revision = ""; + } else { + revision = revisions.get(0).getArgStr(); + } + ModuleId moduleId = new ModuleId(moduleName, revision); + dependencies.add(moduleId); + } + if (module instanceof SubModule) { + List belongsToStatements = module.getSubStatement(YangBuiltinKeyword.BELONGSTO.getQName()); + String moduleName = belongsToStatements.get(0).getArgStr(); + ModuleId moduleId = new ModuleId(moduleName, ""); + dependencies.add(moduleId); + } + return dependencies; + } + + private String urlInvoke(String url) throws IOException { + URL catalogUrl = URI.create(url).toURL(); + Proxy proxy = null; + Authenticator authenticator = null; + if (settings.getProxy() != null) { + String protocol = catalogUrl.getProtocol(); + Proxy.Type proxyType = null; + if (protocol.equalsIgnoreCase("http") || protocol.equalsIgnoreCase("https")) { + proxyType = Proxy.Type.HTTP; + } else { + proxyType = Proxy.Type.SOCKS; + } + proxy = new Proxy(proxyType, + new InetSocketAddress(settings.getProxy().getHostName(), settings.getProxy().getPort())); + if (settings.getProxy().getAuthentication() != null) { + authenticator = new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(settings.getProxy().getAuthentication().getName(), + settings.getProxy().getAuthentication().getPassword().toCharArray() + ); + } + }; + Authenticator.setDefault(authenticator); + } + + } + return URLUtil.URLGet(catalogUrl, proxy, authenticator, settings.getToken()); + } + + private File getFromLocal(ModuleId moduleId) { + File localRepository = new File(settings.getLocalRepository()); + if (!localRepository.exists()) { + localRepository.mkdirs(); + } + String prefix = + moduleId.getModuleName() + (moduleId.getRevision().equals("") ? "" : "@" + moduleId.getRevision()); + String suffix = ".yang"; + FilenameFilter filenameFilter = new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + if (dir != localRepository) { + return false; + } + if (name.startsWith(prefix) && name.endsWith(suffix)) { + String moduleDesc = name.substring(0, name.indexOf(suffix)); + String[] moduleInfo = moduleDesc.split("@"); + String moduleName = moduleInfo[0]; + String revision = moduleInfo[1]; + if (!moduleName.equals(moduleId.getModuleName())) { + return false; + } + if (moduleId.getRevision() != null && moduleId.getRevision().length() > 0) { + if (!revision.equals(moduleId.getRevision())) { + return false; + } + } + return true; + } + return false; + } + }; + System.out.print("[INFO]finding module:" + moduleId.getModuleName() + + (moduleId.getRevision().isEmpty() ? "" : moduleId.getRevision()) + + " from " + localRepository.getAbsolutePath() + + " ..."); + File[] matched = localRepository.listFiles(filenameFilter); + if (matched == null || matched.length == 0) { + System.out.println("not found."); + return null; + } + if (matched.length == 1) { + System.out.println("get " + matched[0].getName()); + return matched[0]; + } + File latest = null; + if (matched.length > 1) { + for (File file : matched) { + if (latest == null) { + latest = file; + } else { + if (file.getName().compareTo(latest.getName()) > 0) { + latest = file; + } + } + } + } + System.out.println("get " + latest.getName()); + return latest; + } + + private File getFromRemote(ModuleId moduleId) throws IOException { + ModuleInfo moduleInfo = null; + if (moduleId.getRevision() == null || moduleId.getRevision().equals("")) { + String url = settings.getRemoteRepository() + "search/name/" + moduleId.getModuleName(); + System.out.print("[INFO]downloading module info:" + moduleId.getModuleName() + " from " + url + " ..."); + YangCatalog yangCatalog = YangCatalog.parse(urlInvoke(url)); + moduleInfo = yangCatalog.getLatestModule(moduleId.getModuleName()); + System.out.println(moduleInfo == null ? " not found." : "revision=" + moduleInfo.getRevision()); + + } else { + String organization = moduleId.getModuleName().substring(0, moduleId.getModuleName().indexOf("-")); + if (organization.equals("junos")) { + organization = "juniper"; + } + String url = settings.getRemoteRepository() + + "search/modules/" + + moduleId.getModuleName() + + "," + + moduleId.getRevision() + + "," + + organization; + System.out.print("[INFO]downloading module info:" + + moduleId.getModuleName() + + " from " + + url + + " ..."); + moduleInfo = ModuleInfo.parse(urlInvoke(url)); + System.out.println(moduleInfo == null ? " not found." : "finished"); + + } + if (moduleInfo == null) { + return null; + } + System.out.print("[INFO]downloading content of module:" + moduleInfo.getName() + "@" + moduleInfo.getRevision() + + " from " + moduleInfo.getSchema().toString() + " ..."); + String yangString = urlInvoke(moduleInfo.getSchema().toString()); + System.out.println("finished."); + File localRepositoryFile = new File(settings.getLocalRepository()); + if (!localRepositoryFile.exists()) { + localRepositoryFile.mkdirs(); + } + String yangfileName = moduleInfo.getName() + "@" + moduleInfo.getRevision() + ".yang"; + File localYangFile = new File(localRepositoryFile, yangfileName); + FileUtil.writeUtf8File(yangString, localYangFile); + System.out.println("[INFO]save module:" + + moduleInfo.getName() + + "@" + + moduleInfo.getRevision() + + " to " + + localYangFile.getAbsolutePath()); + return localYangFile; + } + + private File getFromSettings(ModuleId moduleId) throws IOException { + ModuleInfo moduleInfo = null; + if (moduleId.getRevision() == null || moduleId.getRevision().equals("")) { + moduleInfo = settings.getLatestModuleInfo(moduleId.getModuleName()); + System.out.print("[INFO]getting module info:" + + moduleId.getModuleName() + + " from settings"); + System.out.println(moduleInfo == null ? " not found." : "revision=" + + moduleInfo.getRevision()); + + } else { + System.out.print("[INFO]getting module info:" + + moduleId.getModuleName() + + " from settings."); + moduleInfo = settings.getModuleInfo(moduleId.getModuleName(), moduleId.getRevision()); + System.out.println(moduleInfo == null ? " not found." : "finished"); + + } + if (moduleInfo == null) { + return null; + } + System.out.print("[INFO]downloading content of module:" + + moduleInfo.getName() + + "@" + + moduleInfo.getRevision() + + " from " + + moduleInfo.getSchema().toString() + + " ..."); + String yangString = urlInvoke(moduleInfo.getSchema().toString()); + System.out.println("finished."); + File localRepositoryFile = new File(settings.getLocalRepository()); + if (!localRepositoryFile.exists()) { + localRepositoryFile.mkdirs(); + } + String yangfileName = moduleInfo.getName() + + "@" + + moduleInfo.getRevision() + + ".yang"; + File localYangFile = new File(localRepositoryFile, yangfileName); + FileUtil.writeUtf8File(yangString, localYangFile); + System.out.println("[INFO]save module:" + + moduleInfo.getName() + + "@" + + moduleInfo.getRevision() + + " to " + + localYangFile.getAbsolutePath()); + return localYangFile; + } + + private void buildDependencies(YangSchemaContext schemaContext, List dependencies) + throws IOException, YangParserException, YangCompilerException { + for (ModuleId moduleId : dependencies) { + if (schemaContext.getModule(moduleId).isPresent()) { + continue; + } + //firstly,get yang file from local repository + File file = getFromLocal(moduleId); + if (file == null) { + //secondly,if not found,get yang file from settings + file = getFromSettings(moduleId); + if (file == null) { + //thirdly, if not found, get yang file from remote repository + file = getFromRemote(moduleId); + } + } + if (file == null) { + throw new YangCompilerException("can not find the yang module named:" + + moduleId.getModuleName(), + moduleId); + } + + YangParserEnv env = new YangParserEnv(); + env.setCurPos(0); + env.setYangStr(FileUtil.readFile2String(file)); + env.setFilename(file.getAbsolutePath()); + YangParser yangParser = new YangParser(); + List yangElements = yangParser.parseYang(env.getYangStr(), env); + schemaContext.getParseResult().put(env.getFilename(), yangElements); + Module module = null; + for (YangElement yangElement : yangElements) { + if (yangElement instanceof Module) { + module = (Module) yangElement; + schemaContext.addImportOnlyModule(module); + break; + } + } + if (module != null) { + List subDependencies = getDependencies(module); + if (!subDependencies.isEmpty()) { + buildDependencies(schemaContext, subDependencies); + } + + } + } + } + + /** + * build yang schema context. + * + * @return yang schema context + */ + public YangSchemaContext buildSchemaContext() { + if (!yang.exists()) { + return null; + } + try { + YangSchemaContext schemaContext = YangYinParser.parse(yang); + for (Module module : schemaContext.getModules()) { + List dependencies = getDependencies(module); + buildDependencies(schemaContext, dependencies); + } + return schemaContext; + } catch (IOException e) { + throw new RuntimeException(e); + } catch (YangParserException e) { + throw new RuntimeException(e); + } catch (DocumentException e) { + throw new RuntimeException(e); + } catch (YangCompilerException e) { + throw new RuntimeException(e); + } + } + + /** + * compile yang files. + * + * @param yangdir yang directory + * @param settingsfile the path of settings.json + * @param install whether install to local repository + * @throws IOException io exception + * @throws URISyntaxException uri syntax exception + */ + public void compile(@Nullable String yangdir, @Nullable String settingsfile, boolean install) + throws IOException, URISyntaxException { + String defaultSettingsfile = + System.getProperty("user.home") + + File.separator + + ".yang" + + File.separator + + "settings.json"; + Settings settings = null; + if (settingsfile != null) { + settings = Settings.parse(FileUtil.readFile2String(settingsfile)); + } else { + File defaultSettingsFile = new File(defaultSettingsfile); + if (defaultSettingsFile.exists()) { + settings = Settings.parse(FileUtil.readFile2String(defaultSettingsfile)); + } else { + File programDir = new File(this.getClass().getProtectionDomain().getCodeSource().getLocation() + .toURI()); + File programSettings = new File(programDir.getParentFile(), "settings.json"); + if (programSettings.exists()) { + settings = Settings.parse(FileUtil.readFile2String(programSettings)); + } else { + settings = new Settings(); + } + + } + } + + setSettings(settings); + File builderFile = new File("build.json"); + if (builderFile.exists()) { + Builder builder = prepareBuilder(FileUtil.readFile2String(builderFile)); + setBuilder(builder); + if (yangdir == null) { + yangdir = builder.getYangDir(); + } + } + if (yangdir == null) { + yangdir = "yang"; + //System.out.println("no yang directory!"); + //System.out.println("Usage: yang-compiler yang={yang directory} [settings={settings.json}] [install]"); + //return; + } + File yangDirFile = new File(yangdir); + if (!yangDirFile.exists()) { + System.out.println("yang directory:" + + yangdir + + " is not exist!"); + return; + } + setYang(new File(yangdir)); + Properties compilerProps = new Properties(); + compilerProps.setProperty("yang", yangdir); + if (settings.getLocalRepository() != null) { + compilerProps.setProperty("local-repository", settings.getLocalRepository()); + } + + if (settings.getRemoteRepository() != null) { + compilerProps.setProperty("remote-repository", settings.getRemoteRepository().toString()); + } + + preparePlugins(this); + + YangSchemaContext schemaContext = buildSchemaContext(); + ValidatorResult validatorResult = schemaContext.validate(); + if (!validatorResult.isOk()) { + System.out.println(validatorResult); + return; + } + if (getBuilder() != null) { + for (PluginBuilder pluginBuilder : getBuilder().getPlugins()) { + PluginInfo pluginInfo = getPluginInfo(pluginBuilder.getName()); + if (null == pluginInfo) { + System.out.println("can not find a plugin named:" + + pluginBuilder.getName()); + continue; + } + YangCompilerPlugin plugin = pluginInfo.getPlugin(); + try { + List parameters = new ArrayList<>(); + if (!pluginBuilder.getParameters().isEmpty()) { + for (ParameterBuilder parameterBuilder : pluginBuilder.getParameters()) { + YangCompilerPluginParameter parameter = plugin.getParameter(compilerProps, + parameterBuilder.getName(), parameterBuilder.getValue()); + if (parameter != null) { + parameters.add(parameter); + } + } + } + System.out.println("[INFO]call plugin:" + + pluginInfo.getPluginName() + + " ..."); + plugin.run(schemaContext, this, parameters); + System.out.println("ok."); + } catch (YangCompilerException e) { + System.out.println("[ERROR]" + + e.getMessage()); + } + } + } + ValidatorResultBuilder validatorResultBuilder = new ValidatorResultBuilder(); + List> records = validatorResult.getRecords(); + for (ValidatorRecord record : records) { + if (record.getBadElement() instanceof YangStatement) { + YangStatement yangStatement = (YangStatement) record.getBadElement(); + if (schemaContext.getModules().contains(yangStatement.getContext().getCurModule())) { + validatorResultBuilder.addRecord(record); + } + } + } + validatorResult = validatorResultBuilder.build(); + if (install && validatorResult.isOk()) { + for (Module module : schemaContext.getModules()) { + List elements = + schemaContext.getParseResult().get(module.getElementPosition().getSource()); + StringBuilder sb = new StringBuilder(); + for (YangElement element : elements) { + String yangStr = YangWriter.toYangString(element, YangFormatter.getPrettyYangFormatter(), null); + sb.append(yangStr); + sb.append("\n"); + } + String moduleDesc = module.getArgStr() + + (module.getCurRevisionDate().isPresent() ? "@" + module.getCurRevisionDate().get() : ""); + String fileName = settings.getLocalRepository() + + File.separator + moduleDesc; + FileUtil.writeUtf8File(fileName, sb.toString()); + System.out.println("[INFO]install " + + moduleDesc + + " to " + + settings.getLocalRepository()); + + } + } + System.out.println(validatorResult); + } + + private static void preparePlugins(YangCompiler yangCompiler) throws IOException, URISyntaxException { + InputStream inputStream = yangCompiler.getClass().getResourceAsStream("/plugins.json"); + Scanner scanner = new Scanner(inputStream).useDelimiter("\\A"); + String result = scanner.hasNext() ? scanner.next() : ""; + if (!result.isEmpty()) { + List pluginInfos = parsePlugins(null, result); + for (PluginInfo pluginInfo : pluginInfos) { + yangCompiler.addPluginInfo(pluginInfo); + } + } + File programDir = new File(yangCompiler.getClass().getProtectionDomain().getCodeSource().getLocation() + .toURI()); + File pluginsDir = new File(programDir.getParentFile(), "plugins"); + if (!pluginsDir.exists()) { + System.out.println("[WARNING]plugins dir:" + + pluginsDir.getAbsolutePath() + + " is not exists"); + return; + } + File pluginsFile = new File(pluginsDir, "plugins.json"); + if (pluginsFile.exists()) { + System.out.println("[INFO]reading the information of plugins from:" + + pluginsFile.getAbsolutePath()); + List pluginInfos = parsePlugins(pluginsFile, FileUtil.readFile2String(pluginsFile)); + for (PluginInfo pluginInfo : pluginInfos) { + yangCompiler.addPluginInfo(pluginInfo); + } + } + + + } + + private static List parsePlugins(File pluginsFile, String str) { + List pluginInfos = new ArrayList<>(); + JsonElement pluginsElement = JsonParser.parseString(str); + JsonObject jsonObject = pluginsElement.getAsJsonObject(); + JsonObject pluginsObject = jsonObject.get("plugins").getAsJsonObject(); + JsonArray pluginList = pluginsObject.getAsJsonArray("plugin"); + for (int i = 0; i < pluginList.size(); i++) { + JsonElement pluginElement = pluginList.get(i); + PluginInfo pluginInfo = PluginInfo.parse(pluginsFile, pluginElement); + pluginInfos.add(pluginInfo); + } + return pluginInfos; + } + + private static Builder prepareBuilder(String str) { + JsonElement jsonElement = JsonParser.parseString(str); + return Builder.parse(jsonElement); + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/YangCompilerException.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/YangCompilerException.java new file mode 100644 index 0000000..b3d18e5 --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/YangCompilerException.java @@ -0,0 +1,33 @@ +/* +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.compiler; + +import org.yangcentral.yangkit.model.api.schema.ModuleId; + + +public class YangCompilerException extends Exception{ + private ModuleId module; + + public YangCompilerException(String message, ModuleId module) { + super(message); + this.module = module; + } + + public YangCompilerException(String message) { + super(message); + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/app/YangCompilerRunner.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/app/YangCompilerRunner.java new file mode 100644 index 0000000..650e444 --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/compiler/app/YangCompilerRunner.java @@ -0,0 +1,54 @@ +/* +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.compiler.app; + +import java.io.IOException; +import java.net.URISyntaxException; +import org.onap.modeling.yangkit.compiler.YangCompiler; + + +public class YangCompilerRunner { + /** + * the main method of yang compiler runner. + * @param args arguments + * @throws IOException io exception + * @throws URISyntaxException uri syntax exception + */ + public static void main(String[] args) throws IOException, URISyntaxException { + String yangdir = null; + String settingsfile = null; + boolean install = false; + for (String arg : args) { + String[] paras = arg.split("="); + if (paras.length == 2) { + String para = paras[0]; + String value = paras[1]; + if (para.equals("yang")) { + yangdir = value; + } else if (para.equals("settings")) { + settingsfile = value; + } + } else { + if (arg.equals("install")) { + install = true; + } + } + } + YangCompiler compiler = new YangCompiler(); + compiler.compile(yangdir, settingsfile, install); + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/YangCompilerPlugin.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/YangCompilerPlugin.java new file mode 100644 index 0000000..a30f9fc --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/YangCompilerPlugin.java @@ -0,0 +1,74 @@ +/* +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.plugin; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.regex.Matcher; + +import org.onap.modeling.yangkit.compiler.YangCompiler; +import org.onap.modeling.yangkit.compiler.YangCompilerException; +import org.yangcentral.yangkit.model.api.schema.YangSchemaContext; + + +public interface YangCompilerPlugin { + /** + * default implementation of get parameter method. + * @param compilerProps the properties of yang compiler. + * @param name the name of parameter + * @param value the value of parameter + * @return yang compiler plugin parameter + * @throws YangCompilerException if error occurs, the exception will be thrown. + */ + default YangCompilerPluginParameter getParameter(Properties compilerProps, String name, String value) + throws YangCompilerException { + YangCompilerPluginParameter yangCompilerPluginParameter = new YangCompilerPluginParameter() { + @Override + public String getName() { + return name; + } + + @Override + public Object getValue() { + Iterator> it = compilerProps.entrySet().iterator(); + String formatStr = value; + while (it.hasNext()) { + Map.Entry entry = it.next(); + formatStr = formatStr.replaceAll("\\{" + entry.getKey() + "\\}", + Matcher.quoteReplacement((String) entry.getValue())); + } + return formatStr; + + } + + }; + return yangCompilerPluginParameter; + } + + /** + * the definition of run method. + * @param schemaContext yang schema context + * @param yangCompiler yang compiler instance + * @param parameters parameters + * @throws YangCompilerException if error occurs, the exception will be thrown. + */ + void run(YangSchemaContext schemaContext, YangCompiler yangCompiler, List parameters) + throws YangCompilerException; + +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/YangCompilerPluginParameter.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/YangCompilerPluginParameter.java new file mode 100644 index 0000000..f3cb7aa --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/YangCompilerPluginParameter.java @@ -0,0 +1,35 @@ +/* +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.plugin; + +import org.onap.modeling.yangkit.compiler.YangCompilerException; + + +public interface YangCompilerPluginParameter { + /** + * get parameter name. + * @return name + */ + String getName(); + + /** + * get parameter value. + * @return value + * @throws YangCompilerException yang compiler exception + */ + Object getValue() throws YangCompilerException; +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/stat/YangNodeDescription.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/stat/YangNodeDescription.java new file mode 100644 index 0000000..2a903ca --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/stat/YangNodeDescription.java @@ -0,0 +1,96 @@ +/* +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.plugin.stat; + + +public class YangNodeDescription { + private String path; + private String description; + private String config; + private String schemaType; + private String nodeType; + private String module; + private boolean isActive; + private boolean isDeviated; + + public YangNodeDescription() { + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getConfig() { + return config; + } + + public void setConfig(String config) { + this.config = config; + } + + public String getSchemaType() { + return schemaType; + } + + public void setSchemaType(String schemaType) { + this.schemaType = schemaType; + } + + public String getNodeType() { + return nodeType; + } + + public void setNodeType(String nodeType) { + this.nodeType = nodeType; + } + + public String getModule() { + return module; + } + + public void setModule(String module) { + this.module = module; + } + + public boolean isActive() { + return isActive; + } + + public void setActive(boolean active) { + isActive = active; + } + + public boolean isDeviated() { + return isDeviated; + } + + public void setDeviated(boolean deviated) { + isDeviated = deviated; + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/stat/YangStatistics.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/stat/YangStatistics.java new file mode 100644 index 0000000..f5863cc --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/stat/YangStatistics.java @@ -0,0 +1,278 @@ +/* +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.plugin.stat; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.xssf.streaming.SXSSFCell; +import org.apache.poi.xssf.streaming.SXSSFRow; +import org.apache.poi.xssf.streaming.SXSSFSheet; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.onap.modeling.yangkit.compiler.YangCompiler; +import org.onap.modeling.yangkit.compiler.YangCompilerException; +import org.onap.modeling.yangkit.plugin.YangCompilerPlugin; +import org.onap.modeling.yangkit.plugin.YangCompilerPluginParameter; +import org.yangcentral.yangkit.model.api.schema.YangSchemaContext; +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.SubModule; +import org.yangcentral.yangkit.model.api.stmt.TypedDataNode; +import org.yangcentral.yangkit.model.api.stmt.VirtualSchemaNode; + + +public class YangStatistics implements YangCompilerPlugin { + /** + * get node description. + * @param schemaNode schema node + * @return node description + */ + public YangNodeDescription getNodeDescription(SchemaNode schemaNode) { + if (schemaNode == null) { + return null; + } + if (schemaNode instanceof VirtualSchemaNode) { + return null; + } + if (schemaNode.getSchemaPath() == null) { + return null; + } + YangNodeDescription nodeDescription = new YangNodeDescription(); + nodeDescription.setPath(schemaNode.getSchemaPath().toString()); + nodeDescription.setDescription( + schemaNode.getDescription() == null ? "" : schemaNode.getDescription().getArgStr()); + nodeDescription.setConfig(schemaNode.isConfig() ? "true" : "false"); + nodeDescription.setSchemaType(schemaNode.getYangKeyword().getLocalName()); + if (schemaNode instanceof TypedDataNode) { + TypedDataNode typedDataNode = (TypedDataNode) schemaNode; + nodeDescription.setNodeType(typedDataNode.getType().getArgStr()); + } + nodeDescription.setModule(schemaNode.getContext().getCurModule().getArgStr()); + nodeDescription.setActive(schemaNode.isActive()); + nodeDescription.setDeviated(schemaNode.isDeviated()); + return nodeDescription; + } + + /** + * get node description for schema node container. + * @param schemaNodeContainer schema node container + * @return list of node description. + */ + public List getNodeDescriptions(SchemaNodeContainer schemaNodeContainer) { + if (schemaNodeContainer == null) { + return new ArrayList<>(); + } + List nodeDescriptions = new ArrayList<>(); + if (schemaNodeContainer instanceof SchemaNode) { + SchemaNode schemaNode = (SchemaNode) schemaNodeContainer; + YangNodeDescription nodeDescription = getNodeDescription(schemaNode); + if (nodeDescription != null) { + nodeDescriptions.add(nodeDescription); + } + } + + for (SchemaNode schemaNode : schemaNodeContainer.getSchemaNodeChildren()) { + if (schemaNode instanceof SchemaNodeContainer) { + nodeDescriptions.addAll(getNodeDescriptions((SchemaNodeContainer) schemaNode)); + } else { + YangNodeDescription nodeDescription = getNodeDescription(schemaNode); + if (nodeDescription != null) { + nodeDescriptions.add(nodeDescription); + } + } + } + return nodeDescriptions; + } + + /** + * get yang statistics for yang schema context. + * @param schemaContext yang schema context. + * @return list of node description. + */ + public List getYangStatistics(YangSchemaContext schemaContext) { + List nodeDescriptions = new ArrayList<>(); + if (schemaContext == null) { + return nodeDescriptions; + } + for (Module module : schemaContext.getModules()) { + if (module instanceof SubModule) { + continue; + } + nodeDescriptions.addAll(getNodeDescriptions(module)); + } + return nodeDescriptions; + } + + /** + * serialize the yang statistics of schema context to xlsx format. + * @param schemaContext yang schema context. + * @return xlsx document + */ + public SXSSFWorkbook serializeXlsx(YangSchemaContext schemaContext) { + SXSSFWorkbook workbook = new SXSSFWorkbook(); + SXSSFSheet summary = workbook.createSheet("summary"); + summary.setDisplayGridlines(true); + summary.setAutobreaks(true); + summary.setColumnWidth(0, 5000); + summary.setColumnWidth(1, 5000); + SXSSFRow sumFirstRow = summary.createRow(0); + SXSSFCell totalModules = sumFirstRow.createCell(0); + totalModules.setCellValue("Total modules:"); + SXSSFCell totalModulesVal = sumFirstRow.createCell(1); + totalModulesVal.setCellValue(schemaContext.getModules().size()); + + SXSSFSheet detail = workbook.createSheet("detail"); + detail.setDisplayGridlines(true); + detail.setAutobreaks(true); + detail.setColumnWidth(0, 20000); + detail.setColumnWidth(1, 5000); + detail.setColumnWidth(2, 20000); + detail.setColumnWidth(3, 5000); + detail.setColumnWidth(4, 5000); + detail.setColumnWidth(5, 5000); + detail.setColumnWidth(6, 5000); + detail.setColumnWidth(7, 5000); + + CellStyle style = workbook.createCellStyle(); + style.setBorderBottom(BorderStyle.THIN); + style.setBorderLeft(BorderStyle.THIN); + style.setBorderRight(BorderStyle.THIN); + style.setBorderTop(BorderStyle.THIN); + + CellStyle desStyle = workbook.createCellStyle(); + desStyle.cloneStyleFrom(style); + desStyle.setAlignment(HorizontalAlignment.JUSTIFY); + + detail.setDefaultColumnStyle(0, style); + detail.setDefaultColumnStyle(1, desStyle); + detail.setDefaultColumnStyle(2, style); + detail.setDefaultColumnStyle(3, style); + detail.setDefaultColumnStyle(4, style); + detail.setDefaultColumnStyle(5, style); + detail.setDefaultColumnStyle(6, style); + detail.setDefaultColumnStyle(7, style); + + //generate header + SXSSFRow firstRow = detail.createRow(0); + SXSSFCell yangpath = firstRow.createCell(0); + yangpath.setCellValue("Path"); + yangpath.setCellStyle(style); + SXSSFCell active = firstRow.createCell(1); + active.setCellValue("Active"); + active.setCellStyle(style); + SXSSFCell description = firstRow.createCell(2); + description.setCellValue("Description"); + description.setCellStyle(style); + SXSSFCell config = firstRow.createCell(3); + config.setCellValue("Config"); + config.setCellStyle(style); + SXSSFCell schema = firstRow.createCell(4); + schema.setCellValue("schema"); + schema.setCellStyle(style); + SXSSFCell type = firstRow.createCell(5); + type.setCellValue("type"); + type.setCellStyle(style); + SXSSFCell moduleHeader = firstRow.createCell(6); + moduleHeader.setCellValue("module"); + moduleHeader.setCellStyle(style); + SXSSFCell deviated = firstRow.createCell(7); + deviated.setCellValue("deviated"); + deviated.setCellStyle(style); + + + List totalPaths = getYangStatistics(schemaContext); + + + if (null != totalPaths) { + int pathSize = totalPaths.size(); + SXSSFRow summarySecRow = summary.createRow(1); + SXSSFCell totalNodes = summarySecRow.createCell(0); + totalNodes.setCellValue("Total nodes:"); + SXSSFCell totalNodesVal = summarySecRow.createCell(1); + totalNodesVal.setCellValue(pathSize); + for (int i = 0; i < pathSize; i++) { + YangNodeDescription path = totalPaths.get(i); + SXSSFRow row = detail.createRow(i + 1); + SXSSFCell pathCell = row.createCell(0); + pathCell.setCellValue(path.getPath()); + pathCell.setCellStyle(style); + SXSSFCell activeCell = row.createCell(1); + activeCell.setCellValue(path.isActive()); + activeCell.setCellStyle(style); + SXSSFCell descriptionCell = row.createCell(2); + String str = path.getDescription(); + if (str.length() >= 32767) { + str = str.substring(0, 32767); + } + descriptionCell.setCellValue(str); + descriptionCell.setCellStyle(desStyle); + + SXSSFCell configCell = row.createCell(3); + configCell.setCellValue(path.getConfig()); + configCell.setCellStyle(style); + + SXSSFCell schemaCell = row.createCell(4); + schemaCell.setCellValue(path.getSchemaType()); + schemaCell.setCellStyle(style); + + SXSSFCell typeCell = row.createCell(5); + typeCell.setCellValue(path.getNodeType()); + typeCell.setCellStyle(style); + + SXSSFCell moduleCell = row.createCell(6); + moduleCell.setCellValue(path.getModule()); + moduleCell.setCellStyle(style); + SXSSFCell deviateCell = row.createCell(7); + deviateCell.setCellValue(path.isDeviated()); + deviateCell.setCellStyle(style); + } + } + return workbook; + } + + /** + * a yang compiler plugin implementation (run method). + * @param schemaContext yang schema context + * @param yangCompiler yang compiler instance + * @param parameters parameters for plugin + * @throws YangCompilerException if error occurs, throw the exception + */ + @Override + public void run(YangSchemaContext schemaContext, YangCompiler yangCompiler, + List parameters) throws YangCompilerException { + + YangCompilerPluginParameter para = parameters.get(0); + if (!para.getName().equals("output")) { + throw new YangCompilerException("unknown parameter:" + para.getName()); + } + String output = (String) para.getValue(); + SXSSFWorkbook workbook = serializeXlsx(schemaContext); + try { + workbook.write(new FileOutputStream(output)); + workbook.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/validator/YangValidator.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/validator/YangValidator.java new file mode 100644 index 0000000..5131416 --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/validator/YangValidator.java @@ -0,0 +1,46 @@ +/* +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.plugin.validator; + +import java.util.List; + +import org.onap.modeling.yangkit.compiler.YangCompiler; +import org.onap.modeling.yangkit.compiler.YangCompilerException; +import org.onap.modeling.yangkit.plugin.YangCompilerPlugin; +import org.onap.modeling.yangkit.plugin.YangCompilerPluginParameter; +import org.yangcentral.yangkit.model.api.schema.YangSchemaContext; +import org.yangcentral.yangkit.utils.file.FileUtil; + + +public class YangValidator implements YangCompilerPlugin { + /** + * the implementation of run method. + * @param schemaContext yang schema context. + * @param yangCompiler yang compiler instance. + * @param parameters parameters of plugin. + * @throws YangCompilerException if error occurs, the exception will be thrown. + */ + @Override + public void run(YangSchemaContext schemaContext, YangCompiler yangCompiler, + List parameters) throws YangCompilerException { + YangCompilerPluginParameter parameter = parameters.get(0); + if (!parameter.getName().equals("output")) { + throw new YangCompilerException("unknown parameter:" + parameter.getName()); + } + FileUtil.writeUtf8File((String) parameter.getValue(), schemaContext.getValidateResult().toString()); + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/ModuleInfo.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/ModuleInfo.java new file mode 100644 index 0000000..1b2a4b4 --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/ModuleInfo.java @@ -0,0 +1,117 @@ +/* +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.plugin.yangpackage; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import java.net.URI; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + +public class ModuleInfo extends SubComponentInfo { + private URI namespace; + private final List subModules = new ArrayList<>(); + + /** + * constructor. + * @param name module name + * @param revision module revision + */ + public ModuleInfo(String name, String revision) { + super(name, revision); + } + + /** + * constructor. + * @param name module name + */ + public ModuleInfo(String name) { + super(name); + } + + /** + * serialize the revision. + * @return serialized revision + */ + @Override + protected Map.Entry serializeRevision() { + if (this.getRevision() == null) { + return null; + } + return new AbstractMap.SimpleEntry<>("revision", this.getRevision()); + } + + /** + * get namespace. + * @return the uri of namespace + */ + public URI getNamespace() { + return namespace; + } + + /** + * set namespace. + * @param namespace the uri of namespace + */ + public void setNamespace(URI namespace) { + this.namespace = namespace; + } + + /** + * get submodules. + * @return list of submodules. + */ + public List getSubModules() { + return subModules; + } + + /** + * add submodule. + * @param subModuleInfo submodule + */ + public void addSubModule(SubModuleInfo subModuleInfo) { + if (subModules.contains(subModuleInfo)) { + return; + } + subModules.add(subModuleInfo); + } + + /** + * serialize the module information. + * @return json element. + */ + @Override + public JsonElement serialize() { + JsonObject jsonObject = super.serialize().getAsJsonObject(); + if (this.getNamespace() != null) { + jsonObject.addProperty("namespace", this.getNamespace().toString()); + } + if (!this.getSubModules().isEmpty()) { + JsonArray subModules = new JsonArray(); + for (SubModuleInfo subModule : this.getSubModules()) { + subModules.add(subModule.serialize()); + } + jsonObject.add("submodule", subModules); + } + return jsonObject; + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/PackageInfo.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/PackageInfo.java new file mode 100644 index 0000000..a46f5f3 --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/PackageInfo.java @@ -0,0 +1,45 @@ +/* +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.plugin.yangpackage; + +import java.util.AbstractMap; +import java.util.Map; + + +public class PackageInfo extends SubComponentInfo { + /** + * constructor. + * @param name package name + * @param revision package revision. + */ + public PackageInfo(String name, String revision) { + super(name, revision); + } + + /** + * serialize the revision. + * @return serialized revision. + */ + @Override + protected Map.Entry serializeRevision() { + if (this.getRevision() == null) { + return null; + } + Map.Entry revisionEntry = new AbstractMap.SimpleEntry<>("version", this.getRevision()); + return revisionEntry; + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/SubComponentInfo.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/SubComponentInfo.java new file mode 100644 index 0000000..6cdd005 --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/SubComponentInfo.java @@ -0,0 +1,171 @@ +/* +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.plugin.yangpackage; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + + +public abstract class SubComponentInfo { + private final String name; + private String revision; + private final List replaceRevisions = new ArrayList<>(); + private List locations; + + /** + * constructor. + * @param name the name of subcomponent. + * @param revision the revision of subcomponent. + */ + public SubComponentInfo(String name, String revision) { + this.name = name; + this.revision = revision; + } + + /** + * constructor. + * @param name the name of subcomponent. + */ + public SubComponentInfo(String name) { + this.name = name; + } + + /** + * get the name of subcomponent. + * @return name. + */ + public String getName() { + return name; + } + + /** + * get the revision of subcomponent. + * @return revision + */ + public String getRevision() { + return revision; + } + + /** + * set the revision of subcomponent. + * @param revision revision + */ + public void setRevision(String revision) { + this.revision = revision; + } + + /** + * get the replaced revisions. + * @return the list of revisions. + */ + public List getReplaceRevisions() { + return replaceRevisions; + } + + /** + * add replace revision. + * @param revision the revision to be replaced. + */ + public void addReplaceRevision(String revision) { + if (replaceRevisions.contains(revision)) { + return; + } + replaceRevisions.add(revision); + } + + /** + * get locations of subcomponent. + * @return list of location uri. + */ + public List getLocations() { + return locations; + } + + /** + * add location. + * @param location location uri. + */ + public void addLocation(URI location) { + if (locations.contains(location)) { + return; + } + locations.add(location); + } + + /** + * equals method. + * @param obj other object. + * @return true or false. + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof SubComponentInfo)) { + return false; + } + SubComponentInfo that = (SubComponentInfo) obj; + return getName().equals(that.getName()) && getRevision().equals(that.getRevision()); + } + + @Override + public int hashCode() { + return Objects.hash(getName(), getRevision()); + } + + /** + * the abstract method of serialize the revision. + * @return serialized revision. + */ + protected abstract Map.Entry serializeRevision(); + + /** + * serialize the subcomponent to json element. + * @return json element. + */ + public JsonElement serialize() { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("name", this.getName()); + if (this.getRevision() != null) { + Map.Entry revisionEntry = serializeRevision(); + jsonObject.addProperty(revisionEntry.getKey(), revisionEntry.getValue()); + } + if (!this.getReplaceRevisions().isEmpty()) { + JsonArray replaceRevisions = new JsonArray(); + for (String replaceRevision : this.getReplaceRevisions()) { + replaceRevisions.add(replaceRevision); + } + jsonObject.add("replaces-version", replaceRevisions); + } + if (!this.getLocations().isEmpty()) { + JsonArray locations = new JsonArray(); + for (URI location : this.getLocations()) { + locations.add(location.toString()); + } + jsonObject.add("location", locations); + } + return jsonObject; + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/SubModuleInfo.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/SubModuleInfo.java new file mode 100644 index 0000000..eb290fc --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/SubModuleInfo.java @@ -0,0 +1,125 @@ +/* +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.plugin.yangpackage; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + + +public class SubModuleInfo { + private final String name; + private final String revision; + private List locations = new ArrayList<>(); + + /** + * constructor. + * @param name submodule name + * @param revision submodule revision + */ + public SubModuleInfo(String name, String revision) { + this.name = name; + this.revision = revision; + } + + /** + * get the submodule name. + * @return name + */ + public String getName() { + return name; + } + + /** + * get the revision of submodule. + * @return revision + */ + public String getRevision() { + return revision; + } + + /** + * get locations of submodule. + * @return list of location. + */ + public List getLocations() { + return locations; + } + + /** + * set the locations. + * @param locations list of location. + */ + public void setLocations(List locations) { + this.locations = locations; + } + + /** + * add a location. + * @param location location uri + */ + public void addLocation(URI location) { + if (locations.contains(location)) { + return; + } + locations.add(location); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof SubModuleInfo)) { + return false; + } + SubModuleInfo that = (SubModuleInfo) obj; + return getName().equals(that.getName()) && getRevision().equals(that.getRevision()); + } + + @Override + public int hashCode() { + return Objects.hash(getName(), getRevision()); + } + + /** + * serialize submodule to json. + * @return json element. + */ + public JsonElement serialize() { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("name", this.getName()); + if (this.getRevision() != null) { + jsonObject.addProperty("revision", this.getRevision()); + } + + if (!this.getLocations().isEmpty()) { + JsonArray locations = new JsonArray(); + for (URI location : this.getLocations()) { + locations.add(location.toString()); + } + jsonObject.add("location", locations); + } + return jsonObject; + + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/YangPackage.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/YangPackage.java new file mode 100644 index 0000000..2a7913f --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/YangPackage.java @@ -0,0 +1,395 @@ +/* +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.plugin.yangpackage; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import java.util.ArrayList; +import java.util.List; + + +public class YangPackage { + private final String name; + private final String revision; + private String timestamp; + private String organization; + private String contact; + private String description; + private String reference; + private boolean complete = true; + private boolean local; + private List tags = new ArrayList<>(); + private List mandatoryFeatures = new ArrayList<>(); + private List includePackages = new ArrayList<>(); + private List modules = new ArrayList<>(); + private List importOnlyModules = new ArrayList<>(); + + /** + * constructor. + * @param name package name + * @param revision package revision + */ + public YangPackage(String name, String revision) { + this.name = name; + this.revision = revision; + } + + /** + * get the package name. + * @return name + */ + public String getName() { + return name; + } + + /** + * get the package revision. + * @return revision + */ + public String getRevision() { + return revision; + } + + /** + * get the timestamp. + * @return timestamp. + */ + public String getTimestamp() { + return timestamp; + } + + /** + * set the timestamp. + * @param timestamp timestamp + */ + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } + + /** + * get organization. + * @return organization. + */ + public String getOrganization() { + return organization; + } + + /** + * set organization. + * @param organization organization + */ + public void setOrganization(String organization) { + this.organization = organization; + } + + /** + * get contact information. + * @return contact. + */ + public String getContact() { + return contact; + } + + /** + * set the contact. + * @param contact contact. + */ + public void setContact(String contact) { + this.contact = contact; + } + + /** + * get description. + * @return description. + */ + public String getDescription() { + return description; + } + + /** + * set description. + * @param description description. + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * get reference. + * @return reference. + */ + public String getReference() { + return reference; + } + + /** + * set reference. + * @param reference reference. + */ + public void setReference(String reference) { + this.reference = reference; + } + + /** + * whether the package is complete. + * @return true or false. + */ + public boolean isComplete() { + return complete; + } + + /** + * set whether the package is complete. + * @param complete true or false. + */ + public void setComplete(boolean complete) { + this.complete = complete; + } + + /** + * whether the package is local. + * @return true or false + */ + public boolean isLocal() { + return local; + } + + /** + * set whether the package is local. + * @param local true or false + */ + public void setLocal(boolean local) { + this.local = local; + } + + /** + * get the tags of package. + * @return the list of tags. + */ + public List getTags() { + return tags; + } + + /** + * set the tags of package. + * @param tags the list of tags. + */ + public void setTags(List tags) { + this.tags = tags; + } + + /** + * add a tag to package. + * @param tag tag + */ + public void addTag(String tag) { + if (tags.contains(tag)) { + return; + } + tags.add(tag); + } + + /** + * get mandatory features of package. + * @return list of features. + */ + public List getMandatoryFeatures() { + return mandatoryFeatures; + } + + /** + * set mandatory features. + * @param mandatoryFeatures list of mandatory features. + */ + public void setMandatoryFeatures(List mandatoryFeatures) { + this.mandatoryFeatures = mandatoryFeatures; + } + + /** + * add mandatory feature. + * @param feature feature + */ + public void addMandatoryFeature(String feature) { + if (mandatoryFeatures.contains(feature)) { + return; + } + mandatoryFeatures.add(feature); + } + + /** + * get include packages. + * @return list of included packages. + */ + public List getIncludePackages() { + return includePackages; + } + + /** + * set the include packages. + * @param includePackages the list of include packages. + */ + public void setIncludePackages(List includePackages) { + this.includePackages = includePackages; + } + + /** + * add a include package. + * @param packageInfo package + */ + public void addIncludePackage(PackageInfo packageInfo) { + if (includePackages.contains(packageInfo)) { + return; + } + includePackages.add(packageInfo); + } + + /** + * get the modules of package. + * @return list of modules. + */ + public List getModules() { + return modules; + } + + /** + * set the modules of package. + * @param modules list of modules + */ + public void setModules(List modules) { + this.modules = modules; + } + + /** + * add a module to package. + * @param module module + */ + public void addModule(ModuleInfo module) { + if (this.modules.contains(module)) { + return; + } + modules.add(module); + } + + /** + * get import-only modules. + * @return list of modules. + */ + public List getImportOnlyModules() { + return importOnlyModules; + } + + /** + * add a import-only module. + * @param module module + */ + public void addImportOnlyModule(ModuleInfo module) { + if (importOnlyModules.contains(module)) { + return; + } + importOnlyModules.add(module); + } + + /** + * set import-only modules. + * @param importOnlyModules list of modules + */ + public void setImportOnlyModules(List importOnlyModules) { + this.importOnlyModules = importOnlyModules; + } + + /** + * serialize yang package to json. + * @return json element + */ + public JsonElement serialize() { + JsonObject document = new JsonObject(); + JsonObject instanceDataset = new JsonObject(); + document.add("ietf-yang-instance-data:instance-data-set", instanceDataset); + instanceDataset.addProperty("name", this.getName()); + JsonObject contentSchema = new JsonObject(); + instanceDataset.add("content-schema", contentSchema); + JsonArray moduleArray = new JsonArray(); + moduleArray.add("ietf-yang-package-instance@2020-01-21"); + contentSchema.add("module", moduleArray); + JsonObject contentData = new JsonObject(); + instanceDataset.add("content-data", contentData); + JsonObject yangPackage = new JsonObject(); + contentData.add("ietf-yang-package-instance:yang-package", yangPackage); + yangPackage.addProperty("name", this.getName()); + yangPackage.addProperty("version", this.getRevision()); + // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + // String dateTime = sdf.format(new Date(System.currentTimeMillis())); + if (this.getTimestamp() != null) { + yangPackage.addProperty("timestamp", this.getTimestamp()); + } + + if (this.getOrganization() != null) { + yangPackage.addProperty("organization", this.getOrganization()); + } + if (this.getContact() != null) { + yangPackage.addProperty("contact", this.getContact()); + } + if (this.getDescription() != null) { + yangPackage.addProperty("description", this.getDescription()); + } + if (this.getReference() != null) { + yangPackage.addProperty("reference", this.getReference()); + } + yangPackage.addProperty("complete", this.isComplete()); + yangPackage.addProperty("local", this.isLocal()); + + if (!this.getTags().isEmpty()) { + JsonArray tags = new JsonArray(); + for (String tag : this.getTags()) { + tags.add(tag); + } + yangPackage.add("tag", tags); + } + if (!this.getMandatoryFeatures().isEmpty()) { + JsonArray mandatoryFeatures = new JsonArray(); + for (String mandatoryFeature : this.getMandatoryFeatures()) { + mandatoryFeatures.add(mandatoryFeature); + } + yangPackage.add("mandatory-feature", mandatoryFeatures); + } + if (!this.getIncludePackages().isEmpty()) { + JsonArray includePackages = new JsonArray(); + for (PackageInfo packageInfo : this.getIncludePackages()) { + includePackages.add(packageInfo.serialize()); + } + yangPackage.add("included-package", includePackages); + } + if (!this.getModules().isEmpty()) { + JsonArray modules = new JsonArray(); + for (ModuleInfo moduleInfo : this.getModules()) { + modules.add(moduleInfo.serialize()); + } + yangPackage.add("module", modules); + } + + if (!this.getImportOnlyModules().isEmpty()) { + JsonArray importOnlyModules = new JsonArray(); + for (ModuleInfo importOnlyModule : this.getImportOnlyModules()) { + importOnlyModules.add(importOnlyModule.serialize()); + } + yangPackage.add("import-only-module", importOnlyModules); + } + return yangPackage; + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/YangPackageGenerator.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/YangPackageGenerator.java new file mode 100644 index 0000000..a6cfbef --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/YangPackageGenerator.java @@ -0,0 +1,154 @@ +/* +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.plugin.yangpackage; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FilenameFilter; +import java.util.List; +import java.util.Properties; + +import org.onap.modeling.yangkit.compiler.YangCompiler; +import org.onap.modeling.yangkit.compiler.YangCompilerException; +import org.onap.modeling.yangkit.plugin.YangCompilerPlugin; +import org.onap.modeling.yangkit.plugin.YangCompilerPluginParameter; +import org.yangcentral.yangkit.model.api.schema.YangSchemaContext; +import org.yangcentral.yangkit.model.api.stmt.Include; +import org.yangcentral.yangkit.model.api.stmt.MainModule; +import org.yangcentral.yangkit.model.api.stmt.Module; +import org.yangcentral.yangkit.model.api.stmt.SubModule; + + +public class YangPackageGenerator implements YangCompilerPlugin { + @Override + public YangCompilerPluginParameter getParameter(Properties compilerProps, String name, String value) + throws YangCompilerException { + if (!name.equals("complete") && !name.equals("meta") && !name.equals("output")) { + throw new YangCompilerException("unrecognized parameter:" + name); + } + if (name.equals("complete")) { + YangCompilerPluginParameter pluginParameter = new YangCompilerPluginParameter() { + @Override + public String getName() { + return name; + } + + @Override + public Object getValue() throws YangCompilerException { + return Boolean.valueOf(value); + } + }; + return pluginParameter; + } + return YangCompilerPlugin.super.getParameter(compilerProps, name, value); + } + + @Override + public void run(YangSchemaContext schemaContext, YangCompiler yangCompiler, + List parameters) + throws YangCompilerException { + String output = null; + for (YangCompilerPluginParameter parameter : parameters) { + if (parameter.getName().equals("output")) { + output = (String) parameter.getValue(); + } else { + throw new YangCompilerException("unknown parameter:" + parameter.getName()); + } + } + if (output == null) { + throw new YangCompilerException("missing mandatory parameter:output"); + } + + File yangDir = yangCompiler.getYang(); + //search package_meta.json + File packageMetaFile = new File(yangDir, "package_meta.json"); + if (!packageMetaFile.exists()) { + throw new YangCompilerException("missing package_meta.json in directory:" + yangDir.getAbsolutePath()); + } + + try { + //parse yang package meta information + JsonElement element = JsonParser.parseReader(new FileReader(packageMetaFile)); + YangPackageMeta yangPackageMeta = new YangPackageMeta(); + yangPackageMeta.deserialize(element); + //set meta information for yang package + YangPackage yangPackage = new YangPackage(yangPackageMeta.getName(), yangPackageMeta.getRevision()); + yangPackage.setOrganization(yangPackageMeta.getOrganization()); + yangPackage.setContact(yangPackageMeta.getContact()); + yangPackage.setDescription(yangPackageMeta.getDescription()); + yangPackage.setReference(yangPackageMeta.getReference()); + yangPackage.setLocal(yangPackageMeta.isLocal()); + yangPackage.setTags(yangPackageMeta.getTags()); + yangPackage.setMandatoryFeatures(yangPackageMeta.getMandatoryFeatures()); + yangPackage.setIncludePackages(yangPackageMeta.getIncludePackages()); + if (schemaContext.getImportOnlyModules().isEmpty()) { + yangPackage.setComplete(true); + } + FilenameFilter packageMetaFilter = new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + if (name.equals("package_meta.json")) { + return true; + } + return false; + } + }; + File[] metaFiles = yangDir.listFiles(packageMetaFilter); + List modules = schemaContext.getModules(); + for (Module module : modules) { + if (module instanceof MainModule) { + ModuleInfo moduleInfo = new ModuleInfo(module.getArgStr(), module.getCurRevisionDate().get()); + moduleInfo.setNamespace(((MainModule) module).getNamespace().getUri()); + if (!module.getIncludes().isEmpty()) { + for (Include include : module.getIncludes()) { + SubModule subModule = include.getInclude().get(); + SubModuleInfo subModuleInfo = + new SubModuleInfo(subModule.getArgStr(), subModule.getCurRevisionDate().get()); + moduleInfo.addSubModule(subModuleInfo); + } + } + yangPackage.addModule(moduleInfo); + } + } + for (Module importOnlyModule : schemaContext.getImportOnlyModules()) { + if (!(importOnlyModule instanceof MainModule)) { + continue; + } + ModuleInfo moduleInfo = + new ModuleInfo(importOnlyModule.getArgStr(), importOnlyModule.getCurRevisionDate().get()); + moduleInfo.setNamespace(((MainModule) importOnlyModule).getNamespace().getUri()); + if (!importOnlyModule.getIncludes().isEmpty()) { + for (Include include : importOnlyModule.getIncludes()) { + SubModule subModule = include.getInclude().get(); + SubModuleInfo subModuleInfo = + new SubModuleInfo(subModule.getArgStr(), subModule.getCurRevisionDate().get()); + moduleInfo.addSubModule(subModuleInfo); + } + } + yangPackage.addImportOnlyModule(moduleInfo); + } + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/YangPackageMeta.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/YangPackageMeta.java new file mode 100644 index 0000000..40da4ba --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangpackage/YangPackageMeta.java @@ -0,0 +1,187 @@ +/* +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.plugin.yangpackage; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import java.util.ArrayList; +import java.util.List; + + +public class YangPackageMeta { + private String name; + private String revision; + private String organization; + private String contact; + private String description; + private String reference; + private boolean local; + private final List tags = new ArrayList<>(); + private final List mandatoryFeatures = new ArrayList<>(); + private final List includePackages = new ArrayList<>(); + + /** + * get the package name. + * @return name + */ + public String getName() { + return name; + } + + /** + * get revision of package. + * @return revision + */ + public String getRevision() { + return revision; + } + + /** + * get organization. + * @return organization. + */ + public String getOrganization() { + return organization; + } + + /** + * get contact. + * @return contact. + */ + public String getContact() { + return contact; + } + + /** + * get description. + * @return description. + */ + public String getDescription() { + return description; + } + + /** + * get reference. + * @return reference. + */ + public String getReference() { + return reference; + } + + /** + * whether the package is local. + * @return true or false + */ + public boolean isLocal() { + return local; + } + + /** + * get tags of package. + * @return list of tags. + */ + public List getTags() { + return tags; + } + + /** + * get mandatory features. + * @return list of features/ + */ + public List getMandatoryFeatures() { + return mandatoryFeatures; + } + + /** + * get include packages. + * @return list of packages. + */ + public List getIncludePackages() { + return includePackages; + } + + /** + * deserialized package meta from json. + * @param metaDoc json element + */ + public void deserialize(JsonElement metaDoc) { + JsonObject jsonObject = metaDoc.getAsJsonObject(); + JsonElement nameElement = jsonObject.get("name"); + if (nameElement != null) { + this.name = nameElement.getAsString(); + } + JsonElement versionElement = jsonObject.get("version"); + if (versionElement != null) { + this.revision = versionElement.getAsString(); + } + JsonElement organizationElement = jsonObject.get("organization"); + if (organizationElement != null) { + this.organization = organizationElement.getAsString(); + } + JsonElement contactElement = jsonObject.get("contact"); + if (contactElement != null) { + this.contact = contactElement.getAsString(); + } + JsonElement descElement = jsonObject.get("description"); + if (descElement != null) { + this.description = descElement.getAsString(); + } + JsonElement referElement = jsonObject.get("reference"); + if (referElement != null) { + this.reference = referElement.getAsString(); + } + + JsonElement localElement = jsonObject.get("local"); + if (localElement != null) { + this.local = referElement.getAsBoolean(); + } + JsonElement tagElement = jsonObject.get("tag"); + if (tagElement != null) { + JsonArray tagArray = tagElement.getAsJsonArray(); + int size = tagArray.size(); + for (int i = 0; i < size; i++) { + JsonElement tagIns = tagArray.get(i); + this.tags.add(tagIns.getAsString()); + } + } + + JsonElement mandatoryFeaturesElement = jsonObject.get("mandatory-feature"); + if (mandatoryFeaturesElement != null) { + JsonArray mandatoryFeaturesArray = mandatoryFeaturesElement.getAsJsonArray(); + int size = mandatoryFeaturesArray.size(); + for (int i = 0; i < size; i++) { + JsonElement featureIns = mandatoryFeaturesArray.get(i); + this.mandatoryFeatures.add(featureIns.getAsString()); + } + } + JsonElement includePackagesElement = jsonObject.get("include-package"); + if (includePackagesElement != null) { + JsonArray includePackageArray = includePackagesElement.getAsJsonArray(); + int size = includePackageArray.size(); + for (int i = 0; i < size; i++) { + JsonElement includePackageIns = includePackageArray.get(i); + JsonObject includePackageObj = includePackageIns.getAsJsonObject(); + PackageInfo packageInfo = new PackageInfo(includePackageObj.get("name").getAsString(), + includePackageObj.get("version").getAsString()); + this.includePackages.add(packageInfo); + } + } + + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangtree/GroupingSchemaNodeContainer.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangtree/GroupingSchemaNodeContainer.java new file mode 100644 index 0000000..67fd48d --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangtree/GroupingSchemaNodeContainer.java @@ -0,0 +1,141 @@ +/* +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.plugin.yangtree; + +import java.util.ArrayList; +import java.util.List; + +import org.yangcentral.yangkit.common.api.QName; +import org.yangcentral.yangkit.common.api.validate.ValidatorResult; +import org.yangcentral.yangkit.model.api.stmt.Action; +import org.yangcentral.yangkit.model.api.stmt.ActionContainer; +import org.yangcentral.yangkit.model.api.stmt.Augment; +import org.yangcentral.yangkit.model.api.stmt.DataDefContainer; +import org.yangcentral.yangkit.model.api.stmt.DataDefinition; +import org.yangcentral.yangkit.model.api.stmt.DataNode; +import org.yangcentral.yangkit.model.api.stmt.Grouping; +import org.yangcentral.yangkit.model.api.stmt.GroupingDefContainer; +import org.yangcentral.yangkit.model.api.stmt.Notification; +import org.yangcentral.yangkit.model.api.stmt.NotificationContainer; +import org.yangcentral.yangkit.model.api.stmt.SchemaNode; +import org.yangcentral.yangkit.model.api.stmt.SchemaNodeContainer; +import org.yangcentral.yangkit.model.api.stmt.Uses; +import org.yangcentral.yangkit.model.api.stmt.YangStatement; + + +public class GroupingSchemaNodeContainer implements SchemaNodeContainer, GroupingDefContainer { + + private final YangStatement container; + + /** + * constructor. + * @param container schema node container + */ + public GroupingSchemaNodeContainer(YangStatement container) { + this.container = container; + } + + @Override + public List getGroupings() { + List groupings = new ArrayList<>(); + if (container instanceof GroupingDefContainer) { + groupings.addAll(((GroupingDefContainer) container).getGroupings()); + } + return groupings; + } + + @Override + public Grouping getGrouping(String name) { + return null; + } + + @Override + public List getSchemaNodeChildren() { + List schemaNodes = new ArrayList<>(); + if (container instanceof DataDefContainer) { + DataDefContainer dataDefContainer = (DataDefContainer) container; + for (DataDefinition dataDefinition : dataDefContainer.getDataDefChildren()) { + schemaNodes.add(dataDefinition); + } + } + + if (container instanceof ActionContainer) { + ActionContainer actionContainer = (ActionContainer) container; + for (Action action : actionContainer.getActions()) { + schemaNodes.add(action); + } + } + + if (container instanceof NotificationContainer) { + for (Notification notification : ((NotificationContainer) container).getNotifications()) { + schemaNodes.add(notification); + } + } + if (container instanceof Uses) { + for (Augment augment : ((Uses) container).getAugments()) { + schemaNodes.add(augment); + } + } + + return schemaNodes; + } + + @Override + public ValidatorResult addSchemaNodeChild(SchemaNode schemaNode) { + return null; + } + + @Override + public ValidatorResult addSchemaNodeChildren(List schemaNodes) { + return null; + } + + @Override + public SchemaNode getSchemaNodeChild(QName identifier) { + return null; + } + + @Override + public DataNode getDataNodeChild(QName identifier) { + return null; + } + + @Override + public List getDataNodeChildren() { + return null; + } + + @Override + public List getEffectiveSchemaNodeChildren(boolean ignoreNamespace) { + return null; + } + + @Override + public void removeSchemaNodeChild(QName identifier) { + + } + + @Override + public void removeSchemaNodeChild(SchemaNode schemaNode) { + + } + + @Override + public SchemaNode getMandatoryDescendant() { + return null; + } +} diff --git a/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangtree/YangTreeGenerator.java b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangtree/YangTreeGenerator.java new file mode 100644 index 0000000..45f7b94 --- /dev/null +++ b/yang-compiler/src/main/java/org/onap/modeling/yangkit/plugin/yangtree/YangTreeGenerator.java @@ -0,0 +1,654 @@ +/* +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.plugin.yangtree; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.onap.modeling.yangkit.compiler.YangCompiler; +import org.onap.modeling.yangkit.compiler.YangCompilerException; +import org.onap.modeling.yangkit.plugin.YangCompilerPlugin; +import org.onap.modeling.yangkit.plugin.YangCompilerPluginParameter; +import org.yangcentral.yangkit.common.api.QName; +import org.yangcentral.yangkit.model.api.restriction.LeafRef; +import org.yangcentral.yangkit.model.api.schema.SchemaTreeType; +import org.yangcentral.yangkit.model.api.schema.YangSchemaContext; + +import org.yangcentral.yangkit.model.api.stmt.Action; +import org.yangcentral.yangkit.model.api.stmt.Anydata; +import org.yangcentral.yangkit.model.api.stmt.Anyxml; +import org.yangcentral.yangkit.model.api.stmt.Augment; +import org.yangcentral.yangkit.model.api.stmt.Case; +import org.yangcentral.yangkit.model.api.stmt.Choice; +import org.yangcentral.yangkit.model.api.stmt.Container; +import org.yangcentral.yangkit.model.api.stmt.DataDefinition; +import org.yangcentral.yangkit.model.api.stmt.Entity; +import org.yangcentral.yangkit.model.api.stmt.Grouping; +import org.yangcentral.yangkit.model.api.stmt.GroupingDefContainer; +import org.yangcentral.yangkit.model.api.stmt.IfFeature; +import org.yangcentral.yangkit.model.api.stmt.IfFeatureSupport; +import org.yangcentral.yangkit.model.api.stmt.Leaf; +import org.yangcentral.yangkit.model.api.stmt.MainModule; +import org.yangcentral.yangkit.model.api.stmt.Module; +import org.yangcentral.yangkit.model.api.stmt.MultiInstancesDataNode; +import org.yangcentral.yangkit.model.api.stmt.Notification; +import org.yangcentral.yangkit.model.api.stmt.Rpc; +import org.yangcentral.yangkit.model.api.stmt.SchemaDataNode; +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.TypedDataNode; +import org.yangcentral.yangkit.model.api.stmt.Uses; +import org.yangcentral.yangkit.model.api.stmt.YangList; +import org.yangcentral.yangkit.model.api.stmt.YangStatement; +import org.yangcentral.yangkit.model.api.stmt.YangUnknown; +import org.yangcentral.yangkit.model.api.stmt.ext.AugmentStructure; +import org.yangcentral.yangkit.model.api.stmt.ext.YangData; +import org.yangcentral.yangkit.model.api.stmt.ext.YangDataStructure; +import org.yangcentral.yangkit.utils.file.FileUtil; + + +public class YangTreeGenerator implements YangCompilerPlugin { + private int lineLength = 72; + private boolean expandGrouping = true; + private String output; + private static final String SPACE = " "; + private static final String TWO_SPACES = " "; + private static final String OFFSET = " "; + private static final String VERTICAL_OFFSET = "| "; + + /** + * build yang tree from module. + * @param module module + * @return yang tree string + */ + public String buildYangTree(Module module) { + StringBuilder sb = new StringBuilder(); + if (module instanceof MainModule) { + sb.append("module:"); + } else { + sb.append("submodule:"); + } + sb.append(SPACE); + sb.append(module.getArgStr()); + sb.append("\n"); + //data nodes + List dataDefs = module.getDataDefChildren(); + + //augments + List augments = module.getAugments(); + + + List yangDataList = module.getUnknowns( + new QName("urn:ietf:params:xml:ns:yang:ietf-restconf", "yang-data")); + + // yang structure extension + List yangStructureList = module.getUnknowns(YangDataStructure.YANG_KEYWORD); + + // augment structure extension + List augmentStructureList = module.getUnknowns(AugmentStructure.YANG_KEYWORD); + + if (!module.getGroupings().isEmpty() + && (!expandGrouping + || (module.getDataDefChildren().isEmpty() + && module.getRpcs().isEmpty() + && module.getNotifications().isEmpty() + && module.getAugments().isEmpty() + && yangDataList.isEmpty() + && yangStructureList.isEmpty() + && augmentStructureList.isEmpty()))) { + sb.append(buildGroupingContainer(module, TWO_SPACES)); + } + //data nodes + if (!dataDefs.isEmpty()) { + int size = dataDefs.size(); + boolean last = false; + for (int i = 0; i < size; i++) { + if (i == (size - 1)) { + last = true; + } + DataDefinition dataDefinition = dataDefs.get(i); + sb.append(buildYangTree(dataDefinition, last, TWO_SPACES, !expandGrouping)); + } + } + //augments + if (!augments.isEmpty()) { + for (Augment augment : augments) { + sb.append(buildAugmentRepresentation(augment, TWO_SPACES)); + sb.append(buildChildren(augment, TWO_SPACES + TWO_SPACES, !expandGrouping)); + } + } + //rpcs + List rpcs = module.getRpcs(); + if (!rpcs.isEmpty()) { + sb.append(TWO_SPACES); + sb.append("rpcs:\n"); + int size = rpcs.size(); + boolean last = false; + for (int i = 0; i < size; i++) { + if (i == (size - 1)) { + last = true; + } + Rpc rpc = rpcs.get(i); + sb.append(buildYangTree(rpc, last, TWO_SPACES + TWO_SPACES, !expandGrouping)); + } + } + //notifications + List notifications = module.getNotifications(); + if (!notifications.isEmpty()) { + sb.append(TWO_SPACES); + sb.append("notifications:\n"); + int size = notifications.size(); + boolean last = false; + for (int i = 0; i < size; i++) { + if (i == (size - 1)) { + last = true; + } + Notification notification = notifications.get(i); + sb.append(buildYangTree(notification, last, TWO_SPACES + TWO_SPACES, !expandGrouping)); + } + } + //yang data + if (!yangDataList.isEmpty()) { + for (YangUnknown unknown : yangDataList) { + YangData yangData = (YangData) unknown; + sb.append(TWO_SPACES); + sb.append("yang-data"); + sb.append(" "); + sb.append(yangData.getArgStr()); + sb.append(":\n"); + sb.append(buildChildren(yangData, TWO_SPACES + TWO_SPACES, !expandGrouping)); + } + } + //structures + if (!yangStructureList.isEmpty()) { + for (YangUnknown unknown : yangStructureList) { + YangDataStructure structure = (YangDataStructure) unknown; + sb.append(TWO_SPACES); + sb.append("structure"); + sb.append(" "); + sb.append(structure.getArgStr()); + sb.append(":\n"); + if (!expandGrouping) { + sb.append(buildGroupingContainer(structure, TWO_SPACES + TWO_SPACES)); + } + sb.append(buildChildren(structure, TWO_SPACES + TWO_SPACES, !expandGrouping)); + + } + } + //augment-structures + if (!augmentStructureList.isEmpty()) { + for (YangUnknown unknown : augmentStructureList) { + AugmentStructure augmentStructure = (AugmentStructure) unknown; + sb.append(TWO_SPACES); + sb.append("augment-structure"); + sb.append(" "); + sb.append(augmentStructure.getArgStr()); + sb.append(":\n"); + sb.append(buildChildren(augmentStructure, TWO_SPACES + TWO_SPACES, !expandGrouping)); + } + } + + return sb.toString(); + } + + private String buildYangTree(SchemaNode schemaNode, boolean last, String offSet, boolean grouping) { + StringBuilder sb = new StringBuilder(); + if (!grouping && (schemaNode instanceof Uses)) { + Uses uses = (Uses) schemaNode; + List schemaNodes = uses.getSchemaNodeChildren(); + for (int i = 0; i < schemaNodes.size(); i++) { + SchemaNode exSchemaNode = schemaNodes.get(i); + boolean subLast = last; + if (i != (schemaNodes.size() - 1)) { + subLast = false; + } + sb.append(buildYangTree(exSchemaNode, subLast, offSet, grouping)); + } + return sb.toString(); + } + if (schemaNode instanceof Augment) { + sb.append(buildAugmentRepresentation((Augment) schemaNode, offSet)); + } else { + sb.append(buildNodeRepresentation(schemaNode, offSet)); + } + if ((schemaNode instanceof GroupingDefContainer) && grouping) { + sb.append(buildGroupingContainer((GroupingDefContainer) schemaNode, offSet + TWO_SPACES)); + } + if (schemaNode instanceof SchemaNodeContainer) { + String childOffSet = offSet; + if (schemaNode instanceof Augment) { + childOffSet = childOffSet.concat(TWO_SPACES); + } else { + if (last) { + childOffSet = childOffSet.concat(OFFSET); + } else { + childOffSet = childOffSet.concat(VERTICAL_OFFSET); + } + } + + SchemaNodeContainer schemaNodeContainer; + if (!grouping) { + schemaNodeContainer = (SchemaNodeContainer) schemaNode; + } else { + schemaNodeContainer = new GroupingSchemaNodeContainer(schemaNode); + } + + sb.append(buildChildren(schemaNodeContainer, childOffSet, grouping)); + } + + return sb.toString(); + } + + private String buildGroupingContainer(GroupingDefContainer groupingDefContainer, String offSet) { + StringBuilder sb = new StringBuilder(); + //sb.append(offSet); + List groupings = groupingDefContainer.getGroupings(); + int size = groupings.size(); + for (int i = 0; i < size; i++) { + boolean last = false; + if (i == (size - 1)) { + last = true; + } + Grouping grouping = groupings.get(i); + sb.append(buildGrouping(grouping, last, offSet)); + } + return sb.toString(); + } + + private List getRealSchemaChildren(SchemaNodeContainer schemaNodeContainer, boolean grouping) { + List realSchemaNodeChildren = new ArrayList<>(); + + for (SchemaNode schemaChild : schemaNodeContainer.getSchemaNodeChildren()) { + if (schemaChild instanceof Augment) { + Augment augment = (Augment) schemaChild; + if (schemaNodeContainer instanceof SchemaNode) { + SchemaNode schemaNodeParent = (SchemaNode) schemaNodeContainer; + if (augment.getContext().getNamespace() != null && !augment.getContext().getNamespace() + .equals(schemaNodeParent.getContext().getNamespace())) { + continue; + } + } + if (!grouping) { + realSchemaNodeChildren.addAll(getRealSchemaChildren(augment, grouping)); + continue; + } + } + realSchemaNodeChildren.add(schemaChild); + } + return realSchemaNodeChildren; + } + + private String buildChildren(SchemaNodeContainer schemaNodeContainer, String offSet, boolean grouping) { + StringBuilder sb = new StringBuilder(); + List schemaNodeChildren = schemaNodeContainer.getSchemaNodeChildren(); + List realSchemaNodeChildren = getRealSchemaChildren(schemaNodeContainer, grouping); + + int size = realSchemaNodeChildren.size(); + for (int i = 0; i < size; i++) { + SchemaNode realSchemaNode = realSchemaNodeChildren.get(i); + boolean subLast = false; + if (i == (size - 1)) { + subLast = true; + } + sb.append(buildYangTree(realSchemaNode, subLast, offSet, grouping)); + + } + return sb.toString(); + } + + private String buildGrouping(Grouping grouping, boolean last, String offset) { + StringBuilder sb = new StringBuilder(); + sb.append(offset); + sb.append("grouping "); + sb.append(grouping.getArgStr()); + sb.append(":\n"); + GroupingSchemaNodeContainer groupingSchemaNodeContainer = new GroupingSchemaNodeContainer(grouping); + sb.append(buildGroupingContainer(grouping, offset + TWO_SPACES)); + sb.append(buildChildren(groupingSchemaNodeContainer, offset + TWO_SPACES, true)); + return sb.toString(); + } + + + + private String getStatus(YangStatement yangStatement) { + if (yangStatement instanceof Entity) { + Status status = ((Entity) yangStatement).getEffectiveStatus(); + switch (status) { + case CURRENT: { + return "+"; + } + case DEPRECATED: { + return "x"; + } + case OBSOLETE: { + return "o"; + } + default: + throw new IllegalStateException("Unexpected value: " + status); + } + } + return ""; + } + + private String getFlags(YangStatement yangStatement) { + String flags = ""; + if (yangStatement instanceof SchemaNode) { + SchemaNode schemaNode = (SchemaNode) yangStatement; + if (schemaNode instanceof Uses) { + flags = "-u"; + } else if ((schemaNode instanceof Rpc) || (schemaNode instanceof Action)) { + flags = "-x"; + } else if (schemaNode instanceof Notification) { + flags = "-n"; + } else if (schemaNode instanceof Case) { + flags = ""; + } else if (schemaNode.isConfig()) { + flags = "rw"; + } else { + flags = "ro"; + if (schemaNode.getSchemaTreeType() == SchemaTreeType.INPUTTREE) { + flags = "-w"; + } + } + + if (!schemaNode.getSubStatement(new QName("urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount", + "mount-point")).isEmpty()) { + flags = "mp"; + } + } else if (yangStatement instanceof Grouping) { + flags = "rw"; + } + + return flags; + } + + private String getNodeName(YangStatement yangStatement) { + if (yangStatement instanceof Case) { + return ":(" + yangStatement.getArgStr() + ")"; + } else if (yangStatement instanceof Choice) { + return " (" + yangStatement.getArgStr() + ")"; + } else { + return " " + yangStatement.getArgStr(); + } + } + + private boolean isMandatory(SchemaDataNode dataNode) { + //key nodes + if (dataNode instanceof Leaf) { + SchemaNodeContainer parent = dataNode.getClosestAncestorNode(); + if (parent instanceof YangList) { + YangList list = (YangList) parent; + if (list.getKey().getKeyNode(dataNode.getIdentifier()) != null) { + return true; + } + } + } + return dataNode.isMandatory(); + } + + private String getOpts(YangStatement yangStatement) { + if ((yangStatement instanceof Leaf) + || (yangStatement instanceof Choice) + || (yangStatement instanceof Anydata) + || (yangStatement instanceof Anyxml)) { + if (!isMandatory((SchemaDataNode) yangStatement)) { + return "?"; + } + } else if (yangStatement instanceof Container) { + if (((Container) yangStatement).isPresence()) { + return "!"; + } + } else if (yangStatement instanceof MultiInstancesDataNode) { + StringBuilder sb = new StringBuilder("*"); + if (yangStatement instanceof YangList) { + YangList yangList = (YangList) yangStatement; + if (yangList.getKey() != null) { + sb.append(" ["); + sb.append(yangList.getKey().getArgStr()); + sb.append("]"); + } + } + return sb.toString(); + } + return ""; + } + + private String getType(TypedDataNode typedDataNode) { + if (typedDataNode.getType().getRestriction() instanceof LeafRef) { + LeafRef leafRef = (LeafRef) typedDataNode.getType().getRestriction(); + return "-> " + leafRef.getEffectivePath().getArgStr(); + } else { + return typedDataNode.getType().getArgStr(); + } + } + + private String getFeatures(IfFeatureSupport ifFeatureSupport) { + StringBuilder sb = new StringBuilder(); + List ifFeatures = ifFeatureSupport.getIfFeatures(); + if (!ifFeatures.isEmpty()) { + sb.append(" {"); + int size = ifFeatures.size(); + for (int i = 0; i < size; i++) { + IfFeature ifFeature = ifFeatures.get(i); + sb.append(ifFeature.getArgStr()); + if (i != (size - 1)) { + sb.append(","); + } + } + sb.append("}?"); + } + return sb.toString(); + } + + private String wrapLongPath(String offSet, String longPath) { + if ((offSet.length() + longPath.length()) <= lineLength) { + return offSet + longPath; + } + StringBuilder wrappedLine = new StringBuilder(offSet); + String firstCandidatePath = longPath.substring(0, lineLength - offSet.length()); + int index = firstCandidatePath.lastIndexOf("/"); + firstCandidatePath = firstCandidatePath.substring(0, index); + wrappedLine.append(firstCandidatePath); + wrappedLine.append("\n"); + String nextOffSet = offSet + " "; + String nextLongPath = longPath.substring(index); + wrappedLine.append(wrapLongPath(nextOffSet, nextLongPath)); + return wrappedLine.toString(); + } + + /** + * build augmentation representation string. + * @param augment augment + * @param offSet offset + * @return string + */ + public String buildAugmentRepresentation(Augment augment, String offSet) { + StringBuilder sb = new StringBuilder(offSet); + int beginIndex = sb.length(); + sb.append("augment"); + sb.append(" "); + int nameIndex = sb.length(); + sb.append(augment.getArgStr()); + sb.append(":\n"); + if (sb.length() > lineLength) { + String subString = sb.substring(0, lineLength); + int index = subString.lastIndexOf("/"); + StringBuilder newSb = new StringBuilder(); + String firstLine = sb.substring(0, index); + newSb.append(firstLine); + newSb.append("\n"); + newSb.append(offSet); + for (int i = beginIndex; i < (nameIndex + 2); i++) { + newSb.append(" "); + } + newSb.append(sb.substring(index)); + return newSb.toString(); + } + return sb.toString(); + } + + /** + * build a node representation from yang statement. + * @param yangStatement yang statement. + * @param offSet offset. + * @return string + */ + public String buildNodeRepresentation(YangStatement yangStatement, String offSet) { + StringBuilder sb = new StringBuilder(offSet); + int beginIndex = sb.length(); + //status + sb.append(getStatus(yangStatement)).append("--"); + //flags + sb.append(getFlags(yangStatement)); + //name + String name = getNodeName(yangStatement); + int nameIndex = sb.length(); + if (name.startsWith(" ")) { + nameIndex++; + } + sb.append(name); + sb.append(getOpts(yangStatement)); + + + if (yangStatement instanceof TypedDataNode) { + int typeIndex = sb.length(); + TypedDataNode typedDataNode = (TypedDataNode) yangStatement; + String type = getType(typedDataNode); + if (type.length() + typeIndex + 1 > lineLength) { + //change line + StringBuilder newLine = new StringBuilder(); + + StringBuilder newOffSet = new StringBuilder(offSet); + + for (int i = beginIndex; i < nameIndex + 2; i++) { + newOffSet.append(" "); + } + newLine.append(newOffSet); + newLine.append(type); + + if ((typedDataNode.getType().getRestriction() instanceof LeafRef) + && (newLine.length() > lineLength)) { + sb.append(" "); + sb.append("leafref"); + } else { + sb.append("\n"); + sb.append(newLine); + } + + + } else { + sb.append(" "); + sb.append(type); + } + } + + if (yangStatement instanceof IfFeatureSupport) { + IfFeatureSupport ifFeatureSupport = (IfFeatureSupport) yangStatement; + String features = getFeatures(ifFeatureSupport); + if (features.length() > 0) { + int ifFeatureIndex = sb.length(); + int lastCrIndex = sb.lastIndexOf("\n"); + if (lastCrIndex == -1) { + lastCrIndex = 0; + } + if (((ifFeatureIndex - lastCrIndex) + features.length()) > lineLength) { + //change line + sb.append("\n"); + sb.append(offSet); + for (int i = beginIndex; i < (nameIndex + 2); i++) { + sb.append(" "); + } + sb.append(features); + } else { + sb.append(" "); + sb.append(features); + } + } + + } + sb.append("\n"); + return sb.toString(); + } + + @Override + public YangCompilerPluginParameter getParameter(Properties compilerProps, String name, String value) + throws YangCompilerException { + if (!name.equals("output") && !name.equals("line-length") + && !name.equals("expand-grouping")) { + throw new YangCompilerException("unrecognized parameter:" + name); + } + if (name.equals("output")) { + return YangCompilerPlugin.super.getParameter(compilerProps, name, value); + } + YangCompilerPluginParameter yangCompilerPluginParameter = new YangCompilerPluginParameter() { + @Override + public String getName() { + return name; + } + + @Override + public Object getValue() { + + if (name.equals("line-length")) { + return Integer.parseInt(value); + } + + if (name.equals("expand-grouping")) { + return Boolean.valueOf(value); + } + return null; + } + + }; + return yangCompilerPluginParameter; + + + } + + @Override + public void run(YangSchemaContext schemaContext, YangCompiler yangCompiler, + List parameters) throws YangCompilerException { + for (YangCompilerPluginParameter parameter : parameters) { + if (parameter.getName().equals("output")) { + output = (String) parameter.getValue(); + } else if (parameter.getName().equals("line-length")) { + lineLength = (int) parameter.getValue(); + } else if (parameter.getName().equals("expand-grouping")) { + expandGrouping = (boolean) parameter.getValue(); + } + } + if (output == null) { + throw new YangCompilerException("missing mandatory parameter:output"); + } + File outputDir = new File(output); + if (!outputDir.exists()) { + outputDir.mkdirs(); + } + + List modules = schemaContext.getModules(); + for (Module module : modules) { + String yangTree = buildYangTree(module); + FileUtil.writeUtf8File(yangTree, new File(outputDir, + module.getArgStr() + + (module.getCurRevisionDate().isPresent() ? "@" + module.getCurRevisionDate().get() : "") + + "_tree.txt")); + } + } +} -- cgit 1.2.3-korg