Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

which takes a model object and a property expression. When the property model is asked for its value by the framework, it will use the property expression to access the model object's property. For example, if we have a Java Bean or "POJO" (Plain Old Java Object) like this:

Code Block
class Person
{
	  private String name;

	  Person(String name)
	  {
		    this.name = name;
	  }

	  String getName()
	  {
		    return name;
	  }
}

then the property expression "name" can be used to access the "name" property of any Person object via the getName() getter method.

...

Code Block
public class Address
  implements Serializable 
{

	  private String city;


	  public Address()
  {
		super     super();
	  }

	  public String getCity()
  {
		    return city;
	  }

	  public void setCity(String city)
  {
		    this.city = city;
	  }

}


public class Person
  implements Serializable 
{

	  private String name;
	  private int age;

	  private Address address;


	  public Person()
  {
		    super();
	  }

	  public String getName()
  {
		    return name;
	  }

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

	  public int getAge()
  {
		    return age;
	  }

	  public void setAge(int age)
  {
		    this.age = age;
	  }

	public  public Address getAddress()
  {
		    return address;
	  }

	  public void setAddress(Address address)
  {
		    this.address = address;
	  }

}

The first step is to create a Wrapped Object Model for the Address and Person classes:

Code Block
public class AddressModel
  implements IModel 
{

	  private IModel addressContainingModel;

	  private AddressModelType type;

	  public enum AddressModelType
  {
    CITY_MODEL;
  };

	  public AddressModel(IModel addressContainingModel, AddressModelType type)
  {
		    this.addressContainingModel = addressContainingModel;
		    this.type = type;
	  }

	  @Override
	  public Object getObject()
  {

		    Address address = (Address) addressContainingModel.getObject();

		switch     switch (type)
    {

		      case CITY_MODEL:

			        return address.getCity();
		    }

		    throw new UnsupportedOperationException ("invalid AddressModelType = "
                                            + type.name());
	  }

	  @Override
	  public void setObject(Object object)
  {

		    Address address = (Address) addressContainingModel.getObject();

		    switch (type)
    {

		      case CITY_MODEL:

			        address.setCity((String) object);
        break;
      default:
        throw new UnsupportedOperationException("invalid AddressModelType = break;"
                default:
                         throw new UnsupportedOperationException ("invalid AddressModelType = " + type.name());
		    }

	  }

	  @Override
	  public void detach()
  {

		    addressContainingModel.detach();

	  }

}


public class PersonModel
  implements IModel 
{

	  private IModel personContainingModel;
	  private PersonModelType type;

	  public enum PersonModelType
  {
    NAME_MODEL, AGE_MODEL, ADDRESS_MODEL;
  }

	  public PersonModel(IModel personContainingModel, PersonModelType type)
  {
		    this.personContainingModel = personContainingModel;
		    this.type = type;
	  }

	  @Override
	  public Object getObject()
  {
		    Person person = (Person) personContainingModel.getObject();

		    switch (type)
    {

		      case NAME_MODEL:

			        return person.getName();

		      case AGE_MODEL:
			        return new Integer (person.getAge());

		      case ADDRESS_MODEL:
			return person.getAddress();

		}

		throw new UnsupportedOperationException ("invalid PersonModelType = "
        return person.getAddress();

    }

    throw new UnsupportedOperationException("invalid PersonModelType = "
                                            + type.name());
	  }

	  @Override
	  public void setObject(Object object)
  {

		    Person person = (Person) personContainingModel.getObject();

		    switch (type)
    {

		      case NAME_MODEL:

			 person.setName((String) object);
         person.setName((String) object);
          break;

      break;

		case AGE_MODEL:
  			      person.setAge((Integer) object);
        break;

           case ADDRESS_MODEL:
      break;

		case ADDRESS_MODEL:
			 person.setAddress ((Address) object);
        break;

      default:
        throw new  break;

UnsupportedOperationException("invalid PersonModelType = "
                            default:
	             throw new UnsupportedOperationException ("invalid PersonModelType = " + type.name());
		    }

	  }

	  @Override
	  public void detach()
  {

		    personContainingModel.detach();
	  }

}

Notice how each wrapped model contains an inner model that contains the actual pojo instance. This allows for the wrapped model to be a plain Model or a LoadableDetachableModel, or even another wrapped model where its .getObject() results in a suitably typed input value (see the "address.city" field in the example below).

...

Code Block
Person p = new Person ();


		Form personForm = new Form("aPersonForm");


		personForm.add(new RequiredTextField("name", new PersonModel (new Model (p), PersonModelType.NAME_MODEL)));
		personForm.add(new RequiredTextField("age", new PersonModel (new Model (p), PersonModelType.AGE_MODEL), Integer.class));

		personForm.add(new RequiredTextField("address.city", new AddressModel (new PersonModel (new Model (p),
                                            PersonModelType.ADDRESS_MODEL), AddressModelType.CITY_MODEL)));

		add(personForm);

A wrapped object model also makes working with DataTables's easier as one IColumn implementation can be written for each object class which makes the declaration of the table much simpler.

...

Code Block
DataTable table = new DataTable("datatable", new IColumn[] {
      new PersonTableColumn ("Name", PersonModelType.NAME_MODEL),
      new PersonTableColumn ("Age", PersonModelType.AGE_MODEL),
      new PersonTableColumn ("City", PersonModelType.ADDRESS_MODEL)
  }, new PersonProvider(), 10);

...