ValidationEngine.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.web.lib.mvc.properties.utils;

  21. import java.util.List;

  22. import org.apache.commons.lang.StringUtils;
  23. import org.openspcoop2.core.mvc.properties.Collection;
  24. import org.openspcoop2.core.mvc.properties.Condition;
  25. import org.openspcoop2.core.mvc.properties.Conditions;
  26. import org.openspcoop2.core.mvc.properties.Config;
  27. import org.openspcoop2.core.mvc.properties.Defined;
  28. import org.openspcoop2.core.mvc.properties.Equals;
  29. import org.openspcoop2.core.mvc.properties.Item;
  30. import org.openspcoop2.core.mvc.properties.Property;
  31. import org.openspcoop2.core.mvc.properties.Section;
  32. import org.openspcoop2.core.mvc.properties.Selected;
  33. import org.openspcoop2.core.mvc.properties.Subsection;
  34. import org.openspcoop2.web.lib.mvc.properties.beans.BaseItemBean;
  35. import org.openspcoop2.web.lib.mvc.properties.beans.ConfigBean;
  36. import org.openspcoop2.web.lib.mvc.properties.beans.ItemBean;
  37. import org.openspcoop2.web.lib.mvc.properties.beans.SectionBean;
  38. import org.openspcoop2.web.lib.mvc.properties.beans.SubsectionBean;
  39. import org.openspcoop2.web.lib.mvc.properties.exception.ValidationException;
  40. import org.openspcoop2.core.mvc.properties.constants.ItemType;
  41. import org.openspcoop2.core.mvc.properties.provider.ExternalResources;
  42. import org.openspcoop2.core.mvc.properties.provider.IProvider;
  43. import org.openspcoop2.core.mvc.properties.provider.ProviderException;
  44. import org.openspcoop2.utils.resources.ClassLoaderUtilities;

  45. /****
  46.  *
  47.  * ValidationEngine validatore delle configurazioni
  48.  *
  49.  * @author Pintori Giuliano (pintori@link.it)
  50.  * @author $Author$
  51.  * @version $Rev$, $Date$
  52.  *
  53.  */
  54. public class ValidationEngine {
  55.    
  56.    

  57.     public static boolean validateConfig(Config config, ExternalResources externalResources)  throws ValidationException{
  58.        
  59.         // controllo l'univocita' delle chiavi e le conservo per riutilizzarle per verificare
  60.         //che gli elementi riferiti nelle conditions esistano.
  61.        
  62.         ConfigBean metadata = getMetadata(config);
  63.        
  64.         List<Section> sectionList = config.getSectionList();
  65.         try {
  66.             for (int i= 0; i < sectionList.size() ; i++) {
  67.                 Section section = sectionList.get(i);
  68.                 validateSection(section,metadata, externalResources);
  69.             }
  70.        
  71.             // controllo che tutti gli item che vanno a finire dentro una unica property abbiano lo stesso separatore
  72.             for (String nomeProperty : metadata.getMapPropertyItem().keySet()) {
  73.                 String separatore = null;
  74.                 List<BaseItemBean<?>> list = metadata.getMapPropertyItem().get(nomeProperty);
  75.                 if(list.size() > 1) {
  76.                     for (BaseItemBean<?> itemBean : list) {
  77.                         if(itemBean.getSaveProperty()!= null && itemBean.getSaveProperty().isAppend()) {
  78.                             if(separatore == null) {
  79.                                 separatore = itemBean.getSaveProperty().getAppendSeparator();
  80.                             } else {
  81.                                 if(!separatore.equals(itemBean.getSaveProperty().getAppendSeparator()))
  82.                                     throw new ValidationException("I separatori di append per la property ["+nomeProperty+"] devono essere tutti uguali.");
  83.                             }
  84.                         }
  85.                     }
  86.                 }
  87.             }
  88.        
  89.         }catch(ValidationException e) {
  90.             throw new ValidationException("Errore durante la validazione della configurazione ["+config.getId()+"]: "+ e.getMessage(),e);
  91.         }
  92.        
  93.         return true;
  94.     }

  95.     private static void validateSection(Section section,ConfigBean metadata, ExternalResources externalResources) throws ValidationException{
  96.         try {
  97.             validaConditions(section.getConditions(),metadata);
  98.    
  99.             if(section.getItemList() != null) {
  100.                 for (Item item : section.getItemList()) {
  101.                     validaItem(item,metadata, externalResources);
  102.                 }
  103.             }
  104.            
  105.             if(section.getSubsectionList() != null) {
  106.                 for (int i= 0; i < section.getSubsectionList().size() ; i++) {
  107.                     Subsection subSection  = section.getSubsectionList().get(i);
  108.                     validaSubsection(subSection,metadata, externalResources);
  109.                 }
  110.             }
  111.         }catch(ValidationException e) {
  112.             throw new ValidationException("Section ["+section.getLabel()+"] -> "+ e.getMessage(), e);
  113.         }
  114.     }

  115.     private static void validaSubsection(Subsection subSection,ConfigBean metadata, ExternalResources externalResources) throws ValidationException {
  116.         try {
  117.             validaConditions(subSection.getConditions(),metadata);
  118.    
  119.             if(subSection.getItemList() != null) {
  120.                 for (Item item : subSection.getItemList()) {
  121.                     validaItem(item,metadata, externalResources);
  122.                 }
  123.             }
  124.         }catch(ValidationException e) {
  125.             throw new ValidationException("Subsection ["+subSection.getLabel()+"] -> "+ e.getMessage(), e);
  126.         }
  127.     }

  128.     private static void validaItem(Item item,ConfigBean metadata, ExternalResources externalResources) throws ValidationException {
  129.         try {
  130.             validaConditions(item.getConditions(),metadata);
  131.            
  132.             if(item.getProperty().getProperties() != null) {
  133.                 if(!metadata.getListaNomiProperties().contains(item.getProperty().getProperties()))
  134.                     throw new ValidationException("Il nome delle properties ["+item.getProperty().getProperties()+"] indicato nella collection non e' dichiarato nella sezione collection della configurazione");
  135.             }
  136.            
  137.             // il force puo' essere utilizzato solo da elementi hidden
  138.             if(item.getProperty().isForce() && !item.getType().equals(ItemType.HIDDEN)) {
  139.                 throw new ValidationException("L'attributo Force puo' essere utilizzato solo per gli items di tipo Hidden");
  140.             }
  141.            
  142.             switch(item.getType()){
  143.             case CHECKBOX:
  144.                 validaCheckBox(item);
  145.                 break;
  146.             case HIDDEN:
  147.             case LOCK_HIDDEN:
  148.                 validaHidden(item);
  149.                 break;
  150.             case NUMBER:
  151.                 validaNumber(item,metadata, externalResources);
  152.                 break;
  153.             case SELECT:
  154.                 validaSelect(item,metadata, externalResources);
  155.                 break;
  156.             case TEXT:
  157.             case TEXTAREA:
  158.             case LOCK:
  159.                 validaText(item,metadata, externalResources);
  160.                 break;
  161.             }
  162.         }catch(Exception e) {
  163.             throw new ValidationException("Item ["+item.getName()+"] non valido: "+ e.getMessage(), e);
  164.         }
  165.     }

  166.     private static void validaCheckBox(Item item) throws ValidationException{
  167.         Property property = item.getProperty();
  168.         // se e' una property di tipo append valido il separatore
  169.         if(property.isAppend()) {
  170.             if(property.getSelectedValue().contains(property.getAppendSeparator()))
  171.                 throw new ValidationException("Il valore indicato per l'attributo SelectedValue ["+property.getSelectedValue()+"] contiene il separatore previsto per il salvataggio ["+property.getAppendSeparator()+"]");
  172.            
  173.             if(property.getUnselectedValue().contains(property.getAppendSeparator()))
  174.                 throw new ValidationException("Il valore indicato per l'attributo UnselectedValue ["+property.getUnselectedValue()+"] contiene il separatore previsto per il salvataggio ["+property.getAppendSeparator()+"]");
  175.         }
  176.        
  177.     }

  178.     private static void validaHidden(Item item) throws ValidationException{
  179.         Property property = item.getProperty();
  180.        
  181.         if(item.getValue() == null) {
  182.             throw new ValidationException("L'attributo Value e' obbligatorio per gli elementi di tipo Hidden");
  183.         }
  184.        
  185.         // se e' una property di tipo append valido il separatore
  186.         if(property.isAppend()) {
  187.             if(item.getValue().contains(property.getAppendSeparator()))
  188.                 throw new ValidationException("Il valore indicato per l'attributo Value ["+item.getValue()+"] contiene il separatore previsto per il salvataggio ["+property.getAppendSeparator()+"]");
  189.         }
  190.        
  191.        
  192.     }

  193.     private static String getDefault(Item item,ConfigBean metadata, ExternalResources externalResources) throws ProviderException {
  194.         if(StringUtils.isNotEmpty(item.getDefault())) {
  195.             return item.getDefault();
  196.         }
  197.         else if(metadata.getProvider()!=null) {
  198.             return metadata.getProvider().getDefault(item.getName(), externalResources);
  199.         }
  200.         return null;
  201.     }
  202.    
  203.     private static void validaNumber(Item item,ConfigBean metadata, ExternalResources externalResources) throws ValidationException, ProviderException{
  204.         Property property = item.getProperty();
  205.         // se e' una property di tipo append valido il separatore
  206.         if(property.isAppend()) {
  207.             String defaultValue = getDefault(item, metadata, externalResources);
  208.             if(defaultValue != null && defaultValue.contains(property.getAppendSeparator()))
  209.                 throw new ValidationException("Il valore indicato per l'attributo Default ["+item.getValue()+"] contiene il separatore previsto per il salvataggio ["+property.getAppendSeparator()+"]");
  210.         }
  211.     }

  212.     private static void validaSelect(Item item,ConfigBean metadata, ExternalResources externalResources) throws ValidationException, ProviderException{
  213.         Property property = item.getProperty();
  214.         // se e' una property di tipo append valido il separatore
  215.         if(property.isAppend()) {
  216.             String defaultValue = getDefault(item, metadata, externalResources);
  217.             if(defaultValue != null && defaultValue.contains(property.getAppendSeparator()))
  218.                 throw new ValidationException("Il valore indicato per l'attributo Default ["+item.getValue()+"] contiene il separatore previsto per il salvataggio ["+property.getAppendSeparator()+"]");
  219.         }
  220.        
  221.         if(item.getValues() == null || item.getValues().sizeValueList() == 0) {
  222.             if(metadata.getProvider()==null || metadata.getProvider().getValues(item.getName(), externalResources)==null || metadata.getProvider().getValues(item.getName(), externalResources).size()<=0) {
  223.                 throw new ValidationException("E' necessario indicare una lista di Values, o definirli in un plugins, per gli Item di tipo Select");
  224.             }
  225.         }
  226.     }

  227.     private static void validaText(Item item,ConfigBean metadata, ExternalResources externalResources) throws ValidationException, ProviderException{
  228.         Property property = item.getProperty();
  229.         // se e' una property di tipo append valido il separatore
  230.         if(property.isAppend()) {
  231.             String defaultValue = getDefault(item, metadata, externalResources);
  232.             if(defaultValue != null &&  defaultValue.contains(property.getAppendSeparator()))
  233.                 throw new ValidationException("Il valore indicato per l'attributo Default ["+item.getValue()+"] contiene il separatore previsto per il salvataggio ["+property.getAppendSeparator()+"]");
  234.         }
  235.     }

  236.     private static void validaConditions(Conditions conditions,ConfigBean metadata) throws ValidationException {
  237.         if(conditions == null) return;
  238.        
  239.         for (int i = 0; i < conditions.sizeConditionList(); i ++) {
  240.         Condition condition = conditions.getCondition(i);
  241.             validaCondition(condition, (i+1),metadata);
  242.         }
  243.     }

  244.     private static void validaCondition(Condition condition, int indice,ConfigBean metadata) throws ValidationException{
  245.         if((condition.getDefinedList() == null || condition.getDefinedList().size() == 0)
  246.                 && (condition.getEqualsList() == null || condition.getEqualsList().size() == 0)
  247.                 && (condition.getLessEqualsList() == null || condition.getLessEqualsList().size() == 0)
  248.                 && (condition.getLessThenList() == null || condition.getLessThenList().size() == 0)
  249.                 && (condition.getGreaterEqualsList() == null || condition.getGreaterEqualsList().size() == 0)
  250.                 && (condition.getGreaterThenList() == null || condition.getGreaterThenList().size() == 0)
  251.                 && (condition.getStartsWithList() == null || condition.getStartsWithList().size() == 0)
  252.                 && (condition.getEndsWithList() == null || condition.getEndsWithList().size() == 0)
  253.                 && (condition.getSelectedList() == null || condition.getSelectedList().size() == 0))
  254.             throw new ValidationException("La condition numero ["+indice+"] non e' valida: indicare almeno un elemento tra Defined, Equals o Selected.");
  255.        
  256.         // controlli sulle condizioni le condizioni devono riferire a elementi presenti
  257.         for (int i = 0; i < condition.getDefinedList().size(); i++) {
  258.             Defined defined = condition.getDefined(i);
  259.             if(!itemDefined(defined.getName(),metadata))
  260.                 throw new ValidationException("L'elemento Defined numero ["+(i+1)+"] della Condition numero ["
  261.                         +indice+"] non e' valido: si riferisce ad un elemento ["+defined.getName()+"] non presente nella configurazione.");
  262.                
  263.             BaseItemBean<?> itemToCheck = metadata.getItem(defined.getName());
  264.             ItemType itemToCheckType = itemToCheck.getItemType();
  265.            
  266.             // la condizione defined non si puo' attivare su un elemento checkbox
  267.             if(itemToCheckType.equals(ItemType.CHECKBOX)) {
  268.                 throw new ValidationException("L'elemento Defined numero ["+(i+1)+"] della Condition numero ["
  269.                         +indice+"] non e' valido: si riferisce ad un elemento ["+defined.getName()+"] che ha un tipo non compatibile con la regola, non si puo' controllare se una CheckBox e' Defined");
  270.             }
  271.         }
  272.        
  273.         for (int i = 0; i < condition.getEqualsList().size(); i++) {
  274.             checkEqualsTypeCondition(condition.getEquals(i), condition, indice, metadata, i, "equals");
  275.         }
  276.         for (int i = 0; i < condition.getLessEqualsList().size(); i++) {
  277.             checkEqualsTypeCondition(condition.getLessEquals(i), condition, indice, metadata, i, "lessEquals");
  278.         }
  279.         for (int i = 0; i < condition.getLessThenList().size(); i++) {
  280.             checkEqualsTypeCondition(condition.getLessThen(i), condition, indice, metadata, i, "lessThen");
  281.         }
  282.         for (int i = 0; i < condition.getGreaterEqualsList().size(); i++) {
  283.             checkEqualsTypeCondition(condition.getGreaterEquals(i), condition, indice, metadata, i, "greaterEquals");
  284.         }
  285.         for (int i = 0; i < condition.getGreaterThenList().size(); i++) {
  286.             checkEqualsTypeCondition(condition.getGreaterThen(i), condition, indice, metadata, i, "greaterThen");
  287.         }
  288.         for (int i = 0; i < condition.getStartsWithList().size(); i++) {
  289.             checkEqualsTypeCondition(condition.getStartsWith(i), condition, indice, metadata, i, "startsWith");
  290.         }
  291.         for (int i = 0; i < condition.getEndsWithList().size(); i++) {
  292.             checkEqualsTypeCondition(condition.getEndsWith(i), condition, indice, metadata, i, "endsWith");
  293.         }
  294.        
  295.         for (int i = 0; i < condition.getSelectedList().size(); i++) {
  296.             Selected selected = condition.getSelected(i);
  297.             if(!itemDefined(selected.getName(),metadata))
  298.                 throw new ValidationException("L'elemento Selected numero ["+(i+1)+"] della Condition numero ["
  299.                         +indice+"] non e' valido: si riferisce ad un elemento ["+selected.getName()+"] non presente nella configurazione.");
  300.            
  301.             BaseItemBean<?> itemToCheck = metadata.getItem(selected.getName());
  302.             ItemType itemToCheckType = itemToCheck.getItemType();
  303.            
  304.             // la condizione selected si puo' attivare su un elemento checkbox
  305.             if(!itemToCheckType.equals(ItemType.CHECKBOX)
  306.                     && !itemToCheckType.equals(ItemType.HIDDEN) // aggiunto hidden perche' puo' essere utile quando si disattiva un checbox ma non si vuole eliminare il codice
  307.                     ) {
  308.                 throw new ValidationException("L'elemento Selected numero ["+(i+1)+"] della Condition numero ["
  309.                         +indice+"] non e' valido: si riferisce ad un elemento ["+selected.getName()+"] che non e' di tipo CheckBox");
  310.             }
  311.         }
  312.     }
  313.    
  314.     private static void checkEqualsTypeCondition(Equals equals, Condition condition, int indice,ConfigBean metadata, int i, String tipo) throws ValidationException {
  315.         if(!itemDefined(equals.getName(),metadata))
  316.             throw new ValidationException("L'elemento '"+tipo+"' numero ["+(i+1)+"] della Condition numero ["
  317.                     +indice+"] non e' valido: si riferisce ad un elemento ["+equals.getName()+"] non presente nella configurazione.");
  318.            
  319.         BaseItemBean<?> itemToCheck = metadata.getItem(equals.getName());
  320.         ItemType itemToCheckType = itemToCheck.getItemType();
  321.        
  322.         // la condizione equals non si puo' attivare su un elemento checkbox
  323.         if(itemToCheckType.equals(ItemType.CHECKBOX)) {
  324.             throw new ValidationException("L'elemento '"+tipo+"' numero ["+(i+1)+"] della Condition numero ["
  325.                     +indice+"] non e' valido: si riferisce ad un elemento ["+equals.getName()+"] che ha un tipo non compatibile con la regola, non si puo' controllare se una CheckBox e' Equals");
  326.         }
  327.     }
  328.    
  329.     private static boolean itemDefined(String itemName, ConfigBean metadata) {
  330.         return metadata.getListakeys().contains(itemName);
  331.     }
  332.    
  333.     public static ConfigBean getMetadata(Config config)  throws ValidationException{
  334.         IProvider provider = null;
  335.         if(StringUtils.isNotEmpty(config.getProvider())) {
  336.             try {
  337.                 provider = (IProvider) ClassLoaderUtilities.newInstance(config.getProvider());
  338.             }catch(Exception e) {
  339.                 throw new ValidationException("Errore durante l'istanziazione del provider ["+config.getProvider()+"]: "+e.getMessage(),e);
  340.             }
  341.         }
  342.         ConfigBean cbTmp = new ConfigBean(provider);
  343.         cbTmp.setId(config.getId());
  344.        
  345.         org.openspcoop2.core.mvc.properties.Properties properties = config.getProperties();
  346.         if(properties != null) {
  347.             List<Collection> collectionList = properties.getCollectionList();
  348.             for (Collection collection : collectionList) {
  349.                 cbTmp.getListaNomiProperties().add(collection.getName());
  350.             }
  351.         }
  352.        
  353.         List<Section> sectionList = config.getSectionList();
  354.        
  355.         for (int i= 0; i < sectionList.size() ; i++) {
  356.             Section section = sectionList.get(i);
  357.             getMetadataSection(section,"s"+i,cbTmp);
  358.         }
  359.        
  360.         return cbTmp;
  361.     }
  362.    
  363.     private static void getMetadataSection(Section section, String sectionIdx,ConfigBean cbTmp) throws ValidationException{
  364.         SectionBean sectionBean = new SectionBean(section,sectionIdx, cbTmp.getProvider());
  365.         cbTmp.addItem(sectionBean);
  366.        
  367.         if(section.getItemList() != null) {
  368.             for (Item item : section.getItemList()) {
  369.                 ItemBean itemBean = new ItemBean(item, item.getName(), cbTmp.getProvider());
  370.                 cbTmp.addItem(itemBean);
  371.             }
  372.         }
  373.        
  374.         if(section.getSubsectionList() != null) {
  375.             for (int i= 0; i < section.getSubsectionList().size() ; i++) {
  376.                 Subsection subSection  = section.getSubsectionList().get(i);
  377.                 getMetadataSubsection(subSection,sectionIdx+ "_ss"+i,cbTmp);
  378.             }
  379.         }
  380.      
  381.     }

  382.     private static void getMetadataSubsection(Subsection subSection, String subsectionIdx, ConfigBean cbTmp) throws ValidationException {
  383.         SubsectionBean subsectionBean = new SubsectionBean(subSection,subsectionIdx,cbTmp.getProvider());
  384.         cbTmp.addItem(subsectionBean);
  385.        
  386.         if(subSection.getItemList() != null) {
  387.             for (Item item : subSection.getItemList()) {
  388.                 ItemBean itemBean = new ItemBean(item, item.getName(),cbTmp.getProvider());
  389.                 cbTmp.addItem(itemBean);
  390.             }
  391.         }
  392.     }
  393. }