Skip to content

Commit

Permalink
Fix visitor for traversing aspect models and LanguageCollector
Browse files Browse the repository at this point in the history
  • Loading branch information
atextor committed Oct 13, 2023
1 parent cb4a5d6 commit d4481fa
Show file tree
Hide file tree
Showing 13 changed files with 343 additions and 201 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
/**
* The AspectContext wraps a loaded/resolved Aspect Model and a single Aspect that was instantiated from this model, i.e.,
* which must be defined in the RDF model.
*
* @param rdfModel the RDF model
* @param aspect the Aspect
*/
public record AspectContext(VersionedModel rdfModel, Aspect aspect) {
public record AspectContext( VersionedModel rdfModel, Aspect aspect ) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,27 @@
import java.util.stream.Stream;

import org.eclipse.esmf.characteristic.Either;
import org.eclipse.esmf.characteristic.Enumeration;
import org.eclipse.esmf.characteristic.Quantifiable;
import org.eclipse.esmf.characteristic.StructuredValue;
import org.eclipse.esmf.characteristic.Trait;
import org.eclipse.esmf.metamodel.AbstractEntity;
import org.eclipse.esmf.metamodel.Aspect;
import org.eclipse.esmf.metamodel.Characteristic;
import org.eclipse.esmf.metamodel.CollectionValue;
import org.eclipse.esmf.metamodel.ComplexType;
import org.eclipse.esmf.metamodel.Entity;
import org.eclipse.esmf.metamodel.EntityInstance;
import org.eclipse.esmf.metamodel.ModelElement;
import org.eclipse.esmf.metamodel.Operation;
import org.eclipse.esmf.metamodel.Property;
import org.eclipse.esmf.metamodel.QuantityKind;
import org.eclipse.esmf.metamodel.StructureElement;
import org.eclipse.esmf.metamodel.Unit;

/**
* Aspect Meta Model visitor that recursively traverses all elements of the model
*/
public class AspectStreamTraversalVisitor implements AspectVisitor<Stream<ModelElement>, Void> {

private final Set<ModelElement> hasVisited = new HashSet<>();

@Override
Expand All @@ -49,28 +50,32 @@ public Stream<ModelElement> visitBase( final ModelElement modelElement, final Vo

@Override
public Stream<ModelElement> visitStructureElement( final StructureElement structureElement, final Void context ) {
return Stream.concat( Stream.of( structureElement ),
return Stream.concat(
Stream.of( structureElement ),
visit( structureElement.getProperties() ) );
}

@Override
public Stream<ModelElement> visitAspect( final Aspect aspect, final Void context ) {
return Stream.concat(
visitStructureElement( aspect, null ),
visit( aspect.getOperations() ) );
return Stream.of(
visitStructureElement( aspect, null ),
visit( aspect.getEvents() ),
visit( aspect.getOperations() ) )
.flatMap( Function.identity() );
}

@SuppressWarnings( "squid:S2250" )
//Amount of elements in list is in regard to amount of properties in aspect model. Even in bigger aspects this should not lead to performance issues
//Amount of elements in list is in regard to amount of properties in aspect model. Even in bigger aspects this should not lead to
// performance issues
@Override
public Stream<ModelElement> visitProperty( final Property property, final Void context ) {
if ( hasVisited.contains( property ) ) {
return Stream.of( property );
return Stream.empty();
}
hasVisited.add( property );
final Stream<ModelElement> characteristicResult = visit( property.getCharacteristic() );
final Stream<ModelElement> extendsResult = visit( property.getExtends() );
return Stream.of( Stream.<ModelElement> of( property ), characteristicResult, extendsResult
return Stream.of( Stream.<ModelElement> of( property ),
visit( property.getCharacteristic() ),
visit( property.getExtends() )
).flatMap( Function.identity() );
}

Expand All @@ -82,12 +87,18 @@ public Stream<ModelElement> visitOperation( final Operation operation, final Voi
.reduce( Stream.empty(), Stream::concat );
}

@Override
public Stream<ModelElement> visitCharacteristic( final Characteristic characteristic, final Void context ) {
return Stream.concat( Stream.of( characteristic ),
visit( characteristic.getDataType() ) );
}

@Override
public Stream<ModelElement> visitEither( final Either either, final Void context ) {
return Stream.of(
visitCharacteristic( (Characteristic) either, null ),
either.getLeft().accept( this, null ),
either.getRight().accept( this, null ),
visitCharacteristic( either, null )
either.getRight().accept( this, null )
).flatMap( Function.identity() );
}

Expand All @@ -97,38 +108,31 @@ public Stream<ModelElement> visitUnit( final Unit unit, final Void context ) {
visit( unit.getQuantityKinds() ) );
}

@Override
public Stream<ModelElement> visitQuantityKind( final QuantityKind quantityKind, final Void context ) {
return Stream.of( quantityKind );
}

@Override
public Stream<ModelElement> visitQuantifiable( final Quantifiable quantifiable, final Void context ) {
return Stream.concat(
visit( quantifiable.getUnit() ),
visitCharacteristic( quantifiable, null )
visitCharacteristic( (Characteristic) quantifiable, null ),
visit( quantifiable.getUnit() )
);
}

@Override
public Stream<ModelElement> visitTrait( final Trait trait, final Void context ) {
return Stream.concat(
visitCharacteristic( trait.getBaseCharacteristic(), null ),
visit( trait.getConstraints() ) );
}

@Override
public Stream<ModelElement> visitCharacteristic( final Characteristic characteristic, final Void context ) {
return Stream.concat( Stream.of( characteristic ),
visit( characteristic.getDataType() ) );
return Stream.of(
visitCharacteristic( (Characteristic) trait, null ),
trait.getBaseCharacteristic().accept( this, null ),
visit( trait.getConstraints() ) )
.flatMap( Function.identity() );
}

@Override
public Stream<ModelElement> visitStructuredValue( final StructuredValue structuredValue, final Void context ) {
return Stream.concat( Stream.of( structuredValue ),
structuredValue.getElements().stream().filter( Property.class::isInstance )
.map( Property.class::cast )
.flatMap( property -> property.accept( this, null ) ) );
return Stream.of(
visitCharacteristic( (Characteristic) structuredValue, null ),
structuredValue.getElements().stream().filter( Property.class::isInstance )
.map( Property.class::cast )
.flatMap( property -> property.accept( this, null ) ) )
.flatMap( Function.identity() );
}

@Override
Expand All @@ -144,27 +148,56 @@ public Stream<ModelElement> visitAbstractEntity( final AbstractEntity abstractEn
@Override
public Stream<ModelElement> visitComplexType( final ComplexType entity, final Void context ) {
if ( hasVisited.contains( entity ) ) {
return Stream.of( entity );
return Stream.empty();
}
hasVisited.add( entity );
return Stream.of(
visitStructureElement( entity, null ),
visit( entity.getExtendingElements() ),
visit( entity.getExtends() ) )
.flatMap( Function.identity() );
}

final Stream<ModelElement> complexTypeWithPropertiesStream = Stream.concat(
Stream.of( entity ),
visit( entity.getProperties() ) );
@Override
public Stream<ModelElement> visitEnumeration( final Enumeration enumeration, final Void context ) {
return Stream.concat(
visitCharacteristic( (Characteristic) enumeration, null ),
visit( enumeration.getValues() ) );
}

@Override
public Stream<ModelElement> visitCollectionValue( final CollectionValue collectionValue, final Void context ) {
return Stream.concat(
complexTypeWithPropertiesStream,
Stream.concat(
visit( entity.getExtends() ),
visit( entity.getExtendingElements() ) ) );
Stream.of( collectionValue ),
visit( collectionValue.getValues() ) );
}

@Override
public Stream<ModelElement> visitCollection( final org.eclipse.esmf.characteristic.Collection collection, final Void context ) {
return Stream.concat(
visitCharacteristic( (Characteristic) collection, null ),
visit( collection.getElementCharacteristic() ) );
}

@Override
public Stream<ModelElement> visitEntityInstance( final EntityInstance instance, final Void context ) {
if ( hasVisited.contains( instance ) ) {
return Stream.empty();
}
hasVisited.add( instance );
return Stream.of(
Stream.of( instance ),
instance.getEntityType().accept( this, null ),
visit( instance.getAssertions().values() )
).flatMap( Function.identity() );
}

private <T extends ModelElement> Stream<ModelElement> visit( Collection<T> collection ) {
private <T extends ModelElement> Stream<ModelElement> visit( final Collection<T> collection ) {
return collection.stream().flatMap( item -> item.accept( this, null ) );
}

@SuppressWarnings( "OptionalUsedAsFieldOrParameterType" )
private <T extends ModelElement> Stream<ModelElement> visit( Optional<T> optional ) {
private <T extends ModelElement> Stream<ModelElement> visit( final Optional<T> optional ) {
return optional.stream().flatMap( item -> item.accept( this, null ) );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,42 @@
import java.util.stream.Stream;

import org.eclipse.esmf.characteristic.Collection;
import org.eclipse.esmf.characteristic.Quantifiable;
import org.eclipse.esmf.characteristic.Trait;
import org.eclipse.esmf.metamodel.Aspect;
import org.eclipse.esmf.metamodel.Characteristic;
import org.eclipse.esmf.metamodel.Entity;
import org.eclipse.esmf.metamodel.ModelElement;
import org.eclipse.esmf.metamodel.NamedElement;
import org.eclipse.esmf.metamodel.Operation;
import org.eclipse.esmf.metamodel.Property;
import org.eclipse.esmf.metamodel.QuantityKind;
import org.eclipse.esmf.metamodel.Unit;
import org.eclipse.esmf.metamodel.datatypes.LangString;

import com.google.common.collect.Sets;

/**
* Aspect Model Visitor that retrieves all used Locales in an Aspect Model
*
* @deprecated Use org.eclipse.esmf.aspectmodel.generator.LanguageCollector instead
*/
@Deprecated( forRemoval = true )
public class LanguageCollectorModelVisitor implements AspectVisitor<Set<Locale>, Set<Locale>> {
@Override
public Set<Locale> visitBase( final ModelElement modelElement, final Set<Locale> context ) {
if ( modelElement instanceof final NamedElement described ) {
return visitIsDescribed( described, context );
}
return context;
}

@Override
public Set<Locale> visitCharacteristic( final Characteristic characteristic, final Set<Locale> context ) {
return Stream.of(
Stream.of( visitIsDescribed( characteristic, context ) ),
characteristic.getDataType().stream().map( type -> type.accept( this, Collections.emptySet() ) ) )
.reduce( Stream.empty(), Stream::concat ).reduce( context, Sets::union );
}

public Set<Locale> visitIsDescribed( final NamedElement element, final Set<Locale> context ) {
return Stream.concat(
element.getPreferredNames().stream().map( LangString::getLanguageTag ),
Expand All @@ -54,15 +68,17 @@ public Set<Locale> visitAspect( final Aspect aspect, final Set<Locale> context )
return Stream.of(
Stream.of( visitIsDescribed( aspect, nestedContext ) ),
aspect.getProperties().stream().map( property -> property.accept( this, Collections.emptySet() ) ),
aspect.getOperations().stream().map( operation -> operation.accept( this, Collections.emptySet() ) ) )
aspect.getOperations().stream().map( operation -> operation.accept( this, Collections.emptySet() ) ),
aspect.getEvents().stream().map( event -> event.accept( this, Collections.emptySet() ) ) )
.reduce( Stream.empty(), Stream::concat ).reduce( nestedContext, Sets::union );
}

@Override
public Set<Locale> visitProperty( final Property property, final Set<Locale> context ) {
return Stream.of(
Stream.of( visitIsDescribed( property, context ) ),
property.getCharacteristic().stream().map( characteristic -> characteristic.accept( this, Collections.emptySet() ) ) )
property.getCharacteristic().stream().map( characteristic -> characteristic.accept( this, Collections.emptySet() ) ),
property.getExtends().stream().map( superProperty -> superProperty.accept( this, Collections.emptySet() ) ) )
.reduce( Stream.empty(), Stream::concat ).reduce( context, Sets::union );
}

Expand All @@ -89,23 +105,27 @@ public Set<Locale> visitTrait( final Trait trait, final Set<Locale> context ) {
public Set<Locale> visitEntity( final Entity entity, final Set<Locale> context ) {
return Stream.of(
Stream.of( visitIsDescribed( entity, context ) ),
entity.getProperties().stream().map( property -> property.accept( this, Collections.emptySet() ) ) )
entity.getProperties().stream().map( property -> property.accept( this, Collections.emptySet() ) ),
entity.getExtends().stream().map( superEntity -> superEntity.accept( this, Collections.emptySet() ) ) )
.reduce( Stream.empty(), Stream::concat ).reduce( context, Sets::union );
}

@Override
public Set<Locale> visitUnit( final Unit unit, final Set<Locale> context ) {
return Collections.emptySet();
}

@Override
public Set<Locale> visitQuantityKind( final QuantityKind quantityKind, final Set<Locale> context ) {
return Collections.emptySet();
public Set<Locale> visitCollection( final Collection collection, final Set<Locale> context ) {
return Stream.of(
Stream.of( visitIsDescribed( collection, context ) ),
collection.getElementCharacteristic().stream().map( characteristic -> characteristic.accept( this,
Collections.emptySet() ) ),
collection.getDataType().stream().map( type -> type.accept( this, Collections.emptySet() ) ) )
.reduce( Stream.empty(), Stream::concat ).reduce( context, Sets::union );
}

@Override
public Set<Locale> visitCollection( final Collection collection, final Set<Locale> context ) {
return collection.getElementCharacteristic().isPresent() ? collection.getElementCharacteristic().get().accept( this, Collections.emptySet() ) :
collection.getDataType().get().accept( this, Collections.emptySet() );
public Set<Locale> visitQuantifiable( final Quantifiable quantifiable, final Set<Locale> context ) {
return Stream.of(
Stream.of( visitIsDescribed( quantifiable, context ) ),
quantifiable.getUnit().stream().map( unit -> unit.accept( this, Collections.emptySet() ) ),
quantifiable.getDataType().stream().map( type -> type.accept( this, Collections.emptySet() ) ) )
.reduce( Stream.empty(), Stream::concat ).reduce( context, Sets::union );
}
}
Loading

0 comments on commit d4481fa

Please sign in to comment.