docs: protected void createCells() {
  		DJCrosstabColumn auxCol = new DJCrosstabColumn();
  		DJCrosstabRow auxRow = new DJCrosstabRow();
  		try {
  			BeanUtils.copyProperties(auxCol, djcross.getColumns().get(djcross.getColumns().size()-1));
  			BeanUtils.copyProperties(auxRow, djcross.getRows().get(djcross.getRows().size()-1));
  		} catch (Exception e) {
  			log.error(e.getMessage(),e); //must not happend
  		}
  		auxCol.setProperty(null);
  		auxRow.setProperty(null);
  
  		List<DJCrosstabColumn> auxColsList = new ArrayList<DJCrosstabColumn>(djcross.getColumns());
  		auxColsList.add(auxCol);
  		List<DJCrosstabRow> auxRowsList = new ArrayList<DJCrosstabRow>(djcross.getRows());
  		auxRowsList.add(auxRow);
  
  		DJCrosstabColumn[] auxCols = auxColsList.toArray(new DJCrosstabColumn[]{});
  		DJCrosstabRow[] auxRows = auxRowsList.toArray(new DJCrosstabRow[]{});
  
  
  		for (int i = auxCols.length-1; i >= 0; i--) {
  			for (int j =  auxRows.length-1; j >= 0; j--) {
  				DJCrosstabColumn crosstabColumn = auxCols[i];
  				DJCrosstabRow crosstabRow = auxRows[j];
  
  				JRDesignCrosstabCell cell = new JRDesignCrosstabCell();
  
  				cell.setWidth(crosstabColumn.getWidth());
  				cell.setHeight(crosstabRow.getHeight());
  
  				boolean isRowTotal = crosstabRow.getProperty() != null;
  				boolean isColumnTotal = crosstabColumn.getProperty() != null;
  
  				if (isColumnTotal)
  					cell.setColumnTotalGroup(crosstabColumn.getProperty().getProperty());
  
  				if (isRowTotal)
  					cell.setRowTotalGroup(crosstabRow.getProperty().getProperty());
  
  				JRDesignCellContents contents = new JRDesignCellContents();
  
  				int measureIdx = 0;
  				int yOffsetCounter = 0;
  				int measureHeight = crosstabRow.getHeight() / djcross.getVisibleMeasures().size();
  
  				for (Iterator<DJCrosstabMeasure> iterator = djcross.getMeasures().iterator(); iterator.hasNext(); measureIdx++, yOffsetCounter++) {
  					DJCrosstabMeasure djmeasure = iterator.next();
                      if (!djmeasure.getVisible()) {
                          yOffsetCounter--;
                          continue; //IMPORTANT! we need to keep the idx to match the index of the measure in the measure list
                      }
  
  					JRDesignTextField element = new JRDesignTextField();
  					element.setWidth(crosstabColumn.getWidth());
  					element.setHeight(measureHeight);
  					element.setY(yOffsetCounter*measureHeight);
  
  
  					JRDesignExpression measureExp = new JRDesignExpression();
  
  					boolean isTotalCell = isRowTotal || isColumnTotal;
  
  					String measureValueClassName = djmeasure.getProperty().getValueClassName();
  
                      String measureProperty = djmeasure.getMeasureIdentifier(measureIdx);
                      String meausrePrefix = djmeasure.getMeasurePrefix(measureIdx);
  
  					if (!isTotalCell){
  						if (djmeasure.getValueFormatter()== null){
  							measureExp.setValueClassName(measureValueClassName); //FIXME Shouldn't this be of a class "compatible" with measure's operation?
                              measureExp.setText("$V{"+ measureProperty +"}");
  						} else {
                              measureExp.setText(djmeasure.getTextForValueFormatterExpression(measureProperty, djcross.getMeasures()));
  							measureExp.setValueClassName(djmeasure.getValueFormatter().getClassName());
  						}
  					} else { //is a total cell
  						if (djmeasure.getValueFormatter()== null){
  							if (djmeasure.getPrecalculatedTotalProvider() == null) {
  								measureExp.setValueClassName(measureValueClassName);
  								measureExp.setText("$V{"+measureProperty+"}");
  							} else {
  								//call the precalculated value.
  								setExpressionForPrecalculatedTotalValue(auxCols, auxRows, measureExp, djmeasure, crosstabColumn, crosstabRow, meausrePrefix);
  							}
  						} else { //have value formatter
  							if (djmeasure.getPrecalculatedTotalProvider() == null) {
  								//has value formatter, no total provider
  								measureExp.setText(djmeasure.getTextForValueFormatterExpression(measureProperty, djcross.getMeasures()));
  								measureExp.setValueClassName(djmeasure.getValueFormatter().getClassName());
  
  							} else {
  								//NO value formatter, call the precalculated value only
  								setExpressionForPrecalculatedTotalValue(auxCols, auxRows, measureExp, djmeasure, crosstabColumn, crosstabRow, meausrePrefix);
  							}
  						}
  					}
  
  					element.setExpression(measureExp);
  
  					//measure
  					if (!isRowTotal && !isColumnTotal && djmeasure.getStyle() != null ){
  						//this is the inner most cell
  						layoutManager.applyStyleToElement(djmeasure.getStyle() , element);
  					}
  					//row total only
  					if (isRowTotal && !isColumnTotal) {
  						Style style = getRowTotalStyle(crosstabRow);
  						if (style == null)
  							style = djmeasure.getStyle();
  						if (style != null)
  							layoutManager.applyStyleToElement(style, element);
  					}
  					//column total only
  					if (isColumnTotal && !isRowTotal) {
  						Style style = getColumnTotalStyle(crosstabColumn);
  						if (style == null)
  							style = djmeasure.getStyle();
  						if (style != null)
  							layoutManager.applyStyleToElement(style, element);
  					}
  					//row and column total
  					if (isRowTotal && isColumnTotal) {
  						Style style = getRowTotalStyle(crosstabRow);
  						if (style == null)
  							style = getColumnTotalStyle(crosstabColumn);
  						if (style == null)
  							style = djmeasure.getStyle();
  						if (style != null)
  							layoutManager.applyStyleToElement(style, element);
  					}
  
  					JRDesignStyle jrstyle = (JRDesignStyle) element.getStyle();
  					//FIXME this is a hack
  					if (jrstyle == null){
  						if (log.isDebugEnabled()){
  							log.warn("jrstyle is null in crosstab cell, this should have not happened.");
  						}
  						layoutManager.applyStyleToElement(null, element);
  						jrstyle = (JRDesignStyle)element.getStyle();
  						jrstyle.setBlankWhenNull(true);
  					}
  
  					JRDesignStyle alternateStyle = Utils.cloneStyle(jrstyle);
  	    			alternateStyle.setName(alternateStyle.getFontName() +"_for_column_" + djmeasure.getProperty().getProperty() + "_i" + i + "_j" + j);
  	    			alternateStyle.getConditionalStyleList().clear();
  	    			element.setStyle(alternateStyle);
  	    			try {
  	    				design.addStyle(alternateStyle);
  	    			} catch (JRException e) { /*e.printStackTrace(); //Already there, nothing to do **/}
  	    			setUpConditionStyles(alternateStyle, djmeasure, measureExp.getText());
  
  					if (djmeasure.getLink() != null){
  						String name = "cell_" + i + "_" +  j + "_ope" + djmeasure.getOperation().getValue();
  						HyperLinkUtil.applyHyperLinkToElement((DynamicJasperDesign)this.design, djmeasure.getLink(), element, name);
  					}
  
  					contents.addElement(element);
  
  				}
  
  				contents.setMode( ModeEnum.OPAQUE );
  
  				applyBackgroundColor(contents,crosstabRow,crosstabColumn,i,j);
  
  				applyCellBorder(contents, false, false);
  
  				cell.setContents(contents);
  
  
  				try {
  					jrcross.addCell(cell);
  				} catch (JRException e) {
  					log.error(e.getMessage(),e);
  				}
  
  			}
  
  		}
  	}