diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.nsd/src/fr/centralesupelec/edf/riseclipse/iec61850/nsd/util/NsdResourceSetImpl.java b/fr.centralesupelec.edf.riseclipse.iec61850.nsd/src/fr/centralesupelec/edf/riseclipse/iec61850/nsd/util/NsdResourceSetImpl.java
index 63c24390db51bb3ad44fa1aafd8faec62a4c2e70..1998ef94af2847b0f0c7a526064e647f51134f56 100644
--- a/fr.centralesupelec.edf.riseclipse.iec61850.nsd/src/fr/centralesupelec/edf/riseclipse/iec61850/nsd/util/NsdResourceSetImpl.java
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.nsd/src/fr/centralesupelec/edf/riseclipse/iec61850/nsd/util/NsdResourceSetImpl.java
@@ -20,10 +20,13 @@
 package fr.centralesupelec.edf.riseclipse.iec61850.nsd.util;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import org.eclipse.emf.common.util.URI;
@@ -31,12 +34,16 @@ import org.eclipse.emf.ecore.resource.Resource;
 
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.Abbreviation;
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.Abbreviations;
+import fr.centralesupelec.edf.riseclipse.iec61850.nsd.AgAttributeType;
+import fr.centralesupelec.edf.riseclipse.iec61850.nsd.ApplicableServiceNS;
+import fr.centralesupelec.edf.riseclipse.iec61850.nsd.AppliesToType;
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.BasicType;
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.BasicTypes;
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.CDC;
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.CDCs;
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.ConstructedAttribute;
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.ConstructedAttributes;
+import fr.centralesupelec.edf.riseclipse.iec61850.nsd.DataAttribute;
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.Doc;
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.DocumentRoot;
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.Enumeration;
@@ -50,6 +57,9 @@ import fr.centralesupelec.edf.riseclipse.iec61850.nsd.NSDoc;
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.NsdPackage;
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.PresenceCondition;
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.PresenceConditions;
+import fr.centralesupelec.edf.riseclipse.iec61850.nsd.ServiceCDC;
+import fr.centralesupelec.edf.riseclipse.iec61850.nsd.ServiceNS;
+import fr.centralesupelec.edf.riseclipse.iec61850.nsd.ServiceNsUsage;
 import fr.centralesupelec.edf.riseclipse.util.AbstractRiseClipseConsole;
 import fr.centralesupelec.edf.riseclipse.util.IRiseClipseConsole;
 import fr.centralesupelec.edf.riseclipse.util.RiseClipseMetamodel;
@@ -58,16 +68,25 @@ import fr.centralesupelec.edf.riseclipse.util.AbstractRiseClipseResourceSet;
 
 public class NsdResourceSetImpl extends AbstractRiseClipseResourceSet {
     
-    private Map< NsIdentification, NS > nsdResources;
-    private Map< NsIdentification, NSDoc > nsdocResources;
-    private NsdResourceFactoryImpl resourceFactory;
+    private Map< NsIdentification, NS > nsdResources = new HashMap<>();
+    private Map< NsIdentification, ServiceNS > serviceNSResources = new HashMap<>();
+    private Map< NsIdentification, NSDoc > nsdocResources = new HashMap<>();
+    private NsdResourceFactoryImpl resourceFactory = new NsdResourceFactoryImpl();
+    private ApplicableServiceNS appNS =  null;
+    private Map< NsIdentification, List< ServiceNS > > nsdAdditions = new HashMap<>();
+    private Map< NsIdentification, NsIdentification > equivalentNamespaces = new HashMap<>();
 
     public NsdResourceSetImpl( boolean strictContent, IRiseClipseConsole console ) {
         super( strictContent, console );
         
-        nsdResources = new HashMap<>();
-        nsdocResources = new HashMap<>();
-        resourceFactory = new NsdResourceFactoryImpl();
+        setEquivalentNamespace(
+                new NsIdentification( "IEC 61850-7-2", 2007, "B", 1 ), 
+                new NsIdentification( "IEC 61850-7-3", 2007, "B", 1 )
+        );
+        setEquivalentNamespace(
+                new NsIdentification( "IEC 61850-7-3", 2007, "B", 1 ), 
+                new NsIdentification( "IEC 61850-7-4", 2007, "B", 1 )
+        );
     }
 
     @Override
@@ -94,17 +113,39 @@ public class NsdResourceSetImpl extends AbstractRiseClipseResourceSet {
             return;
         }
         DocumentRoot root = (DocumentRoot) resource.getContents().get( 0 );
+        
         if( root.getNS() != null ) {
-            NS ns = ( NS ) root.getNS();
-            NsIdentification id = new NsIdentification( ns );
+            NsIdentification id = new NsIdentification( root.getNS() );
             if( nsdResources.get( id ) != null ) {
                 AbstractRiseClipseConsole.getConsole().error( "There is already an NSD file with NsIdentification " + id + ", " + resource.getURI() + " is ignored" );
                 this.getResources().remove( resource );
                 return;
             }
-            nsdResources.put( id, ns );
+            nsdResources.put( id, root.getNS() );
+            return;
+        }
+        
+        if( root.getServiceNS() != null ) {
+            NsIdentification id = new NsIdentification( root.getServiceNS() );
+            if( serviceNSResources.get( id ) != null ) {
+                AbstractRiseClipseConsole.getConsole().error( "There is already an NSD file with NsIdentification " + id + ", " + resource.getURI() + " is ignored" );
+                this.getResources().remove( resource );
+                return;
+            }
+            serviceNSResources.put( id, root.getServiceNS() );
+            return;
+        }
+        
+        if( root.getApplicableServiceNS() != null ) {
+            if( appNS != null ) {
+                AbstractRiseClipseConsole.getConsole().error( "There is already an ApplicableServiceNS file, " + resource.getURI() + " is ignored" );
+                this.getResources().remove( resource );
+                return;
+            }
+            appNS = root.getApplicableServiceNS();
             return;
         }
+        
         if( root.getNSDoc() != null ) {
             NSDoc nsdoc = ( NSDoc ) root.getNSDoc();
             NsIdentification id = new NsIdentification( nsdoc );
@@ -116,17 +157,79 @@ public class NsdResourceSetImpl extends AbstractRiseClipseResourceSet {
             nsdocResources.put( id, nsdoc );
             return;
         }
+        
         AbstractRiseClipseConsole.getConsole().error( "The file " + resource.getURI() + " is not an NSD file" );
         this.getResources().remove( resource );
         return;
     }
-
+    
     /* (non-Javadoc)
      * @see fr.centralesupelec.edf.riseclipse.util.AbstractRiseClipseResourceSet#finalizeLoad(fr.centralesupelec.edf.riseclipse.util.IRiseClipseConsole)
      */
     @Override
     public void finalizeLoad( IRiseClipseConsole console ) {
+        if( appNS != null ) {
+            for( ServiceNsUsage serviceNsUsage : appNS.getServiceNsUsage() ) {
+                NsIdentification serviceNsId = new NsIdentification( serviceNsUsage );
+                if( serviceNSResources.get( serviceNsId ) != null ) {
+                    for( AppliesToType applyTo : serviceNsUsage.getAppliesTo() ) {
+                        NsIdentification nsId = new NsIdentification( applyTo );
+                        nsId = getRootNsIdentification( nsId );
+                        if( nsdResources.get( nsId ) != null ) {
+                            if( nsdAdditions.get( nsId ) == null ) {
+                                nsdAdditions.put( nsId, new ArrayList<>() );
+                            }
+                            nsdAdditions.get( nsId ).add( serviceNSResources.get( serviceNsId ));
+                            applyServiceNs( serviceNSResources.get( serviceNsId ), nsdResources.get( nsId ), nsId );
+                        }
+                    }
+                }
+            }
+        }
+        
         buildExplicitLinks( console );
+        
+    }
+
+    private void applyServiceNs( ServiceNS serviceNS, NS ns, NsIdentification nsIdentification ) {
+        // A ServiceTypeRealization gives a new definition to an existing (only basic ? never constructed ?) type
+        for( ConstructedAttribute typeRealization : serviceNS.getServiceTypeRealizations().getServiceTypeRealization() ) {
+            BasicType basic = findBasicType( typeRealization.getName(), nsIdentification, console );
+            if( basic != null ) {
+                // Avoid ConcurrentModificationException
+                List< AgAttributeType > atts = basic
+                        .getReferredByAttributeType()
+                        .stream()
+                        .collect( Collectors.toList() );
+               for( AgAttributeType att : atts ) {
+                    att.unsetRefersToBasicType();
+                    console.info( "Service NS: using TypeRealization " + basic.getName() + " to attribute " + att.getType() );
+                    att.setRefersToConstructedAttribute( typeRealization );
+                }
+                continue;
+            }
+            // TODO: warning
+        }
+        
+        // A ServiceConstructedAttribute defines new ConstructedAttribute:
+        // they are taken into account in getConstructedAttributeStream()
+        
+        // A ServiceCDC add new attribute to an existing CDC
+        for( ServiceCDC serviceCDC : serviceNS.getServiceCDCs().getServiceCDC() ) {
+            CDC cdc = findCDC( serviceCDC.getCdc(), nsIdentification, console );
+            if( cdc != null ) {
+                serviceCDC
+                .getServiceDataAttribute()
+                .stream()
+                .forEach( att -> {
+                    DataAttribute da = att.toDataAttribute();
+                    console.info( "Service NS: Adding DataAttribute " + da.getName() + " to CDC " + cdc.getName() );
+                    da.setParentCDC( cdc );
+                });
+            }
+                    
+        }
+        
     }
 
     /*
@@ -170,10 +273,22 @@ public class NsdResourceSetImpl extends AbstractRiseClipseResourceSet {
         }
         
     }
+    
+    public void setEquivalentNamespace( NsIdentification source, NsIdentification destination ) {
+        equivalentNamespaces.put( source, destination );
+    }
+    
+    public NsIdentification getRootNsIdentification( NsIdentification id ) {
+        // TODO: check conformance with DependsOn
+        while( equivalentNamespaces.containsKey( id )) {
+            id = equivalentNamespaces.get( id );
+        }
+        return id;
+    }
 
     public NS getNS( NsIdentification id ) {
         return nsdResources.get( id );
-    }
+   }
 
     /*
      * Constraints : when DONE, as OCLinEcore in nsd.ecore
@@ -313,7 +428,7 @@ public class NsdResourceSetImpl extends AbstractRiseClipseResourceSet {
     }
 
     public LNClass findLNClass( String lnClass, NsIdentification nsIdentification, IRiseClipseConsole console ) {
-        return getLNClassStream( nsIdentification )
+        return getLNClassStream( getRootNsIdentification( nsIdentification ))
                 .filter( c -> c.getName().equals( lnClass ) )
                 .findAny()
                 .orElse( null );
@@ -350,7 +465,7 @@ public class NsdResourceSetImpl extends AbstractRiseClipseResourceSet {
     }
 
     public Abbreviation findAbbreviation( String abb, NsIdentification nsIdentification, IRiseClipseConsole console ) {
-        return getAbbreviationStream( nsIdentification )
+        return getAbbreviationStream( getRootNsIdentification( nsIdentification ))
                 .filter( a -> a.getName().equals( abb ) )
                 .findAny()
                 .orElse( null );
@@ -387,7 +502,7 @@ public class NsdResourceSetImpl extends AbstractRiseClipseResourceSet {
     }
 
     public Enumeration findEnumeration( String en, NsIdentification nsIdentification, IRiseClipseConsole console ) {
-        return getEnumerationStream( nsIdentification )
+        return getEnumerationStream( getRootNsIdentification( nsIdentification ))
                 .filter( e -> e.getName().equals( en ) )
                 .findAny()
                 .orElse( null );
@@ -424,7 +539,7 @@ public class NsdResourceSetImpl extends AbstractRiseClipseResourceSet {
     }
 
     public CDC findCDC( String cdc, NsIdentification nsIdentification, IRiseClipseConsole console ) {
-        return getCDCStream( nsIdentification )
+        return getCDCStream( getRootNsIdentification( nsIdentification ))
                 .filter( c -> c.getName().equals( cdc ) )
                 .findAny()
                 .orElse( null );
@@ -457,11 +572,24 @@ public class NsdResourceSetImpl extends AbstractRiseClipseResourceSet {
                 constructedAttributeStream = tmp;
             }
         }
+        if( nsdAdditions.get( identification ) != null ) {
+            // We add ServiceTypeRealizations instead of replacing existing (basic ?) type, but
+            // the latter will be replaced in the map because of the identical name
+            // This is OK in TypeValidator but may not work in other usages
+            for( ServiceNS add : nsdAdditions.get( identification )) {
+                Stream< ConstructedAttribute > tmp = Stream.concat( constructedAttributeStream, add.getServiceTypeRealizations().getServiceTypeRealization().stream() );
+                constructedAttributeStream = tmp;
+            }
+            for( ServiceNS add : nsdAdditions.get( identification )) {
+                Stream< ConstructedAttribute > tmp = Stream.concat( constructedAttributeStream, add.getServiceConstructedAttributes().getServiceConstructedAttribute().stream() );
+                constructedAttributeStream = tmp;
+            }
+        }
         return constructedAttributeStream;
     }
 
     public ConstructedAttribute findConstructedAttribute( String att, NsIdentification nsIdentification, IRiseClipseConsole console ) {
-        return getConstructedAttributeStream( nsIdentification )
+        return getConstructedAttributeStream( getRootNsIdentification( nsIdentification ))
                 .filter( c -> c.getName().equals( att ) )
                 .findAny()
                 .orElse( null );
@@ -498,7 +626,7 @@ public class NsdResourceSetImpl extends AbstractRiseClipseResourceSet {
     }
 
     public BasicType findBasicType( String basic, NsIdentification nsIdentification, IRiseClipseConsole console ) {
-        return getBasicTypeStream( nsIdentification )
+        return getBasicTypeStream( getRootNsIdentification( nsIdentification ))
                 .filter( b -> b.getName().equals( basic ) )
                 .findAny()
                 .orElse( null );
@@ -531,14 +659,21 @@ public class NsdResourceSetImpl extends AbstractRiseClipseResourceSet {
                 functionalConstraintStream = tmp;
             }
         }
+        if( nsdAdditions.get( identification ) != null ) {
+            for( ServiceNS add : nsdAdditions.get( identification )) {
+                Stream< FunctionalConstraint > tmp = Stream.concat( functionalConstraintStream, add.getFunctionalConstraints().getFunctionalConstraint().stream() );
+                functionalConstraintStream = tmp;
+            }
+        }
         return functionalConstraintStream;
     }
 
     public FunctionalConstraint findFunctionalConstraint( String fc, NsIdentification nsIdentification, IRiseClipseConsole console ) {
-        return getFunctionalConstraintStream( nsIdentification )
-                .filter( f -> f.getAbbreviation().equals( fc ) )
+        FunctionalConstraint res = getFunctionalConstraintStream( getRootNsIdentification( nsIdentification ))
+                .filter( f -> f.getAbbreviation().equals( fc ))
                 .findAny()
                 .orElse( null );
+        return res;
     }
     
     public Stream< PresenceCondition > getAllPresenceConditionStream() {
@@ -568,11 +703,17 @@ public class NsdResourceSetImpl extends AbstractRiseClipseResourceSet {
                 presenceConditionStream = tmp;
             }
         }
+        if( nsdAdditions.get( identification ) != null ) {
+            for( ServiceNS add : nsdAdditions.get( identification )) {
+                Stream< PresenceCondition > tmp = Stream.concat( presenceConditionStream, add.getPresenceConditions().getPresenceCondition().stream() );
+                presenceConditionStream = tmp;
+            }
+        }
         return presenceConditionStream;
     }
 
     public PresenceCondition findPresenceCondition( String presence, NsIdentification nsIdentification, IRiseClipseConsole console ) {
-        return getPresenceConditionStream( nsIdentification )
+        return getPresenceConditionStream( getRootNsIdentification( nsIdentification ))
                 .filter( p -> p.getName().equals( presence ) )
                 .findAny()
                 .orElse( null );
@@ -591,6 +732,7 @@ public class NsdResourceSetImpl extends AbstractRiseClipseResourceSet {
         }
         return null;
     }
+
 }