diff --git a/src/main/scala/onera/pmlanalyzer/pml/model/hardware/BaseHardwareNodeBuilder.scala b/src/main/scala/onera/pmlanalyzer/pml/model/hardware/BaseHardwareNodeBuilder.scala index 2220d04..b62d7f4 100644 --- a/src/main/scala/onera/pmlanalyzer/pml/model/hardware/BaseHardwareNodeBuilder.scala +++ b/src/main/scala/onera/pmlanalyzer/pml/model/hardware/BaseHardwareNodeBuilder.scala @@ -82,45 +82,63 @@ trait BaseHardwareNodeBuilder[T <: Hardware] extends PMLNodeBuilder[T] { * (the name of the value enclosing the object) * @example {{{ * val mySimpleTransporter = SimpleTransporter() - * }}} - * @param basics the set of basic services provided, if empty a default store and load services are added - * @param implicitName implicitly retrieved name from the declaration context - * @param p implicitly retrieved relation linking components to their provided services - * @param owner implicitly retrieved name of the platform + * }}} + * @param basics the set of basic services provided, if empty a default store and load services are added + * @param withDefaultServices add default Load/Store services on creation + * @param implicitName implicitly retrieved name from the declaration context + * @param p implicitly retrieved relation linking components to their provided services + * @param owner implicitly retrieved name of the platform * @return the physical component * @group publicConstructor */ - def apply(basics: Set[Service] = Set.empty)(implicit implicitName: Name, - p: ProvideRelation[Hardware, Service], - owner: Owner): T = - apply(Symbol(implicitName.value), basics) + def apply(basics: Set[Service] = Set.empty, withDefaultServices: Boolean = true)(implicit implicitName: Name, + p: ProvideRelation[Hardware, Service], + owner: Owner): T = + apply(Symbol(implicitName.value), basics, withDefaultServices) /** * A physical component can be defined by its name and the basic services it provides * A transporter is only defined by its name, so if the transporter already exists it will * simply add the services provided by basics * - * @param name the physical component name - * @param basics the set of basic services provided, if empty a default store and load services are added - * @param p implicitly retrieved relation linking components to their provided services - * @param owner implicitly retrieved name of the platform + * @param name the physical component name + * @param basics the set of basic services provided, if empty a default store and load services are added + * @param withDefaultServices add default Load/Store services on creation + * @param p implicitly retrieved relation linking components to their provided services + * @param owner implicitly retrieved name of the platform * @return the physical component * @group publicConstructor */ - def apply(name: Symbol, basics: Set[Service])(implicit - p: ProvideRelation[Hardware, Service], - owner: Owner): T = { + def apply(name: Symbol, basics: Set[Service], withDefaultServices: Boolean)(implicit + p: ProvideRelation[Hardware, Service], + owner: Owner): T = { val formattedName = formatName(name, owner) val result = _memo.getOrElseUpdate((owner.s, formattedName), builder(formattedName)) val mutableBasic = collection.mutable.Set(basics.toSeq: _*) - if (!basics.exists(_.isInstanceOf[Load])) + if (withDefaultServices && !basics.exists(_.isInstanceOf[Load])) mutableBasic += Load(Symbol(s"${formattedName.name}_load")) - if (!basics.exists(_.isInstanceOf[Store])) + if (withDefaultServices && !basics.exists(_.isInstanceOf[Store])) mutableBasic += Store(Symbol(s"${formattedName.name}_store")) p.add(result, mutableBasic) result } + /** + * A physical component can be defined by its name and the basic services it provides + * + * @param name the physical component name + * @param basics the set of basic services provided, if empty a default store and load services are added + * @param p implicitly retrieved relation linking components to their provided services + * @param owner implicitly retrieved name of the platform + * @return the physical component + * @group publicConstructor + */ + def apply(name: Symbol, basics: Set[Service])(implicit + p: ProvideRelation[Hardware, Service], + owner: Owner): T = { + apply(name, basics, true) + } + /** * A physical component can be defined only its name, the services will be defined by default * @group publicConstructor @@ -131,5 +149,20 @@ trait BaseHardwareNodeBuilder[T <: Hardware] extends PMLNodeBuilder[T] { */ def apply(name: Symbol)(implicit p: ProvideRelation[Hardware, Service], owner: Owner): T = - apply(name, Set.empty) + apply(name, Set.empty, true) + + + /** + * A physical component can be defined only its name, the services will be defined by default + * + * @group publicConstructor + * @param name the physical component name + * @param withDefaultServices add default Load/Store services on creation + * @param p implicitly retrieved relation linking components to their provided services + * @param owner implicitly retrieved name of the platform + * @return the physical component + */ + def apply(name: Symbol, withDefaultServices: Boolean)(implicit p: ProvideRelation[Hardware, Service], + owner: Owner): T = + apply(name, Set.empty, withDefaultServices) } diff --git a/src/test/scala/onera/pmlanalyzer/pml/model/hardware/HardwareTest.scala b/src/test/scala/onera/pmlanalyzer/pml/model/hardware/HardwareTest.scala new file mode 100644 index 0000000..de694ee --- /dev/null +++ b/src/test/scala/onera/pmlanalyzer/pml/model/hardware/HardwareTest.scala @@ -0,0 +1,57 @@ +package onera.pmlanalyzer.pml.model.hardware + +import onera.pmlanalyzer.pml.model.hardware.* +import onera.pmlanalyzer.pml.model.service.{Load, Store} +import onera.pmlanalyzer.pml.operators.* +import sourcecode.Name +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should + +class HardwareTest extends AnyFlatSpec with should.Matchers { + + /* Create a default platform to act as a container for components. */ + object PlatformFixture extends Platform(Symbol("fixture")) + + import PlatformFixture.* + + "A Hardware" should "have default services" in { + val t: Target = Target() + val s: SimpleTransporter = SimpleTransporter() + val i: Initiator = Initiator() + val v: Virtualizer = Virtualizer() + + for (h <- List(t, s, i, v)) { + exactly(1, h.services) shouldBe a [Load] + exactly(1, h.services) shouldBe a [Store] + h.services.size shouldBe 2 + } + } + + it should "have no services when specified" in { + val t: Target = Target(withDefaultServices = false) + val s: SimpleTransporter = SimpleTransporter(withDefaultServices = false) + val i: Initiator = Initiator(withDefaultServices = false) + val v: Virtualizer = Virtualizer(withDefaultServices = false) + + for (h <- List(t, s, i, v)) { + h.services shouldBe empty + } + } + + it should "have only specified services when specified" in { + val t: Target = Target(Set(Load("a"), Load("b")), withDefaultServices = false) + t.services.size shouldEqual 2 + exactly(2, t.services) shouldBe a [Load] + + val s = Target(Set(Store("a")), withDefaultServices = false) + s.services.size shouldEqual 1 + exactly(1, s.services) shouldBe a[Store] + + val i = Target(Set.empty, withDefaultServices = false) + i.services.size shouldEqual 0 + + val j = Target(Symbol("j"), withDefaultServices = false) + j.services.size shouldEqual 0 + } + +}