func (f *Folder) WalkNodes(names ...string) (*Node, []*http.Response, error) {
	resps := make([]*http.Response, 0, len(names))
	if len(names) == 0 {
		return f.Node, resps, nil
	}
	fp := f
	for _, name := range names[:len(names)-1] {
		fn, resp, err := fp.GetFolder(name)
		resps = append(resps, resp)
		if err != nil {
			return fp.Node, resps, err
		}
		fp = fn
	}
	nl, resp, err := fp.GetNode(names[len(names)-1])
	resps = append(resps, resp)
	if err != nil {
		return fp.Node, resps, err
	}
	return nl, resps, nil
}
WalkNodes walks the given node hierarchy, getting each node along the way, and returns
the deepest node. If an error occurs, returns the furthest successful node and the list
of HTTP responses.
package acd
import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"reflect"
	"github.com/google/go-querystring/query"
)
type NodesService struct {
	client *Client
}
func (s *NodesService) GetRoot() (*Folder, *http.Response, error) {
	opts := &NodeListOptions{Filters: "kind:FOLDER AND isRoot:true"}
	roots, resp, err := s.GetNodes(opts)
	if err != nil {
		return nil, resp, err
	}
	if len(roots) < 1 {
		return nil, resp, errors.New("No root found")
	}
	return &Folder{roots[0]}, resp, nil
}
func (s *NodesService) GetAllNodes(opts *NodeListOptions) ([]*Node, *http.Response, error) {
	return s.listAllNodes("nodes", opts)
}
func (s *NodesService) GetNodes(opts *NodeListOptions) ([]*Node, *http.Response, error) {
	return s.listNodes("nodes", opts)
}
func (s *NodesService) listAllNodes(url string, opts *NodeListOptions) ([]*Node, *http.Response, error) {
	if opts == nil {
		opts = &NodeListOptions{}
	}
	result := make([]*Node, 0, 200)
	for {
		nodes, resp, err := s.listNodes(url, opts)
		if err != nil {
			return result, resp, err
		}
		if nodes == nil {
			break
		}
		result = append(result, nodes...)
	}
	return result, nil, nil
}
func (s *NodesService) listNodes(url string, opts *NodeListOptions) ([]*Node, *http.Response, error) {
	if opts != nil && opts.reachedEnd {
		return nil, nil, nil
	}
	url, err := addOptions(url, opts)
	if err != nil {
		return nil, nil, err
	}
	req, err := s.client.NewMetadataRequest("GET", url, nil)
	if err != nil {
		return nil, nil, err
	}
	nodeList := &nodeListInternal{}
	resp, err := s.client.Do(req, nodeList)
	if err != nil {
		return nil, resp, err
	}
	if opts != nil {
		if nodeList.NextToken != nil {
			opts.StartToken = *nodeList.NextToken
		} else {
			opts.reachedEnd = true
		}
	}
	nodes := nodeList.Data
	for _, node := range nodes {
		node.service = s
	}
	return nodes, resp, nil
}
type nodeListInternal struct {
	Count     *uint64 `json:"count"`
	NextToken *string `json:"nextToken"`
	Data      []*Node `json:"data"`
}
type Node struct {
	Id                *string `json:"id"`
	Name              *string `json:"name"`
	Kind              *string `json:"kind"`
	ContentProperties *struct {
		Size *uint64 `json:"size"`
	} `json:"contentProperties"`
	service *NodesService
}
func (n *Node) IsFile() bool {
	return n.Kind != nil && *n.Kind == "FILE"
}
func (n *Node) IsFolder() bool {
	return n.Kind != nil && *n.Kind == "FOLDER"
}
func (n *Node) Typed() interface{} {
	if n.IsFile() {
		return &File{n}
	}
	if n.IsFolder() {
		return &Folder{n}
	}
	return n
}
func (n *Node) GetMetadata() (string, error) {
	url := fmt.Sprintf("nodes/%s?tempLink=true", *n.Id)
	req, err := n.service.client.NewMetadataRequest("GET", url, nil)
	if err != nil {
		return "", err
	}
	buf := &bytes.Buffer{}
	_, err = n.service.client.Do(req, buf)
	if err != nil {
		return "", err
	}
	md := &bytes.Buffer{}
	err = json.Indent(md, buf.Bytes(), "", "    ")
	if err != nil {
		return "", err
	}
	return md.String(), nil
}
type File struct {
	*Node
}
func (f *File) Download(path string) (*http.Response, error) {
	url := fmt.Sprintf("nodes/%s/content", *f.Id)
	req, err := f.service.client.NewContentRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
	if err != nil {
		return nil, err
	}
	defer out.Close()
	resp, err := f.service.client.Do(req, out)
	return resp, err
}
type Folder struct {
	*Node
}
func (f *Folder) GetAllChildren(opts *NodeListOptions) ([]*Node, *http.Response, error) {
	url := fmt.Sprintf("nodes/%s/children", *f.Id)
	return f.service.listAllNodes(url, opts)
}
func (f *Folder) GetChildren(opts *NodeListOptions) ([]*Node, *http.Response, error) {
	url := fmt.Sprintf("nodes/%s/children", *f.Id)
	return f.service.listNodes(url, opts)
}
func (f *Folder) GetFolder(name string) (*Folder, *http.Response, error) {
	n, resp, err := f.GetNode(name)
	if err != nil {
		return nil, resp, err
	}
	res, ok := n.Typed().(*Folder)
	if !ok {
		err := errors.New(fmt.Sprintf("Node '%s' is not a folder", name))
		return nil, resp, err
	}
	return res, resp, nil
}
func (f *Folder) GetFile(name string) (*File, *http.Response, error) {
	n, resp, err := f.GetNode(name)
	if err != nil {
		return nil, resp, err
	}
	res, ok := n.Typed().(*File)
	if !ok {
		err := errors.New(fmt.Sprintf("Node '%s' is not a file", name))
		return nil, resp, err
	}
	return res, resp, nil
}
func (f *Folder) GetNode(name string) (*Node, *http.Response, error) {
	filter := fmt.Sprintf("parents:\"%v\" AND name:\"%s\"", *f.Id, name)
	opts := &NodeListOptions{Filters: filter}
	nodes, resp, err := f.service.GetNodes(opts)
	if err != nil {
		return nil, resp, err
	}
	if len(nodes) < 1 {
		err := errors.New(fmt.Sprintf("No node '%s' found", name))
		return nil, resp, err
	}
	if len(nodes) > 1 {
		err := errors.New(fmt.Sprintf("Too many nodes '%s' found (%v)", name, len(nodes)))
		return nil, resp, err
	}
	return nodes[0], resp, nil
}