From b777f6ed841cc86f359d1093a382d901a4b7a068 Mon Sep 17 00:00:00 2001
From: Dominique Marcadet <Dominique.Marcadet@centralesupelec.fr>
Date: Wed, 26 Jun 2019 15:16:27 +0200
Subject: [PATCH] update messages with filename and line number

---
 .../scl/validator/nsd/CDCValidator.java       |  4 +-
 .../nsd/ConstructedAttributeValidator.java    |  2 +-
 ...taAttributePresenceConditionValidator.java |  7 +-
 .../DataObjectPresenceConditionValidator.java | 78 ++++++++--------
 .../GenericPresenceConditionValidator.java    | 89 ++++++++++---------
 .../scl/validator/nsd/LNClassValidator.java   |  4 +-
 ...taAttributePresenceConditionValidator.java |  7 +-
 ...bDataObjectPresenceConditionValidator.java |  8 +-
 8 files changed, 107 insertions(+), 92 deletions(-)

diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/CDCValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/CDCValidator.java
index 58a5a15..a902c8b 100644
--- a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/CDCValidator.java
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/CDCValidator.java
@@ -62,7 +62,7 @@ public class CDCValidator {
                 dataAttributeValidatorMap.put( da.getName(), validator );
             }
             else {
-                AbstractRiseClipseConsole.getConsole().warning( "[NSD setup] Type not found for DataAttribute " + da.getName() );
+                AbstractRiseClipseConsole.getConsole().warning( "[NSD setup] (" + da.getFilename() + ":" + da.getLineNumber() + ") Type not found for DataAttribute " + da.getName() );
             }
         }
         
@@ -72,7 +72,7 @@ public class CDCValidator {
                 subDataObjectValidatorMap.put( sdo.getName(), validator );
             }
             else {
-                AbstractRiseClipseConsole.getConsole().warning( "[NSD setup] CDC not found for SubDataObject " + sdo.getName() );
+                AbstractRiseClipseConsole.getConsole().warning( "[NSD setup] (" + sdo.getFilename() + ":" + sdo.getLineNumber() + ") CDC not found for SubDataObject " + sdo.getName() );
             }
         }
         
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/ConstructedAttributeValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/ConstructedAttributeValidator.java
index 90958ea..826dc25 100644
--- a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/ConstructedAttributeValidator.java
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/ConstructedAttributeValidator.java
@@ -46,7 +46,7 @@ public class ConstructedAttributeValidator extends TypeValidator {
                 subDataAttributeValidatorMap.put( sda.getName(), validator );
             }
             else {
-                AbstractRiseClipseConsole.getConsole().warning( "[NSD setup] Type not found for DataAttribute " + sda.getName() );
+                AbstractRiseClipseConsole.getConsole().warning( "[NSD setup] (" + sda.getFilename() + ":" + sda.getLineNumber() + ") Type not found for DataAttribute " + sda.getName() );
             }
         }
     }
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DataAttributePresenceConditionValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DataAttributePresenceConditionValidator.java
index 3df5165..4c8fea1 100644
--- a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DataAttributePresenceConditionValidator.java
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DataAttributePresenceConditionValidator.java
@@ -57,7 +57,7 @@ public class DataAttributePresenceConditionValidator extends GenericPresenceCond
         cdc
         .getDataAttribute()
         .stream()
-        .forEach( da -> addSpecification( da.getName(), da.getPresCond(), da.getPresCondArgs(), da.getRefersToPresCondArgsDoc() ));
+        .forEach( da -> addSpecification( da.getName(), da.getPresCond(), da.getPresCondArgs(), da.getRefersToPresCondArgsDoc(), da.getLineNumber(), da.getFilename() ));
     }
 
     @Override
@@ -70,6 +70,11 @@ public class DataAttributePresenceConditionValidator extends GenericPresenceCond
         return cdc.getName();
     }
 
+    @Override
+    protected int getNsdModelLineNumber() {
+        return cdc.getLineNumber();
+    }
+
     @Override
     protected String getNsdModelClassName() {
         return "CDC";
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DataObjectPresenceConditionValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DataObjectPresenceConditionValidator.java
index c81ac6c..936bd8d 100644
--- a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DataObjectPresenceConditionValidator.java
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DataObjectPresenceConditionValidator.java
@@ -33,7 +33,6 @@ import fr.centralesupelec.edf.riseclipse.iec61850.scl.AnyLN;
 import fr.centralesupelec.edf.riseclipse.iec61850.scl.DA;
 import fr.centralesupelec.edf.riseclipse.iec61850.scl.DO;
 import fr.centralesupelec.edf.riseclipse.iec61850.scl.DOI;
-import fr.centralesupelec.edf.riseclipse.iec61850.scl.DOType;
 import fr.centralesupelec.edf.riseclipse.iec61850.scl.LN0;
 import fr.centralesupelec.edf.riseclipse.iec61850.scl.LNodeType;
 import fr.centralesupelec.edf.riseclipse.iec61850.scl.Val;
@@ -58,6 +57,7 @@ public class DataObjectPresenceConditionValidator {
     private static class SingleOrMultiDO {
     }
     private static class SingleDO extends SingleOrMultiDO {
+        @SuppressWarnings( "unused" )
         DO do_;
 
         SingleDO( DO do_ ) {
@@ -122,7 +122,7 @@ public class DataObjectPresenceConditionValidator {
         anyLNClass
         .getDataObject()
         .stream()
-        .forEach( d -> addSpecification( d.getName(), d.getPresCond(), d.getPresCondArgs() ) );
+        .forEach( d -> addSpecification( d.getName(), d.getPresCond(), d.getPresCondArgs(), d.getLineNumber(), d.getFilename() ));
         
         checkSpecification();
         
@@ -140,9 +140,9 @@ public class DataObjectPresenceConditionValidator {
         if( base != null ) base.reset();
     }
     
-    private void addSpecification( String name, String presCond, String presCondArgs ) {
+    private void addSpecification( String name, String presCond, String presCondArgs, int lineNumber, String filename ) {
         if( presentDO.containsKey( name )) {
-            console.warning( "[NSD setup] " + name + " has already been added to DataObjectPresenceConditionValidator" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") " + name + " has already been added to DataObjectPresenceConditionValidator" );
             return;
         }
         presentDO.put( name, null );
@@ -166,7 +166,7 @@ public class DataObjectPresenceConditionValidator {
         case "na" :
             // Element is not applicable
             // -> TODO: what does it mean ? what do we have to check ?
-            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"na\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") NOT IMPLEMENTED: DataObject " + name + " declared as \"na\" in PresenceCondition" );
             if( notApplicable == null ) notApplicable = new HashSet<>();
             notApplicable.add( name );
             break;
@@ -189,7 +189,7 @@ public class DataObjectPresenceConditionValidator {
             try {
                 Integer arg = Integer.valueOf( presCondArgs );
                 if( arg <= 0 ) {
-                    console.warning( "[NSD setup] argument of PresenceCondition \"AtLeastOne\" is not a positive integer" );
+                    console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"AtLeastOne\" is not a positive integer" );
                     break;
                 }
                 if( ! atLeastOne.containsKey( arg )) {
@@ -199,7 +199,7 @@ public class DataObjectPresenceConditionValidator {
                 break;
             }
             catch( NumberFormatException e ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"AtLeastOne\" is not an integer" );
+                console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"AtLeastOne\" is not an integer" );
                 break;
             }
         case "AtMostOne" :
@@ -214,7 +214,7 @@ public class DataObjectPresenceConditionValidator {
             try {
                 Integer arg = Integer.valueOf( presCondArgs );
                 if( arg <= 0 ) {
-                    console.warning( "[NSD setup] argument of PresenceCondition \"AllOrNonePerGroup\" is not a positive integer" );
+                    console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"AllOrNonePerGroup\" is not a positive integer" );
                     break;
                 }
                 if( ! allOrNonePerGroup.containsKey( arg )) {
@@ -224,7 +224,7 @@ public class DataObjectPresenceConditionValidator {
                 break;
             }
             catch( NumberFormatException e ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"AllOrNonePerGroup\" is not an integer" );
+                console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"AllOrNonePerGroup\" is not an integer" );
                 break;
             }
         case "AllOnlyOneGroup" :
@@ -234,7 +234,7 @@ public class DataObjectPresenceConditionValidator {
             try {
                 Integer arg = Integer.valueOf( presCondArgs );
                 if( arg <= 0 ) {
-                    console.warning( "[NSD setup] argument of PresenceCondition \"AllOnlyOneGroup\" is not a positive integer" );
+                    console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"AllOnlyOneGroup\" is not a positive integer" );
                     break;
                 }
                 if( ! allOnlyOneGroup.containsKey( arg )) {
@@ -244,7 +244,7 @@ public class DataObjectPresenceConditionValidator {
                 break;
             }
             catch( NumberFormatException e ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"AllOnlyOneGroup\" is not an integer" );
+                console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"AllOnlyOneGroup\" is not an integer" );
                 break;
             }
         case "AllAtLeastOneGroup" :
@@ -254,7 +254,7 @@ public class DataObjectPresenceConditionValidator {
             try {
                 Integer arg = Integer.valueOf( presCondArgs );
                 if( arg <= 0 ) {
-                    console.warning( "[NSD setup] argument of PresenceCondition \"AllAtLeastOneGroup\" is not a positive integer" );
+                    console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"AllAtLeastOneGroup\" is not a positive integer" );
                     break;
                 }
                 if( ! allAtLeastOneGroup.containsKey( arg )) {
@@ -264,7 +264,7 @@ public class DataObjectPresenceConditionValidator {
                 break;
             }
             catch( NumberFormatException e ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"AllAtLeastOneGroup\" is not an integer" );
+                console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"AllAtLeastOneGroup\" is not an integer" );
                 break;
             }
         case "MF" :
@@ -299,14 +299,14 @@ public class DataObjectPresenceConditionValidator {
             try {
                 Integer arg = Integer.valueOf( presCondArgs );
                 if( arg <= 0 ) {
-                    console.warning( "[NSD setup] argument of PresenceCondition \"MOcond\" is not a positive integer" );
+                    console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"MOcond\" is not a positive integer" );
                     break;
                 }
                 mandatoryIfTextConditionElseOptional.put( name, presCondArgs );
                 break;
             }
             catch( NumberFormatException e ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"MOcond\" is not an integer" );
+                console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"MOcond\" is not an integer" );
                 break;
             }
         case "MFcond" :
@@ -317,14 +317,14 @@ public class DataObjectPresenceConditionValidator {
             try {
                 Integer arg = Integer.valueOf( presCondArgs );
                 if( arg <= 0 ) {
-                    console.warning( "[NSD setup] argument of PresenceCondition \"MFcond\" is not a positive integer" );
+                    console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"MFcond\" is not a positive integer" );
                     break;
                 }
                 mandatoryIfTextConditionElseForbidden.put( name, presCondArgs );
                 break;
             }
             catch( NumberFormatException e ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"MFcond\" is not an integer" );
+                console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"MFcond\" is not an integer" );
                 break;
             }
         case "OFcond" :
@@ -335,14 +335,14 @@ public class DataObjectPresenceConditionValidator {
             try {
                 Integer arg = Integer.valueOf( presCondArgs );
                 if( arg <= 0 ) {
-                    console.warning( "[NSD setup] argument of PresenceCondition \"MFcond\" is not a positive integer" );
+                    console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"MFcond\" is not a positive integer" );
                     break;
                 }
                 optionalIfTextConditionElseForbidden.put( name, presCondArgs );
                 break;
             }
             catch( NumberFormatException e ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"MFcond\" is not an integer" );
+                console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"MFcond\" is not an integer" );
                 break;
             }
         case "MmultiRange" :
@@ -352,17 +352,17 @@ public class DataObjectPresenceConditionValidator {
             if( mandatoryMultiRange == null ) mandatoryMultiRange = new HashMap<>();
             String[] limits1 = presCondArgs.split( "[ ,]+" );
             if( limits1.length != 2 ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"MmultiRange\" is not two integers" );
+                console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"MmultiRange\" is not two integers" );
                 break;
             }
             Integer min1 = Integer.valueOf( limits1[0] );
             if( min1 <= 0 ) {
-                console.warning( "[NSD setup] first argument of PresenceCondition \"MmultiRange\" is not a positive integer" );
+                console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") first argument of PresenceCondition \"MmultiRange\" is not a positive integer" );
                 break;
             }
             Integer max1 = Integer.valueOf( limits1[1] );
             if( max1 <= 0 ) {
-                console.warning( "[NSD setup] second argument of PresenceCondition \"MmultiRange\" is not a positive integer" );
+                console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") second argument of PresenceCondition \"MmultiRange\" is not a positive integer" );
                 break;
             }
             mandatoryMultiRange.put( name, Pair.of( min1, max1 ));
@@ -374,17 +374,17 @@ public class DataObjectPresenceConditionValidator {
             if( optionalMultiRange == null ) optionalMultiRange = new HashMap<>();
             String[] limits2 = presCondArgs.split( "[ ,]+" );
             if( limits2.length != 2 ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"OmultiRange\" is not two integers" );
+                console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") argument of PresenceCondition \"OmultiRange\" is not two integers" );
                 break;
             }
             Integer min2 = Integer.valueOf( limits2[0] );
             if( min2 <= 0 ) {
-                console.warning( "[NSD setup] first argument of PresenceCondition \"OmultiRange\" is not a positive integer" );
+                console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") first argument of PresenceCondition \"OmultiRange\" is not a positive integer" );
                 break;
             }
             Integer max2 = Integer.valueOf( limits2[1] );
             if( max2 <= 0 ) {
-                console.warning( "[NSD setup] second argument of PresenceCondition \"OmultiRange\" is not a positive integer" );
+                console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") second argument of PresenceCondition \"OmultiRange\" is not a positive integer" );
                 break;
             }
             optionalMultiRange.put( name, Pair.of( min2, max2 ));
@@ -392,7 +392,7 @@ public class DataObjectPresenceConditionValidator {
         case "MFsubst" :
             // Element is mandatory if substitution is supported (for substitution, see IEC 61850-7-3), otherwise forbidden
             // TODO: how do we know if substitution is supported ?
-            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MFsubst\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") NOT IMPLEMENTED: DataObject " + name + " declared as \"MFsubst\" in PresenceCondition" );
             if( mandatoryIfSubstitutionElseForbidden == null ) mandatoryIfSubstitutionElseForbidden = new HashSet<>();
             mandatoryIfSubstitutionElseForbidden.add( name );
             break;
@@ -409,14 +409,14 @@ public class DataObjectPresenceConditionValidator {
         case "MOlnNs" :
             // Element is mandatory if the name space of its logical node deviates from the name space of the containing
             // logical device, otherwise optional. See IEC 61850-7-1 for use of name space
-            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MOlnNs\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") NOT IMPLEMENTED: DataObject " + name + " declared as \"MOlnNs\" in PresenceCondition" );
             if( mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional == null ) mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional = new HashSet<>();
             mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional.add( name );
             break;
         case "MOdataNs" :
             // Element is mandatory if the name space of its data object deviates from the name space of its logical node,
             // otherwise optional. See IEC 61850-7-1 for use of name space
-            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MOdataNs\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") NOT IMPLEMENTED: DataObject " + name + " declared as \"MOdataNs\" in PresenceCondition" );
             if( mandatoryIfNameSpaceOfDataObjectDeviatesElseOptional == null ) mandatoryIfNameSpaceOfDataObjectDeviatesElseOptional = new HashSet<>();
             mandatoryIfNameSpaceOfDataObjectDeviatesElseOptional.add( name );
             break;
@@ -424,28 +424,28 @@ public class DataObjectPresenceConditionValidator {
             // Element is mandatory* if any sibling elements of type AnalogueValue include 'i' as a child, otherwise forbidden.
             // *Even though devices without floating point capability cannot exchange floating point values through ACSI services,
             // the description of scaling remains mandatory for their (SCL) configuration
-            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MFscaledAV\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") NOT IMPLEMENTED: DataObject " + name + " declared as \"MFscaledAV\" in PresenceCondition" );
             if( mandatoryIfAnalogValueIncludesIElseForbidden == null ) mandatoryIfAnalogValueIncludesIElseForbidden = new HashSet<>();
             mandatoryIfAnalogValueIncludesIElseForbidden.add( name );
             break;
         case "MFscaledMagV" :
             // Element is mandatory* if any sibling elements of type Vector include 'i' as a child of their 'mag' attribute, otherwise forbidden.
             // *See MFscaledAV
-            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MFscaledMagV\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") NOT IMPLEMENTED: DataObject " + name + " declared as \"MFscaledMagV\" in PresenceCondition" );
             if( mandatoryIfVectorSiblingIncludesIAsChildMagElseForbidden == null ) mandatoryIfVectorSiblingIncludesIAsChildMagElseForbidden = new HashSet<>();
             mandatoryIfVectorSiblingIncludesIAsChildMagElseForbidden.add( name );
             break;
         case "MFscaledAngV" :
             // Element is mandatory* if any sibling elements of type Vector include 'i' as a child of their 'ang' attribute, otherwise forbidden.
             // *See MFscaledAV
-            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MFscaledAngV\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") NOT IMPLEMENTED: DataObject " + name + " declared as \"MFscaledAngV\" in PresenceCondition" );
             if( mandatoryIfVectorSiblingIncludesIAsChildAngElseForbidden == null ) mandatoryIfVectorSiblingIncludesIAsChildAngElseForbidden = new HashSet<>();
             mandatoryIfVectorSiblingIncludesIAsChildAngElseForbidden.add( name );
             break;
         case "MOrms" :
             // Element is mandatory if the harmonic values in the context are calculated as a ratio to RMS value
             // (value of data attribute 'hvRef' is 'rms'), optional otherwise
-            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MOrms\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") NOT IMPLEMENTED: DataObject " + name + " declared as \"MOrms\" in PresenceCondition" );
             if( mandatoryIfHarmonicValuesCalculatedAsRatioElseOptional == null ) mandatoryIfHarmonicValuesCalculatedAsRatioElseOptional = new HashSet<>();
             mandatoryIfHarmonicValuesCalculatedAsRatioElseOptional.add( name );
             break;
@@ -456,28 +456,28 @@ public class DataObjectPresenceConditionValidator {
             break;
         case "MOoperTm" :
             // Element is mandatory if at least one controlled object on the IED supports time activation service; otherwise it is optional
-            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MOoperTm\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") NOT IMPLEMENTED: DataObject " + name + " declared as \"MOoperTm\" in PresenceCondition" );
             if( mandatoryIfControlSupportsTimeElseOptional == null ) mandatoryIfControlSupportsTimeElseOptional = new HashSet<>();
             mandatoryIfControlSupportsTimeElseOptional.add( name );
             break;
         case "MmultiF" :
             // Parameter sibling: sibling element name.
             // One or more elements must be present if sibling element is present, otherwise forbidden
-            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MmultiF\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") NOT IMPLEMENTED: DataObject " + name + " declared as \"MmultiF\" in PresenceCondition" );
             if( oneOrMoreIfSiblingPresentElseForbidden == null ) oneOrMoreIfSiblingPresentElseForbidden = new HashMap<>();
             oneOrMoreIfSiblingPresentElseForbidden.put( name, presCondArgs );
             break;
         case "MOsbo" :
             // Element is mandatory if declared control model supports 'sbo-with-normal-security' or 'sbo-with-enhanced-security',
             // otherwise optional and value is of no impact
-            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MOsbo\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") NOT IMPLEMENTED: DataObject " + name + " declared as \"MOsbo\" in PresenceCondition" );
             if( mandatoryIfControlSupportsSecurity1ElseOptional == null ) mandatoryIfControlSupportsSecurity1ElseOptional = new HashSet<>();
             mandatoryIfControlSupportsSecurity1ElseOptional.add( name );
             break;
         case "MOenhanced" :
             // Element is mandatory if declared control model supports 'direct-with-enhanced-security' or 'sbo-with-enhanced-security',
             // otherwise optional and value is of no impact
-            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MOenhanced\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") NOT IMPLEMENTED: DataObject " + name + " declared as \"MOenhanced\" in PresenceCondition" );
             if( mandatoryIfControlSupportsSecurity2ElseOptional == null ) mandatoryIfControlSupportsSecurity2ElseOptional = new HashSet<>();
             mandatoryIfControlSupportsSecurity2ElseOptional.add( name );
             break;
@@ -497,18 +497,18 @@ public class DataObjectPresenceConditionValidator {
         case "MORange" :
             // Element is mandatory if the measured value associated (amplitude respectively angle) exposes the range eventing
             // (with the attribute range respectively rangeAng)
-            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MORange\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") NOT IMPLEMENTED: DataObject " + name + " declared as \"MORange\" in PresenceCondition" );
             if( mandatoryIfMeasuredValueExposesRange == null ) mandatoryIfMeasuredValueExposesRange = new HashSet<>();
             mandatoryIfMeasuredValueExposesRange.add( name );
             break;
         case "OMSynPh" :
             // This attribute is optional if value of 'phsRef'' is Synchrophasor otherwise Mandatory]]></Doc>
-            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"OMSynPh\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") NOT IMPLEMENTED: DataObject " + name + " declared as \"OMSynPh\" in PresenceCondition" );
             if( optionalIfPhsRefIsSynchrophasorElseMandatory == null ) optionalIfPhsRefIsSynchrophasorElseMandatory = new HashSet<>();
             optionalIfPhsRefIsSynchrophasorElseMandatory.add( name );
             break;
         default:
-            console.warning( "[NSD setup] the PresenceCondition " + presCond + " of AnyLNClass " + name + " is unknown" );
+            console.warning( "[NSD setup] (" + filename + ":" + lineNumber + ") the PresenceCondition " + presCond + " of AnyLNClass " + name + " is unknown" );
             break;
         }
         
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/GenericPresenceConditionValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/GenericPresenceConditionValidator.java
index ac41ef8..e664872 100644
--- a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/GenericPresenceConditionValidator.java
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/GenericPresenceConditionValidator.java
@@ -95,6 +95,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
     protected abstract String getPresenceConditionValidatorName();
 
     protected abstract String getNsdModelName();
+    protected abstract int    getNsdModelLineNumber();
     protected abstract String getNsdModelClassName();
     protected abstract String getNsdComponentClassName();
 
@@ -107,9 +108,9 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
         }
     }
     
-    protected void addSpecification( String name, String presCond, String presCondArgs, Doc doc ) {
+    protected void addSpecification( String name, String presCond, String presCondArgs, Doc doc, int lineNumber, String fileName ) {
         if( presentSclComponent.containsKey( name )) {
-            console.warning( "[NSD setup] " + name + " has already been added to " + getPresenceConditionValidatorName() );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") has already been added to " + getPresenceConditionValidatorName() );
             return;
         }
         presentSclComponent.put( name, null );
@@ -133,21 +134,21 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
         case "na" :
             // Element is not applicable
             // -> TODO: what does it mean ? what do we have to check ?
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"na\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"na\" in PresenceCondition" );
             if( notApplicable == null ) notApplicable = new HashSet<>();
             notApplicable.add( name );
             break;
         case "Mmulti" :
             // At least one element shall be present; all instances have an instance number > 0
             // -> TODO: not sure what is the instance number, it is assumed to be the suffix of DO name
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"Mmulti\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"Mmulti\" in PresenceCondition" );
             if( mandatoryMulti == null ) mandatoryMulti = new HashSet<>();
             mandatoryMulti.add( name );
             break;
         case "Omulti" :
             // Zero or more elements may be present; all instances have an instance number > 0
             // -> TODO: not sure what is the instance number, it is assumed to be the suffix of DO name
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"Omulti\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"Omulti\" in PresenceCondition" );
             if( optionalMulti == null ) optionalMulti = new HashSet<>();
             optionalMulti.add( name );
             break;
@@ -158,7 +159,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
             try {
                 Integer arg = Integer.valueOf( presCondArgs );
                 if( arg <= 0 ) {
-                    console.warning( "[NSD setup] argument of PresenceCondition \"AtLeastOne\" is not a positive integer" );
+                    console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"AtLeastOne\" is not a positive integer" );
                     break;
                 }
                 if( ! atLeastOne.containsKey( arg )) {
@@ -168,7 +169,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
                 break;
             }
             catch( NumberFormatException e ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"AtLeastOne\" is not an integer" );
+                console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"AtLeastOne\" is not an integer" );
                 break;
             }
         case "AtMostOne" :
@@ -183,7 +184,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
             try {
                 Integer arg = Integer.valueOf( presCondArgs );
                 if( arg <= 0 ) {
-                    console.warning( "[NSD setup] argument of PresenceCondition \"AllOrNonePerGroup\" is not a positive integer" );
+                    console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"AllOrNonePerGroup\" is not a positive integer" );
                     break;
                 }
                 if( ! allOrNonePerGroup.containsKey( arg )) {
@@ -193,7 +194,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
                 break;
             }
             catch( NumberFormatException e ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"AllOrNonePerGroup\" is not an integer" );
+                console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"AllOrNonePerGroup\" is not an integer" );
                 break;
             }
         case "AllOnlyOneGroup" :
@@ -203,7 +204,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
             try {
                 Integer arg = Integer.valueOf( presCondArgs );
                 if( arg <= 0 ) {
-                    console.warning( "[NSD setup] argument of PresenceCondition \"AllOnlyOneGroup\" is not a positive integer" );
+                    console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"AllOnlyOneGroup\" is not a positive integer" );
                     break;
                 }
                 if( ! allOnlyOneGroup.containsKey( arg )) {
@@ -213,7 +214,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
                 break;
             }
             catch( NumberFormatException e ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"AllOnlyOneGroup\" is not an integer" );
+                console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"AllOnlyOneGroup\" is not an integer" );
                 break;
             }
         case "AllAtLeastOneGroup" :
@@ -223,7 +224,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
             try {
                 Integer arg = Integer.valueOf( presCondArgs );
                 if( arg <= 0 ) {
-                    console.warning( "[NSD setup] argument of PresenceCondition \"AllAtLeastOneGroup\" is not a positive integer" );
+                    console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"AllAtLeastOneGroup\" is not a positive integer" );
                     break;
                 }
                 if( ! allAtLeastOneGroup.containsKey( arg )) {
@@ -233,7 +234,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
                 break;
             }
             catch( NumberFormatException e ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"AllAtLeastOneGroup\" is not an integer" );
+                console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"AllAtLeastOneGroup\" is not an integer" );
                 break;
             }
         case "MF" :
@@ -269,7 +270,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
             try {
                 Integer arg = Integer.valueOf( presCondArgs );
                 if( arg <= 0 ) {
-                    console.warning( "[NSD setup] argument of PresenceCondition \"MOcond\" is not a positive integer" );
+                    console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"MOcond\" is not a positive integer" );
                     break;
                 }
                 mandatoryIfTextConditionElseOptional.put( name, presCondArgs );
@@ -278,7 +279,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
                 break;
             }
             catch( NumberFormatException e ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"MOcond\" is not an integer" );
+                console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"MOcond\" is not an integer" );
                 break;
             }
         case "MFcond" :
@@ -290,7 +291,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
             try {
                 Integer arg = Integer.valueOf( presCondArgs );
                 if( arg <= 0 ) {
-                    console.warning( "[NSD setup] argument of PresenceCondition \"MFcond\" is not a positive integer" );
+                    console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"MFcond\" is not a positive integer" );
                     break;
                 }
                 mandatoryIfTextConditionElseForbidden.put( name, presCondArgs );
@@ -298,7 +299,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
                 break;
             }
             catch( NumberFormatException e ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"MFcond\" is not an integer" );
+                console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"MFcond\" is not an integer" );
                 break;
             }
         case "OFcond" :
@@ -310,7 +311,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
             try {
                 Integer arg = Integer.valueOf( presCondArgs );
                 if( arg <= 0 ) {
-                    console.warning( "[NSD setup] argument of PresenceCondition \"MFcond\" is not a positive integer" );
+                    console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"MFcond\" is not a positive integer" );
                     break;
                 }
                 optionalIfTextConditionElseForbidden.put( name, presCondArgs );
@@ -318,28 +319,28 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
                 break;
             }
             catch( NumberFormatException e ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"MFcond\" is not an integer" );
+                console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"MFcond\" is not an integer" );
                 break;
             }
         case "MmultiRange" :
             // Parameters min, max: limits for instance number (> 0).
             // One or more elements shall be present; all instances have an instance number within range [min, max] (see IEC 61850-7-1)
             // -> TODO: not sure what is the instance number, it is assumed to be the suffix of DO name
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MmultiRange\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MmultiRange\" in PresenceCondition" );
             if( mandatoryMultiRange == null ) mandatoryMultiRange = new HashMap<>();
             String[] limits1 = presCondArgs.split( "[ ,]+" );
             if( limits1.length != 2 ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"MmultiRange\" is not two integers" );
+                console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"MmultiRange\" is not two integers" );
                 break;
             }
             Integer min1 = Integer.valueOf( limits1[0] );
             if( min1 <= 0 ) {
-                console.warning( "[NSD setup] first argument of PresenceCondition \"MmultiRange\" is not a positive integer" );
+                console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") first argument of PresenceCondition \"MmultiRange\" is not a positive integer" );
                 break;
             }
             Integer max1 = Integer.valueOf( limits1[1] );
             if( max1 <= 0 ) {
-                console.warning( "[NSD setup] second argument of PresenceCondition \"MmultiRange\" is not a positive integer" );
+                console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") second argument of PresenceCondition \"MmultiRange\" is not a positive integer" );
                 break;
             }
             mandatoryMultiRange.put( name, Pair.of( min1, max1 ));
@@ -348,21 +349,21 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
             // Parameters min, max: limits for instance number (> 0).
             // Zero or more elements may be present; all instances have an instance number within range [min, max] (see IEC 61850-7-1)
             // -> TODO: not sure what is the instance number, it is assumed to be the suffix of DO name
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"OmultiRange\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"OmultiRange\" in PresenceCondition" );
             if( optionalMultiRange == null ) optionalMultiRange = new HashMap<>();
             String[] limits2 = presCondArgs.split( "[ ,]+" );
             if( limits2.length != 2 ) {
-                console.warning( "[NSD setup] argument of PresenceCondition \"OmultiRange\" is not two integers" );
+                console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") argument of PresenceCondition \"OmultiRange\" is not two integers" );
                 break;
             }
             Integer min2 = Integer.valueOf( limits2[0] );
             if( min2 <= 0 ) {
-                console.warning( "[NSD setup] first argument of PresenceCondition \"OmultiRange\" is not a positive integer" );
+                console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") first argument of PresenceCondition \"OmultiRange\" is not a positive integer" );
                 break;
             }
             Integer max2 = Integer.valueOf( limits2[1] );
             if( max2 <= 0 ) {
-                console.warning( "[NSD setup] second argument of PresenceCondition \"OmultiRange\" is not a positive integer" );
+                console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") second argument of PresenceCondition \"OmultiRange\" is not a positive integer" );
                 break;
             }
             optionalMultiRange.put( name, Pair.of( min2, max2 ));
@@ -370,7 +371,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
         case "MFsubst" :
             // Element is mandatory if substitution is supported (for substitution, see IEC 61850-7-3), otherwise forbidden
             // TODO: how do we know if substitution is supported ?
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MFsubst\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MFsubst\" in PresenceCondition" );
             if( mandatoryIfSubstitutionElseForbidden == null ) mandatoryIfSubstitutionElseForbidden = new HashSet<>();
             mandatoryIfSubstitutionElseForbidden.add( name );
             break;
@@ -387,14 +388,14 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
         case "MOlnNs" :
             // Element is mandatory if the name space of its logical node deviates from the name space of the containing
             // logical device, otherwise optional. See IEC 61850-7-1 for use of name space
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MOlnNs\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MOlnNs\" in PresenceCondition" );
             if( mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional == null ) mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional = new HashSet<>();
             mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional.add( name );
             break;
         case "MOdataNs" :
             // Element is mandatory if the name space of its data object deviates from the name space of its logical node,
             // otherwise optional. See IEC 61850-7-1 for use of name space
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MOdataNs\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MOdataNs\" in PresenceCondition" );
             if( mandatoryIfNameSpaceOfDataObjectDeviatesElseOptional == null ) mandatoryIfNameSpaceOfDataObjectDeviatesElseOptional = new HashSet<>();
             mandatoryIfNameSpaceOfDataObjectDeviatesElseOptional.add( name );
             break;
@@ -402,61 +403,61 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
             // Element is mandatory* if any sibling elements of type AnalogueValue include 'i' as a child, otherwise forbidden.
             // *Even though devices without floating point capability cannot exchange floating point values through ACSI services,
             // the description of scaling remains mandatory for their (SCL) configuration
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MFscaledAV\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MFscaledAV\" in PresenceCondition" );
             if( mandatoryIfAnalogValueIncludesIElseForbidden == null ) mandatoryIfAnalogValueIncludesIElseForbidden = new HashSet<>();
             mandatoryIfAnalogValueIncludesIElseForbidden.add( name );
             break;
         case "MFscaledMagV" :
             // Element is mandatory* if any sibling elements of type Vector include 'i' as a child of their 'mag' attribute, otherwise forbidden.
             // *See MFscaledAV
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MFscaledMagV\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MFscaledMagV\" in PresenceCondition" );
             if( mandatoryIfVectorSiblingIncludesIAsChildMagElseForbidden == null ) mandatoryIfVectorSiblingIncludesIAsChildMagElseForbidden = new HashSet<>();
             mandatoryIfVectorSiblingIncludesIAsChildMagElseForbidden.add( name );
             break;
         case "MFscaledAngV" :
             // Element is mandatory* if any sibling elements of type Vector include 'i' as a child of their 'ang' attribute, otherwise forbidden.
             // *See MFscaledAV
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MFscaledAngV\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MFscaledAngV\" in PresenceCondition" );
             if( mandatoryIfVectorSiblingIncludesIAsChildAngElseForbidden == null ) mandatoryIfVectorSiblingIncludesIAsChildAngElseForbidden = new HashSet<>();
             mandatoryIfVectorSiblingIncludesIAsChildAngElseForbidden.add( name );
             break;
         case "MOrms" :
             // Element is mandatory if the harmonic values in the context are calculated as a ratio to RMS value
             // (value of data attribute 'hvRef' is 'rms'), optional otherwise
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MOrms\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MOrms\" in PresenceCondition" );
             if( mandatoryIfHarmonicValuesCalculatedAsRatioElseOptional == null ) mandatoryIfHarmonicValuesCalculatedAsRatioElseOptional = new HashSet<>();
             mandatoryIfHarmonicValuesCalculatedAsRatioElseOptional.add( name );
             break;
         case "MOrootLD" :
             // Element is mandatory in the context of a root logical device; otherwise it is optional
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MOrootLD\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MOrootLD\" in PresenceCondition" );
             if( mandatoryInRootLogicalDeviceElseOptional == null ) mandatoryInRootLogicalDeviceElseOptional = new HashSet<>();
             mandatoryInRootLogicalDeviceElseOptional.add( name );
             break;
         case "MOoperTm" :
             // Element is mandatory if at least one controlled object on the IED supports time activation service; otherwise it is optional
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MOoperTm\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MOoperTm\" in PresenceCondition" );
             if( mandatoryIfControlSupportsTimeElseOptional == null ) mandatoryIfControlSupportsTimeElseOptional = new HashSet<>();
             mandatoryIfControlSupportsTimeElseOptional.add( name );
             break;
         case "MmultiF" :
             // Parameter sibling: sibling element name.
             // One or more elements must be present if sibling element is present, otherwise forbidden
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MmultiF\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MmultiF\" in PresenceCondition" );
             if( oneOrMoreIfSiblingPresentElseForbidden == null ) oneOrMoreIfSiblingPresentElseForbidden = new HashMap<>();
             oneOrMoreIfSiblingPresentElseForbidden.put( name, presCondArgs );
             break;
         case "MOsbo" :
             // Element is mandatory if declared control model supports 'sbo-with-normal-security' or 'sbo-with-enhanced-security',
             // otherwise optional and value is of no impact
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MOsbo\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MOsbo\" in PresenceCondition" );
             if( mandatoryIfControlSupportsSecurity1ElseOptional == null ) mandatoryIfControlSupportsSecurity1ElseOptional = new HashSet<>();
             mandatoryIfControlSupportsSecurity1ElseOptional.add( name );
             break;
         case "MOenhanced" :
             // Element is mandatory if declared control model supports 'direct-with-enhanced-security' or 'sbo-with-enhanced-security',
             // otherwise optional and value is of no impact
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MOenhanced\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MOenhanced\" in PresenceCondition" );
             if( mandatoryIfControlSupportsSecurity2ElseOptional == null ) mandatoryIfControlSupportsSecurity2ElseOptional = new HashSet<>();
             mandatoryIfControlSupportsSecurity2ElseOptional.add( name );
             break;
@@ -464,7 +465,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
             // Element is mandatory if the name space of its logical node deviates from the name space of the containing
             // logical device, otherwise optional. See IEC 61850-7-1 for use of name space
             // TODO: same as "MOlnNs" ?
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MONamPlt\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MONamPlt\" in PresenceCondition" );
             if( mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional2 == null ) mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional2 = new HashSet<>();
             mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional2.add( name );
             break;
@@ -477,18 +478,18 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
         case "MORange" :
             // Element is mandatory if the measured value associated (amplitude respectively angle) exposes the range eventing
             // (with the attribute range respectively rangeAng)
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MORange\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"MORange\" in PresenceCondition" );
             if( mandatoryIfMeasuredValueExposesRange == null ) mandatoryIfMeasuredValueExposesRange = new HashSet<>();
             mandatoryIfMeasuredValueExposesRange.add( name );
             break;
         case "OMSynPh" :
             // This attribute is optional if value of 'phsRef'' is Synchrophasor otherwise Mandatory]]></Doc>
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"OMSynPh\" in PresenceCondition" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") NOT IMPLEMENTED: " + getNsdComponentClassName() + " " + name + " declared as \"OMSynPh\" in PresenceCondition" );
             if( optionalIfPhsRefIsSynchrophasorElseMandatory == null ) optionalIfPhsRefIsSynchrophasorElseMandatory = new HashSet<>();
             optionalIfPhsRefIsSynchrophasorElseMandatory.add( name );
             break;
         default:
-            console.warning( "[NSD setup] the PresenceCondition " + presCond + " of AnyLNClass " + name + " is unknown" );
+            console.warning( "[NSD setup] (" + fileName + ":" + lineNumber + ") the PresenceCondition " + presCond + " of AnyLNClass " + name + " is unknown" );
             break;
         }
         
@@ -564,7 +565,7 @@ public abstract class GenericPresenceConditionValidator< NsdModel extends NsdObj
         return true;
     }
     
-    public boolean validate( SclModel sclModel, DiagnosticChain diagnostics ) {
+    public boolean validate( @NonNull SclModel sclModel, DiagnosticChain diagnostics ) {
         AbstractRiseClipseConsole.getConsole().verbose( "[NSD validation] OldDataAttributePresenceConditionValidator.validate() at line " + sclModel.getLineNumber() );
 
         boolean res = true;
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/LNClassValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/LNClassValidator.java
index 228059f..b8c1a61 100644
--- a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/LNClassValidator.java
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/LNClassValidator.java
@@ -58,10 +58,10 @@ public class LNClassValidator {
             for( DataObject do_ : lnClass.getDataObject() ) {
                 if( CDCValidator.get( do_.getType() ) != null ) {
                     dataObjectValidatorMap.put( do_.getName(), CDCValidator.get( do_.getType() ));
-                    AbstractRiseClipseConsole.getConsole().verbose( "[NSD setup] CDC for DataObject " + do_.getName() + " found with type " + do_.getType() );
+                    AbstractRiseClipseConsole.getConsole().verbose( "[NSD setup] (" + do_.getFilename() + ":" + do_.getLineNumber() + ") CDC for DataObject " + do_.getName() + " found with type " + do_.getType() );
                 }
                 else {
-                    AbstractRiseClipseConsole.getConsole().warning( "[NSD setup] CDC for DataObject " + do_.getName() + " not found" );
+                    AbstractRiseClipseConsole.getConsole().warning( "[NSD setup] (" + do_.getFilename() + ":" + do_.getLineNumber() + ") CDC not found for DataObject " + do_.getName() );
                 }
             }
 
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/SubDataAttributePresenceConditionValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/SubDataAttributePresenceConditionValidator.java
index 67af54a..e1b2687 100644
--- a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/SubDataAttributePresenceConditionValidator.java
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/SubDataAttributePresenceConditionValidator.java
@@ -53,7 +53,7 @@ public class SubDataAttributePresenceConditionValidator extends GenericPresenceC
         constructedAttribute
         .getSubDataAttribute()
         .stream()
-        .forEach( sda -> addSpecification( sda.getName(), sda.getPresCond(), sda.getPresCondArgs(), sda.getRefersToPresCondArgsDoc() ) );
+        .forEach( sda -> addSpecification( sda.getName(), sda.getPresCond(), sda.getPresCondArgs(), sda.getRefersToPresCondArgsDoc(), sda.getLineNumber(), sda.getFilename() )); 
     }
     
     @Override
@@ -66,6 +66,11 @@ public class SubDataAttributePresenceConditionValidator extends GenericPresenceC
         return constructedAttribute.getName();
     }
 
+    @Override
+    protected int getNsdModelLineNumber() {
+        return constructedAttribute.getLineNumber();
+    }
+
     @Override
     protected String getNsdModelClassName() {
         return "ConstructedAttribute";
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/SubDataObjectPresenceConditionValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/SubDataObjectPresenceConditionValidator.java
index 64d95c9..8085186 100644
--- a/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/SubDataObjectPresenceConditionValidator.java
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.validator/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/SubDataObjectPresenceConditionValidator.java
@@ -58,7 +58,7 @@ public class SubDataObjectPresenceConditionValidator extends GenericPresenceCond
         cdc
         .getSubDataObject()
         .stream()
-        .forEach( sda -> addSpecification( sda.getName(), sda.getPresCond(), sda.getPresCondArgs(), sda.getRefersToPresCondArgsDoc() ));
+        .forEach( sda -> addSpecification( sda.getName(), sda.getPresCond(), sda.getPresCondArgs(), sda.getRefersToPresCondArgsDoc(), sda.getLineNumber(), sda.getFilename() )); 
     }
 
     @Override
@@ -71,6 +71,11 @@ public class SubDataObjectPresenceConditionValidator extends GenericPresenceCond
         return cdc.getName();
     }
 
+    @Override
+    protected int getNsdModelLineNumber() {
+        return cdc.getLineNumber();
+    }
+
     @Override
     protected String getNsdModelClassName() {
         return "CDC";
@@ -178,5 +183,4 @@ public class SubDataObjectPresenceConditionValidator extends GenericPresenceCond
         return res;
     }
 
-
 }
-- 
GitLab