Hints how to adapt a Wicketizer generated Project

Wicketizer gives you a complete running application - here comes where to adapt it to your flavour.
For Each Table you will find a MenuItemPanel, which is filled with two MenuItemLink objects.
All that is handled in the class BasePage, which is in your.packagestructure.in.jar.file ..util.BasePage (e.g. you gave org.wicketizer.myproject.hib.(Allyour Classes), you will find the BasePage in org.wicketizer.myproject.util.BasePage).

In that Class the method getMenuItems is responsible for Menu Structure. The Menu is build with the Composite Pattern (MenuItem is parent class, MenuItemPanel and MenuItemLink are the children).
The Panel returned by Method is not shown in Menustructure, so leave the Menu
MenuItem result = new MenuItemPanel("base", null, true);
Add all your MenuItemPanel and MenuItemLink to the result MenuItemPanel Object and return that result Object at the end of the getMenuItemPanels.

Hint: You can use the menuPanels hierarchically - I have tested up to 4 Levels - it should work also with more, although that will turn into a doubtable usability.

How to adapt the security in a Wicketizer generated Project

By default Wicketizer will request authentification for all pages (but login Page). Any user with a password longer than 5 digits will be allowed to enter.
This is done as usuall in Wicket. In de.upsb.mbo.AppMbo, which extends WebApplicatio, the following code is responsible for activating Security for all Children of BasePage and redirecting to LoginPage
  protected void init() {
    getSecuritySettings().setAuthorizationStrategy(
        new SimplePageAuthorizationStrategy(BasePage.class,LoginPage.class) {
        protected boolean isAuthorized() {
          return ((MySession) Session.get()).isUserValid();
        }
    });
  }
As you might guess, the Method isUserValid in Session Object handles the validation.
That is in your hibernate.packagestruckture..util.MySession (e.g. you gave org.wicketizer.myproject.hib.(Allyour Classes), you will find the BasePage in org.wicketizer.myproject.util.MySession)

Hibernate -completed

Ensure that your hibernate classes will implement Interface Compareable and are complete:
Therefore add Example:
	public int compareTo(Bankinginfo o) {
		// equal if ident is equal,
		int result = -1;

		if (o.getIdent() == this.ident) {
			result = 0;
		} else if(o.getIdent() == this.ident) {
			result=1;
		}
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj.getClass().isInstance(Bankinginfo.class)) {
			Bankinginfo cg= (Bankinginfo) obj;
			return compareTo(cg) == 0;
		} else {
			return super.equals(obj);
		}
	}
	
	@Override
	public int hashCode() {
		return ident>0?ident:super.hashCode();
	}

Hibernate -Example vs. Subselect

Wicketizers Projects are using both: HQL and Criteria API.
HQL is used in DAOs - mainly used to Fill Comboboxes.
Criteria API is used in Restriction Builder to fill (Ajax)ListPanels (and thereby indirectly also to fill EditPanel).

The implementation for Criteria API is done in two places : What does that mean?
The Filter is used as a Builder for the Criteria. It calls by Default the RestrictionBuilder to add a Restiction for an related Object.
If you add the Restriction in the RestrictionBuilder, all relattions to the Object will be affected. If you add your Restriction in the Filter, only that one Relation is affected.
Example 1:
Ampifiershop      Notesshop
      |               |
       --------------- 
               |
           Guitarplayer
Notesshop is interested in all Guitarplayers as customer. But for a shop which sells Amplifiers only the Guitarplayers who play Electric Guitars are of interest.
If you will add a Restriction in the Restrictionbuilder ( ... criteria.add(Restrictions.propertyeg("guitartype", ""electric"))) in such a case, you would narrow the results for the Notesshop, too. For this scenario you would add the Restriction in the AmplifiershopFilter (public Criteria getListForCurrentFiltersettings(Session session))).

So far so good. But there is a trap
The problem is with that Criteria API you cannot by now use a subselect together with an Example Object.
I use "Example" to add Restrictions to Criteria. That is not working together with Subselects.
If you want to implement a subselect, you cannot use Example.
Therefore you have to adapt the public Criteria getListForCurrentFiltersettings(Session session) method (or the corresponding Method in RestrictionBuilder).

What you have to do is do not use the RestricionBuilder, instead implement all Restricions manually along with the Subselect.
Example 2: SELECT * from Flat f WHERE f.houseident IN(SELECT ident from House h WHERE h.ident= '4711')
(just a subselect)
 	public Criteria getListForCurrentFiltersettings(Session session) {

		[...]

		// type of Selection: Flat
		if (getFlat() != null && filterHouse== null) {
			RestrictionsBuilder.addRestrictions(criteria, getFlat());
		}

		if (filterHouse != null) {
			DetachedCriteria detachedCrit = DetachedCriteria.forClass(Flat.class);
			if (getFlat() != null && getFlat().getIdent() > 0) {
				detachedCrit.add(Restrictions.eq("ident", getFlat().getIdent()));
			}
			// replace 4711 whith dynamic value, e.g. filterHouse.getIdent();
			detachedCrit.add(Restrictions.eq("house.ident", "4711")) 
			detachedCrit.setProjection(Projections.id());

			criteria.add(Subqueries.propertyIn("flat", detachedCrit));
		}
		return criteria;
	}
Example 3: SELECT * from Counter c WHERE c.flatident IN(SELECT ident from Flat f WHERE f.houseident IN(SELECT ident from House h WHERE h.ident = '4711')))
	public Criteria getListForCurrentFiltersettings(Session session) {
		Criteria criteria = session.createCriteria(Countervalue.class);
				
		[...]

		// type of Selection: Counter   && filterHouse== null
		if (getCounter() != null ) {
			RestrictionsBuilder.addRestrictions(criteria, getCounter());
		}

		if (filterHouse != null ){
			DetachedCriteria detachedCritFlat = DetachedCriteria.forClass(Flat.class);
			// replace 4711 whith dynamic value, e.g. filterHouse.getIdent();
			detachedCritFlat.add(Restrictions.eq("house.ident", "4711"));
			detachedCritFlat.setProjection(Projections.id());
			
			DetachedCriteria detachedCrit = DetachedCriteria.forClass(Counter.class);
			if (getCounter() != null && getCounter().getIdent() > 0) {
				detachedCrit.add(Restrictions.eq("ident", getCounter().getIdent()));
			}
			detachedCrit.add(Subqueries.propertyIn("flat", detachedCritFlat));
			detachedCrit.setProjection(Projections.id());
			
			criteria.add(Subqueries.propertyIn("counter", detachedCrit));
		}
		return criteria;
	}
Explanation: Use 2 DetachedCriteria objects and narrow in two steps -(first Flats for House, that Counters for this Flats) The detachedCritFlat is for Flats and is restricted to House house Flats only.
The detachedCrit restricts to selected Counters only AND to the subselect for detachedCritFlat.
The final criteria is restricted by detachedCrit.

IMHO that is a little complicated, but it works. If Someone has a simpler Solution, please let me know ( info[AT]]wicketizer.org ). Marcus Bosten
20090315