Hi to all.

I have a domain implemented in Apache Isis with some similarities.

In our case, we have Item entities with a LOT of custom options that can be 
defined over them (ItemOption).
Those ItemOption’s are grouped in ItemOptionGroup’s, that can be reused by 
different Item’s.

ItemOptions can be of different kinds. Currently implemented ones:
- GenericItemOptionWithChoices
- GenericItemOptionsForDate
- GenericItemOptionsForNumber
- GenericItemOptionsForText




Also, one Item can have SubItems (which are other Item that must be bought 
together - and that can also contain its own ItemOption’s -).


There’s also an Order entity where users can order specific Product 
configurations. 
so when placing the Order you must concrete which Product options you want.

The Ordered Item Options, etc. have custom "compareTo” and “title” methods to 
properly show selected values.


Current entities are similar to this:

**** ITEM-RELATED ENTITIES ****


@PersistenceCapable
public abstract class ItemOption extends AbstractMultiTenantEntity {

…@PersistenceCapable
@XMSEntityNames({ @XMSEntityName(locale = "es", name = "Grupo de Opciones de 
Artículo") })
public abstract class ItemOptionsGroup extends AbstractMultiTenantEntity {

    // {{ Options (Collection)
    @Persistent(mappedBy = "itemOptionGroup", dependentElement = "true")
    private SortedSet<ItemOptionGroupOption> options = new 
TreeSet<ItemOptionGroupOption>();

...
    // }}

}

@PersistenceCapable
public class ItemOptionGroupOption extends AbstractMultiTenantUnnamedEntity {

    // {{ ItemOptionsGroup (property)
    private ItemOptionsGroup itemOptionsGroup;

...
    // }}

    // {{ ItemOption (property)
    private ItemOption itemOption;

   ...
    // }}

    // {{ OrderingCode (property)
    private String orderingCode;

…

    // }}




@PersistenceCapable
@XMSEntityNames({ @XMSEntityName(locale = "es", name = "Artículo") })
public abstract class Item extends AbstractMultiTenantEntity {

    // {{ OptionGroup (property)
    private ItemOptionsGroup optionsGroup;

...


    // }}

    // {{ SubItems (Collection)
    @Persistent(mappedBy = "parentItem", dependentElement = "true")
    private SortedSet<SubItem> subItems = new TreeSet<SubItem>();

   …

    // }}




**** ORDER-RELATED ENTITIES ****

@PersistenceCapable
public abstract class Order extends AbstractMultiTenantUnnamedEntity {

    // {{ ItemsOrdered (Collection)
    @Persistent(mappedBy = "order", dependentElement = "true")
    private SortedSet<OrderedItem> itemsOrdered = new TreeSet<OrderedItem>();

   ...

    // {{ addItem (action)
    @ActionSemantics(Of.SAFE)
    @MemberOrder(name = "itemsOrdered", sequence = "010")
    public abstract OrderedItem addItem(@XMSActionField(locales = { 
@XMSLocale(locale = "es", caption = "Artículo") }) @Named("Item") final Item 
item, @XMSActionField(locales = { @XMSLocale(locale = "es", caption = 
"Unidades") }) @Named("Units") final BigDecimal units,
            @XMSActionField(locales = { @XMSLocale(locale = "es", caption = 
"Descripción") }) @Named("Description") @Optional final String description);

    protected <T extends OrderedItem> T createPersistentOrderedItem(final 
Class<T> clazz, final Item item, final BigDecimal amount, final String 
description) {

        T orderedItem = 
this.getDomainFactoryService().newTransientMultiTenantUnnamedEntity(clazz, 
null, description);

        this.wrapSkipRules(orderedItem).setOrder(this);
        this.wrap(orderedItem).setQuantity(amount);
        this.wrap(orderedItem).setDescription(description);

        orderedItem = this.onInitializeTransientOrderedItem(orderedItem);

        // This setter invokation will persist the Entity, as it will also
        // insert on dependant entities if there are Options or Sub-Items.
        this.wrapSkipRules(orderedItem).setItem(item);

        // if no Options or SubItems present ...
        this.persistIfNotAlready(orderedItem);

        return orderedItem;

    }


————

@PersistenceCapable
public abstract class OrderedItem extends AbstractMultiTenantUnnamedEntity {

    // {{ Options (Collection)
    @Persistent(mappedBy = "orderedItem", dependentElement = "true")
    private SortedSet<OrderedItemOption> options = new 
TreeSet<OrderedItemOption>();

        ….


    private void configureOptions(final Item newItem) {

        // Clear previously existing options.
        this.clearOptions();

        // Create new ones.
        if ((newItem != null) && (newItem.getOptionsGroup() != null)) {
            for (final ItemOptionGroupOption current : 
this.getItem().getOptionsGroup().getOptions()) {
                final Class<? extends OrderedItemOption> clazz1 = 
this.orderedItemOptionsEquivalences.orderedItemOptionClassFor(current.getItemOption().getClass());
                final OrderedItemOption orderedItemOption = 
(this.getDomainFactoryService()).newTransientMultiTenantUnnamedEntity(clazz1, 
null, null);

                this.wrapSkipRules(orderedItemOption).setOrderedItem(this);
                this.wrapSkipRules(orderedItemOption).setGroupOption(current);

                this.persist(orderedItemOption);

            }
        }
    }

    private void clearOptions() {
        final Set<OrderedItemOption> copySet = 
Sets.newHashSet(this.getOptions());
        for (final OrderedItemOption current : copySet) {
            this.getOptions().remove(current);
            this.getContainer().flush();
        }
    }

————

@PersistenceCapable
@XMSEntityNames({ @XMSEntityName(locale = "es", name = "Artículo Principal del 
Pedido") })
public class OrderedMainItem extends OrderedItem {

…
}

————

@PersistenceCapable
public class OrderedSubItem extends OrderedItem {

    // {{ SubItem (property)
    private SubItem subItem;

…
}

————

@PersistenceCapable
@XMSEntityNames({ @XMSEntityName(locale = "es", name = "Opción de Artículo del 
Pedido") })
public abstract class OrderedItemOption extends 
AbstractMultiTenantUnnamedEntity {

    // {{ OrderedItem (property)
    private OrderedItem orderedItem;

…

    // }}

    // {{ ItemOptionGroupOption (property)
    private ItemOptionGroupOption groupOption;



——


And after that some specialized classes for the different types of ItemOption 
the app manages:

@PersistenceCapable
@XMSEntityNames({ @XMSEntityName(locale = "es", name = "Opción con Elección del 
Artículo del Pedido Genérico") })
public class GenericOrderedItemOptionWithChoices extends OrderedItemOption {

    // {{ ChoiceSelected (property)
    private GenericItemOptionWithChoicesChoice choiceSelected;


…}

@PersistenceCapable
@XMSEntityNames({ @XMSEntityName(locale = "es", name = "Opción con Fecha del 
Artículo del Pedido Genérico") })
public class GenericOrderedItemOptionWithDate extends OrderedItemOption {

    // {{ DateSelected (property)
    private Date dateSelected;

...
    // }}
 
@PersistenceCapable
@XMSEntityNames({ @XMSEntityName(locale = "es", name = "Opción con Número del 
Artículo del Pedido Genérico") })
public class GenericOrderedItemOptionWithNumber extends OrderedItemOption {

    // {{ NumberEntered (property)
    private BigDecimal numberEntered;

…
}



 

HTH,

Oscar


> El 28/7/2015, a las 10:15, Stephen Cameron <[email protected]> 
> escribió:
> 
> Hi David,
> 
> My two bits worth, I think Apache Isis is the last thing i would use for
> this kind of a task. If the information collected is that complex, then
> trying to fit in into a relational database via an object model makes no
> sense. Just use an XML database and XForms.
> 
> There are server-side implementations of XForms that work well, namely
> Orbeon and BetterForms, if you want to hide the declarative form logic from
> users.
> 
> For me, its Isis for behaviour and XForms/XQuery for complex data, both are
> efficient in their domains of specialisation.
> 
> Where the boundary lies is an interesting puzzle to me. There is paper that
> myself and another wrote, somewhat on this contrast, here [1].
> 
> XForms is efficient as all the complexity that you describe can be done
> declaratively via XPath predicates [2]. That said, there is no validating
> compiler, so refactoring is a pain for example. Joeron's suggestion of two
> domain models might be alluding to that perhaps? But subforms do provide a
> means to manage this.
> 
> Finally, XForms can be fun too, see [3]
> 
> Cheers
> Steve Cameron
> 
> [1]
> http://www.balisage.net/Proceedings/vol10/html/Velasquez01/BalisageVol10-Velasquez01.html
> [2] http://lib.tkk.fi/Diss/2007/isbn9789512285662/article3.pdf
> [3]
> http://exist-db.org/exist/apps/XSLTForms-Demo/modules/form.xq?form=tic-tac-toe.xml
> 
> 
> 
> On Sun, Jul 26, 2015 at 11:38 AM, David Tildesley <[email protected]>
> wrote:
> 
>> Hi,
>> I am looking for some ideas around how ISIS could be helpful in the
>> following Use Case. N.B. For non-disclosure reasons, I have to mask the
>> real problem domain however at the same time try and give you a sense of
>> what it all about and the degree of complexity.
>> UC1. "Apply for 'XYZ'"
>> N.B. 'XYZ' in truth has many variations ('XYZa, XYZb, XYZc, ...) which
>> differ substantially in the information that must be collected from the
>> Applicant(s). There is only a very small subset of information that is
>> common.
>> 1. The Applicant(s) (individual(s)) core details (name, contact details,
>> dob, identity document number, ...). Depending on the type of 'XYZ' a very
>> large set of additional information about these parties must be collected
>> (e.g. educational qualifications, military history, job history, ...)2.
>> Depending on the type of 'XYZ' and the answers to previous questions,
>> information about other Parties ("Organisation" or "Individual") must be
>> collected.3. The system needs to be reactive to the user input. The user
>> should only be presented with the relevant forms question/input that comply
>> with the rules for the 'XYZ' type and context (their answers to previous
>> questions that may trigger another set of questions).4. The system should
>> group questions into multiple input forms rather than have one large
>> form.5. The system should allow the user to "navigate" between the
>> collection of forms until the "OK to submit" rule is satisfied, only
>> displaying the relevant form questions for the 'XYZ' type and context.
>> There over 1500 information elements in the superset and it is likely that
>> even for the simplest 'XYZ' type (single party), at least 50 information
>> elements will be required. There will be collections in some cases (e.g.
>> "job history").
>> The rules while many, are not complex (no calculations) and focused around
>> "If the user answered "yes" to this question then ask them to complete
>> another section of information." Some rules will apply to multiple 'XYZ'
>> types. I
>> ISIS allows us to hide/unhide, enable/disable properties, objects, etc.
>> dynamically. It's just a question of the rules. Coding the rules would be
>> difficult to maintain because of the size of the data set and the number of
>> 'XYZ' types (About 10 main types, with each type having several variations).
>> From a domain model perspective, there is :
>> A "Party" component which has Party details, Party relationships, contact
>> details. fairly standard stuff
>> A "XyzApplication Lodgement" component that is centered around a
>> Moment-Interval archetype called "XyzApplication" which as you might guess,
>> has a large number of MI-Detail class/object (e.g. JobHistory). And it has
>> a large number of Role archetype class/object that are roles played by
>> "Party" wrt "XyzApplication".
>> Any thoughts on how and what for the rules management and present "smart
>> form" would be appreciated.
>> N.B> If you think you might like to answer this, there is no urgency for
>> answers - if I don't see anything for a few weeks, I will try again :)
>> Regards,David.
>> 
>> 


Óscar Bou Bou
Responsable de Producto
Auditor Jefe de Certificación ISO 27001 en BSI
CISA, CRISC, APMG ISO 20000, ITIL-F

   902 900 231 / 620 267 520
   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>

   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>

   http://www.GesConsultor.com <http://www.gesconsultor.com/> 




Este mensaje y los ficheros anexos son confidenciales. Los mismos contienen 
información reservada que no puede ser difundida. Si usted ha recibido este 
correo por error, tenga la amabilidad de eliminarlo de su sistema y avisar al 
remitente mediante reenvío a su dirección electrónica; no deberá copiar el 
mensaje ni divulgar su contenido a ninguna persona.
Su dirección de correo electrónico junto a sus datos personales constan en un 
fichero titularidad de Gesdatos Software, S.L. cuya finalidad es la de mantener 
el contacto con Ud. Si quiere saber de qué información disponemos de Ud., 
modificarla, y en su caso, cancelarla, puede hacerlo enviando un escrito al 
efecto, acompañado de una fotocopia de su D.N.I. a la siguiente dirección: 
Gesdatos Software, S.L. , Paseo de la Castellana, 153 bajo - 28046 (Madrid), y 
Avda. Cortes Valencianas num. 50, 1ºC - 46015 (Valencia). Asimismo, es su 
responsabilidad comprobar que este mensaje o sus archivos adjuntos no contengan 
virus informáticos, y en caso que los tuvieran eliminarlos.





Reply via email to