gt:     if ( odObject == null ) {
context: /*
   * This program is free software; you can redistribute it and/or modify it under the
   * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
   * Foundation.
   *
   * You should have received a copy of the GNU Lesser General Public License along with this
   * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
   * or from the Free Software Foundation, Inc.,
   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
   * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   * See the GNU Lesser General Public License for more details.
   *
   * Copyright (c) 2001 - 2013 Object Refinery Ltd, Pentaho Corporation and Contributors..  All rights reserved.
   */
  
  package org.pentaho.reporting.engine.classic.core.modules.parser.extwriter;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.pentaho.reporting.engine.classic.core.modules.parser.ext.ExtParserModule;
  import org.pentaho.reporting.engine.classic.core.modules.parser.ext.factory.base.ClassFactoryCollector;
  import org.pentaho.reporting.engine.classic.core.modules.parser.ext.factory.base.ObjectDescription;
  import org.pentaho.reporting.engine.classic.core.modules.parser.ext.factory.base.ObjectFactoryException;
  import org.pentaho.reporting.libraries.base.util.ObjectUtilities;
  import org.pentaho.reporting.libraries.xmlns.common.AttributeList;
  import org.pentaho.reporting.libraries.xmlns.writer.XmlWriter;
  import org.pentaho.reporting.libraries.xmlns.writer.XmlWriterSupport;
  
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.List;
  
  /**
   * A writer.
   *
   * @author Thomas Morgner.
   */
  public class ObjectWriter extends AbstractXMLDefinitionWriter {
    private static final Log logger = LogFactory.getLog( ObjectWriter.class );
    /**
     * The object description.
     */
    private ObjectDescription objectDescription;
  
    /**
     * The object factory.
     */
    private ClassFactoryCollector cc;
  
    /**
     * Creates a new writer.
     *
     * @param reportWriter
     *          the report writer.
     * @param baseObject
     *          the base object (<code>null</code> not permitted).
     * @param objectDescription
     *          the object description (<code>null</code> not permitted) for the to be written object. The base object
     *          will be used to fill the object description parameters.
     * @param indentLevel
     *          the current indention level.
     * @throws ReportWriterException
     *           if no writer could be found for the given baseObject.
     */
    public ObjectWriter( final ReportWriterContext reportWriter, final Object baseObject,
        final ObjectDescription objectDescription, final XmlWriter indentLevel ) throws ReportWriterException {
      this( reportWriter, objectDescription, indentLevel );
      if ( baseObject == null ) {
        throw new NullPointerException( "BaseObject is null" );
      }
      try {
        objectDescription.setParameterFromObject( baseObject );
      } catch ( ObjectFactoryException ofe ) {
        throw new ReportWriterException( "Failed to fill ObjectDescription", ofe );
      }
    }
  
    /**
     * Creates a new object writer for the given object description.
     *
     * @param reportWriter
     *          the report writer used to write the generated description.
     * @param objectDescription
     *          the object description that should be written. It is assumed, that the object description is completly
     *          initialized for writing.
     * @param indentLevel
     *          the current code indention level
     */
    public ObjectWriter( final ReportWriterContext reportWriter, final ObjectDescription objectDescription,
        final XmlWriter indentLevel ) {
  
      super( reportWriter, indentLevel );
      if ( objectDescription == null ) {
        throw new NullPointerException( "ObjectDescription is null" );
      }
  
      this.objectDescription = objectDescription;
      cc = getReportWriter().getClassFactoryCollector();
    }
  
    /**
     * Returns the object description.
     *
     * @return The object description.
     */
    public ObjectDescription getObjectDescription() {
      return objectDescription;
    }
  
    /**
     * Returns the object factory.
     *
     * @return The object factory.
     */
    public ClassFactoryCollector getClassFactoryCollector() {
      return cc;
    }
  
    /**
     * Writes the description.
     *
     * @throws IOException
     *           if there is an I/O problem.
     * @throws ReportWriterException
     *           if the object could not be written.
     */
    public void write() throws IOException, ReportWriterException {
      final Iterator names = objectDescription.getParameterNames();
      while ( names.hasNext() ) {
        final String name = (String) names.next();
        writeParameter( name );
      }
    }
  
    /**
     * Returns a description of a parameter.
     *
     * @param name
     *          the parameter name.
     * @return The description.
     */
    protected ObjectDescription getParameterDescription( final String name ) {
  
      // Try to find the object description directly ...
      // by looking at the given object. This is the most accurate
      // option ...
      ObjectDescription parameterDescription;
      final Object o = objectDescription.getParameter( name );
      if ( o != null ) {
        parameterDescription = cc.getDescriptionForClass( o.getClass() );
        if ( parameterDescription == null ) {
          parameterDescription = cc.getSuperClassObjectDescription( o.getClass(), null );
        } else {
          return parameterDescription;
        }
      } else {
        final Class parameterClass = objectDescription.getParameterDefinition( name );
        parameterDescription = cc.getDescriptionForClass( parameterClass );
  
        if ( parameterDescription != null ) {
          return parameterDescription;
        }
  
        // try to find the super class of the parameter object.
        // maybe this can be used to save the object....
        parameterDescription = cc.getSuperClassObjectDescription( parameterClass, null );
      }
  
      if ( parameterDescription == null ) {
        ObjectWriter.logger.info( "Unable to get parameter description for parameter: " + name );
      }
      return parameterDescription;
    }
  
    /**
     * Writes a parameter to XML.
     *
     * @param parameterName
     *          the parameter name.
     * @throws IOException
     *           if there is an I/O problem.
     * @throws ReportWriterException
     *           if transforming the report into a stream failed.
     */
    protected void writeParameter( final String parameterName ) throws IOException, ReportWriterException {
      final Object parameterValue = getObjectDescription().getParameter( parameterName );
      if ( parameterValue == null ) {
        // Log.info ("Parameter '" + parameterName + "' is null. The Parameter will not be defined.");
        return;
      }
  
      final Class parameterDefinition = getObjectDescription().getParameterDefinition( parameterName );
      final ObjectDescription parameterDescription = getParameterDescription( parameterName );
      if ( parameterDescription == null ) {
        throw new ReportWriterException( "Unable to get Parameter description for "
            + getObjectDescription().getObjectClass() + " Parameter: " + parameterName );
      }
  
      try {
        parameterDescription.setParameterFromObject( parameterValue );
      } catch ( ObjectFactoryException ofe ) {
        throw new ReportWriterException( "Unable to fill parameter object:" + parameterName, ofe );
      }
  
      final List parameterNames = ObjectWriter.getParameterNames( parameterDescription );
      if ( parameterNames.isEmpty() ) {
        return;
      }
  
      final AttributeList p = new AttributeList();
      p.setAttribute( ExtParserModule.NAMESPACE, "name", parameterName );
      if ( isUseParameterObjectDescription( parameterDefinition, parameterValue ) == false ) {
        p.setAttribute( ExtParserModule.NAMESPACE, "class", parameterValue.getClass().getName() );
      }
  
      final XmlWriter writer = getXmlWriter();
      if ( ObjectWriter.isBasicObject( parameterNames, parameterDescription ) ) {
        writer.writeTag( ExtParserModule.NAMESPACE, AbstractXMLDefinitionWriter.BASIC_OBJECT_TAG, p,
            XmlWriterSupport.OPEN );
        final String valueString = (String) parameterDescription.getParameter( "value" );
        writer.writeTextNormalized( valueString, false );
        writer.writeCloseTag();
      } else {
        writer.writeTag( ExtParserModule.NAMESPACE, AbstractXMLDefinitionWriter.COMPOUND_OBJECT_TAG, p,
            XmlWriterSupport.OPEN );
  
        final ObjectWriter objWriter = new ObjectWriter( getReportWriter(), parameterValue, parameterDescription, writer );
        objWriter.write();
        writer.writeCloseTag();
      }
  
    }
  
    /**
     * Checks whether the writer would use the default object type for the given parameter type and value.
     *
     * @param parameter
     *          the defined parameter base type
     * @param o
     *          the parameter value to test
     * @return true, if the default parameter description would be used, false otherwise.
     */
    private boolean isUseParameterObjectDescription( final Class parameter, final Object o ) {
      final ClassFactoryCollector cc = getReportWriter().getClassFactoryCollector();
      ObjectDescription odObject = cc.getDescriptionForClass( o.getClass() );
      ObjectDescription odParameter = cc.getDescriptionForClass( parameter );
  
      // search the most suitable super class object description ...
  