Implements the JSP Tag Library to use makumba in JSP pages.

## The Makumba JSP rendering engine

See also a graphical description of the terms below.
The Makumba JSP rendering engine runs the algorithmic process of converting mak:list, mak:object, mak:value, mak:input to OQL queries and going through their results to display the data in pages . The rendering engine must overcome a wealth of deficinencies of the JSP standard. The JSP standard offers limited capabilities in regard to:

- page identification: it is impossible to know which page has a tag been declared in. It is possible to find out which page has been requested, but if that page includes other pages, there is no way to find out if the tag is in an included file or not. The tomcat-dependent class {@link org.makumba.view.jsptaglib.TomcatJsp} solves the problem
- page analysis: JSP provides a way to get access to an XML image of the JSP file, but whatever analysis is done there is not accessible to the tags at page runtime
- tag identification: the javax.servlet.jsp.tagext.Tag class has no way of identifying itself (e.g. it knows that "I'm a mak:list tag" but it does not know "I am the mak:list query from file F, line C, column L, my constant attributes are as follows: from=... where=...., I contain the following mak:list tags.... and the following mak:value tags:...., my mak:list parent is ...., therefore my query will be: .... ". This problem is solved by parsing the JSP page in classes like {@link org.makumba.util.JspParseData} and {@link org.makumba.view.jsptaglib.MakumbaJspAnalyzer }
- communication between instances of the same tag: if two javax.server.jsp.tagext.Tag represent the same physical tag executing at different times within the same request, it is impossible for the first to leave some data for the other to pick up on and continue

## Terms used for taglib implementation

To explain in more detail how the above problems are solved, we will resort to a glossary of terms, which should be referred from the javadocs of the classes in this package.

- iteration: an iteration of a mak:list (or mak:object, below all references to mak:list also stand for mak:object)
- parentList: below, A is the parent mak:list of B (same goes for any combination of mak:list and mak:object)

      <mak:list A >
      ...<some:otherTagThatIsNotMakListOrObject C > ...
         <mak:list B>
         ...
         </mak:list>
      ...</some:otherTagThatIsNotMakListOrObject> ...
      </mak:list>

- rootList: a mak:list that has no parentList
- parentIteration: an iteration of the parentList of the mak:list.
  parentIterations are important because the object that represents the mak:list (of type {@link org.makumba.view.jsptaglib.QueryTag} ) changes between one parent iteration and another. Due to that, makumba must keep somewhere the data iterated by a mak:list, and retrieve it at each parentIteration.
- iterationGroup: all iterations of a mak:list that are done within the same parentIteration (by the same {@link org.makumba.view.jsptaglib.QueryTag})
- listQuery: every mak:list from the page produces a query.
  The query is executed only once (if not repeated via some scriplet), no matter how many parent iterations there are.
- parentQuery: queries are derived from the query of the parent mak:list tag, by adding the FROM and WHERE sections. This is done in {@link org.makumba.view.ComposedQuery}
- listData: the results of the listQuery
- iterationGroupData: the part of the listData that is iterated through during an iterationGroup
- nullableValueQuery: if a mak:value or mak:input (mentioned only as mak:value in what follows) has an expression of the form label.ptr1.ptr2.ptr3.field and any of ptr1...N is nullable, that mak:value will introduce a separate query, whose parentQuery is the listQuery of the parent mak:list. Consider the following example

      RestaurantCook.mdd
        person = not null ptr Person
        favoriteDish = ptr Dish ; NULLABLE!

      cookView.jsp
        <mak:list from="general.RestaurantCook rc" />
          <mak:value expr="rc.person.name" />
         <mak:value expr="rc.favoriteDish.name" />
        </mak:list>

  If there would be a single query, then the cooks who have no favoriteDish pointer filled in (nullable, so it's possible) would not be returned by the list query (simplified notation):

        SELECT p.name, d.name
        FROM   RestaurantCook rc, Person p, Dish d
        WHERE  rc.person = p AND rc.favoriteDish = d ;

  because the where condition "rc.favoriteDish = d" cannot be fulfilled for those cooks that have rc.favoriteDish = NIL. So instead you do the listQuery:

        SELECT p.name
        FROM   RestaurantCook rc, Person p
        WHERE  rc.person = p ;

  and the nullableValueQuery:

        SELECT p.name, d.name
        FROM   RestaurantCook rc, Person p, Dish d
        WHERE  rc.person = p AND rc.favoriteDish = d ;

  All mak:value's whose expression is nullable due to the same pointer should be computed as projections in the same nullableValueQuery.

- setFieldValueQuery: if a mak:value or mak:input has an expression of the form label.ptr1...ptrN.setField, that mak:value
  will introduce a separate query whose parent is the listQuery of the parent mak:list. setFieldValueQueries are especially used to generate HTML <select> for mak:inputs
- valueQuery: a nullableValueQuery or setFieldValueQuery
- queryMak:value: mak:value/input that does generates a valueQuery, i.e. a query that is forced not by the mak:list per-se, but because of the special data type of the projections
- nonQueryMak:value: mak:value/input that does not generate a valueQuery
- valueProjection: a query projection that corresponds to an nonQueryMak:value.
  Basically every nonQueryMak:value needs to know which query it should read its result from, and which projection (column) of that query corresponds to that nonQueryMak:value . The queryMak:values need to know their valueQuery. In addition queryMak:values that introduce nullableValueQueries also need to know which projection of the nullableValueQuery corresponds to them, because a nullableValueQuerymay be shared by more mak:values
- listGroup: a rootList and all the children mak:lists and mak:values. The rootList has no parent, this is equivalent to having one single parentIteration. So the {@link org.makumba.view.jsptaglib.QueryTag} of a rootList will never change due to parentIterations. That makes it a good candidate to store the data of all its enclosed listQueries and valueQueries. Before storing them, it must execute the queries. So the rootList of the listGroup will execute all the listQueries and valueQueries.
- queryProjection: a column selected in a query (i.e. between SELECT and FROM, comma-separated)
- currentListData: the data row (all queryProjections) from the current iteration of a mak:list or mak:object. Also referred to as the data of an iteration
- currentDataSet: a stack containing the the currentListData of each listQuery that is currently iterating: the data of the current iteration, the data of the parentIteration... and finally the currentDataSet of the rootList at the bottom of the stack. A mak:list will push its current result in the stack at the begining of each iteration, and will pop it out at the end.
- keyLabels: the labels declared in the FROM of a query

    <mak:object from="best.johnny.Season ssn" where="ssn.name = $season" >

-> key label is ssn

- keyProjections: queryProjections made from keyLabels.
  The keyLabels are always (i think) selected as projections, whether they are requested in mak:values or not. All key projections selected in a parent are selected in the children, but not the reverse.
- The rule of the query rendering engine:
  In a currentDataSet, the value of a keyProjection in a listQuery currentListData is equal to the value of that keyProjection in the parentQuery
  currentListData, if it is selected there.
- grouping: to determine an iterationGroupData from a listData (which a {@link org.makumba.view.jsptaglib.QueryTag} should do when it starts), one has to choose all rows from the list data that have the keyProjections equal to those currently iterated by the parentQueriesas stored in the
  currentDataSet. This is done with the help of class {@link org.makumba.view.Grouper}.

    	<mak:list from="lbg l"><mak:value "l.name"/>
      		<mak:list from="members m" where="m.homeLbg = l">
    		<mak:value "m.firstName" />
      		</mak:list>
    	</mak:list>

will result in 2 queries:

    	1/ SELECT l, l.name from Lbg l
    	2/ SELECT l, l.name, m.firstName from Lbg l, Members m WHERE m.homeLbg=l ;

When iterating thru the inner mak:list, the iterationGroupData is selected from the entire list data (of query 2) by selecting only that data for which 'l' (the keyProjection) is equal to the 'l' of the current parent iteration. In other words:
iterationGroupData=grouper(listData, currentDataSet)
where listData (for that mak:list) is computed by the root tag by running that mak:list's listQuery, and stored in the listGroup
actually what happens is

    // at group list start
    Grouper listDataGrouper= new Grouper(dataAboutKeys, listData)

    // then, for every parent iteration
    iterationGroupData=listDataGrouper.getData(currentDataSet)

- to determine a value displayed by queryMak:value, we need to apply the same pattern

    	valueQueryData=grouper(valueQueryResult, currentDataSet)

where valueQueryResult (for that mak:value) is computed by the root tag by running that value query, and stored in the list group for nullableValueQuery mak:values, the valueQueryData can be of length 0 (a null pointer) or 1 (not-null pointers). For setFieldValueQueries it can be of any length.

- tagKey: a key that uniquely identifies a mak:list/object or mak:value/input/editForm tag within the page. The key is made from the tag attributes that cannot cahnge at execution time (mak:list from, where, orderBy, mak:value expr) and the key of the parentList. They key is used for the mak:list/valueto find its listData at the begining of a parentIteration (from which it computes the iterationGroupData), by mak:value/input/editForm to find their value in the iterationGroupData of the parentList (for nonQueryMak:values) or of their own valueQuery
- queryKey: a key that uniquely identifies a listQuery or valueQuery within the page. The querykey of listQueries is the same with their mak:list tagKey. The queryKey of a valueQuery is the queryKey of the parentList plus the path to the nullable pointer that lead to the creation of the nullableValueQuery (this ensures that values that are nullable due to the same pointer will share the same query) or the set field for setValueQuery.

@see org.makumba.view