This is an automated email from the ASF dual-hosted git repository.

aldrin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git


The following commit(s) were added to refs/heads/master by this push:
     new 60da477  MINIFICPP-1108 - Automate the generation of processors.md
60da477 is described below

commit 60da4771a271d618ec253ed7ba546718f5de1ca1
Author: Marc Parisi <[email protected]>
AuthorDate: Wed Dec 18 15:24:35 2019 +0100

    MINIFICPP-1108 - Automate the generation of processors.md
    
    This closes #700.
    
    Signed-off-by: Aldrin Piri <[email protected]>
---
 main/AgentDocs.cpp  | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 main/AgentDocs.h    |  44 +++++++++++++
 main/CMakeLists.txt |   2 +-
 main/MiNiFiMain.cpp |  35 +++++++++++
 4 files changed, 255 insertions(+), 1 deletion(-)

diff --git a/main/AgentDocs.cpp b/main/AgentDocs.cpp
new file mode 100644
index 0000000..3d2eb76
--- /dev/null
+++ b/main/AgentDocs.cpp
@@ -0,0 +1,175 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+#include "AgentDocs.h"
+#include <vector>
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <fstream>
+#include <set>
+#include <memory>
+#include <string>
+#include "core/ClassLoader.h"
+#include "core/ConfigurableComponent.h"
+#include "core/Core.h"
+#include "core/Processor.h"
+#include "core/Property.h"
+#include "core/PropertyValidation.h"
+#include "core/Relationship.h"
+#include "io/validation.h"
+#include "utils/file/FileUtils.h"
+#include "agent/build_description.h"
+#include "agent/agent_version.h"
+
+namespace org {
+namespace apache {
+namespace nifi {
+namespace minifi {
+namespace docs {
+
+std::string AgentDocs::extractClassName(const std::string &processor) const {
+  auto lastOfIdx = processor.find_last_of(".");
+  if (lastOfIdx != std::string::npos) {
+    lastOfIdx++;  // if a value is found, increment to move beyond the .
+    int nameLength = processor.length() - lastOfIdx;
+    std::string processorName = processor.substr(lastOfIdx, nameLength);
+    return processorName;
+  }
+  return processor;
+
+}
+
+void AgentDocs::generate(const std::string &docsdir, std::ostream &genStream) {
+  std::map<std::string, ClassDescription> processorSet;
+  for (const auto &group : minifi::AgentBuild::getExtensions()) {
+
+    struct Components descriptions = 
BuildDescription::getClassDescriptions(group);
+    for (const auto &processorName : descriptions.processors_) {
+      
processorSet.insert(std::make_pair(extractClassName(processorName.class_name_), 
processorName));
+    }
+  }
+  for (const auto &processor : processorSet) {
+    const std::string &filename = docsdir + 
utils::file::FileUtils::get_separator() + processor.first;
+    std::ofstream outfile(filename);
+
+    std::string description;
+
+    bool foundDescription = minifi::AgentDocs::getDescription(processor.first, 
description);
+
+    if (!foundDescription) {
+      foundDescription = 
minifi::AgentDocs::getDescription(processor.second.class_name_, description);
+    }
+
+    outfile << "## " << processor.first << std::endl << std::endl;
+    if (foundDescription) {
+      outfile << "### Description " << std::endl << std::endl;
+      outfile << description << std::endl;
+    }
+
+    outfile << "### Properties " << std::endl << std::endl;
+    outfile
+        << "In the list below, the names of required properties appear in 
bold. Any other properties (not in bold) are considered optional. The table 
also indicates any default values, and whether a property supports the NiFi 
Expression Language."
+        << std::endl<< std::endl;
+
+    outfile << "| Name | Default Value | Allowable Values | Description | " << 
std::endl << "| - | - | - | - | " << std::endl;
+    for (const auto &prop : processor.second.class_properties_) {
+      bool supportsEl = prop.second.supportsExpressionLangauge();
+      outfile << "|";
+      if (prop.second.getRequired()) {
+        outfile << "**";
+      }
+      outfile << prop.first;
+      if (prop.second.getRequired()) {
+        outfile << "**";
+      }
+      const auto allowableValues = prop.second.getAllowedValues();
+      std::stringstream s;
+      std::copy(allowableValues.begin(),allowableValues.end(), 
std::ostream_iterator<std::string>(s,"<br>"));
+      outfile << "|";
+      const auto defaultValue = prop.second.getDefaultValue().to_string();
+      if (defaultValue.size() == 1 && (int)defaultValue.c_str()[0] == 0x0a){
+        outfile << "\\n";
+      }
+      else{
+        outfile << defaultValue;
+      }
+      outfile << "|" << s.str() << "|" << prop.second.getDescription();
+      if (supportsEl){
+        outfile << "<br/>**Supports Expression Language: true**";
+      }
+      outfile << "|" << std::endl;
+    }
+    outfile << "### Properties " << std::endl << std::endl;
+    outfile << "| Name | Description |" << std::endl << "| - | - |" << 
std::endl;
+    for (const auto &rel : processor.second.class_relationships_) {
+      outfile << "|" << rel.getName() << "|" << rel.getDescription() << "|" << 
std::endl;
+    }
+
+    outfile << std::endl;
+
+  }
+
+  std::map<std::string,std::string> fileList;
+
+  auto fileFind = [&fileList,this](const std::string& base_path, const 
std::string& file) -> bool {
+    if (file.find(".extra") == std::string::npos)
+      fileList.insert( std::make_pair(file, base_path + 
utils::file::FileUtils::get_separator() + file) );
+    return true;
+  };
+
+  // shortened with list_dir
+  utils::file::FileUtils::list_dir(docsdir, fileFind, 
logging::LoggerFactory<AgentDocs>::getLogger());
+  genStream << "<!--"
+  "Licensed to the Apache Software Foundation (ASF) under one or more"
+  "contributor license agreements.  See the NOTICE file distributed with"
+  "this work for additional information regarding copyright ownership."
+  "The ASF licenses this file to You 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."
+  "-->"<<std::endl;
+  genStream << "# Processors" << std::endl << std::endl;
+  genStream << "## Table of Contents" << std::endl << std::endl;
+
+  for(const auto &file : fileList){
+    std::string lcfile=file.first;
+    std::transform(lcfile.begin(), lcfile.end(), lcfile.begin(), ::tolower);
+    genStream << "- [" << file.first << "](#" << lcfile << ")" << std::endl;
+  }
+
+  for(const auto &file : fileList){
+      std::ifstream filestream(file.second);
+      genStream << filestream.rdbuf() << std::endl;
+      std::ifstream filestreamExtra(file.second + ".extra");
+      if (filestreamExtra.good()){
+        genStream << filestreamExtra.rdbuf()<< std::endl;
+      }
+  }
+}
+
+} /* namespace docs */
+} /* namespace minifi */
+} /* namespace nifi */
+} /* namespace apache */
+} /* namespace org */
\ No newline at end of file
diff --git a/main/AgentDocs.h b/main/AgentDocs.h
new file mode 100644
index 0000000..b4aa5a4
--- /dev/null
+++ b/main/AgentDocs.h
@@ -0,0 +1,44 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+#ifndef MAIN_AGENTDOCS_H_
+#define MAIN_AGENTDOCS_H_
+
+#include <iostream>
+
+namespace org {
+namespace apache {
+namespace nifi {
+namespace minifi {
+namespace docs {
+
+class AgentDocs {
+ public:
+  AgentDocs() = default;
+  ~AgentDocs() = default;
+  void generate(const std::string &docsdir, std::ostream &genStream);
+ private:
+  inline std::string extractClassName(const std::string &processor) const;
+};
+
+} /* namespace docs */
+} /* namespace minifi */
+} /* namespace nifi */
+} /* namespace apache */
+} /* namespace org */
+
+#endif  // MAIN_AGENTDOCS_H_
\ No newline at end of file
diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt
index e94d35c..3634bf0 100644
--- a/main/CMakeLists.txt
+++ b/main/CMakeLists.txt
@@ -55,7 +55,7 @@ endif()
 
 endif()
 
-add_executable(minifiexe MiNiFiMain.cpp MiNiFiWindowsService.cpp)
+add_executable(minifiexe MiNiFiMain.cpp MiNiFiWindowsService.cpp AgentDocs.cpp)
 
 if (NOT USE_SHARED_LIBS)
        if (LIBC_STATIC)
diff --git a/main/MiNiFiMain.cpp b/main/MiNiFiMain.cpp
index 3d719e9..8325c51 100644
--- a/main/MiNiFiMain.cpp
+++ b/main/MiNiFiMain.cpp
@@ -46,6 +46,7 @@
 #include <queue>
 #include <map>
 #include <iostream>
+#include <utils/file/FileUtils.h>
 #include "ResourceClaim.h"
 #include "core/Core.h"
 
@@ -54,6 +55,7 @@
 #include "core/RepositoryFactory.h"
 #include "utils/file/PathUtils.h"
 #include "FlowController.h"
+#include "AgentDocs.h"
 #include "Main.h"
 
  // Variables that allow us to avoid a timed wait.
@@ -95,6 +97,17 @@ void sigHandler(int signal) {
        }
 }
 
+void dumpDocs(const std::shared_ptr<minifi::Configure> &configuration, const 
std::string &dir, std::ostream &out) {
+       auto pythoncreator = 
core::ClassLoader::getDefaultClassLoader().instantiate("PythonCreator", 
"PythonCreator");
+       if (nullptr != pythoncreator) {
+               pythoncreator->configure(configuration);
+       }
+
+       minifi::docs::AgentDocs docsCreator;
+
+       docsCreator.generate(dir, out);
+}
+
 int main(int argc, char **argv) {
 #ifdef WIN32
   CheckRunAsService();
@@ -234,6 +247,28 @@ int main(int argc, char **argv) {
        configure->setHome(minifiHome);
        configure->loadConfigureFile(DEFAULT_NIFI_PROPERTIES_FILE);
 
+  if (argc >= 3 && std::string("docs") == argv[1]) {
+    if (utils::file::FileUtils::create_dir(argv[2]) != 0) {
+      std::cerr << "Working directory doesn't exist and cannot be created: " 
<< argv[2] << std::endl;
+      exit(1);
+    }
+
+    std::cerr << "Dumping docs to " << argv[2] << std::endl;
+    if (argc == 4) {
+      std::string filepath, filename;
+      utils::file::PathUtils::getFileNameAndPath(argv[3], filepath, filename);
+      if (filepath == argv[2]) {
+        std::cerr << "Target file should be out of the working directory: " << 
filepath << std::endl;
+        exit(1);
+      }
+      std::ofstream outref(argv[3]);
+      dumpDocs(configure, argv[2], outref);
+    } else{
+      dumpDocs(configure, argv[2], std::cout);
+    }
+    exit(0);
+  }
+
 
        if (configure->get(minifi::Configure::nifi_graceful_shutdown_seconds, 
graceful_shutdown_seconds)) {
                try {

Reply via email to