Source for org.jfree.report.data.GlobalMasterRow

   1: /**
   2:  * ========================================
   3:  * JFreeReport : a free Java report library
   4:  * ========================================
   5:  *
   6:  * Project Info:  http://reporting.pentaho.org/
   7:  *
   8:  * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors.
   9:  *
  10:  * This library is free software; you can redistribute it and/or modify it under the terms
  11:  * of the GNU Lesser General Public License as published by the Free Software Foundation;
  12:  * either version 2.1 of the License, or (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  15:  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  16:  * See the GNU Lesser General Public License for more details.
  17:  *
  18:  * You should have received a copy of the GNU Lesser General Public License along with this
  19:  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  20:  * Boston, MA 02111-1307, USA.
  21:  *
  22:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
  23:  * in the United States and other countries.]
  24:  *
  25:  * ------------
  26:  * $Id: GlobalMasterRow.java 3525 2007-10-16 11:43:48Z tmorgner $
  27:  * ------------
  28:  * (C) Copyright 2000-2005, by Object Refinery Limited.
  29:  * (C) Copyright 2005-2007, by Pentaho Corporation.
  30:  */
  31: package org.jfree.report.data;
  32: 
  33: import org.jfree.report.DataRow;
  34: import org.jfree.report.DataSourceException;
  35: import org.jfree.report.flow.ReportContext;
  36: 
  37: /**
  38:  * This data row holds all statefull information from the datasources of the
  39:  * report.
  40:  * <p/>
  41:  * When doing subreports, a datarow only has access to its own dataset and the
  42:  * columns from the next direct subreport, which have been marked as exported.
  43:  *
  44:  * @author Thomas Morgner
  45:  */
  46: public final class GlobalMasterRow
  47: {
  48:   // private StaticDataRow previousRow;
  49:   private ReportDataRow reportDataRow;
  50:   private ParameterDataRow parameterDataRow;
  51:   private ExpressionDataRow expressionDataRow;
  52:   private GlobalMasterRow parentDataRow;
  53:   private GlobalView globalView;
  54:   private ImportedVariablesDataRow importedDataRow;
  55: 
  56:   private GlobalMasterRow()
  57:   {
  58:   }
  59: 
  60:   public static GlobalMasterRow createReportRow(final ReportContext reportContext)
  61:   {
  62:     final GlobalMasterRow gmr = new GlobalMasterRow();
  63:     gmr.globalView = GlobalView.createView();
  64:     gmr.expressionDataRow = new ExpressionDataRow(gmr, reportContext, 10);
  65:     return gmr;
  66:   }
  67: 
  68:   public static GlobalMasterRow createReportRow(final GlobalMasterRow parentRow,
  69:                                                 final ReportContext reportContext)
  70:   {
  71:     final GlobalMasterRow gmr = createReportRow(reportContext);
  72:     gmr.parentDataRow = parentRow;
  73:     return gmr;
  74:   }
  75: 
  76:   public ExpressionDataRow getExpressionDataRow()
  77:   {
  78:     return expressionDataRow;
  79:   }
  80: 
  81:   public ReportDataRow getReportDataRow()
  82:   {
  83:     return reportDataRow;
  84:   }
  85: 
  86:   public void setReportDataRow(final ReportDataRow reportDataRow)
  87:           throws DataSourceException
  88:   {
  89:     this.reportDataRow = reportDataRow;
  90:     updateGlobalView();
  91:   }
  92: 
  93:   public ParameterDataRow getParameterDataRow()
  94:   {
  95:     return parameterDataRow;
  96:   }
  97: 
  98:   public void setParameterDataRow(final ParameterDataRow parameterDataRow)
  99:           throws DataSourceException
 100:   {
 101:     this.parameterDataRow = parameterDataRow;
 102:     updateGlobalView();
 103:   }
 104: 
 105:   public GlobalMasterRow getParentDataRow()
 106:   {
 107:     return parentDataRow;
 108:   }
 109: 
 110:   public ImportedVariablesDataRow getImportedDataRow()
 111:   {
 112:     return importedDataRow;
 113:   }
 114: 
 115:   public void setExportedDataRow(final ImportedVariablesDataRow importedDataRow)
 116:           throws DataSourceException
 117:   {
 118:     this.importedDataRow = importedDataRow;
 119:     updateImportedParameterView();
 120:   }
 121: 
 122:   /**
 123:    * Derives an instance of this datarow. That copy is completly disconnected
 124:    * from the original one and no change made to that copy affects the original
 125:    * datarow.
 126:    *
 127:    * @return the derived datarow.
 128:    */
 129:   public GlobalMasterRow derive() throws DataSourceException
 130:   {
 131:     return derive(null);
 132:   }
 133: 
 134:   private GlobalMasterRow derive(final GlobalMasterRow subReportRow)
 135:           throws DataSourceException
 136:   {
 137:     final GlobalMasterRow dataRow = new GlobalMasterRow();
 138:     dataRow.parameterDataRow = parameterDataRow;
 139:     dataRow.reportDataRow = reportDataRow;
 140:     dataRow.expressionDataRow = expressionDataRow.derive(dataRow);
 141:     dataRow.globalView = globalView.derive();
 142:     if (parentDataRow != null)
 143:     {
 144:       dataRow.parentDataRow = parentDataRow.derive(subReportRow);
 145:     }
 146:     dataRow.importedDataRow = importedDataRow;
 147:     return dataRow;
 148:   }
 149: 
 150:   /**
 151:    * This advances the cursor by one row and updates the flags.
 152:    *
 153:    * @return
 154:    * @throws DataSourceException
 155:    */
 156:   public GlobalMasterRow advance() throws DataSourceException
 157:   {
 158:     return advance(false, null);
 159:   }
 160: 
 161:   private GlobalMasterRow advance(final boolean deepTraversingOnly,
 162:                                     final GlobalMasterRow subReportRow)
 163:           throws DataSourceException
 164:   {
 165:     final GlobalMasterRow dataRow = new GlobalMasterRow();
 166:     dataRow.globalView = globalView.advance();
 167:     dataRow.parameterDataRow = parameterDataRow;
 168: 
 169:     if (deepTraversingOnly == false && reportDataRow != null)
 170:     {
 171:       dataRow.reportDataRow = reportDataRow.advance();
 172:     }
 173:     else
 174:     {
 175:       dataRow.reportDataRow = reportDataRow;
 176:     }
 177:     dataRow.updateGlobalView();
 178:     if (expressionDataRow != null)
 179:     {
 180:       dataRow.expressionDataRow =
 181:               expressionDataRow.advance(dataRow, deepTraversingOnly);
 182:     }
 183:     if (parentDataRow != null)
 184:     {
 185:       // the parent row should get a grip on our data as well - just for the
 186:       // deep traversing fun and so on ..
 187:       dataRow.parentDataRow = parentDataRow.advance(true, dataRow);
 188:     }
 189:     if (importedDataRow != null)
 190:     {
 191:       if (subReportRow == null)
 192:       {
 193:         throw new NullPointerException();
 194:       }
 195:       dataRow.importedDataRow = importedDataRow.advance(subReportRow);
 196:       dataRow.updateImportedParameterView();
 197:     }
 198:     return dataRow;
 199:   }
 200: 
 201:   private void updateImportedParameterView() throws DataSourceException
 202:   {
 203:     if (importedDataRow == null)
 204:     {
 205:       return;
 206:     }
 207: 
 208:     final int parameterCount = importedDataRow.getColumnCount();
 209:     for (int i = 0; i < parameterCount; i++)
 210:     {
 211:       final String columnName = importedDataRow.getColumnName(i);
 212:       if (columnName != null)
 213:       {
 214:         final Object columnValue = importedDataRow.get(i);
 215:         globalView.putField(columnName, columnValue, true);
 216:       }
 217:     }
 218:   }
 219: 
 220:   /** This updates the global view. */
 221:   private void updateGlobalView() throws DataSourceException
 222:   {
 223:     if (parameterDataRow != null)
 224:     {
 225:       final int parameterCount = parameterDataRow.getColumnCount();
 226:       for (int i = 0; i < parameterCount; i++)
 227:       {
 228:         final String columnName = parameterDataRow.getColumnName(i);
 229:         if (columnName != null)
 230:         {
 231:           final Object columnValue = parameterDataRow.get(i);
 232:           globalView.putField(columnName, columnValue, true);
 233:         }
 234:       }
 235:     }
 236:     if (reportDataRow != null)
 237:     {
 238:       final int dataColCount = reportDataRow.getColumnCount();
 239:       for (int i = 0; i < dataColCount; i++)
 240:       {
 241:         final String columnName = reportDataRow.getColumnName(i);
 242:         if (columnName != null)
 243:         {
 244:           final Object columnValue = reportDataRow.get(i);
 245:           globalView.putField(columnName, columnValue, true);
 246:         }
 247:       }
 248:     }
 249:   }
 250: 
 251:   public boolean isAdvanceable() throws DataSourceException
 252:   {
 253:     if (reportDataRow == null)
 254:     {
 255:       return false;
 256:     }
 257:     return reportDataRow.isAdvanceable();
 258:   }
 259: 
 260:   public DataRow getGlobalView()
 261:   {
 262:     return globalView;
 263:   }
 264: 
 265:   /**
 266:    * A call back method to communicate structural changes back to the master
 267:    * rows. (This is only called from the expression row, as all other datarows
 268:    * are static).
 269:    *
 270:    * @param chEvent
 271:    */
 272:   public void dataRowChanged(final MasterDataRowChangeEvent chEvent)
 273:           throws DataSourceException
 274:   {
 275:     // rebuild the global view and tracks changes ..
 276:     final int type = chEvent.getType();
 277:     if (type == MasterDataRowChangeEvent.COLUMN_ADDED)
 278:     {
 279:       globalView.putField(chEvent.getColumnName(), chEvent.getColumnValue(), false);
 280:     }
 281:     else if (type == MasterDataRowChangeEvent.COLUMN_UPDATED)
 282:     {
 283:       globalView.putField(chEvent.getColumnName(), chEvent.getColumnValue(), true);
 284:     }
 285:     else if (type == MasterDataRowChangeEvent.COLUMN_REMOVED)
 286:     {
 287:       globalView.removeColumn(chEvent.getColumnName());
 288:     }
 289:   }
 290: }