cdm/src/main/java/ucar/nc2/iosp/hdf5/H5iosp.java
private Object readData(H5header.Vinfo vinfo, Variable v, Layout layout, DataType dataType, int[] shape,
                          Object fillValue, int endian) throws java.io.IOException, InvalidRangeException {

    H5header.TypeInfo typeInfo = vinfo.typeInfo;

    // special processing
    if (typeInfo.hdfType == 2) { // time
      Object data = IospHelper.readDataFill(raf, layout, dataType, fillValue, endian, true);
      Array timeArray = Array.factory(dataType, shape, data);

      // now transform into an ISO Date String
      String[] stringData = new String[(int) timeArray.getSize()];
      int count = 0;
      while (timeArray.hasNext()) {
        long time = timeArray.nextLong();
        stringData[count++] = CalendarDate.of(time).toString();
      }
      return Array.factory(DataType.STRING, shape, stringData);
    }

    if (typeInfo.hdfType == 8) { // enum
      Object data = IospHelper.readDataFill(raf, layout, dataType, fillValue, endian);
      return Array.factory(dataType, shape, data);
    }

    if (typeInfo.isVlen) { // vlen (not string)
      DataType readType = dataType;
      if (typeInfo.base.hdfType == 7) // reference
        readType = DataType.LONG;

      // general case is to read an array of vlen objects
      // each vlen generates an Array - so return ArrayObject of Array
      // boolean scalar = false; // layout.getTotalNelems() == 1; // if scalar, return just the len Array // remove 12/25/10 jcaron
      Array[] data = new Array[(int) layout.getTotalNelems()];
      int count = 0;
      while (layout.hasNext()) {
        Layout.Chunk chunk = layout.next();
        if (chunk == null) continue;
        for (int i = 0; i < chunk.getNelems(); i++) {
          long address = chunk.getSrcPos() + layout.getElemSize() * i;
          Array vlenArray = headerParser.getHeapDataArray(address, readType, endian);
          data[count++] = (typeInfo.base.hdfType == 7) ? convertReference(vlenArray) : vlenArray;
        }
      }
      int prefixrank = 0;
      for (int i=0;i<shape.length;i++) { // find leftmost vlen
        if (shape[i] < 0) {
          prefixrank = i;
          break;
        }
      }
      Array result;
      if(prefixrank == 0) // if scalar, return just the singleton vlen array
        result = data[0];
       else {
        int[] newshape = new int[prefixrank];
        System.arraycopy(shape, 0, newshape, 0, prefixrank);
        // result = Array.makeObjectArray(readType, data[0].getClass(), newshape, data);
        result = Array.makeVlenArray(newshape, data);
      }

      /*
      else if (prefixrank == 1) // LOOK cant these two cases be combines - just differ in shape ??
        result = Array.makeObjectArray(readType, data[0].getClass(), new int[]{count}, data);
     else {  // LOOK cant these two cases be combines - just differ in shape ??
          // Otherwise create and fill in an n-dimensional Array Of Arrays
          int[] newshape = new int[prefixrank];
          System.arraycopy(shape, 0, newshape, 0, prefixrank);
          Array ndimarray = Array.makeObjectArray(readType, Array.class, newshape, null);
          // Transfer the elements of data into the n-dim arrays
          IndexIterator iter = ndimarray.getIndexIterator();
          for(int i = 0;iter.hasNext();i++) {
              iter.setObjectNext(data[i]);
          }
          result = ndimarray;
      } */
      //return (scalar) ? data[0] : new ArrayObject(data[0].getClass(), shape, data);
      //return new ArrayObject(data[0].getClass(), shape, data);
      return result;
    }

    if (dataType == DataType.STRUCTURE) {  // LOOK what about subset ?
      int recsize = layout.getElemSize();
      long size = recsize * layout.getTotalNelems();
      byte[] byteArray = new byte[(int)size];
      while (layout.hasNext()) {
        Layout.Chunk chunk = layout.next();
        if (chunk == null) continue;
        if (debugStructure)
          System.out.println(" readStructure " + v.getFullName() + " chunk= " + chunk + " index.getElemSize= " + layout.getElemSize());
        // copy bytes directly into the underlying byte[] LOOK : assumes contiguous layout ??
        raf.seek(chunk.getSrcPos());
        raf.readFully(byteArray, (int) chunk.getDestElem() * recsize, chunk.getNelems() * recsize);
      }

      // place data into an ArrayStructureBB
      return convertStructure((Structure) v, layout, shape, byteArray); // LOOK
    }

    // normal case
    return readDataPrimitive(layout, dataType, shape, fillValue, endian, true);
  }
private Object readData(H5header.Vinfo vinfo, Variable v, Layout layout, DataType dataType, int[] shape,
                          Object fillValue, int endian) throws java.io.IOException, InvalidRangeException {

    H5header.TypeInfo typeInfo = vinfo.typeInfo;

    // special processing
    if (typeInfo.hdfType == 2) { // time
      Object data = IospHelper.readDataFill(raf, layout, dataType, fillValue, endian, true);
      Array timeArray = Array.factory(dataType, shape, data);

      // now transform into an ISO Date String
      String[] stringData = new String[(int) timeArray.getSize()];
      int count = 0;
      while (timeArray.hasNext()) {
        long time = timeArray.nextLong();
        stringData[count++] = CalendarDate.of(time).toString();
      }
      return Array.factory(DataType.STRING, shape, stringData);
    }

    if (typeInfo.hdfType == 8) { // enum
      Object data = IospHelper.readDataFill(raf, layout, dataType, fillValue, endian);
      return Array.factory(dataType, shape, data);
    }

    if (typeInfo.isVlen) { // vlen (not string)
      DataType readType = dataType;
      if (typeInfo.base.hdfType == 7) // reference
        readType = DataType.LONG;

      // general case is to read an array of vlen objects
      // each vlen generates an Array - so return ArrayObject of Array
      // boolean scalar = false; // layout.getTotalNelems() == 1; // if scalar, return just the len Array // remove 12/25/10 jcaron
      Array[] data = new Array[(int) layout.getTotalNelems()];
      int count = 0;
      while (layout.hasNext()) {
        Layout.Chunk chunk = layout.next();
        if (chunk == null) continue;
        for (int i = 0; i < chunk.getNelems(); i++) {
          long address = chunk.getSrcPos() + layout.getElemSize() * i;
          Array vlenArray = headerParser.getHeapDataArray(address, readType, endian);
          data[count++] = (typeInfo.base.hdfType == 7) ? convertReference(vlenArray) : vlenArray;
        }
      }
      int prefixrank = 0;
      for (int i=0;i<shape.length;i++) { // find leftmost vlen
        if (shape[i] < 0) {
          prefixrank = i;
          break;
        }
      }
      Array result;
      if(prefixrank == 0) // if scalar, return just the singleton vlen array
        result = data[0];
       else {
        int[] newshape = new int[prefixrank];
        System.arraycopy(shape, 0, newshape, 0, prefixrank);
        // result = Array.makeObjectArray(readType, data[0].getClass(), newshape, data);
        result = Array.makeVlenArray(newshape, data);
      }

      /*
      else if (prefixrank == 1) // LOOK cant these two cases be combines - just differ in shape ??
        result = Array.makeObjectArray(readType, data[0].getClass(), new int[]{count}, data);
     else {  // LOOK cant these two cases be combines - just differ in shape ??
          // Otherwise create and fill in an n-dimensional Array Of Arrays
          int[] newshape = new int[prefixrank];
          System.arraycopy(shape, 0, newshape, 0, prefixrank);
          Array ndimarray = Array.makeObjectArray(readType, Array.class, newshape, null);
          // Transfer the elements of data into the n-dim arrays
          IndexIterator iter = ndimarray.getIndexIterator();
          for(int i = 0;iter.hasNext();i++) {
              iter.setObjectNext(data[i]);
          }
          result = ndimarray;
      } */
      //return (scalar) ? data[0] : new ArrayObject(data[0].getClass(), shape, data);
      //return new ArrayObject(data[0].getClass(), shape, data);
      return result;
    }

    if (dataType == DataType.STRUCTURE) {  // LOOK what about subset ?
      int recsize = layout.getElemSize();
      long size = recsize * layout.getTotalNelems();
      byte[] byteArray = new byte[(int)size];
      while (layout.hasNext()) {
        Layout.Chunk chunk = layout.next();
        if (chunk == null) continue;
        if (debugStructure)
          System.out.println(" readStructure " + v.getFullName() + " chunk= " + chunk + " index.getElemSize= " + layout.getElemSize());
        // copy bytes directly into the underlying byte[] LOOK : assumes contiguous layout ??
        raf.seek(chunk.getSrcPos());
        raf.readFully(byteArray, (int) chunk.getDestElem() * recsize, chunk.getNelems() * recsize);
      }

      // place data into an ArrayStructureBB
      return convertStructure((Structure) v, layout, shape, byteArray); // LOOK
    }

    // normal case
    return readDataPrimitive(layout, dataType, shape, fillValue, endian, true);
  }
/*
Read data subset from file for a variable, return Array or java primitive array.

@param v         the variable to read.
@param layout     handles skipping around in the file.
@param dataType  dataType of the data to read
@param shape     the shape of the output
@param fillValue fill value as a wrapped primitive
@return primitive array or Array with data read in
@throws java.io.IOException            if read error
@throws ucar.ma2.InvalidRangeException if invalid section