AbstractUtils.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */

  20. package org.openspcoop2.utils.json;

  21. import java.io.InputStream;
  22. import java.io.OutputStream;
  23. import java.io.Reader;
  24. import java.io.Serializable;
  25. import java.text.DateFormat;
  26. import java.util.ArrayList;
  27. import java.util.HashMap;
  28. import java.util.Iterator;
  29. import java.util.List;
  30. import java.util.Map;

  31. import org.apache.commons.lang.StringUtils;
  32. import org.openspcoop2.utils.SortedMap;
  33. import org.openspcoop2.utils.UtilsException;
  34. import org.slf4j.Logger;

  35. import com.fasterxml.jackson.databind.JsonNode;
  36. import com.fasterxml.jackson.databind.ObjectMapper;
  37. import com.fasterxml.jackson.databind.ObjectWriter;
  38. import com.fasterxml.jackson.databind.node.ArrayNode;
  39. import com.fasterxml.jackson.databind.node.ObjectNode;
  40. import com.fasterxml.jackson.databind.node.ValueNode;

  41. /**
  42.  * AbstractUtils
  43.  *
  44.  * @author Poli Andrea (apoli@link.it)
  45.  * @author $Author$
  46.  * @version $Rev$, $Date$
  47.  */
  48. public abstract class AbstractUtils {
  49.    
  50.     protected abstract void _initMapper();
  51.     protected abstract void _initWriter(boolean prettyPrint);
  52.    
  53.     protected abstract ObjectMapper _getObjectMapper();
  54.     protected abstract ObjectWriter _getObjectWriter(boolean prettyPrint);
  55.    
  56.     private boolean prettyPrint;
  57.     protected AbstractUtils(boolean prettyPrint) {
  58.         _initMapper();
  59.         this.prettyPrint = prettyPrint;
  60.         _initWriter(this.prettyPrint);
  61.     }
  62.    
  63.     // GET AS
  64.    
  65.     public JsonNode getAsNode(String jsonString) throws UtilsException {
  66.         try {
  67.             return _getObjectMapper().readTree(jsonString);
  68.         }catch(Exception e) {
  69.             throw new UtilsException(e.getMessage(),e);
  70.         }
  71.     }
  72.     public JsonNode getAsNode(byte[] jsonBytes) throws UtilsException {
  73.         try {
  74.             return _getObjectMapper().readTree(jsonBytes);
  75.         }catch(Exception e) {
  76.             throw new UtilsException(e.getMessage(),e);
  77.         }
  78.     }
  79.     public JsonNode getAsNode(InputStream jsonStream) throws UtilsException {
  80.         try {
  81.             return _getObjectMapper().readTree(jsonStream);
  82.         }catch(Exception e) {
  83.             throw new UtilsException(e.getMessage(),e);
  84.         }
  85.     }
  86.     public JsonNode getAsNode(Reader jsonReader) throws UtilsException {
  87.         try {
  88.             return _getObjectMapper().readTree(jsonReader);
  89.         }catch(Exception e) {
  90.             throw new UtilsException(e.getMessage(),e);
  91.         }
  92.     }
  93.     public JsonNode getAsNode(Map<?,?> map) throws UtilsException {
  94.         try {
  95.             return _getObjectMapper().valueToTree(map);
  96.         }catch(Exception e) {
  97.             throw new UtilsException(e.getMessage(),e);
  98.         }
  99.     }
  100.    
  101.     // GET AS OBJECT
  102.    
  103.     public <T> T getAsObject(String jsonString, Class<T> c) throws UtilsException {
  104.         try {
  105.             return _getObjectMapper().readValue(jsonString, c);
  106.         }catch(Exception e) {
  107.             throw new UtilsException(e.getMessage(),e);
  108.         }
  109.     }
  110.     public <T> T getAsObject(byte[] jsonBytes, Class<T> c) throws UtilsException {
  111.         try {
  112.             return _getObjectMapper().readValue(jsonBytes, c);
  113.         }catch(Exception e) {
  114.             throw new UtilsException(e.getMessage(),e);
  115.         }
  116.     }
  117.     public <T> T getAsObject(InputStream jsonStream, Class<T> c) throws UtilsException {
  118.         try {
  119.             return _getObjectMapper().readValue(jsonStream, c);
  120.         }catch(Exception e) {
  121.             throw new UtilsException(e.getMessage(),e);
  122.         }
  123.     }
  124.     public <T> T getAsObject(Reader jsonReader, Class<T> c) throws UtilsException {
  125.         try {
  126.             return _getObjectMapper().readValue(jsonReader, c);
  127.         }catch(Exception e) {
  128.             throw new UtilsException(e.getMessage(),e);
  129.         }
  130.     }

  131.     // NEW DOCUMENT

  132.     public ObjectNode newObjectNode() throws UtilsException {
  133.         try {
  134.             return _getObjectMapper().createObjectNode();
  135.         }catch(Exception e) {
  136.             throw new UtilsException(e.getMessage(),e);
  137.         }
  138.     }
  139.    
  140.     public ArrayNode newArrayNode() throws UtilsException {
  141.         try {
  142.             return _getObjectMapper().createArrayNode();
  143.         }catch(Exception e) {
  144.             throw new UtilsException(e.getMessage(),e);
  145.         }
  146.     }
  147.    
  148.     public DateFormat getDateFormat() throws UtilsException {
  149.         try {
  150.             return _getObjectMapper().getDateFormat();
  151.         }catch(Exception e) {
  152.             throw new UtilsException(e.getMessage(),e);
  153.         }
  154.     }


  155.     // TO BYTE ARRAY

  156.     public byte[] toByteArray(JsonNode doc) throws UtilsException {
  157.         try {
  158.             return _getObjectWriter(this.prettyPrint).writeValueAsBytes(doc);
  159.         }catch(Exception e) {
  160.             throw new UtilsException(e.getMessage(),e);
  161.         }
  162.     }
  163.    
  164.     public byte[] toByteArray(Map<String, Object> doc) throws UtilsException {
  165.         try {
  166.             return _getObjectWriter(this.prettyPrint).writeValueAsBytes(doc);
  167.         }catch(Exception e) {
  168.             throw new UtilsException(e.getMessage(),e);
  169.         }
  170.     }

  171.     // TO STRING

  172.     public String toString(JsonNode doc) throws UtilsException {
  173.         try {
  174.             return _getObjectWriter(this.prettyPrint).writeValueAsString(doc);
  175.         }catch(Exception e) {
  176.             throw new UtilsException(e.getMessage(),e);
  177.         }
  178.     }
  179.    
  180.     public String toString(Map<String, Object> doc) throws UtilsException {
  181.         try {
  182.             return _getObjectWriter(this.prettyPrint).writeValueAsString(doc);
  183.         }catch(Exception e) {
  184.             throw new UtilsException(e.getMessage(),e);
  185.         }
  186.     }

  187.     // WRITE TO

  188.     public void writeTo(JsonNode doc, OutputStream os) throws UtilsException {
  189.         try {
  190.             _getObjectWriter(this.prettyPrint).writeValue(os, doc);
  191.         }catch(Exception e) {
  192.             throw new UtilsException(e.getMessage(),e);
  193.         }
  194.     }
  195.    
  196.     public void writeTo(Object object, OutputStream os) throws UtilsException {
  197.         try {
  198.             _getObjectWriter(this.prettyPrint).writeValue(os, object);
  199.         }catch(Exception e) {
  200.             throw new UtilsException(e.getMessage(),e);
  201.         }
  202.     }
  203.    
  204.     // IS
  205.    
  206.     protected boolean isValid(byte[]jsonBytes){
  207.         try {
  208.             getAsNode(jsonBytes);
  209.             return true;
  210.         } catch(Throwable e) {
  211.             return false;
  212.         }
  213.     }
  214.    
  215.     protected boolean isValid(String jsonString){
  216.         try {
  217.             getAsNode(jsonString);
  218.             return true;
  219.         } catch(Throwable e) {
  220.             return false;
  221.         }
  222.     }
  223.    
  224.     // UTILITIES
  225.    
  226.     public Map<String, Serializable> convertToSimpleMap(JsonNode node){
  227.         return this.convertToSimpleMap(node, true, false, true, false, ".");
  228.     }
  229.     public Map<String, Serializable> convertToSimpleMap(JsonNode node, String separator){
  230.         return this.convertToSimpleMap(node, true, false, true, false, separator);
  231.     }
  232.     public Map<String, Serializable> convertToSimpleMap(JsonNode node,
  233.             boolean analyzeArrayNode, boolean analyzeAsStringArrayNode,
  234.             boolean analyzeObjectNode, boolean analyzeAsStringObjectNode,
  235.             String separator){
  236.         Map<String, Serializable> map = new HashMap<>();
  237.         _convertToSimpleMap(null, node, null, map,
  238.                 analyzeArrayNode, analyzeAsStringArrayNode,
  239.                 analyzeObjectNode, analyzeAsStringObjectNode,
  240.                 separator);
  241.         return map;
  242.     }
  243.     private void _convertToSimpleMap(String name, JsonNode node, String prefix, Map<String, Serializable> map,
  244.             boolean analyzeArrayNode, boolean analyzeAsStringArrayNode,
  245.             boolean analyzeObjectNode, boolean analyzeAsStringObjectNode,
  246.             String separator){
  247.        
  248.         String newPrefix = "";
  249.         if(prefix!=null) {
  250.             newPrefix = prefix+separator;
  251.         }
  252.        
  253.         if(node instanceof ObjectNode) {
  254.        
  255.             Iterator<String> iterator = node.fieldNames();
  256.             while(iterator.hasNext()) {
  257.                 String field = iterator.next();
  258.                 JsonNode child = node.get(field);
  259.                 if(child instanceof ArrayNode) {
  260.                     if(analyzeArrayNode) {
  261.                         ArrayNode array = (ArrayNode) child;
  262.                         if(array.size()>0) {
  263.                             ArrayList<String> lString = new ArrayList<>();
  264.                             for (int i = 0; i < array.size(); i++) {
  265.                                 JsonNode arrayChildNode = array.get(i);
  266.                                 if(arrayChildNode instanceof ArrayNode || arrayChildNode instanceof ObjectNode) {
  267.                                     String prefixRecursive = newPrefix+normalizeKey(field)+"["+i+"]";
  268.                                     _convertToSimpleMap(field, arrayChildNode, prefixRecursive, map,
  269.                                             analyzeArrayNode, analyzeAsStringArrayNode,
  270.                                             analyzeObjectNode, analyzeAsStringObjectNode,
  271.                                             separator);
  272.                                 }
  273.                                 else {
  274.                                     String text = arrayChildNode.asText();
  275.                                     if(text != null && !text.isEmpty())
  276.                                         lString.add(text);
  277.                                 }
  278.                             }
  279.                             if(!lString.isEmpty()) {
  280.                                 map.put(newPrefix+field, lString);
  281.                             }
  282.                         }
  283.                     }
  284.                     else if(analyzeAsStringArrayNode){
  285.                         String text = child.asText();
  286.                         if(text != null && !text.isEmpty())
  287.                             map.put(newPrefix+field, text);
  288.                     }
  289.                 }
  290.                 else if(child instanceof ObjectNode) {
  291.                     if(analyzeObjectNode) {
  292.                         ObjectNode object = (ObjectNode) child;
  293.                         String prefixRecursive = newPrefix+normalizeKey(field);
  294.                         _convertToSimpleMap(field, object, prefixRecursive, map,
  295.                                 analyzeArrayNode, analyzeAsStringArrayNode,
  296.                                 analyzeObjectNode, analyzeAsStringObjectNode,
  297.                                 separator);
  298.                     }
  299.                     else if(analyzeAsStringObjectNode){
  300.                         String text = child.asText();
  301.                         if(text != null && !text.isEmpty())
  302.                             map.put(newPrefix+field, text);
  303.                     }
  304.                 }
  305.                 else {
  306.                     String text = child.asText();
  307.                     if(text != null && !text.isEmpty())
  308.                         map.put(newPrefix+field, text);
  309.                 }
  310.             }
  311.            
  312.         }
  313.         else if(node instanceof ArrayNode) {
  314.             ArrayNode array = (ArrayNode) node;
  315.             if(array.size()>0) {
  316.                 ArrayList<String> lString = new ArrayList<>();
  317.                 for (int i = 0; i < array.size(); i++) {
  318.                     JsonNode arrayChildNode = array.get(i);
  319.                     if(arrayChildNode instanceof ArrayNode || arrayChildNode instanceof ObjectNode) {
  320.                         String prefixRecursive = newPrefix+normalizeKey(name)+"["+i+"]";
  321.                         _convertToSimpleMap(name, arrayChildNode, prefixRecursive, map,
  322.                                 analyzeArrayNode, analyzeAsStringArrayNode,
  323.                                 analyzeObjectNode, analyzeAsStringObjectNode,
  324.                                 separator);
  325.                     }
  326.                     else {
  327.                         String text = arrayChildNode.asText();
  328.                         if(text != null && !text.isEmpty())
  329.                             lString.add(text);
  330.                     }
  331.                 }
  332.                 if(!lString.isEmpty()) {
  333.                     map.put(name, lString);
  334.                 }
  335.             }
  336.         }
  337.         else {
  338.             String text = node.asText();
  339.             if(text != null && !text.isEmpty()) {
  340.                 map.put(name, text);
  341.             }
  342.         }
  343.     }
  344.     private static String normalizeKey(String keyParam) {
  345.         String key = keyParam.trim();
  346.         while(key.contains(" ")) {
  347.             key = key.replace(" ", "_");
  348.         }
  349.         return key;
  350.     }
  351.    
  352.    
  353.     // CONVERT TO MAP
  354.    
  355.     protected Map<String, Serializable> convertToMapEngine(Logger log, String source, String raw, List<String> claimsToConvert) {
  356.         JsonNode jsonResponse = null;
  357.         try {
  358.             jsonResponse = this.getAsNode(raw);
  359.         }catch(Exception t) {
  360.             // ignore
  361.         }
  362.         return convertToMapEngine(log, source, jsonResponse, claimsToConvert);
  363.     }
  364.     protected Map<String, Serializable> convertToMapEngine(Logger log, String source, byte[]raw, List<String> claimsToConvert) {
  365.         JsonNode jsonResponse = null;
  366.         try {
  367.             jsonResponse = this.getAsNode(raw);
  368.         }catch(Exception t) {
  369.             // ignore
  370.         }
  371.         return convertToMapEngine(log, source, jsonResponse, claimsToConvert);
  372.     }
  373.     private Map<String, Serializable> convertToMapEngine(Logger log, String source, JsonNode jsonResponse, List<String> claimsToConvert) {
  374.         Map<String, Serializable> returnMap = new HashMap<>();
  375.            
  376.         try {
  377.             if(jsonResponse instanceof ObjectNode) {
  378.                        
  379.                 Iterator<String> iterator = jsonResponse.fieldNames();
  380.                 while(iterator.hasNext()) {
  381.                     String field = iterator.next();
  382.                     if(claimsToConvert==null || claimsToConvert.contains(field)) {
  383.                         try {
  384.                             JsonNode selectedClaim = jsonResponse.get(field);
  385.                             if(selectedClaim instanceof ValueNode) {
  386.                                 returnMap.put(field, selectedClaim.asText());
  387.                             }
  388.                             else if(selectedClaim instanceof ArrayNode) {
  389.                                 ArrayNode array = (ArrayNode) selectedClaim;
  390.                                 if(array.size()>0) {
  391.                                     JsonNode arrayFirstChildNode = array.get(0);
  392.                                     if(arrayFirstChildNode instanceof ValueNode) {
  393.                                         ArrayList<Serializable> l = new ArrayList<>();
  394.                                         for (int i = 0; i < array.size(); i++) {
  395.                                             JsonNode arrayChildNode = array.get(i);
  396.                                             Map<String, Serializable> readClaims = this.convertToSimpleMap(arrayChildNode);
  397.                                             if(readClaims!=null && readClaims.size()>0) {
  398.                                                 if(readClaims.size()==1) {
  399.                                                     for (String claim : readClaims.keySet()) {
  400.                                                         Serializable value = readClaims.get(claim);
  401.                                                         l.add(value);
  402.                                                     }
  403.                                                 }
  404.                                                 else {
  405.                                                     for (String claim : readClaims.keySet()) {
  406.                                                         Serializable value = readClaims.get(claim);
  407.                                                         addAttributeEngine(returnMap, claim==null ? field : claim, value);
  408.                                                     }
  409.                                                 }
  410.                                             }
  411.                                         }
  412.                                         if(!l.isEmpty()) {
  413.                                             addAttributeEngine(returnMap, field, l);
  414.                                         }
  415.                                     }
  416.                                     else {
  417.                                         for (int i = 0; i < array.size(); i++) {
  418.                                             JsonNode arrayChildNode = array.get(i);
  419.                                             Map<String, Serializable> readClaims = this.convertToSimpleMap(arrayChildNode);
  420.                                             if(readClaims!=null && readClaims.size()>0) {
  421.                                                 for (String claim : readClaims.keySet()) {
  422.                                                     Serializable value = readClaims.get(claim);
  423.                                                     addAttributeEngine(returnMap, claim, value);
  424.                                                 }
  425.                                             }
  426.                                         }
  427.                                     }
  428.                                 }
  429.                             }
  430.                             else {
  431.                                 Map<String, Serializable> readClaims = this.convertToSimpleMap(selectedClaim);
  432.                                 if(readClaims!=null && readClaims.size()>0) {
  433.                                     for (String claim : readClaims.keySet()) {
  434.                                         Serializable value = readClaims.get(claim);
  435.                                         addAttributeEngine(returnMap, claim, value);
  436.                                     }
  437.                                 }
  438.                             }
  439.                         }catch(Throwable e) {
  440.                             log.error("Convert claim '"+field+"' to map failed ("+source+"): "+e.getMessage(),e);
  441.                         }
  442.                     }
  443.                 }
  444.             }
  445.         }catch(Throwable e) {
  446.             // ignore
  447.         }

  448.         return returnMap;
  449.     }
  450.     private void addAttributeEngine(Map<String, Serializable> attributes, String claim, Serializable value) {
  451.         if(attributes.containsKey(claim)) {
  452.             for (int j = 1; j < 100; j++) {
  453.                 String newKeyClaim = "_"+claim+"_"+j;
  454.                 if(!attributes.containsKey(newKeyClaim)) {
  455.                     attributes.put(newKeyClaim, attributes.get(claim));
  456.                     break;
  457.                 }
  458.             }
  459.         }
  460.         attributes.put(claim,value); // sovrascrive claim gia' esistente (e' stato salvato con un nome speciale)
  461.     }  
  462.    
  463.    
  464.    
  465.     // INSERT VALUE
  466.    
  467.     public static final String CAST_PREFIX = "cast(";
  468.     public static final String CAST_SUFFIX_AS_INT = " as int)";
  469.     public static final String CAST_SUFFIX_AS_LONG = " as long)";
  470.     public static final String CAST_SUFFIX_AS_FLOAT = " as float)";
  471.     public static final String CAST_SUFFIX_AS_DOUBLE = " as double)";
  472.     public static final String CAST_SUFFIX_AS_BOOLEAN = " as boolean)";
  473.    
  474.     private static final String CAST_ARRAY_OPTIONAL_EMPTY_RESULT = "cast( as string array)";
  475.     public static final String CAST_PREFIX_ARRAY = "cast([";
  476.     public static final String CAST_SUFFIX_AS_STRING_ARRAY = "] as string array)";
  477.    
  478.     public void putValue(ObjectNode objectNode, String key, String value) throws UtilsException {
  479.         if(value!=null) {
  480.             String checkValue = value.trim();
  481.             if(CAST_ARRAY_OPTIONAL_EMPTY_RESULT.equals(checkValue)) {
  482.                 // nop
  483.             }
  484.             else if(checkValue.startsWith(CAST_PREFIX_ARRAY) && checkValue.endsWith(CAST_SUFFIX_AS_STRING_ARRAY)) {
  485.                 String raw = value.trim();
  486.                 try {
  487.                     raw = value.substring(CAST_PREFIX_ARRAY.length(), (value.length()-CAST_SUFFIX_AS_STRING_ARRAY.length()));
  488.                     String [] tmp = raw.split(",");
  489.                     StringBuilder sb = new StringBuilder();
  490.                     if(tmp!=null && tmp.length>0) {
  491.                         for (int i = 0; i < tmp.length; i++) {
  492.                             String check = tmp[i];
  493.                             if(check!=null) {
  494.                                 check = check.trim();  
  495.                             }
  496.                             if(StringUtils.isNotEmpty(check)) {
  497.                                 if(sb.length()>0) {
  498.                                     sb.append(",");
  499.                                 }
  500.                                 sb.append("\"").append(check).append("\"");
  501.                             }
  502.                         }
  503.                     }
  504.                     if(sb.length()>0) {
  505.                         String newValue = "["+sb.toString()+"]";
  506.                         JsonNode node = this.getAsNode(newValue);
  507.                         objectNode.set(key, node);
  508.                     }
  509.                     else {
  510.                         throw new Exception("empty value after parsing");
  511.                     }
  512.                 }catch(Throwable t) {
  513.                     throw new UtilsException("Cast value '"+raw+"' as string array failed: "+t.getMessage(),t);
  514.                 }
  515.             }
  516.             else if(checkValue.startsWith("[") && checkValue.endsWith("]")) {
  517.                 try {
  518.                     JsonNode node = this.getAsNode(value);
  519.                     objectNode.set(key, node);
  520.                 }catch(Throwable t) {
  521.                     boolean throwException = true;
  522.                     // provo ad aggiungere le stringhe
  523.                     String s = checkValue.substring(1, checkValue.length()-1);
  524.                     if(s!=null && StringUtils.isNotEmpty(s)) {
  525.                         String [] tmp = s.split(",");
  526.                         StringBuilder sb = new StringBuilder();
  527.                         if(tmp!=null && tmp.length>0) {
  528.                             for (int i = 0; i < tmp.length; i++) {
  529.                                 String check = tmp[i];
  530.                                 if(check!=null) {
  531.                                     check = check.trim();  
  532.                                 }
  533.                                 if(StringUtils.isNotEmpty(check)) {
  534.                                     if(sb.length()>0) {
  535.                                         sb.append(",");
  536.                                     }
  537.                                     sb.append("\"").append(check).append("\"");
  538.                                 }
  539.                             }
  540.                         }
  541.                         if(sb.length()>0) {
  542.                             try {
  543.                                 String newValue = "["+sb.toString()+"]";
  544.                                 JsonNode node = this.getAsNode(newValue);
  545.                                 objectNode.set(key, node);
  546.                                 throwException = false;
  547.                             }catch(Throwable t2) {
  548.                                 // rilancio prima eccezione
  549.                             }
  550.                         }
  551.                     }
  552.                     if(throwException) {
  553.                         throw new UtilsException("Process value '"+value+"' as array node failed: "+t.getMessage(),t);
  554.                     }
  555.                 }
  556.             }
  557.             else if(checkValue.startsWith("{") && checkValue.endsWith("}")) {
  558.                 JsonNode node = this.getAsNode(value);
  559.                 objectNode.set(key, node);
  560.             }
  561.             else {
  562.                 String checkValueLowerCase = checkValue.toLowerCase();
  563.                 if(checkValueLowerCase.startsWith(CAST_PREFIX) && checkValueLowerCase.endsWith(CAST_SUFFIX_AS_INT)) {
  564.                     String raw = value.trim();
  565.                     try {
  566.                         raw = value.substring(CAST_PREFIX.length(), (value.length()-CAST_SUFFIX_AS_INT.length()));
  567.                         if(raw!=null) {
  568.                             raw = raw.trim();
  569.                             if(StringUtils.isNotEmpty(raw)) {
  570.                                 int v = Integer.valueOf(raw);
  571.                                 objectNode.put(key, v);
  572.                             }
  573.                         }
  574.                     }catch(Throwable t) {
  575.                         throw new UtilsException("Cast value '"+raw+"' as int failed: "+t.getMessage(),t);
  576.                     }
  577.                 }
  578.                 else if(checkValueLowerCase.startsWith(CAST_PREFIX) && checkValueLowerCase.endsWith(CAST_SUFFIX_AS_LONG)) {
  579.                     String raw = value.trim();
  580.                     try {
  581.                         raw = value.substring(CAST_PREFIX.length(), (value.length()-CAST_SUFFIX_AS_LONG.length()));
  582.                         if(raw!=null) {
  583.                             raw = raw.trim();
  584.                             if(StringUtils.isNotEmpty(raw)) {
  585.                                 long v = Long.valueOf(raw);
  586.                                 objectNode.put(key, v);
  587.                             }
  588.                         }
  589.                     }catch(Throwable t) {
  590.                         throw new UtilsException("Cast value '"+raw+"' as long failed: "+t.getMessage(),t);
  591.                     }
  592.                 }
  593.                 else if(checkValueLowerCase.startsWith(CAST_PREFIX) && checkValueLowerCase.endsWith(CAST_SUFFIX_AS_FLOAT)) {
  594.                     String raw = value.trim();
  595.                     try {
  596.                         raw = value.substring(CAST_PREFIX.length(), (value.length()-CAST_SUFFIX_AS_FLOAT.length()));
  597.                         if(raw!=null) {
  598.                             raw = raw.trim();
  599.                             if(StringUtils.isNotEmpty(raw)) {
  600.                                 float v = Float.valueOf(raw);
  601.                                 objectNode.put(key, v);
  602.                             }
  603.                         }
  604.                     }catch(Throwable t) {
  605.                         throw new UtilsException("Cast value '"+raw+"' as float failed: "+t.getMessage(),t);
  606.                     }
  607.                 }
  608.                 else if(checkValueLowerCase.startsWith(CAST_PREFIX) && checkValueLowerCase.endsWith(CAST_SUFFIX_AS_DOUBLE)) {
  609.                     String raw = value.trim();
  610.                     try {
  611.                         raw = value.substring(CAST_PREFIX.length(), (value.length()-CAST_SUFFIX_AS_DOUBLE.length()));
  612.                         if(raw!=null) {
  613.                             raw = raw.trim();
  614.                             if(StringUtils.isNotEmpty(raw)) {
  615.                                 double v = Double.valueOf(raw);
  616.                                 objectNode.put(key, v);
  617.                             }
  618.                         }
  619.                     }catch(Throwable t) {
  620.                         throw new UtilsException("Cast value '"+raw+"' as double failed: "+t.getMessage(),t);
  621.                     }
  622.                 }
  623.                 else if(checkValueLowerCase.startsWith(CAST_PREFIX) && checkValueLowerCase.endsWith(CAST_SUFFIX_AS_BOOLEAN)) {
  624.                     String raw = value.trim();
  625.                     try {
  626.                         raw = value.substring(CAST_PREFIX.length(), (value.length()-CAST_SUFFIX_AS_BOOLEAN.length()));
  627.                         if(raw!=null) {
  628.                             raw = raw.trim();
  629.                             if(StringUtils.isNotEmpty(raw)) {
  630.                                 boolean v = Boolean.valueOf(raw);
  631.                                 objectNode.put(key, v);
  632.                             }
  633.                         }
  634.                     }catch(Throwable t) {
  635.                         throw new UtilsException("Cast value '"+raw+"' as boolean failed: "+t.getMessage(),t);
  636.                     }
  637.                 }
  638.                 else {
  639.                     objectNode.put(key, value);
  640.                 }
  641.             }
  642.         }
  643.     }
  644.    
  645.    
  646.    
  647.     // RENAME
  648.    
  649.     public void renameFieldByPath(JsonNode oNode, Map<String, String> pathToNewName) throws UtilsException {
  650.         renameFieldByPath(oNode, pathToNewName, true);
  651.     }
  652.     public void renameFieldByPath(JsonNode oNode, Map<String, String> pathToNewName, boolean throwNotFound) throws UtilsException {
  653.         renameFieldByPath(oNode, pathToNewName, false, throwNotFound);
  654.     }
  655.     public void renameFieldByPath(JsonNode oNode, Map<String, String> pathToNewName, boolean forceReorder, boolean throwNotFound) throws UtilsException {
  656.         if(pathToNewName==null || pathToNewName.isEmpty()) {
  657.             throw new UtilsException("Conversion map undefined");
  658.         }
  659.         for (String path : pathToNewName.keySet()) {
  660.             String newName = pathToNewName.get(path);
  661.             renameFieldByPath(oNode, path, newName, forceReorder, throwNotFound);
  662.         }
  663.     }
  664.     public void renameFieldByPath(JsonNode oNode, SortedMap<String> pathToNewName) throws UtilsException {
  665.         renameFieldByPath(oNode, pathToNewName, true);
  666.     }
  667.     public void renameFieldByPath(JsonNode oNode, SortedMap<String> pathToNewName, boolean throwNotFound) throws UtilsException {
  668.         renameFieldByPath(oNode, pathToNewName, false, throwNotFound);
  669.     }
  670.     public void renameFieldByPath(JsonNode oNode, SortedMap<String> pathToNewName, boolean forceReorder, boolean throwNotFound) throws UtilsException {
  671.         if(pathToNewName==null || pathToNewName.isEmpty()) {
  672.             throw new UtilsException("Conversion map undefined");
  673.         }
  674.         for (String path : pathToNewName.keys()) {
  675.             String newName = pathToNewName.get(path);
  676.             renameFieldByPath(oNode, path, newName, forceReorder, throwNotFound);
  677.         }
  678.     }
  679.     public void renameFieldByPath(JsonNode oNode, String path, String newName) throws UtilsException {
  680.         renameFieldByPath(oNode, path, newName, true);
  681.     }
  682.     public void renameFieldByPath(JsonNode oNode, String path, String newName, boolean throwNotFound) throws UtilsException {
  683.         renameFieldByPath(oNode, path, newName, false, throwNotFound);
  684.     }
  685.     public void renameFieldByPath(JsonNode oNode, String path, String newName, boolean forceReorder, boolean throwNotFound) throws UtilsException {
  686.            
  687.         boolean esito = true;
  688.         int i = 0;
  689.         while(esito == true && i < 1000000) { // per avere un limite
  690.             try {
  691.                 _renameFieldByPath(oNode, path, newName, forceReorder, true); // lasciare true
  692.                 esito = true;
  693.                 if(SPECIAL_KEY_CONVERT_TO_ARRAY.equals(newName) || newName.startsWith(SPECIAL_KEY_ORDER_ELEMENTS_PREFIX)) {
  694.                     break; // serve un solo giro
  695.                 }
  696.             }catch(UtilsException e) {
  697.                 if(i==0){
  698.                     if(SPECIAL_KEY_CONVERT_TO_ARRAY.equals(newName)) {
  699.                         if(! (e.getMessage()!=null && e.getMessage().contains(ALREADY_ARRAY_TYPE_ERROR)) ) {
  700.                             if(throwNotFound) {
  701.                                 throw e;
  702.                             }
  703.                         }
  704.                     }
  705.                     else if(newName.startsWith(SPECIAL_KEY_ORDER_ELEMENTS_PREFIX)) {
  706.                         if(throwNotFound || (e.getMessage()!=null && !e.getMessage().contains("not found")) ) {
  707.                             throw e;
  708.                         }
  709.                     }
  710.                     else {
  711.                         if(throwNotFound) {
  712.                             throw e;
  713.                         }
  714.                     }
  715.                 }
  716.                 if(i>0) {
  717.                     // almeno 1 occorrenza gestita
  718.                     return;
  719.                 }
  720.                 esito = false;
  721.             }
  722.             i++;
  723.         }
  724.        
  725.     }
  726.     public void _renameFieldByPath(JsonNode oNode, String path, String newName, boolean forceReorder, boolean throwNotFound) throws UtilsException {

  727.         String [] pathFragment = path.split("\\.");
  728.         if(pathFragment==null || pathFragment.length<=0) {
  729.             throw new UtilsException("Path undefined");
  730.         }
  731.         if(newName==null) {
  732.             throw new UtilsException("New name undefined");
  733.         }
  734.         if(!oNode.isObject()) {
  735.             throw new UtilsException("Node isn't object");
  736.         }
  737.        
  738.         _StructureNode s = new _StructureNode();
  739.         s.parentNode = oNode;
  740.         s.nodeForRename = oNode;
  741.        
  742.         _renameFieldByPath(s,
  743.                 path, pathFragment, 0,
  744.                 newName, forceReorder, throwNotFound);
  745.     }
  746.    
  747.     private void _renameFieldByPath(_StructureNode structure,
  748.             String path, String [] pathFragment, int position,
  749.             String newName, boolean forceReorder, boolean throwNotFound) throws UtilsException {
  750.        
  751.         //System.out.println("PROCESS ["+structure.parent+"]");
  752.                
  753.         boolean foglia = position==pathFragment.length-1;
  754.         String name = pathFragment[position];
  755.        
  756.         JsonNode parentNode = structure.parentNode;
  757.         JsonNode nodeForRename = structure.nodeForRename;
  758.         /*String parent = structure.parent;
  759.         System.out.println("navigo ["+name+"] (padre:"+parent+")");
  760.         if(nodeForRename.get(name)==null) {
  761.             System.out.println("isObject:"+nodeForRename.isObject());
  762.             System.out.println("isArray:"+nodeForRename.isArray());
  763.         }*/
  764.        
  765.        
  766.         parentNode = nodeForRename;
  767.         nodeForRename = nodeForRename.get(name);
  768.         if(nodeForRename==null || nodeForRename instanceof com.fasterxml.jackson.databind.node.MissingNode) {
  769.             if(throwNotFound &&
  770.                     !"".equals(path) // "" rappresenta il root element json
  771.                 ) {
  772.                 throw new UtilsException("Element '"+name+"' not found (path '"+path+"')");
  773.             }
  774.         }
  775.         if(foglia) {
  776.             //System.out.println("padre:"+parent+")");
  777.             //System.out.println("  newName:"+newName+")");
  778.             //System.out.println("  nodeForRename:"+nodeForRename+")");
  779.             //System.out.println("  parentNode:"+parentNode+")");
  780.            
  781.             if(forceReorder) {
  782.                 List<String> nomi = new ArrayList<>();
  783.                 Iterator<String> it = ((ObjectNode)parentNode).fieldNames();
  784.                 if(it!=null) {
  785.                     while (it.hasNext()) {
  786.                         String fieldName = (String) it.next();
  787.                         nomi.add(fieldName);
  788.                     }
  789.                 }
  790.                 for (String fieldName : nomi) {
  791.                     JsonNode n = ((ObjectNode)parentNode).get(fieldName);
  792.                     if(fieldName.equals(name)) {
  793.                        
  794.                         // caso in gestione
  795.                        
  796.                         if(SPECIAL_KEY_CONVERT_TO_ARRAY.equals(newName)) {
  797.                             if(!n.isArray()) {
  798.                                 //System.out.println("CONVERT TO ARRAY ["+path+"] ["+fieldName+"]");
  799.                                 ((ObjectNode)parentNode).remove(fieldName);
  800.                                 ArrayNode arrayNode = ((ObjectNode)parentNode).arrayNode();
  801.                                 arrayNode.add(n);
  802.                                 ((ObjectNode)parentNode).set(fieldName,arrayNode);
  803.                             }
  804.                             else {
  805.                                 //System.out.println("GIA TROVATO COME ARRAY ["+path+"] ["+fieldName+"]");
  806.                                 if(throwNotFound) {
  807.                                     throw new UtilsException("Element '"+name+"' "+ALREADY_ARRAY_TYPE_ERROR+" (path '"+path+"')");
  808.                                 }
  809.                             }
  810.                         }
  811.                         else {
  812.                             ((ObjectNode)parentNode).remove(fieldName);
  813.                             ((ObjectNode)parentNode).set(newName,n);
  814.                         }
  815.                     }
  816.                     else {
  817.                        
  818.                         // elementi da preservarne l'ordine
  819.                        
  820.                         ((ObjectNode)parentNode).remove(fieldName);
  821.                         ((ObjectNode)parentNode).set(fieldName,n);
  822.                     }
  823.                 }
  824.             }
  825.             else {
  826.                 if(newName.startsWith(SPECIAL_KEY_ORDER_ELEMENTS_PREFIX)) {
  827.                
  828.                     // non supporta forceReorder, per quello non e' presente prima
  829.                     List<String> l = convertReorderFieldChildrenByPathKeyToList(newName);
  830.                    
  831.                     //System.out.println("REORDER--- "+l);
  832.                    
  833.                     JsonNode attuale = null;
  834.                     if("".equals(path)) {
  835.                         attuale = ((ObjectNode)parentNode);
  836.                     }
  837.                     else {
  838.                         attuale = ((ObjectNode)parentNode).get(name);
  839.                     }
  840.                     if(attuale.isArray()) {
  841.                         //throw new UtilsException("Cannot execute reorder in array object (path '"+path+"')");
  842.                         ArrayNode array = (ArrayNode) nodeForRename;
  843.                         if(array!=null && array.size()>0) {
  844.                             for (int i = 0; i < array.size(); i++) {
  845.                                 JsonNode arrayChildNode = array.get(i);
  846.                                 if(arrayChildNode.isObject()) {
  847.                                     // aggiungo elementi in ordine
  848.                                     for (String nameReorder : l) {
  849.                                         JsonNode n = arrayChildNode.get(nameReorder);
  850.                                         if(n==null || n instanceof com.fasterxml.jackson.databind.node.MissingNode) {
  851.                                             //System.out.println("REORDERN NOT FOUND PARENT throwNotFound["+throwNotFound+"] ["+(attuale)+"]");
  852.                                             //throw new UtilsException("Element '"+nameReorder+"' for reorder not found (path '"+path+"')");
  853.                                         }
  854.                                         else {
  855.                                             //System.out.println("REORDER["+nameReorder+"]");
  856.                                             ((ObjectNode)arrayChildNode).remove(nameReorder);
  857.                                             ((ObjectNode)arrayChildNode).set(nameReorder, n);
  858.                                         }
  859.                                     }
  860.                                 }
  861.                                 else {
  862.                                     throw new UtilsException("Cannot execute reorder in simple object (path '"+path+"') (array position i="+i+")");
  863.                                 }
  864.                             }
  865.                         }
  866.                     }
  867.                     else if(attuale.isObject()) {
  868.                         // aggiungo elementi in ordine
  869.                         for (String nameReorder : l) {
  870.                             JsonNode n = attuale.get(nameReorder);
  871.                             if(n==null || n instanceof com.fasterxml.jackson.databind.node.MissingNode) {
  872.                                 //System.out.println("REORDERN NOT FOUND PARENT throwNotFound["+throwNotFound+"] ["+(attuale)+"]");
  873.                                 //throw new UtilsException("Element '"+nameReorder+"' for reorder not found (path '"+path+"')");
  874.                             }
  875.                             else {
  876.                                 //System.out.println("REORDER["+nameReorder+"]");
  877.                                 ((ObjectNode)attuale).remove(nameReorder);
  878.                                 ((ObjectNode)attuale).set(nameReorder, n);
  879.                             }
  880.                         }
  881.                     }
  882.                     else {
  883.                         throw new UtilsException("Cannot execute reorder in simple object (path '"+path+"')");
  884.                     }
  885.                    
  886.                 }
  887.                 else if(SPECIAL_KEY_CONVERT_TO_ARRAY.equals(newName)) {
  888.                     if(nodeForRename!=null && !nodeForRename.isArray()) {
  889.                         //System.out.println("CONVERT TO ARRAY ["+path+"] ["+name+"]");
  890.                         ((ObjectNode)parentNode).remove(name);
  891.                         ArrayNode arrayNode = ((ObjectNode)parentNode).arrayNode();
  892.                         arrayNode.add(nodeForRename);
  893.                         ((ObjectNode)parentNode).set(name,arrayNode);
  894.                     }
  895.                     else {
  896.                         //System.out.println("GIA TROVATO COME ARRAY ["+path+"] ["+name+"]");
  897.                         if(throwNotFound) {
  898.                             throw new UtilsException("Element '"+name+"' "+ALREADY_ARRAY_TYPE_ERROR+" (path '"+path+"')");
  899.                         }
  900.                     }
  901.                 }
  902.                 else {
  903.                     ((ObjectNode)parentNode).remove(name);
  904.                     ((ObjectNode)parentNode).set(newName,nodeForRename);
  905.                 }
  906.                
  907.             }
  908.         }
  909.         else {          
  910.             if(nodeForRename!=null && nodeForRename.isObject() && nodeForRename instanceof ObjectNode) {
  911.                 _StructureNode s = new _StructureNode();
  912.                 s.parentNode = parentNode;
  913.                 s.nodeForRename = nodeForRename;
  914.                 s.parent = name;
  915.                 //System.out.println("CHIAMO PER OBJECT s.parent["+s.parent+"]");
  916.                 try {
  917.                     _renameFieldByPath(s,
  918.                             path, pathFragment, position+1,
  919.                             newName, forceReorder, throwNotFound);
  920.                 }catch(UtilsException e) {
  921.                     if(SPECIAL_KEY_CONVERT_TO_ARRAY.equals(newName)) {
  922.                         if(! (e.getMessage()!=null && e.getMessage().contains(ALREADY_ARRAY_TYPE_ERROR)) ) {
  923.                             throw e;
  924.                         }
  925.                     }
  926.                     else if(newName.startsWith(SPECIAL_KEY_ORDER_ELEMENTS_PREFIX)) {
  927.                         if(e.getMessage()!=null && !e.getMessage().contains("not found")) {
  928.                             throw e;
  929.                         }
  930.                     }
  931.                     else {
  932.                         throw e;
  933.                     }
  934.                 }
  935.             }
  936.             else if(nodeForRename!=null && nodeForRename.isArray() && nodeForRename instanceof ArrayNode) {
  937.                 ArrayNode array = (ArrayNode) nodeForRename;
  938.                 if(array.size()>0) {
  939.                     for (int i = 0; i < array.size(); i++) {
  940.                         JsonNode arrayChildNode = array.get(i);
  941.                         _StructureNode s = new _StructureNode();
  942.                         s.parentNode = nodeForRename;
  943.                         s.nodeForRename = arrayChildNode;
  944.                         s.parent = name+"["+i+"]";
  945.                         //System.out.println("CHIAMO PER ARRAY s.parent["+s.parent+"]");
  946.                         try {
  947.                             _renameFieldByPath(s,
  948.                                     path, pathFragment, position+1,
  949.                                     newName, forceReorder, throwNotFound);
  950.                         }catch(UtilsException e) {
  951.                             if(SPECIAL_KEY_CONVERT_TO_ARRAY.equals(newName)) {
  952.                                 if(! (e.getMessage()!=null && e.getMessage().contains(ALREADY_ARRAY_TYPE_ERROR)) ) {
  953.                                     throw e;
  954.                                 }
  955.                             }
  956.                             else if(newName.startsWith(SPECIAL_KEY_ORDER_ELEMENTS_PREFIX)) {
  957.                                 if(e.getMessage()!=null && !e.getMessage().contains("not found")) {
  958.                                     throw e;
  959.                                 }
  960.                             }
  961.                             else {
  962.                                 throw e;
  963.                             }
  964.                         }
  965.                     }
  966.                 }
  967.             }
  968.             else {
  969.                 throw new UtilsException("Element '"+name+"' not found as object/array (path '"+path+"')");
  970.             }
  971.         }
  972.        
  973.     }
  974.    
  975.     public void renameFieldInCamelCase(JsonNode oNode, boolean firstLowerCase) throws UtilsException {
  976.         renameFieldInCamelCase(oNode, firstLowerCase, false);
  977.     }
  978.     public void renameFieldInCamelCase(JsonNode oNode, boolean firstLowerCase, boolean forceReorder) throws UtilsException {
  979.         SortedMap<String> mapForRename = new SortedMap<String>();
  980.         if(!oNode.isObject()) {
  981.             throw new UtilsException("Node isn't object");
  982.         }
  983.         renameFieldInCamelCase((ObjectNode)oNode, "", mapForRename, firstLowerCase, forceReorder);
  984.         if(!mapForRename.isEmpty()) {
  985.             /*for (String path : mapForRename.keys()) {
  986.                 System.out.println("MAP ["+path+"] -> ["+mapForRename.get(path)+"]");
  987.             }*/
  988.             renameFieldByPath(oNode, mapForRename);
  989.         }
  990.     }
  991.     private static void renameFieldInCamelCase(ObjectNode oNode, String prefix, SortedMap<String> mapForRename,
  992.             boolean firstLowerCase, boolean forceReorder) throws UtilsException {
  993.         Iterator<String> it = oNode.fieldNames();
  994.         if(it!=null) {
  995.             while (it.hasNext()) {
  996.                 String fieldName = (String) it.next();
  997.                 JsonNode node = oNode.get(fieldName);
  998.                
  999.                 if(node!=null){
  1000.                     if(node.isObject() && node instanceof ObjectNode) {
  1001.                         if(StringUtils.isNotEmpty(prefix) && !prefix.endsWith(".")){
  1002.                             prefix = prefix + ".";
  1003.                         }
  1004.                         renameFieldInCamelCase((ObjectNode)node , prefix+fieldName, mapForRename, firstLowerCase, forceReorder);
  1005.                     }
  1006.                     else if(node.isArray() && node instanceof ArrayNode) {
  1007.                         ArrayNode array = (ArrayNode) node;
  1008.                         if(array.size()>0) {
  1009.                             for (int i = 0; i < array.size(); i++) {
  1010.                                 JsonNode arrayChildNode = array.get(i);
  1011.                                 if(arrayChildNode.isObject() && arrayChildNode instanceof ObjectNode) {
  1012.                                     if(StringUtils.isNotEmpty(prefix) && !prefix.endsWith(".")){
  1013.                                         prefix = prefix + ".";
  1014.                                     }
  1015.                                     renameFieldInCamelCase((ObjectNode)arrayChildNode , prefix+fieldName, mapForRename, firstLowerCase, forceReorder);
  1016.                                 }
  1017.                             }
  1018.                         }
  1019.                     }
  1020.                 }
  1021.                
  1022.                 String camelCaseName = camelCase(fieldName, firstLowerCase);
  1023.                 if(!camelCaseName.equals(fieldName) || forceReorder) {
  1024.                    
  1025.                     if(StringUtils.isNotEmpty(prefix) && !prefix.endsWith(".")){
  1026.                         prefix = prefix + ".";
  1027.                     }
  1028.                     String key = prefix+fieldName;
  1029.                     if(!mapForRename.containsKey(key)) {
  1030.                         mapForRename.add(key, camelCaseName);
  1031.                     }
  1032.                 }
  1033.             }
  1034.         }
  1035.     }
  1036.    
  1037.     public static String camelCase(String fieldName, boolean firstLowerCase) {
  1038.        
  1039.         boolean firstCase = firstLowerCase ? Character.isUpperCase(fieldName.charAt(0)) : Character.isLowerCase(fieldName.charAt(0));
  1040.         boolean charSpecial = fieldName.contains("-") || fieldName.contains("_");
  1041.         if (firstCase || charSpecial) {
  1042.        
  1043.             String newName = fieldName;
  1044.             //System.out.println("ANALIZZO ["+newName+"]");
  1045.             if(firstCase) {
  1046.                 if(firstLowerCase) {
  1047.                     newName = (fieldName.length()>1) ?
  1048.                             (((fieldName.charAt(0)+"").toLowerCase()) + fieldName.substring(1))
  1049.                             :
  1050.                             (fieldName.toLowerCase());
  1051.                 }
  1052.                 else {
  1053.                     newName = (fieldName.length()>1) ?
  1054.                             (((fieldName.charAt(0)+"").toUpperCase()) + fieldName.substring(1))
  1055.                             :
  1056.                             (fieldName.toUpperCase());
  1057.                 }
  1058.                 //System.out.println("DOPO UPPER ["+newName+"]");
  1059.             }
  1060.            
  1061.             if(charSpecial) {
  1062.                 int indexOf = newName.indexOf("_");
  1063.                 while(indexOf>=0){
  1064.                     if((indexOf+1)<newName.length()){
  1065.                         if((indexOf+2)<newName.length()){
  1066.                             newName = newName.substring(0, indexOf) + (newName.charAt(indexOf+1)+"").toUpperCase() + newName.substring(indexOf+2,newName.length());
  1067.                         }else{
  1068.                             newName = newName.substring(0, indexOf) + (newName.charAt(indexOf+1)+"").toUpperCase();
  1069.                         }
  1070.                         indexOf = newName.indexOf("_");
  1071.                     }else{
  1072.                         break;
  1073.                     }
  1074.                 }
  1075.    
  1076.                 indexOf = newName.indexOf("-");
  1077.                 while(indexOf>=0){
  1078.                     if((indexOf+1)<newName.length()){
  1079.                         if((indexOf+2)<newName.length()){
  1080.                             newName = newName.substring(0, indexOf) + (newName.charAt(indexOf+1)+"").toUpperCase() + newName.substring(indexOf+2,newName.length());
  1081.                         }else{
  1082.                             newName = newName.substring(0, indexOf) + (newName.charAt(indexOf+1)+"").toUpperCase();
  1083.                         }
  1084.                         indexOf = newName.indexOf("-");
  1085.                     }else{
  1086.                         break;
  1087.                     }
  1088.                 }
  1089.                 //System.out.println("DOPO CHAR ["+newName+"]");
  1090.             }
  1091.            
  1092.             return newName;
  1093.         }
  1094.         else {
  1095.             return fieldName;
  1096.         }
  1097.            
  1098.     }
  1099.    
  1100.    
  1101.    
  1102.     // CONVERT TYPE
  1103.    
  1104.     private static final String SPECIAL_KEY_CONVERT_TO_ARRAY = "___CONVERT_TO_ARRAY__";
  1105.     private static final String ALREADY_ARRAY_TYPE_ERROR = "already array type";
  1106.    
  1107.     public void convertFieldToArrayByPath(JsonNode oNode, List<String> listPath) throws UtilsException {
  1108.         SortedMap<String> pathToNewName = new SortedMap<String>();
  1109.         if(listPath!=null) {
  1110.             for (String path : listPath) {
  1111.                 pathToNewName.add(path, SPECIAL_KEY_CONVERT_TO_ARRAY);
  1112.             }
  1113.         }
  1114.         renameFieldByPath(oNode, pathToNewName, true);
  1115.     }
  1116.     public void convertFieldToArrayByPath(JsonNode oNode, List<String> listPath, boolean throwNotFound) throws UtilsException {
  1117.         SortedMap<String> pathToNewName = new SortedMap<String>();
  1118.         if(listPath!=null) {
  1119.             for (String path : listPath) {
  1120.                 pathToNewName.add(path, SPECIAL_KEY_CONVERT_TO_ARRAY);
  1121.             }
  1122.         }
  1123.         renameFieldByPath(oNode, pathToNewName, throwNotFound);
  1124.     }
  1125.     public void convertFieldToArrayByPath(JsonNode oNode, List<String> listPath, boolean forceReorder, boolean throwNotFound) throws UtilsException {
  1126.         SortedMap<String> pathToNewName = new SortedMap<String>();
  1127.         if(listPath!=null) {
  1128.             for (String path : listPath) {
  1129.                 pathToNewName.add(path, SPECIAL_KEY_CONVERT_TO_ARRAY);
  1130.             }
  1131.         }
  1132.         renameFieldByPath(oNode, pathToNewName, forceReorder, throwNotFound);
  1133.     }
  1134.     public void convertFieldToArrayByPath(JsonNode oNode, String path) throws UtilsException {
  1135.         renameFieldByPath(oNode, path, SPECIAL_KEY_CONVERT_TO_ARRAY, true);
  1136.     }
  1137.     public void convertFieldToArrayByPath(JsonNode oNode, String path, boolean throwNotFound) throws UtilsException {
  1138.         renameFieldByPath(oNode, path, SPECIAL_KEY_CONVERT_TO_ARRAY, throwNotFound);
  1139.     }
  1140.     public void convertFieldToArrayByPath(JsonNode oNode, String path, boolean forceReorder, boolean throwNotFound) throws UtilsException {
  1141.         renameFieldByPath(oNode, path, SPECIAL_KEY_CONVERT_TO_ARRAY, forceReorder, throwNotFound);
  1142.     }
  1143.  
  1144.    
  1145.     // ORDER ELEMENTS TYPE
  1146.    
  1147.     private static final String SPECIAL_KEY_ORDER_ELEMENTS_PREFIX = "___REORDER__";
  1148.     private static final String SPECIAL_KEY_ORDER_ELEMENTS_SEPARATOR = ",";
  1149.    
  1150.     public void reorderFieldChildrenByPath(JsonNode oNode, String path, String ... child) throws UtilsException {
  1151.         renameFieldByPath(oNode, path, SPECIAL_KEY_ORDER_ELEMENTS_PREFIX+toReorderFieldChildrenByPathSuffix(child), true);
  1152.     }
  1153.     public void reorderFieldChildrenByPath(JsonNode oNode, String path, boolean throwNotFound, String ... child) throws UtilsException {
  1154.         String key = SPECIAL_KEY_ORDER_ELEMENTS_PREFIX+toReorderFieldChildrenByPathSuffix(child);
  1155.         //System.out.println("KEY ["+key+"]");
  1156.         renameFieldByPath(oNode, path, key, throwNotFound);
  1157.     }
  1158.     private String toReorderFieldChildrenByPathSuffix(String ... child) throws UtilsException {
  1159.         if(child==null || child.length<=0) {
  1160.             throw new UtilsException("Children undefined");
  1161.         }
  1162.         StringBuilder sb = new StringBuilder();
  1163.         for (String c : child) {
  1164.             if(sb.length()>0) {
  1165.                 sb.append(SPECIAL_KEY_ORDER_ELEMENTS_SEPARATOR);
  1166.             }
  1167.             if(c.contains(SPECIAL_KEY_ORDER_ELEMENTS_SEPARATOR)) {
  1168.                 throw new UtilsException("Invalid child name ["+c+"] (contains '"+SPECIAL_KEY_ORDER_ELEMENTS_SEPARATOR+"')");
  1169.             }
  1170.             sb.append(c);
  1171.         }
  1172.         return sb.toString();
  1173.     }
  1174.     private List<String> convertReorderFieldChildrenByPathKeyToList(String v) throws UtilsException{
  1175.         String parsV = v;
  1176.         if(parsV.startsWith(SPECIAL_KEY_ORDER_ELEMENTS_PREFIX)) {
  1177.             parsV = parsV.substring(SPECIAL_KEY_ORDER_ELEMENTS_PREFIX.length());
  1178.         }
  1179.         List<String> l = new ArrayList<>();
  1180.         if(parsV.contains(SPECIAL_KEY_ORDER_ELEMENTS_SEPARATOR)) {
  1181.             String [] tmp = parsV.split(SPECIAL_KEY_ORDER_ELEMENTS_SEPARATOR);
  1182.             if(tmp!=null && tmp.length>0) {
  1183.                 for (String c : tmp) {
  1184.                     l.add(c);
  1185.                 }
  1186.             }
  1187.         }
  1188.         else {
  1189.             l.add(parsV);
  1190.         }
  1191.         if(l.isEmpty()) {
  1192.             throw new UtilsException("Children not found");
  1193.         }
  1194.         return l;
  1195.     }
  1196.    
  1197. }

  1198. class _StructureNode {
  1199.    
  1200.     JsonNode parentNode;
  1201.     JsonNode nodeForRename;
  1202.     String parent;
  1203.    
  1204. }