From 2dca1b4f95fe62eef595cde5509e850973838707 Mon Sep 17 00:00:00 2001 From: Dominique Marcadet <Dominique.Marcadet@centralesupelec.fr> Date: Wed, 22 May 2019 14:52:24 +0200 Subject: [PATCH] add BasicType (partial) and Enumeration validation --- .../scl/validator/nsd/BasicTypeValidator.java | 441 ++++++++++++++++++ .../scl/validator/nsd/CDCValidator.java | 23 + .../validator/nsd/EnumerationValidator.java | 176 +++++++ .../validator/nsd/NsdEObjectValidator.java | 1 + .../scl/validator/nsd/TypeValidator.java | 47 ++ 5 files changed, 688 insertions(+) create mode 100644 fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/BasicTypeValidator.java create mode 100644 fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/EnumerationValidator.java create mode 100644 fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/TypeValidator.java diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/BasicTypeValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/BasicTypeValidator.java new file mode 100644 index 0000000..db302e2 --- /dev/null +++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/BasicTypeValidator.java @@ -0,0 +1,441 @@ +/** + * Copyright (c) 2019 CentraleSupélec & EDF. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * This file is part of the RiseClipse tool + * + * Contributors: + * Computer Science Department, CentraleSupélec + * EDF R&D + * Contacts: + * dominique.marcadet@centralesupelec.fr + * aurelie.dehouck-neveu@edf.fr + * Web site: + * http://wdi.supelec.fr/software/RiseClipse/ + */ +package fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.nsd; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; + +import org.eclipse.emf.common.util.BasicDiagnostic; +import org.eclipse.emf.common.util.Diagnostic; +import org.eclipse.emf.common.util.DiagnosticChain; + +import fr.centralesupelec.edf.riseclipse.iec61850.nsd.BasicType; +import fr.centralesupelec.edf.riseclipse.iec61850.scl.DA; +import fr.centralesupelec.edf.riseclipse.iec61850.scl.Val; +import fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.RiseClipseValidatorSCL; +import fr.centralesupelec.edf.riseclipse.util.AbstractRiseClipseConsole; + +public abstract class BasicTypeValidator extends TypeValidator { + + private static HashMap< String, BasicTypeValidator > validators = new HashMap<>(); + + public static BasicTypeValidator get( BasicType basicType ) { + return validators.get( basicType.getName() ); + } + + static { + validators.put( "BOOLEAN", new BasicTypeValidator( "BOOLEAN" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + switch( value ) { + case "0" : + case "1" : + case "false" : + case "true" : + return true; + default : + return addDiagnosticErrorIfTrue( true, value, da, diagnostics ); + } + } + + }); + + validators.put( "INT8", new BasicTypeValidator( "INT8" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + try { + new Byte( value ); + } + catch( NumberFormatException e ) { + return addDiagnosticErrorIfTrue( true, value, da, diagnostics ); + } + return true; + } + + }); + + validators.put( "INT16", new BasicTypeValidator( "INT16" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + try { + new Short( value ); + } + catch( NumberFormatException e ) { + return addDiagnosticErrorIfTrue( true, value, da, diagnostics ); + } + return true; + } + + }); + + validators.put( "INT32", new BasicTypeValidator( "INT32" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + try { + new Integer( value ); + } + catch( NumberFormatException e ) { + return addDiagnosticErrorIfTrue( true, value, da, diagnostics ); + } + return true; + } + + }); + + validators.put( "INT64", new BasicTypeValidator( "INT64" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + try { + new Long( value ); + } + catch( NumberFormatException e ) { + return addDiagnosticErrorIfTrue( true, value, da, diagnostics ); + } + return true; + } + + }); + + validators.put( "INT8U", new BasicTypeValidator( "INT8U" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + Long v; + try { + v = new Long( value ); + } + catch( NumberFormatException e ) { + return addDiagnosticErrorIfTrue( true, value, da, diagnostics ); + } + return addDiagnosticErrorIfTrue(( v < 0 ) || ( v > 255 ), value, da, diagnostics ); + } + + }); + + validators.put( "INT16U", new BasicTypeValidator( "INT16U" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + Long v; + try { + v = new Long( value ); + } + catch( NumberFormatException e ) { + return addDiagnosticErrorIfTrue( true, value, da, diagnostics ); + } + return addDiagnosticErrorIfTrue(( v < 0 ) || ( v > 65535 ), value, da, diagnostics ); + } + + }); + + validators.put( "INT32U", new BasicTypeValidator( "INT32U" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + Long v; + try { + v = new Long( value ); + } + catch( NumberFormatException e ) { + return addDiagnosticErrorIfTrue( true, value, da, diagnostics ); + } + return addDiagnosticErrorIfTrue(( v < 0 ) || ( v > 4294967295L ), value, da, diagnostics ); + } + + }); + + validators.put( "FLOAT32", new BasicTypeValidator( "FLOAT32" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + try { + new Float( value ); + } + catch( NumberFormatException e ) { + return addDiagnosticErrorIfTrue( true, value, da, diagnostics ); + } + return true; + } + + }); + + validators.put( "Octet64", new BasicTypeValidator( "Octet64" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + return addDiagnosticErrorIfTrue( value.getBytes().length > 64, value, da, diagnostics ); + } + + }); + + validators.put( "VisString64", new BasicTypeValidator( "VisString64" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO: what is a VisString ? + return addDiagnosticErrorIfTrue( value.getBytes().length > 64, value, da, diagnostics ); + } + + }); + + validators.put( "VisString129", new BasicTypeValidator( "VisString129" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO: what is a VisString ? + return addDiagnosticErrorIfTrue( value.getBytes().length > 129, value, da, diagnostics ); + } + + }); + + validators.put( "VisString255", new BasicTypeValidator( "VisString255" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO: what is a VisString ? + return addDiagnosticErrorIfTrue( value.getBytes().length > 255, value, da, diagnostics ); + } + + }); + + validators.put( "Unicode255", new BasicTypeValidator( "Unicode255" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO: how do we handle Unicode ? + return addDiagnosticErrorIfTrue( value.getBytes().length > 255, value, da, diagnostics ); + } + + }); + + validators.put( "PhyComAddr", new BasicTypeValidator( "PhyComAddr" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO + return addDiagnosticWarningNotImplemented( value, da, diagnostics ); + } + + }); + + validators.put( "ObjRef", new BasicTypeValidator( "ObjRef" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO + return addDiagnosticWarningNotImplemented( value, da, diagnostics ); + } + + }); + + validators.put( "EntryID", new BasicTypeValidator( "EntryID" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO + return addDiagnosticWarningNotImplemented( value, da, diagnostics ); + } + + }); + + validators.put( "Currency", new BasicTypeValidator( "Currency" ) { + + final HashSet< String > ISO_4217_3_characterCurrencyCode = new HashSet< String >( Arrays.asList( + "AED", "AFN", "ALL", "AMD", "ANG", "AOA", "ARS", "AUD", "AWG", "AZN", "BAM", "BBD", + "BDT", "BGN", "BHD", "BIF", "BMD", "BND", "BOB", "BOV", "BRL", "BSD", "BTN", "BWP", + "BYN", "BZD", "CAD", "CDF", "CHE", "CHF", "CHW", "CLF", "CLP", "CNY", "COP", "COU", + "CRC", "CUC", "CUP", "CVE", "CZK", "DJF", "DKK", "DOP", "DZD", "EGP", "ERN", "ETB", + "EUR", "FJD", "FKP", "GBP", "GEL", "GHS", "GIP", "GMD", "GNF", "GTQ", "GYD", "HKD", + "HNL", "HRK", "HTG", "HUF", "IDR", "ILS", "INR", "IQD", "IRR", "ISK", "JMD", "JOD", + "JPY", "KES", "KGS", "KHR", "KMF", "KPW", "KRW", "KWD", "KYD", "KZT", "LAK", "LBP", + "LKR", "LRD", "LSL", "LYD", "MAD", "MDL", "MGA", "MKD", "MMK", "MNT", "MOP", "MRU", + "MUR", "MVR", "MWK", "MXN", "MXV", "MYR", "MZN", "NAD", "NGN", "NIO", "NOK", "NPR", + "NZD", "OMR", "PAB", "PEN", "PGK", "PHP", "PKR", "PLN", "PYG", "QAR", "RON", "RSD", + "RUB", "RWF", "SAR", "SBD", "SCR", "SDG", "SEK", "SGD", "SHP", "SLL", "SOS", "SRD", + "SSP", "STN", "SVC", "SYP", "SZL", "THB", "TJS", "TMT", "TND", "TOP", "TRY", "TTD", + "TWD", "TZS", "UAH", "UGX", "USD", "USN", "UYI", "UYU", "UYW", "UZS", "VES", "VND", + "VUV", "WST", "XAF", "XAG", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XDR", "XOF", + "XPD", "XPF", "XPT", "XSU", "XTS", "XUA", "XXX", "YER", "ZAR", "ZMW", "ZWL", "XXX" + )); + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO: what means "The concrete coding shall be defined by the SCSMs." ? + return addDiagnosticErrorIfTrue( ! ISO_4217_3_characterCurrencyCode.contains( value ), value, da, diagnostics ); + } + + }); + + validators.put( "Timestamp", new BasicTypeValidator( "Timestamp" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO + return addDiagnosticWarningNotImplemented( value, da, diagnostics ); + } + + }); + + validators.put( "Quality", new BasicTypeValidator( "Quality" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO + return addDiagnosticWarningNotImplemented( value, da, diagnostics ); + } + + }); + + validators.put( "EntryTime", new BasicTypeValidator( "EntryTime" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO + return addDiagnosticWarningNotImplemented( value, da, diagnostics ); + } + + }); + + validators.put( "TrgOps", new BasicTypeValidator( "TrgOps" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO + return addDiagnosticWarningNotImplemented( value, da, diagnostics ); + } + + }); + + validators.put( "OptFlds", new BasicTypeValidator( "OptFlds" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO + return addDiagnosticWarningNotImplemented( value, da, diagnostics ); + } + + }); + + validators.put( "SvOptFlds", new BasicTypeValidator( "SvOptFlds" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO + return addDiagnosticWarningNotImplemented( value, da, diagnostics ); + } + + }); + + validators.put( "Check", new BasicTypeValidator( "Check" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO + return addDiagnosticWarningNotImplemented( value, da, diagnostics ); + } + + }); + + validators.put( "Tcmd", new BasicTypeValidator( "Tcmd" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO + return addDiagnosticWarningNotImplemented( value, da, diagnostics ); + } + + }); + + validators.put( "Dbpos", new BasicTypeValidator( "Dbpos" ) { + + @Override + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + // TODO + return addDiagnosticWarningNotImplemented( value, da, diagnostics ); + } + + }); + + } + + private String name; + + public BasicTypeValidator( String name ) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public boolean validateDA( DA da, DiagnosticChain diagnostics ) { + AbstractRiseClipseConsole.getConsole().verbose( "[NSD validation] BasicTypeValidator.validateDA( " + da.getName() + " ) at line " + da.getLineNumber() ); + boolean res = true; + if( ! getName().equals( da.getBType() )) { + diagnostics.add( new BasicDiagnostic( + Diagnostic.ERROR, + RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE, + 0, + "[NSD validation] type of DA " + da.getName() + " in DOType (id = " + da.getParentDOType().getId() + + ", line = " + da.getParentDOType().getLineNumber() + ") is not " + getName(), + new Object[] { da } )); + res = false; + } + for( Val val : da.getVal() ) { + res = validateValue( da, val.getValue(), diagnostics ) && res; + } + + return res; + } + + protected boolean addDiagnosticErrorIfTrue( boolean condition, String value, DA da, DiagnosticChain diagnostics ) { + if( condition ) { + diagnostics.add( new BasicDiagnostic( + Diagnostic.ERROR, + RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE, + 0, + "[NSD validation] value " + value + " of Val in DA " + da + " in DOType (id = " + da.getParentDOType().getId() + + ", line = " + da.getParentDOType().getLineNumber() + ") is not a valid " + getName() + " value", + new Object[] { da } )); + return false; + + } + return true; + } + + protected boolean addDiagnosticWarningNotImplemented( String value, DA da, DiagnosticChain diagnostics ) { + diagnostics.add( new BasicDiagnostic( + Diagnostic.WARNING, + RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE, + 0, + "[NSD validation] verification of value " + value + " of Val in DA " + da + " in DOType (id = " + da.getParentDOType().getId() + + ", line = " + da.getParentDOType().getLineNumber() + ") is not implemented for BasicType " + getName(), + new Object[] { da } )); + return true; + } + + protected abstract boolean validateValue( DA da, String value, DiagnosticChain diagnostics ); + +} diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/CDCValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/CDCValidator.java index 377afdd..53d9a37 100644 --- a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/CDCValidator.java +++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/CDCValidator.java @@ -25,7 +25,9 @@ import java.util.stream.Stream; import org.eclipse.emf.common.util.DiagnosticChain; import fr.centralesupelec.edf.riseclipse.iec61850.nsd.CDC; +import fr.centralesupelec.edf.riseclipse.iec61850.nsd.DataAttribute; import fr.centralesupelec.edf.riseclipse.iec61850.nsd.SubDataObject; +import fr.centralesupelec.edf.riseclipse.iec61850.scl.DA; import fr.centralesupelec.edf.riseclipse.iec61850.scl.DOType; import fr.centralesupelec.edf.riseclipse.iec61850.scl.SDO; import fr.centralesupelec.edf.riseclipse.util.AbstractRiseClipseConsole; @@ -45,6 +47,7 @@ public class CDCValidator { private DataAttributePresenceConditionValidator dataAttributePresenceConditionValidator; private SubDataObjectPresenceConditionValidator subDataObjectPresenceConditionValidator; + private HashMap< String, TypeValidator > dataAttributeValidatorMap = new HashMap<>(); private HashMap< String, CDCValidator > subDataObjectValidatorMap = new HashMap<>(); private HashSet< DOType > validatedDOType = new HashSet<>(); @@ -52,6 +55,16 @@ public class CDCValidator { dataAttributePresenceConditionValidator = DataAttributePresenceConditionValidator.get( cdc ); subDataObjectPresenceConditionValidator = SubDataObjectPresenceConditionValidator.get( cdc ); + for( DataAttribute da : cdc.getDataAttribute() ) { + TypeValidator validator = TypeValidator.get( da.getType() ); + if( validator != null ) { + dataAttributeValidatorMap.put( da.getName(), validator ); + } + else { + AbstractRiseClipseConsole.getConsole().warning( "[NSD setup] Type not found for DataAttribute " + da.getName() ); + } + } + for( SubDataObject sdo : cdc.getSubDataObject() ) { CDCValidator validator = CDCValidator.get( sdo.getType() ); if( validator != null ) { @@ -84,6 +97,16 @@ public class CDCValidator { .forEach( d -> subDataObjectPresenceConditionValidator.addSDO( d, diagnostics )); res = subDataObjectPresenceConditionValidator.validate( doType, diagnostics ) && res; + + for( DA da : doType.getDA() ) { + TypeValidator validator = dataAttributeValidatorMap.get( da.getName() ); + if( validator != null ) { + validator.validateDA( da, diagnostics ); + } + else { + AbstractRiseClipseConsole.getConsole().warning( "[NSD validation] while validating DOType (line " + doType.getLineNumber() + "): validator for DA " + da.getName() + " not found" ); + } + } for( SDO sdo : doType.getSDO() ) { CDCValidator validator = subDataObjectValidatorMap.get( sdo.getName() ); diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/EnumerationValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/EnumerationValidator.java new file mode 100644 index 0000000..b4b7205 --- /dev/null +++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/EnumerationValidator.java @@ -0,0 +1,176 @@ +/** + * Copyright (c) 2019 CentraleSupélec & EDF. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * This file is part of the RiseClipse tool + * + * Contributors: + * Computer Science Department, CentraleSupélec + * EDF R&D + * Contacts: + * dominique.marcadet@centralesupelec.fr + * aurelie.dehouck-neveu@edf.fr + * Web site: + * http://wdi.supelec.fr/software/RiseClipse/ + */ +package fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.nsd; + +import java.util.HashMap; +import java.util.HashSet; + +import org.eclipse.emf.common.util.BasicDiagnostic; +import org.eclipse.emf.common.util.Diagnostic; +import org.eclipse.emf.common.util.DiagnosticChain; + +import fr.centralesupelec.edf.riseclipse.iec61850.nsd.Enumeration; +import fr.centralesupelec.edf.riseclipse.iec61850.scl.DA; +import fr.centralesupelec.edf.riseclipse.iec61850.scl.EnumType; +import fr.centralesupelec.edf.riseclipse.iec61850.scl.EnumVal; +import fr.centralesupelec.edf.riseclipse.iec61850.scl.Val; +import fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.RiseClipseValidatorSCL; +import fr.centralesupelec.edf.riseclipse.util.AbstractRiseClipseConsole; + +public class EnumerationValidator extends TypeValidator { + + private HashMap< String, Integer > literals = new HashMap<>(); + private String name; + private String inheritedFromName; + private EnumerationValidator inheritedFrom; + private HashSet< EnumType > validatedEnumType = new HashSet<>(); + + public EnumerationValidator( Enumeration enumeration ) { + this.name = enumeration.getName(); + this.inheritedFromName = enumeration.getInheritedFrom(); + + enumeration + .getLiteral() + .stream() + .forEach( e -> literals.put( e.getName(), e.getLiteralVal() )); + } + + public String getName() { + return name; + } + + @Override + public boolean validateDA( DA da, DiagnosticChain diagnostics ) { + AbstractRiseClipseConsole.getConsole().verbose( "[NSD validation] EnumerationValidator.validateDA( " + da.getName() + " ) at line " + da.getLineNumber() ); + + if(( inheritedFromName != null ) && ( inheritedFrom == null )) { + TypeValidator inheritedValidator = TypeValidator.get( inheritedFromName ); + if(( inheritedValidator != null ) && ( inheritedValidator instanceof EnumerationValidator )) { + inheritedFrom = ( EnumerationValidator ) inheritedValidator; + } + else { + diagnostics.add( new BasicDiagnostic( + Diagnostic.WARNING, + RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE, + 0, + "[NSD validation] validator for inherited enumeration " + inheritedFromName + " not found", + new Object[] { da } )); + // Avoid checking again + inheritedFromName = null; + } + } + + boolean res = true; + if( ! "Enum".equals( da.getBType() )) { + diagnostics.add( new BasicDiagnostic( + Diagnostic.ERROR, + RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE, + 0, + "[NSD validation] bType of DA " + da.getName() + " in DOType (id = " + da.getParentDOType().getId() + + ", line = " + da.getParentDOType().getLineNumber() + ") is not Enum", + new Object[] { da } )); + res = false; + } + if( ! getName().equals( da.getType() )) { + diagnostics.add( new BasicDiagnostic( + Diagnostic.ERROR, + RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE, + 0, + "[NSD validation] type of DA " + da.getName() + " in DOType (id = " + da.getParentDOType().getId() + + ", line = " + da.getParentDOType().getLineNumber() + ") is not " + getName(), + new Object[] { da } )); + res = false; + } + for( Val val : da.getVal() ) { + res = validateValue( da, val.getValue(), diagnostics ) && res; + } + + if( da.getRefersToEnumType() != null ) { + res = validateEnumType( da.getRefersToEnumType(), diagnostics ) && res; + } + + return res; + } + + protected boolean validateValue( DA da, String value, DiagnosticChain diagnostics ) { + boolean res = true; + + if( ! literals.containsKey( value )) { + if( inheritedFrom != null ) { + res = inheritedFrom.validateValue( da, value, diagnostics ) && res; + } + else { + diagnostics.add( new BasicDiagnostic( + Diagnostic.ERROR, + RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE, + 0, + "[NSD validation] value of DA " + da.getName() + " in DOType (id = " + da.getParentDOType().getId() + + ", line = " + da.getParentDOType().getLineNumber() + ") is not valid", + new Object[] { da } )); + res = false; + } + } + + return res; + } + + public boolean validateEnumType( EnumType enumType, DiagnosticChain diagnostics ) { + if( validatedEnumType.contains( enumType )) return true; + AbstractRiseClipseConsole.getConsole().verbose( "[NSD validation] EnumerationValidator.validateEnumType( " + enumType.getId() + " ) at line " + enumType.getLineNumber() ); + validatedEnumType.add( enumType ); + + boolean res = true; + + // enumType.getId().equals( getName() ) already tested because enumType.getId().equals( da.getType() ) + + for( EnumVal enumVal : enumType.getEnumVal() ) { + if( ! literals.containsKey( enumVal.getValue() )) { + if( inheritedFrom != null ) { + res = inheritedFrom.validateEnumType( enumType, diagnostics ) && res; + } + else { + diagnostics.add( new BasicDiagnostic( + Diagnostic.ERROR, + RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE, + 0, + "[NSD validation] EnumVal " + enumVal.getValue() + " in EnumType (id = " + enumType.getId() + + " at line " + enumVal.getLineNumber() + " is unknown", + new Object[] { enumVal } )); + res = false; + } + } + else if( literals.get( enumVal.getValue() ).equals( enumVal.getOrd() )) { + diagnostics.add( new BasicDiagnostic( + Diagnostic.ERROR, + RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE, + 0, + "[NSD validation] EnumVal " + enumVal.getValue() + " in EnumType (id = " + enumType.getId() + + " at line " + enumVal.getLineNumber() + " has incorrect ord (" + enumVal.getOrd() + + " instead of " + literals.get( enumVal.getValue() ), + new Object[] { enumVal } )); + res = false; + } + } + + // TODO: do we have to check that all literals in Enumeration are present as EnumVal ? + + return res; + } + +} diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/NsdEObjectValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/NsdEObjectValidator.java index 20d7cca..392bf65 100644 --- a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/NsdEObjectValidator.java +++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/NsdEObjectValidator.java @@ -41,6 +41,7 @@ public class NsdEObjectValidator implements EValidator { public NsdEObjectValidator( NsdResourceSetImpl nsdResourceSet ) { // Order is important ! + TypeValidator.buildValidators( nsdResourceSet.getBasicTypeStream(), nsdResourceSet.getEnumerationStream(), nsdResourceSet.getConstructedAttributeStream() ); CDCValidator.buildValidators( nsdResourceSet.getCDCStream() ); LNClassValidator.buildValidators( nsdResourceSet.getLNClassStream() ); } diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/TypeValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/TypeValidator.java new file mode 100644 index 0000000..a74944f --- /dev/null +++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/TypeValidator.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2019 CentraleSupélec & EDF. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * This file is part of the RiseClipse tool + * + * Contributors: + * Computer Science Department, CentraleSupélec + * EDF R&D + * Contacts: + * dominique.marcadet@centralesupelec.fr + * aurelie.dehouck-neveu@edf.fr + * Web site: + * http://wdi.supelec.fr/software/RiseClipse/ + */ +package fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.nsd; + +import java.util.HashMap; +import java.util.stream.Stream; + +import org.eclipse.emf.common.util.DiagnosticChain; + +import fr.centralesupelec.edf.riseclipse.iec61850.nsd.BasicType; +import fr.centralesupelec.edf.riseclipse.iec61850.nsd.ConstructedAttribute; +import fr.centralesupelec.edf.riseclipse.iec61850.nsd.Enumeration; +import fr.centralesupelec.edf.riseclipse.iec61850.scl.DA; + +public abstract class TypeValidator { + + private static HashMap< String, TypeValidator > validators = new HashMap<>(); + + public static TypeValidator get( String name ) { + return validators.get( name ); + } + + public static void buildValidators( Stream< BasicType > basicTypeStream, Stream< Enumeration > enumerationStream, Stream< ConstructedAttribute > constructedAttributeStream ) { + basicTypeStream + .forEach( basicType -> validators.put( basicType.getName(), BasicTypeValidator.get( basicType ))); + enumerationStream + .forEach( enumeration -> validators.put( enumeration.getName(), new EnumerationValidator( enumeration ))); + } + + public abstract boolean validateDA( DA da, DiagnosticChain diagnostics ); +} -- GitLab