func WithExtraContexts(contexts ...ldcontext.Document) DocumentLoaderOpts {
	return func(opts *documentLoaderOpts) {
		opts.extraContexts = contexts
	}
}
WithExtraContexts sets the extra contexts (in addition to embedded) for preloading into the underlying storage.
package ld
import (
	"errors"
	"fmt"
	jsonld "github.com/piprate/json-gold/ld"
	"github.com/hyperledger/aries-framework-go/pkg/doc/ldcontext"
	"github.com/hyperledger/aries-framework-go/pkg/doc/ldcontext/embed"
	"github.com/hyperledger/aries-framework-go/pkg/store/ld"
	"github.com/hyperledger/aries-framework-go/spi/storage"
)
var ErrContextNotFound = errors.New("context not found")
type provider interface {
	JSONLDContextStore() ld.ContextStore
	JSONLDRemoteProviderStore() ld.RemoteProviderStore
}
type DocumentLoader struct {
	store                ld.ContextStore
	remoteDocumentLoader jsonld.DocumentLoader
}
func NewDocumentLoader(ctx provider, opts ...DocumentLoaderOpts) (*DocumentLoader, error) {
	loaderOpts := &documentLoaderOpts{}
	for i := range opts {
		opts[i](loaderOpts)
	}
	contexts, err := prepareContexts(ctx.JSONLDRemoteProviderStore(), loaderOpts)
	if err != nil {
		return nil, fmt.Errorf("get contexts: %w", err)
	}
	store := ctx.JSONLDContextStore()
	if err = store.Import(contexts); err != nil {
		return nil, fmt.Errorf("import contexts: %w", err)
	}
	return &DocumentLoader{
		store:                store,
		remoteDocumentLoader: loaderOpts.remoteDocumentLoader,
	}, nil
}
func prepareContexts(providerStore ld.RemoteProviderStore, opts *documentLoaderOpts) ([]ldcontext.Document, error) {
	m := make(map[string]ldcontext.Document)
	for _, c := range append(embed.Contexts, opts.extraContexts...) {
		m[c.URL] = c
	}
	for _, p := range opts.remoteProviders {
		contexts, err := p.Contexts()
		if err != nil {
			return nil, fmt.Errorf("get provider contexts: %w", err)
		}
		for _, c := range contexts {
			m[c.URL] = c
		}
		if _, err = providerStore.Save(p.Endpoint()); err != nil {
			return nil, fmt.Errorf("save remote provider: %w", err)
		}
	}
	var contexts []ldcontext.Document
	for _, c := range m {
		contexts = append(contexts, c)
	}
	return contexts, nil
}
func (l *DocumentLoader) LoadDocument(u string) (*jsonld.RemoteDocument, error) {
	rd, err := l.store.Get(u)
	if err != nil {
		if !errors.Is(err, storage.ErrDataNotFound) {
			return nil, fmt.Errorf("load document: %w", err)
		}
		if l.remoteDocumentLoader == nil {  
			return nil, ErrContextNotFound
		}
		return l.loadDocumentFromURL(u)
	}
	return rd, nil
}
func (l *DocumentLoader) loadDocumentFromURL(u string) (*jsonld.RemoteDocument, error) {
	rd, err := l.remoteDocumentLoader.LoadDocument(u)
	if err != nil {
		return nil, fmt.Errorf("load remote context document: %w", err)
	}
	if err = l.store.Put(u, rd); err != nil {
		return nil, fmt.Errorf("save loaded document: %w", err)
	}
	return rd, nil
}
type documentLoaderOpts struct {
	remoteDocumentLoader jsonld.DocumentLoader
	extraContexts        []ldcontext.Document
	remoteProviders      []RemoteProvider
}
type DocumentLoaderOpts func(opts *documentLoaderOpts)
func WithRemoteDocumentLoader(loader jsonld.DocumentLoader) DocumentLoaderOpts {
	return func(opts *documentLoaderOpts) {
		opts.remoteDocumentLoader = loader
	}
}