Commit b67cce1d authored by Dominique Marcadet's avatar Dominique Marcadet

validation of DataTypeTemplate (first version)

parent dda8b215
/**
* 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.CDC;
import fr.centralesupelec.edf.riseclipse.iec61850.nsd.DataAttribute;
import fr.centralesupelec.edf.riseclipse.iec61850.scl.DA;
import fr.centralesupelec.edf.riseclipse.iec61850.scl.DO;
import fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.RiseClipseValidatorSCL;
import fr.centralesupelec.edf.riseclipse.util.AbstractRiseClipseConsole;
public class DOValidator {
private String cdc;
private HashMap< String, DataAttribute > daMap;
public DOValidator( CDC cdc ) {
this.cdc = cdc.getName();
this.daMap = new HashMap<>(); // link between DAI (name) and its respective DataAttribute
for( DataAttribute da : cdc.getDataAttribute() ) {
this.daMap.put( da.getName(), da );
}
}
public boolean validateDO( DO do_, DiagnosticChain diagnostics ) {
AbstractRiseClipseConsole.getConsole().verbose( "validateDO( " + do_.getName() + " )" );
boolean res = true;
HashSet< String > checkedDA = new HashSet<>();
if( do_.getRefersToDOType() == null ) {
AbstractRiseClipseConsole.getConsole().warning( "validateDO: DO " + do_.getName() + " has no RefersToDOType" );
}
else {
for( DA da : do_.getRefersToDOType().getDA() ) {
AbstractRiseClipseConsole.getConsole().verbose( "validateDO on DA " + da.getName() + " (line" + da.getLineNumber() + ")" );
// Test if DA is a possible DA in this DO
if( ! daMap.containsKey( da.getName() ) ) {
diagnostics.add( new BasicDiagnostic(
Diagnostic.ERROR,
RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
0,
"DA " + da.getName() + " (line" + da.getLineNumber() + ") not found in CDC",
new Object[] { do_, cdc } ));
res = false;
continue;
}
// Control of DAI presence in DO
updateCompulsory( da, checkedDA, diagnostics );
}
}
// Verify all necessary DA were present
if( ! daMap.values().stream()
.map( x -> checkCompulsory( do_, x, checkedDA, diagnostics ) )
.reduce( ( a, b ) -> a && b ).get() ) {
diagnostics.add( new BasicDiagnostic(
Diagnostic.ERROR,
RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
0,
"DO (line " + do_.getLineNumber() + ") does not contain all mandatory DA from CDC ",
new Object[] { do_, cdc } ));
res = false;
}
return res;
}
public boolean checkCompulsory( DO do_, DataAttribute da, HashSet< String > checked, DiagnosticChain diagnostics ) {
switch( da.getPresCond() ) {
case "M":
if( ! checked.contains( da.getName() )) {
diagnostics.add( new BasicDiagnostic(
Diagnostic.ERROR,
RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
0,
"DA " + da.getName() + " not found in DO (line " + do_.getLineNumber() + ")",
new Object[] { da } ));
return false;
}
break;
default:
AbstractRiseClipseConsole.getConsole().info( "NOT IMPLEMENTED: DOValidator.checkCompulsory( " + da.getPresCond() + " )" );
break;
}
return true;
}
public boolean updateCompulsory( DA da, HashSet< String > checked, DiagnosticChain diagnostics ) {
switch( daMap.get( da.getName() ).getPresCond() ) {
case "M":
case "O":
if( checked.contains( da.getName() ) ) {
diagnostics.add( new BasicDiagnostic(
Diagnostic.ERROR,
RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
0,
"DA " + da.getName() + " (line " + da.getLineNumber() + ") cannot appear more than once",
new Object[] { da } ));
return false;
}
else {
checked.add( da.getName() );
break;
}
case "F":
diagnostics.add( new BasicDiagnostic(
Diagnostic.ERROR,
RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
0,
"DA " + da.getName() + " (line " + da.getLineNumber() + ") is forbidden",
new Object[] { da } ));
return false;
default:
AbstractRiseClipseConsole.getConsole().info( "NOT IMPLEMENTED: DOIValidator.updateCompulsory( " + daMap.get( da.getName() ).getPresCond() + " )" );
break;
}
return true;
}
}
/**
* 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.AbstractLNClass;
import fr.centralesupelec.edf.riseclipse.iec61850.nsd.DataObject;
import fr.centralesupelec.edf.riseclipse.iec61850.nsd.LNClass;
import fr.centralesupelec.edf.riseclipse.iec61850.nsd.AnyLNClass;
import fr.centralesupelec.edf.riseclipse.iec61850.scl.DO;
import fr.centralesupelec.edf.riseclipse.iec61850.scl.LNodeType;
import fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.RiseClipseValidatorSCL;
import fr.centralesupelec.edf.riseclipse.util.AbstractRiseClipseConsole;
public class LNodeTypeValidator {
private String lnClass;
private HashMap< String, DataObject > doMap;
private HashMap< String, DOValidator > cdcMap;
public LNodeTypeValidator( LNClass lnClass ) {
this.lnClass = lnClass.getName();
this.doMap = new HashMap<>(); // link between DOI (name) and its respective DataObject
this.cdcMap = new HashMap<>(); // link between CDC (name) and its respective DOIValidator
generateValidators( doMap, cdcMap, lnClass );
// LNClass hierarchy taken into account
AbstractLNClass parent = lnClass.getRefersToAbstractLNClass();
while( parent != null ) {
generateValidators( doMap, cdcMap, parent );
parent = parent.getRefersToAbstractLNClass();
}
}
private void generateValidators( HashMap< String, DataObject > doMap, HashMap< String, DOValidator > cdcMap, AnyLNClass lnClass ) {
for( DataObject dObj : lnClass.getDataObject() ) {
doMap.put( dObj.getName(), dObj );
if( dObj.getRefersToCDC() != null ) {
if( ! cdcMap.containsKey( dObj.getRefersToCDC().getName() )) {
cdcMap.put( dObj.getRefersToCDC().getName(), new DOValidator( dObj.getRefersToCDC() ));
}
}
}
}
public boolean validateLNodeType( LNodeType lNodeType, DiagnosticChain diagnostics ) {
boolean res = true;
HashSet< String > checkedDO = new HashSet<>();
for( DO do_ : lNodeType.getDO() ) {
AbstractRiseClipseConsole.getConsole().verbose( "validateDOI( " + do_.getName() + " )" );
// Test if DOI is a possible DOI in this LN
if( ! doMap.containsKey( do_.getName() ) ) {
diagnostics.add( new BasicDiagnostic(
Diagnostic.ERROR,
RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
0,
"DO " + do_.getName() + " in LN at line " + lNodeType.getLineNumber() + " not found in LNClass " + lNodeType.getLnClass(),
new Object[] { lNodeType } ));
continue;
}
// Control of DOI presence in LN
updateCompulsory( do_, checkedDO, diagnostics );
// Validation of DOI content
if( ! validateDO( do_, diagnostics ) ) {
res = false;
}
}
// Verify all necessary DOI were present
if( ! doMap.values().stream()
.map( x -> checkCompulsory( lNodeType, x, checkedDO, diagnostics ))
.reduce( ( a, b ) -> a && b ).get() ) {
diagnostics.add( new BasicDiagnostic(
Diagnostic.ERROR,
RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
0,
"LNodeType at line " + lNodeType.getLineNumber() + " does not contain all mandatory DO from class " + lNodeType.getLnClass(),
new Object[] { lNodeType } ));
res = false;
}
return res;
}
private boolean checkCompulsory( LNodeType lNodeType, DataObject dataObject, HashSet< String > checkedDO, DiagnosticChain diagnostics ) {
switch( dataObject.getPresCond() ) {
case "M":
if( ! checkedDO.contains( dataObject.getName() ) ) {
diagnostics.add( new BasicDiagnostic(
Diagnostic.ERROR,
RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
0,
"DO " + dataObject.getName() + " is missing in LN at line " + lNodeType.getLineNumber(),
new Object[] { lNodeType } ));
return false;
}
break;
default:
AbstractRiseClipseConsole.getConsole().info( "NOT IMPLEMENTED: AnyLNValidator.checkCompulsory( " + dataObject.getPresCond() + " )" );
break;
}
return true;
}
private boolean updateCompulsory( DO do_, HashSet< String > checkedDO, DiagnosticChain diagnostics ) {
switch( doMap.get( do_.getName() ).getPresCond() ) {
case "M":
case "O":
if( checkedDO.contains( do_.getName() )) {
diagnostics.add( new BasicDiagnostic(
Diagnostic.ERROR,
RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
0,
"DO " + do_ + " cannot appear more than once in LN at line " + do_.getParentLNodeType().getLineNumber(),
new Object[] { do_ } ));
return false;
}
checkedDO.add( do_.getName() );
break;
case "F":
diagnostics.add( new BasicDiagnostic(
Diagnostic.ERROR,
RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
0,
"DO " + do_ + " is forbidden in LN at line " + do_.getParentLNodeType().getLineNumber(),
new Object[] { do_ } ));
return false;
default:
AbstractRiseClipseConsole.getConsole().info( "NOT IMPLEMENTED: AnyLNValidator.updateCompulsory( " + doMap.get( do_.getName() ).getPresCond() + " )" );
break;
}
return true;
}
private boolean validateDO( DO do_, DiagnosticChain diagnostics ) {
AbstractRiseClipseConsole.getConsole().verbose( "found DO " + do_.getName() + " in LNClass " + lnClass );
// DOIValidator validates DOI content
String cdc = doMap.get( do_.getName() ).getRefersToCDC().getName();
return cdcMap.get( cdc ).validateDO( do_, diagnostics );
}
}
......@@ -31,33 +31,49 @@ import org.eclipse.emf.ecore.EValidator;
import fr.centralesupelec.edf.riseclipse.iec61850.nsd.LNClass;
import fr.centralesupelec.edf.riseclipse.iec61850.nsd.util.NsdResourceSetImpl;
import fr.centralesupelec.edf.riseclipse.iec61850.scl.AnyLN;
import fr.centralesupelec.edf.riseclipse.iec61850.scl.LNodeType;
import fr.centralesupelec.edf.riseclipse.iec61850.scl.util.SclSwitch;
import fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.RiseClipseValidatorSCL;
import fr.centralesupelec.edf.riseclipse.util.AbstractRiseClipseConsole;
public class NsdEObjectValidator implements EValidator {
private NsdResourceSetImpl nsdResourceSet;
private HashMap< String, AnyLNValidator > lnMap;
private HashMap< String, AnyLNValidator > anyLNValidatorMap;
private HashMap<String,LNodeTypeValidator> lNodeTypeValidatorMap;
public NsdEObjectValidator( NsdResourceSetImpl nsdResourceSet ) {
this.nsdResourceSet = nsdResourceSet;
}
public void initializeValidationData() {
this.lnMap = this.nsdResourceSet.getLNClassStream()
.map( lnClass -> generateValidators( lnClass ) )
this.anyLNValidatorMap = this.nsdResourceSet.getLNClassStream()
.map( lnClass -> generateAnyLNValidators( lnClass ) )
.reduce( ( a, b ) -> {
a.putAll( b );
return a;
} ).get();
this.lNodeTypeValidatorMap = this.nsdResourceSet.getLNClassStream()
.map( lnClass -> generateLNodeTypeValidators( lnClass ) )
.reduce( ( a, b ) -> {
a.putAll( b );
return a;
} ).get();
}
private HashMap< String, AnyLNValidator > generateValidators( LNClass lnClass ) {
private HashMap< String, AnyLNValidator > generateAnyLNValidators( LNClass lnClass ) {
HashMap< String, AnyLNValidator > lnMap = new HashMap<>();
lnMap.put( lnClass.getName(), new AnyLNValidator( lnClass ));
return lnMap;
}
private HashMap< String, LNodeTypeValidator > generateLNodeTypeValidators( LNClass lnClass ) {
HashMap< String, LNodeTypeValidator > lNodeTypeMap = new HashMap<>();
lNodeTypeMap.put( lnClass.getName(), new LNodeTypeValidator( lnClass ));
return lNodeTypeMap;
}
@Override
public boolean validate( EObject eObject, DiagnosticChain diagnostics, Map< Object, Object > context ) {
return validate( eObject.eClass(), eObject, diagnostics, context );
......@@ -66,19 +82,31 @@ public class NsdEObjectValidator implements EValidator {
@Override
public boolean validate( EClass eClass, EObject eObject, DiagnosticChain diagnostics, Map< Object, Object > context ) {
if( this.lnMap == null ) {
if( this.anyLNValidatorMap == null ) {
this.initializeValidationData();
}
switch( eClass.getName() ) {
case "LN0":
case "LN":
AnyLN ln = ( AnyLN ) eObject;
return validateLN( ln, diagnostics );
default:
AbstractRiseClipseConsole.getConsole().info( "NOT IMPLEMENTED: NsdEObjectValidator.validate( " + eClass.getName() + " )" );
return false;
}
SclSwitch< Boolean > sw = new SclSwitch< Boolean >() {
@Override
public Boolean caseAnyLN( AnyLN anyLN ) {
return validateAnyLN( anyLN, diagnostics );
}
@Override
public Boolean caseLNodeType( LNodeType lNodeType ) {
return validateLNodeType( lNodeType, diagnostics );
}
@Override
public Boolean defaultCase( EObject object ) {
AbstractRiseClipseConsole.getConsole().info( "NOT IMPLEMENTED: NsdEObjectValidator.validate( " + object.eClass().getName() + " )" );
return true;
}
};
return sw.doSwitch( eObject );
}
@Override
......@@ -90,12 +118,12 @@ public class NsdEObjectValidator implements EValidator {
return true;
}
private boolean validateLN( AnyLN ln, DiagnosticChain diagnostics ) {
private boolean validateAnyLN( AnyLN ln, DiagnosticChain diagnostics ) {
AbstractRiseClipseConsole.getConsole().verbose( "" );
AbstractRiseClipseConsole.getConsole().verbose( "NsdEObjectValidator.validateLN( " + ln.getLnClass() + " )" );
// Check that LN has valid LNClass
if( ! this.lnMap.containsKey( ln.getLnClass() )) {
if( ! this.anyLNValidatorMap.containsKey( ln.getLnClass() )) {
diagnostics.add( new BasicDiagnostic(
Diagnostic.ERROR,
RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
......@@ -107,7 +135,27 @@ public class NsdEObjectValidator implements EValidator {
AbstractRiseClipseConsole.getConsole().verbose( "found LNClass " + ln.getLnClass() + " in NSD files for LN at line " + ln.getLineNumber() );
// AnyLNValidator validates LN content
return lnMap.get( ln.getLnClass() ).validateLN( ln, diagnostics );
return anyLNValidatorMap.get( ln.getLnClass() ).validateLN( ln, diagnostics );
}
protected Boolean validateLNodeType( LNodeType lNodeType, DiagnosticChain diagnostics ) {
AbstractRiseClipseConsole.getConsole().verbose( "" );
AbstractRiseClipseConsole.getConsole().verbose( "NsdEObjectValidator.validateLNodeType( " + lNodeType.getLnClass() + " )" );
// Check that LN has valid LNClass
if( ! this.anyLNValidatorMap.containsKey( lNodeType.getLnClass() )) {
diagnostics.add( new BasicDiagnostic(
Diagnostic.ERROR,
RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
0,
"LNClass " + lNodeType.getLnClass() + " not found in NSD files for LN at line " + lNodeType.getLineNumber(),
new Object[] { lNodeType } ));
return false;
}
AbstractRiseClipseConsole.getConsole().verbose( "found LNClass " + lNodeType.getLnClass() + " in NSD files for LN at line " + lNodeType.getLineNumber() );
// AnyLNValidator validates LN content
return lNodeTypeValidatorMap.get( lNodeType.getLnClass() ).validateLNodeType( lNodeType, diagnostics );
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment