diff --git a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/AspectEntity.java b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/AspectEntity.java new file mode 100644 index 000000000..88088c23b --- /dev/null +++ b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/AspectEntity.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH + * + * See the AUTHORS file(s) distributed with this work for additional + * information regarding authorship. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ +package org.eclipse.esmf.metamodel.entity; + +import org.eclipse.esmf.metamodel.Aspect; +import org.eclipse.esmf.metamodel.Event; +import org.eclipse.esmf.metamodel.Operation; +import org.eclipse.esmf.metamodel.Property; +import org.eclipse.esmf.metamodel.loader.MetaModelBaseAttributes; +import org.eclipse.esmf.metamodel.visitor.AspectVisitor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.StringJoiner; + +public class AspectEntity extends ModelEntityImpl implements Aspect { + private List properties; + private List operations; + private List events; + private boolean isCollectionAspect; + + public AspectEntity(final MetaModelBaseAttributes metaModelBaseAttributes, + List properties, + List operations, + List events, + boolean isCollectionAspect ) { + super( metaModelBaseAttributes ); + this.properties = new ArrayList<>( properties ); + this.operations = new ArrayList<>( operations ); + this.events = new ArrayList<>( events ); + this.isCollectionAspect = isCollectionAspect; + } + + public AspectEntity(MetaModelBaseAttributes metaModelBaseAttributes) { + super(metaModelBaseAttributes); + } + + /** + * A list of Properties exposed by the Aspect. + * + * @return the properties. + */ + @Override + public List getProperties() { + return properties; + } + + /** + * A list of Operations exposed by the Aspect. + * + * @return the operations. + */ + @Override + public List getOperations() { + return operations; + } + + /** + * A list of Events provided by the Aspect. + * + * @return the events. + */ + @Override + public List getEvents() { + return events; + } + + /** + * Accepts an Aspect visitor + * + * @param visitor The visitor to accept + * @param The result type of the traversal operation + * @param The context of the visitor traversal + */ + @Override + public T accept( final AspectVisitor visitor, final C context ) { + return visitor.visitAspect( this, context ); + } + + @Override + public boolean isCollectionAspect() { + return isCollectionAspect; + } + + @Override + public String toString() { + return new StringJoiner( ", ", AspectEntity.class.getSimpleName() + "[", "]" ) + .add( "properties=" + properties ) + .add( "operations=" + operations ) + .add( "events=" + events ) + .add( "isCollectionAspect=" + isCollectionAspect ) + .toString(); + } + + @Override + public boolean equals( final Object o ) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + if ( !super.equals( o ) ) { + return false; + } + final AspectEntity that = (AspectEntity) o; + return isCollectionAspect == that.isCollectionAspect && + Objects.equals( properties, that.properties ) && + Objects.equals( operations, that.operations ) && + Objects.equals( events, that.events ); + } + + @Override + public int hashCode() { + return Objects.hash( super.hashCode(), properties, operations, events, isCollectionAspect ); + } +} diff --git a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/CharacteristicEntity.java b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/CharacteristicEntity.java new file mode 100644 index 000000000..c6d488816 --- /dev/null +++ b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/CharacteristicEntity.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH + * + * See the AUTHORS file(s) distributed with this work for additional + * information regarding authorship. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ +package org.eclipse.esmf.metamodel.entity; + +import org.eclipse.esmf.metamodel.Characteristic; +import org.eclipse.esmf.metamodel.Type; +import org.eclipse.esmf.metamodel.impl.ModelElementImpl; +import org.eclipse.esmf.metamodel.loader.MetaModelBaseAttributes; +import org.eclipse.esmf.metamodel.visitor.AspectVisitor; + +import java.util.Objects; +import java.util.Optional; +import java.util.StringJoiner; + +public class CharacteristicEntity extends ModelEntityImpl implements Characteristic { + private final Optional dataType; + + public CharacteristicEntity(final MetaModelBaseAttributes metaModelBaseAttributes, final Optional dataType ) { + super( metaModelBaseAttributes ); + this.dataType = dataType; + } + + /** + * Defines the data type of all Properties which use this Characteristic. + * + * @return the dataType. + */ + @Override + public Optional getDataType() { + return dataType; + } + + /** + * Accepts an Aspect visitor + * + * @param visitor The visitor to accept + * @param The result type of the traversal operation + * @param The context of the visitor traversal + */ + @Override + public T accept( final AspectVisitor visitor, final C context ) { + return visitor.visitCharacteristic( this, context ); + } + + @Override + public String toString() { + return new StringJoiner( ", ", CharacteristicEntity.class.getSimpleName() + "[", "]" ) + .add( "dataType=" + dataType ) + .toString(); + } + + @Override + public boolean equals( final Object o ) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + return super.equals( o ); + } + + @Override + public int hashCode() { + return Objects.hash( super.hashCode() ); + } +} diff --git a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/EventEntity.java b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/EventEntity.java new file mode 100644 index 000000000..261060783 --- /dev/null +++ b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/EventEntity.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH + * + * See the AUTHORS file(s) distributed with this work for additional + * information regarding authorship. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +package org.eclipse.esmf.metamodel.entity; + +import org.eclipse.esmf.metamodel.Event; +import org.eclipse.esmf.metamodel.Property; +import org.eclipse.esmf.metamodel.impl.ModelElementImpl; +import org.eclipse.esmf.metamodel.loader.MetaModelBaseAttributes; +import org.eclipse.esmf.metamodel.visitor.AspectVisitor; + +import java.util.ArrayList; +import java.util.List; + +public class EventEntity extends ModelEntityImpl implements Event { + private List properties; + + public EventEntity(MetaModelBaseAttributes metaModelBaseAttributes, List properties ) { + super( metaModelBaseAttributes ); + this.properties = new ArrayList<>( properties ); + } + + @Override + public List getProperties() { + return properties; + } + + /** + * Accepts an Aspect visitor + * + * @param visitor The visitor to accept + * @param The result type of the traversal operation + * @param The context of the visitor traversal + */ + @Override + public T accept( AspectVisitor visitor, C context ) { + return visitor.visitEvent( this, context ); + } + + public void setProperties(List properties) { + this.properties = properties; + } +} diff --git a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/ModelEntityImpl.java b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/ModelEntityImpl.java new file mode 100644 index 000000000..29e778a64 --- /dev/null +++ b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/ModelEntityImpl.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH + * + * See the AUTHORS file(s) distributed with this work for additional + * information regarding authorship. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ +package org.eclipse.esmf.metamodel.entity; + +import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn; +import org.eclipse.esmf.metamodel.ModelElement; +import org.eclipse.esmf.metamodel.NamedElement; +import org.eclipse.esmf.metamodel.datatypes.LangString; +import org.eclipse.esmf.metamodel.loader.MetaModelBaseAttributes; +import org.eclipse.esmf.samm.KnownVersion; + +import java.util.*; + +/** + * The base implemenation of all model elements. + */ +public abstract class ModelEntityImpl implements ModelElement, NamedElement, Comparable { + private KnownVersion metaModelVersion; + private Optional urn; + private String name; + private Set preferredNames; + private Set descriptions; + private List see; + private boolean hasSyntheticName; + + ModelEntityImpl(final MetaModelBaseAttributes metaModelBaseAttributes ) { + metaModelVersion = metaModelBaseAttributes.getMetaModelVersion(); + urn = metaModelBaseAttributes.getUrn(); + name = metaModelBaseAttributes.getName(); + preferredNames = metaModelBaseAttributes.getPreferredNames(); + descriptions = metaModelBaseAttributes.getDescriptions(); + see = metaModelBaseAttributes.getSee(); + hasSyntheticName = metaModelBaseAttributes.hasSyntheticName(); + } + + /** + * The URN for the element, if present. Certain elements (such as Constraints) are allowed to not have URNs, which is why the URN is optional. + * + * @return the URN. + */ + @Override + public Optional getAspectModelUrn() { + return urn; + } + + /** + * Returns the metamodel version this model element is defined against + */ + @Override + public KnownVersion getMetaModelVersion() { + return metaModelVersion; + } + + /** + * The name of the element. + * + * @return the name. + */ + @Override + public String getName() { + return name; + } + + /** + * A language specific name for the Element. There may be multiple preferred names. + * + * @return the preferredNames. + */ + @Override + public Set getPreferredNames() { + return preferredNames; + } + + /** + * A language specific description of the Element. There may be multiple descriptions. + * + * @return the descriptions. + */ + @Override + public Set getDescriptions() { + return descriptions; + } + + @Override + public List getSee() { + return see; + } + + @Override + public boolean hasSyntheticName() { + return hasSyntheticName; + } + + @Override + public boolean equals( Object o ) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + ModelEntityImpl base = (ModelEntityImpl) o; + return Objects.equals( urn, base.urn ) && + Objects.equals( name, base.name ); + } + + @Override + public int hashCode() { + return Objects.hash( urn, name ); + } + + @Override + public int compareTo( ModelEntityImpl o ) { + if ( this.urn.isPresent() && o.urn.isPresent() ) + return this.urn.get().compareTo( o.urn.get() ); + return Comparator + .comparing( ModelEntityImpl::getMetaModelVersion ) + .thenComparing( ModelEntityImpl::getName ) + .thenComparing( ModelEntityImpl::hasSyntheticName ) + .compare( this, o ); + } +} diff --git a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/OperationEntity.java b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/OperationEntity.java new file mode 100644 index 000000000..1a3811c3c --- /dev/null +++ b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/OperationEntity.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH + * + * See the AUTHORS file(s) distributed with this work for additional + * information regarding authorship. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ +package org.eclipse.esmf.metamodel.entity; + +import org.eclipse.esmf.metamodel.Operation; +import org.eclipse.esmf.metamodel.Property; +import org.eclipse.esmf.metamodel.impl.ModelElementImpl; +import org.eclipse.esmf.metamodel.loader.MetaModelBaseAttributes; +import org.eclipse.esmf.metamodel.visitor.AspectVisitor; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.StringJoiner; + +public class OperationEntity extends ModelEntityImpl implements Operation { + private final List input; + private final Optional output; + + public OperationEntity(final MetaModelBaseAttributes metaModelBaseAttributes, + final List input, + final Optional output ) { + super( metaModelBaseAttributes ); + this.input = input; + this.output = output; + } + + /** + * A list of input parameters for the Operation. If the operation does not take any input parameters, the input may + * be omitted. + * + * @return the input. + */ + @Override + public List getInput() { + return input; + } + + /** + * The return value of the Operation. If the Operation does not return anything, the output may be omitted. + * + * @return the output. + */ + @Override + public Optional getOutput() { + return output; + } + + /** + * Accepts an Aspect visitor + * + * @param visitor The visitor to accept + * @param The result type of the traversal operation + * @param The context of the visitor traversal + */ + @Override + public T accept( final AspectVisitor visitor, final C context ) { + return visitor.visitOperation( this, context ); + } + + @Override + public String toString() { + return new StringJoiner( ", ", OperationEntity.class.getSimpleName() + "[", "]" ) + .add( "input=" + input ) + .add( "output=" + output ) + .toString(); + } + + @Override + public boolean equals( final Object o ) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + if ( !super.equals( o ) ) { + return false; + } + final OperationEntity that = (OperationEntity) o; + return Objects.equals( input, that.input ) && + Objects.equals( output, that.output ); + } + + @Override + public int hashCode() { + return Objects.hash( super.hashCode(), input, output ); + } +} diff --git a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/PropertyEntity.java b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/PropertyEntity.java new file mode 100644 index 000000000..e29ba1aba --- /dev/null +++ b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/PropertyEntity.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH + * + * See the AUTHORS file(s) distributed with this work for additional + * information regarding authorship. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ +package org.eclipse.esmf.metamodel.entity; + +import org.eclipse.esmf.metamodel.Characteristic; +import org.eclipse.esmf.metamodel.Property; +import org.eclipse.esmf.metamodel.ScalarValue; +import org.eclipse.esmf.metamodel.Type; +import org.eclipse.esmf.metamodel.loader.MetaModelBaseAttributes; +import org.eclipse.esmf.metamodel.visitor.AspectVisitor; + +import java.util.Objects; +import java.util.Optional; +import java.util.StringJoiner; + +public class PropertyEntity extends ModelEntityImpl implements Property { + private Optional characteristic; + private Optional exampleValue; + private boolean optional; + private boolean notInPayload; + private Optional payloadName; + private boolean isAbstract; + private Optional extends_; + + public PropertyEntity(MetaModelBaseAttributes metaModelBaseAttributes, + Optional characteristic, + Optional dataType, + Optional exampleValue, + boolean optional, + boolean notInPayload, + Optional payloadName, + boolean isAbstract, + Optional extends_ + ) { + super(metaModelBaseAttributes); + this.characteristic = Optional.of(new CharacteristicEntity(metaModelBaseAttributes, dataType)); + this.exampleValue = exampleValue; + this.optional = optional; + this.notInPayload = notInPayload; + this.payloadName = payloadName; + this.isAbstract = isAbstract; + this.extends_ = extends_; + } + + /** + * The Characteristic describing the semantics of the Property. + * + * @return the characteristic. + */ + @Override + public Optional getCharacteristic() { + return characteristic; + } + + /** + * A real world example value. + * + * @return the exampleValue. + */ + @Override + public Optional getExampleValue() { + return exampleValue; + } + + /** + * Defines whether a property is optional. + * + * @return the optional. + */ + @Override + public boolean isOptional() { + return optional; + } + + /** + * Defines whether a property is included in the runtime data of an Aspect. + * + */ + @Override + public boolean isNotInPayload() { + return notInPayload; + } + + @Override + public String getPayloadName() { + return payloadName.orElseGet( this::getName ); + } + + @Override + public boolean isAbstract() { + return isAbstract; + } + + @Override + public Optional getExtends() { + return extends_; + } + + /** + * Accepts an Aspect visitor + * + * @param visitor The visitor to accept + * @param The result type of the traversal operation + * @param The context of the visitor traversal + */ + @Override + public T accept( final AspectVisitor visitor, final C context ) { + return visitor.visitProperty( this, context ); + } + + @Override + public String toString() { + return new StringJoiner( ", ", PropertyEntity.class.getSimpleName() + "[", "]" ) + .add( "characteristic=" + characteristic ) + .add( "exampleValue=" + exampleValue ) + .add( "optional=" + optional ) + .add( "notInPayload=" + notInPayload ) + .add( "isAbstract=" + isAbstract ) + .add( "extends=" + extends_ ) + .toString(); + } + + @SuppressWarnings( "squid:S1067" ) // Generated equals method + @Override + public boolean equals( final Object o ) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + if ( !super.equals( o ) ) { + return false; + } + final PropertyEntity that = (PropertyEntity) o; + return Objects.equals( getName(), that.getName() ) && + Objects.equals( getAspectModelUrn(), that.getAspectModelUrn() ) && + optional == that.optional && + notInPayload == that.notInPayload && + isAbstract == that.isAbstract && + Objects.equals( characteristic, that.characteristic ) && + Objects.equals( exampleValue, that.exampleValue ) && + Objects.equals( extends_, that.extends_ ); + } + + @Override + public int hashCode() { + return Objects.hash( super.hashCode(), characteristic, exampleValue, optional, notInPayload, isAbstract, extends_ ); + } +} diff --git a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/ScalarEntity.java b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/ScalarEntity.java new file mode 100644 index 000000000..672210a30 --- /dev/null +++ b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/ScalarEntity.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH + * + * See the AUTHORS file(s) distributed with this work for additional + * information regarding authorship. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +package org.eclipse.esmf.metamodel.entity; + +import org.eclipse.esmf.metamodel.Scalar; +import org.eclipse.esmf.metamodel.visitor.AspectVisitor; +import org.eclipse.esmf.samm.KnownVersion; + +import java.util.Objects; +import java.util.StringJoiner; + +public class ScalarEntity implements Scalar { + private final KnownVersion metaModelVersion; + private final String urn; + + public ScalarEntity(final String urn, final KnownVersion metaModelVersion ) { + this.urn = urn; + this.metaModelVersion = metaModelVersion; + } + + @Override + public String getUrn() { + return urn; + } + + @Override + public KnownVersion getMetaModelVersion() { + return metaModelVersion; + } + + @Override + public String toString() { + return new StringJoiner( ", ", ScalarEntity.class.getSimpleName() + "[", "]" ) + .add( "metaModelVersion=" + metaModelVersion ) + .add( "urn='" + urn + "'" ) + .toString(); + } + + /** + * Accepts an Aspect visitor + * + * @param visitor The visitor to accept + * @param The result type of the traversal operation + * @param The context of the visitor traversal + */ + @Override + public T accept( final AspectVisitor visitor, final C context ) { + return visitor.visitScalar( this, context ); + } + + @Override + public boolean equals( final Object o ) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + final ScalarEntity that = (ScalarEntity) o; + return metaModelVersion == that.metaModelVersion && + Objects.equals( urn, that.urn ); + } + + @Override + public int hashCode() { + return Objects.hash( metaModelVersion, urn ); + } +} diff --git a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/ScalarValueEntity.java b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/ScalarValueEntity.java new file mode 100644 index 000000000..9cf6a5ac3 --- /dev/null +++ b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/ScalarValueEntity.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH + * + * See the AUTHORS file(s) distributed with this work for additional + * information regarding authorship. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +package org.eclipse.esmf.metamodel.entity; + +import org.eclipse.esmf.metamodel.Scalar; +import org.eclipse.esmf.metamodel.ScalarValue; +import org.eclipse.esmf.metamodel.visitor.AspectVisitor; +import org.eclipse.esmf.samm.KnownVersion; + +import java.util.Objects; +import java.util.StringJoiner; + +public class ScalarValueEntity implements ScalarValue { + private final Object value; + private final Scalar type; + + public ScalarValueEntity(final Object value, final Scalar type ) { + this.value = value; + this.type = type; + } + + @Override + public Object getValue() { + return value; + } + + @Override + public Scalar getType() { + return type; + } + + @Override + public KnownVersion getMetaModelVersion() { + return type.getMetaModelVersion(); + } + + @Override + public T accept( final AspectVisitor visitor, final C context ) { + return visitor.visitScalarValue( this, context ); + } + + @Override + public int compareTo( final ScalarValue other ) { + if ( !type.equals( other.getType() ) ) { + throw new UnsupportedOperationException( "Tried to compare values of different types" ); + } + if ( value instanceof Comparable ) { + return compareTo( getValue(), other.getValue() ); + } + return 0; + } + + @SuppressWarnings( "unchecked" ) + private > int compareTo( final Object value1, final Object value2 ) { + return ((T) value1).compareTo( (T) value2 ); + } + + @Override + public String toString() { + return new StringJoiner( ", ", ScalarValueEntity.class.getSimpleName() + "[", "]" ) + .add( "value=" + value ) + .add( "typeUri='" + type + "'" ) + .toString(); + } + + @Override + public boolean equals( final Object o ) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + final ScalarValueEntity that = (ScalarValueEntity) o; + return Objects.equals( value, that.value ) && Objects.equals( type, that.type ); + } + + @Override + public int hashCode() { + return Objects.hash( value, type ); + } +} diff --git a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/TypeEntity.java b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/TypeEntity.java new file mode 100644 index 000000000..bf1930d78 --- /dev/null +++ b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/entity/TypeEntity.java @@ -0,0 +1,33 @@ +package org.eclipse.esmf.metamodel.entity; + +import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn; +import org.eclipse.esmf.metamodel.Type; +import org.eclipse.esmf.metamodel.visitor.AspectVisitor; +import org.eclipse.esmf.samm.KnownVersion; + +import java.util.Optional; + +public class TypeEntity implements Type { + private KnownVersion knownVersion; + private Optional urn; + + public TypeEntity(KnownVersion knownVersion, Optional urn) { + this.knownVersion = knownVersion; + this.urn = urn; + } + + @Override + public KnownVersion getMetaModelVersion() { + return this.knownVersion; + } + + @Override + public T accept(AspectVisitor visitor, C context) { + return null; + } + + @Override + public String getUrn() { + return this.urn.toString(); + } +} diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aspect/AASModelAspectGenerator.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aspect/AASModelAspectGenerator.java new file mode 100644 index 000000000..95609f547 --- /dev/null +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aspect/AASModelAspectGenerator.java @@ -0,0 +1,70 @@ +package org.eclipse.esmf.aspectmodel.aspect; + +import org.apache.jena.rdf.model.Model; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.SerializationException; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.aasx.AASXSerializer; +import org.eclipse.digitaltwin.aas4j.v3.model.Environment; +import org.eclipse.esmf.aspectmodel.aas.AspectModelAASVisitor; +import org.eclipse.esmf.aspectmodel.resolver.services.SammAspectMetaModelResourceResolver; +import org.eclipse.esmf.aspectmodel.resolver.services.VersionedModel; +import org.eclipse.esmf.aspectmodel.serializer.PrettyPrinter; +import org.eclipse.esmf.aspectmodel.serializer.RdfModelCreatorVisitor; +import org.eclipse.esmf.aspectmodel.vocabulary.Namespace; +import org.eclipse.esmf.metamodel.Aspect; + +import java.io.*; +import java.util.function.Function; + +public class AASModelAspectGenerator { + + /** + * Generates an AASX archive file for a given Aspect and writes it to a given OutputStream provided by nameMapper + * + * @param environment the Aspect for which an AASX archive shall be generated + * @param nameMapper a Name Mapper implementation, which provides an OutputStream for a given filename + * @throws IOException in case the generation can not properly be executed + */ + public void generateAASXFile(final Environment environment, final Function nameMapper ) + throws IOException { +// try ( final OutputStream output = nameMapper.apply( environment.getName() ) ) { +// output.write( generateAspectOutput( environment ).toByteArray() ); +// } + generateAspectOutput(environment); + } + + protected ByteArrayOutputStream generateAspectOutput(final Environment environment ) throws IOException { + final AASModelAspectVisitor visitor = new AASModelAspectVisitor(); + final Aspect aspect = visitor.visitAAS( environment ); + + final Namespace aspectNamespace = () -> aspect.getAspectModelUrn().get().getUrnPrefix(); + final RdfModelCreatorVisitor rdfCreator = new RdfModelCreatorVisitor( + aspect.getMetaModelVersion(), aspectNamespace ); + final Model model = rdfCreator.visitAspect( aspect, null ).getModel(); + + // At this point, you can manipulate the RDF model, if required + + // Second step: Serialize RDF model into nicely formatted Turtle + final StringWriter stringWriter = new StringWriter(); + final PrintWriter printWriter = new PrintWriter( System.out ); + final VersionedModel versionedModel = new SammAspectMetaModelResourceResolver() + .mergeMetaModelIntoRawModel( model, aspect.getMetaModelVersion() ).get(); + final PrettyPrinter prettyPrinter = new PrettyPrinter( + versionedModel, aspect.getAspectModelUrn().get(), printWriter ); + prettyPrinter.print(); + printWriter.close(); + + try ( final ByteArrayOutputStream out = new ByteArrayOutputStream() ) { +// final AASXSerializer serializer = new AASXSerializer(); +// serializer.write( environment, null, out ); + return out; + } + +// try ( final ByteArrayOutputStream out = new ByteArrayOutputStream() ) { +// final AASXSerializer serializer = new AASXSerializer(); +// serializer.write( environment, null, out ); +// return out; +// } catch ( final SerializationException e ) { +// throw new IOException( e ); +// } + } +} diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aspect/AASModelAspectVisitor.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aspect/AASModelAspectVisitor.java new file mode 100644 index 000000000..6b1ed3db8 --- /dev/null +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aspect/AASModelAspectVisitor.java @@ -0,0 +1,206 @@ +package org.eclipse.esmf.aspectmodel.aspect; + +import org.eclipse.digitaltwin.aas4j.v3.model.Environment; +import org.eclipse.digitaltwin.aas4j.v3.model.ModellingKind; +import org.eclipse.digitaltwin.aas4j.v3.model.Property; +import org.eclipse.digitaltwin.aas4j.v3.model.Submodel; +import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement; +import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElementCollection; +import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElementList; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodelElementList; +import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn; +import org.eclipse.esmf.aspectmodel.vocabulary.SAMM; +import org.eclipse.esmf.metamodel.Type; +import org.eclipse.esmf.metamodel.datatypes.LangString; +import org.eclipse.esmf.metamodel.entity.*; +import org.eclipse.esmf.metamodel.impl.DefaultScalar; +import org.eclipse.esmf.metamodel.loader.AttributeValueRetriever; +import org.eclipse.esmf.metamodel.loader.MetaModelBaseAttributes; +import org.eclipse.esmf.samm.KnownVersion; + +import java.util.*; +import java.util.stream.Collectors; + +public class AASModelAspectVisitor { + + public AspectEntity visitAAS (Environment environment) { + + AspectEntity newAspect = null; + List propertyEntities = new ArrayList<>(); + List operationEntities = new ArrayList<>(); + + List submodels = environment.getSubmodels() + .stream().filter(submodel -> submodel.getKind().equals(ModellingKind.TEMPLATE)).toList(); + + for (Submodel submodel : submodels) { + + //Build MetaModelBaseAttributes for AspectEntity + String aspectMetaModelName = submodel.getIdShort(); + Set metaModelAspectPreferredName = submodel.getDisplayName().stream() + .map(n -> new LangString(n.getText(), Locale.forLanguageTag(n.getLanguage()))).collect(Collectors.toSet()); + Set metaModelAspectDescription = submodel.getDescription().stream() + .map(d -> new LangString(d.getText(), Locale.forLanguageTag(d.getLanguage()))).collect(Collectors.toSet()); + AspectModelUrn aspectModelUrn = AspectModelUrn.fromUrn(submodel.getSemanticID().getKeys().get(0).getValue()); + + MetaModelBaseAttributes aspectMetaModelBaseAttributes = new MetaModelBaseAttributes( + KnownVersion.getLatest(), + aspectModelUrn, + aspectMetaModelName, + metaModelAspectPreferredName, + metaModelAspectDescription, + List.of(""), + false + ); + + // Visit subModel for getting properties + for ( SubmodelElement element : submodel.getSubmodelElements()) { + + // Build Properties for AspectEntity + if (element instanceof SubmodelElementList convertedElement) { + + String metaModelPropertyName = element.getIdShort(); + Set metaModelPropertyPreferredName = element.getDisplayName().stream() + .map(n -> new LangString(n.getText(), Locale.forLanguageTag(n.getLanguage()))).collect(Collectors.toSet()); + Set metaModelPropertyDescription = element.getDescription().stream() + .map(d -> new LangString(d.getText(), Locale.forLanguageTag(d.getLanguage()))).collect(Collectors.toSet()); + Optional propertyUrn = Optional.of(AspectModelUrn.fromUrn("urn:samm:test:0.0.1#" + element.getIdShort().split("id_")[1])); + + MetaModelBaseAttributes proprtyMetaModelBaseAttributes = new MetaModelBaseAttributes( + KnownVersion.getLatest(), + propertyUrn.orElse(null), +// null, + metaModelPropertyName, + metaModelPropertyPreferredName, + metaModelPropertyDescription, + List.of(""), + false + ); + + // Build PropertyEntity +// ScalarValueEntity propertyExampleValue = new ScalarValueEntity( +// new Object(), +// new DefaultScalar(element.getSemanticID().getKeys().get(0).getValue(), KnownVersion.getLatest()) +// ); +// CharacteristicEntity characteristic = new CharacteristicEntity( +// proprtyMetaModelBaseAttributes, +// element +// ); + + PropertyEntity aspectProperty = new PropertyEntity( + proprtyMetaModelBaseAttributes, + Optional.empty(), + Optional.empty(), +// Optional.of(propertyExampleValue), + Optional.empty(), + false, + false, + Optional.of("payload"), + false, + Optional.empty() + ); + + propertyEntities.add(aspectProperty); + + if (!convertedElement.getValue().isEmpty()) { + for (SubmodelElement submodelElementCollection : convertedElement.getValue()) { + + for (SubmodelElement submodelElement : ( (SubmodelElementCollection) submodelElementCollection).getValue()) { + + PropertyEntity currentProperty = visitProperty(submodelElement, null); + + propertyEntities.add(currentProperty); + } + } + } + } + } + + newAspect = new AspectEntity( + aspectMetaModelBaseAttributes, + propertyEntities, + operationEntities, + new ArrayList<>(), + true + ); + } + + return newAspect; + } + + private PropertyEntity visitProperty (SubmodelElement property, PropertyEntity extends_) { + Property currentAasProperty = ((Property) property); + + //Build metaModelBaseAttributes + String metaModelPropertyName = property.getIdShort(); + Set metaModelPropertyPreferredName = property.getDisplayName().stream() + .map(n -> new LangString(n.getText(), Locale.forLanguageTag(n.getLanguage()))).collect(Collectors.toSet()); + Set metaModelPropertyDescription = property.getDescription().stream() + .map(d -> new LangString(d.getText(), Locale.forLanguageTag(d.getLanguage()))).collect(Collectors.toSet()); + Optional propertyUrn = Optional.of(AspectModelUrn.fromUrn(currentAasProperty.getSemanticID().getKeys().get(0).getValue())); + + MetaModelBaseAttributes proprtyMetaModelBaseAttributes = new MetaModelBaseAttributes( + KnownVersion.getLatest(), + propertyUrn.orElse(null), + metaModelPropertyName, + metaModelPropertyPreferredName, + metaModelPropertyDescription, + List.of(""), + false + ); + + // Build PropertyEntity + ScalarValueEntity propertyExampleValue = new ScalarValueEntity( + new Object(), + new DefaultScalar(property.getSemanticID().getKeys().get(0).getValue(), KnownVersion.getLatest()) + ); + + SAMM samm = new SAMM(KnownVersion.SAMM_2_1_0); + AttributeValueRetriever attributeValueRetriever = new AttributeValueRetriever(samm); + +// final Optional extends_ = attributeValueRetriever.optionalAttributeValue( currentProperty, samm._extends() ) +// .map( Statement::getResource ) +// .map( superElementResource -> modelElementFactory.create( org.eclipse.esmf.metamodel.Property.class, superElementResource ) ); +// final boolean isAbstract = property.getModel().contains( property, RDF.type, samm.AbstractProperty() ); + + Optional characteristic = visitCharacteristic(currentAasProperty); + + return new PropertyEntity( + proprtyMetaModelBaseAttributes, + characteristic, + Optional.empty(), + Optional.of(propertyExampleValue), + false, + false, + Optional.of("payload"), + false, + Optional.ofNullable(extends_) + ); + } + + private Optional visitCharacteristic (Property aasProperty) { + + String metaModelPropertyName = aasProperty.getIdShort(); + Set metaModelPropertyPreferredName = aasProperty.getDisplayName().stream() + .map(n -> new LangString(n.getText(), Locale.forLanguageTag(n.getLanguage()))).collect(Collectors.toSet()); + Set metaModelPropertyDescription = aasProperty.getDescription().stream() + .map(d -> new LangString(d.getText(), Locale.forLanguageTag(d.getLanguage()))).collect(Collectors.toSet()); + Optional propertyUrn = Optional.of(AspectModelUrn.fromUrn("urn:samm:test:0.0.1#" + aasProperty.getValueType().toString())); + + MetaModelBaseAttributes proprtyMetaModelBaseAttributes = new MetaModelBaseAttributes( + KnownVersion.getLatest(), + propertyUrn.orElse(null), + metaModelPropertyName, + metaModelPropertyPreferredName, + metaModelPropertyDescription, + List.of(""), + false + ); + + TypeEntity typeEntity = new TypeEntity( + KnownVersion.getLatest(), + propertyUrn + ); + + return Optional.of(new CharacteristicEntity(proprtyMetaModelBaseAttributes, Optional.of(typeEntity))); + } +}