Still no luck with this one.

The derived RegionName appears as a non-editable property, so not sure what
was different before when I was getting an model validation error.

My current code of interest is this:

    @Column(name = "region", allowsNull = "true")
    //@MemberOrder(sequence = "7")
    @Property(hidden=Where.EVERYWHERE)
    public Region getRegion() {
        return this.region;
    }

    public void setRegion(Region region) {
        this.region = region;
    }

    public List<Region> choicesRegion() {
        return regions.listAllRegions();
    }

    @MemberOrder(sequence = "7")
    public String getRegionName() {
        return regions.nameForRegion(getRegion());
    }

    public void setRegionName(String name) {
        setRegion(regions.regionForName(name));
    }

    public List<String> choicesRegionName(){
        return regions.listAllNamesExclusive(getRegion());
    }

My Region class is this:

package au.com.scds.chats.dom.modules.general.codes;

import javax.jdo.annotations.Column;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PrimaryKey;

import org.apache.isis.applib.annotation.Action;
import org.apache.isis.applib.annotation.ActionLayout;
import org.apache.isis.applib.annotation.DomainServiceLayout;
import org.apache.isis.applib.annotation.DomainServiceLayout.MenuBar;
import org.apache.isis.applib.annotation.MemberOrder;
import org.apache.isis.applib.annotation.PropertyLayout;

@javax.jdo.annotations.PersistenceCapable(
         identityType=IdentityType.APPLICATION)
public class Region {

    public String title(){
        return getName();
    }

    private String name;

    @Column(name="region", allowsNull = "false")
    @PrimaryKey()
    @PropertyLayout(named="Region")
    @MemberOrder(sequence="1")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

My Regions repository class is this:

package au.com.scds.chats.dom.modules.general.codes;

import java.util.ArrayList;
import java.util.List;

import org.apache.isis.applib.DomainObjectContainer;
import org.apache.isis.applib.annotation.Action;
import org.apache.isis.applib.annotation.ActionLayout;
import org.apache.isis.applib.annotation.BookmarkPolicy;
import org.apache.isis.applib.annotation.DomainService;
import org.apache.isis.applib.annotation.DomainServiceLayout;
import org.apache.isis.applib.annotation.DomainServiceLayout.MenuBar;
import org.apache.isis.applib.annotation.MemberOrder;
import org.apache.isis.applib.annotation.ParameterLayout;
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.applib.annotation.SemanticsOf;
import org.apache.isis.applib.query.QueryDefault;

import au.com.scds.chats.dom.modules.participant.Participant;

@DomainService(repositoryFor = Region.class)
@DomainServiceLayout(menuBar = MenuBar.SECONDARY, named = "Administration",
menuOrder = "100.1")
public class Regions {

    // region > listAll (action)
    @Action(semantics = SemanticsOf.SAFE)
    @ActionLayout(bookmarking = BookmarkPolicy.AS_ROOT)
    @MemberOrder(sequence = "1")
    public List<Region> listAllRegions() {
        return container.allInstances(Region.class);
    }

    // endregion

    // region > create (action)
    @MemberOrder(sequence = "2")
    public Region createRegion(
            final @ParameterLayout(named = "Region Name") String name) {
        final Region obj = container.newTransientInstance(Region.class);
        obj.setName(name);
        container.persistIfNotAlready(obj);
        return obj;
    }

    // endregion

    // region > injected services

    @javax.inject.Inject
    DomainObjectContainer container;

    // endregion

    @Programmatic
    public String nameForRegion(Region region) {
        return (region != null) ? region.getName() : null;
    }


    @Programmatic
    public List<String> listAllNamesExclusive(Region region) {
        List<Region> regions = listAllRegions();
        List<String> names = new ArrayList<String>();
        for (Region r : regions) {
            if (region != null && r != region) {
                names.add(r.getName());
            }
        }
        return names;
    }


    @Programmatic
    public Region regionForName(String name) {
        Region region = container.firstMatch(new QueryDefault<>(
Region.class,
                 "findRegion", "name", name));
        return region;
    }

}

Just maybe I there is something missing still?

I added a @Property annotation to the getRegionName() method, but that gave
me a message saying it expected @javax.jdo.persistence.Column too.

Note I couldn't use deprecated @Hidden in Isis 1.9.0.


On Thu, Jul 30, 2015 at 8:14 PM, Stephen Cameron <[email protected]
> wrote:

> Hi Dan, When I tried this I got an model validation error message relating
> to the choices method, I will have another go and if it fails, provide the
> test case. Thanks for the tips.
>
> On Thu, Jul 30, 2015 at 7:57 PM, Dan Haywood <[email protected]
> > wrote:
>
>> You should be able to add a choicesXxx() for the derived property:
>>
>>     public List<String> choicesRegionName(){
>>         return Lists.newArrayList(Iterables.transform(choicesRegion(), x
>> ->
>> x.getName()));
>>     }
>>
>> If that isn't sufficient, you might also need to add a setter:
>>
>> public void setRegionName(final String name) {
>> setRegion(Iterables.find(choicesRegion(), x -> x.getName().equals(name)));
>> }
>>
>> Obviously, you might need to also add some error handling.
>>
>> ~~~
>>
>> Regarding the "external URL" idea, perhaps you could raise that as a
>> separate ticket, with a code sketch as to how you'd like this information
>> specified?
>>
>> Thanks
>> Dan
>>
>>
>>
>>
>>
>> On 30 July 2015 at 03:17, Stephen Cameron <[email protected]>
>> wrote:
>>
>> > Not so simple, as now the property cannot be updated.
>> >
>> > I have the following (@Hidden is deprecated)
>> >
>> >     @Column(allowsNull = "true")
>> >     @MemberOrder(sequence = "7")
>> >     @PropertyLayout(hidden=Where.EVERYWHERE)
>> >     public Region getRegion() {
>> >         return this.region;
>> >     }
>> >
>> >     public void setRegion(Region region) {
>> >         this.region = region;
>> >     }
>> >
>> >     public List<Region> choicesRegion(){
>> >         List<Region> regions = container.allInstances(Region.class);
>> >         return regions;
>> >     }
>> >
>> >     @MemberOrder(sequence = "7.1")
>> >     public String getRegionName(){
>> >         return (getRegion() != null) ? getRegion().getName() : null;
>> >     }
>> >
>> > Sure enough getRegion doesn't appear in the UI but getRegionName does,
>> but
>> > then setRegion and choiceRegion don't mean anything to the UI, so the
>> > Region property is read-only.
>> >
>> > This issue is maybe more significant than it appears at first, in terms
>> of
>> > domain modelling such code-lists are simple types that 'represent'
>> things
>> > on the boundary of the domain of interest. So we usually want to just
>> > represent them with a name. Presently it makes no sense to go to that
>> thing
>> > via a hyperlink as all we'll find is that name, our model extends no
>> > further.
>> >
>> > However we just might like to allow users to leave the domain model and
>> go
>> > to a resource outside. So, extending the suppressLink=true idea, I would
>> > add that each object could have an implicit link(URL),created by Isis,
>> or
>> > an explicit one and if the explicit one is present it can optionally be
>> > used as an alternative to the implicit one.
>> >
>> > For example, you might create a database to log fish details, species
>> is a
>> > boundary concept, we aren't likely to want to add a new species to the
>> list
>> > of known species, but we'd like to keep such a list handy, but for each
>> > named species in that list, to provide an explicit link to a resource
>> in a
>> > global fish database. It makes more sense to use this link than the
>> > implicit one, as if the implicit one is used we'd navigate to the domain
>> > object page displaying the name and URL, both of which items of data
>> could
>> > have been in the explicit link.
>> >
>> > In the explicit case you might want to warn the user they are navigating
>> > outside the Isis domain application.
>> >
>> > Perhaps all this could be done simply if there was a URI type in Isis,
>> that
>> > would allow it to create 'smart links' automatically.
>> >
>> >
>> >
>> >
>> >
>> > On Wed, Jul 29, 2015 at 9:37 PM, Stephen Cameron <
>> > [email protected]
>> > > wrote:
>> >
>> > > Thanks Jeroen, seems simple enough :)
>> > >
>> > > On Wed, Jul 29, 2015 at 9:28 PM, Jeroen van der Wal <
>> [email protected]
>> > >
>> > > wrote:
>> > >
>> > >> You could also hide the property and create a separate getter for
>> > display
>> > >> purposes only:
>> > >>
>> > >> private MyProperty myProperty;
>> > >>
>> > >> @Hidden
>> > >> public MyProperty getMyProperty() {...}
>> > >>
>> > >> public void setMyProperty(...) {...}
>> > >>
>> > >> public String getMyPropertyName() {
>> > >>     getMyProperty.getName();
>> > >> }
>> > >>
>> > >> On 29 July 2015 at 13:18, Stephen Cameron <
>> [email protected]>
>> > >> wrote:
>> > >>
>> > >> > On Wed, Jul 29, 2015 at 6:38 PM, Dan Haywood <
>> > >> [email protected]
>> > >> > >
>> > >> > wrote:
>> > >> >
>> > >> > > You are right, they will be displayed as links; there's no way to
>> > >> disable
>> > >> > > it currently.
>> > >> > >
>> > >> > > We could add a bit of metadata perhaps for this, eg
>> > >> > > @DomainObjectLayout(suppressLink=true) or similar.
>> > >> > >
>> > >> > > Please raise a ticket.
>> > >> > >
>> > >> >
>> > >> > OK https://issues.apache.org/jira/browse/ISIS-1180
>> > >> >
>> > >> > >
>> > >> > > Thx
>> > >> > > Dan
>> > >> > >
>> > >> > > PS: these entities wouldn't be value types, rather regular
>> entities.
>> > >> But
>> > >> > > you are right... what we really want is full-class support for
>> value
>> > >> > types.
>> > >> > >   We're just not there yet...
>> > >> > >
>> > >> > >
>> > >> > >
>> > >> >
>> > >> > >
>> > >> > >
>> > >> > > On 29 July 2015 at 09:34, Stephen Cameron <
>> > [email protected]
>> > >> >
>> > >> > > wrote:
>> > >> > >
>> > >> > > > Thanks, but surely such object properties always end up being
>> > >> displayed
>> > >> > > as
>> > >> > > > links? Clicking on the link to go to such an object page is
>> > >> > meaningless,
>> > >> > > as
>> > >> > > > it only has one name property, that was displayed in the link.
>> > Can I
>> > >> > > > disable that default behaviour for value types?
>> > >> > > >
>> > >> > > >
>> > >> > > >
>> > >> > > > On Wed, Jul 29, 2015 at 5:47 PM, Dan Haywood <
>> > >> > > [email protected]
>> > >> > > > >
>> > >> > > > wrote:
>> > >> > > >
>> > >> > > > > On 29 July 2015 at 08:08, Stephen Cameron <
>> > >> > [email protected]>
>> > >>
>> > >> > > > > wrote:
>> > >> > > > >
>> > >> > > > > > Hi,
>> > >> > > > > >
>> > >> > > > > > I want to do have some properties that are essentially
>> String
>> > >> > types,
>> > >> > > > but
>> > >> > > > > > which have a limited range of values (code-lists or
>> restricted
>> > >> > > > > > vocabularies). I want to allow these lists to be
>> administered
>> > >> > > > centrally,
>> > >> > > > > so
>> > >> > > > > > to add them to a single Administration menu item for admin
>> > >> users.
>> > >> > > > > >
>> > >> > > > > > For most users these codes should appears as lists of
>> strings
>> > >> not
>> > >> > as
>> > >> > > > > > objects, but making them objects seems to be the logical OO
>> > way
>> > >> to
>> > >> > > deal
>> > >> > > > > > with them in Isis. So they are basically objects with one
>> > 'name'
>> > >> > > > property
>> > >> > > > > > (and maybe an id added by datanucleus). All users need to
>> see
>> > is
>> > >> > the
>> > >> > > > name
>> > >> > > > > > property, no icon is needed.
>> > >> > > > > >
>> > >> > > > > > Also, if I make them objects I also will get referencial
>> > >> integrity
>> > >> > > > > > constraints applied in the database.
>> > >> > > > > >
>> > >> > > > > >
>> > >> > > > > +1, do it this way.  That way they can also hold behaviour in
>> > the
>> > >> > > future.
>> > >> > > > >
>> > >> > > > >
>> > >> > > > >
>> > >> > > > >
>> > >> > > > > > I wonder there is a simple recipe for this?
>> > >> > > > > >
>> > >> > > > >
>> > >> > > > > No magic recipe for the domain entities... basically
>> > copy-n-paste
>> > >> the
>> > >> > > > > SimpleObject that's in our archetype as many times as needed,
>> > and
>> > >> > tweak
>> > >> > > > as
>> > >> > > > > required.
>> > >> > > > >
>> > >> > > > > If you want to use the code as the primary key, then use DN
>> > >> > application
>> > >> > > > > identity
>> > >> > > > >
>> > >> > > > > @javax.jdo.annotations.PersistenceCapable(
>> > >> > > > >         identityType=IdentityType.APPLICATION,
>> > >> > > > >         schema = "simple",
>> > >> > > > >         table = "SimpleObject"
>> > >> > > > > )
>> > >> > > > >
>> > >> > > > > and add @PrimaryKey to the "name" property.  Also add @Title
>> to
>> > >> that
>> > >> > > > 'name'
>> > >> > > > > property (it is in SimpleObject already).
>> > >> > > > >
>> > >> > > > >
>> > >> > > > > You would probably want to remove the version column, ie
>> remove:
>> > >> > > > >
>> > >> > > > > @javax.jdo.annotations.Version(
>> > >> > > > >         strategy=VersionStrategy.VERSION_NUMBER,
>> > >> > > > >         column="version")
>> > >> > > > >
>> > >> > > > >
>> > >> > > > > In addition, if you annotate the class as "bounded"
>> > >> > > > > (@DomainObject(bounded=true)) then you are telling the
>> framework
>> > >> that
>> > >> > > > > there's a limited - ie bounded - set of instances, and so it
>> > will
>> > >> > > display
>> > >> > > > > all instances in a drop-down for you.
>> > >> > > > >
>> > >> > > > >
>> > >> > > > > HTH
>> > >> > > > > Dan
>> > >> > > > >
>> > >> > > >
>> > >> > >
>> > >> >
>> > >>
>> > >
>> > >
>> >
>>
>
>

Reply via email to