DynamicStringReplace.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;

  21. import java.lang.reflect.Method;
  22. import java.text.SimpleDateFormat;
  23. import java.util.ArrayList;
  24. import java.util.Calendar;
  25. import java.util.Date;
  26. import java.util.Iterator;
  27. import java.util.List;
  28. import java.util.Map;

  29. import org.apache.commons.lang.StringUtils;

  30. /**
  31.  * DynamicStringReplace
  32.  *
  33.  * @author Poli Andrea (apoli@link.it)
  34.  * @author $Author$
  35.  * @version $Rev$, $Date$
  36.  */
  37. public class DynamicStringReplace {

  38.     private static boolean containsKey(Map<?, ?> map, String key) {
  39.         // NOTA: prima volutamente viene cercata la stringa esatta per supportare più entry
  40.         boolean contains = map.containsKey(key) || map.containsKey(key.toLowerCase()) || map.containsKey(key.toUpperCase());
  41.         if(contains) {
  42.             return true;
  43.         }
  44.         else {
  45.             Iterator<?> keys = map.keySet().iterator();
  46.             while (keys.hasNext()) {
  47.                 Object oKey = keys.next();
  48.                 if(oKey!=null && oKey instanceof String) {
  49.                     String keyIterator = (String) oKey;
  50.                     String keyIteratorCaseInsensitive = keyIterator.toLowerCase();
  51.                     String keyCaseInsensitive = key.toLowerCase();
  52.                     if(keyCaseInsensitive.equals( keyIteratorCaseInsensitive )) {
  53.                         return true;
  54.                     }
  55.                 }
  56.             }
  57.         }
  58.         return false;
  59.     }
  60.     private static Object get(Map<?, ?> map, String key) {
  61.         // NOTA: prima volutamente viene cercata la stringa esatta per supportare più entry
  62.         if(map.containsKey(key)) {
  63.             return map.get(key);
  64.         }
  65.         else if(map.containsKey(key.toLowerCase())) {
  66.             return map.get(key.toLowerCase());
  67.         }
  68.         else if(map.containsKey(key.toUpperCase())) {
  69.             return map.get(key.toUpperCase());
  70.         }
  71.         else {
  72.             Iterator<?> keys = map.keySet().iterator();
  73.             while (keys.hasNext()) {
  74.                 Object oKey = keys.next();
  75.                 if(oKey!=null && oKey instanceof String) {
  76.                     String keyIterator = (String) oKey;
  77.                     String keyIteratorCaseInsensitive = keyIterator.toLowerCase();
  78.                     String keyCaseInsensitive = key.toLowerCase();
  79.                     if(keyCaseInsensitive.equals( keyIteratorCaseInsensitive )) {
  80.                         return map.get(oKey);
  81.                     }
  82.                 }
  83.             }
  84.         }
  85.         return null;
  86.     }
  87.    
  88.     public static void validate(String messaggioWithPlaceHolder, boolean startWithDollaro) throws UtilsException{
  89.        
  90.         String start = "{";
  91.         String startOptional = "{";
  92.         if(startWithDollaro) {
  93.             start = "${";
  94.             startOptional = "?{";
  95.         }
  96.         String end = "}";
  97.         int length = start.length()+end.length();

  98.         // Check di esistenza di almeno 1  '{' e '}'
  99.         if(messaggioWithPlaceHolder!=null && messaggioWithPlaceHolder.length()>length){
  100.             int index1 = messaggioWithPlaceHolder.indexOf(start);
  101.             if(index1<0) {
  102.                 index1 = messaggioWithPlaceHolder.indexOf(startOptional);
  103.             }
  104.             int index2 = messaggioWithPlaceHolder.indexOf(end,index1+start.length());
  105.             if(index1<0 || index2<0){
  106.                 return; // non serve il replace
  107.             }
  108.         }
  109.        
  110.         if(messaggioWithPlaceHolder==null) {
  111.             return;
  112.         }
  113.        
  114.         StringBuilder keyword = new StringBuilder();
  115.         //boolean required = true;
  116.         boolean keywordInCorso = false;
  117.         for(int i=0; i<messaggioWithPlaceHolder.length(); i++){
  118.             char ch = messaggioWithPlaceHolder.charAt(i);
  119.             boolean checkPossibleStart = false;
  120.             if(startWithDollaro) {
  121.                 if(ch == '$' || ch == '?') {
  122.                     //if(ch == '?') {
  123.                     //  required=false;
  124.                     //}
  125.                     checkPossibleStart = true;
  126.                     if(i+1 < messaggioWithPlaceHolder.length()) {
  127.                         i++;
  128.                         ch = messaggioWithPlaceHolder.charAt(i);
  129.                     }
  130.                 }
  131.             }
  132.             else {
  133.                 checkPossibleStart = true;
  134.             }
  135.             if(
  136.                     ( (checkPossibleStart && '{' == ch) )
  137.                     ||
  138.                     ( (keywordInCorso && '}' == ch) )
  139.                 ){
  140.                 //char separatorChar = ch;
  141.                 if(keywordInCorso==false){
  142.                     // inizio keyword
  143.                     //keyword.append(separatorChar);
  144.                     keywordInCorso = true; // siamo nel caso di apertura, inizio keyword
  145.                 }
  146.                 else{
  147.                     // fine keyword
  148.                     //keyword.append(separatorChar);
  149.                     String key = keyword.toString();
  150.                     if(key.contains(":")==false){
  151.                         throw new UtilsException("Placeholder [{"+key+"}] resolution failed: wrong format, required {key:value}");
  152.                     }
  153.                     if(key.startsWith(":") || key.endsWith(":") ){
  154.                         throw new UtilsException("Placeholder [{"+key+"}] resolution failed: wrong format, required {key:value}");
  155.                     }
  156.                     String tipo = key.substring(0, key.indexOf(":"));
  157.                     String value = key.substring(key.indexOf(":")+1);
  158.                     if(tipo==null || "".equals(tipo.trim())){
  159.                         throw new UtilsException("Placeholder [{"+key+"}] resolution failed: wrong format, required {key:value}");
  160.                     }
  161.                     if(value==null || "".equals(value.trim())){
  162.                         throw new UtilsException("Placeholder [{"+key+"}] resolution failed: wrong format, required {key:value}");
  163.                     }
  164.                    
  165.                     keyword.delete(0, keyword.length());
  166.                     keywordInCorso=false;
  167.                     checkPossibleStart=false;
  168.                 }
  169.             }else{
  170.                 if(keywordInCorso){
  171.                     // sto scrivendo la keyword
  172.                     keyword.append(ch);
  173.                 }
  174.             }
  175.         }
  176.     }
  177.    
  178.     public static String replace(String messaggioWithPlaceHolder, Map<String, Object> map, boolean startWithDollaro) throws UtilsException{
  179.         return replace(messaggioWithPlaceHolder, map, startWithDollaro, true);
  180.     }
  181.     public static String replace(String messaggioWithPlaceHolder, Map<String, Object> map, boolean startWithDollaro, boolean complexField) throws UtilsException{
  182.        
  183.         validate(messaggioWithPlaceHolder, startWithDollaro);
  184.        
  185.         String start = "{";
  186.         String startOptional = "{";
  187.         if(startWithDollaro) {
  188.             start = "${";
  189.             startOptional = "?{";
  190.         }
  191.         String end = "}";
  192.         int length = start.length()+end.length();
  193.        
  194.         // Check di esistenza di almeno 1  '{' e '}'
  195.         if(messaggioWithPlaceHolder!=null && messaggioWithPlaceHolder.length()>length){
  196.             int index1 = messaggioWithPlaceHolder.indexOf(start);
  197.             if(index1<0) {
  198.                 index1 = messaggioWithPlaceHolder.indexOf(startOptional);
  199.             }
  200.             int index2 = messaggioWithPlaceHolder.indexOf(end,index1+start.length());
  201.             if(index1<0 || index2<0){
  202.                 return messaggioWithPlaceHolder; // non serve il replace
  203.             }
  204.         }
  205.        
  206.         if(messaggioWithPlaceHolder==null) {
  207.             return messaggioWithPlaceHolder;
  208.         }
  209.        
  210.         StringBuilder bf = new StringBuilder();
  211.         StringBuilder keyword = new StringBuilder();
  212.         boolean required = true;
  213.         int countOptionalNotFoundBehaviour = 0;
  214.         boolean keywordInCorso = false;
  215.         for(int i=0; i<messaggioWithPlaceHolder.length(); i++){
  216.             char ch = messaggioWithPlaceHolder.charAt(i);
  217.             Character chDollaro = null;
  218.             boolean checkPossibleStart = false;
  219.             if(startWithDollaro) {
  220.                 if(ch == '$' || ch == '?') {
  221.                     // verifico che il prossimo carattere non sia un ulteriore carattere speciale
  222.                     boolean analize = true;
  223.                     if(i+1 < messaggioWithPlaceHolder.length()) {
  224.                         char chNext = messaggioWithPlaceHolder.charAt(i+1);
  225.                         if(chNext == '$' || chNext == '?') {
  226.                             analize = false;
  227.                         }
  228.                     }
  229.                     if(analize) {
  230.                         if(ch == '?') {
  231.                             required=false;
  232.                         }
  233.                         checkPossibleStart = true;
  234.                         if(i+1 < messaggioWithPlaceHolder.length()) {
  235.                             i++;
  236.                             chDollaro = ch;
  237.                             ch = messaggioWithPlaceHolder.charAt(i);
  238.                         }
  239.                     }
  240.                 }
  241.             }
  242.             else {
  243.                 checkPossibleStart = true;
  244.             }
  245.             if(
  246.                     ( (checkPossibleStart && '{' == ch) )
  247.                     ||
  248.                     ( (keywordInCorso && '}' == ch) )
  249.                 ){
  250.                 //char separatorChar = ch;
  251.                 if(keywordInCorso==false){
  252.                     // inizio keyword
  253.                     //keyword.append(separatorChar);
  254.                     keywordInCorso = true;  // siamo nel caso di apertura, inizio keyword
  255.                 }
  256.                 else{
  257.                     // fine keyword
  258.                     //keyword.append(separatorChar);
  259.                     String key = keyword.toString();
  260.                     if(key.contains(":")==false){
  261.                         throw new UtilsException("Placeholder [{"+key+"}] resolution failed: wrong format, required {key:value}");
  262.                     }
  263.                     if(key.startsWith(":") || key.endsWith(":") ){
  264.                         throw new UtilsException("Placeholder [{"+key+"}] resolution failed: wrong format, required {key:value}");
  265.                     }
  266.                     String tipo = key.substring(0, key.indexOf(":"));
  267.                     String value = key.substring(key.indexOf(":")+1);
  268.                     //if(map.containsKey(tipo)==false){
  269.                     String valoreRimpiazzato = null;
  270.                     if(containsKey(map, tipo)==false) {
  271.                         if(required) {
  272.                             throw new UtilsException("Placeholder [{"+key+"}] resolution failed: object with key '"+tipo+"' not found");
  273.                         }
  274.                         else {
  275.                             countOptionalNotFoundBehaviour++;
  276.                             valoreRimpiazzato = "";
  277.                         }
  278.                     }
  279.                     else {
  280.                         //Object object = map.get(tipo);
  281.                         Object object = get(map, tipo);
  282.                         if(object==null){
  283.                             if(required) {
  284.                                 throw new UtilsException("Placeholder [{"+key+"}] resolution failed: object with key '"+tipo+"' is null");
  285.                             }
  286.                             else {
  287.                                 countOptionalNotFoundBehaviour++;
  288.                                 valoreRimpiazzato = "";
  289.                             }
  290.                         }
  291.                         else {
  292.                             valoreRimpiazzato = getValue(key, tipo, value, object, complexField, required);
  293.                             if(valoreRimpiazzato==null){
  294.                                 if(required) {
  295.                                     throw new UtilsException("Placeholder [{"+key+"}] resolution failed");
  296.                                 }
  297.                                 else {
  298.                                     countOptionalNotFoundBehaviour++;
  299.                                     valoreRimpiazzato = "";
  300.                                 }
  301.                             }
  302.                         }
  303.                     }
  304.                     bf.append(valoreRimpiazzato);
  305.                     keyword.delete(0, keyword.length());
  306.                     keywordInCorso=false;
  307.                     checkPossibleStart=false;
  308.                 }
  309.             }else{
  310.                 if(keywordInCorso){
  311.                     // sto scrivendo la keyword
  312.                     keyword.append(ch);
  313.                 }else{
  314.                     if(chDollaro!=null) {
  315.                         bf.append(chDollaro);
  316.                     }
  317.                     bf.append(ch);
  318.                 }
  319.             }
  320.         }
  321.         String result = bf.toString();
  322.         if(result==null) {
  323.             return null;
  324.         }
  325.         if(countOptionalNotFoundBehaviour > 0 && StringUtils.isEmpty(result)) {
  326.             return null;
  327.         }
  328.         return result;
  329.     }
  330.    
  331.     private static String getValue(String key, String tipo, String value, Object object, boolean complexField, boolean required) throws UtilsException{
  332.        
  333.         // Se l'oggetto nella mappa è una data utilizzo il valore come format
  334.         Date d = null;
  335.         if(object instanceof Date){
  336.             d = (Date) object;
  337.         }
  338.         else if(object instanceof java.sql.Date){
  339.             d = (java.sql.Date) object;
  340.         }
  341.         else if(object instanceof Calendar){
  342.             Calendar c = (Calendar) object;
  343.             d = c.getTime();
  344.         }
  345.         if(d!=null){
  346.             SimpleDateFormat sdf = new SimpleDateFormat(value);
  347.             return sdf.format(d);
  348.         }
  349.        
  350.         // Se l'oggetto è una mappa provo ad estrarre l'oggetto indicato.
  351.         if(object instanceof List<?> || object instanceof Map<?,?> || object instanceof Object[]){
  352.                
  353.             String position = value;
  354.             String newValue = value;
  355.             boolean existsUlterioreParametro = false;
  356.             boolean valueContainsPoint = value.contains(".");
  357.             if(valueContainsPoint && complexField){
  358.                
  359.                 // Devo convertire i punti dentro le quadre che potrebbero far parte delle chiavi
  360.                 StringBuilder sbFormat = new StringBuilder();
  361.                 boolean start = false;
  362.                 int doppieVirgoletteIndex = -1;
  363.                 boolean startDoppieVirgolette = false;
  364.                 for (int i = 0; i < value.length(); i++) {
  365.                     char c = value.charAt(i);
  366.                     if((!start) && (c == '[')) {
  367.                         start = true;
  368.                         if((i+1 < value.length())) {
  369.                             char cc = value.charAt(i+1);
  370.                             if((cc == '"')) {
  371.                                 startDoppieVirgolette=true;
  372.                                 doppieVirgoletteIndex=i+1;
  373.                             }
  374.                         }
  375.                     }
  376.                     if((start) && (c == ']')) {
  377.                         if(!startDoppieVirgolette) {
  378.                             start = false;
  379.                         }
  380.                     }
  381.                     if((startDoppieVirgolette) && (c == '"') && doppieVirgoletteIndex!=i) {
  382.                         if((i+1 < value.length())) {
  383.                             char cc = value.charAt(i+1);
  384.                             if((cc == ']')) {
  385.                                 startDoppieVirgolette = false;
  386.                                 doppieVirgoletteIndex=i;
  387.                             }
  388.                         }
  389.                     }
  390.                     if(start && c == '.') {
  391.                         sbFormat.append('_');
  392.                     }
  393.                     else {
  394.                         sbFormat.append(c);
  395.                     }
  396.                 }
  397.                 String internalNewValue = sbFormat.toString();
  398.                
  399.                 // Devo convertire i punti dentro le tonde che potrebbero far parte delle chiavi
  400.                 sbFormat = new StringBuilder();
  401.                 start = false;
  402.                 doppieVirgoletteIndex = -1;
  403.                 startDoppieVirgolette = false;
  404.                 for (int i = 0; i < internalNewValue.length(); i++) {
  405.                     char c = internalNewValue.charAt(i);
  406.                     if((!start) && (c == '(')) {
  407.                         start = true;
  408.                         if((i+1 < internalNewValue.length())) {
  409.                             char cc = internalNewValue.charAt(i+1);
  410.                             if((cc == '"')) {
  411.                                 startDoppieVirgolette=true;
  412.                                 doppieVirgoletteIndex=i+1;
  413.                             }
  414.                         }
  415.                     }
  416.                     if((start) && (c == ')')) {
  417.                         if(!startDoppieVirgolette) {
  418.                             start = false;
  419.                         }
  420.                     }
  421.                     if((startDoppieVirgolette) && (c == '"') && doppieVirgoletteIndex!=i) {
  422.                         if((i+1 < internalNewValue.length())) {
  423.                             char cc = internalNewValue.charAt(i+1);
  424.                             if((cc == ')')) {
  425.                                 startDoppieVirgolette = false;
  426.                                 doppieVirgoletteIndex=i;
  427.                             }
  428.                         }
  429.                     }
  430.                     if(start && c == '.') {
  431.                         sbFormat.append('_');
  432.                     }
  433.                     else {
  434.                         sbFormat.append(c);
  435.                     }
  436.                 }
  437.                 internalNewValue = sbFormat.toString();
  438.                
  439.                 //System.out.println("OLD ["+value+"]");
  440.                 //System.out.println("NEW ["+internalNewValue+"]");
  441.                
  442.                 int indexOfPoint = internalNewValue.indexOf(".");
  443.                 if(indexOfPoint>0) {
  444.                     position = value.substring(0, indexOfPoint);
  445.                     try{
  446.                         newValue = value.substring(indexOfPoint+1);
  447.                     }catch(Throwable e){
  448.                         // ignore
  449.                     }
  450.                 }
  451.                 else {
  452.                     position = value;
  453.                     newValue = null;
  454.                 }
  455.                 if(position!=null) {
  456.                     if( (position.startsWith("[") || position.startsWith("("))
  457.                             &&
  458.                             position.length()>1) {
  459.                         position = position.substring(1);
  460.                     }
  461.                     if( (position.endsWith("]") || position.endsWith(")"))
  462.                             &&
  463.                             position.length()>1) {
  464.                         position = position.substring(0,(position.length()-1));
  465.                     }
  466.                     //System.out.println("position ["+position+"]");
  467.                 }
  468.                 if(newValue!=null && StringUtils.isNotEmpty(newValue.trim())) {
  469.                     existsUlterioreParametro=true;
  470.                 }
  471.             }
  472.            
  473.            
  474.            
  475.             Object oInternal = null;
  476.            
  477.             // Provo ad utilizzare  il valore come indice
  478.             if(object instanceof List<?> || object instanceof Object[]){
  479.                 int index = -1;
  480.                 try{
  481.                     index = Integer.parseInt(position);
  482.                 }catch(Exception e){
  483.                     throw new UtilsException("Placeholder [{"+key+"}] resolution failed: object ["+object.getClass().getName()+"] with wrong position '"+position+"' (not integer?): "+e.getMessage());
  484.                 }
  485.                 if(object instanceof List<?>){
  486.                     List<?> list = (List<?>) object;
  487.                     if(list.size()<=index){
  488.                         if(required) {
  489.                             throw new UtilsException("Placeholder [{"+key+"}] resolution failed: object ["+object.getClass().getName()+"] with wrong position '"+index+"' (list size:"+list.size()+")");
  490.                         }
  491.                     }
  492.                     else {
  493.                         oInternal = list.get(index);
  494.                     }
  495.                 }
  496.                 else if(object instanceof Object[]){
  497.                     Object[] arrayObj = (Object[]) object;
  498.                     if(arrayObj.length<=index){
  499.                         if(required) {
  500.                             throw new UtilsException("Placeholder [{"+key+"}] resolution failed: object ["+object.getClass().getName()+"] with wrong position '"+index+"' (array size:"+arrayObj.length+")");
  501.                         }
  502.                     }
  503.                     else {
  504.                         oInternal = arrayObj[index];
  505.                     }
  506.                 }
  507.             }
  508.             else if(object instanceof Map<?,?>){
  509.                 Map<?,?> map = (Map<?,?>) object;
  510.                 //if(map.containsKey(position)==false){
  511.                 if(containsKey(map, position)==false) {
  512.                     if(required) {
  513.                         throw new UtilsException("Placeholder [{"+key+"}] resolution failed: object ["+object.getClass().getName()+"] '"+position+"' not exists in map");
  514.                     }
  515.                 }
  516.                 else {
  517.                     //oInternal = map.get(position);
  518.                     oInternal = get(map, position);
  519.                 }
  520.             }  
  521.            
  522.             //if(newValue.contains(".") || (newValue.contains("[") && newValue.contains("]"))){
  523.             if(existsUlterioreParametro) { // se ho definito un parametro dopo la chiave della mappa devo usare il metodo 'readValueInObject'
  524.                 if(oInternal==null){
  525.                     if(required) {
  526.                         throw new UtilsException("Placeholder [{"+key+"}] resolution failed: object ["+object.getClass().getName()+"]["+position+"] return null object");
  527.                     }
  528.                     else {
  529.                         return null;
  530.                     }
  531.                 }
  532.                 else{
  533.                     return readValueInObject(key, oInternal, newValue, complexField, required);
  534.                 }
  535.             }
  536.             else{
  537.                 // finale
  538.                 if(oInternal!=null){
  539.                     String finalValue = null;
  540.                     if(oInternal instanceof Date){
  541.                         SimpleDateFormat dateformat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS");
  542.                         finalValue = dateformat.format((Date)oInternal);
  543.                     }
  544.                     else if(oInternal instanceof byte[]){
  545. //                      // 1024 = 1K
  546. //                       // Visualizzo al massimo 1K
  547. //                       int max = 1 * 1024;
  548. //                       return org.openspcoop2.utils.Utilities.convertToPrintableText((byte[])ret, max);
  549.                         throw new UtilsException("Placeholder [{"+key+"}] resolution failed: object ["+object.getClass().getName()+"]["+position+"] return object with type ["+oInternal.getClass().getName()+"]");
  550.                     }
  551.                     else{
  552.                         finalValue = oInternal.toString();
  553.                     }
  554.                     return finalValue;
  555.                 }
  556.                 else{
  557.                     if(required) {
  558.                         throw new UtilsException("Placeholder [{"+key+"}] resolution failed: object ["+object.getClass().getName()+"]["+position+"] return null object");
  559.                     }
  560.                     else {
  561.                         return null;
  562.                     }
  563.                 }
  564.             }  
  565.            
  566.         }
  567.         else{
  568.            
  569.             // Altrimenti provo a navigarlo
  570.             return readValueInObject(key, object, value, complexField, required);
  571.        
  572.         }
  573.        
  574.     }
  575.     private static String readValueInObject(String key, Object o,String name, boolean complexField, boolean required) throws UtilsException{
  576.         //System.out.println("Invocato con oggetto["+o.getClass().getName()+"] nome["+name+"]");
  577.         String fieldName = name;
  578.         //String position = null;
  579.         List<String> arrayMapPosition = new ArrayList<>();
  580.         boolean nameContainsPoint = name.contains(".");
  581.         if(nameContainsPoint && complexField){
  582.            
  583.             // Devo convertire i punti dentro le quadre che potrebbero far parte delle chiavi
  584.             StringBuilder sbFormat = new StringBuilder();
  585.             boolean start = false;
  586.             int doppieVirgoletteIndex = -1;
  587.             boolean startDoppieVirgolette = false;
  588.             for (int i = 0; i < name.length(); i++) {
  589.                 char c = name.charAt(i);
  590.                 if((!start) && (c == '[')) {
  591.                     start = true;
  592.                     if((i+1 < name.length())) {
  593.                         char cc = name.charAt(i+1);
  594.                         if((cc == '"')) {
  595.                             startDoppieVirgolette=true;
  596.                             doppieVirgoletteIndex=i+1;
  597.                         }
  598.                     }
  599.                 }
  600.                 if((start) && (c == ']')) {
  601.                     if(!startDoppieVirgolette) {
  602.                         start = false;
  603.                     }
  604.                 }
  605.                 if((startDoppieVirgolette) && (c == '"') && doppieVirgoletteIndex!=i) {
  606.                     if((i+1 < name.length())) {
  607.                         char cc = name.charAt(i+1);
  608.                         if((cc == ']')) {
  609.                             startDoppieVirgolette = false;
  610.                             doppieVirgoletteIndex=i;
  611.                         }
  612.                     }
  613.                 }
  614.                 if(start && c == '.') {
  615.                     sbFormat.append('_');
  616.                 }
  617.                 else {
  618.                     sbFormat.append(c);
  619.                 }
  620.             }
  621.             String newName = sbFormat.toString();
  622.            
  623.             // Devo convertire i punti dentro le tonde che potrebbero far parte delle chiavi
  624.             sbFormat = new StringBuilder();
  625.             start = false;
  626.             doppieVirgoletteIndex = -1;
  627.             startDoppieVirgolette = false;
  628.             for (int i = 0; i < newName.length(); i++) {
  629.                 char c = newName.charAt(i);
  630.                 if((!start) && (c == '(')) {
  631.                     start = true;
  632.                     if((i+1 < newName.length())) {
  633.                         char cc = newName.charAt(i+1);
  634.                         if((cc == '"')) {
  635.                             startDoppieVirgolette=true;
  636.                             doppieVirgoletteIndex=i+1;
  637.                         }
  638.                     }
  639.                 }
  640.                 if((start) && (c == ')')) {
  641.                     if(!startDoppieVirgolette) {
  642.                         start = false;
  643.                     }
  644.                 }
  645.                 if((startDoppieVirgolette) && (c == '"') && doppieVirgoletteIndex!=i) {
  646.                     if((i+1 < newName.length())) {
  647.                         char cc = newName.charAt(i+1);
  648.                         if((cc == ')')) {
  649.                             startDoppieVirgolette = false;
  650.                             doppieVirgoletteIndex=i;
  651.                         }
  652.                     }
  653.                 }
  654.                 if(start && c == '.') {
  655.                     sbFormat.append('_');
  656.                 }
  657.                 else {
  658.                     sbFormat.append(c);
  659.                 }
  660.             }
  661.             newName = sbFormat.toString();
  662.            
  663.             //System.out.println("OLD ["+name+"]");
  664.             //System.out.println("NEW ["+newName+"]");
  665.             nameContainsPoint = newName.contains(".");
  666.             if(nameContainsPoint){
  667.                 fieldName = name.substring(0, newName.indexOf("."));
  668.             }
  669.             //System.out.println("fieldName ["+fieldName+"]");
  670.         }
  671.         String methodName = new String(fieldName);
  672.         //System.out.println("fieldName ["+fieldName+"]");
  673.         if(fieldName.endsWith("]") && fieldName.contains("[")){
  674.             try{
  675.                 // fix [][]
  676.                 //position = fieldName.substring(fieldName.indexOf("[")+1,fieldName.length()-1);
  677.                 String tmp = new String(fieldName);
  678.                 //System.out.println("DEBUG ["+tmp+"]");
  679.                 while(tmp.endsWith("]") && tmp.contains("[")){  
  680.                     int firstOpen = tmp.indexOf("[")+1;
  681.                     int lastOpen = tmp.indexOf("]", firstOpen);
  682.                     String position = tmp.substring(firstOpen, lastOpen);
  683.                     arrayMapPosition.add(position);
  684.                     //System.out.println("DEBUG ADD ["+position+"]");
  685.                     if(tmp.length()>(lastOpen+1)) {
  686.                         tmp = tmp.substring(lastOpen+1,tmp.length());
  687.                     }
  688.                     else {
  689.                         tmp="";
  690.                     }
  691.                     //System.out.println("DEBUG NUOVO VALORE ["+tmp+"]");
  692.                 }
  693.                 methodName = fieldName.substring(0, fieldName.indexOf("["));
  694.             }catch(Exception e){
  695.                 throw new UtilsException("Placeholder [{"+key+"}] resolution failed: position error in field ["+fieldName+"]: "+e.getMessage(),e);
  696.             }
  697.         }
  698.         //System.out.println("NAME ["+fieldName+"] position["+position+"]");
  699.         String getMethod = "get"+((methodName.charAt(0)+"").toUpperCase());
  700.         if(methodName.length()>1){
  701.             getMethod = getMethod + methodName.substring(1);
  702.         }
  703.         //System.out.println("getMethod ["+getMethod+"]");
  704.         List<String> parametersObject = null;
  705.         List<Class<?>> parametersClass = null;
  706.         try{
  707.             if(getMethod.contains("(") && getMethod.endsWith(")")) { // supporta 1 solo parametro stringa
  708.                 int startParams = getMethod.indexOf("(");
  709.                
  710.                 String sP = getMethod.substring(startParams, getMethod.length());
  711.                 if(sP.length()>2) {
  712.                     sP = sP.substring(1, sP.length()-1);
  713.                 }
  714.                 //System.out.println("METODO getMethod["+getMethod+"] PARAMS["+sP+"] ");
  715.                 if(sP.contains(",")) {
  716.                     parametersObject = new ArrayList<>();
  717.                     parametersClass = new ArrayList<Class<?>>();
  718.                     StringBuilder sb = new StringBuilder();
  719.                     for (int i = 0; i < sP.length(); i++) {
  720.                         String sAt = sP.charAt(i)+"";
  721.                         if(sAt.equals(",")) {
  722.                             String paramString = sb.toString();
  723.                             //System.out.println("paramString '"+paramString+"'");
  724.                             if(paramString!=null && paramString.length()>=2 && paramString.startsWith("\"") && paramString.endsWith("\"")) {
  725.                                 if(paramString.length()==2) {
  726.                                     paramString = ""; // stringa vuota
  727.                                 }
  728.                                 else {
  729.                                     paramString = paramString.substring(1);
  730.                                     paramString = paramString.substring(0,paramString.length()-1);
  731.                                 }
  732.                                 //System.out.println("paramString DOPO '"+paramString+"'");
  733.                             }
  734.                             parametersObject.add(paramString); // gli spazi possono essere voluti (non fare trim)
  735.                             parametersClass.add(String.class);
  736.                             sb = new StringBuilder();
  737.                         }
  738.                         else {
  739.                             sb.append(sAt);
  740.                         }
  741.                     }
  742.                     parametersObject.add(sb.toString()); // gli spazi possono essere voluti (non fare trim)
  743.                     parametersClass.add(String.class);
  744.                 }
  745.                 else {
  746.                     parametersObject = new ArrayList<>();
  747.                     parametersClass = new ArrayList<Class<?>>();
  748.                     String paramString = sP;
  749.                     //System.out.println("paramString '"+paramString+"'");
  750.                     if(paramString!=null && paramString.length()>=2 && paramString.startsWith("\"") && paramString.endsWith("\"")) {
  751.                         if(paramString.length()==2) {
  752.                             paramString = ""; // stringa vuota
  753.                         }
  754.                         else {
  755.                             paramString = paramString.substring(1);
  756.                             paramString = paramString.substring(0,paramString.length()-1);
  757.                         }
  758.                         //System.out.println("paramString DOPO '"+paramString+"'");
  759.                     }
  760.                     parametersObject.add(paramString); // gli spazi possono essere voluti (non fare trim)
  761.                     parametersClass.add(String.class);
  762.                 }
  763.                 getMethod = getMethod.substring(0, startParams);
  764.             }
  765.         }catch(Throwable e){
  766.             throw new UtilsException("Placeholder [{"+key+"}] resolution failed: method ["+o.getClass().getName()+"."+getMethod+"()] read parameter error; "+e.getMessage(),e);
  767.         }
  768.         Method m = null;
  769.         boolean withoutParams = false;
  770.         try{
  771.             if(parametersClass!=null && !parametersClass.isEmpty()) {
  772.                 m = o.getClass().getMethod(getMethod, parametersClass.toArray(new Class[1]));
  773.             }
  774.             else {
  775.                 withoutParams = true;
  776.                 m = o.getClass().getMethod(getMethod);
  777.             }
  778.         }catch(Throwable e){
  779.            
  780.             UtilsException utilsException = new UtilsException("Placeholder [{"+key+"}] resolution failed: method ["+o.getClass().getName()+"."+getMethod+"()] not found; "+e.getMessage(),e);
  781.            
  782.             // Fix per metodi boolean 'is'
  783.             if(e instanceof java.lang.NoSuchMethodException && withoutParams) {
  784.                 try{
  785.                     String isMethod = getMethod.replaceFirst("get", "is");
  786.                     m = o.getClass().getMethod(isMethod);
  787.                     if(m!=null) {
  788.                         utilsException = null;
  789.                     }
  790.                 }catch(Throwable eIgnore){
  791.                     // rilancio eccezione originale
  792.                 }
  793.             }
  794.            
  795.             if(utilsException!=null && e instanceof java.lang.NoSuchMethodException && !withoutParams) {
  796.                 // Fix per metodi boolean senza 'get' o 'is' che contengono parametri
  797.                 try{
  798.                     String originalMethod = methodName;
  799.                     if(originalMethod.contains("(") && originalMethod.endsWith(")")) { // supporta 1 solo parametro stringa
  800.                         int startParams = originalMethod.indexOf("(");
  801.                         originalMethod = originalMethod.substring(0, startParams);
  802.                     }
  803.                    
  804.                     if(parametersClass!=null && !parametersClass.isEmpty()) {
  805.                         m = o.getClass().getMethod(originalMethod, parametersClass.toArray(new Class[1]));
  806.                     }
  807.                     // non si dovrebbe entrare in questo caso essendoci l'if sopra con !withoutParams
  808. //                  else {
  809. //                      m = o.getClass().getMethod(originalMethod);
  810. //                  }
  811.                     if(m!=null) {
  812.                         utilsException = null;
  813.                     }
  814.                 }catch(Throwable eIgnore){
  815.                     // rilancio eccezione originale
  816.                 }
  817.             }
  818.            
  819.             if(utilsException!=null) {
  820.                 throw utilsException;
  821.             }
  822.         }
  823.         String debugParameters = "";
  824.         Object ret = null;
  825.         try{
  826.             if(parametersObject!=null && !parametersObject.isEmpty()) {
  827.                 StringBuilder sb = new StringBuilder();
  828.                 for (String par : parametersObject) {
  829.                     if(sb.length()>0) {
  830.                         sb.append(",");
  831.                     }
  832.                     sb.append(par);
  833.                 }
  834.                 debugParameters=sb.toString();
  835.                 ret = m.invoke(o, parametersObject.toArray(new Object[1]));
  836.             }
  837.             else {
  838.                 ret = m.invoke(o);
  839.             }
  840.         }catch(Throwable e){
  841.             Throwable tInternal = Utilities.getInnerNotEmptyMessageException(e);
  842.             String msgErrore = tInternal!=null ? tInternal.getMessage() : e.getMessage();
  843.             throw new UtilsException("Placeholder [{"+key+"}] resolution failed: invocation method ["+o.getClass().getName()+"."+getMethod+"("+debugParameters+")] failed; "+msgErrore,e);
  844.         }
  845.        
  846.         if(ret!=null){
  847.             if(ret instanceof List<?> || ret instanceof Map<?,?> || ret instanceof Object[]){
  848.                 if(arrayMapPosition==null || arrayMapPosition.isEmpty()){
  849.                     throw new UtilsException("Placeholder [{"+key+"}] resolution failed: method ["+o.getClass().getName()+"."+getMethod+"("+debugParameters+")] return "+ret.getClass().getName()+" object without position");
  850.                 }
  851.                 while(!arrayMapPosition.isEmpty()) {
  852.                     String position = arrayMapPosition.remove(0);
  853.                     //System.out.println("ARRAY ["+ret.getClass().getName()+"]");
  854.                     if(ret instanceof List<?> || ret instanceof Object[]){
  855.                         int index = -1;
  856.                         try{
  857.                             index = Integer.parseInt(position);
  858.                         }catch(Exception e){
  859.                             throw new UtilsException("Placeholder [{"+key+"}] resolution failed: method ["+o.getClass().getName()+"."+getMethod+"("+debugParameters+")] return "+ret.getClass().getName()+" object, wrong position value (not integer?): "+e.getMessage());
  860.                         }
  861.                         if(ret instanceof List<?>){
  862.                             List<?> list = (List<?>) ret;
  863.                             if(list.size()<=index){
  864.                                 if(required) {
  865.                                     throw new UtilsException("Placeholder [{"+key+"}] resolution failed: method ["+o.getClass().getName()+"."+getMethod+"("+debugParameters+")] return "+ret.getClass().getName()+" object, wrong position '"+index+"' (list size:"+list.size()+")");
  866.                                 }
  867.                                 else {
  868.                                     ret = null;
  869.                                 }
  870.                             }
  871.                             else {
  872.                                 ret = list.get(index);
  873.                             }
  874.                         }
  875.                         else if(ret instanceof Object[]){
  876.                             Object[] arrayObj = (Object[]) ret;
  877.                             if(arrayObj.length<=index){
  878.                                 if(required) {
  879.                                     throw new UtilsException("Placeholder [{"+key+"}] resolution failed: method ["+o.getClass().getName()+"."+getMethod+"("+debugParameters+")] return "+ret.getClass().getName()+" object, wrong position '"+index+"' (array size:"+arrayObj.length+")");
  880.                                 }
  881.                                 else {
  882.                                     ret = null;
  883.                                 }
  884.                             }
  885.                             else {
  886.                                 ret = arrayObj[index];
  887.                             }
  888.                         }
  889.                     }
  890.                     else if(ret instanceof Map<?,?>){
  891.                         Map<?,?> map = (Map<?,?>) ret;
  892.                         //if(map.containsKey(position)==false){
  893.                         if(containsKey(map, position)==false) {
  894.                             if(required) {
  895.                                 throw new UtilsException("Placeholder [{"+key+"}] resolution failed: method ["+o.getClass().getName()+"."+getMethod+"("+debugParameters+")] return "+ret.getClass().getName()+" object, '"+position+"' not exists in map");
  896.                             }
  897.                             else {
  898.                                 ret = null;
  899.                             }
  900.                         }
  901.                         else {
  902.                             //ret = map.get(position);
  903.                             ret = get(map, position);
  904.                         }
  905.                     }      
  906.                 }
  907.             }
  908.         }
  909.         if(nameContainsPoint && complexField){
  910.             if(ret==null){
  911.                 if(required) {
  912.                     throw new UtilsException("Placeholder [{"+key+"}] resolution failed: method ["+o.getClass().getName()+"."+getMethod+"("+debugParameters+")] return null object");
  913.                 }
  914.                 else {
  915.                     return null;
  916.                 }
  917.             }
  918.             else{
  919.                 return readValueInObject(key, ret, name.substring((fieldName+".").length(), name.length()), complexField, required);
  920.             }
  921.         }
  922.         else{
  923.             // finale
  924.             if(ret!=null){
  925.                 String finalValue = null;
  926.                 if(ret instanceof Date){
  927.                     SimpleDateFormat dateformat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS");
  928.                     finalValue = dateformat.format((Date)ret);
  929.                 }
  930.                 else if(ret instanceof byte[]){
  931. //                  // 1024 = 1K
  932. //                   // Visualizzo al massimo 1K
  933. //                   int max = 1 * 1024;
  934. //                   return org.openspcoop2.utils.Utilities.convertToPrintableText((byte[])ret, max);
  935.                     throw new UtilsException("Placeholder [{"+key+"}] resolution failed: method ["+o.getClass().getName()+"."+getMethod+"("+debugParameters+")] return object with type ["+ret.getClass().getName()+"]");
  936.                 }
  937.                 else{
  938.                     finalValue = ret.toString();
  939.                 }
  940.                 return finalValue;
  941.             }
  942.             else{
  943.                 if(required) {
  944.                     throw new UtilsException("Placeholder [{"+key+"}] resolution failed: method ["+o.getClass().getName()+"."+getMethod+"("+debugParameters+")] return null object");
  945.                 }
  946.                 else {
  947.                     return null;
  948.                 }
  949.             }
  950.         }
  951.     }
  952. }