AMBARI-25083. Fallback to use dynamic field 'ws_*' if new field name contains whitespace (#65)

* AMBARI-25083. Fallback to use dynamic field 'ws_*' if new field name contains whitespace

* Remove replace all
diff --git a/ambari-logsearch-logfeeder-plugin-api/src/main/java/org/apache/ambari/logfeeder/plugin/filter/Filter.java b/ambari-logsearch-logfeeder-plugin-api/src/main/java/org/apache/ambari/logfeeder/plugin/filter/Filter.java
index b0c02a6..1547c1a 100644
--- a/ambari-logsearch-logfeeder-plugin-api/src/main/java/org/apache/ambari/logfeeder/plugin/filter/Filter.java
+++ b/ambari-logsearch-logfeeder-plugin-api/src/main/java/org/apache/ambari/logfeeder/plugin/filter/Filter.java
@@ -34,8 +34,10 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Represents the filter in Log Feeder shipper input configurations.
@@ -120,6 +122,7 @@
         }
       }
     }
+    fallbackFieldNames(jsonObj);
     if (nextFilter != null) {
       nextFilter.apply(jsonObj, inputMarker);
     } else {
@@ -200,4 +203,49 @@
   public Object clone() throws CloneNotSupportedException {
     return super.clone();
   }
+
+  /**
+   * Fallback field names to use _ instead of spaces and use lowercase names with ws suffixes, built-in max: 100 characters - if the name is too big, probably it won't be valid anyway
+   * @param jsonObj field / value pairs to process
+   */
+  protected void fallbackFieldNames(Map<String, Object> jsonObj) {
+    final Set<String> fieldsToRemove = new HashSet<>();
+    final Map<String, Object> fieldValuePairsToAdd = new HashMap<>();
+    for (Map.Entry<String, Object> entry : jsonObj.entrySet()) {
+      String name = entry.getKey();
+      if (containsWhitespace(name) && name.length() < 100) {
+        fieldsToRemove.add(name);
+        name = "ws_" + name.toLowerCase().replaceAll(" ", "_");
+        if (!jsonObj.containsKey(name)) {
+          fieldValuePairsToAdd.put(name, entry.getValue());
+        }
+      }
+    }
+    for (String fieldToRemove : fieldsToRemove) {
+      jsonObj.remove(fieldToRemove);
+    }
+    for (Map.Entry<String, Object> entry : fieldValuePairsToAdd.entrySet()) {
+      jsonObj.put(entry.getKey(), entry.getValue());
+    }
+  }
+
+  /**
+   * Check that string contains whitespaces or not - similar as StringUtils function in order to not include it as a dependency
+   * @param seq character sequence
+   * @return character sequence contains whitespace or not
+   */
+  private boolean containsWhitespace(CharSequence seq) {
+    if (seq == null || seq.length() == 0) {
+      return false;
+    } else {
+      int strLen = seq.length();
+
+      for(int i = 0; i < strLen; ++i) {
+        if (Character.isWhitespace(seq.charAt(i))) {
+          return true;
+        }
+      }
+      return false;
+    }
+  }
 }