diff --git a/content/documentation/model.md b/content/documentation/model.md index 34f3256..f1df6ca 100644 --- a/content/documentation/model.md +++ b/content/documentation/model.md @@ -9,6 +9,11 @@ be modelled in Strolch and use in Strolch: ![Strolch model example](/assets/images/strolch-model-example.png) +The model has four entities, which will be modelled using 3 Resources and 1 Order object. The objects have numerous fields and the following relationships: +* Bidirectional between Article <-> Product +* Unidirectional from Order -> Article +* Unidirectional from Order -> Customer + A possible model would look as follows: ```xml @@ -60,158 +65,181 @@ A possible model would look as follows: Let's go through this model: -* In the above model we see that the id and name fields are always on the - element, and thus aren't added as parameters. Further most elements have a - parameters ParameterBag, with one or more parameters, modelling the fields. -* Note that in this example the Type of all the elements is Template. Strolch - has API support to create a clone of these elements, so that they have a - unique ID, and the proper type for persistence. -* The Product element has three parameters: description, color and form. In - this case they are all of type String. Further the relations ParameterBag - defines the relationships, i.e. the product knows its articles. Note how - the relation is first defined in a relations ParameterBag and that the - Parameter has Interpretation="Resource-Ref" Uom="Product" attributes. - Strolch has API support for this, making it trivial to retrieve a dependency. -* The Article element has two parameters description and barcode. Further it - has a reference to its Product. -* The Order element doesn't model the date and state fields as parameters, as - these are inherently part of an Order element. The Order does define two - references to customer and articles. A special case is the quantities - ParameterBag. This bag of parameters is used to store the per article - quantity for this order. With ParameterBags, you can eliminate the use of - simple aggregate classes, as is commonly used in object-oriented programming. -* The Customer element models a address ParameterBag to store the address of - a customer. Using a separate bag allows for further more direct fields to - stored on the default parameters bag. +* In the above model we see that the `id` and `name` fields are always on the + element, and thus aren't added as parameters. Further best practice is to use + a `parameters` ParameterBag, with one or more parameters, modelling the + fields. There is API support to not have to always type the `parameters` bag + id. +* Note that in this example the Type of all the elements is `Template`. Strolch + has API support to create a clone of these elements, so that they have a + unique id, and the proper type for persistence. +* The `Product` element has three parameters: `description`, `color` and `form`. In this + case they are all of type String. Further the `relations` ParameterBag defines + the relationships, i.e. the product knows its articles. Note how the relation + is first defined in a relations ParameterBag and that the Parameter has + `Interpretation="Resource-Ref" Uom="Product"` attributes. Strolch has API + support for this, making it trivial to retrieve a dependency. +* The `Article` element has two parameters `description` and `barcode`. Further it has + a reference to its Product. +* The `Order` element doesn't model the `date` and `state` fields as parameters, as + these are inherently part of an Order element. The Order does define two + references to customer and articles. A special case is the `quantities` + ParameterBag. This bag of parameters is used to store the per article quantity + for this order. With ParameterBags, you can eliminate the use of simple + aggregate classes, as is commonly used in object-oriented programming. +* The `Customer` element models an `address` ParameterBag to store the address of a + customer. Using a separate bag allows for further more direct fields to stored + on the default parameters bag. -Now that we have a basic understanding of te model, it is of far more interest -in how to create and interact with these elements at runtime. The following +Now that we have a basic understanding of te model, it is of far more interest +in how to create and interact with these elements at runtime. The following listing will perform simple operations: ```java -try (StrolchTransaction tx = runtimeMock.openUserTx(certificate, false)) { - - /* - * create a new product - */ - Resource dafalgan = tx.getResourceTemplate("Product", true); - dafalgan.setName("Dafalgan 100mg"); - dafalgan.getParameter("description", true).setValue("Dafalgan is for pain."); - dafalgan.getParameter("color", true).setValue("Yellow"); - dafalgan.getParameter("form", true).setValue("flat"); - - StringListParameter articlesP = dafalgan.getRelationsParam("articles", true); - - /* - * create articles - */ - Resource dafalgan1 = tx.getResourceTemplate("Article", true); - dafalgan1.setName("Dafalgan 100mg 10 pce"); - dafalgan1.getParameter("description", true).setValue("This is pack with 10 pieces."); - dafalgan1.getParameter("barcode", true).setValue("654654"); - - Resource dafalgan2 = tx.getResourceTemplate("Article", true); - dafalgan2.setName("Dafalgan 100mg 20 pce"); - dafalgan2.getParameter("description", true).setValue("This is pack with 20 pieces."); - dafalgan2.getParameter("barcode", true).setValue("654655"); - - /* - * add reference to product - */ - dafalgan1.getRelationParam("product").setValue(dafalgan.getId()); - articlesP.addValue(dafalgan1.getId()); - dafalgan2.getRelationParam("product").setValue(dafalgan.getId()); - articlesP.addValue(dafalgan2.getId()); - - /* - * create a new customer - */ - Resource customer1 = tx.getResourceTemplate("Customer", true); - customer1.setName("John Doe"); - - // set address - ParameterBag addressBag = customer1.getParameterBag("address", true); - addressBag.getParameter("street", true).setValue("Main Str. 1"); - addressBag.getParameter("zip", true).setValue("1234"); - addressBag.getParameter("city", true).setValue("Hometown"); - addressBag.getParameter("country", true).setValue("Switzerland"); - - /* - * create a new order - */ - Order order = tx.getOrderTemplate("Order", true); - order.setName("Order for " + customer1.getName()); - order.setDate(LocalDate.of(2021, 2, 1)); - order.setState(State.PLANNED); - - // store reference to customer - order.getRelationParam("customer", true).setValue(customer1.getId()); - - StringListParameter orderArticlesP = order.getRelationsParam("articles", true); - ParameterBag quantitiesBag = order.getParameterBag("quantities", true); - FloatParameter quantityT = quantitiesBag.removeParameter("quantity"); - - // order quantity of 20 for Dafalgan 1 - FloatParameter q1P = quantityT.getClone(); - q1P.setId(dafalgan1.getId()); - q1P.setValue(20); - quantitiesBag.addParameter(q1P); - orderArticlesP.addValue(dafalgan1.getId()); - - // set order quantity of 10 for Dafalgan 2 - FloatParameter q2P = quantityT.getClone(); - orderArticlesP.addValue(dafalgan2.getId()); - q2P.setId(dafalgan2.getId()); - q2P.setValue(20); - quantitiesBag.addParameter(q2P); +public class Example { + public static void main(String[] args) { // keep IDs for later use - dafalganId = dafalgan.getId(); - dafalgan1Id = dafalgan1.getId(); - dafalgan2Id = dafalgan2.getId(); - customerId = customer1.getId(); - orderId = order.getId(); + String dafalganId; + String dafalgan1Id; + String dafalgan2Id; + String customerId; + String orderId; - /* - * persist - */ - tx.add(dafalgan); - tx.add(dafalgan1); - tx.add(dafalgan2); - tx.add(customer1); - tx.add(order); + // first transaction to create the data + try (StrolchTransaction tx = runtimeMock.openUserTx(certificate, false)) { - // commit - tx.commitOnClose(); + /* + * create a new product + */ + Resource dafalgan = tx.getResourceTemplate("Product", true); + dafalgan.setName("Dafalgan 100mg"); + dafalgan.setString("description", "Dafalgan is for pain."); + dafalgan.setString("color", "Yellow"); + dafalgan.setString("form", "flat"); + + /* + * create articles + */ + Resource dafalgan1 = tx.getResourceTemplate("Article", true); + dafalgan1.setName("Dafalgan 100mg 10 pce"); + dafalgan1.setString("description", "This is pack with 10 pieces."); + dafalgan1.setString("barcode", "654654"); + + Resource dafalgan2 = tx.getResourceTemplate("Article", true); + dafalgan2.setName("Dafalgan 100mg 20 pce"); + dafalgan2.setString("description", "This is pack with 20 pieces."); + dafalgan2.setString("barcode", "654655"); + + /* + * add reference to product + */ + dafalgan1.setRelation("product", dafalgan); + dafalgan2.setRelation("product", dafalgan); + + dafalgan.addRelation("articles", dafalgan1); + dafalgan.addRelation("articles", dafalgan2); + + /* + * create a new customer + */ + Resource customer1 = tx.getResourceTemplate("Customer", true); + customer1.setName("John Doe"); + + // set address + ParameterBag addressBag = customer1.getParameterBag("address", true); + addressBag.setString("street", "Main Str. 1"); + addressBag.setString("zip", "1234"); + addressBag.setString("city", "Hometown"); + addressBag.setString("country", "Switzerland"); + + /* + * create a new order + */ + Order order = tx.getOrderTemplate("Order", true); + order.setName("Order for " + customer1.getName()); + order.setDate(LocalDate.of(2021, 2, 1)); + order.setState(State.PLANNED); + + // store reference to customer + order.setRelation("customer", customer1); + + StringListParameter orderArticlesP = order.getRelationsParam("articles", true); + ParameterBag quantitiesBag = order.getParameterBag("quantities", true); + FloatParameter quantityT = quantitiesBag.removeParameter("quantity"); + + // order quantity of 20 for Dafalgan 1 + quantitiesBag.setDouble(dafalgan1.getId(), 20); + order.addRelation("articles", dafalgan1); + + // set order quantity of 10 for Dafalgan 2 + quantitiesBag.setDouble(dafalgan2.getId(), 20); + order.addRelation("articles", dafalgan2); + + // keep IDs for later use + dafalganId = dafalgan.getId(); + dafalgan1Id = dafalgan1.getId(); + dafalgan2Id = dafalgan2.getId(); + customerId = customer1.getId(); + orderId = order.getId(); + + /* + * persist + */ + tx.add(dafalgan); + tx.add(dafalgan1); + tx.add(dafalgan2); + tx.add(customer1); + tx.add(order); + + // commit + tx.commitOnClose(); + } + } } ``` ```java -try (StrolchTransaction tx = runtimeMock.openUserTx(certificate, true)) { +class Scratch { + public static void main(String[] args) { - // get order - Order order = tx.getOrderBy("Order", orderId, true); - assertNotNull(orderId); - assertEquals("Order for John Doe", order.getName()); + // keep IDs for later use + String dafalganId; + String dafalgan1Id; + String dafalgan2Id; + String customerId; + String orderId; + + // + // .. snip ... + // - // get customer - Resource customer = tx.getResourceByRelation(order, "customer", true); - assertNotNull(customer); - assertEquals("John Doe", customer.getName()); + // second transaction to query the data + try (StrolchTransaction tx = runtimeMock.openUserTx(certificate, true)) { - // get articles - List articles = tx.getResourcesByRelation(order, "articles", true); - assertEquals(2, articles.size()); + // get order + Order order = tx.getOrderBy("Order", orderId, true); + assertEquals("Order for John Doe", order.getName()); - // get products - List products = articles.stream().map(a -> tx.getResourceByRelation(a, "product", true)) - .distinct().collect(Collectors.toList()); - assertEquals(1, products.size()); + // get customer + Resource customer = tx.getResourceByRelation(order, "customer", true); + assertEquals("John Doe", customer.getName()); - // search for all orders in state PLANNED and with customer - List orders = new OrderSearch().types("Order").stateIsIn(State.PLANNED) - .where(ExpressionsSupport.relationParam("customer").isEqualTo(customerId)).search(tx).toList(); - assertEquals(1, orders.size()); + // get articles + List articles = tx.getResourcesByRelation(order, "articles", true); + assertEquals(2, articles.size()); + + // get products by stream + List products = articles.stream().map(a -> tx.getResourceByRelation(a, "product", true)) + .distinct().collect(Collectors.toList()); + assertEquals(1, products.size()); + + // search for all orders in state PLANNED and with customer + List orders = new OrderSearch().types("Order").stateIsIn(State.PLANNED) + .where(ExpressionsSupport.relationParam("customer").isEqualTo(customerId)).search(tx).toList(); + assertEquals(1, orders.size()); + } + } } ```