From cf4efceb5ab76626f82dda896d0a5e438ccb3827 Mon Sep 17 00:00:00 2001 From: Dominique Marcadet <Dominique.Marcadet@centralesupelec.fr> Date: Thu, 30 May 2019 11:43:26 +0200 Subject: [PATCH] take into aaccount .snsd and .AppNS --- .../iec61850/nsd/util/NsdResourceSetImpl.java | 182 ++++++++++++++++-- 1 file changed, 162 insertions(+), 20 deletions(-) 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 63c2439..1998ef9 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; } + } -- GitLab