int OGRDODSFieldDefn::Initialize( const char *pszFieldNameIn,
                                  const char *pszFieldScopeIn,
                                  BaseType *poTarget,
                                  BaseType *poSuperSeq )

{
    pszFieldScope = CPLStrdup( pszFieldScopeIn );
    pszFieldName = CPLStrdup( pszFieldNameIn );

    if( poTarget != NULL && EQUAL(pszFieldScope,"dds") )
    {
        string oTargPath = OGRDODSGetVarPath( poTarget );
        int    nTargPathLen = strlen(oTargPath.c_str());

        if( EQUALN(oTargPath.c_str(),pszFieldNameIn,nTargPathLen)
            && pszFieldNameIn[nTargPathLen] == '.' )
        {
            CPLFree( pszFieldName );
            pszFieldName = CPLStrdup( pszFieldNameIn + nTargPathLen + 1 );

            bRelativeToSequence = TRUE;
            iFieldIndex = OGRDODSGetVarIndex(
                dynamic_cast<Sequence *>( poTarget ), pszFieldName );
        }
        else if( poSuperSeq != NULL  )
        {
            string oTargPath = OGRDODSGetVarPath( poSuperSeq );
            int    nTargPathLen = strlen(oTargPath.c_str());

            if( EQUALN(oTargPath.c_str(),pszFieldNameIn,nTargPathLen)
                && pszFieldNameIn[nTargPathLen] == '.' )
            {
                CPLFree( pszFieldName );
                pszFieldName = CPLStrdup( pszFieldNameIn + nTargPathLen + 1 );

                bRelativeToSuperSequence = TRUE;
                iFieldIndex = OGRDODSGetVarIndex(
                    dynamic_cast<Sequence *>( poSuperSeq ), pszFieldName );
            }
        }
    }

    bValid = TRUE;

    return TRUE;
}
OGRDODSSequenceLayer::OGRDODSSequenceLayer( OGRDODSDataSource *poDSIn, 
                                            const char *pszTargetIn,
                                            AttrTable *poOGRLayerInfoIn )

        : OGRDODSLayer( poDSIn, pszTargetIn, poOGRLayerInfoIn )

{
    pszSubSeqPath = "profile"; // hardcode for now. 
    panSubSeqSize = NULL;
    iLastSuperSeq = -1;

/* -------------------------------------------------------------------- */
/*      What is the layer name?                                         */
/* -------------------------------------------------------------------- */
    string oLayerName;
    const char *pszLayerName = pszTargetIn;

    if( poOGRLayerInfo != NULL )
    {
        oLayerName = poOGRLayerInfo->get_attr( "layer_name" );
        if( strlen(oLayerName.c_str()) > 0 )
            pszLayerName = oLayerName.c_str();
    }
        
    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
    poFeatureDefn->Reference();

/* -------------------------------------------------------------------- */
/*      Fetch the target variable.                                      */
/* -------------------------------------------------------------------- */
    Sequence *seq = dynamic_cast<Sequence *>(poDS->poDDS->var( pszTargetIn ));

    poTargetVar = seq;
    poSuperSeq = FindSuperSequence( seq );

/* -------------------------------------------------------------------- */
/*      X/Y/Z fields.                                                   */
/* -------------------------------------------------------------------- */
    if( poOGRLayerInfo != NULL )
    {
        AttrTable *poField = poOGRLayerInfo->find_container("x_field");
        if( poField != NULL )
            oXField.Initialize( poField, poTargetVar, poSuperSeq );

        poField = poOGRLayerInfo->find_container("y_field");
        if( poField != NULL )
            oYField.Initialize( poField, poTargetVar, poSuperSeq );

        poField = poOGRLayerInfo->find_container("z_field");
        if( poField != NULL )
            oZField.Initialize( poField, poTargetVar, poSuperSeq );
    }

/* -------------------------------------------------------------------- */
/*      If we have no layerinfo, then check if there are obvious x/y    */
/*      fields.                                                         */
/* -------------------------------------------------------------------- */
    else
    {
        string oTargName = pszTargetIn;
        string oSSTargName;
        string x, y;

        if( poSuperSeq != NULL )
            oSSTargName = OGRDODSGetVarPath( poSuperSeq );
        else
            oSSTargName = "impossiblexxx";

        if( poDS->poDDS->var( oTargName + ".lon" ) != NULL 
            && poDS->poDDS->var( oTargName + ".lat" ) != NULL )
        {
            oXField.Initialize( (oTargName + ".lon").c_str(), "dds",
                                poTargetVar, poSuperSeq );
            oYField.Initialize( (oTargName + ".lat").c_str(), "dds",
                                poTargetVar, poSuperSeq );
        }
        else if( poDS->poDDS->var( oSSTargName + ".lon" ) != NULL 
                 && poDS->poDDS->var( oSSTargName + ".lat" ) != NULL )
        {
            oXField.Initialize( (oSSTargName + ".lon").c_str(), "dds",
                                poTargetVar, poSuperSeq );
            oYField.Initialize( (oSSTargName + ".lat").c_str(), "dds",
                                poTargetVar, poSuperSeq );
        }
    }

/* -------------------------------------------------------------------- */
/*      Add fields for the contents of the sequence.                    */
/* -------------------------------------------------------------------- */
    Sequence::Vars_iter v_i;

    for( v_i = seq->var_begin(); v_i != seq->var_end(); v_i++ )
        BuildFields( *v_i, NULL, NULL );

/* -------------------------------------------------------------------- */
/*      Add fields for the contents of the super-sequence if we have    */
/*      one.                                                            */
/* -------------------------------------------------------------------- */
    if( poSuperSeq != NULL )
    {
        for( v_i = poSuperSeq->var_begin(); 
             v_i != poSuperSeq->var_end(); 
             v_i++ )
            BuildFields( *v_i, NULL, NULL );
    }
}
int OGRDODSSequenceLayer::BuildFields( BaseType *poFieldVar, 
                                       const char *pszPathToVar,
                                       const char *pszPathToSequence )
    
{
    OGRFieldDefn oField( "", OFTInteger );

/* -------------------------------------------------------------------- */
/*      Setup field name, including path if non-local.                  */
/* -------------------------------------------------------------------- */
    if( pszPathToVar == NULL )
        oField.SetName( poFieldVar->name().c_str() );
    else
        oField.SetName( CPLSPrintf( "%s.%s", pszPathToVar, 
                                    poFieldVar->name().c_str() ) );
                                    
/* -------------------------------------------------------------------- */
/*      Capture this field definition.                                  */
/* -------------------------------------------------------------------- */
    switch( poFieldVar->type() )
    {
      case dods_byte_c:
      case dods_int16_c:
      case dods_uint16_c:
      case dods_int32_c:
      case dods_uint32_c:
        if( pszPathToSequence )
            oField.SetType( OFTIntegerList );
        else
            oField.SetType( OFTInteger );
        break;

      case dods_float32_c:
      case dods_float64_c:
        if( pszPathToSequence )
            oField.SetType( OFTRealList );
        else
            oField.SetType( OFTReal );
        break;

      case dods_str_c:
      case dods_url_c:
        if( pszPathToSequence )
            oField.SetType( OFTStringList );
        else
            oField.SetType( OFTString );
        break;

      case dods_sequence_c:
      {
          Sequence *seq = dynamic_cast<Sequence *>( poFieldVar );
          Sequence::Vars_iter v_i;

          // We don't support a 3rd level of sequence nesting.
          if( pszPathToSequence != NULL )
              return FALSE;

          // We don't explore down into the target sequence if we
          // are recursing from a supersequence. 
          if( poFieldVar == this->poTargetVar )
              return FALSE;

          for( v_i = seq->var_begin(); v_i != seq->var_end(); v_i++ )
          {
              BuildFields( *v_i, oField.GetNameRef(), oField.GetNameRef() );
          }
      }
      return FALSE;

      default:
        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Add field to feature defn, and capture mapping.                 */
/* -------------------------------------------------------------------- */
    poFeatureDefn->AddFieldDefn( &oField );

    papoFields = (OGRDODSFieldDefn **) 
        CPLRealloc( papoFields, sizeof(void*) * poFeatureDefn->GetFieldCount());

    papoFields[poFeatureDefn->GetFieldCount()-1] = 
        new OGRDODSFieldDefn();

    papoFields[poFeatureDefn->GetFieldCount()-1]->Initialize(
        OGRDODSGetVarPath(poFieldVar).c_str(), "dds", 
        poTargetVar, poSuperSeq );

    
    if( pszPathToSequence )
        papoFields[poFeatureDefn->GetFieldCount()-1]->pszPathToSequence 
            = CPLStrdup( pszPathToSequence );

    return TRUE;
}