/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by  The HDF Group and                                           *
 * The Board of Trustees of the University of Illinois.                      *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of H4H5TOOLS. The full H4H5TOOLS copyright notice,      *
 * including terms governing use, modification, and redistribution, is       *
 * contained in the COPYING file, which can be found at the root of the      *
 * source code distribution tree. The copyright notice can also be found     *
 * at https://www.hdfgroup.org/licenses.  If you do not have access to       *
 * either file, you may request a copy from help@hdfgroup.org.               *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include "h4toh5.h"
#define _HDF_CHK_TBL_CLASST "_HDF_CHK_TBL_"
/* There are 12 test cases for h4toh5 library.*/
/* h4h5apitestdefault,
     h4h5apitestname,
     h4h5apitestimage,
     h4h5apitestimageattr,
     h4h5apitestsds,
     h4h5apitestsdsattr,
     h4h5apitestvdata,
     h4h5apitestvdataattr,
     h4h5apitestadvgroup,
     h4h5apitestbasvgroup,
     h4h5apitestloneimage,
     h4h5apitestlonesds,
     h4h5apitestlonevdata
     
     This file is h4h5apitestadvgroup.c.

     Basic procedure:
     test H4toH5advgroup and use H4toH5vdata for independent vdata conversion to 
     simulate h4toh5 conversion *utility*.
*/

/*-------------------------------------------------------------------------
 * Function:    main
 *
 * Purpose:         test H4toH5advgroup under root.
                                It is supposed to generate the same result as H4toH5 
        converter utility.

 *                       
 * Return:  FAIL if failed, SUCCEED if successful.
 
     Modfication: 
 *-------------------------------------------------------------------------
 */ 

 
int main() {

    hid_t                   h4toh5id; /*h4toh5 id*/
    int32                   file_id;    /*HDF4 file id */
    int32                   vgroup_id;/*HDF4 vgroup id */
    int32                   vdata_id; /*HDF4 vdata id */
    int32                   status;     /*temporary variable to check status of HDF4 APIs */
    int                     h4toh5status; /*temporary variable to check status of H4toH5 APIs */
    int                     num_lonevg;/* number of lone vgroup */
    int                     num_lonevd;/* number of lone vdata */
    char                    vdata_class[VGNAMELENMAX];/* vdata class name */
    int32                *ref_vdata_array;/* array of vdata reference */
    int                     lone_vd_number;/* lone vdata number. */
    int32                *ref_vgroup_array; /* array of vgroup reference */
    int                     lone_vg_number; /* lone vgroup number. */
    char                    vgroup_class[VGNAMELENMAX];/* vgroup class name */


    /** open H(DF4) interface **/
    file_id = Hopen("testallvgroup.hdf",DFACC_READ,0);
    if(file_id == FAIL) {
        printf("cannot open H interface.\n");
        return FAIL;
    }

    /** open V interface **/
    status  = Vstart(file_id);
    if(status == FAIL) {
        printf("cannot start V interface.\n");
        Hclose(file_id);
        return FAIL;
    }

    /* Initialize H4toH5 conversion library */
    if((h4toh5id= H4toH5open("testallvgroup.hdf","testallvgroup.h5",H425_CLOBBER)) < 0) {
        printf("cannot open H4toH5 interface\n");
        Vend(file_id);
        Hclose(file_id);
        return FAIL;
    }

    /* grab the lone vgroup and lone vdata
         use H4toH5advgroup and H4toH5vdata to 
         convert all members under this lone vgroup to
         an HDF5 group. */

    /* get the number of lone vgroup */
    num_lonevg = Vlone(file_id,NULL,0);
    if (num_lonevg == FAIL) {
        printf("error in obtaining lone vgroup number. \n");
        Vend(file_id);
        Hclose(file_id);
        H4toH5close(h4toh5id);
        return FAIL;
    }

    ref_vgroup_array = (int32 *)malloc(sizeof(int32) *num_lonevg);

    if(ref_vgroup_array == NULL) {
         printf("error in allocating memory for ref_array.\n");
         Vend(file_id);
         Hclose(file_id);
         H4toH5close(h4toh5id);
         return FAIL;
    }

    /* get each lone vgroup reference number. */
    num_lonevg = Vlone(file_id,ref_vgroup_array,num_lonevg);

    for(lone_vg_number = 0; lone_vg_number < num_lonevg;
           lone_vg_number++) {

        vgroup_id = Vattach(file_id,ref_vgroup_array[lone_vg_number],"r");

        if(vgroup_id ==FAIL) {
            printf("error in attaching lone vgroup.\n");
            free(ref_vgroup_array);
            Vend(file_id);
            Hclose(file_id);
            H4toH5close(h4toh5id);
            return FAIL;
        }
        
           /*obtain vgroup name and vgroup class name.*/
        status = Vgetclass(vgroup_id,vgroup_class);
        if(status == FAIL) {
            printf("error in attaching lone vgroup.\n");
            free(ref_vgroup_array);
            Vdetach(vgroup_id);
            Vend(file_id);
            Hclose(file_id);
            H4toH5close(h4toh5id);
            return FAIL;
        }

        if(strcmp(vgroup_class,_HDF_CDF)==0) {
            Vdetach(vgroup_id);
            continue;
           }
           if(strcmp(vgroup_class,GR_NAME)==0) {
            Vdetach(vgroup_id);
            continue;
           }

           /* do H4 to H5 vgroup conversion. */
        if(H4toH5adv_group(h4toh5id,vgroup_id,"/",NULL,H425_OSPEC_ALLATTRS)<0){
            printf("cannot convert vgroup \n");
            H4toH5error_get(h4toh5id);
            free(ref_vgroup_array);
            Vend(file_id);
            Hclose(file_id);
            H4toH5close(h4toh5id);
            return FAIL;
        }  
        status = Vdetach(vgroup_id);
        if(status == FAIL) {
            printf("error in detaching lone vgroup.\n");
            free(ref_vgroup_array);
            Vend(file_id);
            Hclose(file_id);
            H4toH5close(h4toh5id);
            return FAIL;
        }
    }

    free(ref_vgroup_array);

     /* obtain number of lone Vdata. */
    num_lonevd = VSlone(file_id,NULL,0);
    if (num_lonevd == FAIL) {
        printf("error in obtaining lone vgroup number. \n");
        Vend(file_id);
        Hclose(file_id);
        H4toH5close(h4toh5id);
        return FAIL;
    }

    if (num_lonevd > 0) {

       /* obtain the reference number of lone Vdata array. */
        ref_vdata_array = (int32 *)malloc(sizeof(int32) *(num_lonevd));
        num_lonevd = VSlone(file_id,ref_vdata_array,num_lonevd);
        if(num_lonevd == FAIL) {
            printf("error in obtaining lone vdata number the second time.\n");
            Vend(file_id);
            Hclose(file_id);
            H4toH5close(h4toh5id);
            free(ref_vdata_array);
            return FAIL;
        }

        /* walk through all lone vdatas. */
        for(lone_vd_number = 0; lone_vd_number < num_lonevd;lone_vd_number++) 
            {
            vdata_id = VSattach(file_id,ref_vdata_array[lone_vd_number],"r");
            if(vdata_id == FAIL) {
                printf("error in obtaining vdata id for lone vdata.\n");
                Vend(file_id);
                Hclose(file_id);
                H4toH5close(h4toh5id);
                free(ref_vdata_array);
                return FAIL;
            }
     
            status = VSgetclass(vdata_id,vdata_class);
            if(status == FAIL) {
                printf("error in getting vdata class name.\n");
                free(ref_vdata_array);
                VSdetach(vdata_id);
                Vend(file_id);
                Hclose(file_id);
                H4toH5close(h4toh5id);
                return FAIL;
            }
   
            /* this Vdata is used to store chunk table for internal HDF4 use. */
            if(!strncmp(vdata_class,_HDF_CHK_TBL_CLASST,strlen(_HDF_CHK_TBL_CLASST))){                      
                            VSdetach(vdata_id);         
                continue;
            }
   
            if(!VSisattr(vdata_id)){
                /* call H4toH5 Vdata conversion routine to convert Vdata. */
                if(H4toH5vdata(h4toh5id,vdata_id,"/",NULL,1)<0) {
                    printf("error H4toH5vdata for user-defined names\n");
                    H4toH5error_get(h4toh5id);
                    VSdetach(vdata_id);
                    Vend(file_id);
                    Hclose(file_id);
                    H4toH5close(h4toh5id);
                    free(ref_vdata_array);
                    return FAIL;
                }
                status = VSdetach(vdata_id);
                if(status == FAIL) {
                    printf("cannot detach this Vdata.\n");
                    Vend(file_id);
                    Hclose(file_id);
                    H4toH5close(h4toh5id);
                    free(ref_vdata_array);
                    return FAIL;
                }
            }
            else {
                status=VSdetach(vdata_id);
                if(status == FAIL) {
                    printf("cannot detach this Vdata.\n");
                    Vend(file_id);
                    Hclose(file_id);
                    H4toH5close(h4toh5id);
                    free(ref_vdata_array);
                    return FAIL;
                }
           }
        }
        free(ref_vdata_array);
    }

    /* close all interfaces. */
    status = Vend(file_id);
    if(status == FAIL){
        printf("cannot close V interface.\n"); 
        Hclose(file_id);
        H4toH5close(h4toh5id);
        return FAIL;
    }
    status = Hclose(file_id);
    if(status == FAIL) {
        printf("cannot close H interface. \n");
        H4toH5close(h4toh5id);
        return FAIL;
    }
    h4toh5status = H4toH5close(h4toh5id);
    if(h4toh5status == FAIL) {
        printf("cannot close H4toH5 interface.\n");
        return FAIL;
    }
    return SUCCEED;
}








