func (col *Collection) init() error {
	if !col.hasInit {
		if err := col.Open(); err != nil {
			return err
		}
		if err := col.ReadCollection(); err != nil {
			return err
		}
	}
	col.hasInit = true
	return nil
}
init opens and reads collection information from iRODS if it hasn't been init'd already
package gorods
import "C"
import (
	"fmt"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"
	"time"
	"unsafe"
)
type Collection struct {
	options  *CollectionOptions
	readOpts *CollectionReadOpts
	readInfo *CollectionReadInfo
	trimRepls   bool
	path        string
	name        string
	dataObjects IRodsObjs
	metaCol     *MetaCollection
	con         *Connection
	col         *Collection
	recursive bool
	hasInit   bool
	typ       int
	parent    *Collection
	ownerName  string
	owner      *User
	createTime time.Time
	modifyTime time.Time
	opened     bool
	cColHandle C.collHandle_t
}
type CollectionOptions struct {
	Path      string
	Recursive bool
	GetRepls  bool
	SkipCache bool
}
func (obj *Collection) String() string {
	str := fmt.Sprintf("Collection: %v\n", obj.path)
	objs, _ := obj.All()
	for _, o := range objs {
		str += fmt.Sprintf("\t%v: %v\n", getTypeString(o.Type()), o.Name())
	}
	return str
}
func initCollection(data *C.collEnt_t, acol *Collection) (*Collection, error) {
	col := new(Collection)
	col.opened = false
	col.typ = CollectionType
	col.col = acol
	col.con = col.col.con
	col.path = C.GoString(data.collName)
	col.options = acol.options
	col.recursive = acol.recursive
	col.trimRepls = acol.trimRepls
	col.parent = acol
	col.ownerName = C.GoString(data.ownerName)
	col.createTime = cTimeToTime(data.createTime)
	col.modifyTime = cTimeToTime(data.modifyTime)
	col.name = filepath.Base(col.path)
	if usrs, err := col.con.Users(); err != nil {
		return nil, err
	} else {
		if u := usrs.FindByName(col.ownerName, col.con); u != nil {
			col.owner = u
		} else {
			return nil, newError(Fatal, -1, fmt.Sprintf("iRODS initCollection Failed: Unable to locate user in cache"))
		}
	}
	if col.recursive {
		if er := col.init(); er != nil {
			return nil, er
		}
	}
	return col, nil
}
func (col *Collection) Stat() (map[string]interface{}, error) {
	var (
		err        *C.char
		statResult *C.rodsObjStat_t
	)
	path := C.CString(col.path)
	defer C.free(unsafe.Pointer(path))
	ccon := col.con.GetCcon()
	defer col.con.ReturnCcon(ccon)
	if status := C.gorods_stat_dataobject(path, &statResult, ccon, &err); status != 0 {
		return nil, newError(Fatal, status, fmt.Sprintf("iRODS Stat Failed: %v, %v", col.path, C.GoString(err)))
	}
	result := make(map[string]interface{})
	result["objSize"] = int(statResult.objSize)
	result["dataMode"] = int(statResult.dataMode)
	result["dataId"] = C.GoString(&statResult.dataId[0])
	result["chksum"] = C.GoString(&statResult.chksum[0])
	result["ownerName"] = C.GoString(&statResult.ownerName[0])
	result["ownerZone"] = C.GoString(&statResult.ownerZone[0])
	result["createTime"] = C.GoString(&statResult.createTime[0])
	result["modifyTime"] = C.GoString(&statResult.modifyTime[0])
	C.freeRodsObjStat(statResult)
	return result, nil
}
func getCollection(opts CollectionOptions, con *Connection) (*Collection, error) {
	col := new(Collection)
	col.options = &opts
	col.con = con
	return setupCollection(col)
}
func getCollectionOpts(opts CollectionOptions, readOpts CollectionReadOpts, con *Connection) (*Collection, error) {
	col := new(Collection)
	col.options = &opts
	col.con = con
	col.readOpts = &readOpts
	return setupCollection(col)
}
func setupCollection(col *Collection) (*Collection, error) {
	col.opened = false
	col.typ = CollectionType
	col.path = strings.TrimRight(col.options.Path, "/")
	col.name = filepath.Base(col.path)
	col.recursive = col.options.Recursive
	col.trimRepls = !col.options.GetRepls
	if col.recursive {
		if er := col.init(); er != nil {
			return nil, er
		}
	} else {
		if er := col.Open(); er != nil {
			return nil, er
		}
	}
	if info, err := col.Stat(); err == nil {
		col.ownerName = info["ownerName"].(string)
		cCreateTime := C.CString(info["createTime"].(string))
		defer C.free(unsafe.Pointer(cCreateTime))
		cModifyTime := C.CString(info["modifyTime"].(string))
		defer C.free(unsafe.Pointer(cModifyTime))
		col.createTime = cTimeToTime(cCreateTime)
		col.modifyTime = cTimeToTime(cModifyTime)
		if usrs, err := col.con.Users(); err != nil {
			return nil, err
		} else {
			if u := usrs.FindByName(col.ownerName, col.con); u != nil {
				col.owner = u
			} else {
				return nil, newError(Fatal, -1, fmt.Sprintf("iRODS getCollection Failed: Unable to locate user in cache"))
			}
		}
	} else {
		return nil, err
	}
	return col, nil
}
func CreateCollection(name string, coll *Collection) (*Collection, error) {
	var (
		errMsg *C.char
	)
	newColPath := coll.path + "/" + name
	path := C.CString(newColPath)
	defer C.free(unsafe.Pointer(path))
	ccon := coll.con.GetCcon()
	if status := C.gorods_create_collection(path, ccon, &errMsg); status != 0 {
		coll.con.ReturnCcon(ccon)
		return nil, newError(Fatal, status, fmt.Sprintf("iRODS Create Collection Failed: %v, Does the collection already exist?", C.GoString(errMsg)))
	}
	coll.con.ReturnCcon(ccon)
	return coll.Con().Collection(CollectionOptions{
		Path: newColPath,
	})
}